2 * PKCS#12 Personal Information Exchange Syntax
4 * Copyright (C) 2006-2014, Brainspark B.V.
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
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.
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.
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.
26 * The PKCS #12 Personal Information Exchange Syntax Standard v1.1
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
32 #if !defined(POLARSSL_CONFIG_FILE)
35 #include POLARSSL_CONFIG_FILE
38 #if defined(POLARSSL_PKCS12_C)
44 #if defined(POLARSSL_ARC4_C)
48 #if defined(POLARSSL_DES_C)
52 static int pkcs12_parse_pbe_params( asn1_buf
*params
,
53 asn1_buf
*salt
, int *iterations
)
56 unsigned char **p
= ¶ms
->p
;
57 const unsigned char *end
= params
->p
+ params
->len
;
60 * pkcs-12PbeParams ::= SEQUENCE {
66 if( params
->tag
!= ( ASN1_CONSTRUCTED
| ASN1_SEQUENCE
) )
67 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT
+
68 POLARSSL_ERR_ASN1_UNEXPECTED_TAG
);
70 if( ( ret
= asn1_get_tag( p
, end
, &salt
->len
, ASN1_OCTET_STRING
) ) != 0 )
71 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT
+ ret
);
76 if( ( ret
= asn1_get_int( p
, end
, iterations
) ) != 0 )
77 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT
+ ret
);
80 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT
+
81 POLARSSL_ERR_ASN1_LENGTH_MISMATCH
);
86 static int pkcs12_pbe_derive_key_iv( asn1_buf
*pbe_params
, md_type_t md_type
,
87 const unsigned char *pwd
, size_t pwdlen
,
88 unsigned char *key
, size_t keylen
,
89 unsigned char *iv
, size_t ivlen
)
94 unsigned char unipwd
[258];
96 memset(&salt
, 0, sizeof(asn1_buf
));
97 memset(&unipwd
, 0, sizeof(unipwd
));
99 if( ( ret
= pkcs12_parse_pbe_params( pbe_params
, &salt
,
100 &iterations
) ) != 0 )
103 for(i
= 0; i
< pwdlen
; i
++)
104 unipwd
[i
* 2 + 1] = pwd
[i
];
106 if( ( ret
= pkcs12_derivation( key
, keylen
, unipwd
, pwdlen
* 2 + 2,
107 salt
.p
, salt
.len
, md_type
,
108 PKCS12_DERIVE_KEY
, iterations
) ) != 0 )
113 if( iv
== NULL
|| ivlen
== 0 )
116 if( ( ret
= pkcs12_derivation( iv
, ivlen
, unipwd
, pwdlen
* 2 + 2,
117 salt
.p
, salt
.len
, md_type
,
118 PKCS12_DERIVE_IV
, iterations
) ) != 0 )
125 int pkcs12_pbe_sha1_rc4_128( asn1_buf
*pbe_params
, int mode
,
126 const unsigned char *pwd
, size_t pwdlen
,
127 const unsigned char *data
, size_t len
,
128 unsigned char *output
)
130 #if !defined(POLARSSL_ARC4_C)
138 return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE
);
141 unsigned char key
[16];
145 if( ( ret
= pkcs12_pbe_derive_key_iv( pbe_params
, POLARSSL_MD_SHA1
,
147 key
, 16, NULL
, 0 ) ) != 0 )
152 arc4_setup( &ctx
, key
, 16 );
153 if( ( ret
= arc4_crypt( &ctx
, len
, data
, output
) ) != 0 )
157 #endif /* POLARSSL_ARC4_C */
160 int pkcs12_pbe( asn1_buf
*pbe_params
, int mode
,
161 cipher_type_t cipher_type
, md_type_t md_type
,
162 const unsigned char *pwd
, size_t pwdlen
,
163 const unsigned char *data
, size_t len
,
164 unsigned char *output
)
167 unsigned char key
[32];
168 unsigned char iv
[16];
169 const cipher_info_t
*cipher_info
;
170 cipher_context_t cipher_ctx
;
173 cipher_info
= cipher_info_from_type( cipher_type
);
174 if( cipher_info
== NULL
)
175 return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE
);
177 keylen
= cipher_info
->key_length
/ 8;
179 if( ( ret
= pkcs12_pbe_derive_key_iv( pbe_params
, md_type
, pwd
, pwdlen
,
181 iv
, cipher_info
->iv_size
) ) != 0 )
186 if( ( ret
= cipher_init_ctx( &cipher_ctx
, cipher_info
) ) != 0 )
189 if( ( ret
= cipher_setkey( &cipher_ctx
, key
, 8 * keylen
, mode
) ) != 0 )
192 if( ( ret
= cipher_set_iv( &cipher_ctx
, iv
, cipher_info
->iv_size
) ) != 0 )
195 if( ( ret
= cipher_reset( &cipher_ctx
) ) != 0 )
198 if( ( ret
= cipher_update( &cipher_ctx
, data
, len
,
199 output
, &olen
) ) != 0 )
204 if( ( ret
= cipher_finish( &cipher_ctx
, output
+ olen
, &olen
) ) != 0 )
205 ret
= POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH
;
208 cipher_free_ctx( &cipher_ctx
);
213 static void pkcs12_fill_buffer( unsigned char *data
, size_t data_len
,
214 const unsigned char *filler
, size_t fill_len
)
216 unsigned char *p
= data
;
219 while( data_len
> 0 )
221 use_len
= ( data_len
> fill_len
) ? fill_len
: data_len
;
222 memcpy( p
, filler
, use_len
);
228 int pkcs12_derivation( unsigned char *data
, size_t datalen
,
229 const unsigned char *pwd
, size_t pwdlen
,
230 const unsigned char *salt
, size_t saltlen
,
231 md_type_t md_type
, int id
, int iterations
)
236 unsigned char diversifier
[128];
237 unsigned char salt_block
[128], pwd_block
[128], hash_block
[128];
238 unsigned char hash_output
[POLARSSL_MD_MAX_SIZE
];
242 size_t hlen
, use_len
, v
, i
;
244 const md_info_t
*md_info
;
247 // This version only allows max of 64 bytes of password or salt
248 if( datalen
> 128 || pwdlen
> 64 || saltlen
> 64 )
249 return( POLARSSL_ERR_PKCS12_BAD_INPUT_DATA
);
251 md_info
= md_info_from_type( md_type
);
252 if( md_info
== NULL
)
253 return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE
);
255 if ( ( ret
= md_init_ctx( &md_ctx
, md_info
) ) != 0 )
257 hlen
= md_get_size( md_info
);
264 memset( diversifier
, (unsigned char) id
, v
);
266 pkcs12_fill_buffer( salt_block
, v
, salt
, saltlen
);
267 pkcs12_fill_buffer( pwd_block
, v
, pwd
, pwdlen
);
272 // Calculate hash( diversifier || salt_block || pwd_block )
273 if( ( ret
= md_starts( &md_ctx
) ) != 0 )
276 if( ( ret
= md_update( &md_ctx
, diversifier
, v
) ) != 0 )
279 if( ( ret
= md_update( &md_ctx
, salt_block
, v
) ) != 0 )
282 if( ( ret
= md_update( &md_ctx
, pwd_block
, v
) ) != 0 )
285 if( ( ret
= md_finish( &md_ctx
, hash_output
) ) != 0 )
288 // Perform remaining ( iterations - 1 ) recursive hash calculations
289 for( i
= 1; i
< (size_t) iterations
; i
++ )
291 if( ( ret
= md( md_info
, hash_output
, hlen
, hash_output
) ) != 0 )
295 use_len
= ( datalen
> hlen
) ? hlen
: datalen
;
296 memcpy( p
, hash_output
, use_len
);
303 // Concatenating copies of hash_output into hash_block (B)
304 pkcs12_fill_buffer( hash_block
, v
, hash_output
, hlen
);
307 for( i
= v
; i
> 0; i
-- )
308 if( ++hash_block
[i
- 1] != 0 )
313 for( i
= v
; i
> 0; i
-- )
315 j
= salt_block
[i
- 1] + hash_block
[i
- 1] + c
;
316 c
= (unsigned char) (j
>> 8);
317 salt_block
[i
- 1] = j
& 0xFF;
322 for( i
= v
; i
> 0; i
-- )
324 j
= pwd_block
[i
- 1] + hash_block
[i
- 1] + c
;
325 c
= (unsigned char) (j
>> 8);
326 pwd_block
[i
- 1] = j
& 0xFF;
333 md_free_ctx( &md_ctx
);
338 #endif /* POLARSSL_PKCS12_C */