1/* 2 * PKCS#12 Personal Information Exchange Syntax 3 * 4 * Copyright The Mbed TLS Contributors 5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6 */ 7/* 8 * The PKCS #12 Personal Information Exchange Syntax Standard v1.1 9 * 10 * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf 11 * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn 12 */ 13 14#include "common.h" 15 16#if defined(MBEDTLS_PKCS12_C) 17 18#include "mbedtls/pkcs12.h" 19#include "mbedtls/asn1.h" 20#if defined(MBEDTLS_CIPHER_C) 21#include "mbedtls/cipher.h" 22#endif /* MBEDTLS_CIPHER_C */ 23#include "mbedtls/platform_util.h" 24#include "mbedtls/error.h" 25 26#include <string.h> 27 28#if defined(MBEDTLS_DES_C) 29#include "mbedtls/des.h" 30#endif 31 32#include "psa_util_internal.h" 33 34#if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C) 35 36static int pkcs12_parse_pbe_params(mbedtls_asn1_buf *params, 37 mbedtls_asn1_buf *salt, int *iterations) 38{ 39 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 40 unsigned char **p = ¶ms->p; 41 const unsigned char *end = params->p + params->len; 42 43 /* 44 * pkcs-12PbeParams ::= SEQUENCE { 45 * salt OCTET STRING, 46 * iterations INTEGER 47 * } 48 * 49 */ 50 if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { 51 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, 52 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); 53 } 54 55 if ((ret = mbedtls_asn1_get_tag(p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { 56 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret); 57 } 58 59 salt->p = *p; 60 *p += salt->len; 61 62 if ((ret = mbedtls_asn1_get_int(p, end, iterations)) != 0) { 63 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret); 64 } 65 66 if (*p != end) { 67 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, 68 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); 69 } 70 71 return 0; 72} 73 74#define PKCS12_MAX_PWDLEN 128 75 76static int pkcs12_pbe_derive_key_iv(mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type, 77 const unsigned char *pwd, size_t pwdlen, 78 unsigned char *key, size_t keylen, 79 unsigned char *iv, size_t ivlen) 80{ 81 int ret, iterations = 0; 82 mbedtls_asn1_buf salt; 83 size_t i; 84 unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2]; 85 86 if (pwdlen > PKCS12_MAX_PWDLEN) { 87 return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA; 88 } 89 90 memset(&salt, 0, sizeof(mbedtls_asn1_buf)); 91 memset(&unipwd, 0, sizeof(unipwd)); 92 93 if ((ret = pkcs12_parse_pbe_params(pbe_params, &salt, 94 &iterations)) != 0) { 95 return ret; 96 } 97 98 for (i = 0; i < pwdlen; i++) { 99 unipwd[i * 2 + 1] = pwd[i]; 100 } 101 102 if ((ret = mbedtls_pkcs12_derivation(key, keylen, unipwd, pwdlen * 2 + 2, 103 salt.p, salt.len, md_type, 104 MBEDTLS_PKCS12_DERIVE_KEY, iterations)) != 0) { 105 return ret; 106 } 107 108 if (iv == NULL || ivlen == 0) { 109 return 0; 110 } 111 112 if ((ret = mbedtls_pkcs12_derivation(iv, ivlen, unipwd, pwdlen * 2 + 2, 113 salt.p, salt.len, md_type, 114 MBEDTLS_PKCS12_DERIVE_IV, iterations)) != 0) { 115 return ret; 116 } 117 return 0; 118} 119 120#undef PKCS12_MAX_PWDLEN 121 122#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7) 123int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode, 124 mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, 125 const unsigned char *pwd, size_t pwdlen, 126 const unsigned char *data, size_t len, 127 unsigned char *output, size_t output_size, 128 size_t *output_len); 129#endif 130 131#if !defined(MBEDTLS_DEPRECATED_REMOVED) 132int mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode, 133 mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, 134 const unsigned char *pwd, size_t pwdlen, 135 const unsigned char *data, size_t len, 136 unsigned char *output) 137{ 138 size_t output_len = 0; 139 140 /* We assume caller of the function is providing a big enough output buffer 141 * so we pass output_size as SIZE_MAX to pass checks, However, no guarantees 142 * for the output size actually being correct. 143 */ 144 return mbedtls_pkcs12_pbe_ext(pbe_params, mode, cipher_type, md_type, 145 pwd, pwdlen, data, len, output, SIZE_MAX, 146 &output_len); 147} 148#endif 149 150int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode, 151 mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, 152 const unsigned char *pwd, size_t pwdlen, 153 const unsigned char *data, size_t len, 154 unsigned char *output, size_t output_size, 155 size_t *output_len) 156{ 157 int ret, keylen = 0; 158 unsigned char key[32]; 159 unsigned char iv[16]; 160 const mbedtls_cipher_info_t *cipher_info; 161 mbedtls_cipher_context_t cipher_ctx; 162 size_t iv_len = 0; 163 size_t finish_olen = 0; 164 unsigned int padlen = 0; 165 166 if (pwd == NULL && pwdlen != 0) { 167 return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA; 168 } 169 170 cipher_info = mbedtls_cipher_info_from_type(cipher_type); 171 if (cipher_info == NULL) { 172 return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE; 173 } 174 175 keylen = (int) mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8; 176 177 if (mode == MBEDTLS_PKCS12_PBE_DECRYPT) { 178 if (output_size < len) { 179 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 180 } 181 } 182 183 if (mode == MBEDTLS_PKCS12_PBE_ENCRYPT) { 184 padlen = cipher_info->block_size - (len % cipher_info->block_size); 185 if (output_size < (len + padlen)) { 186 return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 187 } 188 } 189 190 iv_len = mbedtls_cipher_info_get_iv_size(cipher_info); 191 if ((ret = pkcs12_pbe_derive_key_iv(pbe_params, md_type, pwd, pwdlen, 192 key, keylen, 193 iv, iv_len)) != 0) { 194 return ret; 195 } 196 197 mbedtls_cipher_init(&cipher_ctx); 198 199 if ((ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0) { 200 goto exit; 201 } 202 203 if ((ret = mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen, 204 (mbedtls_operation_t) mode)) != 0) { 205 goto exit; 206 } 207 208#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) 209 { 210 /* PKCS12 uses CBC with PKCS7 padding */ 211 mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7; 212#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7) 213 /* For historical reasons, when decrypting, this function works when 214 * decrypting even when support for PKCS7 padding is disabled. In this 215 * case, it ignores the padding, and so will never report a 216 * password mismatch. 217 */ 218 if (mode == MBEDTLS_PKCS12_PBE_DECRYPT) { 219 padding = MBEDTLS_PADDING_NONE; 220 } 221#endif 222 if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) { 223 goto exit; 224 } 225 } 226#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ 227 228 ret = mbedtls_cipher_crypt(&cipher_ctx, iv, iv_len, data, len, output, &finish_olen); 229 if (ret == MBEDTLS_ERR_CIPHER_INVALID_PADDING) { 230 ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH; 231 } 232 233 *output_len += finish_olen; 234 235exit: 236 mbedtls_platform_zeroize(key, sizeof(key)); 237 mbedtls_platform_zeroize(iv, sizeof(iv)); 238 mbedtls_cipher_free(&cipher_ctx); 239 240 return ret; 241} 242 243#endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C */ 244 245static void pkcs12_fill_buffer(unsigned char *data, size_t data_len, 246 const unsigned char *filler, size_t fill_len) 247{ 248 unsigned char *p = data; 249 size_t use_len; 250 251 if (filler != NULL && fill_len != 0) { 252 while (data_len > 0) { 253 use_len = (data_len > fill_len) ? fill_len : data_len; 254 memcpy(p, filler, use_len); 255 p += use_len; 256 data_len -= use_len; 257 } 258 } else { 259 /* If either of the above are not true then clearly there is nothing 260 * that this function can do. The function should *not* be called 261 * under either of those circumstances, as you could end up with an 262 * incorrect output but for safety's sake, leaving the check in as 263 * otherwise we could end up with memory corruption.*/ 264 } 265} 266 267 268static int calculate_hashes(mbedtls_md_type_t md_type, int iterations, 269 unsigned char *diversifier, unsigned char *salt_block, 270 unsigned char *pwd_block, unsigned char *hash_output, int use_salt, 271 int use_password, size_t hlen, size_t v) 272{ 273 int ret = -1; 274 size_t i; 275 const mbedtls_md_info_t *md_info; 276 mbedtls_md_context_t md_ctx; 277 md_info = mbedtls_md_info_from_type(md_type); 278 if (md_info == NULL) { 279 return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE; 280 } 281 282 mbedtls_md_init(&md_ctx); 283 284 if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) { 285 return ret; 286 } 287 // Calculate hash( diversifier || salt_block || pwd_block ) 288 if ((ret = mbedtls_md_starts(&md_ctx)) != 0) { 289 goto exit; 290 } 291 292 if ((ret = mbedtls_md_update(&md_ctx, diversifier, v)) != 0) { 293 goto exit; 294 } 295 296 if (use_salt != 0) { 297 if ((ret = mbedtls_md_update(&md_ctx, salt_block, v)) != 0) { 298 goto exit; 299 } 300 } 301 302 if (use_password != 0) { 303 if ((ret = mbedtls_md_update(&md_ctx, pwd_block, v)) != 0) { 304 goto exit; 305 } 306 } 307 308 if ((ret = mbedtls_md_finish(&md_ctx, hash_output)) != 0) { 309 goto exit; 310 } 311 312 // Perform remaining ( iterations - 1 ) recursive hash calculations 313 for (i = 1; i < (size_t) iterations; i++) { 314 if ((ret = mbedtls_md(md_info, hash_output, hlen, hash_output)) 315 != 0) { 316 goto exit; 317 } 318 } 319 320exit: 321 mbedtls_md_free(&md_ctx); 322 return ret; 323} 324 325 326int mbedtls_pkcs12_derivation(unsigned char *data, size_t datalen, 327 const unsigned char *pwd, size_t pwdlen, 328 const unsigned char *salt, size_t saltlen, 329 mbedtls_md_type_t md_type, int id, int iterations) 330{ 331 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 332 unsigned int j; 333 334 unsigned char diversifier[128]; 335 unsigned char salt_block[128], pwd_block[128], hash_block[128] = { 0 }; 336 unsigned char hash_output[MBEDTLS_MD_MAX_SIZE]; 337 unsigned char *p; 338 unsigned char c; 339 int use_password = 0; 340 int use_salt = 0; 341 342 size_t hlen, use_len, v, i; 343 344 // This version only allows max of 64 bytes of password or salt 345 if (datalen > 128 || pwdlen > 64 || saltlen > 64) { 346 return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA; 347 } 348 349 if (pwd == NULL && pwdlen != 0) { 350 return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA; 351 } 352 353 if (salt == NULL && saltlen != 0) { 354 return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA; 355 } 356 357 use_password = (pwd && pwdlen != 0); 358 use_salt = (salt && saltlen != 0); 359 360 hlen = mbedtls_md_get_size_from_type(md_type); 361 362 if (hlen <= 32) { 363 v = 64; 364 } else { 365 v = 128; 366 } 367 368 memset(diversifier, (unsigned char) id, v); 369 370 if (use_salt != 0) { 371 pkcs12_fill_buffer(salt_block, v, salt, saltlen); 372 } 373 374 if (use_password != 0) { 375 pkcs12_fill_buffer(pwd_block, v, pwd, pwdlen); 376 } 377 378 p = data; 379 while (datalen > 0) { 380 if (calculate_hashes(md_type, iterations, diversifier, salt_block, 381 pwd_block, hash_output, use_salt, use_password, hlen, 382 v) != 0) { 383 goto exit; 384 } 385 386 use_len = (datalen > hlen) ? hlen : datalen; 387 memcpy(p, hash_output, use_len); 388 datalen -= use_len; 389 p += use_len; 390 391 if (datalen == 0) { 392 break; 393 } 394 395 // Concatenating copies of hash_output into hash_block (B) 396 pkcs12_fill_buffer(hash_block, v, hash_output, hlen); 397 398 // B += 1 399 for (i = v; i > 0; i--) { 400 if (++hash_block[i - 1] != 0) { 401 break; 402 } 403 } 404 405 if (use_salt != 0) { 406 // salt_block += B 407 c = 0; 408 for (i = v; i > 0; i--) { 409 j = salt_block[i - 1] + hash_block[i - 1] + c; 410 c = MBEDTLS_BYTE_1(j); 411 salt_block[i - 1] = MBEDTLS_BYTE_0(j); 412 } 413 } 414 415 if (use_password != 0) { 416 // pwd_block += B 417 c = 0; 418 for (i = v; i > 0; i--) { 419 j = pwd_block[i - 1] + hash_block[i - 1] + c; 420 c = MBEDTLS_BYTE_1(j); 421 pwd_block[i - 1] = MBEDTLS_BYTE_0(j); 422 } 423 } 424 } 425 426 ret = 0; 427 428exit: 429 mbedtls_platform_zeroize(salt_block, sizeof(salt_block)); 430 mbedtls_platform_zeroize(pwd_block, sizeof(pwd_block)); 431 mbedtls_platform_zeroize(hash_block, sizeof(hash_block)); 432 mbedtls_platform_zeroize(hash_output, sizeof(hash_output)); 433 434 return ret; 435} 436 437#endif /* MBEDTLS_PKCS12_C */ 438