Coverage Report

Created: 2026-02-05 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libssh/src/dh_crypto.c
Line
Count
Source
1
/*
2
 * This file is part of the SSH Library
3
 *
4
 * Copyright (c) 2019 by Simo Sorce - Red Hat, Inc.
5
 *
6
 * The SSH Library is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU Lesser General Public License as published by
8
 * the Free Software Foundation; either version 2.1 of the License, or (at your
9
 * option) any later version.
10
 *
11
 * The SSH Library is distributed in the hope that it will be useful, but
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14
 * License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with the SSH Library; see the file COPYING.  If not, write to
18
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19
 * MA 02111-1307, USA.
20
 */
21
22
#include "config.h"
23
#include "libssh/session.h"
24
#include "libssh/dh.h"
25
#include "libssh/buffer.h"
26
#include "libssh/ssh2.h"
27
#include "libssh/pki.h"
28
#include "libssh/bignum.h"
29
30
#include "openssl/crypto.h"
31
#include "openssl/dh.h"
32
#include "libcrypto-compat.h"
33
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
34
#include <openssl/evp.h>
35
#include <openssl/params.h>
36
#include <openssl/core_names.h>
37
#include <openssl/param_build.h>
38
#include <openssl/err.h>
39
#endif /* OPENSSL_VERSION_NUMBER */
40
41
extern bignum ssh_dh_generator;
42
extern bignum ssh_dh_group1;
43
extern bignum ssh_dh_group14;
44
extern bignum ssh_dh_group16;
45
extern bignum ssh_dh_group18;
46
47
struct dh_ctx {
48
#if OPENSSL_VERSION_NUMBER < 0x30000000L
49
    DH *keypair[2];
50
#else
51
    EVP_PKEY *keypair[2];
52
#endif /* OPENSSL_VERSION_NUMBER */
53
};
54
55
void ssh_dh_debug_crypto(struct ssh_crypto_struct *c)
56
270
{
57
#ifdef DEBUG_CRYPTO
58
#if OPENSSL_VERSION_NUMBER < 0x30000000L
59
    const_bignum x = NULL, y = NULL, e = NULL, f = NULL;
60
#else
61
    bignum x = NULL, y = NULL, e = NULL, f = NULL;
62
#endif /* OPENSSL_VERSION_NUMBER */
63
64
    ssh_dh_keypair_get_keys(c->dh_ctx, DH_CLIENT_KEYPAIR, &x, &e);
65
    ssh_dh_keypair_get_keys(c->dh_ctx, DH_SERVER_KEYPAIR, &y, &f);
66
    ssh_print_bignum("x", x);
67
    ssh_print_bignum("y", y);
68
    ssh_print_bignum("e", e);
69
    ssh_print_bignum("f", f);
70
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
71
    bignum_safe_free(x);
72
    bignum_safe_free(y);
73
    bignum_safe_free(e);
74
    bignum_safe_free(f);
75
#endif /* OPENSSL_VERSION_NUMBER */
76
77
    ssh_log_hexdump("Session server cookie", c->server_kex.cookie, 16);
78
    ssh_log_hexdump("Session client cookie", c->client_kex.cookie, 16);
79
    ssh_print_bignum("k", c->shared_secret);
80
81
#else
82
270
    (void)c; /* UNUSED_PARAM */
83
270
#endif /* DEBUG_CRYPTO */
84
270
}
85
86
#if OPENSSL_VERSION_NUMBER < 0x30000000L
87
int ssh_dh_keypair_get_keys(struct dh_ctx *ctx, int peer,
88
                            const_bignum *priv, const_bignum *pub)
89
1.11k
{
90
1.11k
    if (((peer != DH_CLIENT_KEYPAIR) && (peer != DH_SERVER_KEYPAIR)) ||
91
1.11k
        ((priv == NULL) && (pub == NULL)) || (ctx == NULL) ||
92
1.11k
        (ctx->keypair[peer] == NULL)) {
93
0
        return SSH_ERROR;
94
0
    }
95
96
1.11k
    DH_get0_key(ctx->keypair[peer], pub, priv);
97
98
1.11k
    if (priv && (*priv == NULL || bignum_num_bits(*priv) == 0)) {
99
0
        return SSH_ERROR;
100
0
    }
101
1.11k
    if (pub && (*pub == NULL || bignum_num_bits(*pub) == 0)) {
102
4
        return SSH_ERROR;
103
4
    }
104
105
1.11k
    return SSH_OK;
106
1.11k
}
107
108
#else
109
/* If set *priv and *pub should be initialized
110
 * to NULL before calling this function*/
111
int ssh_dh_keypair_get_keys(struct dh_ctx *ctx, int peer,
112
                            bignum *priv, bignum *pub)
113
{
114
    int rc;
115
    if (((peer != DH_CLIENT_KEYPAIR) && (peer != DH_SERVER_KEYPAIR)) ||
116
        ((priv == NULL) && (pub == NULL)) || (ctx == NULL) ||
117
        (ctx->keypair[peer] == NULL)) {
118
        return SSH_ERROR;
119
    }
120
121
    if (priv) {
122
        rc = EVP_PKEY_get_bn_param(ctx->keypair[peer],
123
                                   OSSL_PKEY_PARAM_PRIV_KEY,
124
                                   priv);
125
        if (rc != 1) {
126
            return SSH_ERROR;
127
        }
128
    }
129
    if (pub) {
130
        rc = EVP_PKEY_get_bn_param(ctx->keypair[peer],
131
                                   OSSL_PKEY_PARAM_PUB_KEY,
132
                                   pub);
133
        if (rc != 1) {
134
            return SSH_ERROR;
135
        }
136
    }
137
    if (priv && (*priv == NULL || bignum_num_bits(*priv) == 0)) {
138
        if (pub && (*pub != NULL && bignum_num_bits(*pub) != 0)) {
139
            bignum_safe_free(*pub);
140
            *pub = NULL;
141
        }
142
        return SSH_ERROR;
143
    }
144
    if (pub && (*pub == NULL || bignum_num_bits(*pub) == 0)) {
145
        if (priv) {
146
            bignum_safe_free(*priv);
147
            *priv = NULL;
148
        }
149
        return SSH_ERROR;
150
    }
151
152
    return SSH_OK;
153
}
154
#endif /* OPENSSL_VERSION_NUMBER */
155
156
int ssh_dh_keypair_set_keys(struct dh_ctx *ctx, int peer,
157
                            bignum priv, bignum pub)
158
291
{
159
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
160
    int rc;
161
    OSSL_PARAM *params = NULL, *out_params = NULL, *merged_params = NULL;
162
    OSSL_PARAM_BLD *param_bld = NULL;
163
    EVP_PKEY_CTX *evp_ctx = NULL;
164
#endif /* OPENSSL_VERSION_NUMBER */
165
166
291
    if (((peer != DH_CLIENT_KEYPAIR) && (peer != DH_SERVER_KEYPAIR)) ||
167
291
        ((priv == NULL) && (pub == NULL)) || (ctx == NULL) ||
168
291
        (ctx->keypair[peer] == NULL)) {
169
0
        return SSH_ERROR;
170
0
    }
171
172
291
#if OPENSSL_VERSION_NUMBER < 0x30000000L
173
291
    (void)DH_set0_key(ctx->keypair[peer], pub, priv);
174
175
291
    return SSH_OK;
176
#else
177
    rc = EVP_PKEY_todata(ctx->keypair[peer], EVP_PKEY_KEYPAIR, &out_params);
178
    if (rc != 1) {
179
        return SSH_ERROR;
180
    }
181
182
    param_bld = OSSL_PARAM_BLD_new();
183
    if (param_bld == NULL) {
184
        rc = SSH_ERROR;
185
        goto out;
186
    }
187
188
    evp_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, ctx->keypair[peer], NULL);
189
    if (evp_ctx == NULL) {
190
        rc = SSH_ERROR;
191
        goto out;
192
    }
193
194
    rc = EVP_PKEY_fromdata_init(evp_ctx);
195
    if (rc != 1) {
196
        rc = SSH_ERROR;
197
        goto out;
198
    }
199
200
    if (priv) {
201
        rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PRIV_KEY, priv);
202
        if (rc != 1) {
203
            rc = SSH_ERROR;
204
            goto out;
205
        }
206
    }
207
    if (pub) {
208
        rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PUB_KEY, pub);
209
        if (rc != 1) {
210
            rc = SSH_ERROR;
211
            goto out;
212
        }
213
    }
214
215
    params = OSSL_PARAM_BLD_to_param(param_bld);
216
    if (params == NULL) {
217
        rc = SSH_ERROR;
218
        goto out;
219
    }
220
    OSSL_PARAM_BLD_free(param_bld);
221
222
    merged_params = OSSL_PARAM_merge(out_params, params);
223
    if (merged_params == NULL) {
224
        rc = SSH_ERROR;
225
        goto out;
226
    }
227
228
    rc = EVP_PKEY_fromdata(evp_ctx,
229
                           &(ctx->keypair[peer]),
230
                           EVP_PKEY_PUBLIC_KEY,
231
                           merged_params);
232
    if (rc != 1) {
233
        rc = SSH_ERROR;
234
        goto out;
235
    }
236
237
    rc = SSH_OK;
238
out:
239
    bignum_safe_free(priv);
240
    bignum_safe_free(pub);
241
    EVP_PKEY_CTX_free(evp_ctx);
242
    OSSL_PARAM_free(out_params);
243
    OSSL_PARAM_free(params);
244
    OSSL_PARAM_free(merged_params);
245
246
    return rc;
247
#endif /* OPENSSL_VERSION_NUMBER */
248
291
}
249
250
#if OPENSSL_VERSION_NUMBER < 0x30000000L
251
int ssh_dh_get_parameters(struct dh_ctx *ctx,
252
                          const_bignum *modulus, const_bignum *generator)
253
7
{
254
7
    if (ctx == NULL || ctx->keypair[0] == NULL) {
255
0
        return SSH_ERROR;
256
0
    }
257
7
    DH_get0_pqg(ctx->keypair[0], modulus, NULL, generator);
258
7
    return SSH_OK;
259
7
}
260
#else
261
int ssh_dh_get_parameters(struct dh_ctx *ctx,
262
                          bignum *modulus, bignum *generator)
263
{
264
    int rc;
265
266
    if (ctx == NULL || ctx->keypair[0] == NULL) {
267
        return SSH_ERROR;
268
    }
269
270
    rc = EVP_PKEY_get_bn_param(ctx->keypair[0], OSSL_PKEY_PARAM_FFC_P, (BIGNUM**)modulus);
271
    if (rc != 1) {
272
        return SSH_ERROR;
273
    }
274
    rc = EVP_PKEY_get_bn_param(ctx->keypair[0], OSSL_PKEY_PARAM_FFC_G, (BIGNUM**)generator);
275
    if (rc != 1) {
276
        bignum_safe_free(*modulus);
277
        return SSH_ERROR;
278
    }
279
280
    return SSH_OK;
281
}
282
#endif /* OPENSSL_VERSION_NUMBER */
283
284
int ssh_dh_set_parameters(struct dh_ctx *ctx,
285
                          const bignum modulus, const bignum generator)
286
405
{
287
405
    size_t i;
288
405
    int rc;
289
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
290
    OSSL_PARAM *params = NULL;
291
    OSSL_PARAM_BLD *param_bld = NULL;
292
    EVP_PKEY_CTX *evp_ctx = NULL;
293
#endif /* OPENSSL_VERSION_NUMBER */
294
295
405
    if ((ctx == NULL) || (modulus == NULL) || (generator == NULL)) {
296
0
        return SSH_ERROR;
297
0
    }
298
299
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
300
    evp_ctx = EVP_PKEY_CTX_new_from_name(NULL, "DHX", NULL);
301
#endif
302
303
1.21k
    for (i = 0; i < 2; i++) {
304
810
#if OPENSSL_VERSION_NUMBER < 0x30000000L
305
810
        bignum p = NULL;
306
810
        bignum g = NULL;
307
308
        /* when setting modulus or generator,
309
         * make sure to invalidate existing keys */
310
810
        DH_free(ctx->keypair[i]);
311
810
        ctx->keypair[i] = DH_new();
312
810
        if (ctx->keypair[i] == NULL) {
313
0
            rc = SSH_ERROR;
314
0
            goto done;
315
0
        }
316
317
810
        p = BN_dup(modulus);
318
810
        g = BN_dup(generator);
319
810
        rc = DH_set0_pqg(ctx->keypair[i], p, NULL, g);
320
810
        if (rc != 1) {
321
0
            BN_free(p);
322
0
            BN_free(g);
323
0
            rc = SSH_ERROR;
324
0
            goto done;
325
0
        }
326
#else
327
        param_bld = OSSL_PARAM_BLD_new();
328
329
        if (param_bld == NULL) {
330
            rc = SSH_ERROR;
331
            goto done;
332
        }
333
334
        rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, modulus);
335
        if (rc != 1) {
336
            rc = SSH_ERROR;
337
            goto done;
338
        }
339
        rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, generator);
340
        if (rc != 1) {
341
            rc = SSH_ERROR;
342
            goto done;
343
        }
344
        params = OSSL_PARAM_BLD_to_param(param_bld);
345
        if (params == NULL) {
346
            OSSL_PARAM_BLD_free(param_bld);
347
            rc = SSH_ERROR;
348
            goto done;
349
        }
350
        OSSL_PARAM_BLD_free(param_bld);
351
352
        rc = EVP_PKEY_fromdata_init(evp_ctx);
353
        if (rc != 1) {
354
            OSSL_PARAM_free(params);
355
            rc = SSH_ERROR;
356
            goto done;
357
        }
358
359
        /* make sure to invalidate existing keys */
360
        EVP_PKEY_free(ctx->keypair[i]);
361
        ctx->keypair[i] = NULL;
362
363
        rc = EVP_PKEY_fromdata(evp_ctx,
364
                               &(ctx->keypair[i]),
365
                               EVP_PKEY_KEY_PARAMETERS,
366
                               params);
367
        if (rc != 1) {
368
            OSSL_PARAM_free(params);
369
            rc = SSH_ERROR;
370
            goto done;
371
        }
372
373
        OSSL_PARAM_free(params);
374
#endif /* OPENSSL_VERSION_NUMBER */
375
810
    }
376
377
405
    rc = SSH_OK;
378
405
#if OPENSSL_VERSION_NUMBER < 0x30000000L
379
405
done:
380
405
    if (rc != SSH_OK) {
381
0
        DH_free(ctx->keypair[0]);
382
0
        DH_free(ctx->keypair[1]);
383
0
    }
384
#else
385
done:
386
    EVP_PKEY_CTX_free(evp_ctx);
387
388
    if (rc != SSH_OK) {
389
        EVP_PKEY_free(ctx->keypair[0]);
390
        EVP_PKEY_free(ctx->keypair[1]);
391
    }
392
#endif /* OPENSSL_VERSION_NUMBER */
393
405
    if (rc != SSH_OK) {
394
0
        ctx->keypair[0] = NULL;
395
0
        ctx->keypair[1] = NULL;
396
0
    }
397
398
405
    return rc;
399
405
}
400
401
/**
402
 * @internal
403
 * @brief allocate and initialize ephemeral values used in dh kex
404
 */
405
int ssh_dh_init_common(struct ssh_crypto_struct *crypto)
406
577
{
407
577
    struct dh_ctx *ctx = NULL;
408
577
    int rc;
409
410
    /* Cleanup any previously allocated dh_ctx */
411
577
    if (crypto->dh_ctx != NULL) {
412
0
        ssh_dh_cleanup(crypto);
413
0
    }
414
415
577
    ctx = calloc(1, sizeof(*ctx));
416
577
    if (ctx == NULL) {
417
0
        return SSH_ERROR;
418
0
    }
419
577
    crypto->dh_ctx = ctx;
420
421
577
    switch (crypto->kex_type) {
422
0
    case SSH_KEX_DH_GROUP1_SHA1:
423
0
        rc = ssh_dh_set_parameters(ctx, ssh_dh_group1, ssh_dh_generator);
424
0
        break;
425
0
    case SSH_KEX_DH_GROUP14_SHA1:
426
144
    case SSH_KEX_DH_GROUP14_SHA256:
427
144
    case SSH_GSS_KEX_DH_GROUP14_SHA256:
428
144
        rc = ssh_dh_set_parameters(ctx, ssh_dh_group14, ssh_dh_generator);
429
144
        break;
430
44
    case SSH_KEX_DH_GROUP16_SHA512:
431
44
    case SSH_GSS_KEX_DH_GROUP16_SHA512:
432
44
        rc = ssh_dh_set_parameters(ctx, ssh_dh_group16, ssh_dh_generator);
433
44
        break;
434
129
    case SSH_KEX_DH_GROUP18_SHA512:
435
129
        rc = ssh_dh_set_parameters(ctx, ssh_dh_group18, ssh_dh_generator);
436
129
        break;
437
260
    default:
438
260
        rc = SSH_OK;
439
260
        break;
440
577
    }
441
442
577
    if (rc != SSH_OK) {
443
0
        ssh_dh_cleanup(crypto);
444
0
    }
445
577
    return rc;
446
577
}
447
448
void ssh_dh_cleanup(struct ssh_crypto_struct *crypto)
449
29.1k
{
450
29.1k
    if (crypto->dh_ctx != NULL) {
451
577
#if OPENSSL_VERSION_NUMBER < 0x30000000L
452
577
        DH_free(crypto->dh_ctx->keypair[0]);
453
577
        DH_free(crypto->dh_ctx->keypair[1]);
454
#else
455
        EVP_PKEY_free(crypto->dh_ctx->keypair[0]);
456
        EVP_PKEY_free(crypto->dh_ctx->keypair[1]);
457
#endif /* OPENSSL_VERSION_NUMBER */
458
577
        free(crypto->dh_ctx);
459
577
        crypto->dh_ctx = NULL;
460
577
    }
461
29.1k
}
462
463
/** @internal
464
 * @brief generates a secret DH parameter of at least DH_SECURITY_BITS
465
 *        security as well as the corresponding public key.
466
 *
467
 * @param[out] params a dh_ctx that will hold the new keys.
468
 * @param peer Select either client or server key storage. Valid values are:
469
 *        DH_CLIENT_KEYPAIR or DH_SERVER_KEYPAIR
470
 *
471
 * @return SSH_OK on success, SSH_ERROR on error
472
 */
473
int ssh_dh_keypair_gen_keys(struct dh_ctx *dh_ctx, int peer)
474
332
{
475
332
    int rc;
476
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
477
    EVP_PKEY_CTX *evp_ctx = NULL;
478
#endif
479
480
332
    if ((dh_ctx == NULL) || (dh_ctx->keypair[peer] == NULL)) {
481
0
        return SSH_ERROR;
482
0
    }
483
484
332
#if OPENSSL_VERSION_NUMBER < 0x30000000L
485
332
    rc = DH_generate_key(dh_ctx->keypair[peer]);
486
332
    if (rc != 1) {
487
0
        return SSH_ERROR;
488
0
    }
489
#else
490
    evp_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, dh_ctx->keypair[peer], NULL);
491
    if (evp_ctx == NULL) {
492
        return SSH_ERROR;
493
    }
494
495
    rc = EVP_PKEY_keygen_init(evp_ctx);
496
    if (rc != 1) {
497
        EVP_PKEY_CTX_free(evp_ctx);
498
        return SSH_ERROR;
499
    }
500
501
    rc = EVP_PKEY_generate(evp_ctx, &(dh_ctx->keypair[peer]));
502
    if (rc != 1) {
503
        EVP_PKEY_CTX_free(evp_ctx);
504
        SSH_LOG(SSH_LOG_TRACE,
505
                "Failed to generate DH: %s",
506
                ERR_error_string(ERR_get_error(), NULL));
507
        return SSH_ERROR;
508
    }
509
510
    EVP_PKEY_CTX_free(evp_ctx);
511
#endif /* OPENSSL_VERSION_NUMBER */
512
513
332
    return SSH_OK;
514
332
}
515
516
/** @internal
517
 * @brief generates a shared secret between the local peer and the remote
518
 *        peer. The local peer must have been initialized using either the
519
 *        ssh_dh_keypair_gen_keys() function or by seetting manually both
520
 *        the private and public keys. The remote peer only needs to have
521
 *        the remote's peer public key set.
522
 * @param[in] local peer identifier (DH_CLIENT_KEYPAIR or DH_SERVER_KEYPAIR)
523
 * @param[in] remote peer identifier (DH_CLIENT_KEYPAIR or DH_SERVER_KEYPAIR)
524
 * @param[out] dest a new bignum with the shared secret value is returned.
525
 * @return SSH_OK on success, SSH_ERROR on error
526
 */
527
int ssh_dh_compute_shared_secret(struct dh_ctx *dh_ctx, int local, int remote,
528
                                 bignum *dest)
529
270
{
530
270
    unsigned char *kstring = NULL;
531
270
    int rc;
532
270
#if OPENSSL_VERSION_NUMBER < 0x30000000L
533
270
    const_bignum pub_key = NULL;
534
270
    int klen;
535
#else
536
    size_t klen;
537
    EVP_PKEY_CTX *evp_ctx = NULL;
538
#endif /* OPENSSL_VERSION_NUMBER */
539
540
270
    if ((dh_ctx == NULL) ||
541
270
        (dh_ctx->keypair[local] == NULL) ||
542
270
        (dh_ctx->keypair[remote] == NULL)) {
543
0
        return SSH_ERROR;
544
0
    }
545
546
270
#if OPENSSL_VERSION_NUMBER < 0x30000000L
547
270
    kstring = malloc(DH_size(dh_ctx->keypair[local]));
548
270
    if (kstring == NULL) {
549
0
        rc = SSH_ERROR;
550
0
        goto done;
551
0
    }
552
553
270
    rc = ssh_dh_keypair_get_keys(dh_ctx, remote, NULL, &pub_key);
554
270
    if (rc != SSH_OK) {
555
4
        rc = SSH_ERROR;
556
4
        goto done;
557
4
    }
558
559
266
    klen = DH_compute_key(kstring, pub_key, dh_ctx->keypair[local]);
560
266
    if (klen == -1) {
561
7
        rc = SSH_ERROR;
562
7
        goto done;
563
7
    }
564
#else
565
    evp_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, dh_ctx->keypair[local], NULL);
566
567
    rc = EVP_PKEY_derive_init(evp_ctx);
568
    if (rc != 1) {
569
        rc = SSH_ERROR;
570
        goto done;
571
    }
572
573
    rc = EVP_PKEY_derive_set_peer(evp_ctx, dh_ctx->keypair[remote]);
574
    if (rc != 1) {
575
        SSH_LOG(SSH_LOG_TRACE,
576
                "Failed to set peer key: %s",
577
                ERR_error_string(ERR_get_error(), NULL));
578
        rc = SSH_ERROR;
579
        goto done;
580
    }
581
582
    /* getting the size of the secret */
583
    rc = EVP_PKEY_derive(evp_ctx, kstring, &klen);
584
    if (rc != 1) {
585
        rc = SSH_ERROR;
586
        goto done;
587
    }
588
589
    kstring = malloc(klen);
590
    if (kstring == NULL) {
591
        rc = SSH_ERROR;
592
        goto done;
593
    }
594
595
    rc = EVP_PKEY_derive(evp_ctx, kstring, &klen);
596
    if (rc != 1) {
597
        rc = SSH_ERROR;
598
        goto done;
599
    }
600
#endif /* OPENSSL_VERSION_NUMBER */
601
602
259
    *dest = BN_bin2bn(kstring, (int)klen, NULL);
603
259
    if (*dest == NULL) {
604
0
        rc = SSH_ERROR;
605
0
        goto done;
606
0
    }
607
608
259
    rc = SSH_OK;
609
270
done:
610
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
611
    EVP_PKEY_CTX_free(evp_ctx);
612
#endif
613
270
    free(kstring);
614
270
    return rc;
615
259
}