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-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 #include "mbedtls/platform_util.h" 00040 00041 #include <string.h> 00042 00043 #if defined(MBEDTLS_ARC4_C) 00044 #include "mbedtls/arc4.h" 00045 #endif 00046 00047 #if defined(MBEDTLS_DES_C) 00048 #include "mbedtls/des.h" 00049 #endif 00050 00051 static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params, 00052 mbedtls_asn1_buf *salt, int *iterations ) 00053 { 00054 int ret; 00055 unsigned char **p = ¶ms->p; 00056 const unsigned char *end = params->p + params->len; 00057 00058 /* 00059 * pkcs-12PbeParams ::= SEQUENCE { 00060 * salt OCTET STRING, 00061 * iterations INTEGER 00062 * } 00063 * 00064 */ 00065 if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) 00066 return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + 00067 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); 00068 00069 if( ( ret = mbedtls_asn1_get_tag( p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) 00070 return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); 00071 00072 salt->p = *p; 00073 *p += salt->len; 00074 00075 if( ( ret = mbedtls_asn1_get_int( p, end, iterations ) ) != 0 ) 00076 return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); 00077 00078 if( *p != end ) 00079 return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + 00080 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 00081 00082 return( 0 ); 00083 } 00084 00085 #define PKCS12_MAX_PWDLEN 128 00086 00087 static int pkcs12_pbe_derive_key_iv( mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type, 00088 const unsigned char *pwd, size_t pwdlen, 00089 unsigned char *key, size_t keylen, 00090 unsigned char *iv, size_t ivlen ) 00091 { 00092 int ret, iterations = 0; 00093 mbedtls_asn1_buf salt; 00094 size_t i; 00095 unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2]; 00096 00097 if( pwdlen > PKCS12_MAX_PWDLEN ) 00098 return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); 00099 00100 memset( &salt, 0, sizeof(mbedtls_asn1_buf) ); 00101 memset( &unipwd, 0, sizeof(unipwd) ); 00102 00103 if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt, 00104 &iterations ) ) != 0 ) 00105 return( ret ); 00106 00107 for( i = 0; i < pwdlen; i++ ) 00108 unipwd[i * 2 + 1] = pwd[i]; 00109 00110 if( ( ret = mbedtls_pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2, 00111 salt.p, salt.len, md_type, 00112 MBEDTLS_PKCS12_DERIVE_KEY, iterations ) ) != 0 ) 00113 { 00114 return( ret ); 00115 } 00116 00117 if( iv == NULL || ivlen == 0 ) 00118 return( 0 ); 00119 00120 if( ( ret = mbedtls_pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2, 00121 salt.p, salt.len, md_type, 00122 MBEDTLS_PKCS12_DERIVE_IV, iterations ) ) != 0 ) 00123 { 00124 return( ret ); 00125 } 00126 return( 0 ); 00127 } 00128 00129 #undef PKCS12_MAX_PWDLEN 00130 00131 int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, 00132 const unsigned char *pwd, size_t pwdlen, 00133 const unsigned char *data, size_t len, 00134 unsigned char *output ) 00135 { 00136 #if !defined(MBEDTLS_ARC4_C) 00137 ((void) pbe_params); 00138 ((void) mode); 00139 ((void) pwd); 00140 ((void) pwdlen); 00141 ((void) data); 00142 ((void) len); 00143 ((void) output); 00144 return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); 00145 #else 00146 int ret; 00147 unsigned char key[16]; 00148 mbedtls_arc4_context ctx; 00149 ((void) mode); 00150 00151 mbedtls_arc4_init( &ctx ); 00152 00153 if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, MBEDTLS_MD_SHA1, 00154 pwd, pwdlen, 00155 key, 16, NULL, 0 ) ) != 0 ) 00156 { 00157 return( ret ); 00158 } 00159 00160 mbedtls_arc4_setup( &ctx, key, 16 ); 00161 if( ( ret = mbedtls_arc4_crypt( &ctx, len, data, output ) ) != 0 ) 00162 goto exit; 00163 00164 exit: 00165 mbedtls_platform_zeroize( key, sizeof( key ) ); 00166 mbedtls_arc4_free( &ctx ); 00167 00168 return( ret ); 00169 #endif /* MBEDTLS_ARC4_C */ 00170 } 00171 00172 int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, 00173 mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, 00174 const unsigned char *pwd, size_t pwdlen, 00175 const unsigned char *data, size_t len, 00176 unsigned char *output ) 00177 { 00178 int ret, keylen = 0; 00179 unsigned char key[32]; 00180 unsigned char iv[16]; 00181 const mbedtls_cipher_info_t *cipher_info; 00182 mbedtls_cipher_context_t cipher_ctx; 00183 size_t olen = 0; 00184 00185 cipher_info = mbedtls_cipher_info_from_type( cipher_type ); 00186 if( cipher_info == NULL ) 00187 return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); 00188 00189 keylen = cipher_info->key_bitlen / 8; 00190 00191 if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen, 00192 key, keylen, 00193 iv, cipher_info->iv_size ) ) != 0 ) 00194 { 00195 return( ret ); 00196 } 00197 00198 mbedtls_cipher_init( &cipher_ctx ); 00199 00200 if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) 00201 goto exit; 00202 00203 if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) 00204 goto exit; 00205 00206 if( ( ret = mbedtls_cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 ) 00207 goto exit; 00208 00209 if( ( ret = mbedtls_cipher_reset( &cipher_ctx ) ) != 0 ) 00210 goto exit; 00211 00212 if( ( ret = mbedtls_cipher_update( &cipher_ctx, data, len, 00213 output, &olen ) ) != 0 ) 00214 { 00215 goto exit; 00216 } 00217 00218 if( ( ret = mbedtls_cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) 00219 ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH; 00220 00221 exit: 00222 mbedtls_platform_zeroize( key, sizeof( key ) ); 00223 mbedtls_platform_zeroize( iv, sizeof( iv ) ); 00224 mbedtls_cipher_free( &cipher_ctx ); 00225 00226 return( ret ); 00227 } 00228 00229 static void pkcs12_fill_buffer( unsigned char *data, size_t data_len, 00230 const unsigned char *filler, size_t fill_len ) 00231 { 00232 unsigned char *p = data; 00233 size_t use_len; 00234 00235 while( data_len > 0 ) 00236 { 00237 use_len = ( data_len > fill_len ) ? fill_len : data_len; 00238 memcpy( p, filler, use_len ); 00239 p += use_len; 00240 data_len -= use_len; 00241 } 00242 } 00243 00244 int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, 00245 const unsigned char *pwd, size_t pwdlen, 00246 const unsigned char *salt, size_t saltlen, 00247 mbedtls_md_type_t md_type, int id, int iterations ) 00248 { 00249 int ret; 00250 unsigned int j; 00251 00252 unsigned char diversifier[128]; 00253 unsigned char salt_block[128], pwd_block[128], hash_block[128]; 00254 unsigned char hash_output[MBEDTLS_MD_MAX_SIZE]; 00255 unsigned char *p; 00256 unsigned char c; 00257 00258 size_t hlen, use_len, v, i; 00259 00260 const mbedtls_md_info_t *md_info; 00261 mbedtls_md_context_t md_ctx; 00262 00263 // This version only allows max of 64 bytes of password or salt 00264 if( datalen > 128 || pwdlen > 64 || saltlen > 64 ) 00265 return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); 00266 00267 md_info = mbedtls_md_info_from_type( md_type ); 00268 if( md_info == NULL ) 00269 return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); 00270 00271 mbedtls_md_init( &md_ctx ); 00272 00273 if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) 00274 return( ret ); 00275 hlen = mbedtls_md_get_size( md_info ); 00276 00277 if( hlen <= 32 ) 00278 v = 64; 00279 else 00280 v = 128; 00281 00282 memset( diversifier, (unsigned char) id, v ); 00283 00284 pkcs12_fill_buffer( salt_block, v, salt, saltlen ); 00285 pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen ); 00286 00287 p = data; 00288 while( datalen > 0 ) 00289 { 00290 // Calculate hash( diversifier || salt_block || pwd_block ) 00291 if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) 00292 goto exit; 00293 00294 if( ( ret = mbedtls_md_update( &md_ctx, diversifier, v ) ) != 0 ) 00295 goto exit; 00296 00297 if( ( ret = mbedtls_md_update( &md_ctx, salt_block, v ) ) != 0 ) 00298 goto exit; 00299 00300 if( ( ret = mbedtls_md_update( &md_ctx, pwd_block, v ) ) != 0 ) 00301 goto exit; 00302 00303 if( ( ret = mbedtls_md_finish( &md_ctx, hash_output ) ) != 0 ) 00304 goto exit; 00305 00306 // Perform remaining ( iterations - 1 ) recursive hash calculations 00307 for( i = 1; i < (size_t) iterations; i++ ) 00308 { 00309 if( ( ret = mbedtls_md( md_info, hash_output, hlen, hash_output ) ) != 0 ) 00310 goto exit; 00311 } 00312 00313 use_len = ( datalen > hlen ) ? hlen : datalen; 00314 memcpy( p, hash_output, use_len ); 00315 datalen -= use_len; 00316 p += use_len; 00317 00318 if( datalen == 0 ) 00319 break; 00320 00321 // Concatenating copies of hash_output into hash_block (B) 00322 pkcs12_fill_buffer( hash_block, v, hash_output, hlen ); 00323 00324 // B += 1 00325 for( i = v; i > 0; i-- ) 00326 if( ++hash_block[i - 1] != 0 ) 00327 break; 00328 00329 // salt_block += B 00330 c = 0; 00331 for( i = v; i > 0; i-- ) 00332 { 00333 j = salt_block[i - 1] + hash_block[i - 1] + c; 00334 c = (unsigned char) (j >> 8); 00335 salt_block[i - 1] = j & 0xFF; 00336 } 00337 00338 // pwd_block += B 00339 c = 0; 00340 for( i = v; i > 0; i-- ) 00341 { 00342 j = pwd_block[i - 1] + hash_block[i - 1] + c; 00343 c = (unsigned char) (j >> 8); 00344 pwd_block[i - 1] = j & 0xFF; 00345 } 00346 } 00347 00348 ret = 0; 00349 00350 exit: 00351 mbedtls_platform_zeroize( salt_block, sizeof( salt_block ) ); 00352 mbedtls_platform_zeroize( pwd_block, sizeof( pwd_block ) ); 00353 mbedtls_platform_zeroize( hash_block, sizeof( hash_block ) ); 00354 mbedtls_platform_zeroize( hash_output, sizeof( hash_output ) ); 00355 00356 mbedtls_md_free( &md_ctx ); 00357 00358 return( ret ); 00359 } 00360 00361 #endif /* MBEDTLS_PKCS12_C */
Generated on Tue Jul 12 2022 12:45:41 by
