Coverage Report

Created: 2025-10-12 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/providers/implementations/kdfs/pbkdf1.c
Line
Count
Source
1
/*
2
 * Copyright 1999-2025 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
11
#include <openssl/trace.h>
12
#include <stdlib.h>
13
#include <stdarg.h>
14
#include <string.h>
15
#include <openssl/evp.h>
16
#include <openssl/kdf.h>
17
#include <openssl/core_names.h>
18
#include <openssl/proverr.h>
19
#include "internal/common.h"
20
#include "internal/cryptlib.h"
21
#include "internal/numbers.h"
22
#include "internal/skey.h"
23
#include "crypto/evp.h"
24
#include "crypto/types.h"
25
#include "prov/provider_ctx.h"
26
#include "prov/providercommon.h"
27
#include "prov/implementations.h"
28
#include "prov/provider_util.h"
29
30
static OSSL_FUNC_kdf_newctx_fn kdf_pbkdf1_new;
31
static OSSL_FUNC_kdf_dupctx_fn kdf_pbkdf1_dup;
32
static OSSL_FUNC_kdf_freectx_fn kdf_pbkdf1_free;
33
static OSSL_FUNC_kdf_reset_fn kdf_pbkdf1_reset;
34
static OSSL_FUNC_kdf_derive_fn kdf_pbkdf1_derive;
35
static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_pbkdf1_settable_ctx_params;
36
static OSSL_FUNC_kdf_set_ctx_params_fn kdf_pbkdf1_set_ctx_params;
37
static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_pbkdf1_gettable_ctx_params;
38
static OSSL_FUNC_kdf_get_ctx_params_fn kdf_pbkdf1_get_ctx_params;
39
static OSSL_FUNC_kdf_set_skey_fn kdf_pbkdf1_set_skey;
40
static OSSL_FUNC_kdf_derive_skey_fn kdf_pbkdf1_derive_skey;
41
42
typedef struct {
43
    void *provctx;
44
    PROV_DIGEST digest;
45
    unsigned char *pass;
46
    size_t pass_len;
47
    unsigned char *salt;
48
    size_t salt_len;
49
    uint64_t iter;
50
} KDF_PBKDF1;
51
52
/*
53
 * PKCS5 PBKDF1 compatible key/IV generation as specified in:
54
 * https://tools.ietf.org/html/rfc8018#page-10
55
 */
56
57
static int kdf_pbkdf1_do_derive(const unsigned char *pass, size_t passlen,
58
                                const unsigned char *salt, size_t saltlen,
59
                                uint64_t iter, const EVP_MD *md_type,
60
                                unsigned char *out, size_t n)
61
0
{
62
0
    uint64_t i;
63
0
    int mdsize, ret = 0;
64
0
    unsigned char md_tmp[EVP_MAX_MD_SIZE];
65
0
    EVP_MD_CTX *ctx = NULL;
66
67
0
    ctx = EVP_MD_CTX_new();
68
0
    if (ctx == NULL) {
69
0
        ERR_raise(ERR_LIB_PROV, ERR_R_EVP_LIB);
70
0
        goto err;
71
0
    }
72
73
0
    if (!EVP_DigestInit_ex(ctx, md_type, NULL)
74
0
        || !EVP_DigestUpdate(ctx, pass, passlen)
75
0
        || !EVP_DigestUpdate(ctx, salt, saltlen)
76
0
        || !EVP_DigestFinal_ex(ctx, md_tmp, NULL))
77
0
        goto err;
78
0
    mdsize = EVP_MD_size(md_type);
79
0
    if (mdsize <= 0)
80
0
        goto err;
81
0
    if (n > (size_t)mdsize) {
82
0
        ERR_raise(ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE);
83
0
        goto err;
84
0
    }
85
86
0
    for (i = 1; i < iter; i++) {
87
0
        if (!EVP_DigestInit_ex(ctx, md_type, NULL))
88
0
            goto err;
89
0
        if (!EVP_DigestUpdate(ctx, md_tmp, mdsize))
90
0
            goto err;
91
0
        if (!EVP_DigestFinal_ex(ctx, md_tmp, NULL))
92
0
            goto err;
93
0
    }
94
95
0
    memcpy(out, md_tmp, n);
96
0
    ret = 1;
97
0
err:
98
0
    OPENSSL_cleanse(md_tmp, EVP_MAX_MD_SIZE);
99
0
    EVP_MD_CTX_free(ctx);
100
0
    return ret;
101
0
}
102
103
static void *kdf_pbkdf1_new(void *provctx)
104
0
{
105
0
    KDF_PBKDF1 *ctx;
106
107
0
    if (!ossl_prov_is_running())
108
0
        return NULL;
109
110
0
    ctx = OPENSSL_zalloc(sizeof(*ctx));
111
0
    if (ctx == NULL)
112
0
        return NULL;
113
0
    ctx->provctx = provctx;
114
0
    return ctx;
115
0
}
116
117
static void kdf_pbkdf1_cleanup(KDF_PBKDF1 *ctx)
118
0
{
119
0
    ossl_prov_digest_reset(&ctx->digest);
120
0
    OPENSSL_free(ctx->salt);
121
0
    OPENSSL_clear_free(ctx->pass, ctx->pass_len);
122
0
    memset(ctx, 0, sizeof(*ctx));
123
0
}
124
125
static void kdf_pbkdf1_free(void *vctx)
126
0
{
127
0
    KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
128
129
0
    if (ctx != NULL) {
130
0
        kdf_pbkdf1_cleanup(ctx);
131
0
        OPENSSL_free(ctx);
132
0
    }
133
0
}
134
135
static void kdf_pbkdf1_reset(void *vctx)
136
0
{
137
0
    KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
138
0
    void *provctx = ctx->provctx;
139
140
0
    kdf_pbkdf1_cleanup(ctx);
141
0
    ctx->provctx = provctx;
142
0
}
143
144
static void *kdf_pbkdf1_dup(void *vctx)
145
0
{
146
0
    const KDF_PBKDF1 *src = (const KDF_PBKDF1 *)vctx;
147
0
    KDF_PBKDF1 *dest;
148
149
0
    dest = kdf_pbkdf1_new(src->provctx);
150
0
    if (dest != NULL) {
151
0
        if (!ossl_prov_memdup(src->salt, src->salt_len,
152
0
                              &dest->salt, &dest->salt_len)
153
0
                || !ossl_prov_memdup(src->pass, src->pass_len,
154
0
                                     &dest->pass , &dest->pass_len)
155
0
                || !ossl_prov_digest_copy(&dest->digest, &src->digest))
156
0
            goto err;
157
0
        dest->iter = src->iter;
158
0
    }
159
0
    return dest;
160
161
0
 err:
162
0
    kdf_pbkdf1_free(dest);
163
0
    return NULL;
164
0
}
165
166
static int kdf_pbkdf1_set_membuf(unsigned char **buffer, size_t *buflen,
167
                             const OSSL_PARAM *p)
168
0
{
169
0
    OPENSSL_clear_free(*buffer, *buflen);
170
0
    *buffer = NULL;
171
0
    *buflen = 0;
172
173
0
    if (p->data_size == 0) {
174
0
        if ((*buffer = OPENSSL_malloc(1)) == NULL)
175
0
            return 0;
176
0
    } else if (p->data != NULL) {
177
0
        if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen))
178
0
            return 0;
179
0
    }
180
0
    return 1;
181
0
}
182
183
static int kdf_pbkdf1_set_membuf_skey(unsigned char **buffer, size_t *buflen,
184
                                      const PROV_SKEY *pskey)
185
0
{
186
0
    OPENSSL_clear_free(*buffer, *buflen);
187
0
    *buffer = NULL;
188
0
    *buflen = 0;
189
190
0
    if (pskey->length == 0) {
191
0
        if ((*buffer = OPENSSL_malloc(1)) == NULL)
192
0
            return 0;
193
0
    } else if (pskey->data != NULL) {
194
0
        *buffer = OPENSSL_malloc(pskey->length);
195
0
        if (*buffer == NULL)
196
0
            return 0;
197
198
0
        memcpy(*buffer, pskey->data, pskey->length);
199
0
        *buflen = pskey->length;
200
0
    }
201
0
    return 1;
202
0
}
203
204
static int kdf_pbkdf1_derive(void *vctx, unsigned char *key, size_t keylen,
205
                             const OSSL_PARAM params[])
206
0
{
207
0
    KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
208
0
    const EVP_MD *md;
209
210
0
    if (!ossl_prov_is_running() || !kdf_pbkdf1_set_ctx_params(ctx, params))
211
0
        return 0;
212
213
0
    if (ctx->pass == NULL) {
214
0
        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS);
215
0
        return 0;
216
0
    }
217
218
0
    if (ctx->salt == NULL) {
219
0
        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);
220
0
        return 0;
221
0
    }
222
223
0
    md = ossl_prov_digest_md(&ctx->digest);
224
0
    return kdf_pbkdf1_do_derive(ctx->pass, ctx->pass_len, ctx->salt, ctx->salt_len,
225
0
                                ctx->iter, md, key, keylen);
226
0
}
227
228
/* Machine generated by util/perl/OpenSSL/paramnames.pm */
229
#ifndef pbkdf1_set_ctx_params_list
230
static const OSSL_PARAM pbkdf1_set_ctx_params_list[] = {
231
    OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
232
    OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
233
    OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),
234
    OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
235
    OSSL_PARAM_uint64(OSSL_KDF_PARAM_ITER, NULL),
236
    OSSL_PARAM_END
237
};
238
#endif
239
240
#ifndef pbkdf1_set_ctx_params_st
241
struct pbkdf1_set_ctx_params_st {
242
    OSSL_PARAM *digest;
243
    OSSL_PARAM *engine;
244
    OSSL_PARAM *iter;
245
    OSSL_PARAM *propq;
246
    OSSL_PARAM *pw;
247
    OSSL_PARAM *salt;
248
};
249
#endif
250
251
#ifndef pbkdf1_set_ctx_params_decoder
252
static int pbkdf1_set_ctx_params_decoder
253
    (const OSSL_PARAM *p, struct pbkdf1_set_ctx_params_st *r)
254
0
{
255
0
    const char *s;
256
257
0
    memset(r, 0, sizeof(*r));
258
0
    if (p != NULL)
259
0
        for (; (s = p->key) != NULL; p++)
260
0
            switch(s[0]) {
261
0
            default:
262
0
                break;
263
0
            case 'd':
264
0
                if (ossl_likely(strcmp("igest", s + 1) == 0)) {
265
                    /* OSSL_KDF_PARAM_DIGEST */
266
0
                    if (ossl_unlikely(r->digest != NULL)) {
267
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
268
0
                                       "param %s is repeated", s);
269
0
                        return 0;
270
0
                    }
271
0
                    r->digest = (OSSL_PARAM *)p;
272
0
                }
273
0
                break;
274
0
            case 'e':
275
0
                if (ossl_likely(strcmp("ngine", s + 1) == 0)) {
276
                    /* OSSL_ALG_PARAM_ENGINE */
277
0
                    if (ossl_unlikely(r->engine != NULL)) {
278
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
279
0
                                       "param %s is repeated", s);
280
0
                        return 0;
281
0
                    }
282
0
                    r->engine = (OSSL_PARAM *)p;
283
0
                }
284
0
                break;
285
0
            case 'i':
286
0
                if (ossl_likely(strcmp("ter", s + 1) == 0)) {
287
                    /* OSSL_KDF_PARAM_ITER */
288
0
                    if (ossl_unlikely(r->iter != NULL)) {
289
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
290
0
                                       "param %s is repeated", s);
291
0
                        return 0;
292
0
                    }
293
0
                    r->iter = (OSSL_PARAM *)p;
294
0
                }
295
0
                break;
296
0
            case 'p':
297
0
                switch(s[1]) {
298
0
                default:
299
0
                    break;
300
0
                case 'a':
301
0
                    if (ossl_likely(strcmp("ss", s + 2) == 0)) {
302
                        /* OSSL_KDF_PARAM_PASSWORD */
303
0
                        if (ossl_unlikely(r->pw != NULL)) {
304
0
                            ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
305
0
                                           "param %s is repeated", s);
306
0
                            return 0;
307
0
                        }
308
0
                        r->pw = (OSSL_PARAM *)p;
309
0
                    }
310
0
                    break;
311
0
                case 'r':
312
0
                    if (ossl_likely(strcmp("operties", s + 2) == 0)) {
313
                        /* OSSL_KDF_PARAM_PROPERTIES */
314
0
                        if (ossl_unlikely(r->propq != NULL)) {
315
0
                            ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
316
0
                                           "param %s is repeated", s);
317
0
                            return 0;
318
0
                        }
319
0
                        r->propq = (OSSL_PARAM *)p;
320
0
                    }
321
0
                }
322
0
                break;
323
0
            case 's':
324
0
                if (ossl_likely(strcmp("alt", s + 1) == 0)) {
325
                    /* OSSL_KDF_PARAM_SALT */
326
0
                    if (ossl_unlikely(r->salt != NULL)) {
327
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
328
0
                                       "param %s is repeated", s);
329
0
                        return 0;
330
0
                    }
331
0
                    r->salt = (OSSL_PARAM *)p;
332
0
                }
333
0
            }
334
0
    return 1;
335
0
}
336
#endif
337
/* End of machine generated */
338
339
static int kdf_pbkdf1_set_ctx_params(void *vctx, const OSSL_PARAM params[])
340
0
{
341
0
    struct pbkdf1_set_ctx_params_st p;
342
0
    KDF_PBKDF1 *ctx = vctx;
343
0
    OSSL_LIB_CTX *libctx;
344
345
0
    if (ctx == NULL || !pbkdf1_set_ctx_params_decoder(params, &p))
346
0
        return 0;
347
348
0
    libctx = PROV_LIBCTX_OF(ctx->provctx);
349
350
0
    if (!ossl_prov_digest_load(&ctx->digest, p.digest,
351
0
                               p.propq, p.engine, libctx))
352
0
        return 0;
353
354
0
    if (p.pw != NULL && !kdf_pbkdf1_set_membuf(&ctx->pass, &ctx->pass_len, p.pw))
355
0
        return 0;
356
357
0
    if (p.salt != NULL && !kdf_pbkdf1_set_membuf(&ctx->salt, &ctx->salt_len, p.salt))
358
0
        return 0;
359
360
0
    if (p.iter != NULL && !OSSL_PARAM_get_uint64(p.iter, &ctx->iter))
361
0
            return 0;
362
0
    return 1;
363
0
}
364
365
static const OSSL_PARAM *kdf_pbkdf1_settable_ctx_params(ossl_unused void *ctx,
366
                                                        ossl_unused void *p_ctx)
367
0
{
368
0
    return pbkdf1_set_ctx_params_list;
369
0
}
370
371
/* Machine generated by util/perl/OpenSSL/paramnames.pm */
372
#ifndef pbkdf1_get_ctx_params_list
373
static const OSSL_PARAM pbkdf1_get_ctx_params_list[] = {
374
    OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
375
    OSSL_PARAM_END
376
};
377
#endif
378
379
#ifndef pbkdf1_get_ctx_params_st
380
struct pbkdf1_get_ctx_params_st {
381
    OSSL_PARAM *size;
382
};
383
#endif
384
385
#ifndef pbkdf1_get_ctx_params_decoder
386
static int pbkdf1_get_ctx_params_decoder
387
    (const OSSL_PARAM *p, struct pbkdf1_get_ctx_params_st *r)
388
0
{
389
0
    const char *s;
390
391
0
    memset(r, 0, sizeof(*r));
392
0
    if (p != NULL)
393
0
        for (; (s = p->key) != NULL; p++)
394
0
            if (ossl_likely(strcmp("size", s + 0) == 0)) {
395
                /* OSSL_KDF_PARAM_SIZE */
396
0
                if (ossl_unlikely(r->size != NULL)) {
397
0
                    ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
398
0
                                   "param %s is repeated", s);
399
0
                    return 0;
400
0
                }
401
0
                r->size = (OSSL_PARAM *)p;
402
0
            }
403
0
    return 1;
404
0
}
405
#endif
406
/* End of machine generated */
407
408
static int kdf_pbkdf1_get_ctx_params(void *vctx, OSSL_PARAM params[])
409
0
{
410
0
    struct pbkdf1_get_ctx_params_st p;
411
0
    KDF_PBKDF1 *ctx = vctx;
412
413
0
    if (ctx == NULL || !pbkdf1_get_ctx_params_decoder(params, &p))
414
0
        return 0;
415
416
0
    if (p.size != NULL && !OSSL_PARAM_set_size_t(p.size, SIZE_MAX))
417
0
        return 0;
418
0
    return 1;
419
0
}
420
421
static const OSSL_PARAM *kdf_pbkdf1_gettable_ctx_params(ossl_unused void *ctx,
422
                                                        ossl_unused void *p_ctx)
423
0
{
424
0
    return pbkdf1_get_ctx_params_list;
425
0
}
426
427
static int kdf_pbkdf1_set_skey(void *vctx, void *skeydata, const char *paramname)
428
0
{
429
0
    KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
430
0
    PROV_SKEY *pskey = (PROV_SKEY *)skeydata;
431
432
0
    if (paramname == NULL || skeydata == NULL)
433
0
        return 0;
434
435
0
    if (strcmp(paramname, OSSL_KDF_PARAM_PASSWORD) == 0)
436
0
        return kdf_pbkdf1_set_membuf_skey(&ctx->pass, &ctx->pass_len, pskey);
437
438
0
    if (strcmp(paramname, OSSL_KDF_PARAM_SALT) == 0)
439
0
        return kdf_pbkdf1_set_membuf_skey(&ctx->salt, &ctx->salt_len, pskey);
440
441
0
    return 0;
442
0
}
443
444
static
445
void *kdf_pbkdf1_derive_skey(void *vctx, const char *key_type ossl_unused, void *provctx,
446
                             OSSL_FUNC_skeymgmt_import_fn *import,
447
                             size_t keylen, const OSSL_PARAM params[])
448
0
{
449
0
    unsigned char *key = NULL;
450
0
    void *ret = NULL;
451
0
    OSSL_PARAM import_params[2] = {OSSL_PARAM_END, OSSL_PARAM_END};
452
453
0
    if (import == NULL || keylen == 0)
454
0
        return NULL;
455
456
0
    if ((key = OPENSSL_zalloc(keylen)) == NULL)
457
0
        return NULL;
458
459
0
    if (kdf_pbkdf1_derive(vctx, key, keylen, params) == 0) {
460
0
        OPENSSL_free(key);
461
0
        return NULL;
462
0
    }
463
464
0
    import_params[0] = OSSL_PARAM_construct_octet_string(OSSL_SKEY_PARAM_RAW_BYTES,
465
0
                                                         (void *)key, keylen);
466
467
0
    ret = import(provctx, OSSL_SKEYMGMT_SELECT_SECRET_KEY, import_params);
468
0
    OPENSSL_free(key);
469
470
0
    return ret;
471
0
}
472
473
const OSSL_DISPATCH ossl_kdf_pbkdf1_functions[] = {
474
    { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pbkdf1_new },
475
    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_pbkdf1_dup },
476
    { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pbkdf1_free },
477
    { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pbkdf1_reset },
478
    { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pbkdf1_derive },
479
    { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
480
      (void(*)(void))kdf_pbkdf1_settable_ctx_params },
481
    { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_pbkdf1_set_ctx_params },
482
    { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
483
      (void(*)(void))kdf_pbkdf1_gettable_ctx_params },
484
    { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_pbkdf1_get_ctx_params },
485
    { OSSL_FUNC_KDF_SET_SKEY, (void(*)(void))kdf_pbkdf1_set_skey },
486
    { OSSL_FUNC_KDF_DERIVE_SKEY, (void(*)(void))kdf_pbkdf1_derive_skey },
487
    OSSL_DISPATCH_END
488
};