1 /* 2 * Privacy Enhanced Mail (PEM) decoding 3 * 4 * Copyright The Mbed TLS Contributors 5 * SPDX-License-Identifier: Apache-2.0 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may 8 * not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 20 #include "common.h" 21 22 #if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) 23 24 #include "mbedtls/pem.h" 25 #include "mbedtls/base64.h" 26 #include "mbedtls/des.h" 27 #include "mbedtls/aes.h" 28 #include "mbedtls/md.h" 29 #include "mbedtls/cipher.h" 30 #include "mbedtls/platform_util.h" 31 #include "mbedtls/error.h" 32 #include "hash_info.h" 33 34 #include <string.h> 35 36 #include "mbedtls/platform.h" 37 38 #if defined(MBEDTLS_USE_PSA_CRYPTO) 39 #include "psa/crypto.h" 40 #endif 41 42 #if !defined(MBEDTLS_MD5_C) 43 #include "mbedtls/psa_util.h" 44 #define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ 45 psa_to_md_errors, \ 46 psa_generic_status_to_mbedtls) 47 #endif 48 49 #include "mbedtls/legacy_or_psa.h" 50 51 #if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \ 52 defined(MBEDTLS_CIPHER_MODE_CBC) && \ 53 (defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C)) 54 #define PEM_RFC1421 55 #endif /* MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA && 56 MBEDTLS_CIPHER_MODE_CBC && 57 ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ 58 59 #if defined(MBEDTLS_PEM_PARSE_C) 60 void mbedtls_pem_init(mbedtls_pem_context *ctx) 61 { 62 memset(ctx, 0, sizeof(mbedtls_pem_context)); 63 } 64 65 #if defined(PEM_RFC1421) 66 /* 67 * Read a 16-byte hex string and convert it to binary 68 */ 69 static int pem_get_iv(const unsigned char *s, unsigned char *iv, 70 size_t iv_len) 71 { 72 size_t i, j, k; 73 74 memset(iv, 0, iv_len); 75 76 for (i = 0; i < iv_len * 2; i++, s++) { 77 if (*s >= '0' && *s <= '9') { 78 j = *s - '0'; 79 } else 80 if (*s >= 'A' && *s <= 'F') { 81 j = *s - '7'; 82 } else 83 if (*s >= 'a' && *s <= 'f') { 84 j = *s - 'W'; 85 } else { 86 return MBEDTLS_ERR_PEM_INVALID_ENC_IV; 87 } 88 89 k = ((i & 1) != 0) ? j : j << 4; 90 91 iv[i >> 1] = (unsigned char) (iv[i >> 1] | k); 92 } 93 94 return 0; 95 } 96 97 #if defined(MBEDTLS_MD5_C) 98 static int pem_pbkdf1(unsigned char *key, size_t keylen, 99 unsigned char *iv, 100 const unsigned char *pwd, size_t pwdlen) 101 { 102 mbedtls_md_context_t md5_ctx; 103 const mbedtls_md_info_t *md5_info; 104 unsigned char md5sum[16]; 105 size_t use_len; 106 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 107 108 mbedtls_md_init(&md5_ctx); 109 110 /* Prepare the context. (setup() errors gracefully on NULL info.) */ 111 md5_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5); 112 if ((ret = mbedtls_md_setup(&md5_ctx, md5_info, 0)) != 0) { 113 goto exit; 114 } 115 116 /* 117 * key[ 0..15] = MD5(pwd || IV) 118 */ 119 if ((ret = mbedtls_md_starts(&md5_ctx)) != 0) { 120 goto exit; 121 } 122 if ((ret = mbedtls_md_update(&md5_ctx, pwd, pwdlen)) != 0) { 123 goto exit; 124 } 125 if ((ret = mbedtls_md_update(&md5_ctx, iv, 8)) != 0) { 126 goto exit; 127 } 128 if ((ret = mbedtls_md_finish(&md5_ctx, md5sum)) != 0) { 129 goto exit; 130 } 131 132 if (keylen <= 16) { 133 memcpy(key, md5sum, keylen); 134 goto exit; 135 } 136 137 memcpy(key, md5sum, 16); 138 139 /* 140 * key[16..23] = MD5(key[ 0..15] || pwd || IV]) 141 */ 142 if ((ret = mbedtls_md_starts(&md5_ctx)) != 0) { 143 goto exit; 144 } 145 if ((ret = mbedtls_md_update(&md5_ctx, md5sum, 16)) != 0) { 146 goto exit; 147 } 148 if ((ret = mbedtls_md_update(&md5_ctx, pwd, pwdlen)) != 0) { 149 goto exit; 150 } 151 if ((ret = mbedtls_md_update(&md5_ctx, iv, 8)) != 0) { 152 goto exit; 153 } 154 if ((ret = mbedtls_md_finish(&md5_ctx, md5sum)) != 0) { 155 goto exit; 156 } 157 158 use_len = 16; 159 if (keylen < 32) { 160 use_len = keylen - 16; 161 } 162 163 memcpy(key + 16, md5sum, use_len); 164 165 exit: 166 mbedtls_md_free(&md5_ctx); 167 mbedtls_platform_zeroize(md5sum, 16); 168 169 return ret; 170 } 171 #else 172 static int pem_pbkdf1(unsigned char *key, size_t keylen, 173 unsigned char *iv, 174 const unsigned char *pwd, size_t pwdlen) 175 { 176 unsigned char md5sum[16]; 177 psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; 178 size_t output_length = 0; 179 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; 180 181 182 if ((status = psa_hash_setup(&operation, PSA_ALG_MD5)) != PSA_SUCCESS) { 183 goto exit; 184 } 185 186 if ((status = psa_hash_update(&operation, pwd, pwdlen)) != PSA_SUCCESS) { 187 goto exit; 188 } 189 190 if ((status = psa_hash_update(&operation, iv, 8)) != PSA_SUCCESS) { 191 goto exit; 192 } 193 194 if ((status = psa_hash_finish(&operation, md5sum, 195 PSA_HASH_LENGTH(PSA_ALG_MD5), 196 &output_length)) != PSA_SUCCESS) { 197 goto exit; 198 } 199 200 if ((status = psa_hash_abort(&operation)) != PSA_SUCCESS) { 201 goto exit; 202 } 203 204 /* 205 * key[ 0..15] = MD5(pwd || IV) 206 */ 207 if (keylen <= 16) { 208 memcpy(key, md5sum, keylen); 209 goto exit; 210 } 211 212 memcpy(key, md5sum, 16); 213 214 /* 215 * key[16..23] = MD5(key[ 0..15] || pwd || IV]) 216 */ 217 if ((status = psa_hash_setup(&operation, PSA_ALG_MD5)) != PSA_SUCCESS) { 218 goto exit; 219 } 220 221 if ((status = psa_hash_update(&operation, md5sum, 16)) != PSA_SUCCESS) { 222 goto exit; 223 } 224 225 if ((status = psa_hash_update(&operation, pwd, pwdlen)) != PSA_SUCCESS) { 226 goto exit; 227 } 228 229 if ((status = psa_hash_update(&operation, iv, 8)) != PSA_SUCCESS) { 230 goto exit; 231 } 232 233 if ((status = psa_hash_finish(&operation, md5sum, 234 PSA_HASH_LENGTH(PSA_ALG_MD5), 235 &output_length)) != PSA_SUCCESS) { 236 goto exit; 237 } 238 239 if ((status = psa_hash_abort(&operation)) != PSA_SUCCESS) { 240 goto exit; 241 } 242 243 size_t use_len = 16; 244 if (keylen < 32) { 245 use_len = keylen - 16; 246 } 247 248 memcpy(key + 16, md5sum, use_len); 249 250 exit: 251 mbedtls_platform_zeroize(md5sum, 16); 252 253 return PSA_TO_MBEDTLS_ERR(status); 254 } 255 #endif /* MBEDTLS_MD5_C */ 256 257 #if defined(MBEDTLS_DES_C) 258 /* 259 * Decrypt with DES-CBC, using PBKDF1 for key derivation 260 */ 261 static int pem_des_decrypt(unsigned char des_iv[8], 262 unsigned char *buf, size_t buflen, 263 const unsigned char *pwd, size_t pwdlen) 264 { 265 mbedtls_des_context des_ctx; 266 unsigned char des_key[8]; 267 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 268 269 mbedtls_des_init(&des_ctx); 270 271 if ((ret = pem_pbkdf1(des_key, 8, des_iv, pwd, pwdlen)) != 0) { 272 goto exit; 273 } 274 275 if ((ret = mbedtls_des_setkey_dec(&des_ctx, des_key)) != 0) { 276 goto exit; 277 } 278 ret = mbedtls_des_crypt_cbc(&des_ctx, MBEDTLS_DES_DECRYPT, buflen, 279 des_iv, buf, buf); 280 281 exit: 282 mbedtls_des_free(&des_ctx); 283 mbedtls_platform_zeroize(des_key, 8); 284 285 return ret; 286 } 287 288 /* 289 * Decrypt with 3DES-CBC, using PBKDF1 for key derivation 290 */ 291 static int pem_des3_decrypt(unsigned char des3_iv[8], 292 unsigned char *buf, size_t buflen, 293 const unsigned char *pwd, size_t pwdlen) 294 { 295 mbedtls_des3_context des3_ctx; 296 unsigned char des3_key[24]; 297 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 298 299 mbedtls_des3_init(&des3_ctx); 300 301 if ((ret = pem_pbkdf1(des3_key, 24, des3_iv, pwd, pwdlen)) != 0) { 302 goto exit; 303 } 304 305 if ((ret = mbedtls_des3_set3key_dec(&des3_ctx, des3_key)) != 0) { 306 goto exit; 307 } 308 ret = mbedtls_des3_crypt_cbc(&des3_ctx, MBEDTLS_DES_DECRYPT, buflen, 309 des3_iv, buf, buf); 310 311 exit: 312 mbedtls_des3_free(&des3_ctx); 313 mbedtls_platform_zeroize(des3_key, 24); 314 315 return ret; 316 } 317 #endif /* MBEDTLS_DES_C */ 318 319 #if defined(MBEDTLS_AES_C) 320 /* 321 * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation 322 */ 323 static int pem_aes_decrypt(unsigned char aes_iv[16], unsigned int keylen, 324 unsigned char *buf, size_t buflen, 325 const unsigned char *pwd, size_t pwdlen) 326 { 327 mbedtls_aes_context aes_ctx; 328 unsigned char aes_key[32]; 329 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 330 331 mbedtls_aes_init(&aes_ctx); 332 333 if ((ret = pem_pbkdf1(aes_key, keylen, aes_iv, pwd, pwdlen)) != 0) { 334 goto exit; 335 } 336 337 if ((ret = mbedtls_aes_setkey_dec(&aes_ctx, aes_key, keylen * 8)) != 0) { 338 goto exit; 339 } 340 ret = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, buflen, 341 aes_iv, buf, buf); 342 343 exit: 344 mbedtls_aes_free(&aes_ctx); 345 mbedtls_platform_zeroize(aes_key, keylen); 346 347 return ret; 348 } 349 #endif /* MBEDTLS_AES_C */ 350 351 #endif /* PEM_RFC1421 */ 352 353 int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const char *footer, 354 const unsigned char *data, const unsigned char *pwd, 355 size_t pwdlen, size_t *use_len) 356 { 357 int ret, enc; 358 size_t len; 359 unsigned char *buf; 360 const unsigned char *s1, *s2, *end; 361 #if defined(PEM_RFC1421) 362 unsigned char pem_iv[16]; 363 mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE; 364 #else 365 ((void) pwd); 366 ((void) pwdlen); 367 #endif /* PEM_RFC1421 */ 368 369 if (ctx == NULL) { 370 return MBEDTLS_ERR_PEM_BAD_INPUT_DATA; 371 } 372 373 s1 = (unsigned char *) strstr((const char *) data, header); 374 375 if (s1 == NULL) { 376 return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 377 } 378 379 s2 = (unsigned char *) strstr((const char *) data, footer); 380 381 if (s2 == NULL || s2 <= s1) { 382 return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 383 } 384 385 s1 += strlen(header); 386 if (*s1 == ' ') { 387 s1++; 388 } 389 if (*s1 == '\r') { 390 s1++; 391 } 392 if (*s1 == '\n') { 393 s1++; 394 } else { 395 return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 396 } 397 398 end = s2; 399 end += strlen(footer); 400 if (*end == ' ') { 401 end++; 402 } 403 if (*end == '\r') { 404 end++; 405 } 406 if (*end == '\n') { 407 end++; 408 } 409 *use_len = end - data; 410 411 enc = 0; 412 413 if (s2 - s1 >= 22 && memcmp(s1, "Proc-Type: 4,ENCRYPTED", 22) == 0) { 414 #if defined(PEM_RFC1421) 415 enc++; 416 417 s1 += 22; 418 if (*s1 == '\r') { 419 s1++; 420 } 421 if (*s1 == '\n') { 422 s1++; 423 } else { 424 return MBEDTLS_ERR_PEM_INVALID_DATA; 425 } 426 427 428 #if defined(MBEDTLS_DES_C) 429 if (s2 - s1 >= 23 && memcmp(s1, "DEK-Info: DES-EDE3-CBC,", 23) == 0) { 430 enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC; 431 432 s1 += 23; 433 if (s2 - s1 < 16 || pem_get_iv(s1, pem_iv, 8) != 0) { 434 return MBEDTLS_ERR_PEM_INVALID_ENC_IV; 435 } 436 437 s1 += 16; 438 } else if (s2 - s1 >= 18 && memcmp(s1, "DEK-Info: DES-CBC,", 18) == 0) { 439 enc_alg = MBEDTLS_CIPHER_DES_CBC; 440 441 s1 += 18; 442 if (s2 - s1 < 16 || pem_get_iv(s1, pem_iv, 8) != 0) { 443 return MBEDTLS_ERR_PEM_INVALID_ENC_IV; 444 } 445 446 s1 += 16; 447 } 448 #endif /* MBEDTLS_DES_C */ 449 450 #if defined(MBEDTLS_AES_C) 451 if (s2 - s1 >= 14 && memcmp(s1, "DEK-Info: AES-", 14) == 0) { 452 if (s2 - s1 < 22) { 453 return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG; 454 } else if (memcmp(s1, "DEK-Info: AES-128-CBC,", 22) == 0) { 455 enc_alg = MBEDTLS_CIPHER_AES_128_CBC; 456 } else if (memcmp(s1, "DEK-Info: AES-192-CBC,", 22) == 0) { 457 enc_alg = MBEDTLS_CIPHER_AES_192_CBC; 458 } else if (memcmp(s1, "DEK-Info: AES-256-CBC,", 22) == 0) { 459 enc_alg = MBEDTLS_CIPHER_AES_256_CBC; 460 } else { 461 return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG; 462 } 463 464 s1 += 22; 465 if (s2 - s1 < 32 || pem_get_iv(s1, pem_iv, 16) != 0) { 466 return MBEDTLS_ERR_PEM_INVALID_ENC_IV; 467 } 468 469 s1 += 32; 470 } 471 #endif /* MBEDTLS_AES_C */ 472 473 if (enc_alg == MBEDTLS_CIPHER_NONE) { 474 return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG; 475 } 476 477 if (*s1 == '\r') { 478 s1++; 479 } 480 if (*s1 == '\n') { 481 s1++; 482 } else { 483 return MBEDTLS_ERR_PEM_INVALID_DATA; 484 } 485 #else 486 return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE; 487 #endif /* PEM_RFC1421 */ 488 } 489 490 if (s1 >= s2) { 491 return MBEDTLS_ERR_PEM_INVALID_DATA; 492 } 493 494 ret = mbedtls_base64_decode(NULL, 0, &len, s1, s2 - s1); 495 496 if (ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER) { 497 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret); 498 } 499 500 if ((buf = mbedtls_calloc(1, len)) == NULL) { 501 return MBEDTLS_ERR_PEM_ALLOC_FAILED; 502 } 503 504 if ((ret = mbedtls_base64_decode(buf, len, &len, s1, s2 - s1)) != 0) { 505 mbedtls_platform_zeroize(buf, len); 506 mbedtls_free(buf); 507 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret); 508 } 509 510 if (enc != 0) { 511 #if defined(PEM_RFC1421) 512 if (pwd == NULL) { 513 mbedtls_platform_zeroize(buf, len); 514 mbedtls_free(buf); 515 return MBEDTLS_ERR_PEM_PASSWORD_REQUIRED; 516 } 517 518 ret = 0; 519 520 #if defined(MBEDTLS_DES_C) 521 if (enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC) { 522 ret = pem_des3_decrypt(pem_iv, buf, len, pwd, pwdlen); 523 } else if (enc_alg == MBEDTLS_CIPHER_DES_CBC) { 524 ret = pem_des_decrypt(pem_iv, buf, len, pwd, pwdlen); 525 } 526 #endif /* MBEDTLS_DES_C */ 527 528 #if defined(MBEDTLS_AES_C) 529 if (enc_alg == MBEDTLS_CIPHER_AES_128_CBC) { 530 ret = pem_aes_decrypt(pem_iv, 16, buf, len, pwd, pwdlen); 531 } else if (enc_alg == MBEDTLS_CIPHER_AES_192_CBC) { 532 ret = pem_aes_decrypt(pem_iv, 24, buf, len, pwd, pwdlen); 533 } else if (enc_alg == MBEDTLS_CIPHER_AES_256_CBC) { 534 ret = pem_aes_decrypt(pem_iv, 32, buf, len, pwd, pwdlen); 535 } 536 #endif /* MBEDTLS_AES_C */ 537 538 if (ret != 0) { 539 mbedtls_free(buf); 540 return ret; 541 } 542 543 /* 544 * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 545 * length bytes (allow 4 to be sure) in all known use cases. 546 * 547 * Use that as a heuristic to try to detect password mismatches. 548 */ 549 if (len <= 2 || buf[0] != 0x30 || buf[1] > 0x83) { 550 mbedtls_platform_zeroize(buf, len); 551 mbedtls_free(buf); 552 return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH; 553 } 554 #else 555 mbedtls_platform_zeroize(buf, len); 556 mbedtls_free(buf); 557 return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE; 558 #endif /* PEM_RFC1421 */ 559 } 560 561 ctx->buf = buf; 562 ctx->buflen = len; 563 564 return 0; 565 } 566 567 void mbedtls_pem_free(mbedtls_pem_context *ctx) 568 { 569 if (ctx->buf != NULL) { 570 mbedtls_platform_zeroize(ctx->buf, ctx->buflen); 571 mbedtls_free(ctx->buf); 572 } 573 mbedtls_free(ctx->info); 574 575 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pem_context)); 576 } 577 #endif /* MBEDTLS_PEM_PARSE_C */ 578 579 #if defined(MBEDTLS_PEM_WRITE_C) 580 int mbedtls_pem_write_buffer(const char *header, const char *footer, 581 const unsigned char *der_data, size_t der_len, 582 unsigned char *buf, size_t buf_len, size_t *olen) 583 { 584 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 585 unsigned char *encode_buf = NULL, *c, *p = buf; 586 size_t len = 0, use_len, add_len = 0; 587 588 mbedtls_base64_encode(NULL, 0, &use_len, der_data, der_len); 589 add_len = strlen(header) + strlen(footer) + (use_len / 64) + 1; 590 591 if (use_len + add_len > buf_len) { 592 *olen = use_len + add_len; 593 return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL; 594 } 595 596 if (use_len != 0 && 597 ((encode_buf = mbedtls_calloc(1, use_len)) == NULL)) { 598 return MBEDTLS_ERR_PEM_ALLOC_FAILED; 599 } 600 601 if ((ret = mbedtls_base64_encode(encode_buf, use_len, &use_len, der_data, 602 der_len)) != 0) { 603 mbedtls_free(encode_buf); 604 return ret; 605 } 606 607 memcpy(p, header, strlen(header)); 608 p += strlen(header); 609 c = encode_buf; 610 611 while (use_len) { 612 len = (use_len > 64) ? 64 : use_len; 613 memcpy(p, c, len); 614 use_len -= len; 615 p += len; 616 c += len; 617 *p++ = '\n'; 618 } 619 620 memcpy(p, footer, strlen(footer)); 621 p += strlen(footer); 622 623 *p++ = '\0'; 624 *olen = p - buf; 625 626 /* Clean any remaining data previously written to the buffer */ 627 memset(buf + *olen, 0, buf_len - *olen); 628 629 mbedtls_free(encode_buf); 630 return 0; 631 } 632 #endif /* MBEDTLS_PEM_WRITE_C */ 633 #endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ 634