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