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)
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 */
45 #if defined(MBEDTLS_PLATFORM_C)
46 #include "mbedtls/platform.h"
49 #define mbedtls_printf printf
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 {
67 * iterationCount INTEGER,
68 * keyLength INTEGER OPTIONAL
69 * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1
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
);
80 if ((ret
= mbedtls_asn1_get_int(&p
, end
, iterations
)) != 0)
81 return (MBEDTLS_ERR_PKCS5_INVALID_FORMAT
+ ret
);
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
);
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
);
101 return (MBEDTLS_ERR_PKCS5_INVALID_FORMAT
+
102 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
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];
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
;
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
,
152 md_info
= mbedtls_md_info_from_type(md_type
);
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)
187 if ((ret
= mbedtls_pkcs5_pbkdf2_hmac(&md_ctx
, pwd
, pwdlen
, salt
.p
, salt
.len
,
188 iterations
, keylen
, key
)) != 0) {
192 if ((ret
= mbedtls_cipher_setup(&cipher_ctx
, cipher_info
)) != 0)
195 if ((ret
= mbedtls_cipher_setkey(&cipher_ctx
, key
, 8 * keylen
,
196 (mbedtls_operation_t
) mode
)) != 0)
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
;
204 mbedtls_md_free(&md_ctx
);
205 mbedtls_cipher_free(&cipher_ctx
);
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
;
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
);
223 unsigned char *out_p
= output
;
224 unsigned char counter
[4];
226 memset(counter
, 0, 4);
229 #if UINT_MAX > 0xFFFFFFFF
230 if (iteration_count
> 0xFFFFFFFF)
231 return (MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA
);
234 if ((ret
= mbedtls_md_hmac_starts(ctx
, password
, plen
)) != 0)
237 // U1 ends up in work
239 if ((ret
= mbedtls_md_hmac_update(ctx
, salt
, slen
)) != 0)
242 if ((ret
= mbedtls_md_hmac_update(ctx
, counter
, 4)) != 0)
245 if ((ret
= mbedtls_md_hmac_finish(ctx
, work
)) != 0)
248 if ((ret
= mbedtls_md_hmac_reset(ctx
)) != 0)
251 memcpy(md1
, work
, md_size
);
253 for (i
= 1; i
< iteration_count
; i
++) {
256 if ((ret
= mbedtls_md_hmac_update(ctx
, md1
, md_size
)) != 0)
259 if ((ret
= mbedtls_md_hmac_finish(ctx
, md1
)) != 0)
262 if ((ret
= mbedtls_md_hmac_reset(ctx
)) != 0)
267 for (j
= 0; j
< md_size
; 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
;
277 for (i
= 4; i
> 0; i
--)
278 if (++counter
[i
- 1] != 0)
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
);
290 #if defined(MBEDTLS_SELF_TEST)
292 #if !defined(MBEDTLS_SHA1_C)
293 int mbedtls_pkcs5_self_test(int verbose
) {
295 mbedtls_printf(" PBKDF2 (SHA1): skipped\n\n");
303 static const size_t plen_test_data
[MAX_TESTS
] =
306 static const unsigned char password_test_data
[MAX_TESTS
][32] = {
310 "passwordPASSWORDpassword",
314 static const size_t slen_test_data
[MAX_TESTS
] =
317 static const unsigned char salt_test_data
[MAX_TESTS
][40] = {
321 "saltSALTsaltSALTsaltSALTsaltSALTsalt",
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,
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
;
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
) {
373 if ((ret
= mbedtls_md_setup(&sha1_ctx
, info_sha1
, 1)) != 0) {
378 for (i
= 0; i
< MAX_TESTS
; i
++) {
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
);
387 memcmp(result_key_test_data
[i
], key
, key_len_test_data
[i
]) != 0) {
389 mbedtls_printf("failed\n");
396 mbedtls_printf("passed\n");
400 mbedtls_printf("\n");
403 mbedtls_md_free(&sha1_ctx
);
407 #endif /* MBEDTLS_SHA1_C */
409 #endif /* MBEDTLS_SELF_TEST */
411 #endif /* MBEDTLS_PKCS5_C */