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