diff options
author | Robbie Harwood <rharwood@redhat.com> | 2019-10-17 12:45:03 +1000 |
---|---|---|
committer | Shane Lontis <shane.lontis@oracle.com> | 2019-10-17 12:45:03 +1000 |
commit | f6dead1b72a04b113b4b198ac98a8b9b994ad86f (patch) | |
tree | 2b8869a78f16f0035fc6707440812b2dcc5ac516 | |
parent | 028687c08b20ecc463afaf2d692542b88ebfe8bc (diff) |
[KDF] Add feedback-mode and CMAC support to KBKDF
Implement SP800-108 section 5.2 with CMAC support. As a side effect,
enable 5.1 with CMAC and 5.2 with HMAC. Add test vectors from RFC 6803.
Add OSSL_KDF_PARAM_CIPHER and PROV_R_INVALID_SEED_LENGTH.
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/10143)
-rw-r--r-- | crypto/cmac/cmac.c | 3 | ||||
-rw-r--r-- | crypto/err/openssl.txt | 1 | ||||
-rw-r--r-- | doc/man7/EVP_KDF-KB.pod | 67 | ||||
-rw-r--r-- | include/openssl/core_names.h | 1 | ||||
-rw-r--r-- | providers/common/include/prov/providercommonerr.h | 1 | ||||
-rw-r--r-- | providers/common/provider_err.c | 2 | ||||
-rw-r--r-- | providers/common/provider_util.c | 2 | ||||
-rw-r--r-- | providers/implementations/kdfs/kbkdf.c | 83 | ||||
-rw-r--r-- | test/evp_kdf_test.c | 127 |
9 files changed, 254 insertions, 33 deletions
diff --git a/crypto/cmac/cmac.c b/crypto/cmac/cmac.c index b1be991f87..ec12970cb2 100644 --- a/crypto/cmac/cmac.c +++ b/crypto/cmac/cmac.c @@ -199,7 +199,8 @@ int CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen) return 0; if ((bl = EVP_CIPHER_CTX_block_size(ctx->cctx)) < 0) return 0; - *poutlen = (size_t)bl; + if (poutlen != NULL) + *poutlen = (size_t)bl; if (!out) return 1; lb = ctx->nlast_block; diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index ac170dea6a..46d2eaa2eb 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -2694,6 +2694,7 @@ PROV_R_INVALID_MAC:151:invalid mac PROV_R_INVALID_MODE:125:invalid mode PROV_R_INVALID_MODE_INT:126:invalid mode int PROV_R_INVALID_SALT_LENGTH:112:invalid salt length +PROV_R_INVALID_SEED_LENGTH:154:invalid seed length PROV_R_INVALID_TAG:110:invalid tag PROV_R_INVALID_TAGLEN:118:invalid taglen PROV_R_MISSING_CEK_ALG:144:missing cek alg diff --git a/doc/man7/EVP_KDF-KB.pod b/doc/man7/EVP_KDF-KB.pod index 6fb5415dc1..8a079b2358 100644 --- a/doc/man7/EVP_KDF-KB.pod +++ b/doc/man7/EVP_KDF-KB.pod @@ -21,23 +21,36 @@ The supported parameters are: =over 4 -=item B<OSSL_KDF_PARAM_PROPERTIES> ("properties") <UTF8 string> +=item "properties" (B<OSSL_KDF_PARAM_PROPERTIES>) <UTF8 string> -=item B<OSSL_KDF_PARAM_DIGEST> ("digest") <UTF8 string> +=item "mode" (B<OSSL_KDF_PARAM_MODE>) <UTF8 string> -=item B<OSSL_KDF_PARAM_DIGEST> ("mac") <UTF8 string> +=item "mac" (B<OSSL_KDF_PARAM_MAC>) <UTF8 string> -=item B<OSSL_KDF_PARAM_KEY> ("key") <octet string> +=item "digest" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string> -=item B<OSSL_KDF_PARAM_SALT> ("salt") <octet string> +=item "cipher" (B<OSSL_KDF_PARAM_DIGEST>) <UTF8 string> -=item B<OSSL_KDF_PARAM_INFO> ("info") <octet string> +=item "key" (B<OSSL_KDF_PARAM_KEY>) <octet string> + +=item "salt" (B<OSSL_KDF_PARAM_SALT>) <octet string> + +=item "info (B<OSSL_KDF_PARAM_INFO>) <octet string> + +=item "seed" (B<OSSL_KDF_PARAM_SEED>) <octet string> =back -The parameters key, salt, and info correspond to KI, Label, and Context -(respectively) in SP800-108. As in that document, salt and info are optional -and may be omitted. Currently, only HMAC is supported for mac. +The mode parameter determines which flavor of KBKDF to use - currently the +choices are "counter" and "feedback". Counter is the default, and will be +used if unspecified. The seed parameter is unused in counter mode. + +The parameters key, salt, info, and seed correspond to KI, Label, Context, and +IV (respectively) in SP800-108. As in that document, salt, info, and seed are +optional and may be omitted. + +Depending on whether mac is CMAC or HMAC, either digest or cipher is required +(respectively) and the other is unused. =head1 NOTES @@ -49,7 +62,7 @@ A context for KBKDF can be obtained by calling: The output length of an KBKDF is specified via the C<keylen> parameter to the L<EVP_KDF_derive(3)> function. -Note that currently OpenSSL only implements Counter mode with HMAC. Other +Note that currently OpenSSL only implements counter and feedback modes. Other variants may be supported in the future. =head1 EXAMPLES @@ -84,9 +97,41 @@ Label "label", and Context "context". EVP_KDF_CTX_free(kctx); +This example derives 10 bytes using FEEDBACK-CMAC-AES256, with KI "secret", +Label "label", and IV "sixteen bytes iv". + + EVP_KDF *kdf; + EVP_KDF_CTX *kctx; + unsigned char out[10]; + OSSL_PARAM params[8], *p = params; + unsigned char *iv = "sixteen bytes iv"; + + kdf = EVP_KDF_fetch(NULL, "KBKDF", NULL); + kctx = EVP_KDF_CTX_new(kdf); + EVP_KDF_free(kdf); + + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CIPHER, "AES256", 0); + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC, "CMAC", 0); + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MODE, "FEEDBACK", 0); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, + "secret", strlen("secret")); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, + "context", strlen("context")); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, + "label", strlen("label")); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SEED, + iv, strlen(iv)); + *p = OSSL_PARAM_construct_end(); + if (EVP_KDF_CTX_set_params(kctx, params) <= 0) + error("EVP_KDF_CTX_set_params"); + else if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) + error("EVP_KDF_derive"); + + EVP_KDF_CTX_free(kctx); + =head1 CONFORMING TO -NIST SP800-108, IETF RFC 8009. +NIST SP800-108, IETF RFC 6803, IETF RFC 8009. =head1 SEE ALSO diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h index d9ef31cff0..f0e6334d89 100644 --- a/include/openssl/core_names.h +++ b/include/openssl/core_names.h @@ -114,6 +114,7 @@ extern "C" { #define OSSL_KDF_PARAM_SALT "salt" /* octet string */ #define OSSL_KDF_PARAM_PASSWORD "pass" /* octet string */ #define OSSL_KDF_PARAM_DIGEST OSSL_ALG_PARAM_DIGEST /* utf8 string */ +#define OSSL_KDF_PARAM_CIPHER OSSL_ALG_PARAM_CIPHER /* utf8 string */ #define OSSL_KDF_PARAM_MAC OSSL_ALG_PARAM_MAC /* utf8 string */ #define OSSL_KDF_PARAM_MAC_SIZE "maclen" /* size_t */ #define OSSL_KDF_PARAM_PROPERTIES OSSL_ALG_PARAM_PROPERTIES /* utf8 string */ diff --git a/providers/common/include/prov/providercommonerr.h b/providers/common/include/prov/providercommonerr.h index 90c6d11d83..d35789e832 100644 --- a/providers/common/include/prov/providercommonerr.h +++ b/providers/common/include/prov/providercommonerr.h @@ -73,6 +73,7 @@ int ERR_load_PROV_strings(void); # define PROV_R_INVALID_MODE 125 # define PROV_R_INVALID_MODE_INT 126 # define PROV_R_INVALID_SALT_LENGTH 112 +# define PROV_R_INVALID_SEED_LENGTH 154 # define PROV_R_INVALID_TAG 110 # define PROV_R_INVALID_TAGLEN 118 # define PROV_R_MISSING_CEK_ALG 144 diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c index ae1552283d..20060b0b35 100644 --- a/providers/common/provider_err.c +++ b/providers/common/provider_err.c @@ -49,6 +49,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MODE_INT), "invalid mode int"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_SALT_LENGTH), "invalid salt length"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_SEED_LENGTH), + "invalid seed length"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_TAG), "invalid tag"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_TAGLEN), "invalid taglen"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CEK_ALG), "missing cek alg"}, diff --git a/providers/common/provider_util.c b/providers/common/provider_util.c index bdc86b1c05..ef4396f432 100644 --- a/providers/common/provider_util.c +++ b/providers/common/provider_util.c @@ -214,7 +214,7 @@ int ossl_prov_macctx_load_from_params(EVP_MAC_CTX **macctx, *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, (char *)mdname, 0); if (ciphername != NULL) - *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, + *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, (char *)ciphername, 0); if (properties != NULL) *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_PROPERTIES, diff --git a/providers/implementations/kdfs/kbkdf.c b/providers/implementations/kdfs/kbkdf.c index 6faf22e8d2..1c0e2b2b78 100644 --- a/providers/implementations/kdfs/kbkdf.c +++ b/providers/implementations/kdfs/kbkdf.c @@ -10,13 +10,13 @@ /* * This implements https://csrc.nist.gov/publications/detail/sp/800-108/final - * section 5.1 ("counter mode") in HMAC only. That document does not name the - * KDFs it defines; the name is derived from + * section 5.1 ("counter mode") and section 5.2 ("feedback mode") in both HMAC + * and CMAC. That document does not name the KDFs it defines; the name is + * derived from * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Key-Derivation * - * Note that sections 5.2 ("feedback mode") and 5.3 ("double-pipeline mode") - * are not implemented, though it would be possible to do so in the future. - * CMAC mode is also not implemented; some plumbing would be required. + * Note that section 5.3 ("double-pipeline mode") is not implemented, though + * it would be possible to do so in the future. * * These versions all assume the counter is used. It would be relatively * straightforward to expose a configuration handle should the need arise. @@ -46,9 +46,15 @@ #define MIN(a, b) ((a) < (b)) ? (a) : (b) +typedef enum { + COUNTER = 0, + FEEDBACK +} kbkdf_mode; + /* Our context structure. */ typedef struct { void *provctx; + kbkdf_mode mode; EVP_MAC_CTX *ctx_init; /* Names are lowercased versions of those found in SP800-108. */ @@ -58,6 +64,8 @@ typedef struct { size_t label_len; unsigned char *context; size_t context_len; + unsigned char *iv; + size_t iv_len; } KBKDF; /* Definitions needed for typechecking. */ @@ -117,22 +125,27 @@ static void kbkdf_reset(void *vctx) OPENSSL_clear_free(ctx->context, ctx->context_len); OPENSSL_clear_free(ctx->label, ctx->label_len); OPENSSL_clear_free(ctx->ki, ctx->ki_len); + OPENSSL_clear_free(ctx->iv, ctx->iv_len); memset(ctx, 0, sizeof(*ctx)); } -/* SP800-108 section 5.1. */ -static int kbkdf_derive_counter(EVP_MAC_CTX *ctx_init, - unsigned char *label, size_t label_len, - unsigned char *context, size_t context_len, - unsigned char *k_i, size_t h, uint32_t l, - unsigned char *ko, size_t ko_len) +/* SP800-108 section 5.1 or section 5.2 depending on mode. */ +static int derive(EVP_MAC_CTX *ctx_init, kbkdf_mode mode, unsigned char *iv, + size_t iv_len, unsigned char *label, size_t label_len, + unsigned char *context, size_t context_len, + unsigned char *k_i, size_t h, uint32_t l, unsigned char *ko, + size_t ko_len) { int ret = 0; EVP_MAC_CTX *ctx = NULL; - size_t written = 0, to_write; + size_t written = 0, to_write, k_i_len = iv_len; const unsigned char zero = 0; uint32_t counter, i; + /* Setup K(0) for feedback mode. */ + if (iv_len > 0) + memcpy(k_i, iv, iv_len); + for (counter = 1; written < ko_len; counter++) { i = be32(counter); @@ -140,6 +153,10 @@ static int kbkdf_derive_counter(EVP_MAC_CTX *ctx_init, if (ctx == NULL) goto done; + /* Perform feedback, if appropriate. */ + if (mode == FEEDBACK && !EVP_MAC_update(ctx, k_i, k_i_len)) + goto done; + if (!EVP_MAC_update(ctx, (unsigned char *)&i, 4) || !EVP_MAC_update(ctx, label, label_len) || !EVP_MAC_update(ctx, &zero, 1) @@ -152,6 +169,7 @@ static int kbkdf_derive_counter(EVP_MAC_CTX *ctx_init, memcpy(ko + written, k_i, MIN(to_write, h)); written += h; + k_i_len = h; EVP_MAC_CTX_free(ctx); ctx = NULL; } @@ -170,14 +188,15 @@ static int kbkdf_derive(void *vctx, unsigned char *key, size_t keylen) uint32_t l = be32(keylen * 8); size_t h = 0; - /* Label and Context are permitted to be empty. Check everything else. */ + /* label, context, and iv are permitted to be empty. Check everything + * else. */ if (ctx->ctx_init == NULL) { if (ctx->ki_len == 0 || ctx->ki == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); return 0; } - /* Could either be missing MAC or missing message digest - - * arbitrarily, I pick this one. */ + /* Could either be missing MAC or missing message digest or missing + * cipher - arbitrarily, I pick this one. */ ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MAC); return 0; } @@ -185,14 +204,18 @@ static int kbkdf_derive(void *vctx, unsigned char *key, size_t keylen) h = EVP_MAC_size(ctx->ctx_init); if (h == 0) goto done; + if (ctx->iv_len != 0 && ctx->iv_len != h) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SEED_LENGTH); + goto done; + } k_i = OPENSSL_zalloc(h); if (k_i == NULL) goto done; - ret = kbkdf_derive_counter( - ctx->ctx_init, ctx->label, ctx->label_len, ctx->context, - ctx->context_len, k_i, h, l, key, keylen); + ret = derive(ctx->ctx_init, ctx->mode, ctx->iv, ctx->iv_len, ctx->label, + ctx->label_len, ctx->context, ctx->context_len, k_i, h, l, + key, keylen); done: if (ret != 1) OPENSSL_cleanse(key, keylen); @@ -222,12 +245,25 @@ static int kbkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) NULL, NULL, libctx)) return 0; else if (ctx->ctx_init != NULL - && !EVP_MAC_is_a(EVP_MAC_CTX_mac(ctx->ctx_init), - OSSL_MAC_NAME_HMAC)) { + && !EVP_MAC_is_a(EVP_MAC_CTX_mac(ctx->ctx_init), + OSSL_MAC_NAME_HMAC) + && !EVP_MAC_is_a(EVP_MAC_CTX_mac(ctx->ctx_init), + OSSL_MAC_NAME_CMAC)) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MAC); return 0; } + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE); + if (p != NULL && strncasecmp("counter", p->data, p->data_size) == 0) { + ctx->mode = COUNTER; + } else if (p != NULL + && strncasecmp("feedback", p->data, p->data_size) == 0) { + ctx->mode = FEEDBACK; + } else if (p != NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); + return 0; + } + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY); if (p != NULL && !kbkdf_set_buffer(&ctx->ki, &ctx->ki_len, p)) return 0; @@ -240,6 +276,10 @@ static int kbkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) if (p != NULL && !kbkdf_set_buffer(&ctx->context, &ctx->context_len, p)) return 0; + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SEED); + if (p != NULL && !kbkdf_set_buffer(&ctx->iv, &ctx->iv_len, p)) + return 0; + /* Set up digest context, if we can. */ if (ctx->ctx_init != NULL && ctx->ki_len != 0) { mparams[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, @@ -260,8 +300,11 @@ static const OSSL_PARAM *kbkdf_settable_ctx_params(void) OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0), OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0), OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SEED, NULL, 0), OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CIPHER, NULL, 0), OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MAC, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MODE, NULL, 0), OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), OSSL_PARAM_END, diff --git a/test/evp_kdf_test.c b/test/evp_kdf_test.c index 3761dff9fa..21a0c270fe 100644 --- a/test/evp_kdf_test.c +++ b/test/evp_kdf_test.c @@ -297,6 +297,131 @@ static int test_kdf_x963(void) return ret; } +/* + * KBKDF test vectors from RFC 6803 (Camellia Encryption for Kerberos 5) + * section 10. + */ +static int test_kdf_kbkdf_6803_128(void) +{ + int ret = 0, i, p; + EVP_KDF_CTX *kctx; + OSSL_PARAM params[7]; + static unsigned char input_key[] = { + 0x57, 0xD0, 0x29, 0x72, 0x98, 0xFF, 0xD9, 0xD3, + 0x5D, 0xE5, 0xA4, 0x7F, 0xB4, 0xBD, 0xE2, 0x4B, + }; + static unsigned char constants[][5] = { + { 0x00, 0x00, 0x00, 0x02, 0x99 }, + { 0x00, 0x00, 0x00, 0x02, 0xaa }, + { 0x00, 0x00, 0x00, 0x02, 0x55 }, + }; + static unsigned char outputs[][16] = { + {0xD1, 0x55, 0x77, 0x5A, 0x20, 0x9D, 0x05, 0xF0, + 0x2B, 0x38, 0xD4, 0x2A, 0x38, 0x9E, 0x5A, 0x56}, + {0x64, 0xDF, 0x83, 0xF8, 0x5A, 0x53, 0x2F, 0x17, + 0x57, 0x7D, 0x8C, 0x37, 0x03, 0x57, 0x96, 0xAB}, + {0x3E, 0x4F, 0xBD, 0xF3, 0x0F, 0xB8, 0x25, 0x9C, + 0x42, 0x5C, 0xB6, 0xC9, 0x6F, 0x1F, 0x46, 0x35} + }; + static unsigned char iv[16] = { 0 }; + unsigned char result[16] = { 0 }; + + for (i = 0; i < 3; i++) { + p = 0; + params[p++] = OSSL_PARAM_construct_utf8_string( + OSSL_KDF_PARAM_CIPHER, "CAMELLIA-128-CBC", 0); + params[p++] = OSSL_PARAM_construct_utf8_string( + OSSL_KDF_PARAM_MAC, "CMAC", 0); + params[p++] = OSSL_PARAM_construct_utf8_string( + OSSL_KDF_PARAM_MODE, "FEEDBACK", 0); + params[p++] = OSSL_PARAM_construct_octet_string( + OSSL_KDF_PARAM_KEY, input_key, sizeof(input_key)); + params[p++] = OSSL_PARAM_construct_octet_string( + OSSL_KDF_PARAM_SALT, constants[i], sizeof(constants[i])); + params[p++] = OSSL_PARAM_construct_octet_string( + OSSL_KDF_PARAM_SEED, iv, sizeof(iv)); + params[p] = OSSL_PARAM_construct_end(); + + kctx = get_kdfbyname("KBKDF"); + ret = TEST_ptr(kctx) + && TEST_true(EVP_KDF_CTX_set_params(kctx, params)) + && TEST_int_gt(EVP_KDF_derive(kctx, result, sizeof(result)), 0) + && TEST_mem_eq(result, sizeof(result), outputs[i], + sizeof(outputs[i])); + EVP_KDF_CTX_free(kctx); + if (ret != 1) + return ret; + } + + return ret; +} + +static int test_kdf_kbkdf_6803_256(void) +{ + int ret = 0, i, p; + EVP_KDF_CTX *kctx; + OSSL_PARAM params[7]; + static unsigned char input_key[] = { + 0xB9, 0xD6, 0x82, 0x8B, 0x20, 0x56, 0xB7, 0xBE, + 0x65, 0x6D, 0x88, 0xA1, 0x23, 0xB1, 0xFA, 0xC6, + 0x82, 0x14, 0xAC, 0x2B, 0x72, 0x7E, 0xCF, 0x5F, + 0x69, 0xAF, 0xE0, 0xC4, 0xDF, 0x2A, 0x6D, 0x2C, + }; + static unsigned char constants[][5] = { + { 0x00, 0x00, 0x00, 0x02, 0x99 }, + { 0x00, 0x00, 0x00, 0x02, 0xaa }, + { 0x00, 0x00, 0x00, 0x02, 0x55 }, + }; + static unsigned char outputs[][32] = { + {0xE4, 0x67, 0xF9, 0xA9, 0x55, 0x2B, 0xC7, 0xD3, + 0x15, 0x5A, 0x62, 0x20, 0xAF, 0x9C, 0x19, 0x22, + 0x0E, 0xEE, 0xD4, 0xFF, 0x78, 0xB0, 0xD1, 0xE6, + 0xA1, 0x54, 0x49, 0x91, 0x46, 0x1A, 0x9E, 0x50, + }, + {0x41, 0x2A, 0xEF, 0xC3, 0x62, 0xA7, 0x28, 0x5F, + 0xC3, 0x96, 0x6C, 0x6A, 0x51, 0x81, 0xE7, 0x60, + 0x5A, 0xE6, 0x75, 0x23, 0x5B, 0x6D, 0x54, 0x9F, + 0xBF, 0xC9, 0xAB, 0x66, 0x30, 0xA4, 0xC6, 0x04, + }, + {0xFA, 0x62, 0x4F, 0xA0, 0xE5, 0x23, 0x99, 0x3F, + 0xA3, 0x88, 0xAE, 0xFD, 0xC6, 0x7E, 0x67, 0xEB, + 0xCD, 0x8C, 0x08, 0xE8, 0xA0, 0x24, 0x6B, 0x1D, + 0x73, 0xB0, 0xD1, 0xDD, 0x9F, 0xC5, 0x82, 0xB0, + }, + }; + static unsigned char iv[16] = { 0 }; + unsigned char result[32] = { 0 }; + + for (i = 0; i < 3; i++) { + p = 0; + params[p++] = OSSL_PARAM_construct_utf8_string( + OSSL_KDF_PARAM_CIPHER, "CAMELLIA-256-CBC", 0); + params[p++] = OSSL_PARAM_construct_utf8_string( + OSSL_KDF_PARAM_MAC, "CMAC", 0); + params[p++] = OSSL_PARAM_construct_utf8_string( + OSSL_KDF_PARAM_MODE, "FEEDBACK", 0); + params[p++] = OSSL_PARAM_construct_octet_string( + OSSL_KDF_PARAM_KEY, input_key, sizeof(input_key)); + params[p++] = OSSL_PARAM_construct_octet_string( + OSSL_KDF_PARAM_SALT, constants[i], sizeof(constants[i])); + params[p++] = OSSL_PARAM_construct_octet_string( + OSSL_KDF_PARAM_SEED, iv, sizeof(iv)); + params[p] = OSSL_PARAM_construct_end(); + + kctx = get_kdfbyname("KBKDF"); + ret = TEST_ptr(kctx) + && TEST_true(EVP_KDF_CTX_set_params(kctx, params)) + && TEST_int_gt(EVP_KDF_derive(kctx, result, sizeof(result)), 0) + && TEST_mem_eq(result, sizeof(result), outputs[i], + sizeof(outputs[i])); + EVP_KDF_CTX_free(kctx); + if (ret != 1) + return ret; + } + + return ret; +} + /* Two test vectors from RFC 8009 (AES Encryption with HMAC-SHA2 for Kerberos * 5) appendix A. */ static int test_kdf_kbkdf_8009_prf1(void) @@ -609,6 +734,8 @@ static int test_kdf_x942_asn1(void) int setup_tests(void) { + ADD_TEST(test_kdf_kbkdf_6803_128); + ADD_TEST(test_kdf_kbkdf_6803_256); ADD_TEST(test_kdf_kbkdf_8009_prf1); ADD_TEST(test_kdf_kbkdf_8009_prf2); ADD_TEST(test_kdf_get_kdf); |