Coverage Report

Created: 2025-12-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl36/providers/implementations/kdfs/sshkdf.c
Line
Count
Source
1
/*
2
 * Copyright 2018-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
/* clang-format off */
10
11
/* clang-format on */
12
13
#include <stdlib.h>
14
#include <stdarg.h>
15
#include <string.h>
16
#include <openssl/evp.h>
17
#include <openssl/kdf.h>
18
#include <openssl/core_names.h>
19
#include <openssl/proverr.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
#include "prov/securitycheck.h"
28
29
/* See RFC 4253, Section 7.2 */
30
static OSSL_FUNC_kdf_newctx_fn kdf_sshkdf_new;
31
static OSSL_FUNC_kdf_dupctx_fn kdf_sshkdf_dup;
32
static OSSL_FUNC_kdf_freectx_fn kdf_sshkdf_free;
33
static OSSL_FUNC_kdf_reset_fn kdf_sshkdf_reset;
34
static OSSL_FUNC_kdf_derive_fn kdf_sshkdf_derive;
35
static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_sshkdf_settable_ctx_params;
36
static OSSL_FUNC_kdf_set_ctx_params_fn kdf_sshkdf_set_ctx_params;
37
static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_sshkdf_gettable_ctx_params;
38
static OSSL_FUNC_kdf_get_ctx_params_fn kdf_sshkdf_get_ctx_params;
39
40
static int SSHKDF(const EVP_MD *evp_md,
41
    const unsigned char *key, size_t key_len,
42
    const unsigned char *xcghash, size_t xcghash_len,
43
    const unsigned char *session_id, size_t session_id_len,
44
    char type, unsigned char *okey, size_t okey_len);
45
46
typedef struct {
47
    void *provctx;
48
    PROV_DIGEST digest;
49
    unsigned char *key; /* K */
50
    size_t key_len;
51
    unsigned char *xcghash; /* H */
52
    size_t xcghash_len;
53
    char type; /* X */
54
    unsigned char *session_id;
55
    size_t session_id_len;
56
    OSSL_FIPS_IND_DECLARE
57
} KDF_SSHKDF;
58
59
static void *kdf_sshkdf_new(void *provctx)
60
42
{
61
42
    KDF_SSHKDF *ctx;
62
63
42
    if (!ossl_prov_is_running())
64
0
        return NULL;
65
66
42
    if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) != NULL) {
67
42
        ctx->provctx = provctx;
68
42
        OSSL_FIPS_IND_INIT(ctx)
69
42
    }
70
42
    return ctx;
71
42
}
72
73
static void kdf_sshkdf_free(void *vctx)
74
42
{
75
42
    KDF_SSHKDF *ctx = (KDF_SSHKDF *)vctx;
76
77
42
    if (ctx != NULL) {
78
42
        kdf_sshkdf_reset(ctx);
79
42
        OPENSSL_free(ctx);
80
42
    }
81
42
}
82
83
static void kdf_sshkdf_reset(void *vctx)
84
42
{
85
42
    KDF_SSHKDF *ctx = (KDF_SSHKDF *)vctx;
86
42
    void *provctx = ctx->provctx;
87
88
42
    ossl_prov_digest_reset(&ctx->digest);
89
42
    OPENSSL_clear_free(ctx->key, ctx->key_len);
90
42
    OPENSSL_clear_free(ctx->xcghash, ctx->xcghash_len);
91
42
    OPENSSL_clear_free(ctx->session_id, ctx->session_id_len);
92
42
    memset(ctx, 0, sizeof(*ctx));
93
42
    ctx->provctx = provctx;
94
42
}
95
96
static void *kdf_sshkdf_dup(void *vctx)
97
0
{
98
0
    const KDF_SSHKDF *src = (const KDF_SSHKDF *)vctx;
99
0
    KDF_SSHKDF *dest;
100
101
0
    dest = kdf_sshkdf_new(src->provctx);
102
0
    if (dest != NULL) {
103
0
        if (!ossl_prov_memdup(src->key, src->key_len,
104
0
                &dest->key, &dest->key_len)
105
0
            || !ossl_prov_memdup(src->xcghash, src->xcghash_len,
106
0
                &dest->xcghash, &dest->xcghash_len)
107
0
            || !ossl_prov_memdup(src->session_id, src->session_id_len,
108
0
                &dest->session_id, &dest->session_id_len)
109
0
            || !ossl_prov_digest_copy(&dest->digest, &src->digest))
110
0
            goto err;
111
0
        dest->type = src->type;
112
0
        OSSL_FIPS_IND_COPY(dest, src)
113
0
    }
114
0
    return dest;
115
116
0
err:
117
0
    kdf_sshkdf_free(dest);
118
0
    return NULL;
119
0
}
120
121
static int sshkdf_set_membuf(unsigned char **dst, size_t *dst_len,
122
    const OSSL_PARAM *p)
123
42
{
124
42
    OPENSSL_clear_free(*dst, *dst_len);
125
42
    *dst = NULL;
126
42
    *dst_len = 0;
127
42
    return OSSL_PARAM_get_octet_string(p, (void **)dst, 0, dst_len);
128
42
}
129
130
#ifdef FIPS_MODULE
131
static int fips_digest_check_passed(KDF_SSHKDF *ctx, const EVP_MD *md)
132
{
133
    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
134
    /*
135
     * Perform digest check
136
     *
137
     * According to NIST SP 800-135r1 section 5.2, the valid hash functions are
138
     * specified in FIPS 180-3. ACVP also only lists the same set of hash
139
     * functions.
140
     */
141
    int digest_unapproved = !EVP_MD_is_a(md, SN_sha1)
142
        && !EVP_MD_is_a(md, SN_sha224)
143
        && !EVP_MD_is_a(md, SN_sha256)
144
        && !EVP_MD_is_a(md, SN_sha384)
145
        && !EVP_MD_is_a(md, SN_sha512);
146
147
    if (digest_unapproved) {
148
        if (!OSSL_FIPS_IND_ON_UNAPPROVED(ctx, OSSL_FIPS_IND_SETTABLE0,
149
                libctx, "SSHKDF", "Digest",
150
                ossl_fips_config_sshkdf_digest_check)) {
151
            ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED);
152
            return 0;
153
        }
154
    }
155
    return 1;
156
}
157
158
static int fips_key_check_passed(KDF_SSHKDF *ctx)
159
{
160
    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
161
    int key_approved = ossl_kdf_check_key_size(ctx->key_len);
162
163
    if (!key_approved) {
164
        if (!OSSL_FIPS_IND_ON_UNAPPROVED(ctx, OSSL_FIPS_IND_SETTABLE1,
165
                libctx, "SSHKDF", "Key size",
166
                ossl_fips_config_sshkdf_key_check)) {
167
            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
168
            return 0;
169
        }
170
    }
171
    return 1;
172
}
173
#endif
174
175
static int kdf_sshkdf_derive(void *vctx, unsigned char *key, size_t keylen,
176
    const OSSL_PARAM params[])
177
0
{
178
0
    KDF_SSHKDF *ctx = (KDF_SSHKDF *)vctx;
179
0
    const EVP_MD *md;
180
181
0
    if (!ossl_prov_is_running() || !kdf_sshkdf_set_ctx_params(ctx, params))
182
0
        return 0;
183
184
0
    md = ossl_prov_digest_md(&ctx->digest);
185
0
    if (md == NULL) {
186
0
        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
187
0
        return 0;
188
0
    }
189
0
    if (ctx->key == NULL) {
190
0
        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
191
0
        return 0;
192
0
    }
193
0
    if (ctx->xcghash == NULL) {
194
0
        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_XCGHASH);
195
0
        return 0;
196
0
    }
197
0
    if (ctx->session_id == NULL) {
198
0
        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SESSION_ID);
199
0
        return 0;
200
0
    }
201
0
    if (ctx->type == 0) {
202
0
        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_TYPE);
203
0
        return 0;
204
0
    }
205
206
0
    return SSHKDF(md, ctx->key, ctx->key_len,
207
0
        ctx->xcghash, ctx->xcghash_len,
208
0
        ctx->session_id, ctx->session_id_len,
209
0
        ctx->type, key, keylen);
210
0
}
211
212
/* clang-format off */
213
/* Machine generated by util/perl/OpenSSL/paramnames.pm */
214
#ifndef sshkdf_set_ctx_params_list
215
static const OSSL_PARAM sshkdf_set_ctx_params_list[] = {
216
    OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
217
    OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
218
    OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0),
219
    OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SSHKDF_XCGHASH, NULL, 0),
220
    OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SSHKDF_SESSION_ID, NULL, 0),
221
    OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_SSHKDF_TYPE, NULL, 0),
222
# if defined(FIPS_MODULE)
223
    OSSL_PARAM_int(OSSL_KDF_PARAM_FIPS_DIGEST_CHECK, NULL),
224
# endif
225
# if defined(FIPS_MODULE)
226
    OSSL_PARAM_int(OSSL_KDF_PARAM_FIPS_KEY_CHECK, NULL),
227
# endif
228
    OSSL_PARAM_END
229
};
230
#endif
231
232
#ifndef sshkdf_set_ctx_params_st
233
struct sshkdf_set_ctx_params_st {
234
    OSSL_PARAM *digest;
235
    OSSL_PARAM *engine;
236
# if defined(FIPS_MODULE)
237
    OSSL_PARAM *ind_d;
238
# endif
239
# if defined(FIPS_MODULE)
240
    OSSL_PARAM *ind_k;
241
# endif
242
    OSSL_PARAM *key;
243
    OSSL_PARAM *propq;
244
    OSSL_PARAM *sid;
245
    OSSL_PARAM *type;
246
    OSSL_PARAM *xcg;
247
};
248
#endif
249
250
#ifndef sshkdf_set_ctx_params_decoder
251
static int sshkdf_set_ctx_params_decoder
252
    (const OSSL_PARAM *p, struct sshkdf_set_ctx_params_st *r)
253
11
{
254
11
    const char *s;
255
256
11
    memset(r, 0, sizeof(*r));
257
11
    if (p != NULL)
258
77
        for (; (s = p->key) != NULL; p++)
259
66
            switch(s[0]) {
260
0
            default:
261
0
                break;
262
11
            case 'd':
263
11
                switch(s[1]) {
264
0
                default:
265
0
                    break;
266
11
                case 'i':
267
11
                    switch(s[2]) {
268
0
                    default:
269
0
                        break;
270
11
                    case 'g':
271
11
                        switch(s[3]) {
272
0
                        default:
273
0
                            break;
274
11
                        case 'e':
275
11
                            switch(s[4]) {
276
0
                            default:
277
0
                                break;
278
11
                            case 's':
279
11
                                switch(s[5]) {
280
0
                                default:
281
0
                                    break;
282
11
                                case 't':
283
11
                                    switch(s[6]) {
284
0
                                    default:
285
0
                                        break;
286
0
                                    case '-':
287
# if defined(FIPS_MODULE)
288
                                        if (ossl_likely(strcmp("check", s + 7) == 0)) {
289
                                            /* OSSL_KDF_PARAM_FIPS_DIGEST_CHECK */
290
                                            if (ossl_unlikely(r->ind_d != NULL)) {
291
                                                ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
292
                                                               "param %s is repeated", s);
293
                                                return 0;
294
                                            }
295
                                            r->ind_d = (OSSL_PARAM *)p;
296
                                        }
297
# endif
298
0
                                        break;
299
11
                                    case '\0':
300
11
                                        if (ossl_unlikely(r->digest != NULL)) {
301
0
                                            ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
302
0
                                                           "param %s is repeated", s);
303
0
                                            return 0;
304
0
                                        }
305
11
                                        r->digest = (OSSL_PARAM *)p;
306
11
                                    }
307
11
                                }
308
11
                            }
309
11
                        }
310
11
                    }
311
11
                }
312
11
                break;
313
11
            case 'e':
314
0
                if (ossl_likely(strcmp("ngine", s + 1) == 0)) {
315
                    /* OSSL_ALG_PARAM_ENGINE */
316
0
                    if (ossl_unlikely(r->engine != NULL)) {
317
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
318
0
                                       "param %s is repeated", s);
319
0
                        return 0;
320
0
                    }
321
0
                    r->engine = (OSSL_PARAM *)p;
322
0
                }
323
0
                break;
324
11
            case 'k':
325
11
                switch(s[1]) {
326
0
                default:
327
0
                    break;
328
11
                case 'e':
329
11
                    switch(s[2]) {
330
0
                    default:
331
0
                        break;
332
11
                    case 'y':
333
11
                        switch(s[3]) {
334
0
                        default:
335
0
                            break;
336
0
                        case '-':
337
# if defined(FIPS_MODULE)
338
                            if (ossl_likely(strcmp("check", s + 4) == 0)) {
339
                                /* OSSL_KDF_PARAM_FIPS_KEY_CHECK */
340
                                if (ossl_unlikely(r->ind_k != NULL)) {
341
                                    ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
342
                                                   "param %s is repeated", s);
343
                                    return 0;
344
                                }
345
                                r->ind_k = (OSSL_PARAM *)p;
346
                            }
347
# endif
348
0
                            break;
349
11
                        case '\0':
350
11
                            if (ossl_unlikely(r->key != NULL)) {
351
0
                                ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
352
0
                                               "param %s is repeated", s);
353
0
                                return 0;
354
0
                            }
355
11
                            r->key = (OSSL_PARAM *)p;
356
11
                        }
357
11
                    }
358
11
                }
359
11
                break;
360
11
            case 'p':
361
11
                if (ossl_likely(strcmp("roperties", s + 1) == 0)) {
362
                    /* OSSL_KDF_PARAM_PROPERTIES */
363
11
                    if (ossl_unlikely(r->propq != NULL)) {
364
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
365
0
                                       "param %s is repeated", s);
366
0
                        return 0;
367
0
                    }
368
11
                    r->propq = (OSSL_PARAM *)p;
369
11
                }
370
11
                break;
371
11
            case 's':
372
11
                if (ossl_likely(strcmp("ession_id", s + 1) == 0)) {
373
                    /* OSSL_KDF_PARAM_SSHKDF_SESSION_ID */
374
11
                    if (ossl_unlikely(r->sid != NULL)) {
375
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
376
0
                                       "param %s is repeated", s);
377
0
                        return 0;
378
0
                    }
379
11
                    r->sid = (OSSL_PARAM *)p;
380
11
                }
381
11
                break;
382
11
            case 't':
383
11
                if (ossl_likely(strcmp("ype", s + 1) == 0)) {
384
                    /* OSSL_KDF_PARAM_SSHKDF_TYPE */
385
11
                    if (ossl_unlikely(r->type != NULL)) {
386
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
387
0
                                       "param %s is repeated", s);
388
0
                        return 0;
389
0
                    }
390
11
                    r->type = (OSSL_PARAM *)p;
391
11
                }
392
11
                break;
393
11
            case 'x':
394
11
                if (ossl_likely(strcmp("cghash", s + 1) == 0)) {
395
                    /* OSSL_KDF_PARAM_SSHKDF_XCGHASH */
396
11
                    if (ossl_unlikely(r->xcg != 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
11
                    r->xcg = (OSSL_PARAM *)p;
402
11
                }
403
66
            }
404
11
    return 1;
405
11
}
406
#endif
407
/* End of machine generated */
408
/* clang-format on */
409
410
static int kdf_sshkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
411
19
{
412
19
    struct sshkdf_set_ctx_params_st p;
413
19
    KDF_SSHKDF *ctx = vctx;
414
19
    OSSL_LIB_CTX *provctx;
415
416
19
    if (ctx == NULL || !sshkdf_set_ctx_params_decoder(params, &p))
417
0
        return 0;
418
419
19
    provctx = PROV_LIBCTX_OF(ctx->provctx);
420
421
19
    if (!OSSL_FIPS_IND_SET_CTX_FROM_PARAM(ctx, OSSL_FIPS_IND_SETTABLE0, p.ind_d))
422
0
        return 0;
423
19
    if (!OSSL_FIPS_IND_SET_CTX_FROM_PARAM(ctx, OSSL_FIPS_IND_SETTABLE1, p.ind_k))
424
0
        return 0;
425
426
19
    if (p.digest != NULL) {
427
19
        const EVP_MD *md = NULL;
428
429
19
        if (!ossl_prov_digest_load(&ctx->digest, p.digest,
430
19
                p.propq, p.engine, provctx))
431
11
            return 0;
432
433
8
        md = ossl_prov_digest_md(&ctx->digest);
434
8
        if (EVP_MD_xof(md)) {
435
2
            ERR_raise(ERR_LIB_PROV, PROV_R_XOF_DIGESTS_NOT_ALLOWED);
436
2
            return 0;
437
2
        }
438
439
#ifdef FIPS_MODULE
440
        if (!fips_digest_check_passed(ctx, md))
441
            return 0;
442
#endif
443
8
    }
444
445
6
    if (p.key != NULL) {
446
6
        if (!sshkdf_set_membuf(&ctx->key, &ctx->key_len, p.key))
447
0
            return 0;
448
449
#ifdef FIPS_MODULE
450
        if (!fips_key_check_passed(ctx))
451
            return 0;
452
#endif
453
6
    }
454
455
6
    if (p.xcg != NULL
456
6
        && !sshkdf_set_membuf(&ctx->xcghash, &ctx->xcghash_len, p.xcg))
457
0
        return 0;
458
459
6
    if (p.sid != NULL
460
6
        && !sshkdf_set_membuf(&ctx->session_id, &ctx->session_id_len, p.sid))
461
0
        return 0;
462
463
6
    if (p.type != NULL) {
464
6
        const char *kdftype;
465
466
6
        if (!OSSL_PARAM_get_utf8_string_ptr(p.type, &kdftype))
467
0
            return 0;
468
        /* Expect one character (byte in this case) */
469
6
        if (kdftype == NULL || p.type->data_size != 1)
470
4
            return 0;
471
2
        if (kdftype[0] < 65 || kdftype[0] > 70) {
472
2
            ERR_raise(ERR_LIB_PROV, PROV_R_VALUE_ERROR);
473
2
            return 0;
474
2
        }
475
0
        ctx->type = kdftype[0];
476
0
    }
477
0
    return 1;
478
6
}
479
480
static const OSSL_PARAM *kdf_sshkdf_settable_ctx_params(ossl_unused void *ctx,
481
    ossl_unused void *p_ctx)
482
42
{
483
42
    return sshkdf_set_ctx_params_list;
484
42
}
485
486
/* clang-format off */
487
/* Machine generated by util/perl/OpenSSL/paramnames.pm */
488
#ifndef sshkdf_get_ctx_params_list
489
static const OSSL_PARAM sshkdf_get_ctx_params_list[] = {
490
    OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
491
# if defined(FIPS_MODULE)
492
    OSSL_PARAM_int(OSSL_KDF_PARAM_FIPS_APPROVED_INDICATOR, NULL),
493
# endif
494
    OSSL_PARAM_END
495
};
496
#endif
497
498
#ifndef sshkdf_get_ctx_params_st
499
struct sshkdf_get_ctx_params_st {
500
# if defined(FIPS_MODULE)
501
    OSSL_PARAM *ind;
502
# endif
503
    OSSL_PARAM *size;
504
};
505
#endif
506
507
#ifndef sshkdf_get_ctx_params_decoder
508
static int sshkdf_get_ctx_params_decoder
509
    (const OSSL_PARAM *p, struct sshkdf_get_ctx_params_st *r)
510
0
{
511
0
    const char *s;
512
513
0
    memset(r, 0, sizeof(*r));
514
0
    if (p != NULL)
515
0
        for (; (s = p->key) != NULL; p++)
516
0
            switch(s[0]) {
517
0
            default:
518
0
                break;
519
0
            case 'f':
520
# if defined(FIPS_MODULE)
521
                if (ossl_likely(strcmp("ips-indicator", s + 1) == 0)) {
522
                    /* OSSL_KDF_PARAM_FIPS_APPROVED_INDICATOR */
523
                    if (ossl_unlikely(r->ind != NULL)) {
524
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
525
                                       "param %s is repeated", s);
526
                        return 0;
527
                    }
528
                    r->ind = (OSSL_PARAM *)p;
529
                }
530
# endif
531
0
                break;
532
0
            case 's':
533
0
                if (ossl_likely(strcmp("ize", s + 1) == 0)) {
534
                    /* OSSL_KDF_PARAM_SIZE */
535
0
                    if (ossl_unlikely(r->size != NULL)) {
536
0
                        ERR_raise_data(ERR_LIB_PROV, PROV_R_REPEATED_PARAMETER,
537
0
                                       "param %s is repeated", s);
538
0
                        return 0;
539
0
                    }
540
0
                    r->size = (OSSL_PARAM *)p;
541
0
                }
542
0
            }
543
0
    return 1;
544
0
}
545
#endif
546
/* End of machine generated */
547
/* clang-format on */
548
549
static int kdf_sshkdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
550
0
{
551
0
    KDF_SSHKDF *ctx = (KDF_SSHKDF *)vctx;
552
0
    struct sshkdf_get_ctx_params_st p;
553
554
0
    if (ctx == NULL || !sshkdf_get_ctx_params_decoder(params, &p))
555
0
        return 0;
556
557
0
    if (p.size != NULL && !OSSL_PARAM_set_size_t(p.size, SIZE_MAX))
558
0
        return 0;
559
560
0
    if (!OSSL_FIPS_IND_GET_CTX_FROM_PARAM(ctx, p.ind))
561
0
        return 0;
562
0
    return 1;
563
0
}
564
565
static const OSSL_PARAM *kdf_sshkdf_gettable_ctx_params(ossl_unused void *ctx,
566
    ossl_unused void *p_ctx)
567
0
{
568
0
    return sshkdf_get_ctx_params_list;
569
0
}
570
571
const OSSL_DISPATCH ossl_kdf_sshkdf_functions[] = {
572
    { OSSL_FUNC_KDF_NEWCTX, (void (*)(void))kdf_sshkdf_new },
573
    { OSSL_FUNC_KDF_DUPCTX, (void (*)(void))kdf_sshkdf_dup },
574
    { OSSL_FUNC_KDF_FREECTX, (void (*)(void))kdf_sshkdf_free },
575
    { OSSL_FUNC_KDF_RESET, (void (*)(void))kdf_sshkdf_reset },
576
    { OSSL_FUNC_KDF_DERIVE, (void (*)(void))kdf_sshkdf_derive },
577
    { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
578
        (void (*)(void))kdf_sshkdf_settable_ctx_params },
579
    { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void (*)(void))kdf_sshkdf_set_ctx_params },
580
    { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
581
        (void (*)(void))kdf_sshkdf_gettable_ctx_params },
582
    { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void (*)(void))kdf_sshkdf_get_ctx_params },
583
    OSSL_DISPATCH_END
584
};
585
586
static int SSHKDF(const EVP_MD *evp_md,
587
    const unsigned char *key, size_t key_len,
588
    const unsigned char *xcghash, size_t xcghash_len,
589
    const unsigned char *session_id, size_t session_id_len,
590
    char type, unsigned char *okey, size_t okey_len)
591
0
{
592
0
    EVP_MD_CTX *md = NULL;
593
0
    unsigned char digest[EVP_MAX_MD_SIZE];
594
0
    unsigned int dsize = 0;
595
0
    size_t cursize = 0;
596
0
    int ret = 0;
597
598
0
    md = EVP_MD_CTX_new();
599
0
    if (md == NULL)
600
0
        return 0;
601
602
0
    if (!EVP_DigestInit_ex(md, evp_md, NULL))
603
0
        goto out;
604
605
0
    if (!EVP_DigestUpdate(md, key, key_len))
606
0
        goto out;
607
608
0
    if (!EVP_DigestUpdate(md, xcghash, xcghash_len))
609
0
        goto out;
610
611
0
    if (!EVP_DigestUpdate(md, &type, 1))
612
0
        goto out;
613
614
0
    if (!EVP_DigestUpdate(md, session_id, session_id_len))
615
0
        goto out;
616
617
0
    if (!EVP_DigestFinal_ex(md, digest, &dsize))
618
0
        goto out;
619
620
0
    if (okey_len < dsize) {
621
0
        memcpy(okey, digest, okey_len);
622
0
        ret = 1;
623
0
        goto out;
624
0
    }
625
626
0
    memcpy(okey, digest, dsize);
627
628
0
    for (cursize = dsize; cursize < okey_len; cursize += dsize) {
629
630
0
        if (!EVP_DigestInit_ex(md, evp_md, NULL))
631
0
            goto out;
632
633
0
        if (!EVP_DigestUpdate(md, key, key_len))
634
0
            goto out;
635
636
0
        if (!EVP_DigestUpdate(md, xcghash, xcghash_len))
637
0
            goto out;
638
639
0
        if (!EVP_DigestUpdate(md, okey, cursize))
640
0
            goto out;
641
642
0
        if (!EVP_DigestFinal_ex(md, digest, &dsize))
643
0
            goto out;
644
645
0
        if (okey_len < cursize + dsize) {
646
0
            memcpy(okey + cursize, digest, okey_len - cursize);
647
0
            ret = 1;
648
0
            goto out;
649
0
        }
650
651
0
        memcpy(okey + cursize, digest, dsize);
652
0
    }
653
654
0
    ret = 1;
655
656
0
out:
657
0
    EVP_MD_CTX_free(md);
658
0
    OPENSSL_cleanse(digest, EVP_MAX_MD_SIZE);
659
0
    return ret;
660
0
}