Coverage Report

Created: 2025-08-25 06:30

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