1 /* 2 * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. 3 * Copyright 2019 Red Hat, Inc. 4 * 5 * Licensed under the Apache License 2.0 (the "License"). You may not use 6 * this file except in compliance with the License. You can obtain a copy 7 * in the file LICENSE in the source distribution or at 8 * https://www.openssl.org/source/license.html 9 */ 10 11 /* 12 * This implements https://csrc.nist.gov/publications/detail/sp/800-108/final 13 * section 5.1 ("counter mode") and section 5.2 ("feedback mode") in both HMAC 14 * and CMAC. That document does not name the KDFs it defines; the name is 15 * derived from 16 * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Key-Derivation 17 * 18 * Note that section 5.3 ("double-pipeline mode") is not implemented, though 19 * it would be possible to do so in the future. 20 * 21 * These versions all assume the counter is used. It would be relatively 22 * straightforward to expose a configuration handle should the need arise. 23 * 24 * Variable names attempt to match those of SP800-108. 25 */ 26 27 #include <stdarg.h> 28 #include <stdlib.h> 29 #include <string.h> 30 31 #include <openssl/core_names.h> 32 #include <openssl/evp.h> 33 #include <openssl/hmac.h> 34 #include <openssl/kdf.h> 35 #include <openssl/params.h> 36 #include <openssl/proverr.h> 37 38 #include "internal/cryptlib.h" 39 #include "crypto/evp.h" 40 #include "internal/numbers.h" 41 #include "internal/endian.h" 42 #include "prov/implementations.h" 43 #include "prov/provider_ctx.h" 44 #include "prov/provider_util.h" 45 #include "prov/providercommon.h" 46 #include "prov/securitycheck.h" 47 #include "internal/e_os.h" 48 #include "internal/params.h" 49 50 #define ossl_min(a, b) ((a) < (b)) ? (a) : (b) 51 52 typedef enum { 53 COUNTER = 0, 54 FEEDBACK 55 } kbkdf_mode; 56 57 /* Our context structure. */ 58 typedef struct { 59 void *provctx; 60 kbkdf_mode mode; 61 EVP_MAC_CTX *ctx_init; 62 63 /* Names are lowercased versions of those found in SP800-108. */ 64 int r; 65 unsigned char *ki; 66 size_t ki_len; 67 unsigned char *label; 68 size_t label_len; 69 unsigned char *context; 70 size_t context_len; 71 unsigned char *iv; 72 size_t iv_len; 73 int use_l; 74 int is_kmac; 75 int use_separator; 76 OSSL_FIPS_IND_DECLARE 77 } KBKDF; 78 79 /* Definitions needed for typechecking. */ 80 static OSSL_FUNC_kdf_newctx_fn kbkdf_new; 81 static OSSL_FUNC_kdf_dupctx_fn kbkdf_dup; 82 static OSSL_FUNC_kdf_freectx_fn kbkdf_free; 83 static OSSL_FUNC_kdf_reset_fn kbkdf_reset; 84 static OSSL_FUNC_kdf_derive_fn kbkdf_derive; 85 static OSSL_FUNC_kdf_settable_ctx_params_fn kbkdf_settable_ctx_params; 86 static OSSL_FUNC_kdf_set_ctx_params_fn kbkdf_set_ctx_params; 87 static OSSL_FUNC_kdf_gettable_ctx_params_fn kbkdf_gettable_ctx_params; 88 static OSSL_FUNC_kdf_get_ctx_params_fn kbkdf_get_ctx_params; 89 90 /* Not all platforms have htobe32(). */ 91 static uint32_t be32(uint32_t host) 92 { 93 uint32_t big = 0; 94 DECLARE_IS_ENDIAN; 95 96 if (!IS_LITTLE_ENDIAN) 97 return host; 98 99 big |= (host & 0xff000000) >> 24; 100 big |= (host & 0x00ff0000) >> 8; 101 big |= (host & 0x0000ff00) << 8; 102 big |= (host & 0x000000ff) << 24; 103 return big; 104 } 105 106 static void init(KBKDF *ctx) 107 { 108 ctx->r = 32; 109 ctx->use_l = 1; 110 ctx->use_separator = 1; 111 ctx->is_kmac = 0; 112 } 113 114 static void *kbkdf_new(void *provctx) 115 { 116 KBKDF *ctx; 117 118 if (!ossl_prov_is_running()) 119 return NULL; 120 121 ctx = OPENSSL_zalloc(sizeof(*ctx)); 122 if (ctx == NULL) 123 return NULL; 124 125 ctx->provctx = provctx; 126 OSSL_FIPS_IND_INIT(ctx) 127 init(ctx); 128 return ctx; 129 } 130 131 static void kbkdf_free(void *vctx) 132 { 133 KBKDF *ctx = (KBKDF *)vctx; 134 135 if (ctx != NULL) { 136 kbkdf_reset(ctx); 137 OPENSSL_free(ctx); 138 } 139 } 140 141 static void kbkdf_reset(void *vctx) 142 { 143 KBKDF *ctx = (KBKDF *)vctx; 144 void *provctx = ctx->provctx; 145 146 EVP_MAC_CTX_free(ctx->ctx_init); 147 OPENSSL_clear_free(ctx->context, ctx->context_len); 148 OPENSSL_clear_free(ctx->label, ctx->label_len); 149 OPENSSL_clear_free(ctx->ki, ctx->ki_len); 150 OPENSSL_clear_free(ctx->iv, ctx->iv_len); 151 memset(ctx, 0, sizeof(*ctx)); 152 ctx->provctx = provctx; 153 init(ctx); 154 } 155 156 static void *kbkdf_dup(void *vctx) 157 { 158 const KBKDF *src = (const KBKDF *)vctx; 159 KBKDF *dest; 160 161 dest = kbkdf_new(src->provctx); 162 if (dest != NULL) { 163 dest->ctx_init = EVP_MAC_CTX_dup(src->ctx_init); 164 if (dest->ctx_init == NULL 165 || !ossl_prov_memdup(src->ki, src->ki_len, 166 &dest->ki, &dest->ki_len) 167 || !ossl_prov_memdup(src->label, src->label_len, 168 &dest->label, &dest->label_len) 169 || !ossl_prov_memdup(src->context, src->context_len, 170 &dest->context, &dest->context_len) 171 || !ossl_prov_memdup(src->iv, src->iv_len, 172 &dest->iv, &dest->iv_len)) 173 goto err; 174 dest->mode = src->mode; 175 dest->r = src->r; 176 dest->use_l = src->use_l; 177 dest->use_separator = src->use_separator; 178 dest->is_kmac = src->is_kmac; 179 OSSL_FIPS_IND_COPY(dest, src) 180 } 181 return dest; 182 183 err: 184 kbkdf_free(dest); 185 return NULL; 186 } 187 188 #ifdef FIPS_MODULE 189 static int fips_kbkdf_key_check_passed(KBKDF *ctx) 190 { 191 OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx); 192 int key_approved = ossl_kdf_check_key_size(ctx->ki_len); 193 194 if (!key_approved) { 195 if (!OSSL_FIPS_IND_ON_UNAPPROVED(ctx, OSSL_FIPS_IND_SETTABLE0, 196 libctx, "KBKDF", "Key size", 197 ossl_fips_config_kbkdf_key_check)) { 198 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); 199 return 0; 200 } 201 } 202 return 1; 203 } 204 #endif 205 206 /* SP800-108 section 5.1 or section 5.2 depending on mode. */ 207 static int derive(EVP_MAC_CTX *ctx_init, kbkdf_mode mode, unsigned char *iv, 208 size_t iv_len, unsigned char *label, size_t label_len, 209 unsigned char *context, size_t context_len, 210 unsigned char *k_i, size_t h, uint32_t l, int has_separator, 211 unsigned char *ko, size_t ko_len, int r) 212 { 213 int ret = 0; 214 EVP_MAC_CTX *ctx = NULL; 215 size_t written = 0, to_write, k_i_len = iv_len; 216 const unsigned char zero = 0; 217 uint32_t counter, i; 218 /* 219 * From SP800-108: 220 * The fixed input data is a concatenation of a Label, 221 * a separation indicator 0x00, the Context, and L. 222 * One or more of these fixed input data fields may be omitted. 223 * 224 * has_separator == 0 means that the separator is omitted. 225 * Passing a value of l == 0 means that L is omitted. 226 * The Context and L are omitted automatically if a NULL buffer is passed. 227 */ 228 int has_l = (l != 0); 229 230 /* Setup K(0) for feedback mode. */ 231 if (iv_len > 0) 232 memcpy(k_i, iv, iv_len); 233 234 for (counter = 1; written < ko_len; counter++) { 235 i = be32(counter); 236 237 ctx = EVP_MAC_CTX_dup(ctx_init); 238 if (ctx == NULL) 239 goto done; 240 241 /* Perform feedback, if appropriate. */ 242 if (mode == FEEDBACK && !EVP_MAC_update(ctx, k_i, k_i_len)) 243 goto done; 244 245 if (!EVP_MAC_update(ctx, 4 - (r / 8) + (unsigned char *)&i, r / 8) 246 || !EVP_MAC_update(ctx, label, label_len) 247 || (has_separator && !EVP_MAC_update(ctx, &zero, 1)) 248 || !EVP_MAC_update(ctx, context, context_len) 249 || (has_l && !EVP_MAC_update(ctx, (unsigned char *)&l, 4)) 250 || !EVP_MAC_final(ctx, k_i, NULL, h)) 251 goto done; 252 253 to_write = ko_len - written; 254 memcpy(ko + written, k_i, ossl_min(to_write, h)); 255 written += h; 256 257 k_i_len = h; 258 EVP_MAC_CTX_free(ctx); 259 ctx = NULL; 260 } 261 262 ret = 1; 263 done: 264 EVP_MAC_CTX_free(ctx); 265 return ret; 266 } 267 268 /* This must be run before the key is set */ 269 static int kmac_init(EVP_MAC_CTX *ctx, const unsigned char *custom, size_t customlen) 270 { 271 OSSL_PARAM params[2]; 272 273 if (custom == NULL || customlen == 0) 274 return 1; 275 params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_CUSTOM, 276 (void *)custom, customlen); 277 params[1] = OSSL_PARAM_construct_end(); 278 return EVP_MAC_CTX_set_params(ctx, params) > 0; 279 } 280 281 static int kmac_derive(EVP_MAC_CTX *ctx, unsigned char *out, size_t outlen, 282 const unsigned char *context, size_t contextlen) 283 { 284 OSSL_PARAM params[2]; 285 286 params[0] = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, &outlen); 287 params[1] = OSSL_PARAM_construct_end(); 288 return EVP_MAC_CTX_set_params(ctx, params) > 0 289 && EVP_MAC_update(ctx, context, contextlen) 290 && EVP_MAC_final(ctx, out, NULL, outlen); 291 } 292 293 static int kbkdf_derive(void *vctx, unsigned char *key, size_t keylen, 294 const OSSL_PARAM params[]) 295 { 296 KBKDF *ctx = (KBKDF *)vctx; 297 int ret = 0; 298 unsigned char *k_i = NULL; 299 uint32_t l = 0; 300 size_t h = 0; 301 uint64_t counter_max; 302 303 if (!ossl_prov_is_running() || !kbkdf_set_ctx_params(ctx, params)) 304 return 0; 305 306 /* label, context, and iv are permitted to be empty. Check everything 307 * else. */ 308 if (ctx->ctx_init == NULL) { 309 if (ctx->ki_len == 0 || ctx->ki == NULL) { 310 ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); 311 return 0; 312 } 313 /* Could either be missing MAC or missing message digest or missing 314 * cipher - arbitrarily, I pick this one. */ 315 ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MAC); 316 return 0; 317 } 318 319 /* Fail if the output length is zero */ 320 if (keylen == 0) { 321 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); 322 return 0; 323 } 324 325 if (ctx->is_kmac) { 326 ret = kmac_derive(ctx->ctx_init, key, keylen, 327 ctx->context, ctx->context_len); 328 goto done; 329 } 330 331 h = EVP_MAC_CTX_get_mac_size(ctx->ctx_init); 332 if (h == 0) 333 goto done; 334 335 if (ctx->iv_len != 0 && ctx->iv_len != h) { 336 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SEED_LENGTH); 337 goto done; 338 } 339 340 if (ctx->mode == COUNTER) { 341 /* Fail if keylen is too large for r */ 342 counter_max = (uint64_t)1 << (uint64_t)ctx->r; 343 if ((uint64_t)(keylen / h) >= counter_max) { 344 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); 345 goto done; 346 } 347 } 348 349 if (ctx->use_l != 0) 350 l = be32(keylen * 8); 351 352 k_i = OPENSSL_zalloc(h); 353 if (k_i == NULL) 354 goto done; 355 356 ret = derive(ctx->ctx_init, ctx->mode, ctx->iv, ctx->iv_len, ctx->label, 357 ctx->label_len, ctx->context, ctx->context_len, k_i, h, l, 358 ctx->use_separator, key, keylen, ctx->r); 359 done: 360 if (ret != 1) 361 OPENSSL_cleanse(key, keylen); 362 OPENSSL_clear_free(k_i, h); 363 return ret; 364 } 365 366 static int kbkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) 367 { 368 KBKDF *ctx = (KBKDF *)vctx; 369 OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx); 370 const OSSL_PARAM *p; 371 372 if (ossl_param_is_empty(params)) 373 return 1; 374 375 if (!OSSL_FIPS_IND_SET_CTX_PARAM(ctx, OSSL_FIPS_IND_SETTABLE0, params, 376 OSSL_KDF_PARAM_FIPS_KEY_CHECK)) 377 return 0; 378 379 if (!ossl_prov_macctx_load_from_params(&ctx->ctx_init, params, NULL, 380 NULL, NULL, libctx)) 381 return 0; 382 if (ctx->ctx_init != NULL) { 383 ctx->is_kmac = 0; 384 if (EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->ctx_init), 385 OSSL_MAC_NAME_KMAC128) 386 || EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->ctx_init), 387 OSSL_MAC_NAME_KMAC256)) { 388 ctx->is_kmac = 1; 389 } else if (!EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->ctx_init), 390 OSSL_MAC_NAME_HMAC) 391 && !EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->ctx_init), 392 OSSL_MAC_NAME_CMAC)) { 393 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MAC); 394 return 0; 395 } 396 } 397 398 p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE); 399 if (p != NULL 400 && OPENSSL_strncasecmp("counter", p->data, p->data_size) == 0) { 401 ctx->mode = COUNTER; 402 } else if (p != NULL 403 && OPENSSL_strncasecmp("feedback", p->data, p->data_size) == 0) { 404 ctx->mode = FEEDBACK; 405 } else if (p != NULL) { 406 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); 407 return 0; 408 } 409 410 p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY); 411 if (p != NULL) { 412 if (ossl_param_get1_octet_string(p, OSSL_KDF_PARAM_KEY, 413 &ctx->ki, &ctx->ki_len) == 0) 414 return 0; 415 #ifdef FIPS_MODULE 416 if (!fips_kbkdf_key_check_passed(ctx)) 417 return 0; 418 #endif 419 } 420 421 if (ossl_param_get1_octet_string(params, OSSL_KDF_PARAM_SALT, 422 &ctx->label, &ctx->label_len) == 0) 423 return 0; 424 425 if (ossl_param_get1_concat_octet_string(params, OSSL_KDF_PARAM_INFO, 426 &ctx->context, &ctx->context_len, 427 0) == 0) 428 return 0; 429 430 if (ossl_param_get1_octet_string(params, OSSL_KDF_PARAM_SEED, 431 &ctx->iv, &ctx->iv_len) == 0) 432 return 0; 433 434 p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KBKDF_USE_L); 435 if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->use_l)) 436 return 0; 437 438 p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KBKDF_R); 439 if (p != NULL) { 440 int new_r = 0; 441 442 if (!OSSL_PARAM_get_int(p, &new_r)) 443 return 0; 444 if (new_r != 8 && new_r != 16 && new_r != 24 && new_r != 32) 445 return 0; 446 ctx->r = new_r; 447 } 448 449 p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KBKDF_USE_SEPARATOR); 450 if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->use_separator)) 451 return 0; 452 453 /* Set up digest context, if we can. */ 454 if (ctx->ctx_init != NULL && ctx->ki_len != 0) { 455 if ((ctx->is_kmac && !kmac_init(ctx->ctx_init, ctx->label, ctx->label_len)) 456 || !EVP_MAC_init(ctx->ctx_init, ctx->ki, ctx->ki_len, NULL)) 457 return 0; 458 } 459 return 1; 460 } 461 462 static const OSSL_PARAM *kbkdf_settable_ctx_params(ossl_unused void *ctx, 463 ossl_unused void *provctx) 464 { 465 static const OSSL_PARAM known_settable_ctx_params[] = { 466 OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0), 467 OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0), 468 OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), 469 OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SEED, NULL, 0), 470 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), 471 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CIPHER, NULL, 0), 472 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MAC, NULL, 0), 473 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MODE, NULL, 0), 474 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), 475 OSSL_PARAM_int(OSSL_KDF_PARAM_KBKDF_USE_L, NULL), 476 OSSL_PARAM_int(OSSL_KDF_PARAM_KBKDF_USE_SEPARATOR, NULL), 477 OSSL_PARAM_int(OSSL_KDF_PARAM_KBKDF_R, NULL), 478 OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_KDF_PARAM_FIPS_KEY_CHECK) 479 OSSL_PARAM_END, 480 }; 481 return known_settable_ctx_params; 482 } 483 484 static int kbkdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) 485 { 486 #ifdef FIPS_MODULE 487 KBKDF *ctx = (KBKDF *)vctx; 488 #endif 489 OSSL_PARAM *p; 490 491 /* KBKDF can produce results as large as you like. */ 492 p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE); 493 if (p != NULL && !OSSL_PARAM_set_size_t(p, SIZE_MAX)) 494 return 0; 495 496 if (!OSSL_FIPS_IND_GET_CTX_PARAM(ctx, params)) 497 return 0; 498 return 1; 499 } 500 501 static const OSSL_PARAM *kbkdf_gettable_ctx_params(ossl_unused void *ctx, 502 ossl_unused void *provctx) 503 { 504 static const OSSL_PARAM known_gettable_ctx_params[] = { 505 OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), 506 OSSL_FIPS_IND_GETTABLE_CTX_PARAM() 507 OSSL_PARAM_END 508 }; 509 return known_gettable_ctx_params; 510 } 511 512 const OSSL_DISPATCH ossl_kdf_kbkdf_functions[] = { 513 { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kbkdf_new }, 514 { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kbkdf_dup }, 515 { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kbkdf_free }, 516 { OSSL_FUNC_KDF_RESET, (void(*)(void))kbkdf_reset }, 517 { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kbkdf_derive }, 518 { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, 519 (void(*)(void))kbkdf_settable_ctx_params }, 520 { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kbkdf_set_ctx_params }, 521 { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, 522 (void(*)(void))kbkdf_gettable_ctx_params }, 523 { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kbkdf_get_ctx_params }, 524 OSSL_DISPATCH_END, 525 }; 526