pkcs12.c 10.6 KB
Newer Older
1 2 3
/*
 *  PKCS#12 Personal Information Exchange Syntax
 *
4
 *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
5
 *
6
 *  This file is part of mbed TLS (https://tls.mbed.org)
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
/*
 *  The PKCS #12 Personal Information Exchange Syntax Standard v1.1
 *
 *  http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf
 *  ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn
 */

29
#if !defined(MBEDTLS_CONFIG_FILE)
30
#include "mbedtls/config.h"
31
#else
32
#include MBEDTLS_CONFIG_FILE
33
#endif
34

35
#if defined(MBEDTLS_PKCS12_C)
36

37 38 39
#include "mbedtls/pkcs12.h"
#include "mbedtls/asn1.h"
#include "mbedtls/cipher.h"
40

41 42
#include <string.h>

43
#if defined(MBEDTLS_ARC4_C)
44
#include "mbedtls/arc4.h"
45 46
#endif

47
#if defined(MBEDTLS_DES_C)
48
#include "mbedtls/des.h"
49 50
#endif

51
/* Implementation that should never be optimized out by the compiler */
52
static void mbedtls_zeroize( void *v, size_t n ) {
53 54 55
    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
}

56 57
static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params,
                                    mbedtls_asn1_buf *salt, int *iterations )
58 59
{
    int ret;
60 61
    unsigned char **p = &params->p;
    const unsigned char *end = params->p + params->len;
62 63 64 65 66 67 68 69

    /*
     *  pkcs-12PbeParams ::= SEQUENCE {
     *    salt          OCTET STRING,
     *    iterations    INTEGER
     *  }
     *
     */
70 71 72
    if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
        return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT +
                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
73

74 75
    if( ( ret = mbedtls_asn1_get_tag( p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
        return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret );
76 77 78 79

    salt->p = *p;
    *p += salt->len;

80 81
    if( ( ret = mbedtls_asn1_get_int( p, end, iterations ) ) != 0 )
        return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret );
82 83

    if( *p != end )
84 85
        return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT +
                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
86 87 88 89

    return( 0 );
}

90
static int pkcs12_pbe_derive_key_iv( mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type,
91 92 93 94 95
                                     const unsigned char *pwd,  size_t pwdlen,
                                     unsigned char *key, size_t keylen,
                                     unsigned char *iv,  size_t ivlen )
{
    int ret, iterations;
96
    mbedtls_asn1_buf salt;
97 98 99
    size_t i;
    unsigned char unipwd[258];

100
    memset( &salt, 0, sizeof(mbedtls_asn1_buf) );
101
    memset( &unipwd, 0, sizeof(unipwd) );
102

103 104
    if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt,
                                         &iterations ) ) != 0 )
105 106
        return( ret );

107
    for( i = 0; i < pwdlen; i++ )
108 109
        unipwd[i * 2 + 1] = pwd[i];

110
    if( ( ret = mbedtls_pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2,
111
                                   salt.p, salt.len, md_type,
112
                                   MBEDTLS_PKCS12_DERIVE_KEY, iterations ) ) != 0 )
113 114 115 116 117 118 119
    {
        return( ret );
    }

    if( iv == NULL || ivlen == 0 )
        return( 0 );

120
    if( ( ret = mbedtls_pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2,
121
                                   salt.p, salt.len, md_type,
122
                                   MBEDTLS_PKCS12_DERIVE_IV, iterations ) ) != 0 )
123 124 125 126 127 128
    {
        return( ret );
    }
    return( 0 );
}

129
int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode,
130 131 132 133
                             const unsigned char *pwd,  size_t pwdlen,
                             const unsigned char *data, size_t len,
                             unsigned char *output )
{
134
#if !defined(MBEDTLS_ARC4_C)
135 136 137 138 139 140 141
    ((void) pbe_params);
    ((void) mode);
    ((void) pwd);
    ((void) pwdlen);
    ((void) data);
    ((void) len);
    ((void) output);
142
    return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE );
143 144 145
#else
    int ret;
    unsigned char key[16];
146
    mbedtls_arc4_context ctx;
147 148
    ((void) mode);

149
    mbedtls_arc4_init( &ctx );
150

151
    if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, MBEDTLS_MD_SHA1,
152
                                          pwd, pwdlen,
153 154 155 156 157
                                          key, 16, NULL, 0 ) ) != 0 )
    {
        return( ret );
    }

158 159
    mbedtls_arc4_setup( &ctx, key, 16 );
    if( ( ret = mbedtls_arc4_crypt( &ctx, len, data, output ) ) != 0 )
160
        goto exit;
161

162
exit:
163 164
    mbedtls_zeroize( key, sizeof( key ) );
    mbedtls_arc4_free( &ctx );
165 166

    return( ret );
167
#endif /* MBEDTLS_ARC4_C */
168
}
169

170 171
int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode,
                mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type,
172 173 174
                const unsigned char *pwd,  size_t pwdlen,
                const unsigned char *data, size_t len,
                unsigned char *output )
175
{
176 177 178
    int ret, keylen = 0;
    unsigned char key[32];
    unsigned char iv[16];
179 180
    const mbedtls_cipher_info_t *cipher_info;
    mbedtls_cipher_context_t cipher_ctx;
181 182
    size_t olen = 0;

183
    cipher_info = mbedtls_cipher_info_from_type( cipher_type );
184
    if( cipher_info == NULL )
185
        return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE );
186

187
    keylen = cipher_info->key_bitlen / 8;
188 189 190 191

    if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen,
                                          key, keylen,
                                          iv, cipher_info->iv_size ) ) != 0 )
192 193 194 195
    {
        return( ret );
    }

196
    mbedtls_cipher_init( &cipher_ctx );
197

198
    if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 )
199
        goto exit;
200

201
    if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 )
202
        goto exit;
203

204
    if( ( ret = mbedtls_cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 )
205 206
        goto exit;

207
    if( ( ret = mbedtls_cipher_reset( &cipher_ctx ) ) != 0 )
208
        goto exit;
209

210
    if( ( ret = mbedtls_cipher_update( &cipher_ctx, data, len,
211
                                output, &olen ) ) != 0 )
212
    {
213
        goto exit;
214 215
    }

216 217
    if( ( ret = mbedtls_cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 )
        ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH;
218

219
exit:
220 221 222
    mbedtls_zeroize( key, sizeof( key ) );
    mbedtls_zeroize( iv,  sizeof( iv  ) );
    mbedtls_cipher_free( &cipher_ctx );
223 224

    return( ret );
225
}
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241

static void pkcs12_fill_buffer( unsigned char *data, size_t data_len,
                                const unsigned char *filler, size_t fill_len )
{
    unsigned char *p = data;
    size_t use_len;

    while( data_len > 0 )
    {
        use_len = ( data_len > fill_len ) ? fill_len : data_len;
        memcpy( p, filler, use_len );
        p += use_len;
        data_len -= use_len;
    }
}

242
int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen,
243 244
                       const unsigned char *pwd, size_t pwdlen,
                       const unsigned char *salt, size_t saltlen,
245
                       mbedtls_md_type_t md_type, int id, int iterations )
246
{
247
    int ret;
248 249 250 251
    unsigned int j;

    unsigned char diversifier[128];
    unsigned char salt_block[128], pwd_block[128], hash_block[128];
252
    unsigned char hash_output[MBEDTLS_MD_MAX_SIZE];
253 254 255
    unsigned char *p;
    unsigned char c;

256
    size_t hlen, use_len, v, i;
257

258 259
    const mbedtls_md_info_t *md_info;
    mbedtls_md_context_t md_ctx;
260 261 262

    // This version only allows max of 64 bytes of password or salt
    if( datalen > 128 || pwdlen > 64 || saltlen > 64 )
263
        return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA );
264

265
    md_info = mbedtls_md_info_from_type( md_type );
266
    if( md_info == NULL )
267
        return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE );
268

269
    mbedtls_md_init( &md_ctx );
270

271
    if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
272
        return( ret );
273
    hlen = mbedtls_md_get_size( md_info );
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288

    if( hlen <= 32 )
        v = 64;
    else
        v = 128;

    memset( diversifier, (unsigned char) id, v );

    pkcs12_fill_buffer( salt_block, v, salt, saltlen );
    pkcs12_fill_buffer( pwd_block,  v, pwd,  pwdlen  );

    p = data;
    while( datalen > 0 )
    {
        // Calculate hash( diversifier || salt_block || pwd_block )
289
        if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 )
290
            goto exit;
291

292
        if( ( ret = mbedtls_md_update( &md_ctx, diversifier, v ) ) != 0 )
293
            goto exit;
294

295
        if( ( ret = mbedtls_md_update( &md_ctx, salt_block, v ) ) != 0 )
296
            goto exit;
297

298
        if( ( ret = mbedtls_md_update( &md_ctx, pwd_block, v ) ) != 0 )
299
            goto exit;
300

301
        if( ( ret = mbedtls_md_finish( &md_ctx, hash_output ) ) != 0 )
302
            goto exit;
303 304

        // Perform remaining ( iterations - 1 ) recursive hash calculations
305
        for( i = 1; i < (size_t) iterations; i++ )
306
        {
307
            if( ( ret = mbedtls_md( md_info, hash_output, hlen, hash_output ) ) != 0 )
308
                goto exit;
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
        }

        use_len = ( datalen > hlen ) ? hlen : datalen;
        memcpy( p, hash_output, use_len );
        datalen -= use_len;
        p += use_len;

        if( datalen == 0 )
            break;

        // Concatenating copies of hash_output into hash_block (B)
        pkcs12_fill_buffer( hash_block, v, hash_output, hlen );

        // B += 1
        for( i = v; i > 0; i-- )
            if( ++hash_block[i - 1] != 0 )
                break;

        // salt_block += B
        c = 0;
        for( i = v; i > 0; i-- )
        {
            j = salt_block[i - 1] + hash_block[i - 1] + c;
            c = (unsigned char) (j >> 8);
            salt_block[i - 1] = j & 0xFF;
        }

        // pwd_block  += B
        c = 0;
        for( i = v; i > 0; i-- )
        {
            j = pwd_block[i - 1] + hash_block[i - 1] + c;
            c = (unsigned char) (j >> 8);
            pwd_block[i - 1] = j & 0xFF;
        }
    }

346 347 348
    ret = 0;

exit:
349 350 351 352
    mbedtls_zeroize( salt_block, sizeof( salt_block ) );
    mbedtls_zeroize( pwd_block, sizeof( pwd_block ) );
    mbedtls_zeroize( hash_block, sizeof( hash_block ) );
    mbedtls_zeroize( hash_output, sizeof( hash_output ) );
353

354
    mbedtls_md_free( &md_ctx );
355 356

    return( ret );
357 358
}

359
#endif /* MBEDTLS_PKCS12_C */