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 = ¶ms->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