The branch master has been updated via d36114d7cd363d505940326f5a2512d9661a67ea (commit) via 13eaa4ecaab528e9fd815a1019406335d241d643 (commit) via 810a169eb2b642e5ca1e337bc6a9847defea62da (commit) via e3c2a55d470a313c2fc5f2fb625c086d0cb953ea (commit) from b1c908f421b3466aecf980603132bcab89d1ce99 (commit)
- Log ----------------------------------------------------------------- commit d36114d7cd363d505940326f5a2512d9661a67ea Author: Pauli <pa...@openssl.org> Date: Fri Apr 9 16:36:18 2021 +1000 kmac: update the documention for the customisation string maximum length Reviewed-by: Shane Lontis <shane.lon...@oracle.com> (Merged from https://github.com/openssl/openssl/pull/14810) commit 13eaa4ecaab528e9fd815a1019406335d241d643 Author: Pauli <pa...@openssl.org> Date: Fri Apr 9 16:20:15 2021 +1000 kmac: fix customistation string overflow bug Previously there was an off by two error allowing a stack buffer overrun. Avoided this by allocating a correct sized buffer on the stack. A side effect is that the maximum size of the customisation string can be increased. Reviewed-by: Shane Lontis <shane.lon...@oracle.com> (Merged from https://github.com/openssl/openssl/pull/14810) commit 810a169eb2b642e5ca1e337bc6a9847defea62da Author: Pauli <pa...@openssl.org> Date: Fri Apr 9 15:20:16 2021 +1000 kmac: add long customisation string example Reviewed-by: Shane Lontis <shane.lon...@oracle.com> (Merged from https://github.com/openssl/openssl/pull/14810) commit e3c2a55d470a313c2fc5f2fb625c086d0cb953ea Author: Pauli <pa...@openssl.org> Date: Sat Apr 10 12:40:59 2021 +1000 Add additional KMAC error Reviewed-by: Shane Lontis <shane.lon...@oracle.com> (Merged from https://github.com/openssl/openssl/pull/14810) ----------------------------------------------------------------------- Summary of changes: crypto/err/openssl.txt | 1 + doc/man7/EVP_MAC-KMAC.pod | 2 +- include/openssl/proverr.h | 1 + providers/common/provider_err.c | 1 + providers/implementations/macs/kmac_prov.c | 124 +++++++++++++++--------- test/recipes/30-test_evp_data/evpmac_common.txt | 19 ++++ 6 files changed, 102 insertions(+), 46 deletions(-) diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 07439f7c4a..ee17b68405 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -1006,6 +1006,7 @@ PROV_R_INVALID_X931_DIGEST:170:invalid x931 digest PROV_R_IN_ERROR_STATE:192:in error state PROV_R_KEY_SETUP_FAILED:101:key setup failed PROV_R_KEY_SIZE_TOO_SMALL:171:key size too small +PROV_R_LENGTH_TOO_LARGE:202:length too large PROV_R_MISSING_CEK_ALG:144:missing cek alg PROV_R_MISSING_CIPHER:155:missing cipher PROV_R_MISSING_CONFIG_DATA:213:missing config data diff --git a/doc/man7/EVP_MAC-KMAC.pod b/doc/man7/EVP_MAC-KMAC.pod index 6b02e94ef8..85986d5449 100644 --- a/doc/man7/EVP_MAC-KMAC.pod +++ b/doc/man7/EVP_MAC-KMAC.pod @@ -42,7 +42,7 @@ Setting this parameter is identical to passing a I<key> to L<EVP_MAC_init(3)>. =item "custom" (B<OSSL_MAC_PARAM_CUSTOM>) <octet string> Sets the custom value. -It is an optional value of at most 127 bytes, and is empty by default. +It is an optional value of at most 256 bytes, and is empty by default. =item "size" (B<OSSL_MAC_PARAM_SIZE>) <unsigned integer> diff --git a/include/openssl/proverr.h b/include/openssl/proverr.h index 99a937f1e3..c40815a03b 100644 --- a/include/openssl/proverr.h +++ b/include/openssl/proverr.h @@ -79,6 +79,7 @@ # define PROV_R_IN_ERROR_STATE 192 # define PROV_R_KEY_SETUP_FAILED 101 # define PROV_R_KEY_SIZE_TOO_SMALL 171 +# define PROV_R_LENGTH_TOO_LARGE 202 # define PROV_R_MISSING_CEK_ALG 144 # define PROV_R_MISSING_CIPHER 155 # define PROV_R_MISSING_CONFIG_DATA 213 diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c index 30574f4c6c..dd1a98f935 100644 --- a/providers/common/provider_err.c +++ b/providers/common/provider_err.c @@ -110,6 +110,7 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_KEY_SETUP_FAILED), "key setup failed"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_KEY_SIZE_TOO_SMALL), "key size too small"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_LENGTH_TOO_LARGE), "length too large"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CEK_ALG), "missing cek alg"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CIPHER), "missing cipher"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CONFIG_DATA), diff --git a/providers/implementations/macs/kmac_prov.c b/providers/implementations/macs/kmac_prov.c index 8735705f1b..d6fccf442f 100644 --- a/providers/implementations/macs/kmac_prov.c +++ b/providers/implementations/macs/kmac_prov.c @@ -78,17 +78,15 @@ static OSSL_FUNC_mac_update_fn kmac_update; static OSSL_FUNC_mac_final_fn kmac_final; #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 + * Restrict the maximum length of the customisation string. This must not + * exceed 64 bits = 8k bytes. */ -#define KMAC_MAX_CUSTOM 127 +#define KMAC_MAX_CUSTOM 256 /* Maximum size of encoded custom string */ #define KMAC_MAX_CUSTOM_ENCODED (KMAC_MAX_CUSTOM + KMAC_MAX_ENCODED_HEADER_LEN) @@ -116,8 +114,8 @@ struct kmac_data_st { EVP_MD_CTX *ctx; PROV_DIGEST digest; size_t out_len; - int key_len; - int custom_len; + size_t key_len; + size_t custom_len; /* If xof_mode = 1 then we use right_encode(0) */ int xof_mode; /* key and custom are stored in encoded form */ @@ -125,16 +123,16 @@ struct kmac_data_st { 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 encode_string(unsigned char *out, size_t *out_len, + const unsigned char *in, size_t in_len); +static int right_encode(unsigned char *out, size_t *out_len, size_t bits); +static int bytepad(unsigned char *out, size_t *out_len, + const unsigned char *in1, size_t in1_len, + const unsigned char *in2, size_t in2_len, + size_t w); +static int kmac_bytepad_encode_key(unsigned char *out, size_t *out_len, + const unsigned char *in, size_t in_len, + size_t w); static void kmac_free(void *vmacctx) { @@ -245,13 +243,18 @@ static int kmac_setkey(struct kmac_data_st *kctx, const unsigned char *key, size_t keylen) { const EVP_MD *digest = ossl_prov_digest_md(&kctx->digest); + int w = EVP_MD_block_size(digest); if (keylen < 4 || keylen > KMAC_MAX_KEY) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); return 0; } + if (w < 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH); + return 0; + } if (!kmac_bytepad_encode_key(kctx->key, &kctx->key_len, - key, keylen, EVP_MD_block_size(digest))) + key, keylen, (size_t)w)) return 0; return 1; } @@ -266,11 +269,13 @@ static int kmac_init(void *vmacctx, const unsigned char *key, { struct kmac_data_st *kctx = vmacctx; EVP_MD_CTX *ctx = kctx->ctx; - unsigned char out[KMAC_MAX_BLOCKSIZE]; - int out_len, block_len; + unsigned char *out; + size_t out_len, block_len; + int res, t; if (!ossl_prov_is_running() || !kmac_set_ctx_params(kctx, params)) return 0; + if (key != NULL) { if (!kmac_setkey(kctx, key, keylen)) return 0; @@ -283,9 +288,12 @@ static int kmac_init(void *vmacctx, const unsigned char *key, NULL)) return 0; - block_len = EVP_MD_block_size(ossl_prov_digest_md(&kctx->digest)); - if (block_len < 0) + t = EVP_MD_block_size(ossl_prov_digest_md(&kctx->digest)); + if (t < 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH); return 0; + } + block_len = t; /* Set default custom string if it is not already set */ if (kctx->custom_len == 0) { @@ -296,10 +304,22 @@ static int kmac_init(void *vmacctx, const unsigned char *key, (void)kmac_set_ctx_params(kctx, cparams); } - 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); + if (!bytepad(NULL, &out_len, kmac_string, sizeof(kmac_string), + kctx->custom, kctx->custom_len, block_len)) { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + return 0; + } + out = OPENSSL_malloc(out_len); + if (out == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return 0; + } + res = bytepad(out, NULL, 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); + OPENSSL_free(out); + return res; } static int kmac_update(void *vmacctx, const unsigned char *data, @@ -315,7 +335,7 @@ static int kmac_final(void *vmacctx, unsigned char *out, size_t *outl, { struct kmac_data_st *kctx = vmacctx; EVP_MD_CTX *ctx = kctx->ctx; - int lbits, len; + size_t lbits, len; unsigned char encoded_outlen[KMAC_MAX_ENCODED_HEADER_LEN]; int ok; @@ -431,14 +451,16 @@ static unsigned int get_encode_size(size_t bits) * e.g if bits = 32, out[2] = { 0x20, 0x01 } * */ -static int right_encode(unsigned char *out, int *out_len, size_t bits) +static int right_encode(unsigned char *out, size_t *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) + if (len > 0xFF) { + ERR_raise(ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE); return 0; + } /* MSB's are at the start of the bytes array */ for (i = len - 1; i >= 0; --i) { @@ -460,18 +482,20 @@ static int right_encode(unsigned char *out, int *out_len, size_t bits) * 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) +static int encode_string(unsigned char *out, size_t *out_len, + const unsigned char *in, size_t in_len) { if (in == NULL) { *out_len = 0; } else { - int i, bits, len; + size_t i, bits, len; bits = 8 * in_len; len = get_encode_size(bits); - if (len > 0xFF) + if (len > 0xFF) { + ERR_raise(ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE); return 0; + } out[0] = len; for (i = len; i > 0; --i) { @@ -492,14 +516,24 @@ static int encode_string(unsigned char *out, int *out_len, * 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) +static int bytepad(unsigned char *out, size_t *out_len, + const unsigned char *in1, size_t in1_len, + const unsigned char *in2, size_t in2_len, size_t w) { int len; unsigned char *p = out; int sz = w; + if (out == NULL) { + if (out_len == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + sz = 2 + in1_len + (in2 != NULL ? in2_len : 0); + *out_len = (sz + w - 1) / w * w; + return 1; + } + /* Left encoded w */ *p++ = 1; *p++ = w; @@ -513,24 +547,24 @@ static int bytepad(unsigned char *out, int *out_len, } /* Figure out the pad size (divisible by w) */ len = p - out; - while (len > sz) { - sz += w; - } + sz = (len + w - 1) / w * w; /* zero pad the end of the buffer */ - memset(p, 0, sz - len); - *out_len = sz; + if (sz != len) + memset(p, 0, sz - len); + if (out_len != NULL) + *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) +static int kmac_bytepad_encode_key(unsigned char *out, size_t *out_len, + const unsigned char *in, size_t in_len, + size_t w) { unsigned char tmp[KMAC_MAX_KEY + KMAC_MAX_ENCODED_HEADER_LEN]; - int tmp_len; + size_t tmp_len; if (!encode_string(tmp, &tmp_len, in, in_len)) return 0; diff --git a/test/recipes/30-test_evp_data/evpmac_common.txt b/test/recipes/30-test_evp_data/evpmac_common.txt index 35bba4fcaa..7ddecefc2a 100644 --- a/test/recipes/30-test_evp_data/evpmac_common.txt +++ b/test/recipes/30-test_evp_data/evpmac_common.txt @@ -400,3 +400,22 @@ Custom = "My Tagged Application" Output = D5BE731C954ED7732846BB59DBE3A8E30F83E77A4BFF4459F2F1C2B4ECEBB8CE67BA01C62E8AB8578D2D499BD1BB276768781190020A306A97DE281DCC30305D Ctrl = size:64 Ctrl = xof:1 + +Title = KMAC long customisation string (from NIST ACVP) + +MAC = KMAC256 +Key = 9743DBF93102FAF11227B154B8ACD16CF142671F7AA16C559A393A38B4CEF461ED29A6A328D7379C99718790E38B54CA25E9E831CBEA463EE704D1689F94629AB795DF0C77F756DA743309C0E054596BA2D9CC1768ACF7CD351D9A7EB1ABD0A3 +Input = BA63AC9C711F143CCE7FF92D0322649D1BE437D805FD225C0A2879A008373EC3BCCDB09971FAD2BCE5F4347AF7E5238EF01A90ED34193D6AFC1D +Custom = "]J&/.?L/c&}p(b!X|?>i7!]CAH6P@1<R'6|uOu2Vu^kCM!$ Een^pn&Zlale){mQhKjqe,)'-fsX6:u@D6+ZA^b70A)n)LMxo:Y!62;:[hP*yLERjL@rq30+iRaD#9|" +Output = 4057EFD76A63049418AFC54559589821322B6029808A3BCAE4D49E961F909F5F667ACAD56BBCFB8033DCB4CC10AF1B53F014B8 +Ctrl = size:51 +Ctrl = xof:1 + +Title = KMAC long customisation string negative test + +MAC = KMAC128 +Key = 404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F +Input = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7 +Custom = ":abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789::abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789::abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789::abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789::" +Result = MAC_INIT_ERROR +