blob: f84fd52cdf61a13b5c8f0ae3d30100788d08fe0e [file] [log] [blame]
Paul Bakkerf1f21fe2013-06-24 19:17:19 +02001/*
2 * PKCS#12 Personal Information Exchange Syntax
3 *
Manuel Pégourié-Gonnarda658a402015-01-23 09:45:19 +00004 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
Paul Bakkerf1f21fe2013-06-24 19:17:19 +02005 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +00006 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakkerf1f21fe2013-06-24 19:17:19 +02007 *
Paul Bakkerf1f21fe2013-06-24 19:17:19 +02008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22/*
23 * The PKCS #12 Personal Information Exchange Syntax Standard v1.1
24 *
25 * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf
26 * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn
27 */
28
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020029#if !defined(POLARSSL_CONFIG_FILE)
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020030#include "polarssl/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020031#else
32#include POLARSSL_CONFIG_FILE
33#endif
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020034
35#if defined(POLARSSL_PKCS12_C)
36
37#include "polarssl/pkcs12.h"
38#include "polarssl/asn1.h"
Paul Bakker38b50d72013-06-24 19:33:27 +020039#include "polarssl/cipher.h"
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020040
Rich Evans00ab4702015-02-06 13:43:58 +000041#include <string.h>
42
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020043#if defined(POLARSSL_ARC4_C)
44#include "polarssl/arc4.h"
45#endif
46
47#if defined(POLARSSL_DES_C)
48#include "polarssl/des.h"
49#endif
50
Paul Bakker91c301a2014-06-18 13:59:38 +020051/* Implementation that should never be optimized out by the compiler */
52static void polarssl_zeroize( void *v, size_t n ) {
53 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
54}
55
Paul Bakkerf8d018a2013-06-29 12:16:17 +020056static int pkcs12_parse_pbe_params( asn1_buf *params,
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020057 asn1_buf *salt, int *iterations )
58{
59 int ret;
Paul Bakkerf8d018a2013-06-29 12:16:17 +020060 unsigned char **p = &params->p;
61 const unsigned char *end = params->p + params->len;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020062
63 /*
64 * pkcs-12PbeParams ::= SEQUENCE {
65 * salt OCTET STRING,
66 * iterations INTEGER
67 * }
68 *
69 */
Paul Bakkerf8d018a2013-06-29 12:16:17 +020070 if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) )
71 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT +
72 POLARSSL_ERR_ASN1_UNEXPECTED_TAG );
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020073
74 if( ( ret = asn1_get_tag( p, end, &salt->len, ASN1_OCTET_STRING ) ) != 0 )
75 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret );
76
77 salt->p = *p;
78 *p += salt->len;
79
80 if( ( ret = asn1_get_int( p, end, iterations ) ) != 0 )
81 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret );
82
83 if( *p != end )
84 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT +
85 POLARSSL_ERR_ASN1_LENGTH_MISMATCH );
86
87 return( 0 );
88}
89
Paul Bakker38b50d72013-06-24 19:33:27 +020090static int pkcs12_pbe_derive_key_iv( asn1_buf *pbe_params, md_type_t md_type,
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020091 const unsigned char *pwd, size_t pwdlen,
92 unsigned char *key, size_t keylen,
93 unsigned char *iv, size_t ivlen )
94{
95 int ret, iterations;
96 asn1_buf salt;
97 size_t i;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +020098 unsigned char unipwd[258];
99
Paul Bakker66d5d072014-06-17 16:39:18 +0200100 memset( &salt, 0, sizeof(asn1_buf) );
101 memset( &unipwd, 0, sizeof(unipwd) );
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200102
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200103 if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt,
104 &iterations ) ) != 0 )
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200105 return( ret );
106
Paul Bakker66d5d072014-06-17 16:39:18 +0200107 for( i = 0; i < pwdlen; i++ )
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200108 unipwd[i * 2 + 1] = pwd[i];
109
110 if( ( ret = pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2,
Paul Bakker38b50d72013-06-24 19:33:27 +0200111 salt.p, salt.len, md_type,
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200112 PKCS12_DERIVE_KEY, iterations ) ) != 0 )
113 {
114 return( ret );
115 }
116
117 if( iv == NULL || ivlen == 0 )
118 return( 0 );
119
120 if( ( ret = pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2,
Paul Bakker38b50d72013-06-24 19:33:27 +0200121 salt.p, salt.len, md_type,
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200122 PKCS12_DERIVE_IV, iterations ) ) != 0 )
123 {
124 return( ret );
125 }
126 return( 0 );
127}
128
129int pkcs12_pbe_sha1_rc4_128( asn1_buf *pbe_params, int mode,
130 const unsigned char *pwd, size_t pwdlen,
131 const unsigned char *data, size_t len,
132 unsigned char *output )
133{
134#if !defined(POLARSSL_ARC4_C)
135 ((void) pbe_params);
136 ((void) mode);
137 ((void) pwd);
138 ((void) pwdlen);
139 ((void) data);
140 ((void) len);
141 ((void) output);
142 return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE );
143#else
144 int ret;
145 unsigned char key[16];
146 arc4_context ctx;
147 ((void) mode);
148
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200149 arc4_init( &ctx );
150
Paul Bakker38b50d72013-06-24 19:33:27 +0200151 if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, POLARSSL_MD_SHA1,
152 pwd, pwdlen,
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200153 key, 16, NULL, 0 ) ) != 0 )
154 {
155 return( ret );
156 }
157
158 arc4_setup( &ctx, key, 16 );
159 if( ( ret = arc4_crypt( &ctx, len, data, output ) ) != 0 )
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200160 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200161
Paul Bakkerc7ea99a2014-06-18 11:12:03 +0200162exit:
163 polarssl_zeroize( key, sizeof( key ) );
164 arc4_free( &ctx );
165
166 return( ret );
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200167#endif /* POLARSSL_ARC4_C */
Paul Bakker531e2942013-06-24 19:23:12 +0200168}
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200169
Paul Bakker38b50d72013-06-24 19:33:27 +0200170int pkcs12_pbe( asn1_buf *pbe_params, int mode,
171 cipher_type_t cipher_type, md_type_t md_type,
172 const unsigned char *pwd, size_t pwdlen,
173 const unsigned char *data, size_t len,
174 unsigned char *output )
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200175{
Paul Bakker38b50d72013-06-24 19:33:27 +0200176 int ret, keylen = 0;
177 unsigned char key[32];
178 unsigned char iv[16];
179 const cipher_info_t *cipher_info;
180 cipher_context_t cipher_ctx;
181 size_t olen = 0;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200182
Paul Bakker38b50d72013-06-24 19:33:27 +0200183 cipher_info = cipher_info_from_type( cipher_type );
184 if( cipher_info == NULL )
185 return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE );
186
187 keylen = cipher_info->key_length / 8;
188
189 if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen,
190 key, keylen,
191 iv, cipher_info->iv_size ) ) != 0 )
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200192 {
193 return( ret );
194 }
195
Paul Bakker84bbeb52014-07-01 14:53:22 +0200196 cipher_init( &cipher_ctx );
197
Paul Bakker38b50d72013-06-24 19:33:27 +0200198 if( ( ret = cipher_init_ctx( &cipher_ctx, cipher_info ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200199 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200200
Manuel Pégourié-Gonnarda2733712015-02-10 17:32:14 +0100201 if( ( ret = cipher_setkey( &cipher_ctx, key, 8 * keylen, (operation_t) mode ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200202 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200203
Manuel Pégourié-Gonnarda235b5b2013-09-03 13:25:52 +0200204 if( ( ret = cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 )
Manuel Pégourié-Gonnard9c853b92013-09-03 13:04:44 +0200205 goto exit;
206
Manuel Pégourié-Gonnard2adc40c2013-09-03 13:54:12 +0200207 if( ( ret = cipher_reset( &cipher_ctx ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200208 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200209
Paul Bakker38b50d72013-06-24 19:33:27 +0200210 if( ( ret = cipher_update( &cipher_ctx, data, len,
211 output, &olen ) ) != 0 )
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200212 {
Paul Bakkerbd552442013-07-03 14:44:40 +0200213 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200214 }
215
Manuel Pégourié-Gonnardaa9ffc52013-09-03 16:19:22 +0200216 if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200217 ret = POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200218
Paul Bakkerbd552442013-07-03 14:44:40 +0200219exit:
Paul Bakker91c301a2014-06-18 13:59:38 +0200220 polarssl_zeroize( key, sizeof( key ) );
221 polarssl_zeroize( iv, sizeof( iv ) );
Paul Bakker84bbeb52014-07-01 14:53:22 +0200222 cipher_free( &cipher_ctx );
Paul Bakkerbd552442013-07-03 14:44:40 +0200223
224 return( ret );
Paul Bakker531e2942013-06-24 19:23:12 +0200225}
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200226
227static void pkcs12_fill_buffer( unsigned char *data, size_t data_len,
228 const unsigned char *filler, size_t fill_len )
229{
230 unsigned char *p = data;
231 size_t use_len;
232
233 while( data_len > 0 )
234 {
235 use_len = ( data_len > fill_len ) ? fill_len : data_len;
236 memcpy( p, filler, use_len );
237 p += use_len;
238 data_len -= use_len;
239 }
240}
241
242int pkcs12_derivation( unsigned char *data, size_t datalen,
243 const unsigned char *pwd, size_t pwdlen,
244 const unsigned char *salt, size_t saltlen,
245 md_type_t md_type, int id, int iterations )
246{
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200247 int ret;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200248 unsigned int j;
249
250 unsigned char diversifier[128];
251 unsigned char salt_block[128], pwd_block[128], hash_block[128];
252 unsigned char hash_output[POLARSSL_MD_MAX_SIZE];
253 unsigned char *p;
254 unsigned char c;
255
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200256 size_t hlen, use_len, v, i;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200257
258 const md_info_t *md_info;
259 md_context_t md_ctx;
260
261 // This version only allows max of 64 bytes of password or salt
262 if( datalen > 128 || pwdlen > 64 || saltlen > 64 )
263 return( POLARSSL_ERR_PKCS12_BAD_INPUT_DATA );
264
265 md_info = md_info_from_type( md_type );
266 if( md_info == NULL )
267 return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE );
268
Paul Bakker84bbeb52014-07-01 14:53:22 +0200269 md_init( &md_ctx );
270
Paul Bakker66d5d072014-06-17 16:39:18 +0200271 if( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 )
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200272 return( ret );
273 hlen = md_get_size( md_info );
274
275 if( hlen <= 32 )
276 v = 64;
277 else
278 v = 128;
279
280 memset( diversifier, (unsigned char) id, v );
281
282 pkcs12_fill_buffer( salt_block, v, salt, saltlen );
283 pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen );
284
285 p = data;
286 while( datalen > 0 )
287 {
288 // Calculate hash( diversifier || salt_block || pwd_block )
289 if( ( ret = md_starts( &md_ctx ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200290 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200291
292 if( ( ret = md_update( &md_ctx, diversifier, v ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200293 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200294
295 if( ( ret = md_update( &md_ctx, salt_block, v ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200296 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200297
298 if( ( ret = md_update( &md_ctx, pwd_block, v ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200299 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200300
301 if( ( ret = md_finish( &md_ctx, hash_output ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200302 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200303
304 // Perform remaining ( iterations - 1 ) recursive hash calculations
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200305 for( i = 1; i < (size_t) iterations; i++ )
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200306 {
307 if( ( ret = md( md_info, hash_output, hlen, hash_output ) ) != 0 )
Paul Bakkerbd552442013-07-03 14:44:40 +0200308 goto exit;
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200309 }
310
311 use_len = ( datalen > hlen ) ? hlen : datalen;
312 memcpy( p, hash_output, use_len );
313 datalen -= use_len;
314 p += use_len;
315
316 if( datalen == 0 )
317 break;
318
319 // Concatenating copies of hash_output into hash_block (B)
320 pkcs12_fill_buffer( hash_block, v, hash_output, hlen );
321
322 // B += 1
323 for( i = v; i > 0; i-- )
324 if( ++hash_block[i - 1] != 0 )
325 break;
326
327 // salt_block += B
328 c = 0;
329 for( i = v; i > 0; i-- )
330 {
331 j = salt_block[i - 1] + hash_block[i - 1] + c;
332 c = (unsigned char) (j >> 8);
333 salt_block[i - 1] = j & 0xFF;
334 }
335
336 // pwd_block += B
337 c = 0;
338 for( i = v; i > 0; i-- )
339 {
340 j = pwd_block[i - 1] + hash_block[i - 1] + c;
341 c = (unsigned char) (j >> 8);
342 pwd_block[i - 1] = j & 0xFF;
343 }
344 }
345
Paul Bakkerbd552442013-07-03 14:44:40 +0200346 ret = 0;
347
348exit:
Paul Bakker91c301a2014-06-18 13:59:38 +0200349 polarssl_zeroize( salt_block, sizeof( salt_block ) );
350 polarssl_zeroize( pwd_block, sizeof( pwd_block ) );
351 polarssl_zeroize( hash_block, sizeof( hash_block ) );
352 polarssl_zeroize( hash_output, sizeof( hash_output ) );
353
Paul Bakker84bbeb52014-07-01 14:53:22 +0200354 md_free( &md_ctx );
Paul Bakkerbd552442013-07-03 14:44:40 +0200355
356 return( ret );
Paul Bakkerf1f21fe2013-06-24 19:17:19 +0200357}
358
359#endif /* POLARSSL_PKCS12_C */