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