1 /** 2 * \file pkcs5.c 3 * 4 * \brief PKCS#5 functions 5 * 6 * \author Mathias Olsson <mathias@kompetensum.com> 7 * 8 * Copyright The Mbed TLS Contributors 9 * SPDX-License-Identifier: Apache-2.0 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); you may 12 * not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 19 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 */ 23 /* 24 * PKCS#5 includes PBKDF2 and more 25 * 26 * http://tools.ietf.org/html/rfc2898 (Specification) 27 * http://tools.ietf.org/html/rfc6070 (Test vectors) 28 */ 29 30 #include "common.h" 31 32 #if defined(MBEDTLS_PKCS5_C) 33 34 #include "mbedtls/pkcs5.h" 35 #include "mbedtls/error.h" 36 37 #if defined(MBEDTLS_ASN1_PARSE_C) 38 #include "mbedtls/asn1.h" 39 #include "mbedtls/cipher.h" 40 #include "mbedtls/oid.h" 41 #endif /* MBEDTLS_ASN1_PARSE_C */ 42 43 #include <string.h> 44 45 #include "mbedtls/platform.h" 46 47 #include "hash_info.h" 48 #include "mbedtls/psa_util.h" 49 50 #if !defined(MBEDTLS_MD_C) 51 #define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ 52 psa_to_md_errors, \ 53 psa_generic_status_to_mbedtls) 54 #endif 55 56 #if defined(MBEDTLS_ASN1_PARSE_C) 57 static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params, 58 mbedtls_asn1_buf *salt, int *iterations, 59 int *keylen, mbedtls_md_type_t *md_type) 60 { 61 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 62 mbedtls_asn1_buf prf_alg_oid; 63 unsigned char *p = params->p; 64 const unsigned char *end = params->p + params->len; 65 66 if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { 67 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, 68 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 69 } 70 /* 71 * PBKDF2-params ::= SEQUENCE { 72 * salt OCTET STRING, 73 * iterationCount INTEGER, 74 * keyLength INTEGER OPTIONAL 75 * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 76 * } 77 * 78 */ 79 if ((ret = mbedtls_asn1_get_tag(&p, end, &salt->len, 80 MBEDTLS_ASN1_OCTET_STRING)) != 0) { 81 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); 82 } 83 84 salt->p = p; 85 p += salt->len; 86 87 if ((ret = mbedtls_asn1_get_int(&p, end, iterations)) != 0) { 88 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); 89 } 90 91 if (p == end) { 92 return 0; 93 } 94 95 if ((ret = mbedtls_asn1_get_int(&p, end, keylen)) != 0) { 96 if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 97 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); 98 } 99 } 100 101 if (p == end) { 102 return 0; 103 } 104 105 if ((ret = mbedtls_asn1_get_alg_null(&p, end, &prf_alg_oid)) != 0) { 106 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); 107 } 108 109 if (mbedtls_oid_get_md_hmac(&prf_alg_oid, md_type) != 0) { 110 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; 111 } 112 113 if (p != end) { 114 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, 115 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 116 } 117 118 return 0; 119 } 120 121 int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode, 122 const unsigned char *pwd, size_t pwdlen, 123 const unsigned char *data, size_t datalen, 124 unsigned char *output) 125 { 126 int ret, iterations = 0, keylen = 0; 127 unsigned char *p, *end; 128 mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; 129 mbedtls_asn1_buf salt; 130 mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; 131 unsigned char key[32], iv[32]; 132 size_t olen = 0; 133 const mbedtls_cipher_info_t *cipher_info; 134 mbedtls_cipher_type_t cipher_alg; 135 mbedtls_cipher_context_t cipher_ctx; 136 137 p = pbe_params->p; 138 end = p + pbe_params->len; 139 140 /* 141 * PBES2-params ::= SEQUENCE { 142 * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, 143 * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} 144 * } 145 */ 146 if (pbe_params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { 147 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, 148 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 149 } 150 151 if ((ret = mbedtls_asn1_get_alg(&p, end, &kdf_alg_oid, 152 &kdf_alg_params)) != 0) { 153 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); 154 } 155 156 // Only PBKDF2 supported at the moment 157 // 158 if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid) != 0) { 159 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; 160 } 161 162 if ((ret = pkcs5_parse_pbkdf2_params(&kdf_alg_params, 163 &salt, &iterations, &keylen, 164 &md_type)) != 0) { 165 return ret; 166 } 167 168 if ((ret = mbedtls_asn1_get_alg(&p, end, &enc_scheme_oid, 169 &enc_scheme_params)) != 0) { 170 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); 171 } 172 173 if (mbedtls_oid_get_cipher_alg(&enc_scheme_oid, &cipher_alg) != 0) { 174 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; 175 } 176 177 cipher_info = mbedtls_cipher_info_from_type(cipher_alg); 178 if (cipher_info == NULL) { 179 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; 180 } 181 182 /* 183 * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored 184 * since it is optional and we don't know if it was set or not 185 */ 186 keylen = cipher_info->key_bitlen / 8; 187 188 if (enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING || 189 enc_scheme_params.len != cipher_info->iv_size) { 190 return MBEDTLS_ERR_PKCS5_INVALID_FORMAT; 191 } 192 193 mbedtls_cipher_init(&cipher_ctx); 194 195 memcpy(iv, enc_scheme_params.p, enc_scheme_params.len); 196 197 if ((ret = mbedtls_pkcs5_pbkdf2_hmac_ext(md_type, pwd, pwdlen, salt.p, 198 salt.len, iterations, keylen, 199 key)) != 0) { 200 goto exit; 201 } 202 203 if ((ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0) { 204 goto exit; 205 } 206 207 if ((ret = mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen, 208 (mbedtls_operation_t) mode)) != 0) { 209 goto exit; 210 } 211 212 if ((ret = mbedtls_cipher_crypt(&cipher_ctx, iv, enc_scheme_params.len, 213 data, datalen, output, &olen)) != 0) { 214 ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH; 215 } 216 217 exit: 218 mbedtls_cipher_free(&cipher_ctx); 219 220 return ret; 221 } 222 #endif /* MBEDTLS_ASN1_PARSE_C */ 223 224 #if defined(MBEDTLS_MD_C) 225 static int pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx, 226 const unsigned char *password, 227 size_t plen, const unsigned char *salt, size_t slen, 228 unsigned int iteration_count, 229 uint32_t key_length, unsigned char *output) 230 { 231 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 232 unsigned int i; 233 unsigned char md1[MBEDTLS_MD_MAX_SIZE]; 234 unsigned char work[MBEDTLS_MD_MAX_SIZE]; 235 unsigned char md_size = mbedtls_md_get_size(ctx->md_info); 236 size_t use_len; 237 unsigned char *out_p = output; 238 unsigned char counter[4]; 239 240 memset(counter, 0, 4); 241 counter[3] = 1; 242 243 #if UINT_MAX > 0xFFFFFFFF 244 if (iteration_count > 0xFFFFFFFF) { 245 return MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA; 246 } 247 #endif 248 249 if ((ret = mbedtls_md_hmac_starts(ctx, password, plen)) != 0) { 250 return ret; 251 } 252 while (key_length) { 253 // U1 ends up in work 254 // 255 if ((ret = mbedtls_md_hmac_update(ctx, salt, slen)) != 0) { 256 goto cleanup; 257 } 258 259 if ((ret = mbedtls_md_hmac_update(ctx, counter, 4)) != 0) { 260 goto cleanup; 261 } 262 263 if ((ret = mbedtls_md_hmac_finish(ctx, work)) != 0) { 264 goto cleanup; 265 } 266 267 if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) { 268 goto cleanup; 269 } 270 271 memcpy(md1, work, md_size); 272 273 for (i = 1; i < iteration_count; i++) { 274 // U2 ends up in md1 275 // 276 if ((ret = mbedtls_md_hmac_update(ctx, md1, md_size)) != 0) { 277 goto cleanup; 278 } 279 280 if ((ret = mbedtls_md_hmac_finish(ctx, md1)) != 0) { 281 goto cleanup; 282 } 283 284 if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) { 285 goto cleanup; 286 } 287 288 // U1 xor U2 289 // 290 mbedtls_xor(work, work, md1, md_size); 291 } 292 293 use_len = (key_length < md_size) ? key_length : md_size; 294 memcpy(out_p, work, use_len); 295 296 key_length -= (uint32_t) use_len; 297 out_p += use_len; 298 299 for (i = 4; i > 0; i--) { 300 if (++counter[i - 1] != 0) { 301 break; 302 } 303 } 304 } 305 306 cleanup: 307 /* Zeroise buffers to clear sensitive data from memory. */ 308 mbedtls_platform_zeroize(work, MBEDTLS_MD_MAX_SIZE); 309 mbedtls_platform_zeroize(md1, MBEDTLS_MD_MAX_SIZE); 310 311 return ret; 312 } 313 314 #if !defined(MBEDTLS_DEPRECATED_REMOVED) 315 int mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx, 316 const unsigned char *password, 317 size_t plen, const unsigned char *salt, size_t slen, 318 unsigned int iteration_count, 319 uint32_t key_length, unsigned char *output) 320 { 321 return pkcs5_pbkdf2_hmac(ctx, password, plen, salt, slen, iteration_count, 322 key_length, output); 323 } 324 #endif 325 #endif /* MBEDTLS_MD_C */ 326 327 int mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_alg, 328 const unsigned char *password, 329 size_t plen, const unsigned char *salt, size_t slen, 330 unsigned int iteration_count, 331 uint32_t key_length, unsigned char *output) 332 { 333 #if defined(MBEDTLS_MD_C) 334 mbedtls_md_context_t md_ctx; 335 const mbedtls_md_info_t *md_info = NULL; 336 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 337 338 md_info = mbedtls_md_info_from_type(md_alg); 339 if (md_info == NULL) { 340 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; 341 } 342 343 mbedtls_md_init(&md_ctx); 344 345 if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) { 346 goto exit; 347 } 348 ret = pkcs5_pbkdf2_hmac(&md_ctx, password, plen, salt, slen, 349 iteration_count, key_length, output); 350 exit: 351 mbedtls_md_free(&md_ctx); 352 return ret; 353 #else 354 unsigned int i; 355 unsigned char md1[PSA_HASH_MAX_SIZE]; 356 unsigned char work[PSA_HASH_MAX_SIZE]; 357 const unsigned char md_size = mbedtls_hash_info_get_size(md_alg); 358 psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; 359 360 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 361 psa_status_t status_destruction = PSA_ERROR_CORRUPTION_DETECTED; 362 size_t use_len, out_len; 363 unsigned char *out_p = output; 364 unsigned char counter[4]; 365 mbedtls_svc_key_id_t psa_hmac_key = MBEDTLS_SVC_KEY_ID_INIT; 366 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; 367 const psa_algorithm_t alg = PSA_ALG_HMAC(mbedtls_hash_info_psa_from_md(md_alg)); 368 const size_t out_size = PSA_MAC_LENGTH(PSA_KEY_TYPE_HMAC, 0, alg); 369 370 memset(counter, 0, sizeof(counter)); 371 counter[3] = 1; 372 373 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); 374 psa_set_key_algorithm(&attributes, alg); 375 psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); 376 377 if (key_length == 0) { 378 return 0; 379 } 380 if ((status = psa_import_key(&attributes, 381 password, plen, 382 &psa_hmac_key)) != PSA_SUCCESS) { 383 return MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA; 384 } 385 386 #if UINT_MAX > 0xFFFFFFFF 387 if (iteration_count > 0xFFFFFFFF) { 388 return MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA; 389 } 390 #endif 391 392 while (key_length) { 393 status = psa_mac_sign_setup(&operation, psa_hmac_key, 394 PSA_ALG_HMAC(alg)); 395 if (status != PSA_SUCCESS) { 396 goto cleanup; 397 } 398 // U1 ends up in work 399 if ((status = psa_mac_update(&operation, salt, slen)) != PSA_SUCCESS) { 400 goto cleanup; 401 } 402 403 if ((status = psa_mac_update(&operation, counter, sizeof(counter))) != PSA_SUCCESS) { 404 goto cleanup; 405 } 406 407 if ((status = psa_mac_sign_finish(&operation, work, out_size, &out_len)) 408 != PSA_SUCCESS) { 409 goto cleanup; 410 } 411 412 memcpy(md1, work, out_len); 413 414 for (i = 1; i < iteration_count; i++) { 415 // U2 ends up in md1 416 // 417 status = psa_mac_sign_setup(&operation, psa_hmac_key, 418 PSA_ALG_HMAC(alg)); 419 if (status != PSA_SUCCESS) { 420 goto cleanup; 421 } 422 if ((status = psa_mac_update(&operation, md1, md_size)) != PSA_SUCCESS) { 423 goto cleanup; 424 } 425 if ((status = 426 psa_mac_sign_finish(&operation, md1, out_size, &out_len)) != PSA_SUCCESS) { 427 goto cleanup; 428 } 429 430 // U1 xor U2 431 // 432 mbedtls_xor(work, work, md1, md_size); 433 } 434 435 use_len = (key_length < md_size) ? key_length : md_size; 436 memcpy(out_p, work, use_len); 437 438 key_length -= (uint32_t) use_len; 439 out_p += use_len; 440 441 for (i = 4; i > 0; i--) { 442 if (++counter[i - 1] != 0) { 443 break; 444 } 445 } 446 } 447 448 cleanup: 449 /* Zeroise buffers to clear sensitive data from memory. */ 450 mbedtls_platform_zeroize(work, PSA_HASH_MAX_SIZE); 451 mbedtls_platform_zeroize(md1, PSA_HASH_MAX_SIZE); 452 status_destruction = psa_destroy_key(psa_hmac_key); 453 if (status == PSA_SUCCESS && status_destruction != PSA_SUCCESS) { 454 status = status_destruction; 455 } 456 status_destruction = psa_mac_abort(&operation); 457 if (status == PSA_SUCCESS && status_destruction != PSA_SUCCESS) { 458 status = status_destruction; 459 } 460 461 return PSA_TO_MBEDTLS_ERR(status); 462 #endif /* !MBEDTLS_MD_C */ 463 } 464 465 #if defined(MBEDTLS_SELF_TEST) 466 467 #if !defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA) 468 int mbedtls_pkcs5_self_test(int verbose) 469 { 470 if (verbose != 0) { 471 mbedtls_printf(" PBKDF2 (SHA1): skipped\n\n"); 472 } 473 474 return 0; 475 } 476 #else 477 478 #define MAX_TESTS 6 479 480 static const size_t plen_test_data[MAX_TESTS] = 481 { 8, 8, 8, 24, 9 }; 482 483 static const unsigned char password_test_data[MAX_TESTS][32] = 484 { 485 "password", 486 "password", 487 "password", 488 "passwordPASSWORDpassword", 489 "pass\0word", 490 }; 491 492 static const size_t slen_test_data[MAX_TESTS] = 493 { 4, 4, 4, 36, 5 }; 494 495 static const unsigned char salt_test_data[MAX_TESTS][40] = 496 { 497 "salt", 498 "salt", 499 "salt", 500 "saltSALTsaltSALTsaltSALTsaltSALTsalt", 501 "sa\0lt", 502 }; 503 504 static const uint32_t it_cnt_test_data[MAX_TESTS] = 505 { 1, 2, 4096, 4096, 4096 }; 506 507 static const uint32_t key_len_test_data[MAX_TESTS] = 508 { 20, 20, 20, 25, 16 }; 509 510 static const unsigned char result_key_test_data[MAX_TESTS][32] = 511 { 512 { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, 513 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, 514 0x2f, 0xe0, 0x37, 0xa6 }, 515 { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, 516 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, 517 0xd8, 0xde, 0x89, 0x57 }, 518 { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, 519 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, 520 0x65, 0xa4, 0x29, 0xc1 }, 521 { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, 522 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, 523 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, 524 0x38 }, 525 { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, 526 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, 527 }; 528 529 int mbedtls_pkcs5_self_test(int verbose) 530 { 531 int ret, i; 532 unsigned char key[64]; 533 534 for (i = 0; i < MAX_TESTS; i++) { 535 if (verbose != 0) { 536 mbedtls_printf(" PBKDF2 (SHA1) #%d: ", i); 537 } 538 539 ret = mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, password_test_data[i], 540 plen_test_data[i], salt_test_data[i], 541 slen_test_data[i], it_cnt_test_data[i], 542 key_len_test_data[i], key); 543 if (ret != 0 || 544 memcmp(result_key_test_data[i], key, key_len_test_data[i]) != 0) { 545 if (verbose != 0) { 546 mbedtls_printf("failed\n"); 547 } 548 549 ret = 1; 550 goto exit; 551 } 552 553 if (verbose != 0) { 554 mbedtls_printf("passed\n"); 555 } 556 } 557 558 if (verbose != 0) { 559 mbedtls_printf("\n"); 560 } 561 562 exit: 563 return ret; 564 } 565 #endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA */ 566 567 #endif /* MBEDTLS_SELF_TEST */ 568 569 #endif /* MBEDTLS_PKCS5_C */ 570