From afc580b9b0af0072233e9282915424fd55c366d0 Mon Sep 17 00:00:00 2001 From: Pauli Date: Mon, 5 Nov 2018 08:09:41 +1000 Subject: [PATCH] GMAC implementation Remove GMAC demo program because it has been superceded by the EVP MAC one Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/7548) --- CHANGES | 3 + Configure | 2 +- crypto/err/openssl.txt | 2 + crypto/evp/c_allm.c | 1 + crypto/evp/evp_err.c | 3 + crypto/gmac/build.info | 2 + crypto/gmac/gmac.c | 183 +++++++++++++++++++++++ crypto/include/internal/evp_int.h | 1 + crypto/objects/obj_dat.h | 15 +- crypto/objects/obj_mac.num | 1 + crypto/objects/objects.txt | 3 + demos/evp/Makefile | 8 +- demos/evp/gmac.c | 103 ------------- doc/man3/EVP_MAC.pod | 7 + doc/man7/EVP_MAC_GMAC.pod | 83 ++++++++++ fuzz/oids.txt | 1 + include/openssl/evp.h | 2 + include/openssl/evperr.h | 2 + include/openssl/obj_mac.h | 5 + test/evp_test.c | 18 +++ test/recipes/30-test_evp_data/evpmac.txt | 69 +++++++++ 21 files changed, 400 insertions(+), 114 deletions(-) create mode 100644 crypto/gmac/build.info create mode 100644 crypto/gmac/gmac.c delete mode 100644 demos/evp/gmac.c create mode 100644 doc/man7/EVP_MAC_GMAC.pod 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 +#include +#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 -#include -#include -#include -#include - -/* 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 be set first, see B, B and B below. +=item B + +This control expects two arguments: C, C + +Some MAC implementations require an IV, this control sets the IV. + =item B This control expects one arguments: C @@ -327,6 +333,7 @@ F<./foo>) =head1 SEE ALSO L, +L, L, L 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 API. + +=head2 Numeric identity + +B 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_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_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 + +=item B + +These work as described in L with the restriction that the +cipher must be an AEAD one. + +EVP_MAC_ctrl_str() type string for B: "cipher" + +The value is expected to be the name of a cipher. + +=back + +=head1 SEE ALSO + +L, L + +=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. + +=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 -- 2.25.1