xref: /reactos/dll/3rdparty/mbedtls/pkcs5.c (revision 7eead935)
1 /**
2  * \file pkcs5.c
3  *
4  * \brief PKCS#5 functions
5  *
6  * \author Mathias Olsson <mathias@kompetensum.com>
7  *
8  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
9  *  SPDX-License-Identifier: GPL-2.0
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License along
22  *  with this program; if not, write to the Free Software Foundation, Inc.,
23  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  *
25  *  This file is part of mbed TLS (https://tls.mbed.org)
26  */
27 /*
28  * PKCS#5 includes PBKDF2 and more
29  *
30  * http://tools.ietf.org/html/rfc2898 (Specification)
31  * http://tools.ietf.org/html/rfc6070 (Test vectors)
32  */
33 
34 #if !defined(MBEDTLS_CONFIG_FILE)
35 #include "mbedtls/config.h"
36 #else
37 #include MBEDTLS_CONFIG_FILE
38 #endif
39 
40 #if defined(MBEDTLS_PKCS5_C)
41 
42 #include "mbedtls/pkcs5.h"
43 
44 #if defined(MBEDTLS_ASN1_PARSE_C)
45 #include "mbedtls/asn1.h"
46 #include "mbedtls/cipher.h"
47 #include "mbedtls/oid.h"
48 #endif /* MBEDTLS_ASN1_PARSE_C */
49 
50 #include <string.h>
51 
52 #if defined(MBEDTLS_PLATFORM_C)
53 #include "mbedtls/platform.h"
54 #else
55 #include <stdio.h>
56 #define mbedtls_printf printf
57 #endif
58 
59 #if defined(MBEDTLS_ASN1_PARSE_C)
60 static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params,
61                                       mbedtls_asn1_buf *salt, int *iterations,
62                                       int *keylen, mbedtls_md_type_t *md_type )
63 {
64     int ret;
65     mbedtls_asn1_buf prf_alg_oid;
66     unsigned char *p = params->p;
67     const unsigned char *end = params->p + params->len;
68 
69     if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
70         return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT +
71                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
72     /*
73      *  PBKDF2-params ::= SEQUENCE {
74      *    salt              OCTET STRING,
75      *    iterationCount    INTEGER,
76      *    keyLength         INTEGER OPTIONAL
77      *    prf               AlgorithmIdentifier DEFAULT algid-hmacWithSHA1
78      *  }
79      *
80      */
81     if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
82         return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
83 
84     salt->p = p;
85     p += salt->len;
86 
87     if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 )
88         return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
89 
90     if( p == end )
91         return( 0 );
92 
93     if( ( ret = mbedtls_asn1_get_int( &p, end, keylen ) ) != 0 )
94     {
95         if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
96             return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
97     }
98 
99     if( p == end )
100         return( 0 );
101 
102     if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 )
103         return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
104 
105     if( mbedtls_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 )
106         return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
107 
108     if( p != end )
109         return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT +
110                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
111 
112     return( 0 );
113 }
114 
115 int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode,
116                  const unsigned char *pwd,  size_t pwdlen,
117                  const unsigned char *data, size_t datalen,
118                  unsigned char *output )
119 {
120     int ret, iterations = 0, keylen = 0;
121     unsigned char *p, *end;
122     mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params;
123     mbedtls_asn1_buf salt;
124     mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;
125     unsigned char key[32], iv[32];
126     size_t olen = 0;
127     const mbedtls_md_info_t *md_info;
128     const mbedtls_cipher_info_t *cipher_info;
129     mbedtls_md_context_t md_ctx;
130     mbedtls_cipher_type_t cipher_alg;
131     mbedtls_cipher_context_t cipher_ctx;
132 
133     p = pbe_params->p;
134     end = p + pbe_params->len;
135 
136     /*
137      *  PBES2-params ::= SEQUENCE {
138      *    keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
139      *    encryptionScheme AlgorithmIdentifier {{PBES2-Encs}}
140      *  }
141      */
142     if( pbe_params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
143         return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT +
144                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
145 
146     if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 )
147         return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
148 
149     // Only PBKDF2 supported at the moment
150     //
151     if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid ) != 0 )
152         return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
153 
154     if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params,
155                                            &salt, &iterations, &keylen,
156                                            &md_type ) ) != 0 )
157     {
158         return( ret );
159     }
160 
161     md_info = mbedtls_md_info_from_type( md_type );
162     if( md_info == NULL )
163         return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
164 
165     if( ( ret = mbedtls_asn1_get_alg( &p, end, &enc_scheme_oid,
166                               &enc_scheme_params ) ) != 0 )
167     {
168         return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
169     }
170 
171     if( mbedtls_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 )
172         return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
173 
174     cipher_info = mbedtls_cipher_info_from_type( cipher_alg );
175     if( cipher_info == NULL )
176         return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
177 
178     /*
179      * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored
180      * since it is optional and we don't know if it was set or not
181      */
182     keylen = cipher_info->key_bitlen / 8;
183 
184     if( enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING ||
185         enc_scheme_params.len != cipher_info->iv_size )
186     {
187         return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT );
188     }
189 
190     mbedtls_md_init( &md_ctx );
191     mbedtls_cipher_init( &cipher_ctx );
192 
193     memcpy( iv, enc_scheme_params.p, enc_scheme_params.len );
194 
195     if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 )
196         goto exit;
197 
198     if( ( ret = mbedtls_pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len,
199                                    iterations, keylen, key ) ) != 0 )
200     {
201         goto exit;
202     }
203 
204     if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 )
205         goto exit;
206 
207     if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 )
208         goto exit;
209 
210     if( ( ret = mbedtls_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len,
211                               data, datalen, output, &olen ) ) != 0 )
212         ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH;
213 
214 exit:
215     mbedtls_md_free( &md_ctx );
216     mbedtls_cipher_free( &cipher_ctx );
217 
218     return( ret );
219 }
220 #endif /* MBEDTLS_ASN1_PARSE_C */
221 
222 int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password,
223                        size_t plen, const unsigned char *salt, size_t slen,
224                        unsigned int iteration_count,
225                        uint32_t key_length, unsigned char *output )
226 {
227     int ret, j;
228     unsigned int i;
229     unsigned char md1[MBEDTLS_MD_MAX_SIZE];
230     unsigned char work[MBEDTLS_MD_MAX_SIZE];
231     unsigned char md_size = mbedtls_md_get_size( ctx->md_info );
232     size_t use_len;
233     unsigned char *out_p = output;
234     unsigned char counter[4];
235 
236     memset( counter, 0, 4 );
237     counter[3] = 1;
238 
239 #if UINT_MAX > 0xFFFFFFFF
240     if( iteration_count > 0xFFFFFFFF )
241         return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA );
242 #endif
243 
244     while( key_length )
245     {
246         // U1 ends up in work
247         //
248         if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 )
249             return( ret );
250 
251         if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 )
252             return( ret );
253 
254         if( ( ret = mbedtls_md_hmac_update( ctx, counter, 4 ) ) != 0 )
255             return( ret );
256 
257         if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 )
258             return( ret );
259 
260         memcpy( md1, work, md_size );
261 
262         for( i = 1; i < iteration_count; i++ )
263         {
264             // U2 ends up in md1
265             //
266             if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 )
267                 return( ret );
268 
269             if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 )
270                 return( ret );
271 
272             if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 )
273                 return( ret );
274 
275             // U1 xor U2
276             //
277             for( j = 0; j < md_size; j++ )
278                 work[j] ^= md1[j];
279         }
280 
281         use_len = ( key_length < md_size ) ? key_length : md_size;
282         memcpy( out_p, work, use_len );
283 
284         key_length -= (uint32_t) use_len;
285         out_p += use_len;
286 
287         for( i = 4; i > 0; i-- )
288             if( ++counter[i - 1] != 0 )
289                 break;
290     }
291 
292     return( 0 );
293 }
294 
295 #if defined(MBEDTLS_SELF_TEST)
296 
297 #if !defined(MBEDTLS_SHA1_C)
298 int mbedtls_pkcs5_self_test( int verbose )
299 {
300     if( verbose != 0 )
301         mbedtls_printf( "  PBKDF2 (SHA1): skipped\n\n" );
302 
303     return( 0 );
304 }
305 #else
306 
307 #define MAX_TESTS   6
308 
309 static const size_t plen[MAX_TESTS] =
310     { 8, 8, 8, 24, 9 };
311 
312 static const unsigned char password[MAX_TESTS][32] =
313 {
314     "password",
315     "password",
316     "password",
317     "passwordPASSWORDpassword",
318     "pass\0word",
319 };
320 
321 static const size_t slen[MAX_TESTS] =
322     { 4, 4, 4, 36, 5 };
323 
324 static const unsigned char salt[MAX_TESTS][40] =
325 {
326     "salt",
327     "salt",
328     "salt",
329     "saltSALTsaltSALTsaltSALTsaltSALTsalt",
330     "sa\0lt",
331 };
332 
333 static const uint32_t it_cnt[MAX_TESTS] =
334     { 1, 2, 4096, 4096, 4096 };
335 
336 static const uint32_t key_len[MAX_TESTS] =
337     { 20, 20, 20, 25, 16 };
338 
339 static const unsigned char result_key[MAX_TESTS][32] =
340 {
341     { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
342       0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
343       0x2f, 0xe0, 0x37, 0xa6 },
344     { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
345       0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
346       0xd8, 0xde, 0x89, 0x57 },
347     { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
348       0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
349       0x65, 0xa4, 0x29, 0xc1 },
350     { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
351       0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
352       0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
353       0x38 },
354     { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
355       0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 },
356 };
357 
358 int mbedtls_pkcs5_self_test( int verbose )
359 {
360     mbedtls_md_context_t sha1_ctx;
361     const mbedtls_md_info_t *info_sha1;
362     int ret, i;
363     unsigned char key[64];
364 
365     mbedtls_md_init( &sha1_ctx );
366 
367     info_sha1 = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
368     if( info_sha1 == NULL )
369     {
370         ret = 1;
371         goto exit;
372     }
373 
374     if( ( ret = mbedtls_md_setup( &sha1_ctx, info_sha1, 1 ) ) != 0 )
375     {
376         ret = 1;
377         goto exit;
378     }
379 
380     for( i = 0; i < MAX_TESTS; i++ )
381     {
382         if( verbose != 0 )
383             mbedtls_printf( "  PBKDF2 (SHA1) #%d: ", i );
384 
385         ret = mbedtls_pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i],
386                                   slen[i], it_cnt[i], key_len[i], key );
387         if( ret != 0 ||
388             memcmp( result_key[i], key, key_len[i] ) != 0 )
389         {
390             if( verbose != 0 )
391                 mbedtls_printf( "failed\n" );
392 
393             ret = 1;
394             goto exit;
395         }
396 
397         if( verbose != 0 )
398             mbedtls_printf( "passed\n" );
399     }
400 
401     if( verbose != 0 )
402         mbedtls_printf( "\n" );
403 
404 exit:
405     mbedtls_md_free( &sha1_ctx );
406 
407     return( ret );
408 }
409 #endif /* MBEDTLS_SHA1_C */
410 
411 #endif /* MBEDTLS_SELF_TEST */
412 
413 #endif /* MBEDTLS_PKCS5_C */
414