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