blob: 8521483941fb57ecef757c80274b08c81ec02a91 [file] [log] [blame]
Paul Bakkerf1f21fe2013-06-24 19:17:19 +02001/*
2 * PKCS#12 Personal Information Exchange Syntax
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * 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.
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020018 */
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
Gilles Peskinedb09ef62020-06-03 01:43:33 +020026#include "common.h"
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020027
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020028#if defined(MBEDTLS_PKCS12_C)
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020029
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000030#include "mbedtls/pkcs12.h"
31#include "mbedtls/asn1.h"
32#include "mbedtls/cipher.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050033#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000034#include "mbedtls/error.h"
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020035
Rich Evans00ab4702015-02-06 13:43:58 +000036#include <string.h>
37
Andrzej Kurek8a045ce2022-12-23 11:00:06 -050038#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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020045#if defined(MBEDTLS_DES_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/des.h"
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020047#endif
48
Andrzej Kurek7bd12c52022-08-24 10:47:10 -040049#include "hash_info.h"
50#include "mbedtls/psa_util.h"
51
Hanno Becker8a89f9f2018-10-12 10:46:32 +010052#if defined(MBEDTLS_ASN1_PARSE_C)
53
Gilles Peskine449bd832023-01-11 14:50:10 +010054static int pkcs12_parse_pbe_params(mbedtls_asn1_buf *params,
55 mbedtls_asn1_buf *salt, int *iterations)
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020056{
Janos Follath24eed8d2019-11-22 13:21:35 +000057 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakkerf8d018a2013-06-29 12:16:17 +020058 unsigned char **p = &params->p;
59 const unsigned char *end = params->p + params->len;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020060
61 /*
62 * pkcs-12PbeParams ::= SEQUENCE {
63 * salt OCTET STRING,
64 * iterations INTEGER
65 * }
66 *
67 */
Gilles Peskine449bd832023-01-11 14:50:10 +010068 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 }
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020072
Gilles Peskine449bd832023-01-11 14:50:10 +010073 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 }
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020076
77 salt->p = *p;
78 *p += salt->len;
79
Gilles Peskine449bd832023-01-11 14:50:10 +010080 if ((ret = mbedtls_asn1_get_int(p, end, iterations)) != 0) {
81 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret);
82 }
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020083
Gilles Peskine449bd832023-01-11 14:50:10 +010084 if (*p != end) {
85 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT,
86 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
87 }
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020088
Gilles Peskine449bd832023-01-11 14:50:10 +010089 return 0;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020090}
91
Manuel Pégourié-Gonnardd02a1da2015-09-28 18:34:48 +020092#define PKCS12_MAX_PWDLEN 128
93
Gilles Peskine449bd832023-01-11 14:50:10 +010094static 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)
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020098{
Nicholas Wilson409401c2016-04-13 11:48:25 +010099 int ret, iterations = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100 mbedtls_asn1_buf salt;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200101 size_t i;
Manuel Pégourié-Gonnardd02a1da2015-09-28 18:34:48 +0200102 unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2];
103
Gilles Peskine449bd832023-01-11 14:50:10 +0100104 if (pwdlen > PKCS12_MAX_PWDLEN) {
105 return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;
106 }
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200107
Gilles Peskine449bd832023-01-11 14:50:10 +0100108 memset(&salt, 0, sizeof(mbedtls_asn1_buf));
109 memset(&unipwd, 0, sizeof(unipwd));
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200110
Gilles Peskine449bd832023-01-11 14:50:10 +0100111 if ((ret = pkcs12_parse_pbe_params(pbe_params, &salt,
112 &iterations)) != 0) {
113 return ret;
114 }
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200115
Gilles Peskine449bd832023-01-11 14:50:10 +0100116 for (i = 0; i < pwdlen; i++) {
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200117 unipwd[i * 2 + 1] = pwd[i];
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200118 }
119
Gilles Peskine449bd832023-01-11 14:50:10 +0100120 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;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200124 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100125
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;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200136}
137
Manuel Pégourié-Gonnardd02a1da2015-09-28 18:34:48 +0200138#undef PKCS12_MAX_PWDLEN
139
Gilles Peskine449bd832023-01-11 14:50:10 +0100140int 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)
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200145{
Paul Bakker38b50d72013-06-24 19:33:27 +0200146 int ret, keylen = 0;
147 unsigned char key[32];
148 unsigned char iv[16];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149 const mbedtls_cipher_info_t *cipher_info;
150 mbedtls_cipher_context_t cipher_ctx;
Paul Bakker38b50d72013-06-24 19:33:27 +0200151 size_t olen = 0;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200152
Gilles Peskine449bd832023-01-11 14:50:10 +0100153 if (pwd == NULL && pwdlen != 0) {
154 return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;
155 }
Paul Elliott853c0da2021-11-11 19:00:38 +0000156
Gilles Peskine449bd832023-01-11 14:50:10 +0100157 cipher_info = mbedtls_cipher_info_from_type(cipher_type);
158 if (cipher_info == NULL) {
159 return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE;
160 }
Paul Bakker38b50d72013-06-24 19:33:27 +0200161
Manuel Pégourié-Gonnard898e0aa2015-06-18 15:28:12 +0200162 keylen = cipher_info->key_bitlen / 8;
Paul Bakker38b50d72013-06-24 19:33:27 +0200163
Gilles Peskine449bd832023-01-11 14:50:10 +0100164 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;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200168 }
169
Gilles Peskine449bd832023-01-11 14:50:10 +0100170 mbedtls_cipher_init(&cipher_ctx);
Paul Bakker84bbeb52014-07-01 14:53:22 +0200171
Gilles Peskine449bd832023-01-11 14:50:10 +0100172 if ((ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0) {
Paul Bakkerbd552442013-07-03 14:44:40 +0200173 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200174 }
175
Gilles Peskine449bd832023-01-11 14:50:10 +0100176 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) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200196 ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH;
Gilles Peskine449bd832023-01-11 14:50:10 +0100197 }
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200198
Paul Bakkerbd552442013-07-03 14:44:40 +0200199exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100200 mbedtls_platform_zeroize(key, sizeof(key));
201 mbedtls_platform_zeroize(iv, sizeof(iv));
202 mbedtls_cipher_free(&cipher_ctx);
Paul Bakkerbd552442013-07-03 14:44:40 +0200203
Gilles Peskine449bd832023-01-11 14:50:10 +0100204 return ret;
Paul Bakker531e2942013-06-24 19:23:12 +0200205}
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200206
Hanno Becker8a89f9f2018-10-12 10:46:32 +0100207#endif /* MBEDTLS_ASN1_PARSE_C */
208
Gilles Peskine449bd832023-01-11 14:50:10 +0100209static void pkcs12_fill_buffer(unsigned char *data, size_t data_len,
210 const unsigned char *filler, size_t fill_len)
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200211{
212 unsigned char *p = data;
213 size_t use_len;
214
Gilles Peskine449bd832023-01-11 14:50:10 +0100215 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);
Paul Elliott853c0da2021-11-11 19:00:38 +0000219 p += use_len;
220 data_len -= use_len;
221 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100222 } else {
Paul Elliott7298bef2021-12-02 17:51:34 +0000223 /* 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 }
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200229}
230
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400231
Gilles Peskine449bd832023-01-11 14:50:10 +0100232static 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)
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400236{
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;
Gilles Peskine449bd832023-01-11 14:50:10 +0100242 md_info = mbedtls_md_info_from_type(md_type);
243 if (md_info == NULL) {
244 return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE;
245 }
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400246
Gilles Peskine449bd832023-01-11 14:50:10 +0100247 mbedtls_md_init(&md_ctx);
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400248
Gilles Peskine449bd832023-01-11 14:50:10 +0100249 if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) {
250 return ret;
251 }
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400252 // Calculate hash( diversifier || salt_block || pwd_block )
Gilles Peskine449bd832023-01-11 14:50:10 +0100253 if ((ret = mbedtls_md_starts(&md_ctx)) != 0) {
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400254 goto exit;
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400255 }
256
Gilles Peskine449bd832023-01-11 14:50:10 +0100257 if ((ret = mbedtls_md_update(&md_ctx, diversifier, v)) != 0) {
258 goto exit;
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400259 }
260
Gilles Peskine449bd832023-01-11 14:50:10 +0100261 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) {
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400274 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100275 }
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400276
277 // Perform remaining ( iterations - 1 ) recursive hash calculations
Gilles Peskine449bd832023-01-11 14:50:10 +0100278 for (i = 1; i < (size_t) iterations; i++) {
279 if ((ret = mbedtls_md(md_info, hash_output, hlen, hash_output))
280 != 0) {
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400281 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100282 }
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400283 }
284
285exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100286 mbedtls_md_free(&md_ctx);
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400287 return ret;
288#else
289 psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
Gilles Peskine449bd832023-01-11 14:50:10 +0100290 psa_algorithm_t alg = mbedtls_psa_translate_md(md_type);
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400291 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
292 psa_status_t status_abort = PSA_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100293 size_t i, out_len, out_size = PSA_HASH_LENGTH(alg);
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400294
Gilles Peskine449bd832023-01-11 14:50:10 +0100295 if (alg == PSA_ALG_NONE) {
296 return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE;
297 }
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400298
Gilles Peskine449bd832023-01-11 14:50:10 +0100299 if ((status = psa_hash_setup(&op, alg)) != PSA_SUCCESS) {
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400300 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100301 }
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400302
303 // Calculate hash( diversifier || salt_block || pwd_block )
Gilles Peskine449bd832023-01-11 14:50:10 +0100304 if ((status = psa_hash_update(&op, diversifier, v)) != PSA_SUCCESS) {
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400305 goto exit;
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400306 }
307
Gilles Peskine449bd832023-01-11 14:50:10 +0100308 if (use_salt != 0) {
309 if ((status = psa_hash_update(&op, salt_block, v)) != PSA_SUCCESS) {
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400310 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100311 }
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400312 }
313
Gilles Peskine449bd832023-01-11 14:50:10 +0100314 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) {
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400322 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100323 }
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400324
325 // Perform remaining ( iterations - 1 ) recursive hash calculations
Gilles Peskine449bd832023-01-11 14:50:10 +0100326 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) {
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400329 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100330 }
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400331 }
332
333exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100334 status_abort = psa_hash_abort(&op);
335 if (status == PSA_SUCCESS) {
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400336 status = status_abort;
Gilles Peskine449bd832023-01-11 14:50:10 +0100337 }
Andrzej Kurek8a045ce2022-12-23 11:00:06 -0500338 return PSA_TO_MBEDTLS_ERR(status);
Andrzej Kurek7bd12c52022-08-24 10:47:10 -0400339#endif /* !MBEDTLS_MD_C */
340}
341
342
Gilles Peskine449bd832023-01-11 14:50:10 +0100343int 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)
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200347{
Janos Follath24eed8d2019-11-22 13:21:35 +0000348 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200349 unsigned int j;
350
351 unsigned char diversifier[128];
Gilles Peskine449bd832023-01-11 14:50:10 +0100352 unsigned char salt_block[128], pwd_block[128], hash_block[128] = { 0 };
Przemek Stekiel40afdd22022-09-06 13:08:28 +0200353 unsigned char hash_output[MBEDTLS_HASH_MAX_SIZE];
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200354 unsigned char *p;
355 unsigned char c;
Paul Elliott4086bdb2021-11-18 14:02:21 +0000356 int use_password = 0;
357 int use_salt = 0;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200358
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200359 size_t hlen, use_len, v, i;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200360
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200361 // This version only allows max of 64 bytes of password or salt
Gilles Peskine449bd832023-01-11 14:50:10 +0100362 if (datalen > 128 || pwdlen > 64 || saltlen > 64) {
363 return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;
Paul Elliott4086bdb2021-11-18 14:02:21 +0000364 }
365
Gilles Peskine449bd832023-01-11 14:50:10 +0100366 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);
Paul Elliott4086bdb2021-11-18 14:02:21 +0000393 }
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200394
395 p = data;
Gilles Peskine449bd832023-01-11 14:50:10 +0100396 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) {
Paul Bakkerbd552442013-07-03 14:44:40 +0200400 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200401 }
402
Gilles Peskine449bd832023-01-11 14:50:10 +0100403 use_len = (datalen > hlen) ? hlen : datalen;
404 memcpy(p, hash_output, use_len);
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200405 datalen -= use_len;
406 p += use_len;
407
Gilles Peskine449bd832023-01-11 14:50:10 +0100408 if (datalen == 0) {
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200409 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100410 }
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200411
412 // Concatenating copies of hash_output into hash_block (B)
Gilles Peskine449bd832023-01-11 14:50:10 +0100413 pkcs12_fill_buffer(hash_block, v, hash_output, hlen);
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200414
415 // B += 1
Gilles Peskine449bd832023-01-11 14:50:10 +0100416 for (i = v; i > 0; i--) {
417 if (++hash_block[i - 1] != 0) {
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200418 break;
Paul Elliott4086bdb2021-11-18 14:02:21 +0000419 }
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200420 }
421
Gilles Peskine449bd832023-01-11 14:50:10 +0100422 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) {
Paul Elliott4086bdb2021-11-18 14:02:21 +0000433 // pwd_block += B
434 c = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100435 for (i = v; i > 0; i--) {
Paul Elliott4086bdb2021-11-18 14:02:21 +0000436 j = pwd_block[i - 1] + hash_block[i - 1] + c;
Gilles Peskine449bd832023-01-11 14:50:10 +0100437 c = MBEDTLS_BYTE_1(j);
438 pwd_block[i - 1] = MBEDTLS_BYTE_0(j);
Paul Elliott4086bdb2021-11-18 14:02:21 +0000439 }
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200440 }
441 }
442
Paul Bakkerbd552442013-07-03 14:44:40 +0200443 ret = 0;
444
445exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100446 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));
Paul Bakker91c301a2014-06-18 13:59:38 +0200450
Gilles Peskine449bd832023-01-11 14:50:10 +0100451 return ret;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200452}
453
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454#endif /* MBEDTLS_PKCS12_C */