blob: 4467dd7b199c444b8b63dd199d7512ec7d5c9e9c [file] [log] [blame]
Jaeden Ameroe54e6932018-08-06 16:19:58 +01001/**
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: 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 * This file is part of Mbed Crypto (https://tls.mbed.org)
24 */
25/*
26 * PKCS#5 includes PBKDF2 and more
27 *
28 * http://tools.ietf.org/html/rfc2898 (Specification)
29 * http://tools.ietf.org/html/rfc6070 (Test vectors)
30 */
31
32#if !defined(MBEDCRYPTO_CONFIG_FILE)
33#include "mbedcrypto/config.h"
34#else
35#include MBEDCRYPTO_CONFIG_FILE
36#endif
37
38#if defined(MBEDCRYPTO_PKCS5_C)
39
40#include "mbedcrypto/pkcs5.h"
41
42#if defined(MBEDCRYPTO_ASN1_PARSE_C)
43#include "mbedcrypto/asn1.h"
44#include "mbedcrypto/cipher.h"
45#include "mbedcrypto/oid.h"
46#endif /* MBEDCRYPTO_ASN1_PARSE_C */
47
48#include <string.h>
49
50#if defined(MBEDCRYPTO_PLATFORM_C)
51#include "mbedcrypto/platform.h"
52#else
53#include <stdio.h>
54#define mbedcrypto_printf printf
55#endif
56
57#if !defined(MBEDCRYPTO_ASN1_PARSE_C)
58int mbedcrypto_pkcs5_pbes2( const mbedcrypto_asn1_buf *pbe_params, int mode,
59 const unsigned char *pwd, size_t pwdlen,
60 const unsigned char *data, size_t datalen,
61 unsigned char *output )
62{
63 ((void) pbe_params);
64 ((void) mode);
65 ((void) pwd);
66 ((void) pwdlen);
67 ((void) data);
68 ((void) datalen);
69 ((void) output);
70 return( MBEDCRYPTO_ERR_PKCS5_FEATURE_UNAVAILABLE );
71}
72#else
73static int pkcs5_parse_pbkdf2_params( const mbedcrypto_asn1_buf *params,
74 mbedcrypto_asn1_buf *salt, int *iterations,
75 int *keylen, mbedcrypto_md_type_t *md_type )
76{
77 int ret;
78 mbedcrypto_asn1_buf prf_alg_oid;
79 unsigned char *p = params->p;
80 const unsigned char *end = params->p + params->len;
81
82 if( params->tag != ( MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) )
83 return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT +
84 MBEDCRYPTO_ERR_ASN1_UNEXPECTED_TAG );
85 /*
86 * PBKDF2-params ::= SEQUENCE {
87 * salt OCTET STRING,
88 * iterationCount INTEGER,
89 * keyLength INTEGER OPTIONAL
90 * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1
91 * }
92 *
93 */
94 if( ( ret = mbedcrypto_asn1_get_tag( &p, end, &salt->len, MBEDCRYPTO_ASN1_OCTET_STRING ) ) != 0 )
95 return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT + ret );
96
97 salt->p = p;
98 p += salt->len;
99
100 if( ( ret = mbedcrypto_asn1_get_int( &p, end, iterations ) ) != 0 )
101 return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT + ret );
102
103 if( p == end )
104 return( 0 );
105
106 if( ( ret = mbedcrypto_asn1_get_int( &p, end, keylen ) ) != 0 )
107 {
108 if( ret != MBEDCRYPTO_ERR_ASN1_UNEXPECTED_TAG )
109 return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT + ret );
110 }
111
112 if( p == end )
113 return( 0 );
114
115 if( ( ret = mbedcrypto_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 )
116 return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT + ret );
117
118 if( mbedcrypto_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 )
119 return( MBEDCRYPTO_ERR_PKCS5_FEATURE_UNAVAILABLE );
120
121 if( p != end )
122 return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT +
123 MBEDCRYPTO_ERR_ASN1_LENGTH_MISMATCH );
124
125 return( 0 );
126}
127
128int mbedcrypto_pkcs5_pbes2( const mbedcrypto_asn1_buf *pbe_params, int mode,
129 const unsigned char *pwd, size_t pwdlen,
130 const unsigned char *data, size_t datalen,
131 unsigned char *output )
132{
133 int ret, iterations = 0, keylen = 0;
134 unsigned char *p, *end;
135 mbedcrypto_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params;
136 mbedcrypto_asn1_buf salt;
137 mbedcrypto_md_type_t md_type = MBEDCRYPTO_MD_SHA1;
138 unsigned char key[32], iv[32];
139 size_t olen = 0;
140 const mbedcrypto_md_info_t *md_info;
141 const mbedcrypto_cipher_info_t *cipher_info;
142 mbedcrypto_md_context_t md_ctx;
143 mbedcrypto_cipher_type_t cipher_alg;
144 mbedcrypto_cipher_context_t cipher_ctx;
145
146 p = pbe_params->p;
147 end = p + pbe_params->len;
148
149 /*
150 * PBES2-params ::= SEQUENCE {
151 * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
152 * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}}
153 * }
154 */
155 if( pbe_params->tag != ( MBEDCRYPTO_ASN1_CONSTRUCTED | MBEDCRYPTO_ASN1_SEQUENCE ) )
156 return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT +
157 MBEDCRYPTO_ERR_ASN1_UNEXPECTED_TAG );
158
159 if( ( ret = mbedcrypto_asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 )
160 return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT + ret );
161
162 // Only PBKDF2 supported at the moment
163 //
164 if( MBEDCRYPTO_OID_CMP( MBEDCRYPTO_OID_PKCS5_PBKDF2, &kdf_alg_oid ) != 0 )
165 return( MBEDCRYPTO_ERR_PKCS5_FEATURE_UNAVAILABLE );
166
167 if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params,
168 &salt, &iterations, &keylen,
169 &md_type ) ) != 0 )
170 {
171 return( ret );
172 }
173
174 md_info = mbedcrypto_md_info_from_type( md_type );
175 if( md_info == NULL )
176 return( MBEDCRYPTO_ERR_PKCS5_FEATURE_UNAVAILABLE );
177
178 if( ( ret = mbedcrypto_asn1_get_alg( &p, end, &enc_scheme_oid,
179 &enc_scheme_params ) ) != 0 )
180 {
181 return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT + ret );
182 }
183
184 if( mbedcrypto_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 )
185 return( MBEDCRYPTO_ERR_PKCS5_FEATURE_UNAVAILABLE );
186
187 cipher_info = mbedcrypto_cipher_info_from_type( cipher_alg );
188 if( cipher_info == NULL )
189 return( MBEDCRYPTO_ERR_PKCS5_FEATURE_UNAVAILABLE );
190
191 /*
192 * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored
193 * since it is optional and we don't know if it was set or not
194 */
195 keylen = cipher_info->key_bitlen / 8;
196
197 if( enc_scheme_params.tag != MBEDCRYPTO_ASN1_OCTET_STRING ||
198 enc_scheme_params.len != cipher_info->iv_size )
199 {
200 return( MBEDCRYPTO_ERR_PKCS5_INVALID_FORMAT );
201 }
202
203 mbedcrypto_md_init( &md_ctx );
204 mbedcrypto_cipher_init( &cipher_ctx );
205
206 memcpy( iv, enc_scheme_params.p, enc_scheme_params.len );
207
208 if( ( ret = mbedcrypto_md_setup( &md_ctx, md_info, 1 ) ) != 0 )
209 goto exit;
210
211 if( ( ret = mbedcrypto_pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len,
212 iterations, keylen, key ) ) != 0 )
213 {
214 goto exit;
215 }
216
217 if( ( ret = mbedcrypto_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 )
218 goto exit;
219
220 if( ( ret = mbedcrypto_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedcrypto_operation_t) mode ) ) != 0 )
221 goto exit;
222
223 if( ( ret = mbedcrypto_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len,
224 data, datalen, output, &olen ) ) != 0 )
225 ret = MBEDCRYPTO_ERR_PKCS5_PASSWORD_MISMATCH;
226
227exit:
228 mbedcrypto_md_free( &md_ctx );
229 mbedcrypto_cipher_free( &cipher_ctx );
230
231 return( ret );
232}
233#endif /* MBEDCRYPTO_ASN1_PARSE_C */
234
235int mbedcrypto_pkcs5_pbkdf2_hmac( mbedcrypto_md_context_t *ctx, const unsigned char *password,
236 size_t plen, const unsigned char *salt, size_t slen,
237 unsigned int iteration_count,
238 uint32_t key_length, unsigned char *output )
239{
240 int ret, j;
241 unsigned int i;
242 unsigned char md1[MBEDCRYPTO_MD_MAX_SIZE];
243 unsigned char work[MBEDCRYPTO_MD_MAX_SIZE];
244 unsigned char md_size = mbedcrypto_md_get_size( ctx->md_info );
245 size_t use_len;
246 unsigned char *out_p = output;
247 unsigned char counter[4];
248
249 memset( counter, 0, 4 );
250 counter[3] = 1;
251
252 if( iteration_count > 0xFFFFFFFF )
253 return( MBEDCRYPTO_ERR_PKCS5_BAD_INPUT_DATA );
254
255 while( key_length )
256 {
257 // U1 ends up in work
258 //
259 if( ( ret = mbedcrypto_md_hmac_starts( ctx, password, plen ) ) != 0 )
260 return( ret );
261
262 if( ( ret = mbedcrypto_md_hmac_update( ctx, salt, slen ) ) != 0 )
263 return( ret );
264
265 if( ( ret = mbedcrypto_md_hmac_update( ctx, counter, 4 ) ) != 0 )
266 return( ret );
267
268 if( ( ret = mbedcrypto_md_hmac_finish( ctx, work ) ) != 0 )
269 return( ret );
270
271 memcpy( md1, work, md_size );
272
273 for( i = 1; i < iteration_count; i++ )
274 {
275 // U2 ends up in md1
276 //
277 if( ( ret = mbedcrypto_md_hmac_starts( ctx, password, plen ) ) != 0 )
278 return( ret );
279
280 if( ( ret = mbedcrypto_md_hmac_update( ctx, md1, md_size ) ) != 0 )
281 return( ret );
282
283 if( ( ret = mbedcrypto_md_hmac_finish( ctx, md1 ) ) != 0 )
284 return( ret );
285
286 // U1 xor U2
287 //
288 for( j = 0; j < md_size; j++ )
289 work[j] ^= md1[j];
290 }
291
292 use_len = ( key_length < md_size ) ? key_length : md_size;
293 memcpy( out_p, work, use_len );
294
295 key_length -= (uint32_t) use_len;
296 out_p += use_len;
297
298 for( i = 4; i > 0; i-- )
299 if( ++counter[i - 1] != 0 )
300 break;
301 }
302
303 return( 0 );
304}
305
306#if defined(MBEDCRYPTO_SELF_TEST)
307
308#if !defined(MBEDCRYPTO_SHA1_C)
309int mbedcrypto_pkcs5_self_test( int verbose )
310{
311 if( verbose != 0 )
312 mbedcrypto_printf( " PBKDF2 (SHA1): skipped\n\n" );
313
314 return( 0 );
315}
316#else
317
318#define MAX_TESTS 6
319
320static const size_t plen[MAX_TESTS] =
321 { 8, 8, 8, 24, 9 };
322
323static const unsigned char password[MAX_TESTS][32] =
324{
325 "password",
326 "password",
327 "password",
328 "passwordPASSWORDpassword",
329 "pass\0word",
330};
331
332static const size_t slen[MAX_TESTS] =
333 { 4, 4, 4, 36, 5 };
334
335static const unsigned char salt[MAX_TESTS][40] =
336{
337 "salt",
338 "salt",
339 "salt",
340 "saltSALTsaltSALTsaltSALTsaltSALTsalt",
341 "sa\0lt",
342};
343
344static const uint32_t it_cnt[MAX_TESTS] =
345 { 1, 2, 4096, 4096, 4096 };
346
347static const uint32_t key_len[MAX_TESTS] =
348 { 20, 20, 20, 25, 16 };
349
350static const unsigned char result_key[MAX_TESTS][32] =
351{
352 { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
353 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
354 0x2f, 0xe0, 0x37, 0xa6 },
355 { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
356 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
357 0xd8, 0xde, 0x89, 0x57 },
358 { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
359 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
360 0x65, 0xa4, 0x29, 0xc1 },
361 { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
362 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
363 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
364 0x38 },
365 { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
366 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 },
367};
368
369int mbedcrypto_pkcs5_self_test( int verbose )
370{
371 mbedcrypto_md_context_t sha1_ctx;
372 const mbedcrypto_md_info_t *info_sha1;
373 int ret, i;
374 unsigned char key[64];
375
376 mbedcrypto_md_init( &sha1_ctx );
377
378 info_sha1 = mbedcrypto_md_info_from_type( MBEDCRYPTO_MD_SHA1 );
379 if( info_sha1 == NULL )
380 {
381 ret = 1;
382 goto exit;
383 }
384
385 if( ( ret = mbedcrypto_md_setup( &sha1_ctx, info_sha1, 1 ) ) != 0 )
386 {
387 ret = 1;
388 goto exit;
389 }
390
391 for( i = 0; i < MAX_TESTS; i++ )
392 {
393 if( verbose != 0 )
394 mbedcrypto_printf( " PBKDF2 (SHA1) #%d: ", i );
395
396 ret = mbedcrypto_pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i],
397 slen[i], it_cnt[i], key_len[i], key );
398 if( ret != 0 ||
399 memcmp( result_key[i], key, key_len[i] ) != 0 )
400 {
401 if( verbose != 0 )
402 mbedcrypto_printf( "failed\n" );
403
404 ret = 1;
405 goto exit;
406 }
407
408 if( verbose != 0 )
409 mbedcrypto_printf( "passed\n" );
410 }
411
412 if( verbose != 0 )
413 mbedcrypto_printf( "\n" );
414
415exit:
416 mbedcrypto_md_free( &sha1_ctx );
417
418 return( ret );
419}
420#endif /* MBEDCRYPTO_SHA1_C */
421
422#endif /* MBEDCRYPTO_SELF_TEST */
423
424#endif /* MBEDCRYPTO_PKCS5_C */