blob: e0d7207cef20267f9760b4c3ede3ff339f914849 [file] [log] [blame]
Paul Bakkerf1f21fe2013-06-24 19:17:19 +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 Bakker38b50d72013-06-24 19:33:27 +020038#include "polarssl/cipher.h"
Paul Bakkerf1f21fe2013-06-24 19:17:19 +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
Paul Bakkerf8d018a2013-06-29 12:16:17 +020048static int pkcs12_parse_pbe_params( asn1_buf *params,
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020049 asn1_buf *salt, int *iterations )
50{
51 int ret;
Paul Bakkerf8d018a2013-06-29 12:16:17 +020052 unsigned char **p = &params->p;
53 const unsigned char *end = params->p + params->len;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020054
55 /*
56 * pkcs-12PbeParams ::= SEQUENCE {
57 * salt OCTET STRING,
58 * iterations INTEGER
59 * }
60 *
61 */
Paul Bakkerf8d018a2013-06-29 12:16:17 +020062 if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
63 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT +
64 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020065
66 if( ( ret = asn1_get_tag( p, end, &salt->len, ASN1_OCTET_STRING ) ) != 0 )
67 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret );
68
69 salt->p = *p;
70 *p += salt->len;
71
72 if( ( ret = asn1_get_int( p, end, iterations ) ) != 0 )
73 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret );
74
75 if( *p != end )
76 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT +
77 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
78
79 return( 0 );
80}
81
Paul Bakker38b50d72013-06-24 19:33:27 +020082static int pkcs12_pbe_derive_key_iv( asn1_buf *pbe_params, md_type_t md_type,
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020083 const unsigned char *pwd, size_t pwdlen,
84 unsigned char *key, size_t keylen,
85 unsigned char *iv, size_t ivlen )
86{
87 int ret, iterations;
88 asn1_buf salt;
89 size_t i;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020090 unsigned char unipwd[258];
91
92 memset(&salt, 0, sizeof(asn1_buf));
93 memset(&unipwd, 0, sizeof(unipwd));
94
Paul Bakkerf8d018a2013-06-29 12:16:17 +020095 if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt, &iterations ) ) != 0 )
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020096 return( ret );
97
98 for(i = 0; i < pwdlen; i++)
99 unipwd[i * 2 + 1] = pwd[i];
100
101 if( ( ret = pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2,
Paul Bakker38b50d72013-06-24 19:33:27 +0200102 salt.p, salt.len, md_type,
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200103 PKCS12_DERIVE_KEY, iterations ) ) != 0 )
104 {
105 return( ret );
106 }
107
108 if( iv == NULL || ivlen == 0 )
109 return( 0 );
110
111 if( ( ret = pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2,
Paul Bakker38b50d72013-06-24 19:33:27 +0200112 salt.p, salt.len, md_type,
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200113 PKCS12_DERIVE_IV, iterations ) ) != 0 )
114 {
115 return( ret );
116 }
117 return( 0 );
118}
119
120int pkcs12_pbe_sha1_rc4_128( asn1_buf *pbe_params, int mode,
121 const unsigned char *pwd, size_t pwdlen,
122 const unsigned char *data, size_t len,
123 unsigned char *output )
124{
125#if !defined(POLARSSL_ARC4_C)
126 ((void) pbe_params);
127 ((void) mode);
128 ((void) pwd);
129 ((void) pwdlen);
130 ((void) data);
131 ((void) len);
132 ((void) output);
133 return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE );
134#else
135 int ret;
136 unsigned char key[16];
137 arc4_context ctx;
138 ((void) mode);
139
Paul Bakker38b50d72013-06-24 19:33:27 +0200140 if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, POLARSSL_MD_SHA1,
141 pwd, pwdlen,
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200142 key, 16, NULL, 0 ) ) != 0 )
143 {
144 return( ret );
145 }
146
147 arc4_setup( &ctx, key, 16 );
148 if( ( ret = arc4_crypt( &ctx, len, data, output ) ) != 0 )
149 return( ret );
150
151 return( 0 );
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200152#endif /* POLARSSL_ARC4_C */
Paul Bakker531e2942013-06-24 19:23:12 +0200153}
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200154
Paul Bakker38b50d72013-06-24 19:33:27 +0200155int pkcs12_pbe( asn1_buf *pbe_params, int mode,
156 cipher_type_t cipher_type, md_type_t md_type,
157 const unsigned char *pwd, size_t pwdlen,
158 const unsigned char *data, size_t len,
159 unsigned char *output )
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200160{
Paul Bakker38b50d72013-06-24 19:33:27 +0200161 int ret, keylen = 0;
162 unsigned char key[32];
163 unsigned char iv[16];
164 const cipher_info_t *cipher_info;
165 cipher_context_t cipher_ctx;
166 size_t olen = 0;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200167
Paul Bakker38b50d72013-06-24 19:33:27 +0200168 cipher_info = cipher_info_from_type( cipher_type );
169 if( cipher_info == NULL )
170 return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE );
171
172 keylen = cipher_info->key_length / 8;
173
174 if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen,
175 key, keylen,
176 iv, cipher_info->iv_size ) ) != 0 )
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200177 {
178 return( ret );
179 }
180
Paul Bakker38b50d72013-06-24 19:33:27 +0200181 if( ( ret = cipher_init_ctx( &cipher_ctx, cipher_info ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200182 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200183
Paul Bakker38b50d72013-06-24 19:33:27 +0200184 if( ( ret = cipher_setkey( &cipher_ctx, key, keylen, mode ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200185 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200186
Paul Bakker38b50d72013-06-24 19:33:27 +0200187 if( ( ret = cipher_reset( &cipher_ctx, iv ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200188 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200189
Paul Bakker38b50d72013-06-24 19:33:27 +0200190 if( ( ret = cipher_update( &cipher_ctx, data, len,
191 output, &olen ) ) != 0 )
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200192 {
Paul Bakkerbd552442013-07-03 14:44:40 +0200193 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200194 }
195
Paul Bakker38b50d72013-06-24 19:33:27 +0200196 if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200197 ret = POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200198
Paul Bakkerbd552442013-07-03 14:44:40 +0200199exit:
200 cipher_free_ctx( &cipher_ctx );
201
202 return( ret );
Paul Bakker531e2942013-06-24 19:23:12 +0200203}
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200204
205static void pkcs12_fill_buffer( unsigned char *data, size_t data_len,
206 const unsigned char *filler, size_t fill_len )
207{
208 unsigned char *p = data;
209 size_t use_len;
210
211 while( data_len > 0 )
212 {
213 use_len = ( data_len > fill_len ) ? fill_len : data_len;
214 memcpy( p, filler, use_len );
215 p += use_len;
216 data_len -= use_len;
217 }
218}
219
220int pkcs12_derivation( unsigned char *data, size_t datalen,
221 const unsigned char *pwd, size_t pwdlen,
222 const unsigned char *salt, size_t saltlen,
223 md_type_t md_type, int id, int iterations )
224{
225 int ret, i;
226 unsigned int j;
227
228 unsigned char diversifier[128];
229 unsigned char salt_block[128], pwd_block[128], hash_block[128];
230 unsigned char hash_output[POLARSSL_MD_MAX_SIZE];
231 unsigned char *p;
232 unsigned char c;
233
234 size_t hlen, use_len, v;
235
236 const md_info_t *md_info;
237 md_context_t md_ctx;
238
239 // This version only allows max of 64 bytes of password or salt
240 if( datalen > 128 || pwdlen > 64 || saltlen > 64 )
241 return( POLARSSL_ERR_PKCS12_BAD_INPUT_DATA );
242
243 md_info = md_info_from_type( md_type );
244 if( md_info == NULL )
245 return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE );
246
247 if ( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 )
248 return( ret );
249 hlen = md_get_size( md_info );
250
251 if( hlen <= 32 )
252 v = 64;
253 else
254 v = 128;
255
256 memset( diversifier, (unsigned char) id, v );
257
258 pkcs12_fill_buffer( salt_block, v, salt, saltlen );
259 pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen );
260
261 p = data;
262 while( datalen > 0 )
263 {
264 // Calculate hash( diversifier || salt_block || pwd_block )
265 if( ( ret = md_starts( &md_ctx ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200266 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200267
268 if( ( ret = md_update( &md_ctx, diversifier, v ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200269 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200270
271 if( ( ret = md_update( &md_ctx, salt_block, v ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200272 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200273
274 if( ( ret = md_update( &md_ctx, pwd_block, v ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200275 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200276
277 if( ( ret = md_finish( &md_ctx, hash_output ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200278 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200279
280 // Perform remaining ( iterations - 1 ) recursive hash calculations
281 for( i = 1; i < iterations; i++ )
282 {
283 if( ( ret = md( md_info, hash_output, hlen, hash_output ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200284 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200285 }
286
287 use_len = ( datalen > hlen ) ? hlen : datalen;
288 memcpy( p, hash_output, use_len );
289 datalen -= use_len;
290 p += use_len;
291
292 if( datalen == 0 )
293 break;
294
295 // Concatenating copies of hash_output into hash_block (B)
296 pkcs12_fill_buffer( hash_block, v, hash_output, hlen );
297
298 // B += 1
299 for( i = v; i > 0; i-- )
300 if( ++hash_block[i - 1] != 0 )
301 break;
302
303 // salt_block += B
304 c = 0;
305 for( i = v; i > 0; i-- )
306 {
307 j = salt_block[i - 1] + hash_block[i - 1] + c;
308 c = (unsigned char) (j >> 8);
309 salt_block[i - 1] = j & 0xFF;
310 }
311
312 // pwd_block += B
313 c = 0;
314 for( i = v; i > 0; i-- )
315 {
316 j = pwd_block[i - 1] + hash_block[i - 1] + c;
317 c = (unsigned char) (j >> 8);
318 pwd_block[i - 1] = j & 0xFF;
319 }
320 }
321
Paul Bakkerbd552442013-07-03 14:44:40 +0200322 ret = 0;
323
324exit:
325 md_free_ctx( &md_ctx );
326
327 return( ret );
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200328}
329
330#endif /* POLARSSL_PKCS12_C */