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 OR GPL-2.0-or-later 10 */ 11/* 12 * PKCS#5 includes PBKDF2 and more 13 * 14 * http://tools.ietf.org/html/rfc2898 (Specification) 15 * http://tools.ietf.org/html/rfc6070 (Test vectors) 16 */ 17 18#include "common.h" 19 20#if defined(MBEDTLS_PKCS5_C) 21 22#include "mbedtls/pkcs5.h" 23#include "mbedtls/error.h" 24 25#if defined(MBEDTLS_ASN1_PARSE_C) 26#include "mbedtls/asn1.h" 27#if defined(MBEDTLS_CIPHER_C) 28#include "mbedtls/cipher.h" 29#endif /* MBEDTLS_CIPHER_C */ 30#include "mbedtls/oid.h" 31#endif /* MBEDTLS_ASN1_PARSE_C */ 32 33#include <string.h> 34 35#include "mbedtls/platform.h" 36 37#include "psa_util_internal.h" 38 39#if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C) 40static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params, 41 mbedtls_asn1_buf *salt, int *iterations, 42 int *keylen, mbedtls_md_type_t *md_type) 43{ 44 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 45 mbedtls_asn1_buf prf_alg_oid; 46 unsigned char *p = params->p; 47 const unsigned char *end = params->p + params->len; 48 49 if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { 50 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, 51 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 52 } 53 /* 54 * PBKDF2-params ::= SEQUENCE { 55 * salt OCTET STRING, 56 * iterationCount INTEGER, 57 * keyLength INTEGER OPTIONAL 58 * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 59 * } 60 * 61 */ 62 if ((ret = mbedtls_asn1_get_tag(&p, end, &salt->len, 63 MBEDTLS_ASN1_OCTET_STRING)) != 0) { 64 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); 65 } 66 67 salt->p = p; 68 p += salt->len; 69 70 if ((ret = mbedtls_asn1_get_int(&p, end, iterations)) != 0) { 71 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); 72 } 73 74 if (p == end) { 75 return 0; 76 } 77 78 if ((ret = mbedtls_asn1_get_int(&p, end, keylen)) != 0) { 79 if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { 80 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); 81 } 82 } 83 84 if (p == end) { 85 return 0; 86 } 87 88 if ((ret = mbedtls_asn1_get_alg_null(&p, end, &prf_alg_oid)) != 0) { 89 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); 90 } 91 92 if (mbedtls_oid_get_md_hmac(&prf_alg_oid, md_type) != 0) { 93 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; 94 } 95 96 if (p != end) { 97 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, 98 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 99 } 100 101 return 0; 102} 103 104#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7) 105int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode, 106 const unsigned char *pwd, size_t pwdlen, 107 const unsigned char *data, size_t datalen, 108 unsigned char *output, size_t output_size, 109 size_t *output_len); 110#endif 111 112#if !defined(MBEDTLS_DEPRECATED_REMOVED) 113int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode, 114 const unsigned char *pwd, size_t pwdlen, 115 const unsigned char *data, size_t datalen, 116 unsigned char *output) 117{ 118 size_t output_len = 0; 119 120 /* We assume caller of the function is providing a big enough output buffer 121 * so we pass output_size as SIZE_MAX to pass checks, However, no guarantees 122 * for the output size actually being correct. 123 */ 124 return mbedtls_pkcs5_pbes2_ext(pbe_params, mode, pwd, pwdlen, data, 125 datalen, output, SIZE_MAX, &output_len); 126} 127#endif 128 129int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode, 130 const unsigned char *pwd, size_t pwdlen, 131 const unsigned char *data, size_t datalen, 132 unsigned char *output, size_t output_size, 133 size_t *output_len) 134{ 135 int ret, iterations = 0, keylen = 0; 136 unsigned char *p, *end; 137 mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; 138 mbedtls_asn1_buf salt; 139 mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; 140 unsigned char key[32], iv[32]; 141 const mbedtls_cipher_info_t *cipher_info; 142 mbedtls_cipher_type_t cipher_alg; 143 mbedtls_cipher_context_t cipher_ctx; 144 unsigned int padlen = 0; 145 146 p = pbe_params->p; 147 end = p + pbe_params->len; 148 149 /* 150 * PBES2-params ::= SEQUENCE { 151 * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, 152 * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} 153 * } 154 */ 155 if (pbe_params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { 156 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, 157 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 158 } 159 160 if ((ret = mbedtls_asn1_get_alg(&p, end, &kdf_alg_oid, 161 &kdf_alg_params)) != 0) { 162 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); 163 } 164 165 // Only PBKDF2 supported at the moment 166 // 167 if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid) != 0) { 168 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; 169 } 170 171 if ((ret = pkcs5_parse_pbkdf2_params(&kdf_alg_params, 172 &salt, &iterations, &keylen, 173 &md_type)) != 0) { 174 return ret; 175 } 176 177 if ((ret = mbedtls_asn1_get_alg(&p, end, &enc_scheme_oid, 178 &enc_scheme_params)) != 0) { 179 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); 180 } 181 182 if (mbedtls_oid_get_cipher_alg(&enc_scheme_oid, &cipher_alg) != 0) { 183 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; 184 } 185 186 cipher_info = mbedtls_cipher_info_from_type(cipher_alg); 187 if (cipher_info == NULL) { 188 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; 189 } 190 191 /* 192 * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored 193 * since it is optional and we don't know if it was set or not 194 */ 195 keylen = (int) mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8; 196 197 if (enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING || 198 enc_scheme_params.len != mbedtls_cipher_info_get_iv_size(cipher_info)) { 199 return MBEDTLS_ERR_PKCS5_INVALID_FORMAT; 200 } 201 202 if (mode == MBEDTLS_PKCS5_DECRYPT) { 203 if (output_size < datalen) { 204 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 205 } 206 } 207 208 if (mode == MBEDTLS_PKCS5_ENCRYPT) { 209 padlen = cipher_info->block_size - (datalen % cipher_info->block_size); 210 if (output_size < (datalen + padlen)) { 211 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 212 } 213 } 214 215 mbedtls_cipher_init(&cipher_ctx); 216 217 memcpy(iv, enc_scheme_params.p, enc_scheme_params.len); 218 219 if ((ret = mbedtls_pkcs5_pbkdf2_hmac_ext(md_type, pwd, pwdlen, salt.p, 220 salt.len, iterations, keylen, 221 key)) != 0) { 222 goto exit; 223 } 224 225 if ((ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0) { 226 goto exit; 227 } 228 229 if ((ret = mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen, 230 (mbedtls_operation_t) mode)) != 0) { 231 goto exit; 232 } 233 234#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) 235 { 236 /* PKCS5 uses CBC with PKCS7 padding (which is the same as 237 * "PKCS5 padding" except that it's typically only called PKCS5 238 * with 64-bit-block ciphers). 239 */ 240 mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7; 241#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7) 242 /* For historical reasons, when decrypting, this function works when 243 * decrypting even when support for PKCS7 padding is disabled. In this 244 * case, it ignores the padding, and so will never report a 245 * password mismatch. 246 */ 247 if (mode == MBEDTLS_DECRYPT) { 248 padding = MBEDTLS_PADDING_NONE; 249 } 250#endif 251 if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) { 252 goto exit; 253 } 254 } 255#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ 256 if ((ret = mbedtls_cipher_crypt(&cipher_ctx, iv, enc_scheme_params.len, 257 data, datalen, output, output_len)) != 0) { 258 ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH; 259 } 260 261exit: 262 mbedtls_cipher_free(&cipher_ctx); 263 264 return ret; 265} 266#endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C */ 267 268static int pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx, 269 const unsigned char *password, 270 size_t plen, const unsigned char *salt, size_t slen, 271 unsigned int iteration_count, 272 uint32_t key_length, unsigned char *output) 273{ 274 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 275 unsigned int i; 276 unsigned char md1[MBEDTLS_MD_MAX_SIZE]; 277 unsigned char work[MBEDTLS_MD_MAX_SIZE]; 278 unsigned char md_size = mbedtls_md_get_size(ctx->md_info); 279 size_t use_len; 280 unsigned char *out_p = output; 281 unsigned char counter[4]; 282 283 memset(counter, 0, 4); 284 counter[3] = 1; 285 286#if UINT_MAX > 0xFFFFFFFF 287 if (iteration_count > 0xFFFFFFFF) { 288 return MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA; 289 } 290#endif 291 292 if ((ret = mbedtls_md_hmac_starts(ctx, password, plen)) != 0) { 293 return ret; 294 } 295 while (key_length) { 296 // U1 ends up in work 297 // 298 if ((ret = mbedtls_md_hmac_update(ctx, salt, slen)) != 0) { 299 goto cleanup; 300 } 301 302 if ((ret = mbedtls_md_hmac_update(ctx, counter, 4)) != 0) { 303 goto cleanup; 304 } 305 306 if ((ret = mbedtls_md_hmac_finish(ctx, work)) != 0) { 307 goto cleanup; 308 } 309 310 if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) { 311 goto cleanup; 312 } 313 314 memcpy(md1, work, md_size); 315 316 for (i = 1; i < iteration_count; i++) { 317 // U2 ends up in md1 318 // 319 if ((ret = mbedtls_md_hmac_update(ctx, md1, md_size)) != 0) { 320 goto cleanup; 321 } 322 323 if ((ret = mbedtls_md_hmac_finish(ctx, md1)) != 0) { 324 goto cleanup; 325 } 326 327 if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) { 328 goto cleanup; 329 } 330 331 // U1 xor U2 332 // 333 mbedtls_xor(work, work, md1, md_size); 334 } 335 336 use_len = (key_length < md_size) ? key_length : md_size; 337 memcpy(out_p, work, use_len); 338 339 key_length -= (uint32_t) use_len; 340 out_p += use_len; 341 342 for (i = 4; i > 0; i--) { 343 if (++counter[i - 1] != 0) { 344 break; 345 } 346 } 347 } 348 349cleanup: 350 /* Zeroise buffers to clear sensitive data from memory. */ 351 mbedtls_platform_zeroize(work, MBEDTLS_MD_MAX_SIZE); 352 mbedtls_platform_zeroize(md1, MBEDTLS_MD_MAX_SIZE); 353 354 return ret; 355} 356 357#if !defined(MBEDTLS_DEPRECATED_REMOVED) 358int mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx, 359 const unsigned char *password, 360 size_t plen, const unsigned char *salt, size_t slen, 361 unsigned int iteration_count, 362 uint32_t key_length, unsigned char *output) 363{ 364 return pkcs5_pbkdf2_hmac(ctx, password, plen, salt, slen, iteration_count, 365 key_length, output); 366} 367#endif 368 369int mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_alg, 370 const unsigned char *password, 371 size_t plen, const unsigned char *salt, size_t slen, 372 unsigned int iteration_count, 373 uint32_t key_length, unsigned char *output) 374{ 375 mbedtls_md_context_t md_ctx; 376 const mbedtls_md_info_t *md_info = NULL; 377 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 378 379 md_info = mbedtls_md_info_from_type(md_alg); 380 if (md_info == NULL) { 381 return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; 382 } 383 384 mbedtls_md_init(&md_ctx); 385 386 if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) { 387 goto exit; 388 } 389 ret = pkcs5_pbkdf2_hmac(&md_ctx, password, plen, salt, slen, 390 iteration_count, key_length, output); 391exit: 392 mbedtls_md_free(&md_ctx); 393 return ret; 394} 395 396#if defined(MBEDTLS_SELF_TEST) 397 398#if !defined(MBEDTLS_MD_CAN_SHA1) 399int mbedtls_pkcs5_self_test(int verbose) 400{ 401 if (verbose != 0) { 402 mbedtls_printf(" PBKDF2 (SHA1): skipped\n\n"); 403 } 404 405 return 0; 406} 407#else 408 409#define MAX_TESTS 6 410 411static const size_t plen_test_data[MAX_TESTS] = 412{ 8, 8, 8, 24, 9 }; 413 414static const unsigned char password_test_data[MAX_TESTS][32] = 415{ 416 "password", 417 "password", 418 "password", 419 "passwordPASSWORDpassword", 420 "pass\0word", 421}; 422 423static const size_t slen_test_data[MAX_TESTS] = 424{ 4, 4, 4, 36, 5 }; 425 426static const unsigned char salt_test_data[MAX_TESTS][40] = 427{ 428 "salt", 429 "salt", 430 "salt", 431 "saltSALTsaltSALTsaltSALTsaltSALTsalt", 432 "sa\0lt", 433}; 434 435static const uint32_t it_cnt_test_data[MAX_TESTS] = 436{ 1, 2, 4096, 4096, 4096 }; 437 438static const uint32_t key_len_test_data[MAX_TESTS] = 439{ 20, 20, 20, 25, 16 }; 440 441static const unsigned char result_key_test_data[MAX_TESTS][32] = 442{ 443 { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, 444 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, 445 0x2f, 0xe0, 0x37, 0xa6 }, 446 { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, 447 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, 448 0xd8, 0xde, 0x89, 0x57 }, 449 { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, 450 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, 451 0x65, 0xa4, 0x29, 0xc1 }, 452 { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, 453 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, 454 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, 455 0x38 }, 456 { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, 457 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, 458}; 459 460int mbedtls_pkcs5_self_test(int verbose) 461{ 462 int ret, i; 463 unsigned char key[64]; 464 465 for (i = 0; i < MAX_TESTS; i++) { 466 if (verbose != 0) { 467 mbedtls_printf(" PBKDF2 (SHA1) #%d: ", i); 468 } 469 470 ret = mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, password_test_data[i], 471 plen_test_data[i], salt_test_data[i], 472 slen_test_data[i], it_cnt_test_data[i], 473 key_len_test_data[i], key); 474 if (ret != 0 || 475 memcmp(result_key_test_data[i], key, key_len_test_data[i]) != 0) { 476 if (verbose != 0) { 477 mbedtls_printf("failed\n"); 478 } 479 480 ret = 1; 481 goto exit; 482 } 483 484 if (verbose != 0) { 485 mbedtls_printf("passed\n"); 486 } 487 } 488 489 if (verbose != 0) { 490 mbedtls_printf("\n"); 491 } 492 493exit: 494 return ret; 495} 496#endif /* MBEDTLS_MD_CAN_SHA1 */ 497 498#endif /* MBEDTLS_SELF_TEST */ 499 500#endif /* MBEDTLS_PKCS5_C */ 501