Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
8774 rgimad 1
/**
2
 * \file pkcs5.c
3
 *
4
 * \brief PKCS#5 functions
5
 *
6
 * \author Mathias Olsson 
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 
51
 
52
#if defined(MBEDTLS_PLATFORM_C)
53
#include "mbedtls/platform.h"
54
#else
55
#include 
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 */