quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

pkcs12.c (13550B)


      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 
     36 static 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 = &params->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 
     76 static 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)
    123 int 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)
    132 int 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 
    150 int 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 
    235 exit:
    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 
    245 static 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 
    268 static 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 
    320 exit:
    321     mbedtls_md_free(&md_ctx);
    322     return ret;
    323 }
    324 
    325 
    326 int 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 
    428 exit:
    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 */