Committer:
kevman
Date:
Wed Mar 13 11:03:24 2019 +0000
Revision:
2:7aab896b1a3b
Parent:
0:38ceb79fef03
2019-03-13

Who changed what in which revision?

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