Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
8774 rgimad 1
/*
2
 *  PKCS#12 Personal Information Exchange Syntax
3
 *
4
 *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5
 *  SPDX-License-Identifier: GPL-2.0
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  (at your option) any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License along
18
 *  with this program; if not, write to the Free Software Foundation, Inc.,
19
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
 *
21
 *  This file is part of mbed TLS (https://tls.mbed.org)
22
 */
23
/*
24
 *  The PKCS #12 Personal Information Exchange Syntax Standard v1.1
25
 *
26
 *  http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf
27
 *  ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn
28
 */
29
 
30
#if !defined(MBEDTLS_CONFIG_FILE)
31
#include "mbedtls/config.h"
32
#else
33
#include MBEDTLS_CONFIG_FILE
34
#endif
35
 
36
#if defined(MBEDTLS_PKCS12_C)
37
 
38
#include "mbedtls/pkcs12.h"
39
#include "mbedtls/asn1.h"
40
#include "mbedtls/cipher.h"
41
#include "mbedtls/platform_util.h"
42
 
43
#include 
44
 
45
#if defined(MBEDTLS_ARC4_C)
46
#include "mbedtls/arc4.h"
47
#endif
48
 
49
#if defined(MBEDTLS_DES_C)
50
#include "mbedtls/des.h"
51
#endif
52
 
53
#if defined(MBEDTLS_ASN1_PARSE_C)
54
 
55
static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params,
56
                                    mbedtls_asn1_buf *salt, int *iterations )
57
{
58
    int ret;
59
    unsigned char **p = ¶ms->p;
60
    const unsigned char *end = params->p + params->len;
61
 
62
    /*
63
     *  pkcs-12PbeParams ::= SEQUENCE {
64
     *    salt          OCTET STRING,
65
     *    iterations    INTEGER
66
     *  }
67
     *
68
     */
69
    if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
70
        return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT +
71
                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
72
 
73
    if( ( ret = mbedtls_asn1_get_tag( p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
74
        return( MBEDTLS_ERR_PKCS12_PBE_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_ERR_PKCS12_PBE_INVALID_FORMAT + ret );
81
 
82
    if( *p != end )
83
        return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT +
84
                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
85
 
86
    return( 0 );
87
}
88
 
89
#define PKCS12_MAX_PWDLEN 128
90
 
91
static int pkcs12_pbe_derive_key_iv( mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type,
92
                                     const unsigned char *pwd,  size_t pwdlen,
93
                                     unsigned char *key, size_t keylen,
94
                                     unsigned char *iv,  size_t ivlen )
95
{
96
    int ret, iterations = 0;
97
    mbedtls_asn1_buf salt;
98
    size_t i;
99
    unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2];
100
 
101
    if( pwdlen > PKCS12_MAX_PWDLEN )
102
        return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA );
103
 
104
    memset( &salt, 0, sizeof(mbedtls_asn1_buf) );
105
    memset( &unipwd, 0, sizeof(unipwd) );
106
 
107
    if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt,
108
                                         &iterations ) ) != 0 )
109
        return( ret );
110
 
111
    for( i = 0; i < pwdlen; i++ )
112
        unipwd[i * 2 + 1] = pwd[i];
113
 
114
    if( ( ret = mbedtls_pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2,
115
                                   salt.p, salt.len, md_type,
116
                                   MBEDTLS_PKCS12_DERIVE_KEY, iterations ) ) != 0 )
117
    {
118
        return( ret );
119
    }
120
 
121
    if( iv == NULL || ivlen == 0 )
122
        return( 0 );
123
 
124
    if( ( ret = mbedtls_pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2,
125
                                   salt.p, salt.len, md_type,
126
                                   MBEDTLS_PKCS12_DERIVE_IV, iterations ) ) != 0 )
127
    {
128
        return( ret );
129
    }
130
    return( 0 );
131
}
132
 
133
#undef PKCS12_MAX_PWDLEN
134
 
135
int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode,
136
                             const unsigned char *pwd,  size_t pwdlen,
137
                             const unsigned char *data, size_t len,
138
                             unsigned char *output )
139
{
140
#if !defined(MBEDTLS_ARC4_C)
141
    ((void) pbe_params);
142
    ((void) mode);
143
    ((void) pwd);
144
    ((void) pwdlen);
145
    ((void) data);
146
    ((void) len);
147
    ((void) output);
148
    return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE );
149
#else
150
    int ret;
151
    unsigned char key[16];
152
    mbedtls_arc4_context ctx;
153
    ((void) mode);
154
 
155
    mbedtls_arc4_init( &ctx );
156
 
157
    if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, MBEDTLS_MD_SHA1,
158
                                          pwd, pwdlen,
159
                                          key, 16, NULL, 0 ) ) != 0 )
160
    {
161
        return( ret );
162
    }
163
 
164
    mbedtls_arc4_setup( &ctx, key, 16 );
165
    if( ( ret = mbedtls_arc4_crypt( &ctx, len, data, output ) ) != 0 )
166
        goto exit;
167
 
168
exit:
169
    mbedtls_platform_zeroize( key, sizeof( key ) );
170
    mbedtls_arc4_free( &ctx );
171
 
172
    return( ret );
173
#endif /* MBEDTLS_ARC4_C */
174
}
175
 
176
int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode,
177
                mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type,
178
                const unsigned char *pwd,  size_t pwdlen,
179
                const unsigned char *data, size_t len,
180
                unsigned char *output )
181
{
182
    int ret, keylen = 0;
183
    unsigned char key[32];
184
    unsigned char iv[16];
185
    const mbedtls_cipher_info_t *cipher_info;
186
    mbedtls_cipher_context_t cipher_ctx;
187
    size_t olen = 0;
188
 
189
    cipher_info = mbedtls_cipher_info_from_type( cipher_type );
190
    if( cipher_info == NULL )
191
        return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE );
192
 
193
    keylen = cipher_info->key_bitlen / 8;
194
 
195
    if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen,
196
                                          key, keylen,
197
                                          iv, cipher_info->iv_size ) ) != 0 )
198
    {
199
        return( ret );
200
    }
201
 
202
    mbedtls_cipher_init( &cipher_ctx );
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_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 )
211
        goto exit;
212
 
213
    if( ( ret = mbedtls_cipher_reset( &cipher_ctx ) ) != 0 )
214
        goto exit;
215
 
216
    if( ( ret = mbedtls_cipher_update( &cipher_ctx, data, len,
217
                                output, &olen ) ) != 0 )
218
    {
219
        goto exit;
220
    }
221
 
222
    if( ( ret = mbedtls_cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 )
223
        ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH;
224
 
225
exit:
226
    mbedtls_platform_zeroize( key, sizeof( key ) );
227
    mbedtls_platform_zeroize( iv,  sizeof( iv  ) );
228
    mbedtls_cipher_free( &cipher_ctx );
229
 
230
    return( ret );
231
}
232
 
233
#endif /* MBEDTLS_ASN1_PARSE_C */
234
 
235
static void pkcs12_fill_buffer( unsigned char *data, size_t data_len,
236
                                const unsigned char *filler, size_t fill_len )
237
{
238
    unsigned char *p = data;
239
    size_t use_len;
240
 
241
    while( data_len > 0 )
242
    {
243
        use_len = ( data_len > fill_len ) ? fill_len : data_len;
244
        memcpy( p, filler, use_len );
245
        p += use_len;
246
        data_len -= use_len;
247
    }
248
}
249
 
250
int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen,
251
                       const unsigned char *pwd, size_t pwdlen,
252
                       const unsigned char *salt, size_t saltlen,
253
                       mbedtls_md_type_t md_type, int id, int iterations )
254
{
255
    int ret;
256
    unsigned int j;
257
 
258
    unsigned char diversifier[128];
259
    unsigned char salt_block[128], pwd_block[128], hash_block[128];
260
    unsigned char hash_output[MBEDTLS_MD_MAX_SIZE];
261
    unsigned char *p;
262
    unsigned char c;
263
 
264
    size_t hlen, use_len, v, i;
265
 
266
    const mbedtls_md_info_t *md_info;
267
    mbedtls_md_context_t md_ctx;
268
 
269
    // This version only allows max of 64 bytes of password or salt
270
    if( datalen > 128 || pwdlen > 64 || saltlen > 64 )
271
        return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA );
272
 
273
    md_info = mbedtls_md_info_from_type( md_type );
274
    if( md_info == NULL )
275
        return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE );
276
 
277
    mbedtls_md_init( &md_ctx );
278
 
279
    if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
280
        return( ret );
281
    hlen = mbedtls_md_get_size( md_info );
282
 
283
    if( hlen <= 32 )
284
        v = 64;
285
    else
286
        v = 128;
287
 
288
    memset( diversifier, (unsigned char) id, v );
289
 
290
    pkcs12_fill_buffer( salt_block, v, salt, saltlen );
291
    pkcs12_fill_buffer( pwd_block,  v, pwd,  pwdlen  );
292
 
293
    p = data;
294
    while( datalen > 0 )
295
    {
296
        // Calculate hash( diversifier || salt_block || pwd_block )
297
        if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 )
298
            goto exit;
299
 
300
        if( ( ret = mbedtls_md_update( &md_ctx, diversifier, v ) ) != 0 )
301
            goto exit;
302
 
303
        if( ( ret = mbedtls_md_update( &md_ctx, salt_block, v ) ) != 0 )
304
            goto exit;
305
 
306
        if( ( ret = mbedtls_md_update( &md_ctx, pwd_block, v ) ) != 0 )
307
            goto exit;
308
 
309
        if( ( ret = mbedtls_md_finish( &md_ctx, hash_output ) ) != 0 )
310
            goto exit;
311
 
312
        // Perform remaining ( iterations - 1 ) recursive hash calculations
313
        for( i = 1; i < (size_t) iterations; i++ )
314
        {
315
            if( ( ret = mbedtls_md( md_info, hash_output, hlen, hash_output ) ) != 0 )
316
                goto exit;
317
        }
318
 
319
        use_len = ( datalen > hlen ) ? hlen : datalen;
320
        memcpy( p, hash_output, use_len );
321
        datalen -= use_len;
322
        p += use_len;
323
 
324
        if( datalen == 0 )
325
            break;
326
 
327
        // Concatenating copies of hash_output into hash_block (B)
328
        pkcs12_fill_buffer( hash_block, v, hash_output, hlen );
329
 
330
        // B += 1
331
        for( i = v; i > 0; i-- )
332
            if( ++hash_block[i - 1] != 0 )
333
                break;
334
 
335
        // salt_block += B
336
        c = 0;
337
        for( i = v; i > 0; i-- )
338
        {
339
            j = salt_block[i - 1] + hash_block[i - 1] + c;
340
            c = (unsigned char) (j >> 8);
341
            salt_block[i - 1] = j & 0xFF;
342
        }
343
 
344
        // pwd_block  += B
345
        c = 0;
346
        for( i = v; i > 0; i-- )
347
        {
348
            j = pwd_block[i - 1] + hash_block[i - 1] + c;
349
            c = (unsigned char) (j >> 8);
350
            pwd_block[i - 1] = j & 0xFF;
351
        }
352
    }
353
 
354
    ret = 0;
355
 
356
exit:
357
    mbedtls_platform_zeroize( salt_block, sizeof( salt_block ) );
358
    mbedtls_platform_zeroize( pwd_block, sizeof( pwd_block ) );
359
    mbedtls_platform_zeroize( hash_block, sizeof( hash_block ) );
360
    mbedtls_platform_zeroize( hash_output, sizeof( hash_output ) );
361
 
362
    mbedtls_md_free( &md_ctx );
363
 
364
    return( ret );
365
}
366
 
367
#endif /* MBEDTLS_PKCS12_C */