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