From 6e624a645300d784eaa97ddda29364081ede36d7 Mon Sep 17 00:00:00 2001 From: Shane Lontis Date: Fri, 9 Nov 2018 14:00:05 +1000 Subject: [PATCH] KMAC implementation using EVP_MAC Reviewed-by: Richard Levitte Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/7597) --- crypto/build.info | 2 +- crypto/err/openssl.txt | 3 + crypto/evp/c_allm.c | 2 + crypto/evp/evp_err.c | 4 + crypto/evp/m_sha3.c | 30 ++ crypto/include/internal/evp_int.h | 6 + crypto/kmac/build.info | 3 + crypto/kmac/kmac.c | 469 +++++++++++++++++++++++ crypto/objects/obj_dat.h | 12 +- crypto/objects/obj_mac.num | 2 + crypto/objects/objects.txt | 4 + doc/man3/EVP_MAC.pod | 17 +- doc/man7/EVP_MAC_KMAC.pod | 94 +++++ include/openssl/evp.h | 5 + include/openssl/evperr.h | 3 + include/openssl/obj_mac.h | 8 + test/evp_test.c | 16 + test/recipes/30-test_evp_data/evpmac.txt | 86 +++++ 18 files changed, 761 insertions(+), 5 deletions(-) create mode 100644 crypto/kmac/build.info create mode 100644 crypto/kmac/kmac.c create mode 100644 doc/man7/EVP_MAC_KMAC.pod diff --git a/crypto/build.info b/crypto/build.info index 75739c07a1..a0bb90acb4 100644 --- a/crypto/build.info +++ b/crypto/build.info @@ -5,7 +5,7 @@ SUBDIRS=objects buffer bio stack lhash rand evp asn1 pem x509 x509v3 conf \ md2 md4 md5 sha mdc2 gmac hmac ripemd whrlpool poly1305 blake2 \ siphash sm3 des aes rc2 rc4 rc5 idea aria bf cast camellia \ seed sm4 chacha modes bn ec rsa dsa dh sm2 dso engine \ - err comp ocsp cms ts srp cmac ct async + err comp ocsp cms ts srp cmac ct async kmac LIBS=../libcrypto SOURCE[../libcrypto]=\ diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 49e487523e..0f8cbf4df9 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -803,6 +803,8 @@ 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_KMAC_CTRL:217:kmac_ctrl +EVP_F_KMAC_INIT:218:kmac_init EVP_F_OK_NEW:200:ok_new EVP_F_PKCS5_PBE_KEYIVGEN:117:PKCS5_PBE_keyivgen EVP_F_PKCS5_V2_PBE_KEYIVGEN:118:PKCS5_v2_PBE_keyivgen @@ -2249,6 +2251,7 @@ EVP_R_GET_RAW_KEY_FAILED:182:get raw key failed EVP_R_ILLEGAL_SCRYPT_PARAMETERS:171:illegal scrypt parameters EVP_R_INITIALIZATION_ERROR:134:initialization error EVP_R_INPUT_NOT_INITIALIZED:111:input not initialized +EVP_R_INVALID_CUSTOM_LENGTH:185:invalid custom length EVP_R_INVALID_DIGEST:152:invalid digest EVP_R_INVALID_FIPS_MODE:168:invalid fips mode EVP_R_INVALID_KEY:163:invalid key diff --git a/crypto/evp/c_allm.c b/crypto/evp/c_allm.c index ba8acc7884..a1379d5524 100644 --- a/crypto/evp/c_allm.c +++ b/crypto/evp/c_allm.c @@ -17,6 +17,8 @@ void openssl_add_all_macs_int(void) #endif EVP_add_mac(&gmac_meth); EVP_add_mac(&hmac_meth); + EVP_add_mac(&kmac128_meth); + EVP_add_mac(&kmac256_meth); #ifndef OPENSSL_NO_SIPHASH EVP_add_mac(&siphash_meth); #endif diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c index 4ef0cf5491..16fa8650d8 100644 --- a/crypto/evp/evp_err.c +++ b/crypto/evp/evp_err.c @@ -143,6 +143,8 @@ static const ERR_STRING_DATA EVP_str_functs[] = { {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_KMAC_CTRL, 0), "kmac_ctrl"}, + {ERR_PACK(ERR_LIB_EVP, EVP_F_KMAC_INIT, 0), "kmac_init"}, {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"}, {ERR_PACK(ERR_LIB_EVP, EVP_F_PKCS5_V2_PBE_KEYIVGEN, 0), @@ -215,6 +217,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = { "initialization error"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INPUT_NOT_INITIALIZED), "input not initialized"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_CUSTOM_LENGTH), + "invalid custom length"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_DIGEST), "invalid digest"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_FIPS_MODE), "invalid fips mode"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_KEY), "invalid key"}, diff --git a/crypto/evp/m_sha3.c b/crypto/evp/m_sha3.c index 31379c0f6b..57a2986fe1 100644 --- a/crypto/evp/m_sha3.c +++ b/crypto/evp/m_sha3.c @@ -59,6 +59,11 @@ static int shake_init(EVP_MD_CTX *evp_ctx) return init(evp_ctx, '\x1f'); } +static int kmac_init(EVP_MD_CTX *evp_ctx) +{ + return init(evp_ctx, '\x04'); +} + static int sha3_update(EVP_MD_CTX *evp_ctx, const void *_inp, size_t len) { KECCAK1600_CTX *ctx = evp_ctx->md_data; @@ -395,6 +400,7 @@ const EVP_MD *EVP_shake##bitlen(void) \ }; \ return &shake##bitlen##_md; \ } + #endif EVP_MD_SHA3(224) @@ -404,3 +410,27 @@ EVP_MD_SHA3(512) EVP_MD_SHAKE(128) EVP_MD_SHAKE(256) + + +# define EVP_MD_KECCAK_KMAC(bitlen) \ +const EVP_MD *evp_keccak_kmac##bitlen(void) \ +{ \ + static const EVP_MD kmac_##bitlen##_md = { \ + -1, \ + 0, \ + 2 * bitlen / 8, \ + EVP_MD_FLAG_XOF, \ + kmac_init, \ + sha3_update, \ + sha3_final, \ + NULL, \ + NULL, \ + (KECCAK1600_WIDTH - bitlen * 2) / 8, \ + sizeof(KECCAK1600_CTX), \ + shake_ctrl \ + }; \ + return &kmac_##bitlen##_md; \ +} + +EVP_MD_KECCAK_KMAC(128) +EVP_MD_KECCAK_KMAC(256) diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h index 85d3487adc..1828125292 100644 --- a/crypto/include/internal/evp_int.h +++ b/crypto/include/internal/evp_int.h @@ -131,9 +131,15 @@ 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 kmac128_meth; +extern const EVP_MAC kmac256_meth; extern const EVP_MAC siphash_meth; extern const EVP_MAC poly1305_meth; +/* Internal keccak algorithms used for KMAC */ +const EVP_MD *evp_keccak_kmac128(void); +const EVP_MD *evp_keccak_kmac256(void); + /* * This function is internal for now, but can be made external when needed. * The documentation would read: diff --git a/crypto/kmac/build.info b/crypto/kmac/build.info new file mode 100644 index 0000000000..01d04be580 --- /dev/null +++ b/crypto/kmac/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=kmac.c + diff --git a/crypto/kmac/kmac.c b/crypto/kmac/kmac.c new file mode 100644 index 0000000000..db0a42c3a3 --- /dev/null +++ b/crypto/kmac/kmac.c @@ -0,0 +1,469 @@ +/* + * 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 + */ + +/* + * See SP800-185 "Appendix A - KMAC, .... in Terms of Keccak[c]" + * + * Inputs are: + * K = Key (len(K) < 2^2040 bits) + * X = Input + * L = Output length (0 <= L < 2^2040 bits) + * S = Customization String Default="" (len(S) < 2^2040 bits) + * + * KMAC128(K, X, L, S) + * { + * newX = bytepad(encode_string(K), 168) || X || right_encode(L). + * T = bytepad(encode_string(“KMAC”) || encode_string(S), 168). + * return KECCAK[256](T || newX || 00, L). + * } + * + * KMAC256(K, X, L, S) + * { + * newX = bytepad(encode_string(K), 136) || X || right_encode(L). + * T = bytepad(encode_string(“KMAC”) || encode_string(S), 136). + * return KECCAK[512](T || newX || 00, L). + * } + * + * KMAC128XOF(K, X, L, S) + * { + * newX = bytepad(encode_string(K), 168) || X || right_encode(0). + * T = bytepad(encode_string(“KMAC”) || encode_string(S), 168). + * return KECCAK[256](T || newX || 00, L). + * } + * + * KMAC256XOF(K, X, L, S) + * { + * newX = bytepad(encode_string(K), 136) || X || right_encode(0). + * T = bytepad(encode_string(“KMAC”) || encode_string(S), 136). + * return KECCAK[512](T || newX || 00, L). + * } + * + */ + +#include +#include +#include "internal/cryptlib.h" +#include "internal/evp_int.h" + +#define KMAC_MAX_BLOCKSIZE ((1600 - 128*2) / 8) /* 168 */ +#define KMAC_MIN_BLOCKSIZE ((1600 - 256*2) / 8) /* 136 */ + +/* Length encoding will be a 1 byte size + length in bits (2 bytes max) */ +#define KMAC_MAX_ENCODED_HEADER_LEN 3 + +/* + * Custom string max size is chosen such that: + * len(encoded_string(custom) + len(kmac_encoded_string) <= KMAC_MIN_BLOCKSIZE + * i.e: (KMAC_MAX_CUSTOM + KMAC_MAX_ENCODED_LEN) + 6 <= 136 + */ +#define KMAC_MAX_CUSTOM 127 + +/* Maximum size of encoded custom string */ +#define KMAC_MAX_CUSTOM_ENCODED (KMAC_MAX_CUSTOM + KMAC_MAX_ENCODED_HEADER_LEN) + +/* Maximum key size in bytes = 2040 / 8 */ +#define KMAC_MAX_KEY 255 + +/* + * Maximum Encoded Key size will be padded to a multiple of the blocksize + * i.e KMAC_MAX_KEY + KMAC_MAX_ENCODED_LEN = 258 + * Padded to a multiple of KMAC_MAX_BLOCKSIZE + */ +#define KMAC_MAX_KEY_ENCODED (KMAC_MAX_BLOCKSIZE * 2) + +/* Fixed value of encode_string("KMAC") */ +static const unsigned char kmac_string[] = { + 0x01, 0x20, 0x4B, 0x4D, 0x41, 0x43 +}; + + +#define KMAC_FLAG_XOF_MODE 1 + +/* typedef EVP_MAC_IMPL */ +struct evp_mac_impl_st { + EVP_MD_CTX *ctx; + const EVP_MD *md; + size_t out_len; + int key_len; + int custom_len; + /* If xof_mode = 1 then we use right_encode(0) */ + int xof_mode; + /* key and custom are stored in encoded form */ + unsigned char key[KMAC_MAX_KEY_ENCODED]; + unsigned char custom[KMAC_MAX_CUSTOM_ENCODED]; +}; + +static int encode_string(unsigned char *out, int *out_len, + const unsigned char *in, int in_len); +static int right_encode(unsigned char *out, int *out_len, size_t bits); +static int bytepad(unsigned char *out, int *out_len, + const unsigned char *in1, int in1_len, + const unsigned char *in2, int in2_len, + int w); +static int kmac_bytepad_encode_key(unsigned char *out, int *out_len, + const unsigned char *in, int in_len, + int w); +static int kmac_ctrl_str(EVP_MAC_IMPL *kctx, const char *type, + const char *value); + + +static void kmac_free(EVP_MAC_IMPL *kctx) +{ + if (kctx != NULL) { + EVP_MD_CTX_free(kctx->ctx); + OPENSSL_cleanse(kctx->key, kctx->key_len); + OPENSSL_cleanse(kctx->custom, kctx->custom_len); + OPENSSL_free(kctx); + } +} + +static EVP_MAC_IMPL *kmac_new(const EVP_MD *md) +{ + EVP_MAC_IMPL *kctx = NULL; + + if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL + || (kctx->ctx = EVP_MD_CTX_new()) == NULL) { + kmac_free(kctx); + return NULL; + } + kctx->md = md; + kctx->out_len = md->md_size; + return kctx; +} + +static EVP_MAC_IMPL *kmac128_new(void) +{ + return kmac_new(evp_keccak_kmac128()); +} + +static EVP_MAC_IMPL *kmac256_new(void) +{ + return kmac_new(evp_keccak_kmac256()); +} + +static int kmac_copy(EVP_MAC_IMPL *gdst, EVP_MAC_IMPL *gsrc) +{ + gdst->md = gsrc->md; + gdst->out_len = gsrc->out_len; + gdst->key_len = gsrc->key_len; + gdst->custom_len = gsrc->custom_len; + gdst->xof_mode = gsrc->xof_mode; + memcpy(gdst->key, gsrc->key, gsrc->key_len); + memcpy(gdst->custom, gsrc->custom, gdst->custom_len); + + return EVP_MD_CTX_copy(gdst->ctx, gsrc->ctx); +} + +/* + * The init() assumes that any ctrl methods are set beforehand for + * md, key and custom. Setting the fields afterwards will have no + * effect on the output mac. + */ +static int kmac_init(EVP_MAC_IMPL *kctx) +{ + EVP_MD_CTX *ctx = kctx->ctx; + unsigned char out[KMAC_MAX_BLOCKSIZE]; + int out_len, block_len; + + /* Check key has been set */ + if (kctx->key_len == 0) { + EVPerr(EVP_F_KMAC_INIT, EVP_R_NO_KEY_SET); + return 0; + } + if (!EVP_DigestInit_ex(kctx->ctx, kctx->md, NULL)) + return 0; + + block_len = EVP_MD_block_size(kctx->md); + + /* Set default custom string if it is not already set */ + if (kctx->custom_len == 0) + (void)kmac_ctrl_str(kctx, "custom", ""); + + return bytepad(out, &out_len, kmac_string, sizeof(kmac_string), + kctx->custom, kctx->custom_len, block_len) + && EVP_DigestUpdate(ctx, out, out_len) + && EVP_DigestUpdate(ctx, kctx->key, kctx->key_len); +} + +static size_t kmac_size(EVP_MAC_IMPL *kctx) +{ + return kctx->out_len; +} + +static int kmac_update(EVP_MAC_IMPL *kctx, const unsigned char *data, + size_t datalen) +{ + return EVP_DigestUpdate(kctx->ctx, data, datalen); +} + +static int kmac_final(EVP_MAC_IMPL *kctx, unsigned char *out) +{ + EVP_MD_CTX *ctx = kctx->ctx; + int lbits, len; + unsigned char encoded_outlen[KMAC_MAX_ENCODED_HEADER_LEN]; + + /* KMAC XOF mode sets the encoded length to 0 */ + lbits = (kctx->xof_mode ? 0 : (kctx->out_len * 8)); + + return right_encode(encoded_outlen, &len, lbits) + && EVP_DigestUpdate(ctx, encoded_outlen, len) + && EVP_DigestFinalXOF(ctx, out, kctx->out_len); +} + +/* + * The following Ctrl functions can be set any time before final(): + * - EVP_MAC_CTRL_SET_SIZE: The requested output length. + * - EVP_MAC_CTRL_SET_XOF: If set, this indicates that right_encoded(0) is + * part of the digested data, otherwise it uses + * right_encoded(requested output length). + + * All other Ctrl functions should be set before init(). + */ +static int kmac_ctrl(EVP_MAC_IMPL *kctx, int cmd, va_list args) +{ + const unsigned char *p; + size_t len; + size_t size; + + switch (cmd) { + case EVP_MAC_CTRL_SET_XOF: + kctx->xof_mode = va_arg(args, int); + return 1; + + case EVP_MAC_CTRL_SET_SIZE: + size = va_arg(args, size_t); + kctx->out_len = size; + return 1; + + case EVP_MAC_CTRL_SET_KEY: + p = va_arg(args, const unsigned char *); + len = va_arg(args, size_t); + if (len < 4 || len > KMAC_MAX_KEY) { + EVPerr(EVP_F_KMAC_CTRL, EVP_R_INVALID_KEY_LENGTH); + return 0; + } + return kmac_bytepad_encode_key(kctx->key, &kctx->key_len, p, len, + EVP_MD_block_size(kctx->md)); + + case EVP_MAC_CTRL_SET_CUSTOM: + p = va_arg(args, const unsigned char *); + len = va_arg(args, size_t); + if (len > KMAC_MAX_CUSTOM) { + EVPerr(EVP_F_KMAC_CTRL, EVP_R_INVALID_CUSTOM_LENGTH); + return 0; + } + return encode_string(kctx->custom, &kctx->custom_len, p, len); + + default: + return -2; + } +} + +static int kmac_ctrl_int(EVP_MAC_IMPL *kctx, int cmd, ...) +{ + int rv; + va_list args; + + va_start(args, cmd); + rv = kmac_ctrl(kctx, cmd, args); + va_end(args); + + return rv; +} + +static int kmac_ctrl_str_cb(void *kctx, int cmd, void *buf, size_t buflen) +{ + return kmac_ctrl_int(kctx, cmd, buf, buflen); +} + +static int kmac_ctrl_str(EVP_MAC_IMPL *kctx, const char *type, + const char *value) +{ + if (value == NULL) + return 0; + + if (strcmp(type, "outlen") == 0) + return kmac_ctrl_int(kctx, EVP_MAC_CTRL_SET_SIZE, (size_t)atoi(value)); + if (strcmp(type, "xof") == 0) + return kmac_ctrl_int(kctx, EVP_MAC_CTRL_SET_XOF, atoi(value)); + if (strcmp(type, "key") == 0) + return EVP_str2ctrl(kmac_ctrl_str_cb, kctx, EVP_MAC_CTRL_SET_KEY, + value); + if (strcmp(type, "hexkey") == 0) + return EVP_hex2ctrl(kmac_ctrl_str_cb, kctx, EVP_MAC_CTRL_SET_KEY, + value); + if (strcmp(type, "custom") == 0) + return EVP_str2ctrl(kmac_ctrl_str_cb, kctx, EVP_MAC_CTRL_SET_CUSTOM, + value); + if (strcmp(type, "hexcustom") == 0) + return EVP_hex2ctrl(kmac_ctrl_str_cb, kctx, EVP_MAC_CTRL_SET_CUSTOM, + value); + return -2; +} + +/* + * Encoding/Padding Methods. + */ + +/* Returns the number of bytes required to store 'bits' into a byte array */ +static unsigned int get_encode_size(size_t bits) +{ + unsigned int cnt = 0, sz = sizeof(size_t); + + while (bits && (cnt < sz)) { + ++cnt; + bits >>= 8; + } + /* If bits is zero 1 byte is required */ + if (cnt == 0) + cnt = 1; + return cnt; +} + +/* + * Convert an integer into bytes . The number of bytes is appended + * to the end of the buffer. Returns an array of bytes 'out' of size + * *out_len. + * + * e.g if bits = 32, out[2] = { 0x20, 0x01 } + * + */ +static int right_encode(unsigned char *out, int *out_len, size_t bits) +{ + unsigned int len = get_encode_size(bits); + int i; + + /* The length is constrained to a single byte: 2040/8 = 255 */ + if (len > 0xFF) + return 0; + + /* MSB's are at the start of the bytes array */ + for (i = len - 1; i >= 0; --i) { + out[i] = (unsigned char)(bits & 0xFF); + bits >>= 8; + } + /* Tack the length onto the end */ + out[len] = (unsigned char)len; + + /* The Returned length includes the tacked on byte */ + *out_len = len + 1; + return 1; +} + +/* + * Encodes a string with a left encoded length added. Note that the + * in_len is converted to bits (*8). + * + * e.g- in="KMAC" gives out[6] = { 0x01, 0x20, 0x4B, 0x4D, 0x41, 0x43 } + * len bits K M A C + */ +static int encode_string(unsigned char *out, int *out_len, + const unsigned char *in, int in_len) +{ + if (in == NULL) { + *out_len = 0; + } else { + int i, bits, len; + + bits = 8 * in_len; + len = get_encode_size(bits); + if (len > 0xFF) + return 0; + + out[0] = len; + for (i = len; i > 0; --i) { + out[i] = (bits & 0xFF); + bits >>= 8; + } + memcpy(out + len + 1, in, in_len); + *out_len = (1 + len + in_len); + } + return 1; +} + +/* + * Returns a zero padded encoding of the inputs in1 and an optional + * in2 (can be NULL). The padded output must be a multiple of the blocksize 'w'. + * The value of w is in bytes (< 256). + * + * The returned output is: + * zero_padded(multiple of w, (left_encode(w) || in1 [|| in2]) + */ +static int bytepad(unsigned char *out, int *out_len, + const unsigned char *in1, int in1_len, + const unsigned char *in2, int in2_len, int w) +{ + int len; + unsigned char *p = out; + int sz = w; + + /* Left encoded w */ + *p++ = 1; + *p++ = w; + /* || in1 */ + memcpy(p, in1, in1_len); + p += in1_len; + /* [ || in2 ] */ + if (in2 != NULL && in2_len > 0) { + memcpy(p, in2, in2_len); + p += in2_len; + } + /* Figure out the pad size (divisible by w) */ + len = p - out; + while (len > sz) { + sz += w; + } + /* zero pad the end of the buffer */ + memset(p, 0, sz - len); + *out_len = sz; + return 1; +} + +/* + * Returns out = bytepad(encode_string(in), w) + */ +static int kmac_bytepad_encode_key(unsigned char *out, int *out_len, + const unsigned char *in, int in_len, + int w) +{ + unsigned char tmp[KMAC_MAX_KEY + KMAC_MAX_ENCODED_HEADER_LEN]; + int tmp_len; + + if (!encode_string(tmp, &tmp_len, in, in_len)) + return 0; + + return bytepad(out, out_len, tmp, tmp_len, NULL, 0, w); +} + +const EVP_MAC kmac128_meth = { + EVP_MAC_KMAC128, + kmac128_new, + kmac_copy, + kmac_free, + kmac_size, + kmac_init, + kmac_update, + kmac_final, + kmac_ctrl, + kmac_ctrl_str +}; + +const EVP_MAC kmac256_meth = { + EVP_MAC_KMAC256, + kmac256_new, + kmac_copy, + kmac_free, + kmac_size, + kmac_init, + kmac_update, + kmac_final, + kmac_ctrl, + kmac_ctrl_str +}; + diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h index d9365ceccd..7d058fce01 100644 --- a/crypto/objects/obj_dat.h +++ b/crypto/objects/obj_dat.h @@ -1079,7 +1079,7 @@ static const unsigned char so[7767] = { 0x28,0xCC,0x45,0x03,0x04, /* [ 7761] OBJ_gmac */ }; -#define NUM_NID 1196 +#define NUM_NID 1198 static const ASN1_OBJECT nid_objs[NUM_NID] = { {"UNDEF", "undefined", NID_undef}, {"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]}, @@ -2277,9 +2277,11 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = { {"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]}, + {"KMAC128", "kmac128", NID_kmac128}, + {"KMAC256", "kmac256", NID_kmac256}, }; -#define NUM_SN 1187 +#define NUM_SN 1189 static const unsigned int sn_objs[NUM_SN] = { 364, /* "AD_DVCS" */ 419, /* "AES-128-CBC" */ @@ -2445,6 +2447,8 @@ static const unsigned int sn_objs[NUM_SN] = { 645, /* "ITU-T" */ 646, /* "JOINT-ISO-ITU-T" */ 773, /* "KISA" */ + 1196, /* "KMAC128" */ + 1197, /* "KMAC256" */ 1063, /* "KxANY" */ 1039, /* "KxDHE" */ 1041, /* "KxDHE-PSK" */ @@ -3470,7 +3474,7 @@ static const unsigned int sn_objs[NUM_SN] = { 1093, /* "x509ExtAdmission" */ }; -#define NUM_LN 1187 +#define NUM_LN 1189 static const unsigned int ln_objs[NUM_LN] = { 363, /* "AD Time Stamping" */ 405, /* "ANSI X9.62" */ @@ -4266,6 +4270,8 @@ static const unsigned int ln_objs[NUM_LN] = { 956, /* "jurisdictionStateOrProvinceName" */ 150, /* "keyBag" */ 773, /* "kisa" */ + 1196, /* "kmac128" */ + 1197, /* "kmac256" */ 1063, /* "kx-any" */ 1039, /* "kx-dhe" */ 1041, /* "kx-dhe-psk" */ diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num index 487eefff8d..ad47750f5d 100644 --- a/crypto/objects/obj_mac.num +++ b/crypto/objects/obj_mac.num @@ -1193,3 +1193,5 @@ magma_mac 1192 hmacWithSHA512_224 1193 hmacWithSHA512_256 1194 gmac 1195 +kmac128 1196 +kmac256 1197 diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt index 1e83dffc09..590bbe9a13 100644 --- a/crypto/objects/objects.txt +++ b/crypto/objects/objects.txt @@ -13,6 +13,10 @@ iso 3 : identified-organization # GMAC OID iso 0 9797 3 4 : GMAC : gmac + +# There are no OIDs for these yet... + : KMAC128 : kmac128 + : KMAC256 : kmac256 # HMAC OIDs identified-organization 6 1 5 5 8 1 1 : HMAC-MD5 : hmac-md5 diff --git a/doc/man3/EVP_MAC.pod b/doc/man3/EVP_MAC.pod index cc0d543162..3444707dea 100644 --- a/doc/man3/EVP_MAC.pod +++ b/doc/man3/EVP_MAC.pod @@ -169,9 +169,23 @@ This control expects two arguments: C, C Some MAC implementations require an IV, this control sets the IV. +=item B + +This control expects two arguments: C, C + +Some MAC implementations (KMAC) require an Customization String, +this control sets the Customization String. The default value is "". + +=item B + +This control expects one argument: C + +This option is used by KMAC. + + =item B -This control expects one arguments: C +This control expects one argument: C These will set the MAC flags to the given numbers. Some MACs do not support this option. @@ -335,6 +349,7 @@ F<./foo>) L, L, L, +L, L, L diff --git a/doc/man7/EVP_MAC_KMAC.pod b/doc/man7/EVP_MAC_KMAC.pod new file mode 100644 index 0000000000..0e6d45be73 --- /dev/null +++ b/doc/man7/EVP_MAC_KMAC.pod @@ -0,0 +1,94 @@ +=pod + +=head1 NAME + +EVP_MAC_KMAC - The KMAC EVP_MAC implementation + +=head1 DESCRIPTION + +Support for computing KMAC MACs through the B API. + +=head2 Numeric identity + +B and B are the numeric identities 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 + +This must be set before calling EVP_MAC_init(). + +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 + +This is an optional string value that can be set before calling EVP_MAC_init(). +If it is not set it uses the default value "". + +EVP_MAC_ctrl_str() takes two type strings for this control: + +=over 4 + +=item "custom" + +The value string is used as is. + +=item "hexcustom" + +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() type string: "outlen" + +This is an optional value string containing a decimal number. If it is not set +it uses the default value of 32 for EVP_MAC_KMAC128 and 64 for EVP_MAC_KMAC256. +This can be called any time before EVP_MAC_final(). + +=item B + +EVP_MAC_ctrl_str() type string: "xof" + +The value string is expected to be an integer value of 1 or 0. Use 1 to enable +XOF mode. If XOF is enabled then the output len that is encoded as part of the +input stream is set to zero. +This can be called any time before EVP_MAC_final(). + +=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/include/openssl/evp.h b/include/openssl/evp.h index a0b7a54d3c..d22956d343 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -717,6 +717,7 @@ const EVP_MD *EVP_sha3_384(void); const EVP_MD *EVP_sha3_512(void); const EVP_MD *EVP_shake128(void); const EVP_MD *EVP_shake256(void); + # ifndef OPENSSL_NO_MDC2 const EVP_MD *EVP_mdc2(void); # endif @@ -990,6 +991,8 @@ void EVP_MD_do_all_sorted(void (*fn) # define EVP_MAC_CMAC NID_cmac # define EVP_MAC_GMAC NID_gmac # define EVP_MAC_HMAC NID_hmac +# define EVP_MAC_KMAC128 NID_kmac128 +# define EVP_MAC_KMAC256 NID_kmac256 # define EVP_MAC_SIPHASH NID_siphash # define EVP_MAC_POLY1305 NID_poly1305 @@ -1027,6 +1030,8 @@ void EVP_MAC_do_all_sorted(void (*fn) # define EVP_MAC_CTRL_SET_CIPHER 0x05 /* EVP_CIPHER * */ # define EVP_MAC_CTRL_SET_SIZE 0x06 /* size_t */ # define EVP_MAC_CTRL_SET_IV 0x07 /* unsigned char *, size_t */ +# define EVP_MAC_CTRL_SET_CUSTOM 0x08 /* unsigned char *, size_t */ +# define EVP_MAC_CTRL_SET_XOF 0x09 /* int */ /* PKEY stuff */ int EVP_PKEY_decrypt_old(unsigned char *dec_key, diff --git a/include/openssl/evperr.h b/include/openssl/evperr.h index fff78cc473..2c727d34ce 100644 --- a/include/openssl/evperr.h +++ b/include/openssl/evperr.h @@ -113,6 +113,8 @@ int ERR_load_EVP_strings(void); # define EVP_F_EVP_VERIFYFINAL 108 # define EVP_F_GMAC_CTRL 215 # define EVP_F_INT_CTX_NEW 157 +# define EVP_F_KMAC_CTRL 217 +# define EVP_F_KMAC_INIT 218 # define EVP_F_OK_NEW 200 # define EVP_F_PKCS5_PBE_KEYIVGEN 117 # define EVP_F_PKCS5_V2_PBE_KEYIVGEN 118 @@ -159,6 +161,7 @@ int ERR_load_EVP_strings(void); # define EVP_R_ILLEGAL_SCRYPT_PARAMETERS 171 # define EVP_R_INITIALIZATION_ERROR 134 # define EVP_R_INPUT_NOT_INITIALIZED 111 +# define EVP_R_INVALID_CUSTOM_LENGTH 185 # define EVP_R_INVALID_DIGEST 152 # define EVP_R_INVALID_FIPS_MODE 168 # define EVP_R_INVALID_KEY 163 diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h index 0a3e4c509a..e977a24c66 100644 --- a/include/openssl/obj_mac.h +++ b/include/openssl/obj_mac.h @@ -49,6 +49,14 @@ #define NID_gmac 1195 #define OBJ_gmac OBJ_iso,0L,9797L,3L,4L +#define SN_kmac128 "KMAC128" +#define LN_kmac128 "kmac128" +#define NID_kmac128 1196 + +#define SN_kmac256 "KMAC256" +#define LN_kmac256 "kmac256" +#define NID_kmac256 1197 + #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 18b20af5ff..0677b85e6f 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -847,6 +847,8 @@ typedef struct mac_data_st { /* Expected output */ unsigned char *output; size_t output_len; + unsigned char *custom; + size_t custom_len; /* Collection of controls */ STACK_OF(OPENSSL_STRING) *controls; } MAC_DATA; @@ -929,6 +931,7 @@ static void mac_test_cleanup(EVP_TEST *t) OPENSSL_free(mdat->alg); OPENSSL_free(mdat->key); OPENSSL_free(mdat->iv); + OPENSSL_free(mdat->custom); OPENSSL_free(mdat->input); OPENSSL_free(mdat->output); } @@ -942,6 +945,8 @@ static int mac_test_parse(EVP_TEST *t, 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, "Custom") == 0) + return parse_bin(value, &mdata->custom, &mdata->custom_len); if (strcmp(keyword, "Algorithm") == 0) { mdata->alg = OPENSSL_strdup(value); if (!mdata->alg) @@ -1124,6 +1129,17 @@ static int mac_test_run_mac(EVP_TEST *t) t->err = "MAC_CTRL_ERROR"; goto err; } + if (expected->custom != NULL) { + rv = EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_CUSTOM, + expected->custom, expected->custom_len); + if (rv == -2) { + t->err = "MAC_CTRL_INVALID"; + goto err; + } else if (rv <= 0) { + t->err = "MAC_CTRL_ERROR"; + goto err; + } + } if (expected->iv != NULL) { rv = EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_IV, diff --git a/test/recipes/30-test_evp_data/evpmac.txt b/test/recipes/30-test_evp_data/evpmac.txt index 1d635ba54b..940ef189ed 100644 --- a/test/recipes/30-test_evp_data/evpmac.txt +++ b/test/recipes/30-test_evp_data/evpmac.txt @@ -455,6 +455,92 @@ Input = 68F2E77696CE7AE8E2CA4EC588E541002E58495C08000F101112131415161718191A1B1C Output = 00BDA1B7E87608BCBF470F12157F4C07 +Title = KMAC Tests (From NIST) +MAC = KMAC128 +Key = 404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F +Input = 00010203 +Custom = "" +Output = E5780B0D3EA6F7D3A429C5706AA43A00FADBD7D49628839E3187243F456EE14E +Ctrl = xof:0 + +MAC = KMAC128 +Key = 404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F +Input = 00010203 +Custom = "My Tagged Application" +Output = 3B1FBA963CD8B0B59E8C1A6D71888B7143651AF8BA0A7070C0979E2811324AA5 + +MAC = KMAC128 +Key = 404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F +Input = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7 +Custom = "My Tagged Application" +Output = 1F5B4E6CCA02209E0DCB5CA635B89A15E271ECC760071DFD805FAA38F9729230 +Ctrl = outlen:32 + +MAC = KMAC256 +Key = 404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F +Input = 00010203 +Custom = "My Tagged Application" +Output = 20C570C31346F703C9AC36C61C03CB64C3970D0CFC787E9B79599D273A68D2F7F69D4CC3DE9D104A351689F27CF6F5951F0103F33F4F24871024D9C27773A8DD + +MAC = KMAC256 +Key = 404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F +Input = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7 +Custom = "" +Output = 75358CF39E41494E949707927CEE0AF20A3FF553904C86B08F21CC414BCFD691589D27CF5E15369CBBFF8B9A4C2EB17800855D0235FF635DA82533EC6B759B69 + +MAC = KMAC256 +Key = 404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F +Input = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7 +Custom = "My Tagged Application" +Output = B58618F71F92E1D56C1B8C55DDD7CD188B97B4CA4D99831EB2699A837DA2E4D970FBACFDE50033AEA585F1A2708510C32D07880801BD182898FE476876FC8965 +Ctrl = outlen:64 + +Title = KMAC XOF Tests (From NIST) + +MAC = KMAC128 +Key = 404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F +Input = 00010203 +Output = CD83740BBD92CCC8CF032B1481A0F4460E7CA9DD12B08A0C4031178BACD6EC35 +Ctrl = xof:1 + +MAC = KMAC128 +Key = 404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F +Input = 00010203 +Custom = "My Tagged Application" +Output = 31A44527B4ED9F5C6101D11DE6D26F0620AA5C341DEF41299657FE9DF1A3B16C +Ctrl = xof:1 + +MAC = KMAC128 +Key = 404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F +Input = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7 +Custom = "My Tagged Application" +Output = 47026C7CD793084AA0283C253EF658490C0DB61438B8326FE9BDDF281B83AE0F +Ctrl = xof:1 +Ctrl = outlen:32 + +MAC = KMAC256 +Key = 404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F +Input = 00010203 +Custom = "My Tagged Application" +Output = 1755133F1534752AAD0748F2C706FB5C784512CAB835CD15676B16C0C6647FA96FAA7AF634A0BF8FF6DF39374FA00FAD9A39E322A7C92065A64EB1FB0801EB2B +Ctrl = xof:1 + +MAC = KMAC256 +Key = 404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F +Input = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7 +Custom = "" +Output = FF7B171F1E8A2B24683EED37830EE797538BA8DC563F6DA1E667391A75EDC02CA633079F81CE12A25F45615EC89972031D18337331D24CEB8F8CA8E6A19FD98B +Ctrl = xof:1 + +MAC = KMAC256 +Key = 404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F +Input = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7 +Custom = "My Tagged Application" +Output = D5BE731C954ED7732846BB59DBE3A8E30F83E77A4BFF4459F2F1C2B4ECEBB8CE67BA01C62E8AB8578D2D499BD1BB276768781190020A306A97DE281DCC30305D +Ctrl = outlen:64 +Ctrl = xof:1 + + Title = Poly1305 Tests (from RFC 7539 and others) MAC = Poly1305 -- 2.25.1