~bibledit/bibledit/client

« back to all changes in this revision

Viewing changes to mbedtls2/pkcs5.c

  • Committer: Teus Benschop
  • Date: 2024-08-17 17:08:44 UTC
  • Revision ID: teusjannette@gmail.com-20240817170844-0qf789ywtms3hyz7
new upstream version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#pragma clang diagnostic ignored "-Wunknown-warning-option"
 
2
#pragma clang diagnostic ignored "-Wimplicit-int-conversion"
 
3
#pragma clang diagnostic ignored "-Wsign-conversion"
 
4
 
 
5
#pragma GCC diagnostic ignored "-Wconversion"
 
6
 
 
7
#pragma clang diagnostic ignored "-Wimplicit-int-conversion"
 
8
#pragma clang diagnostic ignored "-Wsign-conversion"
 
9
 
 
10
#pragma GCC diagnostic ignored "-Wconversion"
 
11
 
 
12
#pragma clang diagnostic ignored "-Wimplicit-int-conversion"
 
13
#pragma clang diagnostic ignored "-Wsign-conversion"
 
14
/**
 
15
 * \file pkcs5.c
 
16
 *
 
17
 * \brief PKCS#5 functions
 
18
 *
 
19
 * \author Mathias Olsson <mathias@kompetensum.com>
 
20
 *
 
21
 *  Copyright The Mbed TLS Contributors
 
22
 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
 
23
 *
 
24
 *  This file is provided under the Apache License 2.0, or the
 
25
 *  GNU General Public License v2.0 or later.
 
26
 *
 
27
 *  **********
 
28
 *  Apache License 2.0:
 
29
 *
 
30
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may
 
31
 *  not use this file except in compliance with the License.
 
32
 *  You may obtain a copy of the License at
 
33
 *
 
34
 *  http://www.apache.org/licenses/LICENSE-2.0
 
35
 *
 
36
 *  Unless required by applicable law or agreed to in writing, software
 
37
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 
38
 *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
39
 *  See the License for the specific language governing permissions and
 
40
 *  limitations under the License.
 
41
 *
 
42
 *  **********
 
43
 *
 
44
 *  **********
 
45
 *  GNU General Public License v2.0 or later:
 
46
 *
 
47
 *  This program is free software; you can redistribute it and/or modify
 
48
 *  it under the terms of the GNU General Public License as published by
 
49
 *  the Free Software Foundation; either version 2 of the License, or
 
50
 *  (at your option) any later version.
 
51
 *
 
52
 *  This program is distributed in the hope that it will be useful,
 
53
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
54
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
55
 *  GNU General Public License for more details.
 
56
 *
 
57
 *  You should have received a copy of the GNU General Public License along
 
58
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 
59
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
60
 *
 
61
 *  **********
 
62
 */
 
63
/*
 
64
 * PKCS#5 includes PBKDF2 and more
 
65
 *
 
66
 * http://tools.ietf.org/html/rfc2898 (Specification)
 
67
 * http://tools.ietf.org/html/rfc6070 (Test vectors)
 
68
 */
 
69
 
 
70
#if !defined(MBEDTLS_CONFIG_FILE)
 
71
#include "mbedtls/config.h"
 
72
#else
 
73
#include MBEDTLS_CONFIG_FILE
 
74
#endif
 
75
 
 
76
#if defined(MBEDTLS_PKCS5_C)
 
77
 
 
78
#include "mbedtls/pkcs5.h"
 
79
 
 
80
#if defined(MBEDTLS_ASN1_PARSE_C)
 
81
#include "mbedtls/asn1.h"
 
82
#include "mbedtls/cipher.h"
 
83
#include "mbedtls/oid.h"
 
84
#endif /* MBEDTLS_ASN1_PARSE_C */
 
85
 
 
86
#include <string.h>
 
87
 
 
88
#if defined(MBEDTLS_PLATFORM_C)
 
89
#include "mbedtls/platform.h"
 
90
#else
 
91
#include <stdio.h>
 
92
#define mbedtls_printf printf
 
93
#endif
 
94
 
 
95
#if defined(MBEDTLS_ASN1_PARSE_C)
 
96
static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params,
 
97
                                      mbedtls_asn1_buf *salt, int *iterations,
 
98
                                      int *keylen, mbedtls_md_type_t *md_type )
 
99
{
 
100
    int ret;
 
101
    mbedtls_asn1_buf prf_alg_oid;
 
102
    unsigned char *p = params->p;
 
103
    const unsigned char *end = params->p + params->len;
 
104
 
 
105
    if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
 
106
        return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT +
 
107
                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
 
108
    /*
 
109
     *  PBKDF2-params ::= SEQUENCE {
 
110
     *    salt              OCTET STRING,
 
111
     *    iterationCount    INTEGER,
 
112
     *    keyLength         INTEGER OPTIONAL
 
113
     *    prf               AlgorithmIdentifier DEFAULT algid-hmacWithSHA1
 
114
     *  }
 
115
     *
 
116
     */
 
117
    if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
 
118
        return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
 
119
 
 
120
    salt->p = p;
 
121
    p += salt->len;
 
122
 
 
123
    if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 )
 
124
        return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
 
125
 
 
126
    if( p == end )
 
127
        return( 0 );
 
128
 
 
129
    if( ( ret = mbedtls_asn1_get_int( &p, end, keylen ) ) != 0 )
 
130
    {
 
131
        if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
 
132
            return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
 
133
    }
 
134
 
 
135
    if( p == end )
 
136
        return( 0 );
 
137
 
 
138
    if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 )
 
139
        return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
 
140
 
 
141
    if( mbedtls_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 )
 
142
        return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
 
143
 
 
144
    if( p != end )
 
145
        return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT +
 
146
                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
 
147
 
 
148
    return( 0 );
 
149
}
 
150
 
 
151
int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode,
 
152
                 const unsigned char *pwd,  size_t pwdlen,
 
153
                 const unsigned char *data, size_t datalen,
 
154
                 unsigned char *output )
 
155
{
 
156
    int ret, iterations = 0, keylen = 0;
 
157
    unsigned char *p, *end;
 
158
    mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params;
 
159
    mbedtls_asn1_buf salt;
 
160
    mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;
 
161
    unsigned char key[32], iv[32];
 
162
    size_t olen = 0;
 
163
    const mbedtls_md_info_t *md_info;
 
164
    const mbedtls_cipher_info_t *cipher_info;
 
165
    mbedtls_md_context_t md_ctx;
 
166
    mbedtls_cipher_type_t cipher_alg;
 
167
    mbedtls_cipher_context_t cipher_ctx;
 
168
 
 
169
    p = pbe_params->p;
 
170
    end = p + pbe_params->len;
 
171
 
 
172
    /*
 
173
     *  PBES2-params ::= SEQUENCE {
 
174
     *    keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
 
175
     *    encryptionScheme AlgorithmIdentifier {{PBES2-Encs}}
 
176
     *  }
 
177
     */
 
178
    if( pbe_params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
 
179
        return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT +
 
180
                MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
 
181
 
 
182
    if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 )
 
183
        return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
 
184
 
 
185
    // Only PBKDF2 supported at the moment
 
186
    //
 
187
    if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid ) != 0 )
 
188
        return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
 
189
 
 
190
    if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params,
 
191
                                           &salt, &iterations, &keylen,
 
192
                                           &md_type ) ) != 0 )
 
193
    {
 
194
        return( ret );
 
195
    }
 
196
 
 
197
    md_info = mbedtls_md_info_from_type( md_type );
 
198
    if( md_info == NULL )
 
199
        return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
 
200
 
 
201
    if( ( ret = mbedtls_asn1_get_alg( &p, end, &enc_scheme_oid,
 
202
                              &enc_scheme_params ) ) != 0 )
 
203
    {
 
204
        return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret );
 
205
    }
 
206
 
 
207
    if( mbedtls_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 )
 
208
        return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
 
209
 
 
210
    cipher_info = mbedtls_cipher_info_from_type( cipher_alg );
 
211
    if( cipher_info == NULL )
 
212
        return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
 
213
 
 
214
    /*
 
215
     * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored
 
216
     * since it is optional and we don't know if it was set or not
 
217
     */
 
218
    keylen = cipher_info->key_bitlen / 8;
 
219
 
 
220
    if( enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING ||
 
221
        enc_scheme_params.len != cipher_info->iv_size )
 
222
    {
 
223
        return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT );
 
224
    }
 
225
 
 
226
    mbedtls_md_init( &md_ctx );
 
227
    mbedtls_cipher_init( &cipher_ctx );
 
228
 
 
229
    memcpy( iv, enc_scheme_params.p, enc_scheme_params.len );
 
230
 
 
231
    if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 )
 
232
        goto exit;
 
233
 
 
234
    if( ( ret = mbedtls_pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len,
 
235
                                   iterations, keylen, key ) ) != 0 )
 
236
    {
 
237
        goto exit;
 
238
    }
 
239
 
 
240
    if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 )
 
241
        goto exit;
 
242
 
 
243
    if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 )
 
244
        goto exit;
 
245
 
 
246
    if( ( ret = mbedtls_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len,
 
247
                              data, datalen, output, &olen ) ) != 0 )
 
248
        ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH;
 
249
 
 
250
exit:
 
251
    mbedtls_md_free( &md_ctx );
 
252
    mbedtls_cipher_free( &cipher_ctx );
 
253
 
 
254
    return( ret );
 
255
}
 
256
#endif /* MBEDTLS_ASN1_PARSE_C */
 
257
 
 
258
int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password,
 
259
                       size_t plen, const unsigned char *salt, size_t slen,
 
260
                       unsigned int iteration_count,
 
261
                       uint32_t key_length, unsigned char *output )
 
262
{
 
263
    int ret = 0, j;
 
264
    unsigned int i;
 
265
    unsigned char md1[MBEDTLS_MD_MAX_SIZE];
 
266
    unsigned char work[MBEDTLS_MD_MAX_SIZE];
 
267
    unsigned char md_size = mbedtls_md_get_size( ctx->md_info );
 
268
    size_t use_len;
 
269
    unsigned char *out_p = output;
 
270
    unsigned char counter[4];
 
271
 
 
272
    memset( counter, 0, 4 );
 
273
    counter[3] = 1;
 
274
 
 
275
#if UINT_MAX > 0xFFFFFFFF
 
276
    if( iteration_count > 0xFFFFFFFF )
 
277
        return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA );
 
278
#endif
 
279
 
 
280
    while( key_length )
 
281
    {
 
282
        // U1 ends up in work
 
283
        //
 
284
        if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 )
 
285
            goto cleanup;
 
286
 
 
287
        if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 )
 
288
            goto cleanup;
 
289
 
 
290
        if( ( ret = mbedtls_md_hmac_update( ctx, counter, 4 ) ) != 0 )
 
291
            goto cleanup;
 
292
 
 
293
        if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 )
 
294
            goto cleanup;
 
295
 
 
296
        memcpy( md1, work, md_size );
 
297
 
 
298
        for( i = 1; i < iteration_count; i++ )
 
299
        {
 
300
            // U2 ends up in md1
 
301
            //
 
302
            if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 )
 
303
                goto cleanup;
 
304
 
 
305
            if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 )
 
306
                goto cleanup;
 
307
 
 
308
            if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 )
 
309
                goto cleanup;
 
310
 
 
311
            // U1 xor U2
 
312
            //
 
313
            for( j = 0; j < md_size; j++ )
 
314
                work[j] ^= md1[j];
 
315
        }
 
316
 
 
317
        use_len = ( key_length < md_size ) ? key_length : md_size;
 
318
        memcpy( out_p, work, use_len );
 
319
 
 
320
        key_length -= (uint32_t) use_len;
 
321
        out_p += use_len;
 
322
 
 
323
        for( i = 4; i > 0; i-- )
 
324
            if( ++counter[i - 1] != 0 )
 
325
                break;
 
326
    }
 
327
 
 
328
cleanup:
 
329
    /* Zeroise buffers to clear sensitive data from memory. */
 
330
    mbedtls_platform_zeroize( work, MBEDTLS_MD_MAX_SIZE );
 
331
    mbedtls_platform_zeroize( md1, MBEDTLS_MD_MAX_SIZE );
 
332
 
 
333
    return( ret );
 
334
}
 
335
 
 
336
#if defined(MBEDTLS_SELF_TEST)
 
337
 
 
338
#if !defined(MBEDTLS_SHA1_C)
 
339
int mbedtls_pkcs5_self_test( int verbose )
 
340
{
 
341
    if( verbose != 0 )
 
342
        mbedtls_printf( "  PBKDF2 (SHA1): skipped\n\n" );
 
343
 
 
344
    return( 0 );
 
345
}
 
346
#else
 
347
 
 
348
#define MAX_TESTS   6
 
349
 
 
350
static const size_t plen[MAX_TESTS] =
 
351
    { 8, 8, 8, 24, 9 };
 
352
 
 
353
static const unsigned char password[MAX_TESTS][32] =
 
354
{
 
355
    "password",
 
356
    "password",
 
357
    "password",
 
358
    "passwordPASSWORDpassword",
 
359
    "pass\0word",
 
360
};
 
361
 
 
362
static const size_t slen[MAX_TESTS] =
 
363
    { 4, 4, 4, 36, 5 };
 
364
 
 
365
static const unsigned char salt[MAX_TESTS][40] =
 
366
{
 
367
    "salt",
 
368
    "salt",
 
369
    "salt",
 
370
    "saltSALTsaltSALTsaltSALTsaltSALTsalt",
 
371
    "sa\0lt",
 
372
};
 
373
 
 
374
static const uint32_t it_cnt[MAX_TESTS] =
 
375
    { 1, 2, 4096, 4096, 4096 };
 
376
 
 
377
static const uint32_t key_len[MAX_TESTS] =
 
378
    { 20, 20, 20, 25, 16 };
 
379
 
 
380
static const unsigned char result_key[MAX_TESTS][32] =
 
381
{
 
382
    { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
 
383
      0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
 
384
      0x2f, 0xe0, 0x37, 0xa6 },
 
385
    { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
 
386
      0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
 
387
      0xd8, 0xde, 0x89, 0x57 },
 
388
    { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
 
389
      0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
 
390
      0x65, 0xa4, 0x29, 0xc1 },
 
391
    { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
 
392
      0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
 
393
      0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
 
394
      0x38 },
 
395
    { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
 
396
      0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 },
 
397
};
 
398
 
 
399
int mbedtls_pkcs5_self_test( int verbose )
 
400
{
 
401
    mbedtls_md_context_t sha1_ctx;
 
402
    const mbedtls_md_info_t *info_sha1;
 
403
    int ret, i;
 
404
    unsigned char key[64];
 
405
 
 
406
    mbedtls_md_init( &sha1_ctx );
 
407
 
 
408
    info_sha1 = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
 
409
    if( info_sha1 == NULL )
 
410
    {
 
411
        ret = 1;
 
412
        goto exit;
 
413
    }
 
414
 
 
415
    if( ( ret = mbedtls_md_setup( &sha1_ctx, info_sha1, 1 ) ) != 0 )
 
416
    {
 
417
        ret = 1;
 
418
        goto exit;
 
419
    }
 
420
 
 
421
    for( i = 0; i < MAX_TESTS; i++ )
 
422
    {
 
423
        if( verbose != 0 )
 
424
            mbedtls_printf( "  PBKDF2 (SHA1) #%d: ", i );
 
425
 
 
426
        ret = mbedtls_pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i],
 
427
                                  slen[i], it_cnt[i], key_len[i], key );
 
428
        if( ret != 0 ||
 
429
            memcmp( result_key[i], key, key_len[i] ) != 0 )
 
430
        {
 
431
            if( verbose != 0 )
 
432
                mbedtls_printf( "failed\n" );
 
433
 
 
434
            ret = 1;
 
435
            goto exit;
 
436
        }
 
437
 
 
438
        if( verbose != 0 )
 
439
            mbedtls_printf( "passed\n" );
 
440
    }
 
441
 
 
442
    if( verbose != 0 )
 
443
        mbedtls_printf( "\n" );
 
444
 
 
445
exit:
 
446
    mbedtls_md_free( &sha1_ctx );
 
447
 
 
448
    return( ret );
 
449
}
 
450
#endif /* MBEDTLS_SHA1_C */
 
451
 
 
452
#endif /* MBEDTLS_SELF_TEST */
 
453
 
 
454
#endif /* MBEDTLS_PKCS5_C */