Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
pkcs12.c
00001 /* 00002 * PKCS#12 Personal Information Exchange Syntax 00003 * 00004 * Copyright (C) 2006-2014, Brainspark B.V. 00005 * 00006 * This file is part of PolarSSL (http://www.polarssl.org) 00007 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> 00008 * 00009 * All rights reserved. 00010 * 00011 * This program is free software; you can redistribute it and/or modify 00012 * it under the terms of the GNU General Public License as published by 00013 * the Free Software Foundation; either version 2 of the License, or 00014 * (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License along 00022 * with this program; if not, write to the Free Software Foundation, Inc., 00023 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00024 */ 00025 /* 00026 * The PKCS #12 Personal Information Exchange Syntax Standard v1.1 00027 * 00028 * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf 00029 * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn 00030 */ 00031 00032 #if !defined(POLARSSL_CONFIG_FILE) 00033 #include "polarssl/config.h" 00034 #else 00035 #include POLARSSL_CONFIG_FILE 00036 #endif 00037 00038 #if defined(POLARSSL_PKCS12_C) 00039 00040 #include "polarssl/pkcs12.h" 00041 #include "polarssl/asn1.h" 00042 #include "polarssl/cipher.h" 00043 00044 #if defined(POLARSSL_ARC4_C) 00045 #include "polarssl/arc4.h" 00046 #endif 00047 00048 #if defined(POLARSSL_DES_C) 00049 #include "polarssl/des.h" 00050 #endif 00051 00052 static int pkcs12_parse_pbe_params( asn1_buf *params, 00053 asn1_buf *salt, int *iterations ) 00054 { 00055 int ret; 00056 unsigned char **p = ¶ms->p; 00057 const unsigned char *end = params->p + params->len; 00058 00059 /* 00060 * pkcs-12PbeParams ::= SEQUENCE { 00061 * salt OCTET STRING, 00062 * iterations INTEGER 00063 * } 00064 * 00065 */ 00066 if( params->tag != ( ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) 00067 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + 00068 POLARSSL_ERR_ASN1_UNEXPECTED_TAG ); 00069 00070 if( ( ret = asn1_get_tag( p, end, &salt->len, ASN1_OCTET_STRING ) ) != 0 ) 00071 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); 00072 00073 salt->p = *p; 00074 *p += salt->len; 00075 00076 if( ( ret = asn1_get_int( p, end, iterations ) ) != 0 ) 00077 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); 00078 00079 if( *p != end ) 00080 return( POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT + 00081 POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); 00082 00083 return( 0 ); 00084 } 00085 00086 static int pkcs12_pbe_derive_key_iv( asn1_buf *pbe_params, md_type_t md_type, 00087 const unsigned char *pwd, size_t pwdlen, 00088 unsigned char *key, size_t keylen, 00089 unsigned char *iv, size_t ivlen ) 00090 { 00091 int ret, iterations; 00092 asn1_buf salt; 00093 size_t i; 00094 unsigned char unipwd[258]; 00095 00096 memset(&salt, 0, sizeof(asn1_buf)); 00097 memset(&unipwd, 0, sizeof(unipwd)); 00098 00099 if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt, 00100 &iterations ) ) != 0 ) 00101 return( ret ); 00102 00103 for(i = 0; i < pwdlen; i++) 00104 unipwd[i * 2 + 1] = pwd[i]; 00105 00106 if( ( ret = pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2, 00107 salt.p, salt.len, md_type, 00108 PKCS12_DERIVE_KEY, iterations ) ) != 0 ) 00109 { 00110 return( ret ); 00111 } 00112 00113 if( iv == NULL || ivlen == 0 ) 00114 return( 0 ); 00115 00116 if( ( ret = pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2, 00117 salt.p, salt.len, md_type, 00118 PKCS12_DERIVE_IV, iterations ) ) != 0 ) 00119 { 00120 return( ret ); 00121 } 00122 return( 0 ); 00123 } 00124 00125 int pkcs12_pbe_sha1_rc4_128( asn1_buf *pbe_params, int mode, 00126 const unsigned char *pwd, size_t pwdlen, 00127 const unsigned char *data, size_t len, 00128 unsigned char *output ) 00129 { 00130 #if !defined(POLARSSL_ARC4_C) 00131 ((void) pbe_params); 00132 ((void) mode); 00133 ((void) pwd); 00134 ((void) pwdlen); 00135 ((void) data); 00136 ((void) len); 00137 ((void) output); 00138 return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE ); 00139 #else 00140 int ret; 00141 unsigned char key[16]; 00142 arc4_context ctx; 00143 ((void) mode); 00144 00145 if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, POLARSSL_MD_SHA1, 00146 pwd, pwdlen, 00147 key, 16, NULL, 0 ) ) != 0 ) 00148 { 00149 return( ret ); 00150 } 00151 00152 arc4_setup( &ctx, key, 16 ); 00153 if( ( ret = arc4_crypt( &ctx, len, data, output ) ) != 0 ) 00154 return( ret ); 00155 00156 return( 0 ); 00157 #endif /* POLARSSL_ARC4_C */ 00158 } 00159 00160 int pkcs12_pbe( asn1_buf *pbe_params, int mode, 00161 cipher_type_t cipher_type, md_type_t md_type, 00162 const unsigned char *pwd, size_t pwdlen, 00163 const unsigned char *data, size_t len, 00164 unsigned char *output ) 00165 { 00166 int ret, keylen = 0; 00167 unsigned char key[32]; 00168 unsigned char iv[16]; 00169 const cipher_info_t *cipher_info; 00170 cipher_context_t cipher_ctx; 00171 size_t olen = 0; 00172 00173 cipher_info = cipher_info_from_type( cipher_type ); 00174 if( cipher_info == NULL ) 00175 return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE ); 00176 00177 keylen = cipher_info->key_length / 8; 00178 00179 if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen, 00180 key, keylen, 00181 iv, cipher_info->iv_size ) ) != 0 ) 00182 { 00183 return( ret ); 00184 } 00185 00186 if( ( ret = cipher_init_ctx( &cipher_ctx, cipher_info ) ) != 0 ) 00187 goto exit; 00188 00189 if( ( ret = cipher_setkey( &cipher_ctx, key, 8 * keylen, mode ) ) != 0 ) 00190 goto exit; 00191 00192 if( ( ret = cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 ) 00193 goto exit; 00194 00195 if( ( ret = cipher_reset( &cipher_ctx ) ) != 0 ) 00196 goto exit; 00197 00198 if( ( ret = cipher_update( &cipher_ctx, data, len, 00199 output, &olen ) ) != 0 ) 00200 { 00201 goto exit; 00202 } 00203 00204 if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) 00205 ret = POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH; 00206 00207 exit: 00208 cipher_free_ctx( &cipher_ctx ); 00209 00210 return( ret ); 00211 } 00212 00213 static void pkcs12_fill_buffer( unsigned char *data, size_t data_len, 00214 const unsigned char *filler, size_t fill_len ) 00215 { 00216 unsigned char *p = data; 00217 size_t use_len; 00218 00219 while( data_len > 0 ) 00220 { 00221 use_len = ( data_len > fill_len ) ? fill_len : data_len; 00222 memcpy( p, filler, use_len ); 00223 p += use_len; 00224 data_len -= use_len; 00225 } 00226 } 00227 00228 int pkcs12_derivation( unsigned char *data, size_t datalen, 00229 const unsigned char *pwd, size_t pwdlen, 00230 const unsigned char *salt, size_t saltlen, 00231 md_type_t md_type, int id, int iterations ) 00232 { 00233 int ret; 00234 unsigned int j; 00235 00236 unsigned char diversifier[128]; 00237 unsigned char salt_block[128], pwd_block[128], hash_block[128]; 00238 unsigned char hash_output[POLARSSL_MD_MAX_SIZE]; 00239 unsigned char *p; 00240 unsigned char c; 00241 00242 size_t hlen, use_len, v, i; 00243 00244 const md_info_t *md_info; 00245 md_context_t md_ctx; 00246 00247 // This version only allows max of 64 bytes of password or salt 00248 if( datalen > 128 || pwdlen > 64 || saltlen > 64 ) 00249 return( POLARSSL_ERR_PKCS12_BAD_INPUT_DATA ); 00250 00251 md_info = md_info_from_type( md_type ); 00252 if( md_info == NULL ) 00253 return( POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE ); 00254 00255 if ( ( ret = md_init_ctx( &md_ctx, md_info ) ) != 0 ) 00256 return( ret ); 00257 hlen = md_get_size( md_info ); 00258 00259 if( hlen <= 32 ) 00260 v = 64; 00261 else 00262 v = 128; 00263 00264 memset( diversifier, (unsigned char) id, v ); 00265 00266 pkcs12_fill_buffer( salt_block, v, salt, saltlen ); 00267 pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen ); 00268 00269 p = data; 00270 while( datalen > 0 ) 00271 { 00272 // Calculate hash( diversifier || salt_block || pwd_block ) 00273 if( ( ret = md_starts( &md_ctx ) ) != 0 ) 00274 goto exit; 00275 00276 if( ( ret = md_update( &md_ctx, diversifier, v ) ) != 0 ) 00277 goto exit; 00278 00279 if( ( ret = md_update( &md_ctx, salt_block, v ) ) != 0 ) 00280 goto exit; 00281 00282 if( ( ret = md_update( &md_ctx, pwd_block, v ) ) != 0 ) 00283 goto exit; 00284 00285 if( ( ret = md_finish( &md_ctx, hash_output ) ) != 0 ) 00286 goto exit; 00287 00288 // Perform remaining ( iterations - 1 ) recursive hash calculations 00289 for( i = 1; i < (size_t) iterations; i++ ) 00290 { 00291 if( ( ret = md( md_info, hash_output, hlen, hash_output ) ) != 0 ) 00292 goto exit; 00293 } 00294 00295 use_len = ( datalen > hlen ) ? hlen : datalen; 00296 memcpy( p, hash_output, use_len ); 00297 datalen -= use_len; 00298 p += use_len; 00299 00300 if( datalen == 0 ) 00301 break; 00302 00303 // Concatenating copies of hash_output into hash_block (B) 00304 pkcs12_fill_buffer( hash_block, v, hash_output, hlen ); 00305 00306 // B += 1 00307 for( i = v; i > 0; i-- ) 00308 if( ++hash_block[i - 1] != 0 ) 00309 break; 00310 00311 // salt_block += B 00312 c = 0; 00313 for( i = v; i > 0; i-- ) 00314 { 00315 j = salt_block[i - 1] + hash_block[i - 1] + c; 00316 c = (unsigned char) (j >> 8); 00317 salt_block[i - 1] = j & 0xFF; 00318 } 00319 00320 // pwd_block += B 00321 c = 0; 00322 for( i = v; i > 0; i-- ) 00323 { 00324 j = pwd_block[i - 1] + hash_block[i - 1] + c; 00325 c = (unsigned char) (j >> 8); 00326 pwd_block[i - 1] = j & 0xFF; 00327 } 00328 } 00329 00330 ret = 0; 00331 00332 exit: 00333 md_free_ctx( &md_ctx ); 00334 00335 return( ret ); 00336 } 00337 00338 #endif /* POLARSSL_PKCS12_C */ 00339 00340
Generated on Tue Jul 12 2022 19:40:20 by
1.7.2