1 /**
2 * \file pkcs5.c
3 *
4 * \brief PKCS#5 functions
5 *
6 * \author Mathias Olsson <mathias@kompetensum.com>
7 *
8 * Copyright The Mbed TLS Contributors
9 * SPDX-License-Identifier: Apache-2.0
10 *
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
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
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.
22 */
23 /*
24 * PKCS#5 includes PBKDF2 and more
25 *
26 * http://tools.ietf.org/html/rfc2898 (Specification)
27 * http://tools.ietf.org/html/rfc6070 (Test vectors)
28 */
29
30 #include "common.h"
31
32 #if defined(MBEDTLS_PKCS5_C)
33
34 #include "mbedtls/pkcs5.h"
35 #include "mbedtls/error.h"
36
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 */
42
43 #include <string.h>
44
45 #include "mbedtls/platform.h"
46
47 #include "hash_info.h"
48 #include "mbedtls/psa_util.h"
49
50 #if defined(MBEDTLS_ASN1_PARSE_C)
pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf * params,mbedtls_asn1_buf * salt,int * iterations,int * keylen,mbedtls_md_type_t * md_type)51 static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params,
52 mbedtls_asn1_buf *salt, int *iterations,
53 int *keylen, mbedtls_md_type_t *md_type )
54 {
55 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
56 mbedtls_asn1_buf prf_alg_oid;
57 unsigned char *p = params->p;
58 const unsigned char *end = params->p + params->len;
59
60 if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
61 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
62 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
63 /*
64 * PBKDF2-params ::= SEQUENCE {
65 * salt OCTET STRING,
66 * iterationCount INTEGER,
67 * keyLength INTEGER OPTIONAL
68 * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1
69 * }
70 *
71 */
72 if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len,
73 MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
74 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
75
76 salt->p = p;
77 p += salt->len;
78
79 if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 )
80 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
81
82 if( p == end )
83 return( 0 );
84
85 if( ( ret = mbedtls_asn1_get_int( &p, end, keylen ) ) != 0 )
86 {
87 if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
88 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
89 }
90
91 if( p == end )
92 return( 0 );
93
94 if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 )
95 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
96
97 if( mbedtls_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 )
98 return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
99
100 if( p != end )
101 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
102 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
103
104 return( 0 );
105 }
106
mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf * pbe_params,int mode,const unsigned char * pwd,size_t pwdlen,const unsigned char * data,size_t datalen,unsigned char * output)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 {
112 int ret, iterations = 0, keylen = 0;
113 unsigned char *p, *end;
114 mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params;
115 mbedtls_asn1_buf salt;
116 mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;
117 unsigned char key[32], iv[32];
118 size_t olen = 0;
119 const mbedtls_cipher_info_t *cipher_info;
120 mbedtls_cipher_type_t cipher_alg;
121 mbedtls_cipher_context_t cipher_ctx;
122
123 p = pbe_params->p;
124 end = p + pbe_params->len;
125
126 /*
127 * PBES2-params ::= SEQUENCE {
128 * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
129 * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}}
130 * }
131 */
132 if( pbe_params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
133 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
134 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
135
136 if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid,
137 &kdf_alg_params ) ) != 0 )
138 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
139
140 // Only PBKDF2 supported at the moment
141 //
142 if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid ) != 0 )
143 return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
144
145 if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params,
146 &salt, &iterations, &keylen,
147 &md_type ) ) != 0 )
148 {
149 return( ret );
150 }
151
152 if( ( ret = mbedtls_asn1_get_alg( &p, end, &enc_scheme_oid,
153 &enc_scheme_params ) ) != 0 )
154 {
155 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
156 }
157
158 if( mbedtls_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 )
159 return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
160
161 cipher_info = mbedtls_cipher_info_from_type( cipher_alg );
162 if( cipher_info == NULL )
163 return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
164
165 /*
166 * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored
167 * since it is optional and we don't know if it was set or not
168 */
169 keylen = cipher_info->key_bitlen / 8;
170
171 if( enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING ||
172 enc_scheme_params.len != cipher_info->iv_size )
173 {
174 return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT );
175 }
176
177 mbedtls_cipher_init( &cipher_ctx );
178
179 memcpy( iv, enc_scheme_params.p, enc_scheme_params.len );
180
181 if( ( ret = mbedtls_pkcs5_pbkdf2_hmac_ext( md_type, pwd, pwdlen, salt.p,
182 salt.len, iterations, keylen,
183 key ) ) != 0 )
184 {
185 goto exit;
186 }
187
188 if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 )
189 goto exit;
190
191 if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen,
192 (mbedtls_operation_t) mode ) ) != 0 )
193 goto exit;
194
195 if( ( ret = mbedtls_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len,
196 data, datalen, output, &olen ) ) != 0 )
197 ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH;
198
199 exit:
200 mbedtls_cipher_free( &cipher_ctx );
201
202 return( ret );
203 }
204 #endif /* MBEDTLS_ASN1_PARSE_C */
205
206 #if defined(MBEDTLS_MD_C)
pkcs5_pbkdf2_hmac(mbedtls_md_context_t * ctx,const unsigned char * password,size_t plen,const unsigned char * salt,size_t slen,unsigned int iteration_count,uint32_t key_length,unsigned char * output)207 static int pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx,
208 const unsigned char *password,
209 size_t plen, const unsigned char *salt, size_t slen,
210 unsigned int iteration_count,
211 uint32_t key_length, unsigned char *output )
212 {
213 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
214 int j;
215 unsigned int i;
216 unsigned char md1[MBEDTLS_MD_MAX_SIZE];
217 unsigned char work[MBEDTLS_MD_MAX_SIZE];
218 unsigned char md_size = mbedtls_md_get_size( ctx->md_info );
219 size_t use_len;
220 unsigned char *out_p = output;
221 unsigned char counter[4];
222
223 memset( counter, 0, 4 );
224 counter[3] = 1;
225
226 #if UINT_MAX > 0xFFFFFFFF
227 if( iteration_count > 0xFFFFFFFF )
228 return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA );
229 #endif
230
231 if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 )
232 return( ret );
233 while( key_length )
234 {
235 // U1 ends up in work
236 //
237 if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 )
238 goto cleanup;
239
240 if( ( ret = mbedtls_md_hmac_update( ctx, counter, 4 ) ) != 0 )
241 goto cleanup;
242
243 if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 )
244 goto cleanup;
245
246 if( ( ret = mbedtls_md_hmac_reset( ctx ) ) != 0 )
247 goto cleanup;
248
249 memcpy( md1, work, md_size );
250
251 for( i = 1; i < iteration_count; i++ )
252 {
253 // U2 ends up in md1
254 //
255 if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 )
256 goto cleanup;
257
258 if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 )
259 goto cleanup;
260
261 if( ( ret = mbedtls_md_hmac_reset( ctx ) ) != 0 )
262 goto cleanup;
263
264 // U1 xor U2
265 //
266 for( j = 0; j < md_size; j++ )
267 work[j] ^= md1[j];
268 }
269
270 use_len = ( key_length < md_size ) ? key_length : md_size;
271 memcpy( out_p, work, use_len );
272
273 key_length -= (uint32_t) use_len;
274 out_p += use_len;
275
276 for( i = 4; i > 0; i-- )
277 if( ++counter[i - 1] != 0 )
278 break;
279 }
280
281 cleanup:
282 /* Zeroise buffers to clear sensitive data from memory. */
283 mbedtls_platform_zeroize( work, MBEDTLS_MD_MAX_SIZE );
284 mbedtls_platform_zeroize( md1, MBEDTLS_MD_MAX_SIZE );
285
286 return( ret );
287 }
288
289 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t * ctx,const unsigned char * password,size_t plen,const unsigned char * salt,size_t slen,unsigned int iteration_count,uint32_t key_length,unsigned char * output)290 int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx,
291 const unsigned char *password,
292 size_t plen, const unsigned char *salt, size_t slen,
293 unsigned int iteration_count,
294 uint32_t key_length, unsigned char *output )
295 {
296 return( pkcs5_pbkdf2_hmac( ctx, password, plen, salt, slen, iteration_count,
297 key_length, output ) );
298 }
299 #endif
300 #endif /* MBEDTLS_MD_C */
301
mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_alg,const unsigned char * password,size_t plen,const unsigned char * salt,size_t slen,unsigned int iteration_count,uint32_t key_length,unsigned char * output)302 int mbedtls_pkcs5_pbkdf2_hmac_ext( mbedtls_md_type_t md_alg,
303 const unsigned char *password,
304 size_t plen, const unsigned char *salt, size_t slen,
305 unsigned int iteration_count,
306 uint32_t key_length, unsigned char *output )
307 {
308 #if defined(MBEDTLS_MD_C)
309 mbedtls_md_context_t md_ctx;
310 const mbedtls_md_info_t *md_info = NULL;
311 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
312
313 md_info = mbedtls_md_info_from_type( md_alg );
314 if( md_info == NULL )
315 return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
316
317 mbedtls_md_init( &md_ctx );
318
319 if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 )
320 goto exit;
321 ret = pkcs5_pbkdf2_hmac( &md_ctx, password, plen, salt, slen,
322 iteration_count, key_length, output );
323 exit:
324 mbedtls_md_free( &md_ctx );
325 return( ret );
326 #else
327 int j;
328 unsigned int i;
329 unsigned char md1[PSA_HASH_MAX_SIZE];
330 unsigned char work[PSA_HASH_MAX_SIZE];
331 const unsigned char md_size = mbedtls_hash_info_get_size( md_alg );
332 psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
333
334 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
335 psa_status_t status_destruction = PSA_ERROR_CORRUPTION_DETECTED;
336 size_t use_len, out_len;
337 unsigned char *out_p = output;
338 unsigned char counter[4];
339 mbedtls_svc_key_id_t psa_hmac_key = MBEDTLS_SVC_KEY_ID_INIT;
340 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
341 const psa_algorithm_t alg = PSA_ALG_HMAC( mbedtls_hash_info_psa_from_md( md_alg ) );
342 const size_t out_size = PSA_MAC_LENGTH( PSA_KEY_TYPE_HMAC, 0, alg );
343
344 memset( counter, 0, sizeof( counter ) );
345 counter[3] = 1;
346
347 psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_MESSAGE );
348 psa_set_key_algorithm( &attributes, alg );
349 psa_set_key_type( &attributes, PSA_KEY_TYPE_HMAC );
350
351 if( key_length == 0 )
352 return 0;
353 if( ( status = psa_import_key( &attributes,
354 password, plen,
355 &psa_hmac_key ) ) != PSA_SUCCESS )
356 {
357 return MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA;
358 }
359
360 #if UINT_MAX > 0xFFFFFFFF
361 if( iteration_count > 0xFFFFFFFF )
362 return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA );
363 #endif
364
365 while( key_length )
366 {
367 status = psa_mac_sign_setup( &operation, psa_hmac_key,
368 PSA_ALG_HMAC( alg ) );
369 if( status != PSA_SUCCESS )
370 goto cleanup;
371 // U1 ends up in work
372 if( ( status = psa_mac_update( &operation, salt, slen ) ) != PSA_SUCCESS )
373 goto cleanup;
374
375 if( ( status = psa_mac_update( &operation, counter, sizeof( counter ) ) ) != PSA_SUCCESS )
376 goto cleanup;
377
378 if( ( status = psa_mac_sign_finish( &operation, work, out_size, &out_len ) )
379 != PSA_SUCCESS )
380 goto cleanup;
381
382 memcpy( md1, work, out_len );
383
384 for( i = 1; i < iteration_count; i++ )
385 {
386 // U2 ends up in md1
387 //
388 status = psa_mac_sign_setup( &operation, psa_hmac_key,
389 PSA_ALG_HMAC( alg ) );
390 if( status != PSA_SUCCESS )
391 goto cleanup;
392 if( ( status = psa_mac_update( &operation, md1, md_size ) ) != PSA_SUCCESS )
393 goto cleanup;
394 if( ( status = psa_mac_sign_finish( &operation, md1, out_size, &out_len ) ) != PSA_SUCCESS )
395 goto cleanup;
396
397 // U1 xor U2
398 //
399 for( j = 0; j < md_size; j++ )
400 work[j] ^= md1[j];
401 }
402
403 use_len = ( key_length < md_size ) ? key_length : md_size;
404 memcpy( out_p, work, use_len );
405
406 key_length -= (uint32_t) use_len;
407 out_p += use_len;
408
409 for( i = 4; i > 0; i-- )
410 if( ++counter[i - 1] != 0 )
411 break;
412 }
413
414 cleanup:
415 /* Zeroise buffers to clear sensitive data from memory. */
416 mbedtls_platform_zeroize( work, PSA_HASH_MAX_SIZE );
417 mbedtls_platform_zeroize( md1, PSA_HASH_MAX_SIZE );
418 status_destruction = psa_destroy_key( psa_hmac_key );
419 if( status == PSA_SUCCESS && status_destruction != PSA_SUCCESS )
420 status = status_destruction;
421 status_destruction = psa_mac_abort( &operation );
422 if( status == PSA_SUCCESS && status_destruction != PSA_SUCCESS )
423 status = status_destruction;
424
425 return( mbedtls_md_error_from_psa( status ) );
426 #endif /* !MBEDTLS_MD_C */
427 }
428
429 #if defined(MBEDTLS_SELF_TEST)
430
431 #if !defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA)
mbedtls_pkcs5_self_test(int verbose)432 int mbedtls_pkcs5_self_test( int verbose )
433 {
434 if( verbose != 0 )
435 mbedtls_printf( " PBKDF2 (SHA1): skipped\n\n" );
436
437 return( 0 );
438 }
439 #else
440
441 #define MAX_TESTS 6
442
443 static const size_t plen_test_data[MAX_TESTS] =
444 { 8, 8, 8, 24, 9 };
445
446 static const unsigned char password_test_data[MAX_TESTS][32] =
447 {
448 "password",
449 "password",
450 "password",
451 "passwordPASSWORDpassword",
452 "pass\0word",
453 };
454
455 static const size_t slen_test_data[MAX_TESTS] =
456 { 4, 4, 4, 36, 5 };
457
458 static const unsigned char salt_test_data[MAX_TESTS][40] =
459 {
460 "salt",
461 "salt",
462 "salt",
463 "saltSALTsaltSALTsaltSALTsaltSALTsalt",
464 "sa\0lt",
465 };
466
467 static const uint32_t it_cnt_test_data[MAX_TESTS] =
468 { 1, 2, 4096, 4096, 4096 };
469
470 static const uint32_t key_len_test_data[MAX_TESTS] =
471 { 20, 20, 20, 25, 16 };
472
473 static const unsigned char result_key_test_data[MAX_TESTS][32] =
474 {
475 { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
476 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
477 0x2f, 0xe0, 0x37, 0xa6 },
478 { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
479 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
480 0xd8, 0xde, 0x89, 0x57 },
481 { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
482 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
483 0x65, 0xa4, 0x29, 0xc1 },
484 { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
485 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
486 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
487 0x38 },
488 { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
489 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 },
490 };
491
mbedtls_pkcs5_self_test(int verbose)492 int mbedtls_pkcs5_self_test( int verbose )
493 {
494 int ret, i;
495 unsigned char key[64];
496
497 for( i = 0; i < MAX_TESTS; i++ )
498 {
499 if( verbose != 0 )
500 mbedtls_printf( " PBKDF2 (SHA1) #%d: ", i );
501
502 ret = mbedtls_pkcs5_pbkdf2_hmac_ext( MBEDTLS_MD_SHA1, password_test_data[i],
503 plen_test_data[i], salt_test_data[i],
504 slen_test_data[i], it_cnt_test_data[i],
505 key_len_test_data[i], key );
506 if( ret != 0 ||
507 memcmp( result_key_test_data[i], key, key_len_test_data[i] ) != 0 )
508 {
509 if( verbose != 0 )
510 mbedtls_printf( "failed\n" );
511
512 ret = 1;
513 goto exit;
514 }
515
516 if( verbose != 0 )
517 mbedtls_printf( "passed\n" );
518 }
519
520 if( verbose != 0 )
521 mbedtls_printf( "\n" );
522
523 exit:
524 return( ret );
525 }
526 #endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA */
527
528 #endif /* MBEDTLS_SELF_TEST */
529
530 #endif /* MBEDTLS_PKCS5_C */
531