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.
Fork of mbedtls by
pkcs12.c
00001 /* 00002 * PKCS#12 Personal Information Exchange Syntax 00003 * 00004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 00005 * SPDX-License-Identifier: Apache-2.0 00006 * 00007 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00008 * not use this file except in compliance with the License. 00009 * You may obtain a copy of the License at 00010 * 00011 * http://www.apache.org/licenses/LICENSE-2.0 00012 * 00013 * Unless required by applicable law or agreed to in writing, software 00014 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00015 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00016 * See the License for the specific language governing permissions and 00017 * limitations under the License. 00018 * 00019 * This file is part of mbed TLS (https://tls.mbed.org) 00020 */ 00021 /* 00022 * The PKCS #12 Personal Information Exchange Syntax Standard v1.1 00023 * 00024 * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf 00025 * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn 00026 */ 00027 00028 #if !defined(MBEDTLS_CONFIG_FILE) 00029 #include "mbedtls/config.h" 00030 #else 00031 #include MBEDTLS_CONFIG_FILE 00032 #endif 00033 00034 #if defined(MBEDTLS_PKCS12_C) 00035 00036 #include "mbedtls/pkcs12.h" 00037 #include "mbedtls/asn1.h" 00038 #include "mbedtls/cipher.h" 00039 00040 #include <string.h> 00041 00042 #if defined(MBEDTLS_ARC4_C) 00043 #include "mbedtls/arc4.h" 00044 #endif 00045 00046 #if defined(MBEDTLS_DES_C) 00047 #include "mbedtls/des.h" 00048 #endif 00049 00050 /* Implementation that should never be optimized out by the compiler */ 00051 static void mbedtls_zeroize( void *v, size_t n ) { 00052 volatile unsigned char *p = v; while( n-- ) *p++ = 0; 00053 } 00054 00055 static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params, 00056 mbedtls_asn1_buf *salt, int *iterations ) 00057 { 00058 int ret; 00059 unsigned char **p = ¶ms->p; 00060 const unsigned char *end = params->p + params->len; 00061 00062 /* 00063 * pkcs-12PbeParams ::= SEQUENCE { 00064 * salt OCTET STRING, 00065 * iterations INTEGER 00066 * } 00067 * 00068 */ 00069 if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) 00070 return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + 00071 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); 00072 00073 if( ( ret = mbedtls_asn1_get_tag( p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) 00074 return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); 00075 00076 salt->p = *p; 00077 *p += salt->len; 00078 00079 if( ( ret = mbedtls_asn1_get_int( p, end, iterations ) ) != 0 ) 00080 return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); 00081 00082 if( *p != end ) 00083 return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + 00084 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 00085 00086 return( 0 ); 00087 } 00088 00089 #define PKCS12_MAX_PWDLEN 128 00090 00091 static int pkcs12_pbe_derive_key_iv( mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type, 00092 const unsigned char *pwd, size_t pwdlen, 00093 unsigned char *key, size_t keylen, 00094 unsigned char *iv, size_t ivlen ) 00095 { 00096 int ret, iterations = 0; 00097 mbedtls_asn1_buf salt; 00098 size_t i; 00099 unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2]; 00100 00101 if( pwdlen > PKCS12_MAX_PWDLEN ) 00102 return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); 00103 00104 memset( &salt, 0, sizeof(mbedtls_asn1_buf) ); 00105 memset( &unipwd, 0, sizeof(unipwd) ); 00106 00107 if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt, 00108 &iterations ) ) != 0 ) 00109 return( ret ); 00110 00111 for( i = 0; i < pwdlen; i++ ) 00112 unipwd[i * 2 + 1] = pwd[i]; 00113 00114 if( ( ret = mbedtls_pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2, 00115 salt.p, salt.len, md_type, 00116 MBEDTLS_PKCS12_DERIVE_KEY, iterations ) ) != 0 ) 00117 { 00118 return( ret ); 00119 } 00120 00121 if( iv == NULL || ivlen == 0 ) 00122 return( 0 ); 00123 00124 if( ( ret = mbedtls_pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2, 00125 salt.p, salt.len, md_type, 00126 MBEDTLS_PKCS12_DERIVE_IV, iterations ) ) != 0 ) 00127 { 00128 return( ret ); 00129 } 00130 return( 0 ); 00131 } 00132 00133 #undef PKCS12_MAX_PWDLEN 00134 00135 int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, 00136 const unsigned char *pwd, size_t pwdlen, 00137 const unsigned char *data, size_t len, 00138 unsigned char *output ) 00139 { 00140 #if !defined(MBEDTLS_ARC4_C) 00141 ((void) pbe_params); 00142 ((void) mode); 00143 ((void) pwd); 00144 ((void) pwdlen); 00145 ((void) data); 00146 ((void) len); 00147 ((void) output); 00148 return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); 00149 #else 00150 int ret; 00151 unsigned char key[16]; 00152 mbedtls_arc4_context ctx; 00153 ((void) mode); 00154 00155 mbedtls_arc4_init( &ctx ); 00156 00157 if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, MBEDTLS_MD_SHA1, 00158 pwd, pwdlen, 00159 key, 16, NULL, 0 ) ) != 0 ) 00160 { 00161 return( ret ); 00162 } 00163 00164 mbedtls_arc4_setup( &ctx, key, 16 ); 00165 if( ( ret = mbedtls_arc4_crypt( &ctx, len, data, output ) ) != 0 ) 00166 goto exit; 00167 00168 exit: 00169 mbedtls_zeroize( key, sizeof( key ) ); 00170 mbedtls_arc4_free( &ctx ); 00171 00172 return( ret ); 00173 #endif /* MBEDTLS_ARC4_C */ 00174 } 00175 00176 int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, 00177 mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, 00178 const unsigned char *pwd, size_t pwdlen, 00179 const unsigned char *data, size_t len, 00180 unsigned char *output ) 00181 { 00182 int ret, keylen = 0; 00183 unsigned char key[32]; 00184 unsigned char iv[16]; 00185 const mbedtls_cipher_info_t *cipher_info; 00186 mbedtls_cipher_context_t cipher_ctx; 00187 size_t olen = 0; 00188 00189 cipher_info = mbedtls_cipher_info_from_type( cipher_type ); 00190 if( cipher_info == NULL ) 00191 return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); 00192 00193 keylen = cipher_info->key_bitlen / 8; 00194 00195 if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen, 00196 key, keylen, 00197 iv, cipher_info->iv_size ) ) != 0 ) 00198 { 00199 return( ret ); 00200 } 00201 00202 mbedtls_cipher_init( &cipher_ctx ); 00203 00204 if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) 00205 goto exit; 00206 00207 if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) 00208 goto exit; 00209 00210 if( ( ret = mbedtls_cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 ) 00211 goto exit; 00212 00213 if( ( ret = mbedtls_cipher_reset( &cipher_ctx ) ) != 0 ) 00214 goto exit; 00215 00216 if( ( ret = mbedtls_cipher_update( &cipher_ctx, data, len, 00217 output, &olen ) ) != 0 ) 00218 { 00219 goto exit; 00220 } 00221 00222 if( ( ret = mbedtls_cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) 00223 ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH; 00224 00225 exit: 00226 mbedtls_zeroize( key, sizeof( key ) ); 00227 mbedtls_zeroize( iv, sizeof( iv ) ); 00228 mbedtls_cipher_free( &cipher_ctx ); 00229 00230 return( ret ); 00231 } 00232 00233 static void pkcs12_fill_buffer( unsigned char *data, size_t data_len, 00234 const unsigned char *filler, size_t fill_len ) 00235 { 00236 unsigned char *p = data; 00237 size_t use_len; 00238 00239 while( data_len > 0 ) 00240 { 00241 use_len = ( data_len > fill_len ) ? fill_len : data_len; 00242 memcpy( p, filler, use_len ); 00243 p += use_len; 00244 data_len -= use_len; 00245 } 00246 } 00247 00248 int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, 00249 const unsigned char *pwd, size_t pwdlen, 00250 const unsigned char *salt, size_t saltlen, 00251 mbedtls_md_type_t md_type, int id, int iterations ) 00252 { 00253 int ret; 00254 unsigned int j; 00255 00256 unsigned char diversifier[128]; 00257 unsigned char salt_block[128], pwd_block[128], hash_block[128]; 00258 unsigned char hash_output[MBEDTLS_MD_MAX_SIZE]; 00259 unsigned char *p; 00260 unsigned char c; 00261 00262 size_t hlen, use_len, v, i; 00263 00264 const mbedtls_md_info_t *md_info; 00265 mbedtls_md_context_t md_ctx; 00266 00267 // This version only allows max of 64 bytes of password or salt 00268 if( datalen > 128 || pwdlen > 64 || saltlen > 64 ) 00269 return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); 00270 00271 md_info = mbedtls_md_info_from_type( md_type ); 00272 if( md_info == NULL ) 00273 return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); 00274 00275 mbedtls_md_init( &md_ctx ); 00276 00277 if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) 00278 return( ret ); 00279 hlen = mbedtls_md_get_size( md_info ); 00280 00281 if( hlen <= 32 ) 00282 v = 64; 00283 else 00284 v = 128; 00285 00286 memset( diversifier, (unsigned char) id, v ); 00287 00288 pkcs12_fill_buffer( salt_block, v, salt, saltlen ); 00289 pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen ); 00290 00291 p = data; 00292 while( datalen > 0 ) 00293 { 00294 // Calculate hash( diversifier || salt_block || pwd_block ) 00295 if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) 00296 goto exit; 00297 00298 if( ( ret = mbedtls_md_update( &md_ctx, diversifier, v ) ) != 0 ) 00299 goto exit; 00300 00301 if( ( ret = mbedtls_md_update( &md_ctx, salt_block, v ) ) != 0 ) 00302 goto exit; 00303 00304 if( ( ret = mbedtls_md_update( &md_ctx, pwd_block, v ) ) != 0 ) 00305 goto exit; 00306 00307 if( ( ret = mbedtls_md_finish( &md_ctx, hash_output ) ) != 0 ) 00308 goto exit; 00309 00310 // Perform remaining ( iterations - 1 ) recursive hash calculations 00311 for( i = 1; i < (size_t) iterations; i++ ) 00312 { 00313 if( ( ret = mbedtls_md( md_info, hash_output, hlen, hash_output ) ) != 0 ) 00314 goto exit; 00315 } 00316 00317 use_len = ( datalen > hlen ) ? hlen : datalen; 00318 memcpy( p, hash_output, use_len ); 00319 datalen -= use_len; 00320 p += use_len; 00321 00322 if( datalen == 0 ) 00323 break; 00324 00325 // Concatenating copies of hash_output into hash_block (B) 00326 pkcs12_fill_buffer( hash_block, v, hash_output, hlen ); 00327 00328 // B += 1 00329 for( i = v; i > 0; i-- ) 00330 if( ++hash_block[i - 1] != 0 ) 00331 break; 00332 00333 // salt_block += B 00334 c = 0; 00335 for( i = v; i > 0; i-- ) 00336 { 00337 j = salt_block[i - 1] + hash_block[i - 1] + c; 00338 c = (unsigned char) (j >> 8); 00339 salt_block[i - 1] = j & 0xFF; 00340 } 00341 00342 // pwd_block += B 00343 c = 0; 00344 for( i = v; i > 0; i-- ) 00345 { 00346 j = pwd_block[i - 1] + hash_block[i - 1] + c; 00347 c = (unsigned char) (j >> 8); 00348 pwd_block[i - 1] = j & 0xFF; 00349 } 00350 } 00351 00352 ret = 0; 00353 00354 exit: 00355 mbedtls_zeroize( salt_block, sizeof( salt_block ) ); 00356 mbedtls_zeroize( pwd_block, sizeof( pwd_block ) ); 00357 mbedtls_zeroize( hash_block, sizeof( hash_block ) ); 00358 mbedtls_zeroize( hash_output, sizeof( hash_output ) ); 00359 00360 mbedtls_md_free( &md_ctx ); 00361 00362 return( ret ); 00363 } 00364 00365 #endif /* MBEDTLS_PKCS12_C */
Generated on Tue Jul 12 2022 17:25:42 by
