Coverage Report

Created: 2025-06-13 06:58

/src/openssl32/providers/implementations/kdfs/hmacdrbg_kdf.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2022-2023 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 <stdlib.h>
11
#include <string.h>
12
#include <openssl/crypto.h>
13
#include <openssl/err.h>
14
#include <openssl/kdf.h>
15
#include <openssl/proverr.h>
16
#include <openssl/core_names.h>
17
#include "prov/providercommon.h"
18
#include "prov/implementations.h"
19
#include "prov/hmac_drbg.h"
20
#include "prov/provider_ctx.h"
21
22
static OSSL_FUNC_kdf_newctx_fn hmac_drbg_kdf_new;
23
static OSSL_FUNC_kdf_dupctx_fn hmac_drbg_kdf_dup;
24
static OSSL_FUNC_kdf_freectx_fn hmac_drbg_kdf_free;
25
static OSSL_FUNC_kdf_reset_fn hmac_drbg_kdf_reset;
26
static OSSL_FUNC_kdf_derive_fn hmac_drbg_kdf_derive;
27
static OSSL_FUNC_kdf_settable_ctx_params_fn hmac_drbg_kdf_settable_ctx_params;
28
static OSSL_FUNC_kdf_set_ctx_params_fn hmac_drbg_kdf_set_ctx_params;
29
static OSSL_FUNC_kdf_gettable_ctx_params_fn hmac_drbg_kdf_gettable_ctx_params;
30
static OSSL_FUNC_kdf_get_ctx_params_fn hmac_drbg_kdf_get_ctx_params;
31
32
typedef struct {
33
    PROV_DRBG_HMAC base;
34
    void *provctx;
35
    unsigned char *entropy, *nonce;
36
    size_t entropylen, noncelen;
37
    int init;
38
} KDF_HMAC_DRBG;
39
40
static void *hmac_drbg_kdf_new(void *provctx)
41
142
{
42
142
    KDF_HMAC_DRBG *ctx;
43
44
142
    if (!ossl_prov_is_running())
45
0
        return NULL;
46
47
142
    ctx = OPENSSL_zalloc(sizeof(*ctx));
48
142
    if (ctx == NULL) {
49
0
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
50
0
        return NULL;
51
0
    }
52
142
    ctx->provctx = provctx;
53
142
    return ctx;
54
142
}
55
56
static void hmac_drbg_kdf_reset(void *vctx)
57
142
{
58
142
    KDF_HMAC_DRBG *ctx = (KDF_HMAC_DRBG *)vctx;
59
142
    PROV_DRBG_HMAC *drbg = &ctx->base;
60
142
    void *provctx = ctx->provctx;
61
62
142
    EVP_MAC_CTX_free(drbg->ctx);
63
142
    ossl_prov_digest_reset(&drbg->digest);
64
142
    OPENSSL_clear_free(ctx->entropy, ctx->entropylen);
65
142
    OPENSSL_clear_free(ctx->nonce, ctx->noncelen);
66
142
    OPENSSL_cleanse(ctx, sizeof(*ctx));
67
142
    ctx->provctx = provctx;
68
142
}
69
70
static void hmac_drbg_kdf_free(void *vctx)
71
142
{
72
142
    KDF_HMAC_DRBG *ctx = (KDF_HMAC_DRBG *)vctx;
73
74
142
    if (ctx != NULL) {
75
142
        hmac_drbg_kdf_reset(ctx);
76
142
        OPENSSL_free(ctx);
77
142
    }
78
142
}
79
80
0
static int ossl_drbg_hmac_dup(PROV_DRBG_HMAC *dst, const PROV_DRBG_HMAC *src) {
81
0
    if (src->ctx != NULL) {
82
0
        dst->ctx = EVP_MAC_CTX_dup(src->ctx);
83
0
        if (dst->ctx == NULL)
84
0
            return 0;
85
0
    }
86
0
    if (!ossl_prov_digest_copy(&dst->digest, &src->digest))
87
0
        return 0;
88
0
    memcpy(dst->K, src->K, sizeof(dst->K));
89
0
    memcpy(dst->V, src->V, sizeof(dst->V));
90
0
    dst->blocklen = src->blocklen;
91
0
    return 1;
92
0
}
93
94
static void *hmac_drbg_kdf_dup(void *vctx)
95
0
{
96
0
    const KDF_HMAC_DRBG *src = (const KDF_HMAC_DRBG *)vctx;
97
0
    KDF_HMAC_DRBG *dst;
98
99
0
    dst = hmac_drbg_kdf_new(src->provctx);
100
0
    if (dst != NULL) {
101
0
        if (!ossl_drbg_hmac_dup(&dst->base, &src->base)
102
0
                || !ossl_prov_memdup(src->entropy, src->entropylen,
103
0
                                     &dst->entropy , &dst->entropylen)
104
0
                || !ossl_prov_memdup(src->nonce, src->noncelen,
105
0
                                     &dst->nonce, &dst->noncelen))
106
0
            goto err;
107
0
        dst->init = src->init;
108
0
    }
109
0
    return dst;
110
111
0
 err:
112
0
    hmac_drbg_kdf_free(dst);
113
0
    return NULL;
114
0
}
115
116
static int hmac_drbg_kdf_derive(void *vctx, unsigned char *out, size_t outlen,
117
                                const OSSL_PARAM params[])
118
135
{
119
135
    KDF_HMAC_DRBG *ctx = (KDF_HMAC_DRBG *)vctx;
120
135
    PROV_DRBG_HMAC *drbg = &ctx->base;
121
122
135
    if (!ossl_prov_is_running()
123
135
            || !hmac_drbg_kdf_set_ctx_params(vctx, params))
124
0
        return 0;
125
135
    if (!ctx->init) {
126
135
        if (ctx->entropy == NULL
127
135
                || ctx->entropylen == 0
128
135
                || ctx->nonce == NULL
129
135
                || ctx->noncelen == 0
130
135
                || !ossl_drbg_hmac_init(drbg, ctx->entropy, ctx->entropylen,
131
123
                                        ctx->nonce, ctx->noncelen, NULL, 0))
132
12
            return 0;
133
123
        ctx->init = 1;
134
123
    }
135
136
123
    return ossl_drbg_hmac_generate(drbg, out, outlen, NULL, 0);
137
135
}
138
139
static int hmac_drbg_kdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
140
0
{
141
0
    KDF_HMAC_DRBG *hmac = (KDF_HMAC_DRBG *)vctx;
142
0
    PROV_DRBG_HMAC *drbg = &hmac->base;
143
0
    const char *name;
144
0
    const EVP_MD *md;
145
0
    OSSL_PARAM *p;
146
147
0
    p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_MAC);
148
0
    if (p != NULL) {
149
0
        if (drbg->ctx == NULL)
150
0
            return 0;
151
0
        name = EVP_MAC_get0_name(EVP_MAC_CTX_get0_mac(drbg->ctx));
152
0
        if (!OSSL_PARAM_set_utf8_string(p, name))
153
0
            return 0;
154
0
    }
155
156
0
    p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_DIGEST);
157
0
    if (p != NULL) {
158
0
        md = ossl_prov_digest_md(&drbg->digest);
159
0
        if (md == NULL || !OSSL_PARAM_set_utf8_string(p, EVP_MD_get0_name(md)))
160
0
            return 0;
161
0
    }
162
0
    return 1;
163
0
}
164
165
static const OSSL_PARAM *hmac_drbg_kdf_gettable_ctx_params(
166
    ossl_unused void *vctx, ossl_unused void *p_ctx)
167
0
{
168
0
    static const OSSL_PARAM known_gettable_ctx_params[] = {
169
0
        OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MAC, NULL, 0),
170
0
        OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
171
0
        OSSL_PARAM_END
172
0
    };
173
0
    return known_gettable_ctx_params;
174
0
}
175
176
static int hmac_drbg_kdf_set_ctx_params(void *vctx,
177
                                        const OSSL_PARAM params[])
178
0
{
179
0
    KDF_HMAC_DRBG *hmac = (KDF_HMAC_DRBG *)vctx;
180
0
    PROV_DRBG_HMAC *drbg = &hmac->base;
181
0
    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(hmac->provctx);
182
0
    const EVP_MD *md;
183
0
    const OSSL_PARAM *p;
184
0
    void *ptr = NULL;
185
0
    size_t size = 0;
186
187
0
    if (params == NULL)
188
0
        return 1;
189
190
0
    p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_HMACDRBG_ENTROPY);
191
0
    if (p != NULL) {
192
0
        if (!OSSL_PARAM_get_octet_string(p, &ptr, 0, &size))
193
0
            return 0;
194
0
        OPENSSL_free(hmac->entropy);
195
0
        hmac->entropy = ptr;
196
0
        hmac->entropylen = size;
197
0
        hmac->init = 0;
198
0
        ptr = NULL;
199
0
    }
200
201
0
    p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_HMACDRBG_NONCE);
202
0
    if (p != NULL) {
203
0
        if (!OSSL_PARAM_get_octet_string(p, &ptr, 0, &size))
204
0
            return 0;
205
0
        OPENSSL_free(hmac->nonce);
206
0
        hmac->nonce = ptr;
207
0
        hmac->noncelen = size;
208
0
        hmac->init = 0;
209
0
    }
210
211
0
    p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST);
212
0
    if (p != NULL) {
213
0
        if (!ossl_prov_digest_load_from_params(&drbg->digest, params, libctx))
214
0
            return 0;
215
216
        /* Confirm digest is allowed. Allow all digests that are not XOF */
217
0
        md = ossl_prov_digest_md(&drbg->digest);
218
0
        if (md != NULL) {
219
0
            if ((EVP_MD_get_flags(md) & EVP_MD_FLAG_XOF) != 0) {
220
0
                ERR_raise(ERR_LIB_PROV, PROV_R_XOF_DIGESTS_NOT_ALLOWED);
221
0
                return 0;
222
0
            }
223
0
            drbg->blocklen = EVP_MD_get_size(md);
224
0
        }
225
0
        return ossl_prov_macctx_load_from_params(&drbg->ctx, params,
226
0
                                                 "HMAC", NULL, NULL, libctx);
227
0
    }
228
0
    return 1;
229
0
}
230
231
static const OSSL_PARAM *hmac_drbg_kdf_settable_ctx_params(
232
    ossl_unused void *vctx, ossl_unused void *p_ctx)
233
142
{
234
142
    static const OSSL_PARAM known_settable_ctx_params[] = {
235
142
        OSSL_PARAM_octet_string(OSSL_KDF_PARAM_HMACDRBG_ENTROPY, NULL, 0),
236
142
        OSSL_PARAM_octet_string(OSSL_KDF_PARAM_HMACDRBG_NONCE, NULL, 0),
237
142
        OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
238
142
        OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
239
142
        OSSL_PARAM_END
240
142
    };
241
142
    return known_settable_ctx_params;
242
142
}
243
244
const OSSL_DISPATCH ossl_kdf_hmac_drbg_functions[] = {
245
    { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))hmac_drbg_kdf_new },
246
    { OSSL_FUNC_KDF_FREECTX, (void(*)(void))hmac_drbg_kdf_free },
247
    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))hmac_drbg_kdf_dup },
248
    { OSSL_FUNC_KDF_RESET, (void(*)(void))hmac_drbg_kdf_reset },
249
    { OSSL_FUNC_KDF_DERIVE, (void(*)(void))hmac_drbg_kdf_derive },
250
    { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
251
      (void(*)(void))hmac_drbg_kdf_settable_ctx_params },
252
    { OSSL_FUNC_KDF_SET_CTX_PARAMS,
253
      (void(*)(void))hmac_drbg_kdf_set_ctx_params },
254
    { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
255
      (void(*)(void))hmac_drbg_kdf_gettable_ctx_params },
256
    { OSSL_FUNC_KDF_GET_CTX_PARAMS,
257
      (void(*)(void))hmac_drbg_kdf_get_ctx_params },
258
    OSSL_DISPATCH_END
259
};