update atrs list
[RRG-proxmark3.git] / common / mbedtls / pkcs5.c
blob72d06d05d955a2738666e9dbc7dfe648adc8ce68
1 /**
2 * \file pkcs5.c
4 * \brief PKCS#5 functions
6 * \author Mathias Olsson <mathias@kompetensum.com>
8 * Copyright The Mbed TLS Contributors
9 * SPDX-License-Identifier: Apache-2.0
11 * Licensed under the Apache License, Version 2.0 (the "License"); you may
12 * not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
15 * http://www.apache.org/licenses/LICENSE-2.0
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
19 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
24 * PKCS#5 includes PBKDF2 and more
26 * http://tools.ietf.org/html/rfc2898 (Specification)
27 * http://tools.ietf.org/html/rfc6070 (Test vectors)
30 #include "common.h"
32 #if defined(MBEDTLS_PKCS5_C)
34 #include "mbedtls/pkcs5.h"
35 #include "mbedtls/error.h"
37 #if defined(MBEDTLS_ASN1_PARSE_C)
38 #include "mbedtls/asn1.h"
39 #include "mbedtls/cipher.h"
40 #include "mbedtls/oid.h"
41 #endif /* MBEDTLS_ASN1_PARSE_C */
43 #include <string.h>
45 #if defined(MBEDTLS_PLATFORM_C)
46 #include "mbedtls/platform.h"
47 #else
48 #include <stdio.h>
49 #define mbedtls_printf printf
50 #endif
52 #if defined(MBEDTLS_ASN1_PARSE_C)
53 static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params,
54 mbedtls_asn1_buf *salt, int *iterations,
55 int *keylen, mbedtls_md_type_t *md_type) {
56 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
57 mbedtls_asn1_buf prf_alg_oid;
58 unsigned char *p = params->p;
59 const unsigned char *end = params->p + params->len;
61 if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE))
62 return (MBEDTLS_ERR_PKCS5_INVALID_FORMAT +
63 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
65 * PBKDF2-params ::= SEQUENCE {
66 * salt OCTET STRING,
67 * iterationCount INTEGER,
68 * keyLength INTEGER OPTIONAL
69 * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1
70 * }
73 if ((ret = mbedtls_asn1_get_tag(&p, end, &salt->len,
74 MBEDTLS_ASN1_OCTET_STRING)) != 0)
75 return (MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret);
77 salt->p = p;
78 p += salt->len;
80 if ((ret = mbedtls_asn1_get_int(&p, end, iterations)) != 0)
81 return (MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret);
83 if (p == end)
84 return (0);
86 if ((ret = mbedtls_asn1_get_int(&p, end, keylen)) != 0) {
87 if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)
88 return (MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret);
91 if (p == end)
92 return (0);
94 if ((ret = mbedtls_asn1_get_alg_null(&p, end, &prf_alg_oid)) != 0)
95 return (MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret);
97 if (mbedtls_oid_get_md_hmac(&prf_alg_oid, md_type) != 0)
98 return (MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE);
100 if (p != end)
101 return (MBEDTLS_ERR_PKCS5_INVALID_FORMAT +
102 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
104 return (0);
107 int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode,
108 const unsigned char *pwd, size_t pwdlen,
109 const unsigned char *data, size_t datalen,
110 unsigned char *output) {
111 int ret, iterations = 0, keylen = 0;
112 unsigned char *p, *end;
113 mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params;
114 mbedtls_asn1_buf salt;
115 mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;
116 unsigned char key[32], iv[32];
117 size_t olen = 0;
118 const mbedtls_md_info_t *md_info;
119 const mbedtls_cipher_info_t *cipher_info;
120 mbedtls_md_context_t md_ctx;
121 mbedtls_cipher_type_t cipher_alg;
122 mbedtls_cipher_context_t cipher_ctx;
124 p = pbe_params->p;
125 end = p + pbe_params->len;
128 * PBES2-params ::= SEQUENCE {
129 * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
130 * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}}
133 if (pbe_params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE))
134 return (MBEDTLS_ERR_PKCS5_INVALID_FORMAT +
135 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
137 if ((ret = mbedtls_asn1_get_alg(&p, end, &kdf_alg_oid,
138 &kdf_alg_params)) != 0)
139 return (MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret);
141 // Only PBKDF2 supported at the moment
143 if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid) != 0)
144 return (MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE);
146 if ((ret = pkcs5_parse_pbkdf2_params(&kdf_alg_params,
147 &salt, &iterations, &keylen,
148 &md_type)) != 0) {
149 return (ret);
152 md_info = mbedtls_md_info_from_type(md_type);
153 if (md_info == NULL)
154 return (MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE);
156 if ((ret = mbedtls_asn1_get_alg(&p, end, &enc_scheme_oid,
157 &enc_scheme_params)) != 0) {
158 return (MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret);
161 if (mbedtls_oid_get_cipher_alg(&enc_scheme_oid, &cipher_alg) != 0)
162 return (MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE);
164 cipher_info = mbedtls_cipher_info_from_type(cipher_alg);
165 if (cipher_info == NULL)
166 return (MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE);
169 * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored
170 * since it is optional and we don't know if it was set or not
172 keylen = cipher_info->key_bitlen / 8;
174 if (enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING ||
175 enc_scheme_params.len != cipher_info->iv_size) {
176 return (MBEDTLS_ERR_PKCS5_INVALID_FORMAT);
179 mbedtls_md_init(&md_ctx);
180 mbedtls_cipher_init(&cipher_ctx);
182 memcpy(iv, enc_scheme_params.p, enc_scheme_params.len);
184 if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0)
185 goto exit;
187 if ((ret = mbedtls_pkcs5_pbkdf2_hmac(&md_ctx, pwd, pwdlen, salt.p, salt.len,
188 iterations, keylen, key)) != 0) {
189 goto exit;
192 if ((ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0)
193 goto exit;
195 if ((ret = mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen,
196 (mbedtls_operation_t) mode)) != 0)
197 goto exit;
199 if ((ret = mbedtls_cipher_crypt(&cipher_ctx, iv, enc_scheme_params.len,
200 data, datalen, output, &olen)) != 0)
201 ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH;
203 exit:
204 mbedtls_md_free(&md_ctx);
205 mbedtls_cipher_free(&cipher_ctx);
207 return (ret);
209 #endif /* MBEDTLS_ASN1_PARSE_C */
211 int mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx,
212 const unsigned char *password,
213 size_t plen, const unsigned char *salt, size_t slen,
214 unsigned int iteration_count,
215 uint32_t key_length, unsigned char *output) {
216 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
217 int j;
218 unsigned int i;
219 unsigned char md1[MBEDTLS_MD_MAX_SIZE];
220 unsigned char work[MBEDTLS_MD_MAX_SIZE];
221 unsigned char md_size = mbedtls_md_get_size(ctx->md_info);
222 size_t use_len;
223 unsigned char *out_p = output;
224 unsigned char counter[4];
226 memset(counter, 0, 4);
227 counter[3] = 1;
229 #if UINT_MAX > 0xFFFFFFFF
230 if (iteration_count > 0xFFFFFFFF)
231 return (MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA);
232 #endif
234 if ((ret = mbedtls_md_hmac_starts(ctx, password, plen)) != 0)
235 return (ret);
236 while (key_length) {
237 // U1 ends up in work
239 if ((ret = mbedtls_md_hmac_update(ctx, salt, slen)) != 0)
240 goto cleanup;
242 if ((ret = mbedtls_md_hmac_update(ctx, counter, 4)) != 0)
243 goto cleanup;
245 if ((ret = mbedtls_md_hmac_finish(ctx, work)) != 0)
246 goto cleanup;
248 if ((ret = mbedtls_md_hmac_reset(ctx)) != 0)
249 goto cleanup;
251 memcpy(md1, work, md_size);
253 for (i = 1; i < iteration_count; i++) {
254 // U2 ends up in md1
256 if ((ret = mbedtls_md_hmac_update(ctx, md1, md_size)) != 0)
257 goto cleanup;
259 if ((ret = mbedtls_md_hmac_finish(ctx, md1)) != 0)
260 goto cleanup;
262 if ((ret = mbedtls_md_hmac_reset(ctx)) != 0)
263 goto cleanup;
265 // U1 xor U2
267 for (j = 0; j < md_size; j++)
268 work[j] ^= md1[j];
271 use_len = (key_length < md_size) ? key_length : md_size;
272 memcpy(out_p, work, use_len);
274 key_length -= (uint32_t) use_len;
275 out_p += use_len;
277 for (i = 4; i > 0; i--)
278 if (++counter[i - 1] != 0)
279 break;
282 cleanup:
283 /* Zeroise buffers to clear sensitive data from memory. */
284 mbedtls_platform_zeroize(work, MBEDTLS_MD_MAX_SIZE);
285 mbedtls_platform_zeroize(md1, MBEDTLS_MD_MAX_SIZE);
287 return (ret);
290 #if defined(MBEDTLS_SELF_TEST)
292 #if !defined(MBEDTLS_SHA1_C)
293 int mbedtls_pkcs5_self_test(int verbose) {
294 if (verbose != 0)
295 mbedtls_printf(" PBKDF2 (SHA1): skipped\n\n");
297 return (0);
299 #else
301 #define MAX_TESTS 6
303 static const size_t plen_test_data[MAX_TESTS] =
304 { 8, 8, 8, 24, 9 };
306 static const unsigned char password_test_data[MAX_TESTS][32] = {
307 "password",
308 "password",
309 "password",
310 "passwordPASSWORDpassword",
311 "pass\0word",
314 static const size_t slen_test_data[MAX_TESTS] =
315 { 4, 4, 4, 36, 5 };
317 static const unsigned char salt_test_data[MAX_TESTS][40] = {
318 "salt",
319 "salt",
320 "salt",
321 "saltSALTsaltSALTsaltSALTsaltSALTsalt",
322 "sa\0lt",
325 static const uint32_t it_cnt_test_data[MAX_TESTS] =
326 { 1, 2, 4096, 4096, 4096 };
328 static const uint32_t key_len_test_data[MAX_TESTS] =
329 { 20, 20, 20, 25, 16 };
331 static const unsigned char result_key_test_data[MAX_TESTS][32] = {
333 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
334 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
335 0x2f, 0xe0, 0x37, 0xa6
338 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
339 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
340 0xd8, 0xde, 0x89, 0x57
343 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
344 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
345 0x65, 0xa4, 0x29, 0xc1
348 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
349 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
350 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
351 0x38
354 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
355 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3
359 int mbedtls_pkcs5_self_test(int verbose) {
360 mbedtls_md_context_t sha1_ctx;
361 const mbedtls_md_info_t *info_sha1;
362 int ret, i;
363 unsigned char key[64];
365 mbedtls_md_init(&sha1_ctx);
367 info_sha1 = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
368 if (info_sha1 == NULL) {
369 ret = 1;
370 goto exit;
373 if ((ret = mbedtls_md_setup(&sha1_ctx, info_sha1, 1)) != 0) {
374 ret = 1;
375 goto exit;
378 for (i = 0; i < MAX_TESTS; i++) {
379 if (verbose != 0)
380 mbedtls_printf(" PBKDF2 (SHA1) #%d: ", i);
382 ret = mbedtls_pkcs5_pbkdf2_hmac(&sha1_ctx, password_test_data[i],
383 plen_test_data[i], salt_test_data[i],
384 slen_test_data[i], it_cnt_test_data[i],
385 key_len_test_data[i], key);
386 if (ret != 0 ||
387 memcmp(result_key_test_data[i], key, key_len_test_data[i]) != 0) {
388 if (verbose != 0)
389 mbedtls_printf("failed\n");
391 ret = 1;
392 goto exit;
395 if (verbose != 0)
396 mbedtls_printf("passed\n");
399 if (verbose != 0)
400 mbedtls_printf("\n");
402 exit:
403 mbedtls_md_free(&sha1_ctx);
405 return (ret);
407 #endif /* MBEDTLS_SHA1_C */
409 #endif /* MBEDTLS_SELF_TEST */
411 #endif /* MBEDTLS_PKCS5_C */