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