Coverage Report

Created: 2025-08-28 06:41

/src/openssl/providers/implementations/kdfs/pbkdf1.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 1999-2024 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 "crypto/evp.h"
23
#include "prov/provider_ctx.h"
24
#include "prov/providercommon.h"
25
#include "prov/implementations.h"
26
#include "prov/provider_util.h"
27
28
static OSSL_FUNC_kdf_newctx_fn kdf_pbkdf1_new;
29
static OSSL_FUNC_kdf_dupctx_fn kdf_pbkdf1_dup;
30
static OSSL_FUNC_kdf_freectx_fn kdf_pbkdf1_free;
31
static OSSL_FUNC_kdf_reset_fn kdf_pbkdf1_reset;
32
static OSSL_FUNC_kdf_derive_fn kdf_pbkdf1_derive;
33
static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_pbkdf1_settable_ctx_params;
34
static OSSL_FUNC_kdf_set_ctx_params_fn kdf_pbkdf1_set_ctx_params;
35
static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_pbkdf1_gettable_ctx_params;
36
static OSSL_FUNC_kdf_get_ctx_params_fn kdf_pbkdf1_get_ctx_params;
37
38
typedef struct {
39
    void *provctx;
40
    PROV_DIGEST digest;
41
    unsigned char *pass;
42
    size_t pass_len;
43
    unsigned char *salt;
44
    size_t salt_len;
45
    uint64_t iter;
46
} KDF_PBKDF1;
47
48
/*
49
 * PKCS5 PBKDF1 compatible key/IV generation as specified in:
50
 * https://tools.ietf.org/html/rfc8018#page-10
51
 */
52
53
static int kdf_pbkdf1_do_derive(const unsigned char *pass, size_t passlen,
54
                                const unsigned char *salt, size_t saltlen,
55
                                uint64_t iter, const EVP_MD *md_type,
56
                                unsigned char *out, size_t n)
57
0
{
58
0
    uint64_t i;
59
0
    int mdsize, ret = 0;
60
0
    unsigned char md_tmp[EVP_MAX_MD_SIZE];
61
0
    EVP_MD_CTX *ctx = NULL;
62
63
0
    ctx = EVP_MD_CTX_new();
64
0
    if (ctx == NULL) {
65
0
        ERR_raise(ERR_LIB_PROV, ERR_R_EVP_LIB);
66
0
        goto err;
67
0
    }
68
69
0
    if (!EVP_DigestInit_ex(ctx, md_type, NULL)
70
0
        || !EVP_DigestUpdate(ctx, pass, passlen)
71
0
        || !EVP_DigestUpdate(ctx, salt, saltlen)
72
0
        || !EVP_DigestFinal_ex(ctx, md_tmp, NULL))
73
0
        goto err;
74
0
    mdsize = EVP_MD_size(md_type);
75
0
    if (mdsize <= 0)
76
0
        goto err;
77
0
    if (n > (size_t)mdsize) {
78
0
        ERR_raise(ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE);
79
0
        goto err;
80
0
    }
81
82
0
    for (i = 1; i < iter; i++) {
83
0
        if (!EVP_DigestInit_ex(ctx, md_type, NULL))
84
0
            goto err;
85
0
        if (!EVP_DigestUpdate(ctx, md_tmp, mdsize))
86
0
            goto err;
87
0
        if (!EVP_DigestFinal_ex(ctx, md_tmp, NULL))
88
0
            goto err;
89
0
    }
90
91
0
    memcpy(out, md_tmp, n);
92
0
    ret = 1;
93
0
err:
94
0
    OPENSSL_cleanse(md_tmp, EVP_MAX_MD_SIZE);
95
0
    EVP_MD_CTX_free(ctx);
96
0
    return ret;
97
0
}
98
99
static void *kdf_pbkdf1_new(void *provctx)
100
0
{
101
0
    KDF_PBKDF1 *ctx;
102
103
0
    if (!ossl_prov_is_running())
104
0
        return NULL;
105
106
0
    ctx = OPENSSL_zalloc(sizeof(*ctx));
107
0
    if (ctx == NULL)
108
0
        return NULL;
109
0
    ctx->provctx = provctx;
110
0
    return ctx;
111
0
}
112
113
static void kdf_pbkdf1_cleanup(KDF_PBKDF1 *ctx)
114
0
{
115
0
    ossl_prov_digest_reset(&ctx->digest);
116
0
    OPENSSL_free(ctx->salt);
117
0
    OPENSSL_clear_free(ctx->pass, ctx->pass_len);
118
0
    memset(ctx, 0, sizeof(*ctx));
119
0
}
120
121
static void kdf_pbkdf1_free(void *vctx)
122
0
{
123
0
    KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
124
125
0
    if (ctx != NULL) {
126
0
        kdf_pbkdf1_cleanup(ctx);
127
0
        OPENSSL_free(ctx);
128
0
    }
129
0
}
130
131
static void kdf_pbkdf1_reset(void *vctx)
132
0
{
133
0
    KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
134
0
    void *provctx = ctx->provctx;
135
136
0
    kdf_pbkdf1_cleanup(ctx);
137
0
    ctx->provctx = provctx;
138
0
}
139
140
static void *kdf_pbkdf1_dup(void *vctx)
141
0
{
142
0
    const KDF_PBKDF1 *src = (const KDF_PBKDF1 *)vctx;
143
0
    KDF_PBKDF1 *dest;
144
145
0
    dest = kdf_pbkdf1_new(src->provctx);
146
0
    if (dest != NULL) {
147
0
        if (!ossl_prov_memdup(src->salt, src->salt_len,
148
0
                              &dest->salt, &dest->salt_len)
149
0
                || !ossl_prov_memdup(src->pass, src->pass_len,
150
0
                                     &dest->pass , &dest->pass_len)
151
0
                || !ossl_prov_digest_copy(&dest->digest, &src->digest))
152
0
            goto err;
153
0
        dest->iter = src->iter;
154
0
    }
155
0
    return dest;
156
157
0
 err:
158
0
    kdf_pbkdf1_free(dest);
159
0
    return NULL;
160
0
}
161
162
static int kdf_pbkdf1_set_membuf(unsigned char **buffer, size_t *buflen,
163
                             const OSSL_PARAM *p)
164
0
{
165
0
    OPENSSL_clear_free(*buffer, *buflen);
166
0
    *buffer = NULL;
167
0
    *buflen = 0;
168
169
0
    if (p->data_size == 0) {
170
0
        if ((*buffer = OPENSSL_malloc(1)) == NULL)
171
0
            return 0;
172
0
    } else if (p->data != NULL) {
173
0
        if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen))
174
0
            return 0;
175
0
    }
176
0
    return 1;
177
0
}
178
179
static int kdf_pbkdf1_derive(void *vctx, unsigned char *key, size_t keylen,
180
                             const OSSL_PARAM params[])
181
0
{
182
0
    KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
183
0
    const EVP_MD *md;
184
185
0
    if (!ossl_prov_is_running() || !kdf_pbkdf1_set_ctx_params(ctx, params))
186
0
        return 0;
187
188
0
    if (ctx->pass == NULL) {
189
0
        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS);
190
0
        return 0;
191
0
    }
192
193
0
    if (ctx->salt == NULL) {
194
0
        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT);
195
0
        return 0;
196
0
    }
197
198
0
    md = ossl_prov_digest_md(&ctx->digest);
199
0
    return kdf_pbkdf1_do_derive(ctx->pass, ctx->pass_len, ctx->salt, ctx->salt_len,
200
0
                                ctx->iter, md, key, keylen);
201
0
}
202
203
/* Machine generated by util/perl/OpenSSL/paramnames.pm */
204
#ifndef pbkdf1_set_ctx_params_list
205
static const OSSL_PARAM pbkdf1_set_ctx_params_list[] = {
206
    OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
207
    OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
208
    OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),
209
    OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
210
    OSSL_PARAM_uint64(OSSL_KDF_PARAM_ITER, NULL),
211
    OSSL_PARAM_END
212
};
213
#endif
214
215
#ifndef pbkdf1_set_ctx_params_st
216
struct pbkdf1_set_ctx_params_st {
217
    OSSL_PARAM *digest;
218
    OSSL_PARAM *engine;
219
    OSSL_PARAM *iter;
220
    OSSL_PARAM *propq;
221
    OSSL_PARAM *pw;
222
    OSSL_PARAM *salt;
223
};
224
#endif
225
226
#ifndef pbkdf1_set_ctx_params_decoder
227
static int pbkdf1_set_ctx_params_decoder
228
    (const OSSL_PARAM *p, struct pbkdf1_set_ctx_params_st *r)
229
0
{
230
0
    const char *s;
231
232
0
    memset(r, 0, sizeof(*r));
233
0
    if (p != NULL)
234
0
        for (; (s = p->key) != NULL; p++)
235
0
            switch(s[0]) {
236
0
            default:
237
0
                break;
238
0
            case 'd':
239
0
                if (ossl_likely(strcmp("igest", s + 1) == 0)) {
240
                    /* KDF_PARAM_DIGEST */
241
0
                    if (ossl_unlikely(r->digest != NULL)) {
242
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
243
0
                                       "param %s is repeated", s);
244
0
                        return 0;
245
0
                    }
246
0
                    r->digest = (OSSL_PARAM *)p;
247
0
                }
248
0
                break;
249
0
            case 'e':
250
0
                if (ossl_likely(strcmp("ngine", s + 1) == 0)) {
251
                    /* ALG_PARAM_ENGINE */
252
0
                    if (ossl_unlikely(r->engine != NULL)) {
253
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
254
0
                                       "param %s is repeated", s);
255
0
                        return 0;
256
0
                    }
257
0
                    r->engine = (OSSL_PARAM *)p;
258
0
                }
259
0
                break;
260
0
            case 'i':
261
0
                if (ossl_likely(strcmp("ter", s + 1) == 0)) {
262
                    /* KDF_PARAM_ITER */
263
0
                    if (ossl_unlikely(r->iter != NULL)) {
264
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
265
0
                                       "param %s is repeated", s);
266
0
                        return 0;
267
0
                    }
268
0
                    r->iter = (OSSL_PARAM *)p;
269
0
                }
270
0
                break;
271
0
            case 'p':
272
0
                switch(s[1]) {
273
0
                default:
274
0
                    break;
275
0
                case 'a':
276
0
                    if (ossl_likely(strcmp("ss", s + 2) == 0)) {
277
                        /* KDF_PARAM_PASSWORD */
278
0
                        if (ossl_unlikely(r->pw != NULL)) {
279
0
                            ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
280
0
                                           "param %s is repeated", s);
281
0
                            return 0;
282
0
                        }
283
0
                        r->pw = (OSSL_PARAM *)p;
284
0
                    }
285
0
                    break;
286
0
                case 'r':
287
0
                    if (ossl_likely(strcmp("operties", s + 2) == 0)) {
288
                        /* KDF_PARAM_PROPERTIES */
289
0
                        if (ossl_unlikely(r->propq != NULL)) {
290
0
                            ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
291
0
                                           "param %s is repeated", s);
292
0
                            return 0;
293
0
                        }
294
0
                        r->propq = (OSSL_PARAM *)p;
295
0
                    }
296
0
                }
297
0
                break;
298
0
            case 's':
299
0
                if (ossl_likely(strcmp("alt", s + 1) == 0)) {
300
                    /* KDF_PARAM_SALT */
301
0
                    if (ossl_unlikely(r->salt != NULL)) {
302
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
303
0
                                       "param %s is repeated", s);
304
0
                        return 0;
305
0
                    }
306
0
                    r->salt = (OSSL_PARAM *)p;
307
0
                }
308
0
            }
309
0
    return 1;
310
0
}
311
#endif
312
/* End of machine generated */
313
314
static int kdf_pbkdf1_set_ctx_params(void *vctx, const OSSL_PARAM params[])
315
0
{
316
0
    struct pbkdf1_set_ctx_params_st p;
317
0
    KDF_PBKDF1 *ctx = vctx;
318
0
    OSSL_LIB_CTX *libctx;
319
320
0
    if (ctx == NULL || !pbkdf1_set_ctx_params_decoder(params, &p))
321
0
        return 0;
322
323
0
    libctx = PROV_LIBCTX_OF(ctx->provctx);
324
325
0
    if (!ossl_prov_digest_load(&ctx->digest, p.digest,
326
0
                               p.propq, p.engine, libctx))
327
0
        return 0;
328
329
0
    if (p.pw != NULL && !kdf_pbkdf1_set_membuf(&ctx->pass, &ctx->pass_len, p.pw))
330
0
        return 0;
331
332
0
    if (p.salt != NULL && !kdf_pbkdf1_set_membuf(&ctx->salt, &ctx->salt_len, p.salt))
333
0
        return 0;
334
335
0
    if (p.iter != NULL && !OSSL_PARAM_get_uint64(p.iter, &ctx->iter))
336
0
            return 0;
337
0
    return 1;
338
0
}
339
340
static const OSSL_PARAM *kdf_pbkdf1_settable_ctx_params(ossl_unused void *ctx,
341
                                                        ossl_unused void *p_ctx)
342
0
{
343
0
    return pbkdf1_set_ctx_params_list;
344
0
}
345
346
/* Machine generated by util/perl/OpenSSL/paramnames.pm */
347
#ifndef pbkdf1_get_ctx_params_list
348
static const OSSL_PARAM pbkdf1_get_ctx_params_list[] = {
349
    OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
350
    OSSL_PARAM_END
351
};
352
#endif
353
354
#ifndef pbkdf1_get_ctx_params_st
355
struct pbkdf1_get_ctx_params_st {
356
    OSSL_PARAM *size;
357
};
358
#endif
359
360
#ifndef pbkdf1_get_ctx_params_decoder
361
static int pbkdf1_get_ctx_params_decoder
362
    (const OSSL_PARAM *p, struct pbkdf1_get_ctx_params_st *r)
363
0
{
364
0
    const char *s;
365
366
0
    memset(r, 0, sizeof(*r));
367
0
    if (p != NULL)
368
0
        for (; (s = p->key) != NULL; p++)
369
0
            if (ossl_likely(strcmp("size", s + 0) == 0)) {
370
                /* KDF_PARAM_SIZE */
371
0
                if (ossl_unlikely(r->size != NULL)) {
372
0
                    ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
373
0
                                   "param %s is repeated", s);
374
0
                    return 0;
375
0
                }
376
0
                r->size = (OSSL_PARAM *)p;
377
0
            }
378
0
    return 1;
379
0
}
380
#endif
381
/* End of machine generated */
382
383
static int kdf_pbkdf1_get_ctx_params(void *vctx, OSSL_PARAM params[])
384
0
{
385
0
    struct pbkdf1_get_ctx_params_st p;
386
0
    KDF_PBKDF1 *ctx = vctx;
387
388
0
    if (ctx == NULL || !pbkdf1_get_ctx_params_decoder(params, &p))
389
0
        return 0;
390
391
0
    if (p.size != NULL && !OSSL_PARAM_set_size_t(p.size, SIZE_MAX))
392
0
        return 0;
393
0
    return 1;
394
0
}
395
396
static const OSSL_PARAM *kdf_pbkdf1_gettable_ctx_params(ossl_unused void *ctx,
397
                                                        ossl_unused void *p_ctx)
398
0
{
399
0
    return pbkdf1_get_ctx_params_list;
400
0
}
401
402
const OSSL_DISPATCH ossl_kdf_pbkdf1_functions[] = {
403
    { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pbkdf1_new },
404
    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_pbkdf1_dup },
405
    { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pbkdf1_free },
406
    { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pbkdf1_reset },
407
    { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pbkdf1_derive },
408
    { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
409
      (void(*)(void))kdf_pbkdf1_settable_ctx_params },
410
    { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_pbkdf1_set_ctx_params },
411
    { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
412
      (void(*)(void))kdf_pbkdf1_gettable_ctx_params },
413
    { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_pbkdf1_get_ctx_params },
414
    OSSL_DISPATCH_END
415
};