summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES3
-rwxr-xr-xConfigure2
-rw-r--r--crypto/err/openssl.txt2
-rw-r--r--crypto/evp/c_allm.c1
-rw-r--r--crypto/evp/evp_err.c3
-rw-r--r--crypto/gmac/build.info2
-rw-r--r--crypto/gmac/gmac.c183
-rw-r--r--crypto/include/internal/evp_int.h1
-rw-r--r--crypto/objects/obj_dat.h15
-rw-r--r--crypto/objects/obj_mac.num1
-rw-r--r--crypto/objects/objects.txt3
-rw-r--r--demos/evp/Makefile8
-rw-r--r--demos/evp/gmac.c103
-rw-r--r--doc/man3/EVP_MAC.pod7
-rw-r--r--doc/man7/EVP_MAC_GMAC.pod83
-rw-r--r--fuzz/oids.txt1
-rw-r--r--include/openssl/evp.h2
-rw-r--r--include/openssl/evperr.h2
-rw-r--r--include/openssl/obj_mac.h5
-rw-r--r--test/evp_test.c18
-rw-r--r--test/recipes/30-test_evp_data/evpmac.txt69
21 files changed, 400 insertions, 114 deletions
diff --git a/CHANGES b/CHANGES
index 29be4fc769..de10744357 100644
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,9 @@
Changes between 1.1.1 and 1.1.2 [xx XXX xxxx]
+ *) Add GMAC to EVP_MAC.
+ [Paul Dale]
+
*) Ported the HMAC, CMAC and SipHash EVP_PKEY_METHODs to EVP_MAC.
[Richard Levitte]
diff --git a/Configure b/Configure
index f46be6b4e5..53d5549eaf 100755
--- a/Configure
+++ b/Configure
@@ -308,7 +308,7 @@ $config{sdirs} = [
"bn", "ec", "rsa", "dsa", "dh", "sm2", "dso", "engine",
"buffer", "bio", "stack", "lhash", "rand", "err",
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",
- "cms", "ts", "srp", "cmac", "ct", "async", "kdf", "store"
+ "cms", "ts", "srp", "gmac", "cmac", "ct", "async", "kdf", "store"
];
# test/ subdirectories to build
$config{tdirs} = [ "ossl_shim" ];
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 151bc83183..6c52881e53 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -801,6 +801,7 @@ EVP_F_EVP_PKEY_VERIFY_RECOVER:144:EVP_PKEY_verify_recover
EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT:145:EVP_PKEY_verify_recover_init
EVP_F_EVP_SIGNFINAL:107:EVP_SignFinal
EVP_F_EVP_VERIFYFINAL:108:EVP_VerifyFinal
+EVP_F_GMAC_CTRL:215:gmac_ctrl
EVP_F_INT_CTX_NEW:157:int_ctx_new
EVP_F_OK_NEW:200:ok_new
EVP_F_PKCS5_PBE_KEYIVGEN:117:PKCS5_PBE_keyivgen
@@ -2223,6 +2224,7 @@ EVP_R_ARIA_KEY_SETUP_FAILED:176:aria key setup failed
EVP_R_BAD_DECRYPT:100:bad decrypt
EVP_R_BUFFER_TOO_SMALL:155:buffer too small
EVP_R_CAMELLIA_KEY_SETUP_FAILED:157:camellia key setup failed
+EVP_R_CIPHER_NOT_GCM_MODE:184:cipher not gcm mode
EVP_R_CIPHER_PARAMETER_ERROR:122:cipher parameter error
EVP_R_COMMAND_NOT_SUPPORTED:147:command not supported
EVP_R_COPY_ERROR:173:copy error
diff --git a/crypto/evp/c_allm.c b/crypto/evp/c_allm.c
index 2bcd9dc9b5..2b9d442d6b 100644
--- a/crypto/evp/c_allm.c
+++ b/crypto/evp/c_allm.c
@@ -15,6 +15,7 @@ void openssl_add_all_macs_int(void)
#ifndef OPENSSL_NO_CMAC
EVP_add_mac(&cmac_meth);
#endif
+ EVP_add_mac(&gmac_meth);
EVP_add_mac(&hmac_meth);
#ifndef OPENSSL_NO_SIPHASH
EVP_add_mac(&siphash_meth);
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index 32760db02f..05d956548f 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -141,6 +141,7 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
"EVP_PKEY_verify_recover_init"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_SIGNFINAL, 0), "EVP_SignFinal"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_VERIFYFINAL, 0), "EVP_VerifyFinal"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_GMAC_CTRL, 0), "gmac_ctrl"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_INT_CTX_NEW, 0), "int_ctx_new"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_OK_NEW, 0), "ok_new"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_PKCS5_PBE_KEYIVGEN, 0), "PKCS5_PBE_keyivgen"},
@@ -170,6 +171,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_BUFFER_TOO_SMALL), "buffer too small"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CAMELLIA_KEY_SETUP_FAILED),
"camellia key setup failed"},
+ {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CIPHER_NOT_GCM_MODE),
+ "cipher not gcm mode"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CIPHER_PARAMETER_ERROR),
"cipher parameter error"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_COMMAND_NOT_SUPPORTED),
diff --git a/crypto/gmac/build.info b/crypto/gmac/build.info
new file mode 100644
index 0000000000..6d9f22e235
--- /dev/null
+++ b/crypto/gmac/build.info
@@ -0,0 +1,2 @@
+LIBS=../../libcrypto
+SOURCE[../../libcrypto]=gmac.c
diff --git a/crypto/gmac/gmac.c b/crypto/gmac/gmac.c
new file mode 100644
index 0000000000..929d9a8e0b
--- /dev/null
+++ b/crypto/gmac/gmac.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdlib.h>
+#include <openssl/evp.h>
+#include "internal/cryptlib.h"
+#include "internal/evp_int.h"
+
+/* typedef EVP_MAC_IMPL */
+struct evp_mac_impl_st {
+ EVP_CIPHER *cipher; /* Cache GCM cipher */
+ EVP_CIPHER_CTX *ctx; /* Cipher context */
+ ENGINE *engine; /* Engine implementating the algorithm */
+};
+
+static void gmac_free(EVP_MAC_IMPL *gctx)
+{
+ if (gctx != NULL) {
+ EVP_CIPHER_CTX_free(gctx->ctx);
+ OPENSSL_free(gctx);
+ }
+}
+
+static EVP_MAC_IMPL *gmac_new(void)
+{
+ EVP_MAC_IMPL *gctx;
+
+ if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) == NULL
+ || (gctx->ctx = EVP_CIPHER_CTX_new()) == NULL) {
+ gmac_free(gctx);
+ return NULL;
+ }
+ return gctx;
+}
+
+static int gmac_copy(EVP_MAC_IMPL *gdst, EVP_MAC_IMPL *gsrc)
+{
+ gdst->cipher = gsrc->cipher;
+ gdst->engine = gsrc->engine;
+ return EVP_CIPHER_CTX_copy(gdst->ctx, gsrc->ctx);
+}
+
+static size_t gmac_size(EVP_MAC_IMPL *gctx)
+{
+ return EVP_GCM_TLS_TAG_LEN;
+}
+
+static int gmac_init(EVP_MAC_IMPL *gctx)
+{
+ return 1;
+}
+
+static int gmac_update(EVP_MAC_IMPL *gctx, const unsigned char *data,
+ size_t datalen)
+{
+ EVP_CIPHER_CTX *ctx = gctx->ctx;
+ int outlen;
+
+ while (datalen > INT_MAX) {
+ if (!EVP_EncryptUpdate(ctx, NULL, &outlen, data, INT_MAX))
+ return 0;
+ data += INT_MAX;
+ datalen -= INT_MAX;
+ }
+ return EVP_EncryptUpdate(ctx, NULL, &outlen, data, datalen);
+}
+
+static int gmac_final(EVP_MAC_IMPL *gctx, unsigned char *out)
+{
+ int hlen;
+
+ if (!EVP_EncryptFinal_ex(gctx->ctx, out, &hlen)
+ || !EVP_CIPHER_CTX_ctrl(gctx->ctx, EVP_CTRL_AEAD_GET_TAG,
+ gmac_size(gctx), out))
+ return 0;
+ return 1;
+}
+
+static int gmac_ctrl(EVP_MAC_IMPL *gctx, int cmd, va_list args)
+{
+ const unsigned char *p;
+ size_t len;
+ EVP_CIPHER_CTX *ctx = gctx->ctx;
+ const EVP_CIPHER *cipher;
+ ENGINE *engine;
+
+ switch (cmd) {
+ case EVP_MAC_CTRL_SET_CIPHER:
+ cipher = va_arg(args, const EVP_CIPHER *);
+ if (cipher == NULL)
+ return 0;
+ if (EVP_CIPHER_mode(cipher) != EVP_CIPH_GCM_MODE) {
+ EVPerr(EVP_F_GMAC_CTRL, EVP_R_CIPHER_NOT_GCM_MODE);
+ return 0;
+ }
+ return EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL);
+
+ case EVP_MAC_CTRL_SET_KEY:
+ p = va_arg(args, const unsigned char *);
+ len = va_arg(args, size_t);
+ if (len != (size_t)EVP_CIPHER_CTX_key_length(ctx)) {
+ EVPerr(EVP_F_GMAC_CTRL, EVP_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ return EVP_EncryptInit_ex(ctx, NULL, NULL, p, NULL);
+
+ case EVP_MAC_CTRL_SET_IV:
+ p = va_arg(args, const unsigned char *);
+ len = va_arg(args, size_t);
+ return EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, len, NULL)
+ && EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, p);
+
+ case EVP_MAC_CTRL_SET_ENGINE:
+ engine = va_arg(args, ENGINE *);
+ return EVP_EncryptInit_ex(ctx, NULL, engine, NULL, NULL);
+
+ default:
+ return -2;
+ }
+}
+
+static int gmac_ctrl_int(EVP_MAC_IMPL *gctx, int cmd, ...)
+{
+ int rv;
+ va_list args;
+
+ va_start(args, cmd);
+ rv = gmac_ctrl(gctx, cmd, args);
+ va_end(args);
+
+ return rv;
+}
+
+static int gmac_ctrl_str_cb(void *gctx, int cmd, void *buf, size_t buflen)
+{
+ return gmac_ctrl_int(gctx, cmd, buf, buflen);
+}
+
+static int gmac_ctrl_str(EVP_MAC_IMPL *gctx, const char *type,
+ const char *value)
+{
+ if (!value)
+ return 0;
+ if (strcmp(type, "cipher") == 0) {
+ const EVP_CIPHER *c = EVP_get_cipherbyname(value);
+
+ if (c == NULL)
+ return 0;
+ return gmac_ctrl_int(gctx, EVP_MAC_CTRL_SET_CIPHER, c);
+ }
+ if (strcmp(type, "key") == 0)
+ return EVP_str2ctrl(gmac_ctrl_str_cb, gctx, EVP_MAC_CTRL_SET_KEY,
+ value);
+ if (strcmp(type, "hexkey") == 0)
+ return EVP_hex2ctrl(gmac_ctrl_str_cb, gctx, EVP_MAC_CTRL_SET_KEY,
+ value);
+ if (strcmp(type, "iv") == 0)
+ return EVP_str2ctrl(gmac_ctrl_str_cb, gctx, EVP_MAC_CTRL_SET_IV,
+ value);
+ if (strcmp(type, "hexiv") == 0)
+ return EVP_hex2ctrl(gmac_ctrl_str_cb, gctx, EVP_MAC_CTRL_SET_IV,
+ value);
+ return -2;
+}
+
+const EVP_MAC gmac_meth = {
+ EVP_MAC_GMAC,
+ gmac_new,
+ gmac_copy,
+ gmac_free,
+ gmac_size,
+ gmac_init,
+ gmac_update,
+ gmac_final,
+ gmac_ctrl,
+ gmac_ctrl_str
+};
diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h
index 060538e737..98adf1fd2f 100644
--- a/crypto/include/internal/evp_int.h
+++ b/crypto/include/internal/evp_int.h
@@ -129,6 +129,7 @@ struct evp_mac_st {
};
extern const EVP_MAC cmac_meth;
+extern const EVP_MAC gmac_meth;
extern const EVP_MAC hmac_meth;
extern const EVP_MAC siphash_meth;
diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h
index e931f7f516..d9365ceccd 100644
--- a/crypto/objects/obj_dat.h
+++ b/crypto/objects/obj_dat.h
@@ -10,7 +10,7 @@
*/
/* Serialized OID's */
-static const unsigned char so[7762] = {
+static const unsigned char so[7767] = {
0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 0] OBJ_rsadsi */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, /* [ 6] OBJ_pkcs */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x02, /* [ 13] OBJ_md2 */
@@ -1076,9 +1076,10 @@ static const unsigned char so[7762] = {
0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x04, /* [ 7736] OBJ_id_tc26_gost_3410_2012_256_paramSetD */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0C, /* [ 7745] OBJ_hmacWithSHA512_224 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0D, /* [ 7753] OBJ_hmacWithSHA512_256 */
+ 0x28,0xCC,0x45,0x03,0x04, /* [ 7761] OBJ_gmac */
};
-#define NUM_NID 1195
+#define NUM_NID 1196
static const ASN1_OBJECT nid_objs[NUM_NID] = {
{"UNDEF", "undefined", NID_undef},
{"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]},
@@ -2275,9 +2276,10 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = {
{"magma-mac", "magma-mac", NID_magma_mac},
{"hmacWithSHA512-224", "hmacWithSHA512-224", NID_hmacWithSHA512_224, 8, &so[7745]},
{"hmacWithSHA512-256", "hmacWithSHA512-256", NID_hmacWithSHA512_256, 8, &so[7753]},
+ {"GMAC", "gmac", NID_gmac, 5, &so[7761]},
};
-#define NUM_SN 1186
+#define NUM_SN 1187
static const unsigned int sn_objs[NUM_SN] = {
364, /* "AD_DVCS" */
419, /* "AES-128-CBC" */
@@ -2424,6 +2426,7 @@ static const unsigned int sn_objs[NUM_SN] = {
297, /* "DVCS" */
1087, /* "ED25519" */
1088, /* "ED448" */
+ 1195, /* "GMAC" */
99, /* "GN" */
1036, /* "HKDF" */
855, /* "HMAC" */
@@ -3467,7 +3470,7 @@ static const unsigned int sn_objs[NUM_SN] = {
1093, /* "x509ExtAdmission" */
};
-#define NUM_LN 1186
+#define NUM_LN 1187
static const unsigned int ln_objs[NUM_LN] = {
363, /* "AD Time Stamping" */
405, /* "ANSI X9.62" */
@@ -3961,6 +3964,7 @@ static const unsigned int ln_objs[NUM_LN] = {
509, /* "generationQualifier" */
601, /* "generic cryptogram" */
99, /* "givenName" */
+ 1195, /* "gmac" */
976, /* "gost-mac-12" */
1009, /* "gost89-cbc" */
814, /* "gost89-cnt" */
@@ -4657,7 +4661,7 @@ static const unsigned int ln_objs[NUM_LN] = {
125, /* "zlib compression" */
};
-#define NUM_OBJ 1071
+#define NUM_OBJ 1072
static const unsigned int obj_objs[NUM_OBJ] = {
0, /* OBJ_undef 0 */
181, /* OBJ_iso 1 */
@@ -4904,6 +4908,7 @@ static const unsigned int obj_objs[NUM_OBJ] = {
637, /* OBJ_set_brand_Diners 2 23 42 8 30 */
638, /* OBJ_set_brand_AmericanExpress 2 23 42 8 34 */
639, /* OBJ_set_brand_JCB 2 23 42 8 35 */
+ 1195, /* OBJ_gmac 1 0 9797 3 4 */
1141, /* OBJ_oscca 1 2 156 10197 */
805, /* OBJ_cryptopro 1 2 643 2 2 */
806, /* OBJ_cryptocom 1 2 643 2 9 */
diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num
index 1b6a9c61a1..487eefff8d 100644
--- a/crypto/objects/obj_mac.num
+++ b/crypto/objects/obj_mac.num
@@ -1192,3 +1192,4 @@ magma_cfb 1191
magma_mac 1192
hmacWithSHA512_224 1193
hmacWithSHA512_256 1194
+gmac 1195
diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt
index 6dbc41ce37..1e83dffc09 100644
--- a/crypto/objects/objects.txt
+++ b/crypto/objects/objects.txt
@@ -11,6 +11,9 @@ iso 2 : member-body : ISO Member Body
iso 3 : identified-organization
+# GMAC OID
+iso 0 9797 3 4 : GMAC : gmac
+
# HMAC OIDs
identified-organization 6 1 5 5 8 1 1 : HMAC-MD5 : hmac-md5
identified-organization 6 1 5 5 8 1 2 : HMAC-SHA1 : hmac-sha1
diff --git a/demos/evp/Makefile b/demos/evp/Makefile
index 1fb0f39c77..c2e10a1ded 100644
--- a/demos/evp/Makefile
+++ b/demos/evp/Makefile
@@ -7,19 +7,17 @@
#
# LD_LIBRARY_PATH=../.. ./aesccm
# LD_LIBRARY_PATH=../.. ./aesgcm
-# LD_LIBRARY_PATH=../.. ./gmac
CFLAGS = $(OPENSSL_INCS_LOCATION)
LDFLAGS = $(OPENSSL_LIBS_LOCATION) -lssl -lcrypto
-all: aesccm aesgcm gmac
+all: aesccm aesgcm
aesccm: aesccm.o
aesgcm: aesgcm.o
-gmac: gmac.o
-aesccm aesgcm gmac:
+aesccm aesgcm:
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
clean:
- $(RM) aesccm aesgcm gmac *.o
+ $(RM) aesccm aesgcm *.o
diff --git a/demos/evp/gmac.c b/demos/evp/gmac.c
deleted file mode 100644
index 0b2231b368..0000000000
--- a/demos/evp/gmac.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*
- * Simple AES GMAC test program, uses the same NIST data used for the FIPS
- * self test but uses the application level EVP APIs.
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <openssl/bio.h>
-#include <openssl/evp.h>
-
-/* AES-GMAC test data from NIST public test vectors */
-
-static const unsigned char gmac_key[] = { 0x77, 0xbe, 0x63, 0x70, 0x89, 0x71, 0xc4, 0xe2,
- 0x40, 0xd1, 0xcb, 0x79, 0xe8, 0xd7, 0x7f, 0xeb };
-static const unsigned char gmac_iv[] = { 0xe0, 0xe0, 0x0f, 0x19, 0xfe, 0xd7, 0xba, 0x01,
- 0x36, 0xa7, 0x97, 0xf3 };
-static const unsigned char gmac_aad[] = { 0x7a, 0x43, 0xec, 0x1d, 0x9c, 0x0a, 0x5a, 0x78,
- 0xa0, 0xb1, 0x65, 0x33, 0xa6, 0x21, 0x3c, 0xab };
-
-static const unsigned char gmac_tag[] = { 0x20, 0x9f, 0xcc, 0x8d, 0x36, 0x75, 0xed, 0x93,
- 0x8e, 0x9c, 0x71, 0x66, 0x70, 0x9d, 0xd9, 0x46 };
-
-static int aes_gmac(void)
-{
- EVP_CIPHER_CTX *ctx;
- int outlen, tmplen;
- unsigned char outbuf[1024];
- int ret = 0;
-
- printf("AES GMAC:\n");
- printf("Authenticated Data:\n");
- BIO_dump_fp(stdout, gmac_aad, sizeof(gmac_aad));
-
- if ((ctx = EVP_CIPHER_CTX_new()) == NULL) {
- printf("EVP_CIPHER_CTX_new: failed\n");
- goto err;
- }
-
- /* Set cipher type and mode */
- if (!EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL)) {
- printf("EVP_EncryptInit_ex: failed\n");
- goto err;
- }
-
- /* Set IV length if default 96 bits is not appropriate */
- if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, sizeof(gmac_iv),
- NULL)) {
- printf("EVP_CIPHER_CTX_ctrl: set IV length failed\n");
- goto err;
- }
-
- /* Initialise key and IV */
- if (!EVP_EncryptInit_ex(ctx, NULL, NULL, gmac_key, gmac_iv)) {
- printf("EVP_EncryptInit_ex: set key and IV failed\n");
- goto err;
- }
-
- /* Zero or more calls to specify any AAD */
- if (!EVP_EncryptUpdate(ctx, NULL, &outlen, gmac_aad, sizeof(gmac_aad))) {
- printf("EVP_EncryptUpdate: setting AAD failed\n");
- goto err;
- }
-
- /* Finalise: note get no output for GMAC */
- if (!EVP_EncryptFinal_ex(ctx, outbuf, &outlen)) {
- printf("EVP_EncryptFinal_ex: failed\n");
- goto err;
- }
-
- /* Get tag */
- if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, outbuf)) {
- printf("EVP_CIPHER_CTX_ctrl: failed\n");
- goto err;
- }
-
- /* Output tag */
- printf("Tag:\n");
- BIO_dump_fp(stdout, outbuf, 16);
-
- /* Is the tag correct? */
- if (memcmp(outbuf, gmac_tag, sizeof(gmac_tag)) != 0) {
- printf("Expected:\n");
- BIO_dump_fp(stdout, gmac_tag, sizeof(gmac_tag));
- } else
- ret = 1;
-err:
- EVP_CIPHER_CTX_free(ctx);
- return ret;
-}
-
-int main(int argc, char **argv)
-{
- return aes_gmac() ? EXIT_SUCCESS : EXIT_FAILURE;
-}
diff --git a/doc/man3/EVP_MAC.pod b/doc/man3/EVP_MAC.pod
index a320181174..473d6c9e6b 100644
--- a/doc/man3/EVP_MAC.pod
+++ b/doc/man3/EVP_MAC.pod
@@ -163,6 +163,12 @@ For MACs that use an underlying computation algorithm, the algorithm
I<must> be set first, see B<EVP_MAC_CTRL_SET_ENGINE>,
B<EVP_MAC_CTRL_SET_MD> and B<EVP_MAC_CTRL_SET_CIPHER> below.
+=item B<EVP_MAC_CTRL_SET_IV>
+
+This control expects two arguments: C<unsigned char *key>, C<size_t keylen>
+
+Some MAC implementations require an IV, this control sets the IV.
+
=item B<EVP_MAC_CTRL_SET_FLAGS>
This control expects one arguments: C<unsigned long flags>
@@ -327,6 +333,7 @@ F<./foo>)
=head1 SEE ALSO
L<EVP_MAC_CMAC(7)>,
+L<EVP_MAC_GMAC(7)>,
L<EVP_MAC_HMAC(7)>,
L<EVP_MAC_SIPHASH(7)>
diff --git a/doc/man7/EVP_MAC_GMAC.pod b/doc/man7/EVP_MAC_GMAC.pod
new file mode 100644
index 0000000000..c35d781475
--- /dev/null
+++ b/doc/man7/EVP_MAC_GMAC.pod
@@ -0,0 +1,83 @@
+=pod
+
+=head1 NAME
+
+EVP_MAC_GMAC - The GMAC EVP_MAC implementation
+
+=head1 DESCRIPTION
+
+Support for computing GMAC MACs through the B<EVP_MAC> API.
+
+=head2 Numeric identity
+
+B<EVP_MAC_GMAC> is the numeric identity for this implementation, and
+can be used in functions like EVP_MAC_CTX_new_id() and
+EVP_get_macbynid().
+
+=head2 Supported controls
+
+The supported controls are:
+
+=over 4
+
+=item B<EVP_MAC_CTRL_SET_KEY>
+
+EVP_MAC_ctrl_str() takes two type strings for this control:
+
+=over 4
+
+=item "key"
+
+The value string is used as is.
+
+=item "hexkey"
+
+The value string is expected to be a hexadecimal number, which will be
+decoded before passing on as control value.
+
+=back
+
+=item B<EVP_MAC_CTRL_SET_IV>
+
+EVP_MAC_ctrl_str() takes two type strings for this control:
+
+=over 4
+
+=item "iv"
+
+The value string is used as is.
+
+=item "hexiv"
+
+The value string is expected to be a hexadecimal number, which will be
+decoded before passing on as control value.
+
+=back
+
+=item B<EVP_MAC_CTRL_SET_ENGINE>
+
+=item B<EVP_MAC_CTRL_SET_CIPHER>
+
+These work as described in L<EVP_MAC(3)/CONTROLS> with the restriction that the
+cipher must be an AEAD one.
+
+EVP_MAC_ctrl_str() type string for B<EVP_MAC_CTRL_SET_CIPHER>: "cipher"
+
+The value is expected to be the name of a cipher.
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_MAC_ctrl(3)>, L<EVP_MAC(3)/CONTROLS>
+
+=head1 COPYRIGHT
+
+Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the OpenSSL license (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/fuzz/oids.txt b/fuzz/oids.txt
index fe363fd37e..79a68fcd02 100644
--- a/fuzz/oids.txt
+++ b/fuzz/oids.txt
@@ -1063,3 +1063,4 @@ OBJ_id_tc26_gost_3410_2012_256_paramSetC="\x2A\x85\x03\x07\x01\x02\x01\x01\x03"
OBJ_id_tc26_gost_3410_2012_256_paramSetD="\x2A\x85\x03\x07\x01\x02\x01\x01\x04"
OBJ_hmacWithSHA512_224="\x2A\x86\x48\x86\xF7\x0D\x02\x0C"
OBJ_hmacWithSHA512_256="\x2A\x86\x48\x86\xF7\x0D\x02\x0D"
+OBJ_gmac="\x28\xCC\x45\x03\x04"
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index cfd6369ab0..79845aa1e2 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -988,6 +988,7 @@ void EVP_MD_do_all_sorted(void (*fn)
/* MAC stuff */
# define EVP_MAC_CMAC NID_cmac
+# define EVP_MAC_GMAC NID_gmac
# define EVP_MAC_HMAC NID_hmac
# define EVP_MAC_SIPHASH NID_siphash
@@ -1024,6 +1025,7 @@ void EVP_MAC_do_all_sorted(void (*fn)
# define EVP_MAC_CTRL_SET_MD 0x04 /* EVP_MD * */
# define EVP_MAC_CTRL_SET_CIPHER 0x04 /* EVP_CIPHER * */
# define EVP_MAC_CTRL_SET_SIZE 0x05 /* size_t */
+# define EVP_MAC_CTRL_SET_IV 0x06 /* unsigned char *, size_t */
/* PKEY stuff */
int EVP_PKEY_decrypt_old(unsigned char *dec_key,
diff --git a/include/openssl/evperr.h b/include/openssl/evperr.h
index a17e1599bb..17b8187f71 100644
--- a/include/openssl/evperr.h
+++ b/include/openssl/evperr.h
@@ -111,6 +111,7 @@ int ERR_load_EVP_strings(void);
# define EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT 145
# define EVP_F_EVP_SIGNFINAL 107
# define EVP_F_EVP_VERIFYFINAL 108
+# define EVP_F_GMAC_CTRL 215
# define EVP_F_INT_CTX_NEW 157
# define EVP_F_OK_NEW 200
# define EVP_F_PKCS5_PBE_KEYIVGEN 117
@@ -133,6 +134,7 @@ int ERR_load_EVP_strings(void);
# define EVP_R_BAD_DECRYPT 100
# define EVP_R_BUFFER_TOO_SMALL 155
# define EVP_R_CAMELLIA_KEY_SETUP_FAILED 157
+# define EVP_R_CIPHER_NOT_GCM_MODE 184
# define EVP_R_CIPHER_PARAMETER_ERROR 122
# define EVP_R_COMMAND_NOT_SUPPORTED 147
# define EVP_R_COPY_ERROR 173
diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h
index 80ff5a7c86..0a3e4c509a 100644
--- a/include/openssl/obj_mac.h
+++ b/include/openssl/obj_mac.h
@@ -44,6 +44,11 @@
#define NID_identified_organization 676
#define OBJ_identified_organization OBJ_iso,3L
+#define SN_gmac "GMAC"
+#define LN_gmac "gmac"
+#define NID_gmac 1195
+#define OBJ_gmac OBJ_iso,0L,9797L,3L,4L
+
#define SN_hmac_md5 "HMAC-MD5"
#define LN_hmac_md5 "hmac-md5"
#define NID_hmac_md5 780
diff --git a/test/evp_test.c b/test/evp_test.c
index 25b10d3314..18b20af5ff 100644
--- a/test/evp_test.c
+++ b/test/evp_test.c
@@ -838,6 +838,9 @@ typedef struct mac_data_st {
/* MAC key */
unsigned char *key;
size_t key_len;
+ /* MAC IV (GMAC) */
+ unsigned char *iv;
+ size_t iv_len;
/* Input to MAC */
unsigned char *input;
size_t input_len;
@@ -925,6 +928,7 @@ static void mac_test_cleanup(EVP_TEST *t)
sk_OPENSSL_STRING_pop_free(mdat->controls, openssl_free);
OPENSSL_free(mdat->alg);
OPENSSL_free(mdat->key);
+ OPENSSL_free(mdat->iv);
OPENSSL_free(mdat->input);
OPENSSL_free(mdat->output);
}
@@ -936,6 +940,8 @@ static int mac_test_parse(EVP_TEST *t,
if (strcmp(keyword, "Key") == 0)
return parse_bin(value, &mdata->key, &mdata->key_len);
+ if (strcmp(keyword, "IV") == 0)
+ return parse_bin(value, &mdata->iv, &mdata->iv_len);
if (strcmp(keyword, "Algorithm") == 0) {
mdata->alg = OPENSSL_strdup(value);
if (!mdata->alg)
@@ -1119,6 +1125,18 @@ static int mac_test_run_mac(EVP_TEST *t)
goto err;
}
+ if (expected->iv != NULL) {
+ rv = EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_IV,
+ expected->iv, expected->iv_len);
+ if (rv == -2) {
+ t->err = "MAC_CTRL_INVALID";
+ goto err;
+ } else if (rv <= 0) {
+ t->err = "MAC_CTRL_ERROR";
+ goto err;
+ }
+ }
+
if (!EVP_MAC_init(ctx)) {
t->err = "MAC_INIT_ERROR";
goto err;
diff --git a/test/recipes/30-test_evp_data/evpmac.txt b/test/recipes/30-test_evp_data/evpmac.txt
index 4788626dc8..82a350763f 100644
--- a/test/recipes/30-test_evp_data/evpmac.txt
+++ b/test/recipes/30-test_evp_data/evpmac.txt
@@ -386,6 +386,75 @@ Key = 89BCD952A8C8AB371AF48AC7D07085D5EFF702E6D62CDC23
Input = FA620C1BBE97319E9A0CF0492121F7A20EB08A6A709DCBD00AAF38E4F99E754E
Output = 8F49A1B7D6AA2258
+
+Title = GMAC Tests (from NIST)
+
+MAC = GMAC
+Algorithm = AES-128-GCM
+Key = 77BE63708971C4E240D1CB79E8D77FEB
+IV = E0E00F19FED7BA0136A797F3
+Input = 7A43EC1D9C0A5A78A0B16533A6213CAB
+Output = 209FCC8D3675ED938E9C7166709DD946
+
+Title = GMAC Tests (from http://www.ieee802.org/1/files/public/docs2011/bn-randall-test-vectors-0511-v1.pdf)
+
+MAC = GMAC
+Algorithm = AES-128-GCM
+Key = AD7A2BD03EAC835A6F620FDCB506B345
+IV = 12153524C0895E81B2C28465
+Input = D609B1F056637A0D46DF998D88E5222AB2C2846512153524C0895E8108000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233340001
+Output = F09478A9B09007D06F46E9B6A1DA25DD
+
+MAC = GMAC
+Algorithm = AES-256-GCM
+Key = E3C08A8F06C6E3AD95A70557B23F75483CE33021A9C72B7025666204C69C0B72
+IV = 12153524C0895E81B2C28465
+Input = D609B1F056637A0D46DF998D88E5222AB2C2846512153524C0895E8108000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233340001
+Output = 2F0BC5AF409E06D609EA8B7D0FA5EA50
+
+MAC = GMAC
+Algorithm = AES-128-GCM
+Key = 071B113B0CA743FECCCF3D051F737382
+IV = F0761E8DCD3D000176D457ED
+Input = E20106D7CD0DF0761E8DCD3D88E5400076D457ED08000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A0003
+Output = 0C017BC73B227DFCC9BAFA1C41ACC353
+
+MAC = GMAC
+Algorithm = AES-256-GCM
+Key = 691D3EE909D7F54167FD1CA0B5D769081F2BDE1AEE655FDBAB80BD5295AE6BE7
+IV = F0761E8DCD3D000176D457ED
+Input = E20106D7CD0DF0761E8DCD3D88E5400076D457ED08000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A0003
+Output = 35217C774BBC31B63166BCF9D4ABED07
+
+MAC = GMAC
+Algorithm = AES-128-GCM
+Key = 013FE00B5F11BE7F866D0CBBC55A7A90
+IV = 7CFDE9F9E33724C68932D612
+Input = 84C5D513D2AAF6E5BBD2727788E523008932D6127CFDE9F9E33724C608000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F0005
+Output = 217867E50C2DAD74C28C3B50ABDF695A
+
+MAC = GMAC
+Algorithm = AES-256-GCM
+Key = 83C093B58DE7FFE1C0DA926AC43FB3609AC1C80FEE1B624497EF942E2F79A823
+IV = 7CFDE9F9E33724C68932D612
+Input = 84C5D513D2AAF6E5BBD2727788E523008932D6127CFDE9F9E33724C608000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F0005
+Output = 6EE160E8FAECA4B36C86B234920CA975
+
+MAC = GMAC
+Algorithm = AES-128-GCM
+Key = 88EE087FD95DA9FBF6725AA9D757B0CD
+IV = 7AE8E2CA4EC500012E58495C
+Input = 68F2E77696CE7AE8E2CA4EC588E541002E58495C08000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D0007
+Output = 07922B8EBCF10BB2297588CA4C614523
+
+MAC = GMAC
+Algorithm = AES-256-GCM
+Key = 4C973DBC7364621674F8B5B89E5C15511FCED9216490FB1C1A2CAA0FFE0407E5
+IV = 7AE8E2CA4EC500012E58495C
+Input = 68F2E77696CE7AE8E2CA4EC588E541002E58495C08000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D0007
+Output = 00BDA1B7E87608BCBF470F12157F4C07
+
+
Title = Poly1305 Tests (from RFC 7539 and others)
MAC = Poly1305