Coverage Report

Created: 2025-11-07 06:58

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
#include <openssl/trace.h>
11
#include <stdlib.h>
12
#include <stdarg.h>
13
#include <string.h>
14
#include <openssl/evp.h>
15
#include <openssl/kdf.h>
16
#include <openssl/core_names.h>
17
#include <openssl/proverr.h>
18
#include "internal/common.h"
19
#include "internal/cryptlib.h"
20
#include "internal/numbers.h"
21
#include "internal/skey.h"
22
#include "crypto/evp.h"
23
#include "crypto/types.h"
24
#include "prov/provider_ctx.h"
25
#include "prov/providercommon.h"
26
#include "prov/implementations.h"
27
#include "prov/provider_util.h"
28
#include "providers/implementations/kdfs/pbkdf1.inc"
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
static int kdf_pbkdf1_set_ctx_params(void *vctx, const OSSL_PARAM params[])
229
0
{
230
0
    struct pbkdf1_set_ctx_params_st p;
231
0
    KDF_PBKDF1 *ctx = vctx;
232
0
    OSSL_LIB_CTX *libctx;
233
234
0
    if (ctx == NULL || !pbkdf1_set_ctx_params_decoder(params, &p))
235
0
        return 0;
236
237
0
    libctx = PROV_LIBCTX_OF(ctx->provctx);
238
239
0
    if (!ossl_prov_digest_load(&ctx->digest, p.digest,
240
0
                               p.propq, p.engine, libctx))
241
0
        return 0;
242
243
0
    if (p.pw != NULL && !kdf_pbkdf1_set_membuf(&ctx->pass, &ctx->pass_len, p.pw))
244
0
        return 0;
245
246
0
    if (p.salt != NULL && !kdf_pbkdf1_set_membuf(&ctx->salt, &ctx->salt_len, p.salt))
247
0
        return 0;
248
249
0
    if (p.iter != NULL && !OSSL_PARAM_get_uint64(p.iter, &ctx->iter))
250
0
            return 0;
251
0
    return 1;
252
0
}
253
254
static const OSSL_PARAM *kdf_pbkdf1_settable_ctx_params(ossl_unused void *ctx,
255
                                                        ossl_unused void *p_ctx)
256
0
{
257
0
    return pbkdf1_set_ctx_params_list;
258
0
}
259
260
static int kdf_pbkdf1_get_ctx_params(void *vctx, OSSL_PARAM params[])
261
0
{
262
0
    struct pbkdf1_get_ctx_params_st p;
263
0
    KDF_PBKDF1 *ctx = vctx;
264
265
0
    if (ctx == NULL || !pbkdf1_get_ctx_params_decoder(params, &p))
266
0
        return 0;
267
268
0
    if (p.size != NULL && !OSSL_PARAM_set_size_t(p.size, SIZE_MAX))
269
0
        return 0;
270
0
    return 1;
271
0
}
272
273
static const OSSL_PARAM *kdf_pbkdf1_gettable_ctx_params(ossl_unused void *ctx,
274
                                                        ossl_unused void *p_ctx)
275
0
{
276
0
    return pbkdf1_get_ctx_params_list;
277
0
}
278
279
static int kdf_pbkdf1_set_skey(void *vctx, void *skeydata, const char *paramname)
280
0
{
281
0
    KDF_PBKDF1 *ctx = (KDF_PBKDF1 *)vctx;
282
0
    PROV_SKEY *pskey = (PROV_SKEY *)skeydata;
283
284
0
    if (paramname == NULL || skeydata == NULL)
285
0
        return 0;
286
287
0
    if (strcmp(paramname, OSSL_KDF_PARAM_PASSWORD) == 0)
288
0
        return kdf_pbkdf1_set_membuf_skey(&ctx->pass, &ctx->pass_len, pskey);
289
290
0
    if (strcmp(paramname, OSSL_KDF_PARAM_SALT) == 0)
291
0
        return kdf_pbkdf1_set_membuf_skey(&ctx->salt, &ctx->salt_len, pskey);
292
293
0
    return 0;
294
0
}
295
296
static
297
void *kdf_pbkdf1_derive_skey(void *vctx, const char *key_type ossl_unused, void *provctx,
298
                             OSSL_FUNC_skeymgmt_import_fn *import,
299
                             size_t keylen, const OSSL_PARAM params[])
300
0
{
301
0
    unsigned char *key = NULL;
302
0
    void *ret = NULL;
303
0
    OSSL_PARAM import_params[2] = {OSSL_PARAM_END, OSSL_PARAM_END};
304
305
0
    if (import == NULL || keylen == 0)
306
0
        return NULL;
307
308
0
    if ((key = OPENSSL_zalloc(keylen)) == NULL)
309
0
        return NULL;
310
311
0
    if (kdf_pbkdf1_derive(vctx, key, keylen, params) == 0) {
312
0
        OPENSSL_free(key);
313
0
        return NULL;
314
0
    }
315
316
0
    import_params[0] = OSSL_PARAM_construct_octet_string(OSSL_SKEY_PARAM_RAW_BYTES,
317
0
                                                         (void *)key, keylen);
318
319
0
    ret = import(provctx, OSSL_SKEYMGMT_SELECT_SECRET_KEY, import_params);
320
0
    OPENSSL_free(key);
321
322
0
    return ret;
323
0
}
324
325
const OSSL_DISPATCH ossl_kdf_pbkdf1_functions[] = {
326
    { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pbkdf1_new },
327
    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_pbkdf1_dup },
328
    { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pbkdf1_free },
329
    { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pbkdf1_reset },
330
    { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pbkdf1_derive },
331
    { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
332
      (void(*)(void))kdf_pbkdf1_settable_ctx_params },
333
    { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_pbkdf1_set_ctx_params },
334
    { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
335
      (void(*)(void))kdf_pbkdf1_gettable_ctx_params },
336
    { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_pbkdf1_get_ctx_params },
337
    { OSSL_FUNC_KDF_SET_SKEY, (void(*)(void))kdf_pbkdf1_set_skey },
338
    { OSSL_FUNC_KDF_DERIVE_SKEY, (void(*)(void))kdf_pbkdf1_derive_skey },
339
    OSSL_DISPATCH_END
340
};