blob: 649541ec7802574903ab51093f7ec39efb8dc8b3 [file] [log] [blame]
Paul Bakkercf6e95d2013-06-12 13:18:15 +02001/*
2 * PKCS#12 Personal Information Exchange Syntax
3 *
4 * Copyright (C) 2006-2013, Brainspark B.V.
5 *
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8 *
9 * All rights reserved.
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/*
26 * The PKCS #12 Personal Information Exchange Syntax Standard v1.1
27 *
28 * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf
29 * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn
30 */
31
32#include "polarssl/config.h"
33
34#if defined(POLARSSL_PKCS12_C)
35
36#include "polarssl/pkcs12.h"
37#include "polarssl/asn1.h"
Paul Bakker14a222c2013-06-18 16:35:48 +020038#include "polarssl/cipher.h"
Paul Bakkercf6e95d2013-06-12 13:18:15 +020039
40#if defined(POLARSSL_ARC4_C)
41#include "polarssl/arc4.h"
42#endif
43
44#if defined(POLARSSL_DES_C)
45#include "polarssl/des.h"
46#endif
47
48static int pkcs12_parse_pbe_params( unsigned char **p,
49 const unsigned char *end,
50 asn1_buf *salt, int *iterations )
51{
52 int ret;
53 size_t len = 0;
54
55 /*
56 * pkcs-12PbeParams ::= SEQUENCE {
57 * salt OCTET STRING,
58 * iterations INTEGER
59 * }
60 *
61 */
62 if( ( ret = asn1_get_tag( p, end, &len,
63 ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
64 {
65 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret );
66 }
67
68 end = *p + len;
69
70 if( ( ret = asn1_get_tag( p, end, &salt->len, ASN1_OCTET_STRING ) ) != 0 )
71 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret );
72
73 salt->p = *p;
74 *p += salt->len;
75
76 if( ( ret = asn1_get_int( p, end, iterations ) ) != 0 )
77 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret );
78
79 if( *p != end )
80 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT +
81 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
82
83 return( 0 );
84}
85
Paul Bakker14a222c2013-06-18 16:35:48 +020086static int pkcs12_pbe_derive_key_iv( asn1_buf *pbe_params, md_type_t md_type,
Paul Bakkercf6e95d2013-06-12 13:18:15 +020087 const unsigned char *pwd, size_t pwdlen,
88 unsigned char *key, size_t keylen,
89 unsigned char *iv, size_t ivlen )
90{
91 int ret, iterations;
92 asn1_buf salt;
93 size_t i;
94 unsigned char *p, *end;
95 unsigned char unipwd[258];
96
97 memset(&salt, 0, sizeof(asn1_buf));
98 memset(&unipwd, 0, sizeof(unipwd));
99
100 p = pbe_params->p;
101 end = p + pbe_params->len;
102
103 if( ( ret = pkcs12_parse_pbe_params( &p, end, &salt, &iterations ) ) != 0 )
104 return( ret );
105
106 for(i = 0; i < pwdlen; i++)
107 unipwd[i * 2 + 1] = pwd[i];
108
109 if( ( ret = pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2,
Paul Bakker14a222c2013-06-18 16:35:48 +0200110 salt.p, salt.len, md_type,
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200111 PKCS12_DERIVE_KEY, iterations ) ) != 0 )
112 {
113 return( ret );
114 }
115
116 if( iv == NULL || ivlen == 0 )
117 return( 0 );
118
119 if( ( ret = pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2,
Paul Bakker14a222c2013-06-18 16:35:48 +0200120 salt.p, salt.len, md_type,
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200121 PKCS12_DERIVE_IV, iterations ) ) != 0 )
122 {
123 return( ret );
124 }
125 return( 0 );
126}
127
128int pkcs12_pbe_sha1_rc4_128( asn1_buf *pbe_params, int mode,
129 const unsigned char *pwd, size_t pwdlen,
130 const unsigned char *data, size_t len,
131 unsigned char *output )
132{
133#if !defined(POLARSSL_ARC4_C)
134 ((void) pbe_params);
135 ((void) mode);
136 ((void) pwd);
137 ((void) pwdlen);
138 ((void) data);
139 ((void) len);
140 ((void) output);
141 return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE );
142#else
143 int ret;
144 unsigned char key[16];
145 arc4_context ctx;
146 ((void) mode);
147
Paul Bakker14a222c2013-06-18 16:35:48 +0200148 if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, POLARSSL_MD_SHA1,
149 pwd, pwdlen,
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200150 key, 16, NULL, 0 ) ) != 0 )
151 {
152 return( ret );
153 }
154
155 arc4_setup( &ctx, key, 16 );
156 if( ( ret = arc4_crypt( &ctx, len, data, output ) ) != 0 )
157 return( ret );
158
159 return( 0 );
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200160#endif /* POLARSSL_ARC4_C */
Paul Bakker67812d32013-06-14 11:35:09 +0200161}
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200162
Paul Bakker14a222c2013-06-18 16:35:48 +0200163int pkcs12_pbe( asn1_buf *pbe_params, int mode,
164 cipher_type_t cipher_type, md_type_t md_type,
165 const unsigned char *pwd, size_t pwdlen,
166 const unsigned char *data, size_t len,
167 unsigned char *output )
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200168{
Paul Bakker14a222c2013-06-18 16:35:48 +0200169 int ret, keylen = 0;
170 unsigned char key[32];
171 unsigned char iv[16];
172 const cipher_info_t *cipher_info;
173 cipher_context_t cipher_ctx;
174 size_t olen = 0;
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200175
Paul Bakker14a222c2013-06-18 16:35:48 +0200176 cipher_info = cipher_info_from_type( cipher_type );
177 if( cipher_info == NULL )
178 return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE );
179
180 keylen = cipher_info->key_length / 8;
181
182 if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen,
183 key, keylen,
184 iv, cipher_info->iv_size ) ) != 0 )
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200185 {
186 return( ret );
187 }
188
Paul Bakker14a222c2013-06-18 16:35:48 +0200189 if( ( ret = cipher_init_ctx( &cipher_ctx, cipher_info ) ) != 0 )
190 return( ret );
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200191
Paul Bakker14a222c2013-06-18 16:35:48 +0200192 if( ( ret = cipher_setkey( &cipher_ctx, key, keylen, mode ) ) != 0 )
Manuel Pégourié-Gonnard1c022a62014-11-17 12:24:41 +0100193 goto cleanup;
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200194
Paul Bakker14a222c2013-06-18 16:35:48 +0200195 if( ( ret = cipher_reset( &cipher_ctx, iv ) ) != 0 )
Manuel Pégourié-Gonnard1c022a62014-11-17 12:24:41 +0100196 goto cleanup;
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200197
Paul Bakker14a222c2013-06-18 16:35:48 +0200198 if( ( ret = cipher_update( &cipher_ctx, data, len,
199 output, &olen ) ) != 0 )
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200200 {
Manuel Pégourié-Gonnard1c022a62014-11-17 12:24:41 +0100201 goto cleanup;
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200202 }
203
Paul Bakker14a222c2013-06-18 16:35:48 +0200204 if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 )
Manuel Pégourié-Gonnard1c022a62014-11-17 12:24:41 +0100205 {
206 ret = POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH;
207 goto cleanup;
208 }
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200209
Manuel Pégourié-Gonnard1c022a62014-11-17 12:24:41 +0100210cleanup:
211 cipher_free_ctx( &cipher_ctx );
212
213 return( ret );
Paul Bakker67812d32013-06-14 11:35:09 +0200214}
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200215
216static void pkcs12_fill_buffer( unsigned char *data, size_t data_len,
217 const unsigned char *filler, size_t fill_len )
218{
219 unsigned char *p = data;
220 size_t use_len;
221
222 while( data_len > 0 )
223 {
224 use_len = ( data_len > fill_len ) ? fill_len : data_len;
225 memcpy( p, filler, use_len );
226 p += use_len;
227 data_len -= use_len;
228 }
229}
230
231int pkcs12_derivation( unsigned char *data, size_t datalen,
232 const unsigned char *pwd, size_t pwdlen,
233 const unsigned char *salt, size_t saltlen,
234 md_type_t md_type, int id, int iterations )
235{
236 int ret, i;
237 unsigned int j;
238
239 unsigned char diversifier[128];
240 unsigned char salt_block[128], pwd_block[128], hash_block[128];
241 unsigned char hash_output[POLARSSL_MD_MAX_SIZE];
242 unsigned char *p;
243 unsigned char c;
244
245 size_t hlen, use_len, v;
246
247 const md_info_t *md_info;
248 md_context_t md_ctx;
249
250 // This version only allows max of 64 bytes of password or salt
251 if( datalen > 128 || pwdlen > 64 || saltlen > 64 )
252 return( POLARSSL_ERR_PKCS12_BAD_INPUT_DATA );
253
254 md_info = md_info_from_type( md_type );
255 if( md_info == NULL )
256 return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE );
257
258 if ( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 )
259 return( ret );
260 hlen = md_get_size( md_info );
261
262 if( hlen <= 32 )
263 v = 64;
264 else
265 v = 128;
266
267 memset( diversifier, (unsigned char) id, v );
268
269 pkcs12_fill_buffer( salt_block, v, salt, saltlen );
270 pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen );
271
272 p = data;
273 while( datalen > 0 )
274 {
275 // Calculate hash( diversifier || salt_block || pwd_block )
276 if( ( ret = md_starts( &md_ctx ) ) != 0 )
Manuel Pégourié-Gonnard1c022a62014-11-17 12:24:41 +0100277 goto cleanup;
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200278
279 if( ( ret = md_update( &md_ctx, diversifier, v ) ) != 0 )
Manuel Pégourié-Gonnard1c022a62014-11-17 12:24:41 +0100280 goto cleanup;
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200281
282 if( ( ret = md_update( &md_ctx, salt_block, v ) ) != 0 )
Manuel Pégourié-Gonnard1c022a62014-11-17 12:24:41 +0100283 goto cleanup;
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200284
285 if( ( ret = md_update( &md_ctx, pwd_block, v ) ) != 0 )
Manuel Pégourié-Gonnard1c022a62014-11-17 12:24:41 +0100286 goto cleanup;
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200287
288 if( ( ret = md_finish( &md_ctx, hash_output ) ) != 0 )
Manuel Pégourié-Gonnard1c022a62014-11-17 12:24:41 +0100289 goto cleanup;
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200290
291 // Perform remaining ( iterations - 1 ) recursive hash calculations
292 for( i = 1; i < iterations; i++ )
293 {
294 if( ( ret = md( md_info, hash_output, hlen, hash_output ) ) != 0 )
Manuel Pégourié-Gonnard1c022a62014-11-17 12:24:41 +0100295 goto cleanup;
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200296 }
297
298 use_len = ( datalen > hlen ) ? hlen : datalen;
299 memcpy( p, hash_output, use_len );
300 datalen -= use_len;
301 p += use_len;
302
303 if( datalen == 0 )
304 break;
305
306 // Concatenating copies of hash_output into hash_block (B)
307 pkcs12_fill_buffer( hash_block, v, hash_output, hlen );
308
309 // B += 1
310 for( i = v; i > 0; i-- )
311 if( ++hash_block[i - 1] != 0 )
312 break;
313
314 // salt_block += B
315 c = 0;
316 for( i = v; i > 0; i-- )
317 {
318 j = salt_block[i - 1] + hash_block[i - 1] + c;
319 c = (unsigned char) (j >> 8);
320 salt_block[i - 1] = j & 0xFF;
321 }
322
323 // pwd_block += B
324 c = 0;
325 for( i = v; i > 0; i-- )
326 {
327 j = pwd_block[i - 1] + hash_block[i - 1] + c;
328 c = (unsigned char) (j >> 8);
329 pwd_block[i - 1] = j & 0xFF;
330 }
331 }
332
Manuel Pégourié-Gonnard1c022a62014-11-17 12:24:41 +0100333cleanup:
334 md_free_ctx( &md_ctx );
335
336 return( ret );
Paul Bakkercf6e95d2013-06-12 13:18:15 +0200337}
338
339#endif /* POLARSSL_PKCS12_C */