Coverage Report

Created: 2025-07-12 07:16

/src/libssh2/src/kex.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) Sara Golemon <sarag@libssh2.org>
2
 * Copyright (C) Daniel Stenberg <daniel@haxx.se>
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms,
6
 * with or without modification, are permitted provided
7
 * that the following conditions are met:
8
 *
9
 *   Redistributions of source code must retain the above
10
 *   copyright notice, this list of conditions and the
11
 *   following disclaimer.
12
 *
13
 *   Redistributions in binary form must reproduce the above
14
 *   copyright notice, this list of conditions and the following
15
 *   disclaimer in the documentation and/or other materials
16
 *   provided with the distribution.
17
 *
18
 *   Neither the name of the copyright holder nor the names
19
 *   of any other contributors may be used to endorse or
20
 *   promote products derived from this software without
21
 *   specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
24
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
28
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
35
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
36
 * OF SUCH DAMAGE.
37
 *
38
 * SPDX-License-Identifier: BSD-3-Clause
39
 */
40
41
#include "libssh2_priv.h"
42
43
#include "transport.h"
44
#include "comp.h"
45
#include "mac.h"
46
47
#include <assert.h>
48
49
/* define SHA1_DIGEST_LENGTH for the macro below */
50
#ifndef SHA1_DIGEST_LENGTH
51
678
#define SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH
52
#endif
53
54
/* TODO: Switch this to an inline and handle alloc() failures */
55
/* Helper macro called from
56
   kex_method_diffie_hellman_group1_sha1_key_exchange */
57
58
#if LIBSSH2_ECDSA
59
#define LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(value, reqlen, version)        \
60
0
    do {                                                                    \
61
0
        if(type == LIBSSH2_EC_CURVE_NISTP256) {                             \
62
0
            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, value, reqlen, version); \
63
0
        }                                                                   \
64
0
        else if(type == LIBSSH2_EC_CURVE_NISTP384) {                        \
65
0
            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(384, value, reqlen, version); \
66
0
        }                                                                   \
67
0
        else if(type == LIBSSH2_EC_CURVE_NISTP521) {                        \
68
0
            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(512, value, reqlen, version); \
69
0
        }                                                                   \
70
0
    } while(0)
71
#endif
72
73
#define LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(digest_type, value,               \
74
0
                                          reqlen, version)                  \
75
0
do {                                                                        \
76
0
    libssh2_sha##digest_type##_ctx hash;                                    \
77
0
    size_t len = 0;                                                         \
78
0
    if(!(value)) {                                                          \
79
0
        value = LIBSSH2_ALLOC(session,                                      \
80
0
                              reqlen + SHA##digest_type##_DIGEST_LENGTH);   \
81
0
    }                                                                       \
82
0
    if(value)                                                               \
83
0
        while(len < (size_t)reqlen) {                                       \
84
0
            if(!libssh2_sha##digest_type##_init(&hash) ||                   \
85
0
               !libssh2_sha##digest_type##_update(hash,                     \
86
0
                                       exchange_state->k_value,             \
87
0
                                       exchange_state->k_value_len) ||      \
88
0
               !libssh2_sha##digest_type##_update(hash,                     \
89
0
                                       exchange_state->h_sig_comp,          \
90
0
                                       SHA##digest_type##_DIGEST_LENGTH)) { \
91
0
                LIBSSH2_FREE(session, value);                               \
92
0
                value = NULL;                                               \
93
0
                break;                                                      \
94
0
            }                                                               \
95
0
            if(len > 0) {                                                   \
96
0
                if(!libssh2_sha##digest_type##_update(hash, value, len)) {  \
97
0
                    LIBSSH2_FREE(session, value);                           \
98
0
                    value = NULL;                                           \
99
0
                    break;                                                  \
100
0
                }                                                           \
101
0
            }                                                               \
102
0
            else {                                                          \
103
0
                if(!libssh2_sha##digest_type##_update(hash,                 \
104
0
                                                      (version), 1) ||      \
105
0
                   !libssh2_sha##digest_type##_update(hash,                 \
106
0
                                                session->session_id,        \
107
0
                                                session->session_id_len)) { \
108
0
                    LIBSSH2_FREE(session, value);                           \
109
0
                    value = NULL;                                           \
110
0
                    break;                                                  \
111
0
                }                                                           \
112
0
            }                                                               \
113
0
            if(!libssh2_sha##digest_type##_final(hash, (value) + len)) {    \
114
0
                LIBSSH2_FREE(session, value);                               \
115
0
                value = NULL;                                               \
116
0
                break;                                                      \
117
0
            }                                                               \
118
0
            len += SHA##digest_type##_DIGEST_LENGTH;                        \
119
0
        }                                                                   \
120
0
} while(0)
121
122
/*!
123
 * @note The following are wrapper functions used by diffie_hellman_sha_algo().
124
 * TODO: Switch backend SHA macros to functions to allow function pointers
125
 * @discussion Ideally these would be function pointers but the backend macros
126
 * don't allow it so we have to wrap them up in helper functions
127
 */
128
129
static int _libssh2_sha_algo_ctx_init(int sha_algo, void *ctx)
130
18
{
131
18
    if(sha_algo == 512) {
132
1
        return libssh2_sha512_init((libssh2_sha512_ctx*)ctx);
133
1
    }
134
17
    else if(sha_algo == 384) {
135
0
        return libssh2_sha384_init((libssh2_sha384_ctx*)ctx);
136
0
    }
137
17
    else if(sha_algo == 256) {
138
0
        return libssh2_sha256_init((libssh2_sha256_ctx*)ctx);
139
0
    }
140
17
    else if(sha_algo == 1) {
141
17
        return libssh2_sha1_init((libssh2_sha1_ctx*)ctx);
142
17
    }
143
0
    else {
144
0
#ifdef LIBSSH2DEBUG
145
0
        assert(0);
146
0
#endif
147
0
    }
148
0
    return 0;
149
18
}
150
151
static int _libssh2_sha_algo_ctx_update(int sha_algo, void *ctx,
152
                                        const void *data, size_t len)
153
252
{
154
252
    if(sha_algo == 512) {
155
14
        libssh2_sha512_ctx *_ctx = (libssh2_sha512_ctx*)ctx;
156
14
        return libssh2_sha512_update(*_ctx, data, len);
157
14
    }
158
238
    else if(sha_algo == 384) {
159
0
        libssh2_sha384_ctx *_ctx = (libssh2_sha384_ctx*)ctx;
160
0
        return libssh2_sha384_update(*_ctx, data, len);
161
0
    }
162
238
    else if(sha_algo == 256) {
163
0
        libssh2_sha256_ctx *_ctx = (libssh2_sha256_ctx*)ctx;
164
0
        return libssh2_sha256_update(*_ctx, data, len);
165
0
    }
166
238
    else if(sha_algo == 1) {
167
238
        libssh2_sha1_ctx *_ctx = (libssh2_sha1_ctx*)ctx;
168
238
        return libssh2_sha1_update(*_ctx, data, len);
169
238
    }
170
0
    else {
171
0
#ifdef LIBSSH2DEBUG
172
0
        assert(0);
173
0
#endif
174
0
    }
175
0
    return 0;
176
252
}
177
178
static int _libssh2_sha_algo_ctx_final(int sha_algo, void *ctx,
179
                                       void *hash)
180
18
{
181
18
    if(sha_algo == 512) {
182
1
        libssh2_sha512_ctx *_ctx = (libssh2_sha512_ctx*)ctx;
183
1
        return libssh2_sha512_final(*_ctx, hash);
184
1
    }
185
17
    else if(sha_algo == 384) {
186
0
        libssh2_sha384_ctx *_ctx = (libssh2_sha384_ctx*)ctx;
187
0
        return libssh2_sha384_final(*_ctx, hash);
188
0
    }
189
17
    else if(sha_algo == 256) {
190
0
        libssh2_sha256_ctx *_ctx = (libssh2_sha256_ctx*)ctx;
191
0
        return libssh2_sha256_final(*_ctx, hash);
192
0
    }
193
17
    else if(sha_algo == 1) {
194
17
        libssh2_sha1_ctx *_ctx = (libssh2_sha1_ctx*)ctx;
195
17
        return libssh2_sha1_final(*_ctx, hash);
196
17
    }
197
0
    else {
198
0
#ifdef LIBSSH2DEBUG
199
0
        assert(0);
200
0
#endif
201
0
    }
202
0
    return 0;
203
18
}
204
205
static void _libssh2_sha_algo_value_hash(int sha_algo,
206
                                         LIBSSH2_SESSION *session,
207
                                         kmdhgGPshakex_state_t *exchange_state,
208
                                         unsigned char **data, size_t data_len,
209
                                         const unsigned char *version)
210
0
{
211
0
    if(sha_algo == 512) {
212
0
        LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(512, *data, data_len, version);
213
0
    }
214
0
    else if(sha_algo == 384) {
215
0
        LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(384, *data, data_len, version);
216
0
    }
217
0
    else if(sha_algo == 256) {
218
0
        LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, *data, data_len, version);
219
0
    }
220
0
    else if(sha_algo == 1) {
221
0
        LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(1, *data, data_len, version);
222
0
    }
223
0
    else {
224
0
#ifdef LIBSSH2DEBUG
225
0
        assert(0);
226
0
#endif
227
0
    }
228
0
}
229
230
231
static void
232
diffie_hellman_state_cleanup(LIBSSH2_SESSION * session,
233
                             kmdhgGPshakex_state_t *exchange_state)
234
1.16k
{
235
1.16k
    libssh2_dh_dtor(&exchange_state->x);
236
1.16k
    _libssh2_bn_free(exchange_state->e);
237
1.16k
    exchange_state->e = NULL;
238
1.16k
    _libssh2_bn_free(exchange_state->f);
239
1.16k
    exchange_state->f = NULL;
240
1.16k
    _libssh2_bn_free(exchange_state->k);
241
1.16k
    exchange_state->k = NULL;
242
1.16k
    _libssh2_bn_ctx_free(exchange_state->ctx);
243
1.16k
    exchange_state->ctx = NULL;
244
245
1.16k
    if(exchange_state->e_packet) {
246
909
        LIBSSH2_FREE(session, exchange_state->e_packet);
247
909
        exchange_state->e_packet = NULL;
248
909
    }
249
250
1.16k
    if(exchange_state->s_packet) {
251
236
        LIBSSH2_FREE(session, exchange_state->s_packet);
252
236
        exchange_state->s_packet = NULL;
253
236
    }
254
255
1.16k
    if(exchange_state->k_value) {
256
20
        LIBSSH2_FREE(session, exchange_state->k_value);
257
20
        exchange_state->k_value = NULL;
258
20
    }
259
260
1.16k
    exchange_state->state = libssh2_NB_state_idle;
261
1.16k
}
262
263
static void
264
kex_diffie_hellman_cleanup(LIBSSH2_SESSION * session,
265
2.80k
                           key_exchange_state_low_t * key_state) {
266
2.80k
    if(key_state->state != libssh2_NB_state_idle) {
267
1.05k
        _libssh2_bn_free(key_state->p);
268
1.05k
        key_state->p = NULL;
269
1.05k
        _libssh2_bn_free(key_state->g);
270
1.05k
        key_state->g = NULL;
271
272
1.05k
        if(key_state->data) {
273
175
            LIBSSH2_FREE(session, key_state->data);
274
175
            key_state->data = NULL;
275
175
        }
276
1.05k
        key_state->state = libssh2_NB_state_idle;
277
1.05k
    }
278
279
2.80k
    if(key_state->exchange_state.state != libssh2_NB_state_idle) {
280
0
        diffie_hellman_state_cleanup(session, &key_state->exchange_state);
281
0
    }
282
2.80k
}
283
284
285
/*!
286
 * @function diffie_hellman_sha_algo
287
 * @abstract Diffie Hellman Key Exchange, Group Agnostic,
288
 * SHA Algorithm Agnostic
289
 * @result 0 on success, error code on failure
290
 */
291
static int diffie_hellman_sha_algo(LIBSSH2_SESSION *session,
292
                                   _libssh2_bn *g,
293
                                   _libssh2_bn *p,
294
                                   int group_order,
295
                                   int sha_algo_value,
296
                                   void *exchange_hash_ctx,
297
                                   unsigned char packet_type_init,
298
                                   unsigned char packet_type_reply,
299
                                   unsigned char *midhash,
300
                                   size_t midhash_len,
301
                                   kmdhgGPshakex_state_t *exchange_state)
302
1.16k
{
303
1.16k
    int ret = 0;
304
1.16k
    int rc;
305
306
1.16k
    int digest_len = 0;
307
308
1.16k
    if(sha_algo_value == 512)
309
308
        digest_len = SHA512_DIGEST_LENGTH;
310
859
    else if(sha_algo_value == 384)
311
0
        digest_len = SHA384_DIGEST_LENGTH;
312
859
    else if(sha_algo_value == 256)
313
181
        digest_len = SHA256_DIGEST_LENGTH;
314
678
    else if(sha_algo_value == 1)
315
678
        digest_len = SHA1_DIGEST_LENGTH;
316
0
    else {
317
0
        ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
318
0
                             "sha algo value is unimplemented");
319
0
        goto clean_exit;
320
0
    }
321
322
1.16k
    if(exchange_state->state == libssh2_NB_state_idle) {
323
        /* Setup initial values */
324
1.16k
        exchange_state->e_packet = NULL;
325
1.16k
        exchange_state->s_packet = NULL;
326
1.16k
        exchange_state->k_value = NULL;
327
1.16k
        exchange_state->ctx = _libssh2_bn_ctx_new();
328
1.16k
        libssh2_dh_init(&exchange_state->x);
329
1.16k
        exchange_state->e = _libssh2_bn_init(); /* g^x mod p */
330
1.16k
        exchange_state->f = _libssh2_bn_init_from_bin(); /* g^(Random from
331
                                                            server) mod p */
332
1.16k
        exchange_state->k = _libssh2_bn_init(); /* The shared secret: f^x mod
333
                                                   p */
334
335
        /* Zero the whole thing out */
336
1.16k
        memset(&exchange_state->req_state, 0, sizeof(packet_require_state_t));
337
338
        /* Generate x and e */
339
1.16k
        if(_libssh2_bn_bits(p) > LIBSSH2_DH_MAX_MODULUS_BITS) {
340
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_INVAL,
341
0
                                 "dh modulus value is too large");
342
0
            goto clean_exit;
343
0
        }
344
345
1.16k
        rc = libssh2_dh_key_pair(&exchange_state->x, exchange_state->e, g, p,
346
1.16k
                                 group_order, exchange_state->ctx);
347
1.16k
        if(rc) {
348
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
349
0
                                 "dh key pair generation failed");
350
0
            goto clean_exit;
351
0
        }
352
353
        /* Send KEX init */
354
        /* packet_type(1) + String Length(4) + leading 0(1) */
355
1.16k
        exchange_state->e_packet_len =
356
1.16k
            _libssh2_bn_bytes(exchange_state->e) + 6;
357
1.16k
        if(_libssh2_bn_bits(exchange_state->e) % 8) {
358
            /* Leading 00 not needed */
359
652
            exchange_state->e_packet_len--;
360
652
        }
361
362
1.16k
        exchange_state->e_packet =
363
1.16k
            LIBSSH2_ALLOC(session, exchange_state->e_packet_len);
364
1.16k
        if(!exchange_state->e_packet) {
365
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
366
0
                                 "Out of memory error");
367
0
            goto clean_exit;
368
0
        }
369
1.16k
        exchange_state->e_packet[0] = packet_type_init;
370
1.16k
        _libssh2_htonu32(exchange_state->e_packet + 1,
371
1.16k
                         (uint32_t)(exchange_state->e_packet_len - 5));
372
1.16k
        if(_libssh2_bn_bits(exchange_state->e) % 8) {
373
652
            if(_libssh2_bn_to_bin(exchange_state->e,
374
652
                                  exchange_state->e_packet + 5)) {
375
0
                ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
376
0
                                     "Can't write exchange_state->e");
377
0
                goto clean_exit;
378
0
            }
379
652
        }
380
515
        else {
381
515
            exchange_state->e_packet[5] = 0;
382
515
            if(_libssh2_bn_to_bin(exchange_state->e,
383
515
                                  exchange_state->e_packet + 6)) {
384
5
                ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
385
5
                                     "Can't write exchange_state->e");
386
5
                goto clean_exit;
387
5
            }
388
515
        }
389
390
1.16k
        _libssh2_debug((session, LIBSSH2_TRACE_KEX, "Sending KEX packet %u",
391
1.16k
                       (unsigned int) packet_type_init));
392
1.16k
        exchange_state->state = libssh2_NB_state_created;
393
1.16k
    }
394
395
1.16k
    if(exchange_state->state == libssh2_NB_state_created) {
396
1.16k
        rc = _libssh2_transport_send(session, exchange_state->e_packet,
397
1.16k
                                     exchange_state->e_packet_len,
398
1.16k
                                     NULL, 0);
399
1.16k
        if(rc == LIBSSH2_ERROR_EAGAIN) {
400
0
            return rc;
401
0
        }
402
1.16k
        else if(rc) {
403
0
            ret = _libssh2_error(session, rc,
404
0
                                 "Unable to send KEX init message");
405
0
            goto clean_exit;
406
0
        }
407
1.16k
        exchange_state->state = libssh2_NB_state_sent;
408
1.16k
    }
409
410
1.16k
    if(exchange_state->state == libssh2_NB_state_sent) {
411
1.16k
        if(session->burn_optimistic_kexinit) {
412
            /* The first KEX packet to come along will be the guess initially
413
             * sent by the server.  That guess turned out to be wrong so we
414
             * need to silently ignore it */
415
527
            int burn_type;
416
417
527
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
418
527
                           "Waiting for badly guessed KEX packet "
419
527
                           "(to be ignored)"));
420
527
            burn_type =
421
527
                _libssh2_packet_burn(session, &exchange_state->burn_state);
422
527
            if(burn_type == LIBSSH2_ERROR_EAGAIN) {
423
0
                return burn_type;
424
0
            }
425
527
            else if(burn_type <= 0) {
426
                /* Failed to receive a packet */
427
254
                ret = burn_type;
428
254
                goto clean_exit;
429
254
            }
430
273
            session->burn_optimistic_kexinit = 0;
431
432
273
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
433
273
                           "Burnt packet of type: %02x",
434
273
                           (unsigned int) burn_type));
435
273
        }
436
437
908
        exchange_state->state = libssh2_NB_state_sent1;
438
908
    }
439
440
908
    if(exchange_state->state == libssh2_NB_state_sent1) {
441
        /* Wait for KEX reply */
442
908
        struct string_buf buf;
443
908
        size_t host_key_len;
444
908
        int err;
445
908
        int hok;
446
447
908
        rc = _libssh2_packet_require(session, packet_type_reply,
448
908
                                     &exchange_state->s_packet,
449
908
                                     &exchange_state->s_packet_len, 0, NULL,
450
908
                                     0, &exchange_state->req_state);
451
908
        if(rc == LIBSSH2_ERROR_EAGAIN) {
452
0
            return rc;
453
0
        }
454
908
        if(rc) {
455
672
            ret = _libssh2_error(session, LIBSSH2_ERROR_TIMEOUT,
456
672
                                 "Timed out waiting for KEX reply");
457
672
            goto clean_exit;
458
672
        }
459
460
        /* Parse KEXDH_REPLY */
461
236
        if(exchange_state->s_packet_len < 5) {
462
2
            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
463
2
                                 "Unexpected packet length DH-SHA");
464
2
            goto clean_exit;
465
2
        }
466
467
234
        buf.data = exchange_state->s_packet;
468
234
        buf.len = exchange_state->s_packet_len;
469
234
        buf.dataptr = buf.data;
470
234
        buf.dataptr++; /* advance past type */
471
472
234
        if(session->server_hostkey) {
473
0
            LIBSSH2_FREE(session, session->server_hostkey);
474
0
            session->server_hostkey = NULL;
475
0
            session->server_hostkey_len = 0;
476
0
        }
477
478
234
        if(_libssh2_copy_string(session, &buf, &(session->server_hostkey),
479
234
                                &host_key_len)) {
480
3
            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
481
3
                                 "Could not copy host key");
482
3
            goto clean_exit;
483
3
        }
484
485
231
        session->server_hostkey_len = (uint32_t)host_key_len;
486
487
#if LIBSSH2_MD5
488
        {
489
            libssh2_md5_ctx fingerprint_ctx;
490
491
            if(libssh2_md5_init(&fingerprint_ctx) &&
492
               libssh2_md5_update(fingerprint_ctx, session->server_hostkey,
493
                                  session->server_hostkey_len) &&
494
               libssh2_md5_final(fingerprint_ctx,
495
                                 session->server_hostkey_md5)) {
496
                session->server_hostkey_md5_valid = TRUE;
497
            }
498
            else {
499
                session->server_hostkey_md5_valid = FALSE;
500
            }
501
        }
502
#ifdef LIBSSH2DEBUG
503
        {
504
            char fingerprint[50], *fprint = fingerprint;
505
            int i;
506
            for(i = 0; i < 16; i++, fprint += 3) {
507
                snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]);
508
            }
509
            *(--fprint) = '\0';
510
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
511
                           "Server's MD5 Fingerprint: %s", fingerprint));
512
        }
513
#endif /* LIBSSH2DEBUG */
514
#endif /* ! LIBSSH2_MD5 */
515
516
231
        {
517
231
            libssh2_sha1_ctx fingerprint_ctx;
518
519
231
            if(libssh2_sha1_init(&fingerprint_ctx) &&
520
231
               libssh2_sha1_update(fingerprint_ctx, session->server_hostkey,
521
231
                                   session->server_hostkey_len) &&
522
231
               libssh2_sha1_final(fingerprint_ctx,
523
231
                                  session->server_hostkey_sha1)) {
524
231
                session->server_hostkey_sha1_valid = TRUE;
525
231
            }
526
0
            else {
527
0
                session->server_hostkey_sha1_valid = FALSE;
528
0
            }
529
231
        }
530
231
#ifdef LIBSSH2DEBUG
531
231
        {
532
231
            char fingerprint[64], *fprint = fingerprint;
533
231
            int i;
534
4.85k
            for(i = 0; i < 20; i++, fprint += 3) {
535
4.62k
                snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]);
536
4.62k
            }
537
231
            *(--fprint) = '\0';
538
231
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
539
231
                           "Server's SHA1 Fingerprint: %s", fingerprint));
540
231
        }
541
231
#endif /* LIBSSH2DEBUG */
542
543
231
        {
544
231
            libssh2_sha256_ctx fingerprint_ctx;
545
546
231
            if(libssh2_sha256_init(&fingerprint_ctx) &&
547
231
               libssh2_sha256_update(fingerprint_ctx, session->server_hostkey,
548
231
                                     session->server_hostkey_len) &&
549
231
               libssh2_sha256_final(fingerprint_ctx,
550
231
                                    session->server_hostkey_sha256)) {
551
231
                session->server_hostkey_sha256_valid = TRUE;
552
231
            }
553
0
            else {
554
0
                session->server_hostkey_sha256_valid = FALSE;
555
0
            }
556
231
        }
557
231
#ifdef LIBSSH2DEBUG
558
231
        {
559
231
            char *base64Fingerprint = NULL;
560
231
            _libssh2_base64_encode(session,
561
231
                                   (const char *)
562
231
                                   session->server_hostkey_sha256,
563
231
                                   SHA256_DIGEST_LENGTH, &base64Fingerprint);
564
231
            if(base64Fingerprint) {
565
231
                _libssh2_debug((session, LIBSSH2_TRACE_KEX,
566
231
                               "Server's SHA256 Fingerprint: %s",
567
231
                               base64Fingerprint));
568
231
                LIBSSH2_FREE(session, base64Fingerprint);
569
231
            }
570
231
        }
571
231
#endif /* LIBSSH2DEBUG */
572
573
574
231
        if(!session->hostkey) {
575
1
            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
576
1
                                 "hostkey is NULL");
577
1
            goto clean_exit;
578
1
        }
579
230
        if(session->hostkey->init(session, session->server_hostkey,
580
230
                                  session->server_hostkey_len,
581
230
                                  &session->server_hostkey_abstract)) {
582
208
            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
583
208
                                 "Unable to initialize hostkey importer "
584
208
                                 "DH-SHA");
585
208
            goto clean_exit;
586
208
        }
587
588
22
        if(_libssh2_get_string(&buf, &(exchange_state->f_value),
589
22
                               &(exchange_state->f_value_len))) {
590
1
            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
591
1
                                 "Unable to get DH-SHA f value");
592
1
            goto clean_exit;
593
1
        }
594
595
21
        if(_libssh2_bn_from_bin(exchange_state->f,
596
21
                                exchange_state->f_value_len,
597
21
                                exchange_state->f_value)) {
598
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
599
0
                                 "Invalid DH-SHA f value");
600
0
            goto clean_exit;
601
0
        }
602
603
21
        if(_libssh2_get_string(&buf, &(exchange_state->h_sig),
604
21
                               &(exchange_state->h_sig_len))) {
605
1
            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
606
1
                                 "Unable to get DH-SHA h sig");
607
1
            goto clean_exit;
608
1
        }
609
610
        /* Compute the shared secret */
611
20
        libssh2_dh_secret(&exchange_state->x, exchange_state->k,
612
20
                          exchange_state->f, p, exchange_state->ctx);
613
20
        exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5;
614
20
        if(_libssh2_bn_bits(exchange_state->k) % 8) {
615
            /* don't need leading 00 */
616
6
            exchange_state->k_value_len--;
617
6
        }
618
20
        exchange_state->k_value =
619
20
            LIBSSH2_ALLOC(session, exchange_state->k_value_len);
620
20
        if(!exchange_state->k_value) {
621
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
622
0
                                 "Unable to allocate buffer for DH-SHA K");
623
0
            goto clean_exit;
624
0
        }
625
20
        _libssh2_htonu32(exchange_state->k_value,
626
20
                         (uint32_t)(exchange_state->k_value_len - 4));
627
20
        if(_libssh2_bn_bits(exchange_state->k) % 8) {
628
6
            if(_libssh2_bn_to_bin(exchange_state->k,
629
6
                                  exchange_state->k_value + 4)) {
630
0
                ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
631
0
                                     "Can't write exchange_state->k");
632
0
                goto clean_exit;
633
0
            }
634
6
        }
635
14
        else {
636
14
            exchange_state->k_value[4] = 0;
637
14
            if(_libssh2_bn_to_bin(exchange_state->k,
638
14
                                  exchange_state->k_value + 5)) {
639
2
                ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
640
2
                                     "Can't write exchange_state->k");
641
2
                goto clean_exit;
642
2
            }
643
14
        }
644
645
18
        exchange_state->exchange_hash = (void *)&exchange_hash_ctx;
646
18
        if(!_libssh2_sha_algo_ctx_init(sha_algo_value, exchange_hash_ctx)) {
647
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_HASH_INIT,
648
0
                                 "Unable to initialize hash context");
649
0
            goto clean_exit;
650
0
        }
651
18
        hok = 1;
652
18
        if(session->local.banner) {
653
0
            _libssh2_htonu32(exchange_state->h_sig_comp,
654
0
                (uint32_t)(strlen((char *) session->local.banner) - 2));
655
0
            hok &= _libssh2_sha_algo_ctx_update(sha_algo_value,
656
0
                                                exchange_hash_ctx,
657
0
                                                exchange_state->h_sig_comp, 4);
658
0
            hok &= _libssh2_sha_algo_ctx_update(sha_algo_value,
659
0
                                                exchange_hash_ctx,
660
0
                                                session->local.banner,
661
0
                                   strlen((char *) session->local.banner) - 2);
662
0
        }
663
18
        else {
664
18
            _libssh2_htonu32(exchange_state->h_sig_comp,
665
18
                             sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
666
18
            hok &= _libssh2_sha_algo_ctx_update(sha_algo_value,
667
18
                                                exchange_hash_ctx,
668
18
                                                exchange_state->h_sig_comp, 4);
669
18
            hok &= _libssh2_sha_algo_ctx_update(sha_algo_value,
670
18
                                                exchange_hash_ctx,
671
18
                                      (const void *)LIBSSH2_SSH_DEFAULT_BANNER,
672
18
                                       sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);
673
18
        }
674
675
18
        _libssh2_htonu32(exchange_state->h_sig_comp,
676
18
                         (uint32_t)strlen((char *) session->remote.banner));
677
18
        hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx,
678
18
                                            exchange_state->h_sig_comp, 4);
679
18
        hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx,
680
18
                                            session->remote.banner,
681
18
                                       strlen((char *)session->remote.banner));
682
683
18
        _libssh2_htonu32(exchange_state->h_sig_comp,
684
18
                         (uint32_t)session->local.kexinit_len);
685
18
        hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx,
686
18
                                            exchange_state->h_sig_comp, 4);
687
18
        hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx,
688
18
                                            session->local.kexinit,
689
18
                                            session->local.kexinit_len);
690
691
18
        _libssh2_htonu32(exchange_state->h_sig_comp,
692
18
                         (uint32_t)session->remote.kexinit_len);
693
18
        hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx,
694
18
                                            exchange_state->h_sig_comp, 4);
695
18
        hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx,
696
18
                                            session->remote.kexinit,
697
18
                                            session->remote.kexinit_len);
698
699
18
        _libssh2_htonu32(exchange_state->h_sig_comp,
700
18
                         session->server_hostkey_len);
701
18
        hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx,
702
18
                                            exchange_state->h_sig_comp, 4);
703
18
        hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx,
704
18
                                            session->server_hostkey,
705
18
                                            session->server_hostkey_len);
706
707
18
        if(packet_type_init == SSH_MSG_KEX_DH_GEX_INIT) {
708
            /* diffie-hellman-group-exchange hashes additional fields */
709
0
            _libssh2_htonu32(exchange_state->h_sig_comp,
710
0
                             LIBSSH2_DH_GEX_MINGROUP);
711
0
            _libssh2_htonu32(exchange_state->h_sig_comp + 4,
712
0
                             LIBSSH2_DH_GEX_OPTGROUP);
713
0
            _libssh2_htonu32(exchange_state->h_sig_comp + 8,
714
0
                             LIBSSH2_DH_GEX_MAXGROUP);
715
0
            hok &= _libssh2_sha_algo_ctx_update(sha_algo_value,
716
0
                                                exchange_hash_ctx,
717
0
                                                exchange_state->h_sig_comp,
718
0
                                                12);
719
0
        }
720
721
18
        if(midhash) {
722
0
            hok &= _libssh2_sha_algo_ctx_update(sha_algo_value,
723
0
                                                exchange_hash_ctx,
724
0
                                                midhash, midhash_len);
725
0
        }
726
727
18
        hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx,
728
18
                                            exchange_state->e_packet + 1,
729
18
                                            exchange_state->e_packet_len - 1);
730
731
18
        _libssh2_htonu32(exchange_state->h_sig_comp,
732
18
                         (uint32_t)exchange_state->f_value_len);
733
18
        hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx,
734
18
                                            exchange_state->h_sig_comp, 4);
735
18
        hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx,
736
18
                                            exchange_state->f_value,
737
18
                                            exchange_state->f_value_len);
738
739
18
        hok &= _libssh2_sha_algo_ctx_update(sha_algo_value, exchange_hash_ctx,
740
18
                                            exchange_state->k_value,
741
18
                                            exchange_state->k_value_len);
742
743
18
        if(!hok ||
744
18
           !_libssh2_sha_algo_ctx_final(sha_algo_value, exchange_hash_ctx,
745
18
                                        exchange_state->h_sig_comp)) {
746
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_HASH_CALC,
747
0
                                 "kex: failed to calculate hash");
748
0
            goto clean_exit;
749
0
        }
750
751
18
        err = session->hostkey->sig_verify(session,
752
18
                                           exchange_state->h_sig,
753
18
                                           exchange_state->h_sig_len,
754
18
                                           exchange_state->h_sig_comp,
755
18
                                           digest_len,
756
18
                                           &session->server_hostkey_abstract);
757
758
18
        if(err) {
759
18
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
760
18
                           "Failed hostkey sig_verify(): %s: %d",
761
18
                           session->hostkey->name, err));
762
18
            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN,
763
18
                                 "Unable to verify hostkey signature "
764
18
                                 "DH-SHA");
765
18
            goto clean_exit;
766
18
        }
767
768
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
769
0
                       "Sending NEWKEYS message"));
770
0
        exchange_state->c = SSH_MSG_NEWKEYS;
771
772
0
        exchange_state->state = libssh2_NB_state_sent2;
773
0
    }
774
775
0
    if(exchange_state->state == libssh2_NB_state_sent2) {
776
0
        rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0);
777
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
778
0
            return rc;
779
0
        }
780
0
        else if(rc) {
781
0
            ret = _libssh2_error(session, rc,
782
0
                                 "Unable to send NEWKEYS message DH-SHA");
783
0
            goto clean_exit;
784
0
        }
785
786
0
        exchange_state->state = libssh2_NB_state_sent3;
787
0
    }
788
789
0
    if(exchange_state->state == libssh2_NB_state_sent3) {
790
0
        rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS,
791
0
                                     &exchange_state->tmp,
792
0
                                     &exchange_state->tmp_len, 0, NULL, 0,
793
0
                                     &exchange_state->req_state);
794
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
795
0
            return rc;
796
0
        }
797
0
        else if(rc) {
798
0
            ret = _libssh2_error(session, rc,
799
0
                                 "Timed out waiting for NEWKEYS DH-SHA");
800
0
            goto clean_exit;
801
0
        }
802
803
        /* The first key exchange has been performed,
804
           switch to active crypt/comp/mac mode */
805
0
        session->state |= LIBSSH2_STATE_NEWKEYS;
806
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
807
0
                       "Received NEWKEYS message DH-SHA"));
808
809
        /* This will actually end up being just packet_type(1)
810
           for this packet type anyway */
811
0
        LIBSSH2_FREE(session, exchange_state->tmp);
812
813
0
        if(!session->session_id) {
814
0
            session->session_id = LIBSSH2_ALLOC(session, digest_len);
815
0
            if(!session->session_id) {
816
0
                ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
817
0
                                     "Unable to allocate buffer for "
818
0
                                     "SHA digest");
819
0
                goto clean_exit;
820
0
            }
821
0
            memcpy(session->session_id, exchange_state->h_sig_comp,
822
0
                   digest_len);
823
0
            session->session_id_len = digest_len;
824
0
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
825
0
                           "session_id calculated"));
826
0
        }
827
828
        /* Cleanup any existing cipher */
829
0
        if(session->local.crypt->dtor) {
830
0
            session->local.crypt->dtor(session,
831
0
                                       &session->local.crypt_abstract);
832
0
        }
833
834
        /* Calculate IV/Secret/Key for each direction */
835
0
        if(session->local.crypt->init) {
836
0
            unsigned char *iv = NULL, *secret = NULL;
837
0
            int free_iv = 0, free_secret = 0;
838
839
0
            _libssh2_sha_algo_value_hash(sha_algo_value, session,
840
0
                                         exchange_state, &iv,
841
0
                                         session->local.crypt->iv_len,
842
0
                                         (const unsigned char *)"A");
843
844
0
            if(!iv) {
845
0
                ret = -1;
846
0
                goto clean_exit;
847
0
            }
848
0
            _libssh2_sha_algo_value_hash(sha_algo_value, session,
849
0
                                         exchange_state, &secret,
850
0
                                         session->local.crypt->secret_len,
851
0
                                         (const unsigned char *)"C");
852
853
0
            if(!secret) {
854
0
                LIBSSH2_FREE(session, iv);
855
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
856
0
                goto clean_exit;
857
0
            }
858
0
            if(session->local.crypt->
859
0
                init(session, session->local.crypt, iv, &free_iv, secret,
860
0
                     &free_secret, 1, &session->local.crypt_abstract)) {
861
0
                LIBSSH2_FREE(session, iv);
862
0
                LIBSSH2_FREE(session, secret);
863
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
864
0
                goto clean_exit;
865
0
            }
866
867
0
            if(free_iv) {
868
0
                _libssh2_explicit_zero(iv, session->local.crypt->iv_len);
869
0
                LIBSSH2_FREE(session, iv);
870
0
            }
871
872
0
            if(free_secret) {
873
0
                _libssh2_explicit_zero(secret,
874
0
                                       session->local.crypt->secret_len);
875
0
                LIBSSH2_FREE(session, secret);
876
0
            }
877
0
        }
878
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
879
0
                       "Client to Server IV and Key calculated"));
880
881
0
        if(session->remote.crypt->dtor) {
882
            /* Cleanup any existing cipher */
883
0
            session->remote.crypt->dtor(session,
884
0
                                        &session->remote.crypt_abstract);
885
0
        }
886
887
0
        if(session->remote.crypt->init) {
888
0
            unsigned char *iv = NULL, *secret = NULL;
889
0
            int free_iv = 0, free_secret = 0;
890
891
0
            _libssh2_sha_algo_value_hash(sha_algo_value, session,
892
0
                                         exchange_state, &iv,
893
0
                                         session->remote.crypt->iv_len,
894
0
                                         (const unsigned char *)"B");
895
0
            if(!iv) {
896
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
897
0
                goto clean_exit;
898
0
            }
899
0
            _libssh2_sha_algo_value_hash(sha_algo_value, session,
900
0
                                         exchange_state, &secret,
901
0
                                         session->remote.crypt->secret_len,
902
0
                                         (const unsigned char *)"D");
903
0
            if(!secret) {
904
0
                LIBSSH2_FREE(session, iv);
905
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
906
0
                goto clean_exit;
907
0
            }
908
0
            if(session->remote.crypt->
909
0
                init(session, session->remote.crypt, iv, &free_iv, secret,
910
0
                     &free_secret, 0, &session->remote.crypt_abstract)) {
911
0
                LIBSSH2_FREE(session, iv);
912
0
                LIBSSH2_FREE(session, secret);
913
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
914
0
                goto clean_exit;
915
0
            }
916
917
0
            if(free_iv) {
918
0
                _libssh2_explicit_zero(iv, session->remote.crypt->iv_len);
919
0
                LIBSSH2_FREE(session, iv);
920
0
            }
921
922
0
            if(free_secret) {
923
0
                _libssh2_explicit_zero(secret,
924
0
                                       session->remote.crypt->secret_len);
925
0
                LIBSSH2_FREE(session, secret);
926
0
            }
927
0
        }
928
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
929
0
                       "Server to Client IV and Key calculated"));
930
931
0
        if(session->local.mac->dtor) {
932
0
            session->local.mac->dtor(session, &session->local.mac_abstract);
933
0
        }
934
935
0
        if(session->local.mac->init) {
936
0
            unsigned char *key = NULL;
937
0
            int free_key = 0;
938
939
0
            _libssh2_sha_algo_value_hash(sha_algo_value, session,
940
0
                                         exchange_state, &key,
941
0
                                         session->local.mac->key_len,
942
0
                                         (const unsigned char *)"E");
943
0
            if(!key) {
944
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
945
0
                goto clean_exit;
946
0
            }
947
0
            session->local.mac->init(session, key, &free_key,
948
0
                                     &session->local.mac_abstract);
949
950
0
            if(free_key) {
951
0
                _libssh2_explicit_zero(key, session->local.mac->key_len);
952
0
                LIBSSH2_FREE(session, key);
953
0
            }
954
0
        }
955
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
956
0
                       "Client to Server HMAC Key calculated"));
957
958
0
        if(session->remote.mac->dtor) {
959
0
            session->remote.mac->dtor(session, &session->remote.mac_abstract);
960
0
        }
961
962
0
        if(session->remote.mac->init) {
963
0
            unsigned char *key = NULL;
964
0
            int free_key = 0;
965
966
0
            _libssh2_sha_algo_value_hash(sha_algo_value, session,
967
0
                                         exchange_state, &key,
968
0
                                         session->remote.mac->key_len,
969
0
                                         (const unsigned char *)"F");
970
0
            if(!key) {
971
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
972
0
                goto clean_exit;
973
0
            }
974
0
            session->remote.mac->init(session, key, &free_key,
975
0
                                      &session->remote.mac_abstract);
976
977
0
            if(free_key) {
978
0
                _libssh2_explicit_zero(key, session->remote.mac->key_len);
979
0
                LIBSSH2_FREE(session, key);
980
0
            }
981
0
        }
982
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
983
0
                       "Server to Client HMAC Key calculated"));
984
985
        /* Initialize compression for each direction */
986
987
        /* Cleanup any existing compression */
988
0
        if(session->local.comp && session->local.comp->dtor) {
989
0
            session->local.comp->dtor(session, 1,
990
0
                                      &session->local.comp_abstract);
991
0
        }
992
993
0
        if(session->local.comp && session->local.comp->init) {
994
0
            if(session->local.comp->init(session, 1,
995
0
                                         &session->local.comp_abstract)) {
996
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
997
0
                goto clean_exit;
998
0
            }
999
0
        }
1000
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
1001
0
                       "Client to Server compression initialized"));
1002
1003
0
        if(session->remote.comp && session->remote.comp->dtor) {
1004
0
            session->remote.comp->dtor(session, 0,
1005
0
                                       &session->remote.comp_abstract);
1006
0
        }
1007
1008
0
        if(session->remote.comp && session->remote.comp->init) {
1009
0
            if(session->remote.comp->init(session, 0,
1010
0
                                          &session->remote.comp_abstract)) {
1011
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
1012
0
                goto clean_exit;
1013
0
            }
1014
0
        }
1015
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
1016
0
                       "Server to Client compression initialized"));
1017
1018
0
    }
1019
1020
1.16k
clean_exit:
1021
1.16k
    diffie_hellman_state_cleanup(session, exchange_state);
1022
1023
1.16k
    return ret;
1024
0
}
1025
1026
1027
1028
/* kex_method_diffie_hellman_group1_sha1_key_exchange
1029
 * Diffie-Hellman Group1 (Actually Group2) Key Exchange using SHA1
1030
 */
1031
static int
1032
kex_method_diffie_hellman_group1_sha1_key_exchange(LIBSSH2_SESSION *session,
1033
                                                   key_exchange_state_low_t
1034
                                                   * key_state)
1035
393
{
1036
393
    static const unsigned char p_value[128] = {
1037
393
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1038
393
        0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
1039
393
        0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
1040
393
        0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
1041
393
        0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
1042
393
        0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
1043
393
        0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
1044
393
        0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
1045
393
        0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
1046
393
        0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
1047
393
        0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
1048
393
        0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
1049
393
        0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
1050
393
        0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
1051
393
        0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
1052
393
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
1053
393
    };
1054
1055
393
    int ret;
1056
393
    libssh2_sha1_ctx exchange_hash_ctx;
1057
1058
393
    if(key_state->state == libssh2_NB_state_idle) {
1059
        /* g == 2 */
1060
393
        key_state->p = _libssh2_bn_init_from_bin(); /* SSH2 defined value
1061
                                                       (p_value) */
1062
393
        key_state->g = _libssh2_bn_init();      /* SSH2 defined value (2) */
1063
1064
        /* Initialize P and G */
1065
393
        if(!key_state->g || _libssh2_bn_set_word(key_state->g, 2)) {
1066
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1067
0
                                 "Failed to allocate key state g.");
1068
0
            goto clean_exit;
1069
0
        }
1070
393
        if(!key_state->p || _libssh2_bn_from_bin(key_state->p, 128, p_value)) {
1071
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1072
0
                                 "Failed to allocate key state p.");
1073
0
            goto clean_exit;
1074
0
        }
1075
1076
393
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
1077
393
                       "Initiating Diffie-Hellman Group1 Key Exchange"));
1078
1079
393
        key_state->state = libssh2_NB_state_created;
1080
393
    }
1081
1082
393
    ret = diffie_hellman_sha_algo(session, key_state->g, key_state->p, 128, 1,
1083
393
                                  (void *)&exchange_hash_ctx,
1084
393
                                  SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY,
1085
393
                                  NULL, 0, &key_state->exchange_state);
1086
393
    if(ret == LIBSSH2_ERROR_EAGAIN) {
1087
0
        return ret;
1088
0
    }
1089
1090
393
clean_exit:
1091
393
    kex_diffie_hellman_cleanup(session, key_state);
1092
1093
393
    return ret;
1094
393
}
1095
1096
1097
/* kex_method_diffie_hellman_group14_key_exchange
1098
 * Diffie-Hellman Group14 Key Exchange with hash function callback
1099
 */
1100
typedef int (*diffie_hellman_hash_func_t)(LIBSSH2_SESSION *,
1101
                                          _libssh2_bn *,
1102
                                          _libssh2_bn *,
1103
                                          int,
1104
                                          int,
1105
                                          void *,
1106
                                          unsigned char,
1107
                                          unsigned char,
1108
                                          unsigned char *,
1109
                                          size_t,
1110
                                          kmdhgGPshakex_state_t *);
1111
static int
1112
kex_method_diffie_hellman_group14_key_exchange(LIBSSH2_SESSION *session,
1113
                                               key_exchange_state_low_t
1114
                                               * key_state,
1115
                                               int sha_algo_value,
1116
                                               void *exchange_hash_ctx,
1117
                                               diffie_hellman_hash_func_t
1118
                                               hashfunc)
1119
265
{
1120
265
    static const unsigned char p_value[256] = {
1121
265
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1122
265
        0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
1123
265
        0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
1124
265
        0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
1125
265
        0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
1126
265
        0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
1127
265
        0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
1128
265
        0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
1129
265
        0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
1130
265
        0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
1131
265
        0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
1132
265
        0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
1133
265
        0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
1134
265
        0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
1135
265
        0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
1136
265
        0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
1137
265
        0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
1138
265
        0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
1139
265
        0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
1140
265
        0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
1141
265
        0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
1142
265
        0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
1143
265
        0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
1144
265
        0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
1145
265
        0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
1146
265
        0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
1147
265
        0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
1148
265
        0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
1149
265
        0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
1150
265
        0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
1151
265
        0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68,
1152
265
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
1153
265
    };
1154
265
    int ret;
1155
1156
265
    if(key_state->state == libssh2_NB_state_idle) {
1157
265
        key_state->p = _libssh2_bn_init_from_bin(); /* SSH2 defined value
1158
                                                       (p_value) */
1159
265
        key_state->g = _libssh2_bn_init();      /* SSH2 defined value (2) */
1160
1161
        /* g == 2 */
1162
        /* Initialize P and G */
1163
265
        if(!key_state->g || _libssh2_bn_set_word(key_state->g, 2)) {
1164
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1165
0
                                 "Failed to allocate key state g.");
1166
0
            goto clean_exit;
1167
0
        }
1168
265
        else if(!key_state->p ||
1169
265
                _libssh2_bn_from_bin(key_state->p, 256, p_value)) {
1170
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1171
0
                                 "Failed to allocate key state p.");
1172
0
            goto clean_exit;
1173
0
        }
1174
1175
265
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
1176
265
                       "Initiating Diffie-Hellman Group14 Key Exchange"));
1177
1178
265
        key_state->state = libssh2_NB_state_created;
1179
265
    }
1180
265
    ret = hashfunc(session, key_state->g, key_state->p,
1181
265
                   256, sha_algo_value, exchange_hash_ctx, SSH_MSG_KEXDH_INIT,
1182
265
                   SSH_MSG_KEXDH_REPLY, NULL, 0, &key_state->exchange_state);
1183
265
    if(ret == LIBSSH2_ERROR_EAGAIN) {
1184
0
        return ret;
1185
0
    }
1186
1187
265
clean_exit:
1188
265
    kex_diffie_hellman_cleanup(session, key_state);
1189
1190
265
    return ret;
1191
265
}
1192
1193
1194
1195
/* kex_method_diffie_hellman_group14_sha1_key_exchange
1196
 * Diffie-Hellman Group14 Key Exchange using SHA1
1197
 */
1198
static int
1199
kex_method_diffie_hellman_group14_sha1_key_exchange(LIBSSH2_SESSION *session,
1200
                                                    key_exchange_state_low_t
1201
                                                    * key_state)
1202
264
{
1203
264
    libssh2_sha1_ctx ctx;
1204
264
    return kex_method_diffie_hellman_group14_key_exchange(session,
1205
264
                                                      key_state, 1,
1206
264
                                                      &ctx,
1207
264
                                                      diffie_hellman_sha_algo);
1208
264
}
1209
1210
1211
1212
/* kex_method_diffie_hellman_group14_sha256_key_exchange
1213
 * Diffie-Hellman Group14 Key Exchange using SHA256
1214
 */
1215
static int
1216
kex_method_diffie_hellman_group14_sha256_key_exchange(LIBSSH2_SESSION *session,
1217
                                                      key_exchange_state_low_t
1218
                                                      * key_state)
1219
1
{
1220
1
    libssh2_sha256_ctx ctx;
1221
1
    return kex_method_diffie_hellman_group14_key_exchange(session,
1222
1
                                                      key_state, 256,
1223
1
                                                      &ctx,
1224
1
                                                      diffie_hellman_sha_algo);
1225
1
}
1226
1227
/* kex_method_diffie_hellman_group16_sha512_key_exchange
1228
* Diffie-Hellman Group16 Key Exchange using SHA512
1229
*/
1230
static int
1231
kex_method_diffie_hellman_group16_sha512_key_exchange(LIBSSH2_SESSION *session,
1232
                                                      key_exchange_state_low_t
1233
                                                      * key_state)
1234
154
{
1235
154
    static const unsigned char p_value[512] = {
1236
154
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
1237
154
    0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
1238
154
    0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
1239
154
    0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
1240
154
    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
1241
154
    0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
1242
154
    0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
1243
154
    0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
1244
154
    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
1245
154
    0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
1246
154
    0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
1247
154
    0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
1248
154
    0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
1249
154
    0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
1250
154
    0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
1251
154
    0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
1252
154
    0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
1253
154
    0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
1254
154
    0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
1255
154
    0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
1256
154
    0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
1257
154
    0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
1258
154
    0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
1259
154
    0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
1260
154
    0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
1261
154
    0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
1262
154
    0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
1263
154
    0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
1264
154
    0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
1265
154
    0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
1266
154
    0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
1267
154
    0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
1268
154
    0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
1269
154
    0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
1270
154
    0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
1271
154
    0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
1272
154
    0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
1273
154
    0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
1274
154
    0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
1275
154
    0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
1276
154
    0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
1277
154
    0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
1278
154
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
1279
154
    };
1280
154
    int ret;
1281
154
    libssh2_sha512_ctx exchange_hash_ctx;
1282
1283
154
    if(key_state->state == libssh2_NB_state_idle) {
1284
154
        key_state->p = _libssh2_bn_init_from_bin(); /* SSH2 defined value
1285
                                                       (p_value) */
1286
154
        key_state->g = _libssh2_bn_init();      /* SSH2 defined value (2) */
1287
1288
        /* g == 2 */
1289
        /* Initialize P and G */
1290
154
        if(!key_state->g || _libssh2_bn_set_word(key_state->g, 2)) {
1291
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1292
0
                                 "Failed to allocate key state g.");
1293
0
            goto clean_exit;
1294
0
        }
1295
154
        if(!key_state->p || _libssh2_bn_from_bin(key_state->p, 512, p_value)) {
1296
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1297
0
                                 "Failed to allocate key state p.");
1298
0
            goto clean_exit;
1299
0
        }
1300
1301
154
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
1302
154
                       "Initiating Diffie-Hellman Group16 Key Exchange"));
1303
1304
154
        key_state->state = libssh2_NB_state_created;
1305
154
    }
1306
1307
154
    ret = diffie_hellman_sha_algo(session, key_state->g, key_state->p, 512,
1308
154
                                  512, (void *)&exchange_hash_ctx,
1309
154
                                  SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY,
1310
154
                                  NULL, 0, &key_state->exchange_state);
1311
154
    if(ret == LIBSSH2_ERROR_EAGAIN) {
1312
0
        return ret;
1313
0
    }
1314
1315
154
clean_exit:
1316
154
    kex_diffie_hellman_cleanup(session, key_state);
1317
1318
154
    return ret;
1319
154
}
1320
1321
/* kex_method_diffie_hellman_group16_sha512_key_exchange
1322
* Diffie-Hellman Group18 Key Exchange using SHA512
1323
*/
1324
static int
1325
kex_method_diffie_hellman_group18_sha512_key_exchange(LIBSSH2_SESSION *session,
1326
                                                      key_exchange_state_low_t
1327
                                                      * key_state)
1328
154
{
1329
154
    static const unsigned char p_value[1024] = {
1330
154
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
1331
154
    0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
1332
154
    0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
1333
154
    0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
1334
154
    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
1335
154
    0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
1336
154
    0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
1337
154
    0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
1338
154
    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
1339
154
    0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
1340
154
    0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
1341
154
    0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
1342
154
    0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
1343
154
    0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
1344
154
    0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
1345
154
    0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
1346
154
    0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
1347
154
    0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
1348
154
    0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
1349
154
    0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
1350
154
    0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
1351
154
    0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
1352
154
    0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
1353
154
    0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
1354
154
    0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
1355
154
    0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
1356
154
    0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
1357
154
    0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
1358
154
    0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
1359
154
    0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
1360
154
    0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
1361
154
    0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
1362
154
    0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
1363
154
    0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
1364
154
    0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
1365
154
    0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
1366
154
    0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
1367
154
    0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
1368
154
    0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
1369
154
    0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
1370
154
    0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
1371
154
    0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92,
1372
154
    0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, 0xC1, 0xD4, 0xDC, 0xB2,
1373
154
    0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
1374
154
    0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F,
1375
154
    0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31,
1376
154
    0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, 0xDA, 0x3E, 0xDB, 0xEB,
1377
154
    0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
1378
154
    0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51,
1379
154
    0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF,
1380
154
    0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, 0x32, 0xEA, 0x15,
1381
154
    0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
1382
154
    0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31,
1383
154
    0x90, 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3,
1384
154
    0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, 0x45, 0xB7,
1385
154
    0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
1386
154
    0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2,
1387
154
    0x0F, 0x80, 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28,
1388
154
    0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, 0x3D,
1389
154
    0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
1390
154
    0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7,
1391
154
    0x6E, 0x3C, 0x04, 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE,
1392
154
    0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E,
1393
154
    0x6D, 0xBE, 0x11, 0x59, 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4,
1394
154
    0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, 0xD8, 0xBE, 0xC4, 0xD0,
1395
154
    0x73, 0xB9, 0x31, 0xBA, 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00,
1396
154
    0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, 0x25, 0x76, 0xF6, 0x93,
1397
154
    0x6B, 0xA4, 0x24, 0x66, 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68,
1398
154
    0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, 0x23, 0x8F, 0x16, 0xCB,
1399
154
    0xE3, 0x9D, 0x65, 0x2D, 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9,
1400
154
    0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, 0x13, 0xEB, 0x57, 0xA8,
1401
154
    0x1A, 0x23, 0xF0, 0xC7, 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B,
1402
154
    0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, 0xFA, 0x9D, 0x4B, 0x7F,
1403
154
    0xA2, 0xC0, 0x87, 0xE8, 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A,
1404
154
    0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, 0x6D, 0x2A, 0x13, 0xF8,
1405
154
    0x3F, 0x44, 0xF8, 0x2D, 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36,
1406
154
    0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, 0x64, 0xF3, 0x1C, 0xC5,
1407
154
    0x08, 0x46, 0x85, 0x1D, 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1,
1408
154
    0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, 0xFA, 0xF3, 0x6B, 0xC3,
1409
154
    0x1E, 0xCF, 0xA2, 0x68, 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92,
1410
154
    0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, 0x88, 0x9A, 0x00, 0x2E,
1411
154
    0xD5, 0xEE, 0x38, 0x2B, 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47,
1412
154
    0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, 0x9E, 0x30, 0x50, 0xE2,
1413
154
    0x76, 0x56, 0x94, 0xDF, 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71,
1414
154
    0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF,
1415
154
    0xFF, 0xFF, 0xFF, 0xFF
1416
154
    };
1417
154
    int ret;
1418
154
    libssh2_sha512_ctx exchange_hash_ctx;
1419
1420
154
    if(key_state->state == libssh2_NB_state_idle) {
1421
154
        key_state->p = _libssh2_bn_init_from_bin(); /* SSH2 defined value
1422
                                                       (p_value) */
1423
154
        key_state->g = _libssh2_bn_init();      /* SSH2 defined value (2) */
1424
1425
        /* g == 2 */
1426
        /* Initialize P and G */
1427
154
        if(!key_state->g || _libssh2_bn_set_word(key_state->g, 2)) {
1428
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1429
0
                                 "Failed to allocate key state g.");
1430
0
            goto clean_exit;
1431
0
        }
1432
154
        else if(!key_state->p ||
1433
154
                _libssh2_bn_from_bin(key_state->p, 1024, p_value)) {
1434
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1435
0
                                 "Failed to allocate key state p.");
1436
0
            goto clean_exit;
1437
0
        }
1438
1439
154
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
1440
154
                       "Initiating Diffie-Hellman Group18 Key Exchange"));
1441
1442
154
        key_state->state = libssh2_NB_state_created;
1443
154
    }
1444
1445
154
    ret = diffie_hellman_sha_algo(session, key_state->g, key_state->p, 1024,
1446
154
                                  512, (void *)&exchange_hash_ctx,
1447
154
                                  SSH_MSG_KEXDH_INIT, SSH_MSG_KEXDH_REPLY,
1448
154
                                  NULL, 0, &key_state->exchange_state);
1449
154
    if(ret == LIBSSH2_ERROR_EAGAIN) {
1450
0
        return ret;
1451
0
    }
1452
1453
154
clean_exit:
1454
154
    kex_diffie_hellman_cleanup(session, key_state);
1455
1456
154
    return ret;
1457
154
}
1458
1459
/* kex_method_diffie_hellman_group_exchange_sha1_key_exchange
1460
 * Diffie-Hellman Group Exchange Key Exchange using SHA1
1461
 * Negotiates random(ish) group for secret derivation
1462
 */
1463
static int
1464
kex_method_diffie_hellman_group_exchange_sha1_key_exchange(
1465
                                          LIBSSH2_SESSION * session,
1466
                                          key_exchange_state_low_t * key_state)
1467
37
{
1468
37
    int ret = 0;
1469
37
    int rc;
1470
1471
37
    if(key_state->state == libssh2_NB_state_idle) {
1472
37
        key_state->p = _libssh2_bn_init_from_bin();
1473
37
        key_state->g = _libssh2_bn_init_from_bin();
1474
        /* Ask for a P and G pair */
1475
37
        key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST;
1476
37
        _libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_MINGROUP);
1477
37
        _libssh2_htonu32(key_state->request + 5, LIBSSH2_DH_GEX_OPTGROUP);
1478
37
        _libssh2_htonu32(key_state->request + 9, LIBSSH2_DH_GEX_MAXGROUP);
1479
37
        key_state->request_len = 13;
1480
37
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
1481
37
                       "Initiating Diffie-Hellman Group-Exchange SHA1"));
1482
1483
37
        key_state->state = libssh2_NB_state_created;
1484
37
    }
1485
1486
37
    if(key_state->state == libssh2_NB_state_created) {
1487
37
        rc = _libssh2_transport_send(session, key_state->request,
1488
37
                                     key_state->request_len, NULL, 0);
1489
37
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1490
0
            return rc;
1491
0
        }
1492
37
        else if(rc) {
1493
0
            ret = _libssh2_error(session, rc,
1494
0
                                 "Unable to send Group Exchange Request");
1495
0
            goto dh_gex_clean_exit;
1496
0
        }
1497
1498
37
        key_state->state = libssh2_NB_state_sent;
1499
37
    }
1500
1501
37
    if(key_state->state == libssh2_NB_state_sent) {
1502
37
        rc = _libssh2_packet_require(session, SSH_MSG_KEX_DH_GEX_GROUP,
1503
37
                                     &key_state->data, &key_state->data_len,
1504
37
                                     0, NULL, 0, &key_state->req_state);
1505
37
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1506
0
            return rc;
1507
0
        }
1508
37
        else if(rc) {
1509
9
            ret = _libssh2_error(session, rc,
1510
9
                                 "Timeout waiting for GEX_GROUP reply");
1511
9
            goto dh_gex_clean_exit;
1512
9
        }
1513
1514
28
        key_state->state = libssh2_NB_state_sent1;
1515
28
    }
1516
1517
28
    if(key_state->state == libssh2_NB_state_sent1) {
1518
28
        size_t p_len, g_len;
1519
28
        unsigned char *p, *g;
1520
28
        struct string_buf buf;
1521
28
        libssh2_sha1_ctx exchange_hash_ctx;
1522
1523
28
        if(key_state->data_len < 9) {
1524
2
            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
1525
2
                                 "Unexpected key length DH-SHA1");
1526
2
            goto dh_gex_clean_exit;
1527
2
        }
1528
1529
26
        buf.data = key_state->data;
1530
26
        buf.dataptr = buf.data;
1531
26
        buf.len = key_state->data_len;
1532
1533
26
        buf.dataptr++; /* increment to big num */
1534
1535
26
        if(_libssh2_get_bignum_bytes(&buf, &p, &p_len)) {
1536
3
            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
1537
3
                                 "Unexpected value DH-SHA1 p");
1538
3
            goto dh_gex_clean_exit;
1539
3
        }
1540
1541
23
        if(_libssh2_get_bignum_bytes(&buf, &g, &g_len)) {
1542
2
            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
1543
2
                                 "Unexpected value DH-SHA1 g");
1544
2
            goto dh_gex_clean_exit;
1545
2
        }
1546
1547
21
        if(_libssh2_bn_from_bin(key_state->p, p_len, p)) {
1548
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
1549
0
                                 "Invalid DH-SHA1 p");
1550
0
            goto dh_gex_clean_exit;
1551
0
        }
1552
1553
21
        if(_libssh2_bn_from_bin(key_state->g, g_len, g)) {
1554
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
1555
0
                                 "Invalid DH-SHA1 g");
1556
0
            goto dh_gex_clean_exit;
1557
0
        }
1558
1559
21
        ret = diffie_hellman_sha_algo(session, key_state->g, key_state->p,
1560
21
                                      (int)p_len, 1,
1561
21
                                      (void *)&exchange_hash_ctx,
1562
21
                                      SSH_MSG_KEX_DH_GEX_INIT,
1563
21
                                      SSH_MSG_KEX_DH_GEX_REPLY,
1564
21
                                      key_state->data + 1,
1565
21
                                      key_state->data_len - 1,
1566
21
                                      &key_state->exchange_state);
1567
21
        if(ret == LIBSSH2_ERROR_EAGAIN) {
1568
0
            return ret;
1569
0
        }
1570
21
    }
1571
1572
37
dh_gex_clean_exit:
1573
37
    kex_diffie_hellman_cleanup(session, key_state);
1574
1575
37
    return ret;
1576
28
}
1577
1578
1579
1580
/* kex_method_diffie_hellman_group_exchange_sha256_key_exchange
1581
 * Diffie-Hellman Group Exchange Key Exchange using SHA256
1582
 * Negotiates random(ish) group for secret derivation
1583
 */
1584
static int
1585
kex_method_diffie_hellman_group_exchange_sha256_key_exchange(
1586
                                          LIBSSH2_SESSION * session,
1587
                                          key_exchange_state_low_t * key_state)
1588
307
{
1589
307
    int ret = 0;
1590
307
    int rc;
1591
1592
307
    if(key_state->state == libssh2_NB_state_idle) {
1593
307
        key_state->p = _libssh2_bn_init();
1594
307
        key_state->g = _libssh2_bn_init();
1595
        /* Ask for a P and G pair */
1596
307
        key_state->request[0] = SSH_MSG_KEX_DH_GEX_REQUEST;
1597
307
        _libssh2_htonu32(key_state->request + 1, LIBSSH2_DH_GEX_MINGROUP);
1598
307
        _libssh2_htonu32(key_state->request + 5, LIBSSH2_DH_GEX_OPTGROUP);
1599
307
        _libssh2_htonu32(key_state->request + 9, LIBSSH2_DH_GEX_MAXGROUP);
1600
307
        key_state->request_len = 13;
1601
307
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
1602
307
                       "Initiating Diffie-Hellman Group-Exchange SHA256"));
1603
1604
307
        key_state->state = libssh2_NB_state_created;
1605
307
    }
1606
1607
307
    if(key_state->state == libssh2_NB_state_created) {
1608
307
        rc = _libssh2_transport_send(session, key_state->request,
1609
307
                                     key_state->request_len, NULL, 0);
1610
307
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1611
0
            return rc;
1612
0
        }
1613
307
        else if(rc) {
1614
0
            ret = _libssh2_error(session, rc,
1615
0
                                 "Unable to send "
1616
0
                                 "Group Exchange Request SHA256");
1617
0
            goto dh_gex_clean_exit;
1618
0
        }
1619
1620
307
        key_state->state = libssh2_NB_state_sent;
1621
307
    }
1622
1623
307
    if(key_state->state == libssh2_NB_state_sent) {
1624
307
        rc = _libssh2_packet_require(session, SSH_MSG_KEX_DH_GEX_GROUP,
1625
307
                                     &key_state->data, &key_state->data_len,
1626
307
                                     0, NULL, 0, &key_state->req_state);
1627
307
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1628
0
            return rc;
1629
0
        }
1630
307
        else if(rc) {
1631
101
            ret = _libssh2_error(session, rc,
1632
101
                                 "Timeout waiting for GEX_GROUP reply SHA256");
1633
101
            goto dh_gex_clean_exit;
1634
101
        }
1635
1636
206
        key_state->state = libssh2_NB_state_sent1;
1637
206
    }
1638
1639
206
    if(key_state->state == libssh2_NB_state_sent1) {
1640
206
        unsigned char *p, *g;
1641
206
        size_t p_len, g_len;
1642
206
        struct string_buf buf;
1643
206
        libssh2_sha256_ctx exchange_hash_ctx;
1644
1645
206
        if(key_state->data_len < 9) {
1646
3
            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
1647
3
                                 "Unexpected key length DH-SHA256");
1648
3
            goto dh_gex_clean_exit;
1649
3
        }
1650
1651
203
        buf.data = key_state->data;
1652
203
        buf.dataptr = buf.data;
1653
203
        buf.len = key_state->data_len;
1654
1655
203
        buf.dataptr++; /* increment to big num */
1656
1657
203
        if(_libssh2_get_bignum_bytes(&buf, &p, &p_len)) {
1658
12
            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
1659
12
                                 "Unexpected value DH-SHA256 p");
1660
12
            goto dh_gex_clean_exit;
1661
12
        }
1662
1663
191
        if(_libssh2_get_bignum_bytes(&buf, &g, &g_len)) {
1664
11
            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
1665
11
                                 "Unexpected value DH-SHA256 g");
1666
11
            goto dh_gex_clean_exit;
1667
11
        }
1668
1669
180
        if(_libssh2_bn_from_bin(key_state->p, p_len, p)) {
1670
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
1671
0
                                 "Invalid DH-SHA256 p");
1672
0
            goto dh_gex_clean_exit;
1673
0
        }
1674
1675
180
        if(_libssh2_bn_from_bin(key_state->g, g_len, g)) {
1676
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
1677
0
                                 "Invalid DH-SHA256 g");
1678
0
            goto dh_gex_clean_exit;
1679
0
        }
1680
1681
180
        ret = diffie_hellman_sha_algo(session, key_state->g, key_state->p,
1682
180
                                      (int)p_len, 256,
1683
180
                                      (void *)&exchange_hash_ctx,
1684
180
                                      SSH_MSG_KEX_DH_GEX_INIT,
1685
180
                                      SSH_MSG_KEX_DH_GEX_REPLY,
1686
180
                                      key_state->data + 1,
1687
180
                                      key_state->data_len - 1,
1688
180
                                      &key_state->exchange_state);
1689
180
        if(ret == LIBSSH2_ERROR_EAGAIN) {
1690
0
            return ret;
1691
0
        }
1692
180
    }
1693
1694
307
dh_gex_clean_exit:
1695
307
    kex_diffie_hellman_cleanup(session, key_state);
1696
1697
307
    return ret;
1698
206
}
1699
1700
#if LIBSSH2_ECDSA
1701
1702
/* LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY
1703
 *
1704
 * Macro that create and verifies EC SHA hash with a given digest bytes
1705
 *
1706
 * Payload format:
1707
 *
1708
 * string   V_C, client's identification string (CR and LF excluded)
1709
 * string   V_S, server's identification string (CR and LF excluded)
1710
 * string   I_C, payload of the client's SSH_MSG_KEXINIT
1711
 * string   I_S, payload of the server's SSH_MSG_KEXINIT
1712
 * string   K_S, server's public host key
1713
 * string   Q_C, client's ephemeral public key octet string
1714
 * string   Q_S, server's ephemeral public key octet string
1715
 * mpint    K,   shared secret
1716
 *
1717
 */
1718
6
#define LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(digest_type)            \
1719
6
do {                                                                         \
1720
6
    libssh2_sha##digest_type##_ctx ctx;                                      \
1721
6
    int hok;                                                                 \
1722
6
    if(!libssh2_sha##digest_type##_init(&ctx)) {                             \
1723
0
        rc = -1;                                                             \
1724
0
        break;                                                               \
1725
0
    }                                                                        \
1726
6
    exchange_state->exchange_hash = (void *)&ctx;                            \
1727
6
    hok = 1;                                                                 \
1728
6
    if(session->local.banner) {                                              \
1729
0
        _libssh2_htonu32(exchange_state->h_sig_comp,                         \
1730
0
            (uint32_t)(strlen((char *) session->local.banner) - 2));         \
1731
0
        hok &= libssh2_sha##digest_type##_update(ctx,                        \
1732
0
                                                 exchange_state->h_sig_comp, \
1733
0
                                                 4);                         \
1734
0
        hok &= libssh2_sha##digest_type##_update(ctx,                        \
1735
0
                                              (char *)session->local.banner, \
1736
0
                                       strlen((char *)session->local.banner) \
1737
0
                                       - 2);                                 \
1738
0
    }                                                                        \
1739
6
    else {                                                                   \
1740
6
        _libssh2_htonu32(exchange_state->h_sig_comp,                         \
1741
6
                         sizeof(LIBSSH2_SSH_DEFAULT_BANNER) - 1);            \
1742
6
        hok &= libssh2_sha##digest_type##_update(ctx,                        \
1743
6
                                          exchange_state->h_sig_comp, 4);    \
1744
6
        hok &= libssh2_sha##digest_type##_update(ctx,                        \
1745
6
                                                 LIBSSH2_SSH_DEFAULT_BANNER, \
1746
6
                                          sizeof(LIBSSH2_SSH_DEFAULT_BANNER) \
1747
6
                                          - 1);                              \
1748
6
    }                                                                        \
1749
6
                                                                             \
1750
6
    _libssh2_htonu32(exchange_state->h_sig_comp,                             \
1751
6
        (uint32_t)strlen((char *) session->remote.banner));                  \
1752
6
    hok &= libssh2_sha##digest_type##_update(ctx,                            \
1753
6
                                             exchange_state->h_sig_comp, 4); \
1754
6
    hok &= libssh2_sha##digest_type##_update(ctx, session->remote.banner,    \
1755
6
                                   strlen((char *)session->remote.banner));  \
1756
6
                                                                             \
1757
6
    _libssh2_htonu32(exchange_state->h_sig_comp,                             \
1758
6
                     (uint32_t)session->local.kexinit_len);                  \
1759
6
    hok &= libssh2_sha##digest_type##_update(ctx,                            \
1760
6
                                             exchange_state->h_sig_comp, 4); \
1761
6
    hok &= libssh2_sha##digest_type##_update(ctx,                            \
1762
6
                                             session->local.kexinit,         \
1763
6
                                             session->local.kexinit_len);    \
1764
6
                                                                             \
1765
6
    _libssh2_htonu32(exchange_state->h_sig_comp,                             \
1766
6
                     (uint32_t)session->remote.kexinit_len);                 \
1767
6
    hok &= libssh2_sha##digest_type##_update(ctx,                            \
1768
6
                                             exchange_state->h_sig_comp, 4); \
1769
6
    hok &= libssh2_sha##digest_type##_update(ctx,                            \
1770
6
                                             session->remote.kexinit,        \
1771
6
                                             session->remote.kexinit_len);   \
1772
6
                                                                             \
1773
6
    _libssh2_htonu32(exchange_state->h_sig_comp,                             \
1774
6
                     session->server_hostkey_len);                           \
1775
6
    hok &= libssh2_sha##digest_type##_update(ctx,                            \
1776
6
                                             exchange_state->h_sig_comp, 4); \
1777
6
    hok &= libssh2_sha##digest_type##_update(ctx,                            \
1778
6
                                             session->server_hostkey,        \
1779
6
                                             session->server_hostkey_len);   \
1780
6
                                                                             \
1781
6
    _libssh2_htonu32(exchange_state->h_sig_comp,                             \
1782
6
                     (uint32_t)public_key_len);                              \
1783
6
    hok &= libssh2_sha##digest_type##_update(ctx,                            \
1784
6
                                             exchange_state->h_sig_comp, 4); \
1785
6
    hok &= libssh2_sha##digest_type##_update(ctx,                            \
1786
6
                                             public_key,                     \
1787
6
                                             public_key_len);                \
1788
6
                                                                             \
1789
6
    _libssh2_htonu32(exchange_state->h_sig_comp,                             \
1790
6
                     (uint32_t)server_public_key_len);                       \
1791
6
    hok &= libssh2_sha##digest_type##_update(ctx,                            \
1792
6
                                             exchange_state->h_sig_comp, 4); \
1793
6
    hok &= libssh2_sha##digest_type##_update(ctx,                            \
1794
6
                                             server_public_key,              \
1795
6
                                             server_public_key_len);         \
1796
6
                                                                             \
1797
6
    hok &= libssh2_sha##digest_type##_update(ctx,                            \
1798
6
                                             exchange_state->k_value,        \
1799
6
                                             exchange_state->k_value_len);   \
1800
6
                                                                             \
1801
6
    if(!hok ||                                                               \
1802
6
       !libssh2_sha##digest_type##_final(ctx, exchange_state->h_sig_comp)) { \
1803
0
        rc = -1;                                                             \
1804
0
        break;                                                               \
1805
0
    }                                                                        \
1806
6
                                                                             \
1807
6
    if(session->hostkey->                                                    \
1808
6
        sig_verify(session, exchange_state->h_sig,                           \
1809
6
                   exchange_state->h_sig_len, exchange_state->h_sig_comp,    \
1810
6
                   SHA##digest_type##_DIGEST_LENGTH,                         \
1811
6
                   &session->server_hostkey_abstract)) {                     \
1812
6
        rc = -1;                                                             \
1813
6
    }                                                                        \
1814
6
} while(0)
1815
1816
/* kex_session_ecdh_curve_type
1817
 * returns the EC curve type by name used in key exchange
1818
 */
1819
1820
static int
1821
kex_session_ecdh_curve_type(const char *name, libssh2_curve_type *out_type)
1822
392
{
1823
392
    libssh2_curve_type type;
1824
1825
392
    if(!name)
1826
0
        return -1;
1827
1828
392
    if(strcmp(name, "ecdh-sha2-nistp256") == 0)
1829
121
        type = LIBSSH2_EC_CURVE_NISTP256;
1830
271
    else if(strcmp(name, "ecdh-sha2-nistp384") == 0)
1831
40
        type = LIBSSH2_EC_CURVE_NISTP384;
1832
231
    else if(strcmp(name, "ecdh-sha2-nistp521") == 0)
1833
231
        type = LIBSSH2_EC_CURVE_NISTP521;
1834
0
    else {
1835
0
        return -1;
1836
0
    }
1837
1838
392
    if(out_type) {
1839
392
        *out_type = type;
1840
392
    }
1841
1842
392
    return 0;
1843
392
}
1844
1845
1846
static void
1847
ecdh_exchange_state_cleanup(LIBSSH2_SESSION * session,
1848
                            kmdhgGPshakex_state_t *exchange_state)
1849
156
{
1850
156
    _libssh2_bn_free(exchange_state->k);
1851
156
    exchange_state->k = NULL;
1852
1853
156
    if(exchange_state->k_value) {
1854
0
        LIBSSH2_FREE(session, exchange_state->k_value);
1855
0
        exchange_state->k_value = NULL;
1856
0
    }
1857
1858
156
    exchange_state->state = libssh2_NB_state_idle;
1859
156
}
1860
1861
1862
static void
1863
kex_method_ecdh_cleanup
1864
(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
1865
580
{
1866
580
    if(key_state->public_key_oct) {
1867
233
        LIBSSH2_FREE(session, key_state->public_key_oct);
1868
233
        key_state->public_key_oct = NULL;
1869
233
    }
1870
1871
580
    if(key_state->private_key) {
1872
233
        _libssh2_ecdsa_free(key_state->private_key);
1873
233
        key_state->private_key = NULL;
1874
233
    }
1875
1876
580
    if(key_state->data) {
1877
159
        LIBSSH2_FREE(session, key_state->data);
1878
159
        key_state->data = NULL;
1879
159
    }
1880
1881
580
    key_state->state = libssh2_NB_state_idle;
1882
1883
580
    if(key_state->exchange_state.state != libssh2_NB_state_idle) {
1884
0
        ecdh_exchange_state_cleanup(session, &key_state->exchange_state);
1885
0
    }
1886
580
}
1887
1888
1889
/* ecdh_sha2_nistp
1890
 * Elliptic Curve Diffie Hellman Key Exchange
1891
 */
1892
1893
static int ecdh_sha2_nistp(LIBSSH2_SESSION *session, libssh2_curve_type type,
1894
                           unsigned char *data, size_t data_len,
1895
                           unsigned char *public_key,
1896
                           size_t public_key_len, _libssh2_ec_key *private_key,
1897
                           kmdhgGPshakex_state_t *exchange_state)
1898
159
{
1899
159
    int ret = 0;
1900
159
    int rc;
1901
1902
159
    if(data_len < 5) {
1903
3
        ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
1904
3
                             "Host key data is too short");
1905
3
        return ret;
1906
3
    }
1907
1908
156
    if(exchange_state->state == libssh2_NB_state_idle) {
1909
1910
        /* Setup initial values */
1911
156
        exchange_state->k = _libssh2_bn_init();
1912
1913
156
        exchange_state->state = libssh2_NB_state_created;
1914
156
    }
1915
1916
156
    if(exchange_state->state == libssh2_NB_state_created) {
1917
        /* parse INIT reply data */
1918
1919
        /* host key K_S */
1920
156
        unsigned char *server_public_key;
1921
156
        size_t server_public_key_len;
1922
156
        struct string_buf buf;
1923
1924
156
        buf.data = data;
1925
156
        buf.len = data_len;
1926
156
        buf.dataptr = buf.data;
1927
156
        buf.dataptr++; /* Advance past packet type */
1928
1929
156
        if(_libssh2_copy_string(session, &buf, &(session->server_hostkey),
1930
156
                                &server_public_key_len)) {
1931
5
            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1932
5
                                 "Unable to allocate memory for a copy "
1933
5
                                 "of the host ECDH key");
1934
5
            goto clean_exit;
1935
5
        }
1936
1937
151
        session->server_hostkey_len = (uint32_t)server_public_key_len;
1938
1939
#if LIBSSH2_MD5
1940
        {
1941
            libssh2_md5_ctx fingerprint_ctx;
1942
1943
            if(libssh2_md5_init(&fingerprint_ctx) &&
1944
               libssh2_md5_update(fingerprint_ctx, session->server_hostkey,
1945
                                  session->server_hostkey_len) &&
1946
               libssh2_md5_final(fingerprint_ctx,
1947
                                 session->server_hostkey_md5)) {
1948
                session->server_hostkey_md5_valid = TRUE;
1949
            }
1950
            else {
1951
                session->server_hostkey_md5_valid = FALSE;
1952
            }
1953
        }
1954
#ifdef LIBSSH2DEBUG
1955
        {
1956
            char fingerprint[50], *fprint = fingerprint;
1957
            int i;
1958
            for(i = 0; i < 16; i++, fprint += 3) {
1959
                snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]);
1960
            }
1961
            *(--fprint) = '\0';
1962
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
1963
                           "Server's MD5 Fingerprint: %s", fingerprint));
1964
        }
1965
#endif /* LIBSSH2DEBUG */
1966
#endif /* ! LIBSSH2_MD5 */
1967
1968
151
        {
1969
151
            libssh2_sha1_ctx fingerprint_ctx;
1970
1971
151
            if(libssh2_sha1_init(&fingerprint_ctx) &&
1972
151
               libssh2_sha1_update(fingerprint_ctx, session->server_hostkey,
1973
151
                                   session->server_hostkey_len) &&
1974
151
               libssh2_sha1_final(fingerprint_ctx,
1975
151
                                  session->server_hostkey_sha1)) {
1976
151
                session->server_hostkey_sha1_valid = TRUE;
1977
151
            }
1978
0
            else {
1979
0
                session->server_hostkey_sha1_valid = FALSE;
1980
0
            }
1981
151
        }
1982
151
#ifdef LIBSSH2DEBUG
1983
151
        {
1984
151
            char fingerprint[64], *fprint = fingerprint;
1985
151
            int i;
1986
3.17k
            for(i = 0; i < 20; i++, fprint += 3) {
1987
3.02k
                snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]);
1988
3.02k
            }
1989
151
            *(--fprint) = '\0';
1990
151
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
1991
151
                           "Server's SHA1 Fingerprint: %s", fingerprint));
1992
151
        }
1993
151
#endif /* LIBSSH2DEBUG */
1994
1995
        /* SHA256 */
1996
151
        {
1997
151
            libssh2_sha256_ctx fingerprint_ctx;
1998
1999
151
            if(libssh2_sha256_init(&fingerprint_ctx) &&
2000
151
               libssh2_sha256_update(fingerprint_ctx, session->server_hostkey,
2001
151
                                     session->server_hostkey_len) &&
2002
151
               libssh2_sha256_final(fingerprint_ctx,
2003
151
                                    session->server_hostkey_sha256)) {
2004
151
                session->server_hostkey_sha256_valid = TRUE;
2005
151
            }
2006
0
            else {
2007
0
                session->server_hostkey_sha256_valid = FALSE;
2008
0
            }
2009
151
        }
2010
151
#ifdef LIBSSH2DEBUG
2011
151
        {
2012
151
            char *base64Fingerprint = NULL;
2013
151
            _libssh2_base64_encode(session,
2014
151
                                   (const char *)
2015
151
                                   session->server_hostkey_sha256,
2016
151
                                   SHA256_DIGEST_LENGTH, &base64Fingerprint);
2017
151
            if(base64Fingerprint) {
2018
151
                _libssh2_debug((session, LIBSSH2_TRACE_KEX,
2019
151
                               "Server's SHA256 Fingerprint: %s",
2020
151
                               base64Fingerprint));
2021
151
                LIBSSH2_FREE(session, base64Fingerprint);
2022
151
            }
2023
151
        }
2024
151
#endif /* LIBSSH2DEBUG */
2025
2026
151
        if(session->hostkey->init(session, session->server_hostkey,
2027
151
                                  session->server_hostkey_len,
2028
151
                                  &session->server_hostkey_abstract)) {
2029
147
            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
2030
147
                                 "Unable to initialize hostkey importer "
2031
147
                                 "ECDH");
2032
147
            goto clean_exit;
2033
147
        }
2034
2035
        /* server public key Q_S */
2036
4
        if(_libssh2_get_string(&buf, &server_public_key,
2037
4
                               &server_public_key_len)) {
2038
1
            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
2039
1
                                 "Unexpected key length ECDH");
2040
1
            goto clean_exit;
2041
1
        }
2042
2043
        /* server signature */
2044
3
        if(_libssh2_get_string(&buf, &exchange_state->h_sig,
2045
3
           &(exchange_state->h_sig_len))) {
2046
1
            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
2047
1
                                 "Unexpected ECDH server sig length");
2048
1
            goto clean_exit;
2049
1
        }
2050
2051
        /* Compute the shared secret K */
2052
2
        rc = _libssh2_ecdh_gen_k(&exchange_state->k, private_key,
2053
2
                                 server_public_key, server_public_key_len);
2054
2
        if(rc) {
2055
2
            ret = _libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
2056
2
                                 "Unable to create ECDH shared secret");
2057
2
            goto clean_exit;
2058
2
        }
2059
2060
0
        exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5;
2061
0
        if(_libssh2_bn_bits(exchange_state->k) % 8) {
2062
            /* don't need leading 00 */
2063
0
            exchange_state->k_value_len--;
2064
0
        }
2065
0
        exchange_state->k_value =
2066
0
        LIBSSH2_ALLOC(session, exchange_state->k_value_len);
2067
0
        if(!exchange_state->k_value) {
2068
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2069
0
                                 "Unable to allocate buffer for ECDH K");
2070
0
            goto clean_exit;
2071
0
        }
2072
0
        _libssh2_htonu32(exchange_state->k_value,
2073
0
                         (uint32_t)(exchange_state->k_value_len - 4));
2074
0
        if(_libssh2_bn_bits(exchange_state->k) % 8) {
2075
0
            if(_libssh2_bn_to_bin(exchange_state->k,
2076
0
                                  exchange_state->k_value + 4)) {
2077
0
                ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
2078
0
                                     "Can't write exchange_state->k");
2079
0
                goto clean_exit;
2080
0
            }
2081
0
        }
2082
0
        else {
2083
0
            exchange_state->k_value[4] = 0;
2084
0
            if(_libssh2_bn_to_bin(exchange_state->k,
2085
0
                                  exchange_state->k_value + 5)) {
2086
0
                ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
2087
0
                                     "Can't write exchange_state->e");
2088
0
                goto clean_exit;
2089
0
            }
2090
0
        }
2091
2092
        /* verify hash */
2093
2094
0
        switch(type) {
2095
0
            case LIBSSH2_EC_CURVE_NISTP256:
2096
0
                LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(256);
2097
0
                break;
2098
0
            case LIBSSH2_EC_CURVE_NISTP384:
2099
0
                LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(384);
2100
0
                break;
2101
0
            case LIBSSH2_EC_CURVE_NISTP521:
2102
0
                LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(512);
2103
0
                break;
2104
0
        }
2105
2106
0
        if(rc) {
2107
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN,
2108
0
                                 "Unable to verify hostkey signature "
2109
0
                                 "ECDH");
2110
0
            goto clean_exit;
2111
0
        }
2112
2113
0
        exchange_state->c = SSH_MSG_NEWKEYS;
2114
0
        exchange_state->state = libssh2_NB_state_sent;
2115
0
    }
2116
2117
0
    if(exchange_state->state == libssh2_NB_state_sent) {
2118
0
        rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0);
2119
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
2120
0
            return rc;
2121
0
        }
2122
0
        else if(rc) {
2123
0
            ret = _libssh2_error(session, rc,
2124
0
                                 "Unable to send NEWKEYS message ECDH");
2125
0
            goto clean_exit;
2126
0
        }
2127
2128
0
        exchange_state->state = libssh2_NB_state_sent2;
2129
0
    }
2130
2131
0
    if(exchange_state->state == libssh2_NB_state_sent2) {
2132
0
        rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS,
2133
0
                                     &exchange_state->tmp,
2134
0
                                     &exchange_state->tmp_len, 0, NULL, 0,
2135
0
                                     &exchange_state->req_state);
2136
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
2137
0
            return rc;
2138
0
        }
2139
0
        else if(rc) {
2140
0
            ret = _libssh2_error(session, rc,
2141
0
                                 "Timed out waiting for NEWKEYS ECDH");
2142
0
            goto clean_exit;
2143
0
        }
2144
2145
        /* The first key exchange has been performed,
2146
           switch to active crypt/comp/mac mode */
2147
0
        session->state |= LIBSSH2_STATE_NEWKEYS;
2148
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
2149
0
                       "Received NEWKEYS message ECDH"));
2150
2151
        /* This will actually end up being just packet_type(1)
2152
           for this packet type anyway */
2153
0
        LIBSSH2_FREE(session, exchange_state->tmp);
2154
2155
0
        if(!session->session_id) {
2156
2157
0
            size_t digest_length = 0;
2158
2159
0
            if(type == LIBSSH2_EC_CURVE_NISTP256)
2160
0
                digest_length = SHA256_DIGEST_LENGTH;
2161
0
            else if(type == LIBSSH2_EC_CURVE_NISTP384)
2162
0
                digest_length = SHA384_DIGEST_LENGTH;
2163
0
            else if(type == LIBSSH2_EC_CURVE_NISTP521)
2164
0
                digest_length = SHA512_DIGEST_LENGTH;
2165
0
            else{
2166
0
                ret = _libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
2167
0
                                     "Unknown SHA digest for EC curve");
2168
0
                goto clean_exit;
2169
2170
0
            }
2171
0
            session->session_id = LIBSSH2_ALLOC(session, digest_length);
2172
0
            if(!session->session_id) {
2173
0
                ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2174
0
                                     "Unable to allocate buffer for "
2175
0
                                     "SHA digest");
2176
0
                goto clean_exit;
2177
0
            }
2178
0
            memcpy(session->session_id, exchange_state->h_sig_comp,
2179
0
                   digest_length);
2180
0
             session->session_id_len = (uint32_t)digest_length;
2181
0
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
2182
0
                           "session_id calculated"));
2183
0
        }
2184
2185
        /* Cleanup any existing cipher */
2186
0
        if(session->local.crypt->dtor) {
2187
0
            session->local.crypt->dtor(session,
2188
0
                                       &session->local.crypt_abstract);
2189
0
        }
2190
2191
        /* Calculate IV/Secret/Key for each direction */
2192
0
        if(session->local.crypt->init) {
2193
0
            unsigned char *iv = NULL, *secret = NULL;
2194
0
            int free_iv = 0, free_secret = 0;
2195
2196
0
            LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(iv,
2197
0
                                                 session->local.crypt->
2198
0
                                                 iv_len, "A");
2199
0
            if(!iv) {
2200
0
                ret = -1;
2201
0
                goto clean_exit;
2202
0
            }
2203
2204
0
            LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(secret,
2205
0
                                                 session->local.crypt->
2206
0
                                                 secret_len, "C");
2207
2208
0
            if(!secret) {
2209
0
                LIBSSH2_FREE(session, iv);
2210
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
2211
0
                goto clean_exit;
2212
0
            }
2213
0
            if(session->local.crypt->
2214
0
                init(session, session->local.crypt, iv, &free_iv, secret,
2215
0
                     &free_secret, 1, &session->local.crypt_abstract)) {
2216
0
                    LIBSSH2_FREE(session, iv);
2217
0
                    LIBSSH2_FREE(session, secret);
2218
0
                    ret = LIBSSH2_ERROR_KEX_FAILURE;
2219
0
                    goto clean_exit;
2220
0
                }
2221
2222
0
            if(free_iv) {
2223
0
                _libssh2_explicit_zero(iv, session->local.crypt->iv_len);
2224
0
                LIBSSH2_FREE(session, iv);
2225
0
            }
2226
2227
0
            if(free_secret) {
2228
0
                _libssh2_explicit_zero(secret,
2229
0
                                       session->local.crypt->secret_len);
2230
0
                LIBSSH2_FREE(session, secret);
2231
0
            }
2232
0
        }
2233
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
2234
0
                       "Client to Server IV and Key calculated"));
2235
2236
0
        if(session->remote.crypt->dtor) {
2237
            /* Cleanup any existing cipher */
2238
0
            session->remote.crypt->dtor(session,
2239
0
                                        &session->remote.crypt_abstract);
2240
0
        }
2241
2242
0
        if(session->remote.crypt->init) {
2243
0
            unsigned char *iv = NULL, *secret = NULL;
2244
0
            int free_iv = 0, free_secret = 0;
2245
2246
0
            LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(iv,
2247
0
                                                 session->remote.crypt->
2248
0
                                                 iv_len, "B");
2249
2250
0
            if(!iv) {
2251
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
2252
0
                goto clean_exit;
2253
0
            }
2254
0
            LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(secret,
2255
0
                                                 session->remote.crypt->
2256
0
                                                 secret_len, "D");
2257
2258
0
            if(!secret) {
2259
0
                LIBSSH2_FREE(session, iv);
2260
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
2261
0
                goto clean_exit;
2262
0
            }
2263
0
            if(session->remote.crypt->
2264
0
                init(session, session->remote.crypt, iv, &free_iv, secret,
2265
0
                     &free_secret, 0, &session->remote.crypt_abstract)) {
2266
0
                    LIBSSH2_FREE(session, iv);
2267
0
                    LIBSSH2_FREE(session, secret);
2268
0
                    ret = LIBSSH2_ERROR_KEX_FAILURE;
2269
0
                    goto clean_exit;
2270
0
                }
2271
2272
0
            if(free_iv) {
2273
0
                _libssh2_explicit_zero(iv, session->remote.crypt->iv_len);
2274
0
                LIBSSH2_FREE(session, iv);
2275
0
            }
2276
2277
0
            if(free_secret) {
2278
0
                _libssh2_explicit_zero(secret,
2279
0
                                       session->remote.crypt->secret_len);
2280
0
                LIBSSH2_FREE(session, secret);
2281
0
            }
2282
0
        }
2283
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
2284
0
                       "Server to Client IV and Key calculated"));
2285
2286
0
        if(session->local.mac->dtor) {
2287
0
            session->local.mac->dtor(session, &session->local.mac_abstract);
2288
0
        }
2289
2290
0
        if(session->local.mac->init) {
2291
0
            unsigned char *key = NULL;
2292
0
            int free_key = 0;
2293
2294
0
            LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(key,
2295
0
                                                 session->local.mac->
2296
0
                                                 key_len, "E");
2297
2298
0
            if(!key) {
2299
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
2300
0
                goto clean_exit;
2301
0
            }
2302
0
            session->local.mac->init(session, key, &free_key,
2303
0
                                     &session->local.mac_abstract);
2304
2305
0
            if(free_key) {
2306
0
                _libssh2_explicit_zero(key, session->local.mac->key_len);
2307
0
                LIBSSH2_FREE(session, key);
2308
0
            }
2309
0
        }
2310
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
2311
0
                       "Client to Server HMAC Key calculated"));
2312
2313
0
        if(session->remote.mac->dtor) {
2314
0
            session->remote.mac->dtor(session, &session->remote.mac_abstract);
2315
0
        }
2316
2317
0
        if(session->remote.mac->init) {
2318
0
            unsigned char *key = NULL;
2319
0
            int free_key = 0;
2320
2321
0
            LIBSSH2_KEX_METHOD_EC_SHA_VALUE_HASH(key,
2322
0
                                                 session->remote.mac->
2323
0
                                                 key_len, "F");
2324
2325
0
            if(!key) {
2326
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
2327
0
                goto clean_exit;
2328
0
            }
2329
0
            session->remote.mac->init(session, key, &free_key,
2330
0
                                      &session->remote.mac_abstract);
2331
2332
0
            if(free_key) {
2333
0
                _libssh2_explicit_zero(key, session->remote.mac->key_len);
2334
0
                LIBSSH2_FREE(session, key);
2335
0
            }
2336
0
        }
2337
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
2338
0
                       "Server to Client HMAC Key calculated"));
2339
2340
        /* Initialize compression for each direction */
2341
2342
        /* Cleanup any existing compression */
2343
0
        if(session->local.comp && session->local.comp->dtor) {
2344
0
            session->local.comp->dtor(session, 1,
2345
0
                                      &session->local.comp_abstract);
2346
0
        }
2347
2348
0
        if(session->local.comp && session->local.comp->init) {
2349
0
            if(session->local.comp->init(session, 1,
2350
0
                                         &session->local.comp_abstract)) {
2351
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
2352
0
                goto clean_exit;
2353
0
            }
2354
0
        }
2355
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
2356
0
                       "Client to Server compression initialized"));
2357
2358
0
        if(session->remote.comp && session->remote.comp->dtor) {
2359
0
            session->remote.comp->dtor(session, 0,
2360
0
                                       &session->remote.comp_abstract);
2361
0
        }
2362
2363
0
        if(session->remote.comp && session->remote.comp->init) {
2364
0
            if(session->remote.comp->init(session, 0,
2365
0
                                          &session->remote.comp_abstract)) {
2366
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
2367
0
                goto clean_exit;
2368
0
            }
2369
0
        }
2370
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
2371
0
                       "Server to Client compression initialized"));
2372
0
    }
2373
2374
156
clean_exit:
2375
156
    ecdh_exchange_state_cleanup(session, exchange_state);
2376
2377
156
    return ret;
2378
0
}
2379
2380
/* kex_method_ecdh_key_exchange
2381
 *
2382
 * Elliptic Curve Diffie Hellman Key Exchange
2383
 * supports SHA256/384/512 hashes based on negotiated ecdh method
2384
 *
2385
 */
2386
static int
2387
kex_method_ecdh_key_exchange
2388
(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
2389
233
{
2390
233
    int ret = 0;
2391
233
    int rc = 0;
2392
233
    unsigned char *s;
2393
233
    libssh2_curve_type type;
2394
2395
233
    if(key_state->state == libssh2_NB_state_idle) {
2396
2397
233
        key_state->public_key_oct = NULL;
2398
233
        key_state->state = libssh2_NB_state_created;
2399
233
    }
2400
2401
233
    if(key_state->state == libssh2_NB_state_created) {
2402
233
        rc = kex_session_ecdh_curve_type(session->kex->name, &type);
2403
2404
233
        if(rc) {
2405
0
            ret = _libssh2_error(session, -1,
2406
0
                                 "Unknown KEX nistp curve type");
2407
0
            goto ecdh_clean_exit;
2408
0
        }
2409
2410
233
        rc = _libssh2_ecdsa_create_key(session, &key_state->private_key,
2411
233
                                       &key_state->public_key_oct,
2412
233
                                       &key_state->public_key_oct_len, type);
2413
2414
233
        if(rc) {
2415
0
            ret = _libssh2_error(session, rc,
2416
0
                                 "Unable to create private key");
2417
0
            goto ecdh_clean_exit;
2418
0
        }
2419
2420
233
        key_state->request[0] = SSH2_MSG_KEX_ECDH_INIT;
2421
233
        s = key_state->request + 1;
2422
233
        _libssh2_store_str(&s, (const char *)key_state->public_key_oct,
2423
233
                           key_state->public_key_oct_len);
2424
233
        key_state->request_len = key_state->public_key_oct_len + 5;
2425
2426
233
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
2427
233
                       "Initiating ECDH SHA2 NISTP256"));
2428
2429
233
        key_state->state = libssh2_NB_state_sent;
2430
233
    }
2431
2432
233
    if(key_state->state == libssh2_NB_state_sent) {
2433
233
        rc = _libssh2_transport_send(session, key_state->request,
2434
233
                                     key_state->request_len, NULL, 0);
2435
233
        if(rc == LIBSSH2_ERROR_EAGAIN) {
2436
0
            return rc;
2437
0
        }
2438
233
        else if(rc) {
2439
0
            ret = _libssh2_error(session, rc,
2440
0
                                 "Unable to send ECDH_INIT");
2441
0
            goto ecdh_clean_exit;
2442
0
        }
2443
2444
233
        key_state->state = libssh2_NB_state_sent1;
2445
233
    }
2446
2447
233
    if(key_state->state == libssh2_NB_state_sent1) {
2448
233
        rc = _libssh2_packet_require(session, SSH2_MSG_KEX_ECDH_REPLY,
2449
233
                                     &key_state->data, &key_state->data_len,
2450
233
                                     0, NULL, 0, &key_state->req_state);
2451
233
        if(rc == LIBSSH2_ERROR_EAGAIN) {
2452
0
            return rc;
2453
0
        }
2454
233
        else if(rc) {
2455
74
            ret = _libssh2_error(session, rc,
2456
74
                                 "Timeout waiting for ECDH_REPLY reply");
2457
74
            goto ecdh_clean_exit;
2458
74
        }
2459
2460
159
        key_state->state = libssh2_NB_state_sent2;
2461
159
    }
2462
2463
159
    if(key_state->state == libssh2_NB_state_sent2) {
2464
2465
159
        rc = kex_session_ecdh_curve_type(session->kex->name, &type);
2466
2467
159
        if(rc) {
2468
0
            ret = _libssh2_error(session, -1,
2469
0
                                 "Unknown KEX nistp curve type");
2470
0
            goto ecdh_clean_exit;
2471
0
        }
2472
2473
159
        ret = ecdh_sha2_nistp(session, type, key_state->data,
2474
159
                              key_state->data_len,
2475
159
                              (unsigned char *)key_state->public_key_oct,
2476
159
                              key_state->public_key_oct_len,
2477
159
                              key_state->private_key,
2478
159
                              &key_state->exchange_state);
2479
2480
159
        if(ret == LIBSSH2_ERROR_EAGAIN) {
2481
0
            return ret;
2482
0
        }
2483
159
    }
2484
2485
233
ecdh_clean_exit:
2486
2487
233
    kex_method_ecdh_cleanup(session, key_state);
2488
2489
233
    return ret;
2490
159
}
2491
2492
#endif /* LIBSSH2_ECDSA */
2493
2494
2495
#if LIBSSH2_ED25519
2496
2497
static void
2498
curve25519_exchange_state_cleanup(LIBSSH2_SESSION * session,
2499
                                  kmdhgGPshakex_state_t *exchange_state)
2500
48
{
2501
48
    _libssh2_bn_free(exchange_state->k);
2502
48
    exchange_state->k = NULL;
2503
2504
48
    if(exchange_state->k_value) {
2505
6
        LIBSSH2_FREE(session, exchange_state->k_value);
2506
6
        exchange_state->k_value = NULL;
2507
6
    }
2508
2509
48
    exchange_state->state = libssh2_NB_state_idle;
2510
48
}
2511
2512
static void
2513
kex_method_curve25519_cleanup
2514
(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
2515
328
{
2516
328
    if(key_state->curve25519_public_key) {
2517
136
        _libssh2_explicit_zero(key_state->curve25519_public_key,
2518
136
                               LIBSSH2_ED25519_KEY_LEN);
2519
136
        LIBSSH2_FREE(session, key_state->curve25519_public_key);
2520
136
        key_state->curve25519_public_key = NULL;
2521
136
    }
2522
2523
328
    if(key_state->curve25519_private_key) {
2524
136
        _libssh2_explicit_zero(key_state->curve25519_private_key,
2525
136
                               LIBSSH2_ED25519_KEY_LEN);
2526
136
        LIBSSH2_FREE(session, key_state->curve25519_private_key);
2527
136
        key_state->curve25519_private_key = NULL;
2528
136
    }
2529
2530
328
    if(key_state->data) {
2531
50
        LIBSSH2_FREE(session, key_state->data);
2532
50
        key_state->data = NULL;
2533
50
    }
2534
2535
328
    key_state->state = libssh2_NB_state_idle;
2536
2537
328
    if(key_state->exchange_state.state != libssh2_NB_state_idle) {
2538
0
        curve25519_exchange_state_cleanup(session, &key_state->exchange_state);
2539
0
    }
2540
328
}
2541
2542
/* curve25519_sha256
2543
 * Elliptic Curve Key Exchange
2544
 */
2545
static int
2546
curve25519_sha256(LIBSSH2_SESSION *session, unsigned char *data,
2547
                  size_t data_len,
2548
                  unsigned char public_key[LIBSSH2_ED25519_KEY_LEN],
2549
                  unsigned char private_key[LIBSSH2_ED25519_KEY_LEN],
2550
                  kmdhgGPshakex_state_t *exchange_state)
2551
50
{
2552
50
    int ret = 0;
2553
50
    int rc;
2554
50
    int public_key_len = LIBSSH2_ED25519_KEY_LEN;
2555
2556
50
    if(data_len < 5) {
2557
2
        return _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
2558
2
                              "Data is too short");
2559
2
    }
2560
2561
48
    if(exchange_state->state == libssh2_NB_state_idle) {
2562
2563
        /* Setup initial values */
2564
48
        exchange_state->k = _libssh2_bn_init();
2565
2566
48
        exchange_state->state = libssh2_NB_state_created;
2567
48
    }
2568
2569
48
    if(exchange_state->state == libssh2_NB_state_created) {
2570
        /* parse INIT reply data */
2571
48
        unsigned char *server_public_key, *server_host_key;
2572
48
        size_t server_public_key_len, hostkey_len;
2573
48
        struct string_buf buf;
2574
2575
48
        if(data_len < 5) {
2576
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
2577
0
                                 "Unexpected curve25519 key length 1");
2578
0
            goto clean_exit;
2579
0
        }
2580
2581
48
        buf.data = data;
2582
48
        buf.len = data_len;
2583
48
        buf.dataptr = buf.data;
2584
48
        buf.dataptr++; /* advance past packet type */
2585
2586
48
        if(_libssh2_get_string(&buf, &server_host_key, &hostkey_len)) {
2587
2
            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
2588
2
                                 "Unexpected curve25519 key length 2");
2589
2
            goto clean_exit;
2590
2
        }
2591
2592
46
        session->server_hostkey_len = (uint32_t)hostkey_len;
2593
46
        session->server_hostkey = LIBSSH2_ALLOC(session,
2594
46
                                                session->server_hostkey_len);
2595
46
        if(!session->server_hostkey) {
2596
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2597
0
                                 "Unable to allocate memory for a copy "
2598
0
                                 "of the host curve25519 key");
2599
0
            goto clean_exit;
2600
0
        }
2601
2602
46
        memcpy(session->server_hostkey, server_host_key,
2603
46
               session->server_hostkey_len);
2604
2605
#if LIBSSH2_MD5
2606
        {
2607
            libssh2_md5_ctx fingerprint_ctx;
2608
2609
            if(libssh2_md5_init(&fingerprint_ctx) &&
2610
               libssh2_md5_update(fingerprint_ctx, session->server_hostkey,
2611
                                  session->server_hostkey_len) &&
2612
               libssh2_md5_final(fingerprint_ctx,
2613
                                 session->server_hostkey_md5)) {
2614
                session->server_hostkey_md5_valid = TRUE;
2615
            }
2616
            else {
2617
                session->server_hostkey_md5_valid = FALSE;
2618
            }
2619
        }
2620
#ifdef LIBSSH2DEBUG
2621
        {
2622
            char fingerprint[50], *fprint = fingerprint;
2623
            int i;
2624
            for(i = 0; i < 16; i++, fprint += 3) {
2625
                snprintf(fprint, 4, "%02x:", session->server_hostkey_md5[i]);
2626
            }
2627
            *(--fprint) = '\0';
2628
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
2629
                           "Server's MD5 Fingerprint: %s", fingerprint));
2630
        }
2631
#endif /* LIBSSH2DEBUG */
2632
#endif /* ! LIBSSH2_MD5 */
2633
2634
46
        {
2635
46
            libssh2_sha1_ctx fingerprint_ctx;
2636
2637
46
            if(libssh2_sha1_init(&fingerprint_ctx) &&
2638
46
               libssh2_sha1_update(fingerprint_ctx, session->server_hostkey,
2639
46
                                   session->server_hostkey_len) &&
2640
46
               libssh2_sha1_final(fingerprint_ctx,
2641
46
                                  session->server_hostkey_sha1)) {
2642
46
                session->server_hostkey_sha1_valid = TRUE;
2643
46
            }
2644
0
            else {
2645
0
                session->server_hostkey_sha1_valid = FALSE;
2646
0
            }
2647
46
        }
2648
46
#ifdef LIBSSH2DEBUG
2649
46
        {
2650
46
            char fingerprint[64], *fprint = fingerprint;
2651
46
            int i;
2652
966
            for(i = 0; i < 20; i++, fprint += 3) {
2653
920
                snprintf(fprint, 4, "%02x:", session->server_hostkey_sha1[i]);
2654
920
            }
2655
46
            *(--fprint) = '\0';
2656
46
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
2657
46
                           "Server's SHA1 Fingerprint: %s", fingerprint));
2658
46
        }
2659
46
#endif /* LIBSSH2DEBUG */
2660
2661
        /* SHA256 */
2662
46
        {
2663
46
            libssh2_sha256_ctx fingerprint_ctx;
2664
2665
46
            if(libssh2_sha256_init(&fingerprint_ctx) &&
2666
46
               libssh2_sha256_update(fingerprint_ctx, session->server_hostkey,
2667
46
                                     session->server_hostkey_len) &&
2668
46
               libssh2_sha256_final(fingerprint_ctx,
2669
46
                                    session->server_hostkey_sha256)) {
2670
46
                session->server_hostkey_sha256_valid = TRUE;
2671
46
            }
2672
0
            else {
2673
0
                session->server_hostkey_sha256_valid = FALSE;
2674
0
            }
2675
46
        }
2676
46
#ifdef LIBSSH2DEBUG
2677
46
        {
2678
46
            char *base64Fingerprint = NULL;
2679
46
            _libssh2_base64_encode(session,
2680
46
                                   (const char *)
2681
46
                                   session->server_hostkey_sha256,
2682
46
                                   SHA256_DIGEST_LENGTH, &base64Fingerprint);
2683
46
            if(base64Fingerprint) {
2684
46
                _libssh2_debug((session, LIBSSH2_TRACE_KEX,
2685
46
                               "Server's SHA256 Fingerprint: %s",
2686
46
                               base64Fingerprint));
2687
46
                LIBSSH2_FREE(session, base64Fingerprint);
2688
46
            }
2689
46
        }
2690
46
#endif /* LIBSSH2DEBUG */
2691
2692
46
        if(session->hostkey->init(session, session->server_hostkey,
2693
46
                                  session->server_hostkey_len,
2694
46
                                  &session->server_hostkey_abstract)) {
2695
36
            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
2696
36
                                 "Unable to initialize hostkey importer "
2697
36
                                 "curve25519");
2698
36
            goto clean_exit;
2699
36
        }
2700
2701
        /* server public key Q_S */
2702
10
        if(_libssh2_get_string(&buf, &server_public_key,
2703
10
                               &server_public_key_len)) {
2704
1
            ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
2705
1
                                 "Unexpected curve25519 key length");
2706
1
            goto clean_exit;
2707
1
        }
2708
2709
9
        if(server_public_key_len != LIBSSH2_ED25519_KEY_LEN) {
2710
1
            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
2711
1
                                 "Unexpected curve25519 server "
2712
1
                                 "public key length");
2713
1
            goto clean_exit;
2714
1
        }
2715
2716
        /* server signature */
2717
8
        if(_libssh2_get_string(&buf, &exchange_state->h_sig,
2718
8
           &(exchange_state->h_sig_len))) {
2719
1
            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_INIT,
2720
1
                                 "Unexpected curve25519 server sig length");
2721
1
            goto clean_exit;
2722
1
        }
2723
2724
        /* Compute the shared secret K */
2725
7
        rc = _libssh2_curve25519_gen_k(&exchange_state->k, private_key,
2726
7
                                       server_public_key);
2727
7
        if(rc) {
2728
1
            ret = _libssh2_error(session, LIBSSH2_ERROR_KEX_FAILURE,
2729
1
                                 "Unable to create curve25519 shared secret");
2730
1
            goto clean_exit;
2731
1
        }
2732
2733
6
        exchange_state->k_value_len = _libssh2_bn_bytes(exchange_state->k) + 5;
2734
6
        if(_libssh2_bn_bits(exchange_state->k) % 8) {
2735
            /* don't need leading 00 */
2736
1
            exchange_state->k_value_len--;
2737
1
        }
2738
6
        exchange_state->k_value =
2739
6
        LIBSSH2_ALLOC(session, exchange_state->k_value_len);
2740
6
        if(!exchange_state->k_value) {
2741
0
            ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2742
0
                                 "Unable to allocate buffer for K");
2743
0
            goto clean_exit;
2744
0
        }
2745
6
        _libssh2_htonu32(exchange_state->k_value,
2746
6
                         (uint32_t)(exchange_state->k_value_len - 4));
2747
6
        if(_libssh2_bn_bits(exchange_state->k) % 8) {
2748
1
            if(_libssh2_bn_to_bin(exchange_state->k,
2749
1
                                  exchange_state->k_value + 4)) {
2750
0
                ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
2751
0
                                     "Can't write exchange_state->e");
2752
0
                goto clean_exit;
2753
0
            }
2754
1
        }
2755
5
        else {
2756
5
            exchange_state->k_value[4] = 0;
2757
5
            if(_libssh2_bn_to_bin(exchange_state->k,
2758
5
                                  exchange_state->k_value + 5)) {
2759
0
                ret = _libssh2_error(session, LIBSSH2_ERROR_OUT_OF_BOUNDARY,
2760
0
                                     "Can't write exchange_state->e");
2761
0
                goto clean_exit;
2762
0
            }
2763
5
        }
2764
2765
        /*/ verify hash */
2766
6
        LIBSSH2_KEX_METHOD_EC_SHA_HASH_CREATE_VERIFY(256);
2767
2768
6
        if(rc) {
2769
6
            ret = _libssh2_error(session, LIBSSH2_ERROR_HOSTKEY_SIGN,
2770
6
                                 "Unable to verify hostkey signature "
2771
6
                                 "curve25519");
2772
6
            goto clean_exit;
2773
6
        }
2774
2775
0
        exchange_state->c = SSH_MSG_NEWKEYS;
2776
0
        exchange_state->state = libssh2_NB_state_sent;
2777
0
    }
2778
2779
0
    if(exchange_state->state == libssh2_NB_state_sent) {
2780
0
        rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0);
2781
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
2782
0
            return rc;
2783
0
        }
2784
0
        else if(rc) {
2785
0
            ret = _libssh2_error(session, rc,
2786
0
                                 "Unable to send NEWKEYS message curve25519");
2787
0
            goto clean_exit;
2788
0
        }
2789
2790
0
        exchange_state->state = libssh2_NB_state_sent2;
2791
0
    }
2792
2793
0
    if(exchange_state->state == libssh2_NB_state_sent2) {
2794
0
        rc = _libssh2_packet_require(session, SSH_MSG_NEWKEYS,
2795
0
                                     &exchange_state->tmp,
2796
0
                                     &exchange_state->tmp_len, 0, NULL, 0,
2797
0
                                     &exchange_state->req_state);
2798
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
2799
0
            return rc;
2800
0
        }
2801
0
        else if(rc) {
2802
0
            ret = _libssh2_error(session, rc,
2803
0
                                 "Timed out waiting for NEWKEYS curve25519");
2804
0
            goto clean_exit;
2805
0
        }
2806
2807
        /* The first key exchange has been performed,
2808
           switch to active crypt/comp/mac mode */
2809
0
        session->state |= LIBSSH2_STATE_NEWKEYS;
2810
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
2811
0
                       "Received NEWKEYS message curve25519"));
2812
2813
        /* This will actually end up being just packet_type(1)
2814
           for this packet type anyway */
2815
0
        LIBSSH2_FREE(session, exchange_state->tmp);
2816
2817
0
        if(!session->session_id) {
2818
2819
0
            size_t digest_length = SHA256_DIGEST_LENGTH;
2820
0
            session->session_id = LIBSSH2_ALLOC(session, digest_length);
2821
0
            if(!session->session_id) {
2822
0
                ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
2823
0
                                     "Unable to allocate buffer for "
2824
0
                                     "SHA digest");
2825
0
                goto clean_exit;
2826
0
            }
2827
0
            memcpy(session->session_id, exchange_state->h_sig_comp,
2828
0
                   digest_length);
2829
0
            session->session_id_len = (uint32_t)digest_length;
2830
0
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
2831
0
                           "session_id calculated"));
2832
0
        }
2833
2834
        /* Cleanup any existing cipher */
2835
0
        if(session->local.crypt->dtor) {
2836
0
            session->local.crypt->dtor(session,
2837
0
                                       &session->local.crypt_abstract);
2838
0
        }
2839
2840
        /* Calculate IV/Secret/Key for each direction */
2841
0
        if(session->local.crypt->init) {
2842
0
            unsigned char *iv = NULL, *secret = NULL;
2843
0
            int free_iv = 0, free_secret = 0;
2844
2845
0
            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv,
2846
0
                                              session->local.crypt->
2847
0
                                              iv_len, "A");
2848
0
            if(!iv) {
2849
0
                ret = -1;
2850
0
                goto clean_exit;
2851
0
            }
2852
2853
0
            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret,
2854
0
                                              session->local.crypt->
2855
0
                                              secret_len, "C");
2856
2857
0
            if(!secret) {
2858
0
                LIBSSH2_FREE(session, iv);
2859
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
2860
0
                goto clean_exit;
2861
0
            }
2862
0
            if(session->local.crypt->
2863
0
                init(session, session->local.crypt, iv, &free_iv, secret,
2864
0
                     &free_secret, 1, &session->local.crypt_abstract)) {
2865
0
                    LIBSSH2_FREE(session, iv);
2866
0
                    LIBSSH2_FREE(session, secret);
2867
0
                    ret = LIBSSH2_ERROR_KEX_FAILURE;
2868
0
                    goto clean_exit;
2869
0
                }
2870
2871
0
            if(free_iv) {
2872
0
                _libssh2_explicit_zero(iv, session->local.crypt->iv_len);
2873
0
                LIBSSH2_FREE(session, iv);
2874
0
            }
2875
2876
0
            if(free_secret) {
2877
0
                _libssh2_explicit_zero(secret,
2878
0
                                       session->local.crypt->secret_len);
2879
0
                LIBSSH2_FREE(session, secret);
2880
0
            }
2881
0
        }
2882
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
2883
0
                       "Client to Server IV and Key calculated"));
2884
2885
0
        if(session->remote.crypt->dtor) {
2886
            /* Cleanup any existing cipher */
2887
0
            session->remote.crypt->dtor(session,
2888
0
                                        &session->remote.crypt_abstract);
2889
0
        }
2890
2891
0
        if(session->remote.crypt->init) {
2892
0
            unsigned char *iv = NULL, *secret = NULL;
2893
0
            int free_iv = 0, free_secret = 0;
2894
2895
0
            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, iv,
2896
0
                                              session->remote.crypt->
2897
0
                                              iv_len, "B");
2898
2899
0
            if(!iv) {
2900
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
2901
0
                goto clean_exit;
2902
0
            }
2903
0
            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, secret,
2904
0
                                              session->remote.crypt->
2905
0
                                              secret_len, "D");
2906
2907
0
            if(!secret) {
2908
0
                LIBSSH2_FREE(session, iv);
2909
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
2910
0
                goto clean_exit;
2911
0
            }
2912
0
            if(session->remote.crypt->
2913
0
                init(session, session->remote.crypt, iv, &free_iv, secret,
2914
0
                     &free_secret, 0, &session->remote.crypt_abstract)) {
2915
0
                    LIBSSH2_FREE(session, iv);
2916
0
                    LIBSSH2_FREE(session, secret);
2917
0
                    ret = LIBSSH2_ERROR_KEX_FAILURE;
2918
0
                    goto clean_exit;
2919
0
                }
2920
2921
0
            if(free_iv) {
2922
0
                _libssh2_explicit_zero(iv, session->remote.crypt->iv_len);
2923
0
                LIBSSH2_FREE(session, iv);
2924
0
            }
2925
2926
0
            if(free_secret) {
2927
0
                _libssh2_explicit_zero(secret,
2928
0
                                       session->remote.crypt->secret_len);
2929
0
                LIBSSH2_FREE(session, secret);
2930
0
            }
2931
0
        }
2932
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
2933
0
                       "Server to Client IV and Key calculated"));
2934
2935
0
        if(session->local.mac->dtor) {
2936
0
            session->local.mac->dtor(session, &session->local.mac_abstract);
2937
0
        }
2938
2939
0
        if(session->local.mac->init) {
2940
0
            unsigned char *key = NULL;
2941
0
            int free_key = 0;
2942
2943
0
            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key,
2944
0
                                              session->local.mac->
2945
0
                                              key_len, "E");
2946
2947
0
            if(!key) {
2948
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
2949
0
                goto clean_exit;
2950
0
            }
2951
0
            session->local.mac->init(session, key, &free_key,
2952
0
                                     &session->local.mac_abstract);
2953
2954
0
            if(free_key) {
2955
0
                _libssh2_explicit_zero(key, session->local.mac->key_len);
2956
0
                LIBSSH2_FREE(session, key);
2957
0
            }
2958
0
        }
2959
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
2960
0
                       "Client to Server HMAC Key calculated"));
2961
2962
0
        if(session->remote.mac->dtor) {
2963
0
            session->remote.mac->dtor(session, &session->remote.mac_abstract);
2964
0
        }
2965
2966
0
        if(session->remote.mac->init) {
2967
0
            unsigned char *key = NULL;
2968
0
            int free_key = 0;
2969
2970
0
            LIBSSH2_KEX_METHOD_SHA_VALUE_HASH(256, key,
2971
0
                                              session->remote.mac->
2972
0
                                              key_len, "F");
2973
2974
0
            if(!key) {
2975
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
2976
0
                goto clean_exit;
2977
0
            }
2978
0
            session->remote.mac->init(session, key, &free_key,
2979
0
                                      &session->remote.mac_abstract);
2980
2981
0
            if(free_key) {
2982
0
                _libssh2_explicit_zero(key, session->remote.mac->key_len);
2983
0
                LIBSSH2_FREE(session, key);
2984
0
            }
2985
0
        }
2986
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
2987
0
                       "Server to Client HMAC Key calculated"));
2988
2989
        /* Initialize compression for each direction */
2990
2991
        /* Cleanup any existing compression */
2992
0
        if(session->local.comp && session->local.comp->dtor) {
2993
0
            session->local.comp->dtor(session, 1,
2994
0
                                      &session->local.comp_abstract);
2995
0
        }
2996
2997
0
        if(session->local.comp && session->local.comp->init) {
2998
0
            if(session->local.comp->init(session, 1,
2999
0
                                         &session->local.comp_abstract)) {
3000
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
3001
0
                goto clean_exit;
3002
0
            }
3003
0
        }
3004
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
3005
0
                       "Client to Server compression initialized"));
3006
3007
0
        if(session->remote.comp && session->remote.comp->dtor) {
3008
0
            session->remote.comp->dtor(session, 0,
3009
0
                                       &session->remote.comp_abstract);
3010
0
        }
3011
3012
0
        if(session->remote.comp && session->remote.comp->init) {
3013
0
            if(session->remote.comp->init(session, 0,
3014
0
                                          &session->remote.comp_abstract)) {
3015
0
                ret = LIBSSH2_ERROR_KEX_FAILURE;
3016
0
                goto clean_exit;
3017
0
            }
3018
0
        }
3019
0
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
3020
0
                       "Server to Client compression initialized"));
3021
0
    }
3022
3023
48
clean_exit:
3024
48
    curve25519_exchange_state_cleanup(session, exchange_state);
3025
3026
48
    return ret;
3027
0
}
3028
3029
/* kex_method_curve25519_key_exchange
3030
 *
3031
 * Elliptic Curve X25519 Key Exchange with SHA256 hash
3032
 *
3033
 */
3034
static int
3035
kex_method_curve25519_key_exchange
3036
(LIBSSH2_SESSION * session, key_exchange_state_low_t * key_state)
3037
136
{
3038
136
    int ret = 0;
3039
136
    int rc = 0;
3040
3041
136
    if(key_state->state == libssh2_NB_state_idle) {
3042
3043
136
        key_state->public_key_oct = NULL;
3044
136
        key_state->state = libssh2_NB_state_created;
3045
136
    }
3046
3047
136
    if(key_state->state == libssh2_NB_state_created) {
3048
136
        unsigned char *s = NULL;
3049
3050
136
        rc = strcmp(session->kex->name, "curve25519-sha256@libssh.org");
3051
136
        if(rc)
3052
134
            rc = strcmp(session->kex->name, "curve25519-sha256");
3053
3054
136
        if(rc) {
3055
0
            ret = _libssh2_error(session, -1,
3056
0
                                 "Unknown KEX curve25519 curve type");
3057
0
            goto clean_exit;
3058
0
        }
3059
3060
136
        rc = _libssh2_curve25519_new(session,
3061
136
                                     &key_state->curve25519_public_key,
3062
136
                                     &key_state->curve25519_private_key);
3063
3064
136
        if(rc) {
3065
0
            ret = _libssh2_error(session, rc,
3066
0
                                 "Unable to create private key");
3067
0
            goto clean_exit;
3068
0
        }
3069
3070
136
        key_state->request[0] = SSH2_MSG_KEX_ECDH_INIT;
3071
136
        s = key_state->request + 1;
3072
136
        _libssh2_store_str(&s, (const char *)key_state->curve25519_public_key,
3073
136
                           LIBSSH2_ED25519_KEY_LEN);
3074
136
        key_state->request_len = LIBSSH2_ED25519_KEY_LEN + 5;
3075
3076
136
        _libssh2_debug((session, LIBSSH2_TRACE_KEX,
3077
136
                       "Initiating curve25519 SHA2"));
3078
3079
136
        key_state->state = libssh2_NB_state_sent;
3080
136
    }
3081
3082
136
    if(key_state->state == libssh2_NB_state_sent) {
3083
136
        rc = _libssh2_transport_send(session, key_state->request,
3084
136
                                     key_state->request_len, NULL, 0);
3085
136
        if(rc == LIBSSH2_ERROR_EAGAIN) {
3086
0
            return rc;
3087
0
        }
3088
136
        else if(rc) {
3089
0
            ret = _libssh2_error(session, rc,
3090
0
                                 "Unable to send ECDH_INIT");
3091
0
            goto clean_exit;
3092
0
        }
3093
3094
136
        key_state->state = libssh2_NB_state_sent1;
3095
136
    }
3096
3097
136
    if(key_state->state == libssh2_NB_state_sent1) {
3098
136
        rc = _libssh2_packet_require(session, SSH2_MSG_KEX_ECDH_REPLY,
3099
136
                                     &key_state->data, &key_state->data_len,
3100
136
                                     0, NULL, 0, &key_state->req_state);
3101
136
        if(rc == LIBSSH2_ERROR_EAGAIN) {
3102
0
            return rc;
3103
0
        }
3104
136
        else if(rc) {
3105
86
            ret = _libssh2_error(session, rc,
3106
86
                                 "Timeout waiting for ECDH_REPLY reply");
3107
86
            goto clean_exit;
3108
86
        }
3109
3110
50
        key_state->state = libssh2_NB_state_sent2;
3111
50
    }
3112
3113
50
    if(key_state->state == libssh2_NB_state_sent2) {
3114
3115
50
        ret = curve25519_sha256(session, key_state->data, key_state->data_len,
3116
50
                                key_state->curve25519_public_key,
3117
50
                                key_state->curve25519_private_key,
3118
50
                                &key_state->exchange_state);
3119
3120
50
        if(ret == LIBSSH2_ERROR_EAGAIN) {
3121
0
            return ret;
3122
0
        }
3123
50
    }
3124
3125
136
clean_exit:
3126
3127
136
    kex_method_curve25519_cleanup(session, key_state);
3128
3129
136
    return ret;
3130
50
}
3131
3132
3133
#endif /* LIBSSH2_ED25519 */
3134
3135
3136
2.20k
#define LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY     0x0001
3137
2.20k
#define LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY    0x0002
3138
3139
static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group1_sha1 = {
3140
    "diffie-hellman-group1-sha1",
3141
    kex_method_diffie_hellman_group1_sha1_key_exchange,
3142
    kex_diffie_hellman_cleanup,
3143
    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
3144
};
3145
3146
static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group14_sha1 = {
3147
    "diffie-hellman-group14-sha1",
3148
    kex_method_diffie_hellman_group14_sha1_key_exchange,
3149
    kex_diffie_hellman_cleanup,
3150
    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
3151
};
3152
3153
static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group14_sha256 = {
3154
    "diffie-hellman-group14-sha256",
3155
    kex_method_diffie_hellman_group14_sha256_key_exchange,
3156
    kex_diffie_hellman_cleanup,
3157
    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
3158
};
3159
3160
static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group16_sha512 = {
3161
    "diffie-hellman-group16-sha512",
3162
    kex_method_diffie_hellman_group16_sha512_key_exchange,
3163
    kex_diffie_hellman_cleanup,
3164
    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
3165
};
3166
3167
static const LIBSSH2_KEX_METHOD kex_method_diffie_helman_group18_sha512 = {
3168
    "diffie-hellman-group18-sha512",
3169
    kex_method_diffie_hellman_group18_sha512_key_exchange,
3170
    kex_diffie_hellman_cleanup,
3171
    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
3172
};
3173
3174
static const LIBSSH2_KEX_METHOD
3175
kex_method_diffie_helman_group_exchange_sha1 = {
3176
    "diffie-hellman-group-exchange-sha1",
3177
    kex_method_diffie_hellman_group_exchange_sha1_key_exchange,
3178
    kex_diffie_hellman_cleanup,
3179
    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
3180
};
3181
3182
static const LIBSSH2_KEX_METHOD
3183
kex_method_diffie_helman_group_exchange_sha256 = {
3184
    "diffie-hellman-group-exchange-sha256",
3185
    kex_method_diffie_hellman_group_exchange_sha256_key_exchange,
3186
    kex_diffie_hellman_cleanup,
3187
    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
3188
};
3189
3190
#if LIBSSH2_ECDSA
3191
static const LIBSSH2_KEX_METHOD
3192
kex_method_ecdh_sha2_nistp256 = {
3193
    "ecdh-sha2-nistp256",
3194
    kex_method_ecdh_key_exchange,
3195
    kex_method_ecdh_cleanup,
3196
    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
3197
};
3198
3199
static const LIBSSH2_KEX_METHOD
3200
kex_method_ecdh_sha2_nistp384 = {
3201
    "ecdh-sha2-nistp384",
3202
    kex_method_ecdh_key_exchange,
3203
    kex_method_ecdh_cleanup,
3204
    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
3205
};
3206
3207
static const LIBSSH2_KEX_METHOD
3208
kex_method_ecdh_sha2_nistp521 = {
3209
    "ecdh-sha2-nistp521",
3210
    kex_method_ecdh_key_exchange,
3211
    kex_method_ecdh_cleanup,
3212
    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
3213
};
3214
#endif
3215
3216
#if LIBSSH2_ED25519
3217
static const LIBSSH2_KEX_METHOD
3218
kex_method_ssh_curve25519_sha256_libssh = {
3219
    "curve25519-sha256@libssh.org",
3220
    kex_method_curve25519_key_exchange,
3221
    kex_method_curve25519_cleanup,
3222
    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
3223
};
3224
static const LIBSSH2_KEX_METHOD
3225
kex_method_ssh_curve25519_sha256 = {
3226
    "curve25519-sha256",
3227
    kex_method_curve25519_key_exchange,
3228
    kex_method_curve25519_cleanup,
3229
    LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY,
3230
};
3231
#endif
3232
3233
/* this kex method signals that client can receive extensions
3234
 * as described in https://datatracker.ietf.org/doc/html/rfc8308
3235
*/
3236
3237
static const LIBSSH2_KEX_METHOD
3238
kex_method_extension_negotiation = {
3239
    "ext-info-c",
3240
    NULL,
3241
    NULL,
3242
    0,
3243
};
3244
3245
static const LIBSSH2_KEX_METHOD
3246
kex_method_strict_client_extension = {
3247
    "kex-strict-c-v00@openssh.com",
3248
    NULL,
3249
    NULL,
3250
    0,
3251
};
3252
3253
static const LIBSSH2_KEX_METHOD *libssh2_kex_methods[] = {
3254
#if LIBSSH2_ED25519
3255
    &kex_method_ssh_curve25519_sha256,
3256
    &kex_method_ssh_curve25519_sha256_libssh,
3257
#endif
3258
#if LIBSSH2_ECDSA
3259
    &kex_method_ecdh_sha2_nistp256,
3260
    &kex_method_ecdh_sha2_nistp384,
3261
    &kex_method_ecdh_sha2_nistp521,
3262
#endif
3263
    &kex_method_diffie_helman_group_exchange_sha256,
3264
    &kex_method_diffie_helman_group16_sha512,
3265
    &kex_method_diffie_helman_group18_sha512,
3266
    &kex_method_diffie_helman_group14_sha256,
3267
    &kex_method_diffie_helman_group14_sha1,
3268
    &kex_method_diffie_helman_group1_sha1,
3269
    &kex_method_diffie_helman_group_exchange_sha1,
3270
    &kex_method_extension_negotiation,
3271
    &kex_method_strict_client_extension,
3272
    NULL
3273
};
3274
3275
typedef struct _LIBSSH2_COMMON_METHOD
3276
{
3277
    const char *name;
3278
} LIBSSH2_COMMON_METHOD;
3279
3280
/* kex_method_strlen
3281
 *
3282
 * Calculate the length of a particular method list's resulting string
3283
 * Includes SUM(strlen() of each individual method plus 1 (for coma)) - 1
3284
 * (because the last coma isn't used)
3285
 * Another sign of bad coding practices gone mad.  Pretend you don't see this.
3286
 */
3287
static size_t
3288
kex_method_strlen(const LIBSSH2_COMMON_METHOD ** method)
3289
60.6k
{
3290
60.6k
    size_t len = 0;
3291
3292
60.6k
    if(!method || !*method) {
3293
12.1k
        return 0;
3294
12.1k
    }
3295
3296
436k
    while(*method && (*method)->name) {
3297
388k
        len += strlen((*method)->name) + 1;
3298
388k
        method++;
3299
388k
    }
3300
3301
48.5k
    return len - 1;
3302
60.6k
}
3303
3304
3305
3306
/* kex_method_list
3307
 * Generate formatted preference list in buf
3308
 */
3309
static uint32_t
3310
kex_method_list(unsigned char *buf, uint32_t list_strlen,
3311
                const LIBSSH2_COMMON_METHOD ** method)
3312
60.6k
{
3313
60.6k
    _libssh2_htonu32(buf, list_strlen);
3314
60.6k
    buf += 4;
3315
3316
60.6k
    if(!method || !*method) {
3317
12.1k
        return 4;
3318
12.1k
    }
3319
3320
436k
    while(*method && (*method)->name) {
3321
388k
        uint32_t mlen = (uint32_t)strlen((*method)->name);
3322
388k
        memcpy(buf, (*method)->name, mlen);
3323
388k
        buf += mlen;
3324
388k
        *(buf++) = ',';
3325
388k
        method++;
3326
388k
    }
3327
3328
48.5k
    return list_strlen + 4;
3329
60.6k
}
3330
3331
3332
3333
#define LIBSSH2_METHOD_PREFS_LEN(prefvar, defaultvar)           \
3334
60.6k
    (uint32_t)((prefvar) ? strlen(prefvar) :                    \
3335
60.6k
        kex_method_strlen((const LIBSSH2_COMMON_METHOD**)(defaultvar)))
3336
3337
#define LIBSSH2_METHOD_PREFS_STR(buf, prefvarlen, prefvar, defaultvar)        \
3338
60.6k
    do {                                                                      \
3339
60.6k
        if(prefvar) {                                                         \
3340
0
            _libssh2_htonu32((buf), (prefvarlen));                            \
3341
0
            buf += 4;                                                         \
3342
0
            memcpy((buf), (prefvar), (prefvarlen));                           \
3343
0
            buf += (prefvarlen);                                              \
3344
0
        }                                                                     \
3345
60.6k
        else {                                                                \
3346
60.6k
            buf += kex_method_list((buf), (prefvarlen),                       \
3347
60.6k
                                (const LIBSSH2_COMMON_METHOD**)(defaultvar)); \
3348
60.6k
        }                                                                     \
3349
60.6k
    } while(0)
3350
3351
/* kexinit
3352
 * Send SSH_MSG_KEXINIT packet
3353
 */
3354
static int kexinit(LIBSSH2_SESSION * session)
3355
6.06k
{
3356
    /* 62 = packet_type(1) + cookie(16) + first_packet_follows(1) +
3357
       reserved(4) + length longs(40) */
3358
6.06k
    size_t data_len = 62;
3359
6.06k
    unsigned char *data, *s;
3360
6.06k
    int rc;
3361
3362
6.06k
    if(session->kexinit_state == libssh2_NB_state_idle) {
3363
6.06k
        uint32_t kex_len, hostkey_len;
3364
6.06k
        uint32_t crypt_cs_len, crypt_sc_len;
3365
6.06k
        uint32_t comp_cs_len, comp_sc_len;
3366
6.06k
        uint32_t mac_cs_len, mac_sc_len;
3367
6.06k
        uint32_t lang_cs_len, lang_sc_len;
3368
3369
6.06k
        kex_len =
3370
6.06k
            LIBSSH2_METHOD_PREFS_LEN(session->kex_prefs, libssh2_kex_methods);
3371
6.06k
        hostkey_len =
3372
6.06k
            LIBSSH2_METHOD_PREFS_LEN(session->hostkey_prefs,
3373
6.06k
                                     libssh2_hostkey_methods());
3374
6.06k
        crypt_cs_len =
3375
6.06k
            LIBSSH2_METHOD_PREFS_LEN(session->local.crypt_prefs,
3376
6.06k
                                     libssh2_crypt_methods());
3377
6.06k
        crypt_sc_len =
3378
6.06k
            LIBSSH2_METHOD_PREFS_LEN(session->remote.crypt_prefs,
3379
6.06k
                                     libssh2_crypt_methods());
3380
6.06k
        mac_cs_len =
3381
6.06k
            LIBSSH2_METHOD_PREFS_LEN(session->local.mac_prefs,
3382
6.06k
                                     _libssh2_mac_methods());
3383
6.06k
        mac_sc_len =
3384
6.06k
            LIBSSH2_METHOD_PREFS_LEN(session->remote.mac_prefs,
3385
6.06k
                                     _libssh2_mac_methods());
3386
6.06k
        comp_cs_len =
3387
6.06k
            LIBSSH2_METHOD_PREFS_LEN(session->local.comp_prefs,
3388
6.06k
                                     _libssh2_comp_methods(session));
3389
6.06k
        comp_sc_len =
3390
6.06k
            LIBSSH2_METHOD_PREFS_LEN(session->remote.comp_prefs,
3391
6.06k
                                     _libssh2_comp_methods(session));
3392
6.06k
        lang_cs_len =
3393
6.06k
            LIBSSH2_METHOD_PREFS_LEN(session->local.lang_prefs, NULL);
3394
6.06k
        lang_sc_len =
3395
6.06k
            LIBSSH2_METHOD_PREFS_LEN(session->remote.lang_prefs, NULL);
3396
3397
6.06k
        data_len += kex_len + hostkey_len + crypt_cs_len + crypt_sc_len +
3398
6.06k
                    comp_cs_len + comp_sc_len + mac_cs_len + mac_sc_len +
3399
6.06k
                    lang_cs_len + lang_sc_len;
3400
3401
6.06k
        s = data = LIBSSH2_ALLOC(session, data_len);
3402
6.06k
        if(!data) {
3403
0
            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
3404
0
                                  "Unable to allocate memory");
3405
0
        }
3406
3407
6.06k
        *(s++) = SSH_MSG_KEXINIT;
3408
3409
6.06k
        if(_libssh2_random(s, 16)) {
3410
0
            return _libssh2_error(session, LIBSSH2_ERROR_RANDGEN,
3411
0
                                  "Unable to get random bytes "
3412
0
                                  "for KEXINIT cookie");
3413
0
        }
3414
6.06k
        s += 16;
3415
3416
        /* Ennumerating through these lists twice is probably (certainly?)
3417
           inefficient from a CPU standpoint, but it saves multiple
3418
           malloc/realloc calls */
3419
6.06k
        LIBSSH2_METHOD_PREFS_STR(s, kex_len, session->kex_prefs,
3420
6.06k
                                 libssh2_kex_methods);
3421
6.06k
        LIBSSH2_METHOD_PREFS_STR(s, hostkey_len, session->hostkey_prefs,
3422
6.06k
                                 libssh2_hostkey_methods());
3423
6.06k
        LIBSSH2_METHOD_PREFS_STR(s, crypt_cs_len, session->local.crypt_prefs,
3424
6.06k
                                 libssh2_crypt_methods());
3425
6.06k
        LIBSSH2_METHOD_PREFS_STR(s, crypt_sc_len, session->remote.crypt_prefs,
3426
6.06k
                                 libssh2_crypt_methods());
3427
6.06k
        LIBSSH2_METHOD_PREFS_STR(s, mac_cs_len, session->local.mac_prefs,
3428
6.06k
                                 _libssh2_mac_methods());
3429
6.06k
        LIBSSH2_METHOD_PREFS_STR(s, mac_sc_len, session->remote.mac_prefs,
3430
6.06k
                                 _libssh2_mac_methods());
3431
6.06k
        LIBSSH2_METHOD_PREFS_STR(s, comp_cs_len, session->local.comp_prefs,
3432
6.06k
                                 _libssh2_comp_methods(session));
3433
6.06k
        LIBSSH2_METHOD_PREFS_STR(s, comp_sc_len, session->remote.comp_prefs,
3434
6.06k
                                 _libssh2_comp_methods(session));
3435
6.06k
        LIBSSH2_METHOD_PREFS_STR(s, lang_cs_len, session->local.lang_prefs,
3436
6.06k
                                 NULL);
3437
6.06k
        LIBSSH2_METHOD_PREFS_STR(s, lang_sc_len, session->remote.lang_prefs,
3438
6.06k
                                 NULL);
3439
3440
        /* No optimistic KEX packet follows */
3441
        /* Deal with optimistic packets
3442
         * session->flags |= KEXINIT_OPTIMISTIC
3443
         * session->flags |= KEXINIT_METHODSMATCH
3444
         */
3445
6.06k
        *(s++) = 0;
3446
3447
        /* Reserved == 0 */
3448
6.06k
        _libssh2_htonu32(s, 0);
3449
3450
6.06k
#ifdef LIBSSH2DEBUG
3451
6.06k
        {
3452
            /* Funnily enough, they'll all "appear" to be '\0' terminated */
3453
6.06k
            unsigned char *p = data + 21;   /* type(1) + cookie(16) + len(4) */
3454
3455
6.06k
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
3456
6.06k
                           "Sent KEX: %s", p));
3457
6.06k
            p += kex_len + 4;
3458
6.06k
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
3459
6.06k
                           "Sent HOSTKEY: %s", p));
3460
6.06k
            p += hostkey_len + 4;
3461
6.06k
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
3462
6.06k
                           "Sent CRYPT_CS: %s", p));
3463
6.06k
            p += crypt_cs_len + 4;
3464
6.06k
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
3465
6.06k
                           "Sent CRYPT_SC: %s", p));
3466
6.06k
            p += crypt_sc_len + 4;
3467
6.06k
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
3468
6.06k
                           "Sent MAC_CS: %s", p));
3469
6.06k
            p += mac_cs_len + 4;
3470
6.06k
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
3471
6.06k
                           "Sent MAC_SC: %s", p));
3472
6.06k
            p += mac_sc_len + 4;
3473
6.06k
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
3474
6.06k
                           "Sent COMP_CS: %s", p));
3475
6.06k
            p += comp_cs_len + 4;
3476
6.06k
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
3477
6.06k
                           "Sent COMP_SC: %s", p));
3478
6.06k
            p += comp_sc_len + 4;
3479
6.06k
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
3480
6.06k
                           "Sent LANG_CS: %s", p));
3481
6.06k
            p += lang_cs_len + 4;
3482
6.06k
            _libssh2_debug((session, LIBSSH2_TRACE_KEX,
3483
6.06k
                           "Sent LANG_SC: %s", p));
3484
            /* p += lang_sc_len + 4; */
3485
6.06k
        }
3486
6.06k
#endif /* LIBSSH2DEBUG */
3487
3488
6.06k
        session->kexinit_state = libssh2_NB_state_created;
3489
6.06k
    }
3490
0
    else {
3491
0
        data = session->kexinit_data;
3492
0
        data_len = session->kexinit_data_len;
3493
        /* zap the variables to ensure there is NOT a double free later */
3494
0
        session->kexinit_data = NULL;
3495
0
        session->kexinit_data_len = 0;
3496
0
    }
3497
3498
6.06k
    rc = _libssh2_transport_send(session, data, data_len, NULL, 0);
3499
6.06k
    if(rc == LIBSSH2_ERROR_EAGAIN) {
3500
0
        session->kexinit_data = data;
3501
0
        session->kexinit_data_len = data_len;
3502
0
        return rc;
3503
0
    }
3504
6.06k
    else if(rc) {
3505
0
        LIBSSH2_FREE(session, data);
3506
0
        session->kexinit_state = libssh2_NB_state_idle;
3507
0
        return _libssh2_error(session, rc,
3508
0
                              "Unable to send KEXINIT packet to remote host");
3509
3510
0
    }
3511
3512
6.06k
    if(session->local.kexinit) {
3513
0
        LIBSSH2_FREE(session, session->local.kexinit);
3514
0
    }
3515
3516
6.06k
    session->local.kexinit = data;
3517
6.06k
    session->local.kexinit_len = data_len;
3518
3519
6.06k
    session->kexinit_state = libssh2_NB_state_idle;
3520
3521
6.06k
    return 0;
3522
6.06k
}
3523
3524
/* _libssh2_kex_agree_instr
3525
 * Kex specific variant of strstr()
3526
 * Needle must be preceded by BOL or ',', and followed by ',' or EOL
3527
 */
3528
unsigned char *
3529
_libssh2_kex_agree_instr(unsigned char *haystack, size_t haystack_len,
3530
                         const unsigned char *needle, size_t needle_len)
3531
76.9k
{
3532
76.9k
    unsigned char *s;
3533
76.9k
    unsigned char *end_haystack;
3534
76.9k
    size_t left;
3535
3536
76.9k
    if(!haystack || !needle) {
3537
0
        return NULL;
3538
0
    }
3539
3540
    /* Haystack too short to bother trying */
3541
76.9k
    if(haystack_len < needle_len || needle_len == 0) {
3542
7.79k
        return NULL;
3543
7.79k
    }
3544
3545
69.1k
    s = haystack;
3546
69.1k
    end_haystack = &haystack[haystack_len];
3547
69.1k
    left = end_haystack - s;
3548
3549
    /* Needle at start of haystack */
3550
69.1k
    if((strncmp((char *) haystack, (const char *) needle, needle_len) == 0) &&
3551
69.1k
        (needle_len == haystack_len || haystack[needle_len] == ',')) {
3552
7.73k
        return haystack;
3553
7.73k
    }
3554
3555
    /* Search until we run out of comas or we run out of haystack,
3556
       whichever comes first */
3557
    /* !checksrc! disable EQUALSNULL 1 */
3558
516k
    while((s = (unsigned char *) memchr((char *) s, ',', left)) != NULL) {
3559
        /* Advance buffer past coma if we can */
3560
492k
        left = end_haystack - s;
3561
492k
        if((left >= 1) && (left <= haystack_len) && (left > needle_len)) {
3562
462k
            s++;
3563
462k
            left--;
3564
462k
        }
3565
30.3k
        else {
3566
30.3k
            return NULL;
3567
30.3k
        }
3568
3569
        /* Needle at X position */
3570
462k
        if((strncmp((char *) s, (const char *) needle, needle_len) == 0) &&
3571
462k
            (((s - haystack) + needle_len) == haystack_len
3572
8.27k
             || s[needle_len] == ',')) {
3573
6.98k
            return s;
3574
6.98k
        }
3575
462k
    }
3576
3577
24.0k
    return NULL;
3578
61.3k
}
3579
3580
3581
3582
/* kex_get_method_by_name
3583
 */
3584
static const LIBSSH2_COMMON_METHOD *
3585
kex_get_method_by_name(const char *name, size_t name_len,
3586
                       const LIBSSH2_COMMON_METHOD ** methodlist)
3587
0
{
3588
0
    while(*methodlist) {
3589
0
        if((strlen((*methodlist)->name) == name_len) &&
3590
0
            (strncmp((*methodlist)->name, name, name_len) == 0)) {
3591
0
            return *methodlist;
3592
0
        }
3593
0
        methodlist++;
3594
0
    }
3595
0
    return NULL;
3596
0
}
3597
3598
3599
3600
/* kex_agree_hostkey
3601
 * Agree on a Hostkey which works with this kex
3602
 */
3603
static int kex_agree_hostkey(LIBSSH2_SESSION * session,
3604
                             size_t kex_flags,
3605
                             unsigned char *hostkey, size_t hostkey_len)
3606
2.45k
{
3607
2.45k
    const LIBSSH2_HOSTKEY_METHOD **hostkeyp = libssh2_hostkey_methods();
3608
2.45k
    unsigned char *s;
3609
3610
2.45k
    if(session->hostkey_prefs) {
3611
0
        s = (unsigned char *) session->hostkey_prefs;
3612
3613
0
        while(s && *s) {
3614
0
            unsigned char *p = (unsigned char *) strchr((char *) s, ',');
3615
0
            size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
3616
0
            if(_libssh2_kex_agree_instr(hostkey, hostkey_len, s, method_len)) {
3617
0
                const LIBSSH2_HOSTKEY_METHOD *method =
3618
0
                    (const LIBSSH2_HOSTKEY_METHOD *)
3619
0
                    kex_get_method_by_name((char *) s, method_len,
3620
0
                                           (const LIBSSH2_COMMON_METHOD **)
3621
0
                                           hostkeyp);
3622
3623
0
                if(!method) {
3624
                    /* Invalid method -- Should never be reached */
3625
0
                    return -1;
3626
0
                }
3627
3628
                /* So far so good, but does it suit our purposes? (Encrypting
3629
                   vs Signing) */
3630
0
                if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) ==
3631
0
                     0) || (method->encrypt)) {
3632
                    /* Either this hostkey can do encryption or this kex just
3633
                       doesn't require it */
3634
0
                    if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY)
3635
0
                         == 0) || (method->sig_verify)) {
3636
                        /* Either this hostkey can do signing or this kex just
3637
                           doesn't require it */
3638
0
                        session->hostkey = method;
3639
0
                        return 0;
3640
0
                    }
3641
0
                }
3642
0
            }
3643
3644
0
            s = p ? p + 1 : NULL;
3645
0
        }
3646
0
        return -1;
3647
0
    }
3648
3649
22.5k
    while(hostkeyp && (*hostkeyp) && (*hostkeyp)->name) {
3650
22.1k
        s = _libssh2_kex_agree_instr(hostkey, hostkey_len,
3651
22.1k
                                     (const unsigned char *) (*hostkeyp)->name,
3652
22.1k
                                     strlen((*hostkeyp)->name));
3653
22.1k
        if(s) {
3654
            /* So far so good, but does it suit our purposes? (Encrypting vs
3655
               Signing) */
3656
2.20k
            if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_ENC_HOSTKEY) == 0) ||
3657
2.20k
                ((*hostkeyp)->encrypt)) {
3658
                /* Either this hostkey can do encryption or this kex just
3659
                   doesn't require it */
3660
2.20k
                if(((kex_flags & LIBSSH2_KEX_METHOD_FLAG_REQ_SIGN_HOSTKEY) ==
3661
2.20k
                     0) || ((*hostkeyp)->sig_verify)) {
3662
                    /* Either this hostkey can do signing or this kex just
3663
                       doesn't require it */
3664
2.06k
                    session->hostkey = *hostkeyp;
3665
2.06k
                    return 0;
3666
2.06k
                }
3667
2.20k
            }
3668
2.20k
        }
3669
20.0k
        hostkeyp++;
3670
20.0k
    }
3671
3672
386
    return -1;
3673
2.45k
}
3674
3675
3676
3677
/* kex_agree_kex_hostkey
3678
 * Agree on a Key Exchange method and a hostkey encoding type
3679
 */
3680
static int kex_agree_kex_hostkey(LIBSSH2_SESSION * session, unsigned char *kex,
3681
                                 size_t kex_len, unsigned char *hostkey,
3682
                                 size_t hostkey_len)
3683
2.38k
{
3684
2.38k
    const LIBSSH2_KEX_METHOD **kexp = libssh2_kex_methods;
3685
2.38k
    unsigned char *s;
3686
2.38k
    const unsigned char *strict =
3687
2.38k
        (const unsigned char *)"kex-strict-s-v00@openssh.com";
3688
3689
2.38k
    if(_libssh2_kex_agree_instr(kex, kex_len, strict, 28)) {
3690
552
        session->kex_strict = 1;
3691
552
    }
3692
3693
2.38k
    if(session->kex_prefs) {
3694
0
        s = (unsigned char *) session->kex_prefs;
3695
3696
0
        while(s && *s) {
3697
0
            unsigned char *q, *p = (unsigned char *) strchr((char *) s, ',');
3698
0
            size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
3699
0
            q = _libssh2_kex_agree_instr(kex, kex_len, s, method_len);
3700
0
            if(q) {
3701
0
                const LIBSSH2_KEX_METHOD *method = (const LIBSSH2_KEX_METHOD *)
3702
0
                    kex_get_method_by_name((char *) s, method_len,
3703
0
                                           (const LIBSSH2_COMMON_METHOD **)
3704
0
                                           kexp);
3705
3706
0
                if(!method) {
3707
                    /* Invalid method -- Should never be reached */
3708
0
                    return -1;
3709
0
                }
3710
3711
                /* We've agreed on a key exchange method,
3712
                 * Can we agree on a hostkey that works with this kex?
3713
                 */
3714
0
                if(kex_agree_hostkey(session, method->flags, hostkey,
3715
0
                                     hostkey_len) == 0) {
3716
0
                    session->kex = method;
3717
0
                    if(session->burn_optimistic_kexinit && (kex == q)) {
3718
                        /* Server sent an optimistic packet, and client agrees
3719
                         * with preference cancel burning the first KEX_INIT
3720
                         * packet that comes in */
3721
0
                        session->burn_optimistic_kexinit = 0;
3722
0
                    }
3723
0
                    return 0;
3724
0
                }
3725
0
            }
3726
3727
0
            s = p ? p + 1 : NULL;
3728
0
        }
3729
0
        return -1;
3730
0
    }
3731
3732
19.7k
    while(*kexp && (*kexp)->name) {
3733
19.4k
        s = _libssh2_kex_agree_instr(kex, kex_len,
3734
19.4k
                                     (const unsigned char *) (*kexp)->name,
3735
19.4k
                                     strlen((*kexp)->name));
3736
19.4k
        if(s) {
3737
            /* We've agreed on a key exchange method,
3738
             * Can we agree on a hostkey that works with this kex?
3739
             */
3740
2.45k
            if(kex_agree_hostkey(session, (*kexp)->flags, hostkey,
3741
2.45k
                                 hostkey_len) == 0) {
3742
2.06k
                session->kex = *kexp;
3743
2.06k
                if(session->burn_optimistic_kexinit && (kex == s)) {
3744
                    /* Server sent an optimistic packet, and client agrees
3745
                     * with preference cancel burning the first KEX_INIT
3746
                     * packet that comes in */
3747
876
                    session->burn_optimistic_kexinit = 0;
3748
876
                }
3749
2.06k
                return 0;
3750
2.06k
            }
3751
2.45k
        }
3752
17.4k
        kexp++;
3753
17.4k
    }
3754
314
    return -1;
3755
2.38k
}
3756
3757
3758
3759
/* kex_agree_crypt
3760
 * Agree on a cipher algo
3761
 */
3762
static int kex_agree_crypt(LIBSSH2_SESSION * session,
3763
                           libssh2_endpoint_data *endpoint,
3764
                           unsigned char *crypt,
3765
                           size_t crypt_len)
3766
4.02k
{
3767
4.02k
    const LIBSSH2_CRYPT_METHOD **cryptp = libssh2_crypt_methods();
3768
4.02k
    unsigned char *s;
3769
3770
4.02k
    (void)session;
3771
3772
4.02k
    if(endpoint->crypt_prefs) {
3773
0
        s = (unsigned char *) endpoint->crypt_prefs;
3774
3775
0
        while(s && *s) {
3776
0
            unsigned char *p = (unsigned char *) strchr((char *) s, ',');
3777
0
            size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
3778
3779
0
            if(_libssh2_kex_agree_instr(crypt, crypt_len, s, method_len)) {
3780
0
                const LIBSSH2_CRYPT_METHOD *method =
3781
0
                    (const LIBSSH2_CRYPT_METHOD *)
3782
0
                    kex_get_method_by_name((char *) s, method_len,
3783
0
                                           (const LIBSSH2_COMMON_METHOD **)
3784
0
                                           cryptp);
3785
3786
0
                if(!method) {
3787
                    /* Invalid method -- Should never be reached */
3788
0
                    return -1;
3789
0
                }
3790
3791
0
                endpoint->crypt = method;
3792
0
                return 0;
3793
0
            }
3794
3795
0
            s = p ? p + 1 : NULL;
3796
0
        }
3797
0
        return -1;
3798
0
    }
3799
3800
18.0k
    while(*cryptp && (*cryptp)->name) {
3801
17.8k
        s = _libssh2_kex_agree_instr(crypt, crypt_len,
3802
17.8k
                                     (const unsigned char *) (*cryptp)->name,
3803
17.8k
                                     strlen((*cryptp)->name));
3804
17.8k
        if(s) {
3805
3.84k
            endpoint->crypt = *cryptp;
3806
3.84k
            return 0;
3807
3.84k
        }
3808
14.0k
        cryptp++;
3809
14.0k
    }
3810
3811
182
    return -1;
3812
4.02k
}
3813
3814
3815
3816
/* kex_agree_mac
3817
 * Agree on a message authentication hash
3818
 */
3819
static int kex_agree_mac(LIBSSH2_SESSION * session,
3820
                         libssh2_endpoint_data * endpoint, unsigned char *mac,
3821
                         size_t mac_len)
3822
3.73k
{
3823
3.73k
    const LIBSSH2_MAC_METHOD **macp = _libssh2_mac_methods();
3824
3.73k
    const LIBSSH2_MAC_METHOD *override;
3825
3.73k
    unsigned char *s;
3826
3.73k
    (void)session;
3827
3828
3.73k
    override = _libssh2_mac_override(endpoint->crypt);
3829
3.73k
    if(override) {
3830
        /* This crypto method has its own hmac method built-in, so a separate
3831
         * negotiation (and use) of a separate hmac method is unnecessary */
3832
1.72k
        endpoint->mac = override;
3833
1.72k
        return 0;
3834
1.72k
    }
3835
3836
2.00k
    if(endpoint->mac_prefs) {
3837
0
        s = (unsigned char *) endpoint->mac_prefs;
3838
3839
0
        while(s && *s) {
3840
0
            unsigned char *p = (unsigned char *) strchr((char *) s, ',');
3841
0
            size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
3842
3843
0
            if(_libssh2_kex_agree_instr(mac, mac_len, s, method_len)) {
3844
0
                const LIBSSH2_MAC_METHOD *method = (const LIBSSH2_MAC_METHOD *)
3845
0
                    kex_get_method_by_name((char *) s, method_len,
3846
0
                                           (const LIBSSH2_COMMON_METHOD **)
3847
0
                                           macp);
3848
3849
0
                if(!method) {
3850
                    /* Invalid method -- Should never be reached */
3851
0
                    return -1;
3852
0
                }
3853
3854
0
                endpoint->mac = method;
3855
0
                return 0;
3856
0
            }
3857
3858
0
            s = p ? p + 1 : NULL;
3859
0
        }
3860
0
        return -1;
3861
0
    }
3862
3863
10.1k
    while(*macp && (*macp)->name) {
3864
10.0k
        s = _libssh2_kex_agree_instr(mac, mac_len,
3865
10.0k
                                     (const unsigned char *) (*macp)->name,
3866
10.0k
                                     strlen((*macp)->name));
3867
10.0k
        if(s) {
3868
1.91k
            endpoint->mac = *macp;
3869
1.91k
            return 0;
3870
1.91k
        }
3871
8.15k
        macp++;
3872
8.15k
    }
3873
3874
95
    return -1;
3875
2.00k
}
3876
3877
3878
3879
/* kex_agree_comp
3880
 * Agree on a compression scheme
3881
 */
3882
static int kex_agree_comp(LIBSSH2_SESSION *session,
3883
                          libssh2_endpoint_data *endpoint, unsigned char *comp,
3884
                          size_t comp_len)
3885
3.54k
{
3886
3.54k
    const LIBSSH2_COMP_METHOD **compp = _libssh2_comp_methods(session);
3887
3.54k
    unsigned char *s;
3888
3.54k
    (void)session;
3889
3890
3.54k
    if(endpoint->comp_prefs) {
3891
0
        s = (unsigned char *) endpoint->comp_prefs;
3892
3893
0
        while(s && *s) {
3894
0
            unsigned char *p = (unsigned char *) strchr((char *) s, ',');
3895
0
            size_t method_len = (p ? (size_t)(p - s) : strlen((char *) s));
3896
3897
0
            if(_libssh2_kex_agree_instr(comp, comp_len, s, method_len)) {
3898
0
                const LIBSSH2_COMP_METHOD *method =
3899
0
                    (const LIBSSH2_COMP_METHOD *)
3900
0
                    kex_get_method_by_name((char *) s, method_len,
3901
0
                                           (const LIBSSH2_COMMON_METHOD **)
3902
0
                                           compp);
3903
3904
0
                if(!method) {
3905
                    /* Invalid method -- Should never be reached */
3906
0
                    return -1;
3907
0
                }
3908
3909
0
                endpoint->comp = method;
3910
0
                return 0;
3911
0
            }
3912
3913
0
            s = p ? p + 1 : NULL;
3914
0
        }
3915
0
        return -1;
3916
0
    }
3917
3918
3.65k
    while(*compp && (*compp)->name) {
3919
3.54k
        s = _libssh2_kex_agree_instr(comp, comp_len,
3920
3.54k
                                     (const unsigned char *) (*compp)->name,
3921
3.54k
                                     strlen((*compp)->name));
3922
3.54k
        if(s) {
3923
3.43k
            endpoint->comp = *compp;
3924
3.43k
            return 0;
3925
3.43k
        }
3926
110
        compp++;
3927
110
    }
3928
3929
110
    return -1;
3930
3.54k
}
3931
3932
3933
/* TODO: When in server mode we need to turn this logic on its head
3934
 * The Client gets to make the final call on "agreed methods"
3935
 */
3936
3937
/* kex_agree_methods
3938
 * Decide which specific method to use of the methods offered by each party
3939
 */
3940
static int kex_agree_methods(LIBSSH2_SESSION * session, unsigned char *data,
3941
                             size_t data_len)
3942
4.68k
{
3943
4.68k
    unsigned char *kex, *hostkey, *crypt_cs, *crypt_sc, *comp_cs, *comp_sc,
3944
4.68k
        *mac_cs, *mac_sc;
3945
4.68k
    size_t kex_len, hostkey_len, crypt_cs_len, crypt_sc_len, comp_cs_len;
3946
4.68k
    size_t comp_sc_len, mac_cs_len, mac_sc_len;
3947
4.68k
    struct string_buf buf;
3948
3949
4.68k
    if(data_len < 17)
3950
388
        return -1;
3951
3952
4.29k
    buf.data = (unsigned char *)data;
3953
4.29k
    buf.len = data_len;
3954
4.29k
    buf.dataptr = buf.data;
3955
4.29k
    buf.dataptr++; /* advance past packet type */
3956
3957
    /* Skip cookie, don't worry, it's preserved in the kexinit field */
3958
4.29k
    buf.dataptr += 16;
3959
3960
    /* Locate each string */
3961
4.29k
    if(_libssh2_get_string(&buf, &kex, &kex_len))
3962
205
        return -1;
3963
4.09k
    if(_libssh2_get_string(&buf, &hostkey, &hostkey_len))
3964
500
        return -1;
3965
3.59k
    if(_libssh2_get_string(&buf, &crypt_cs, &crypt_cs_len))
3966
137
        return -1;
3967
3.45k
    if(_libssh2_get_string(&buf, &crypt_sc, &crypt_sc_len))
3968
298
        return -1;
3969
3.15k
    if(_libssh2_get_string(&buf, &mac_cs, &mac_cs_len))
3970
242
        return -1;
3971
2.91k
    if(_libssh2_get_string(&buf, &mac_sc, &mac_sc_len))
3972
163
        return -1;
3973
2.75k
    if(_libssh2_get_string(&buf, &comp_cs, &comp_cs_len))
3974
124
        return -1;
3975
2.62k
    if(_libssh2_get_string(&buf, &comp_sc, &comp_sc_len))
3976
144
        return -1;
3977
3978
    /* If the server sent an optimistic packet, assume that it guessed wrong.
3979
     * If the guess is determined to be right (by kex_agree_kex_hostkey)
3980
     * This flag will be reset to zero so that it's not ignored */
3981
2.48k
    if(_libssh2_check_length(&buf, 1)) {
3982
2.38k
        session->burn_optimistic_kexinit = *(buf.dataptr++);
3983
2.38k
    }
3984
103
    else {
3985
103
        return -1;
3986
103
    }
3987
3988
    /* Next uint32 in packet is all zeros (reserved) */
3989
3990
2.38k
    if(kex_agree_kex_hostkey(session, kex, kex_len, hostkey, hostkey_len)) {
3991
314
        return -1;
3992
314
    }
3993
3994
2.06k
    if(kex_agree_crypt(session, &session->local, crypt_cs, crypt_cs_len)
3995
2.06k
       || kex_agree_crypt(session, &session->remote, crypt_sc, crypt_sc_len)) {
3996
182
        return -1;
3997
182
    }
3998
3999
    /* This must happen after kex_agree_crypt since some MACs depend on the
4000
       negotiated crypto method */
4001
1.88k
    if(kex_agree_mac(session, &session->local, mac_cs, mac_cs_len)
4002
1.88k
       || kex_agree_mac(session, &session->remote, mac_sc, mac_sc_len)) {
4003
95
        return -1;
4004
95
    }
4005
4006
1.78k
    if(kex_agree_comp(session, &session->local, comp_cs, comp_cs_len)
4007
1.78k
       || kex_agree_comp(session, &session->remote, comp_sc, comp_sc_len)) {
4008
110
        return -1;
4009
110
    }
4010
4011
#if 0
4012
    if(libssh2_kex_agree_lang(session, &session->local, lang_cs, lang_cs_len)
4013
       || libssh2_kex_agree_lang(session, &session->remote, lang_sc,
4014
                                 lang_sc_len)) {
4015
        return -1;
4016
    }
4017
#endif
4018
4019
1.67k
    _libssh2_debug((session, LIBSSH2_TRACE_KEX,
4020
1.67k
                   "Agreed on KEX method: %s",
4021
1.67k
                   session->kex->name));
4022
1.67k
    _libssh2_debug((session, LIBSSH2_TRACE_KEX,
4023
1.67k
                   "Agreed on HOSTKEY method: %s",
4024
1.67k
                   session->hostkey->name));
4025
1.67k
    _libssh2_debug((session, LIBSSH2_TRACE_KEX,
4026
1.67k
                   "Agreed on CRYPT_CS method: %s",
4027
1.67k
                   session->local.crypt->name));
4028
1.67k
    _libssh2_debug((session, LIBSSH2_TRACE_KEX,
4029
1.67k
                   "Agreed on CRYPT_SC method: %s",
4030
1.67k
                   session->remote.crypt->name));
4031
1.67k
    _libssh2_debug((session, LIBSSH2_TRACE_KEX,
4032
1.67k
                   "Agreed on MAC_CS method: %s",
4033
1.67k
                   session->local.mac->name));
4034
1.67k
    _libssh2_debug((session, LIBSSH2_TRACE_KEX,
4035
1.67k
                   "Agreed on MAC_SC method: %s",
4036
1.67k
                   session->remote.mac->name));
4037
1.67k
    _libssh2_debug((session, LIBSSH2_TRACE_KEX,
4038
1.67k
                   "Agreed on COMP_CS method: %s",
4039
1.67k
                   session->local.comp->name));
4040
1.67k
    _libssh2_debug((session, LIBSSH2_TRACE_KEX,
4041
1.67k
                   "Agreed on COMP_SC method: %s",
4042
1.67k
                   session->remote.comp->name));
4043
4044
1.67k
    return 0;
4045
1.78k
}
4046
4047
4048
4049
/* _libssh2_kex_exchange
4050
 * Exchange keys
4051
 * Returns 0 on success, non-zero on failure
4052
 *
4053
 * Returns some errors without _libssh2_error()
4054
 */
4055
int
4056
_libssh2_kex_exchange(LIBSSH2_SESSION * session, int reexchange,
4057
                      key_exchange_state_t * key_state)
4058
6.07k
{
4059
6.07k
    int rc = 0;
4060
6.07k
    int retcode;
4061
4062
6.07k
    session->state |= LIBSSH2_STATE_KEX_ACTIVE;
4063
4064
6.07k
    if(key_state->state == libssh2_NB_state_idle) {
4065
        /* Prevent loop in packet_add() */
4066
6.06k
        session->state |= LIBSSH2_STATE_EXCHANGING_KEYS;
4067
4068
6.06k
        if(reexchange) {
4069
3.29k
            if(session->kex && session->kex->cleanup) {
4070
1.22k
                session->kex->cleanup(session, &key_state->key_state_low);
4071
1.22k
            }
4072
4073
3.29k
            session->kex = NULL;
4074
4075
3.29k
            if(session->hostkey && session->hostkey->dtor) {
4076
1.23k
                session->hostkey->dtor(session,
4077
1.23k
                                       &session->server_hostkey_abstract);
4078
1.23k
            }
4079
3.29k
            session->hostkey = NULL;
4080
3.29k
        }
4081
4082
6.06k
        key_state->state = libssh2_NB_state_created;
4083
6.06k
    }
4084
4085
6.07k
    if(!session->kex || !session->hostkey) {
4086
6.07k
        if(key_state->state == libssh2_NB_state_created) {
4087
            /* Preserve in case of failure */
4088
6.06k
            key_state->oldlocal = session->local.kexinit;
4089
6.06k
            key_state->oldlocal_len = session->local.kexinit_len;
4090
4091
6.06k
            session->local.kexinit = NULL;
4092
4093
6.06k
            key_state->state = libssh2_NB_state_sent;
4094
6.06k
        }
4095
4096
6.07k
        if(key_state->state == libssh2_NB_state_sent) {
4097
6.06k
            retcode = kexinit(session);
4098
6.06k
            if(retcode == LIBSSH2_ERROR_EAGAIN) {
4099
0
                session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
4100
0
                return retcode;
4101
0
            }
4102
6.06k
            else if(retcode) {
4103
0
                session->local.kexinit = key_state->oldlocal;
4104
0
                session->local.kexinit_len = key_state->oldlocal_len;
4105
0
                key_state->state = libssh2_NB_state_idle;
4106
0
                session->state &= ~LIBSSH2_STATE_INITIAL_KEX;
4107
0
                session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
4108
0
                session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
4109
0
                return -1;
4110
0
            }
4111
4112
6.06k
            key_state->state = libssh2_NB_state_sent1;
4113
6.06k
        }
4114
4115
6.07k
        if(key_state->state == libssh2_NB_state_sent1) {
4116
6.07k
            retcode =
4117
6.07k
                _libssh2_packet_require(session, SSH_MSG_KEXINIT,
4118
6.07k
                                        &key_state->data,
4119
6.07k
                                        &key_state->data_len, 0, NULL, 0,
4120
6.07k
                                        &key_state->req_state);
4121
6.07k
            if(retcode == LIBSSH2_ERROR_EAGAIN) {
4122
11
                session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
4123
11
                return retcode;
4124
11
            }
4125
6.06k
            else if(retcode) {
4126
1.37k
                if(session->local.kexinit) {
4127
1.37k
                    LIBSSH2_FREE(session, session->local.kexinit);
4128
1.37k
                }
4129
1.37k
                session->local.kexinit = key_state->oldlocal;
4130
1.37k
                session->local.kexinit_len = key_state->oldlocal_len;
4131
1.37k
                key_state->state = libssh2_NB_state_idle;
4132
1.37k
                session->state &= ~LIBSSH2_STATE_INITIAL_KEX;
4133
1.37k
                session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
4134
1.37k
                session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
4135
1.37k
                return -1;
4136
1.37k
            }
4137
4138
4.68k
            if(session->remote.kexinit) {
4139
258
                LIBSSH2_FREE(session, session->remote.kexinit);
4140
258
            }
4141
4.68k
            session->remote.kexinit = key_state->data;
4142
4.68k
            session->remote.kexinit_len = key_state->data_len;
4143
4.68k
            key_state->data = NULL;
4144
4145
4.68k
            if(kex_agree_methods(session, session->remote.kexinit,
4146
4.68k
                                 session->remote.kexinit_len))
4147
3.00k
                rc = LIBSSH2_ERROR_KEX_FAILURE;
4148
4149
4.68k
            key_state->state = libssh2_NB_state_sent2;
4150
4.68k
        }
4151
6.07k
    }
4152
0
    else {
4153
0
        key_state->state = libssh2_NB_state_sent2;
4154
0
    }
4155
4156
4.68k
    if(rc == 0 && session->kex) {
4157
1.67k
        if(key_state->state == libssh2_NB_state_sent2) {
4158
1.67k
            retcode = session->kex->exchange_keys(session,
4159
1.67k
                                                  &key_state->key_state_low);
4160
1.67k
            if(retcode == LIBSSH2_ERROR_EAGAIN) {
4161
0
                session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
4162
0
                return retcode;
4163
0
            }
4164
1.67k
            else if(retcode) {
4165
1.67k
                rc = _libssh2_error(session,
4166
1.67k
                                    LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE,
4167
1.67k
                                    "Unrecoverable error exchanging keys");
4168
1.67k
            }
4169
1.67k
        }
4170
1.67k
    }
4171
4172
    /* Done with kexinit buffers */
4173
4.68k
    if(session->local.kexinit) {
4174
4.42k
        LIBSSH2_FREE(session, session->local.kexinit);
4175
4.42k
        session->local.kexinit = NULL;
4176
4.42k
    }
4177
4.68k
    if(session->remote.kexinit) {
4178
4.42k
        LIBSSH2_FREE(session, session->remote.kexinit);
4179
4.42k
        session->remote.kexinit = NULL;
4180
4.42k
    }
4181
4182
4.68k
    session->state &= ~LIBSSH2_STATE_INITIAL_KEX;
4183
4.68k
    session->state &= ~LIBSSH2_STATE_KEX_ACTIVE;
4184
4.68k
    session->state &= ~LIBSSH2_STATE_EXCHANGING_KEYS;
4185
4186
4.68k
    key_state->state = libssh2_NB_state_idle;
4187
4188
4.68k
    return rc;
4189
4.68k
}
4190
4191
4192
4193
/* libssh2_session_method_pref
4194
 * Set preferred method
4195
 */
4196
LIBSSH2_API int
4197
libssh2_session_method_pref(LIBSSH2_SESSION * session, int method_type,
4198
                            const char *prefs)
4199
0
{
4200
0
    char **prefvar, *s, *newprefs;
4201
0
    char *tmpprefs = NULL;
4202
0
    size_t prefs_len = strlen(prefs);
4203
0
    const LIBSSH2_COMMON_METHOD **mlist;
4204
4205
0
    switch(method_type) {
4206
0
    case LIBSSH2_METHOD_KEX:
4207
0
        prefvar = &session->kex_prefs;
4208
0
        mlist = (const LIBSSH2_COMMON_METHOD **)libssh2_kex_methods;
4209
0
        break;
4210
4211
0
    case LIBSSH2_METHOD_HOSTKEY:
4212
0
        prefvar = &session->hostkey_prefs;
4213
0
        mlist = (const LIBSSH2_COMMON_METHOD **)libssh2_hostkey_methods();
4214
0
        break;
4215
4216
0
    case LIBSSH2_METHOD_CRYPT_CS:
4217
0
        prefvar = &session->local.crypt_prefs;
4218
0
        mlist = (const LIBSSH2_COMMON_METHOD **)libssh2_crypt_methods();
4219
0
        break;
4220
4221
0
    case LIBSSH2_METHOD_CRYPT_SC:
4222
0
        prefvar = &session->remote.crypt_prefs;
4223
0
        mlist = (const LIBSSH2_COMMON_METHOD **)libssh2_crypt_methods();
4224
0
        break;
4225
4226
0
    case LIBSSH2_METHOD_MAC_CS:
4227
0
        prefvar = &session->local.mac_prefs;
4228
0
        mlist = (const LIBSSH2_COMMON_METHOD **)_libssh2_mac_methods();
4229
0
        break;
4230
4231
0
    case LIBSSH2_METHOD_MAC_SC:
4232
0
        prefvar = &session->remote.mac_prefs;
4233
0
        mlist = (const LIBSSH2_COMMON_METHOD **)_libssh2_mac_methods();
4234
0
        break;
4235
4236
0
    case LIBSSH2_METHOD_COMP_CS:
4237
0
        prefvar = &session->local.comp_prefs;
4238
0
        mlist = (const LIBSSH2_COMMON_METHOD **)_libssh2_comp_methods(session);
4239
0
        break;
4240
4241
0
    case LIBSSH2_METHOD_COMP_SC:
4242
0
        prefvar = &session->remote.comp_prefs;
4243
0
        mlist = (const LIBSSH2_COMMON_METHOD **)_libssh2_comp_methods(session);
4244
0
        break;
4245
4246
0
    case LIBSSH2_METHOD_LANG_CS:
4247
0
        prefvar = &session->local.lang_prefs;
4248
0
        mlist = NULL;
4249
0
        break;
4250
4251
0
    case LIBSSH2_METHOD_LANG_SC:
4252
0
        prefvar = &session->remote.lang_prefs;
4253
0
        mlist = NULL;
4254
0
        break;
4255
4256
0
    case LIBSSH2_METHOD_SIGN_ALGO:
4257
0
        prefvar = &session->sign_algo_prefs;
4258
0
        mlist = NULL;
4259
0
        break;
4260
4261
0
    default:
4262
0
        return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
4263
0
                              "Invalid parameter specified for method_type");
4264
0
    }
4265
4266
0
    s = newprefs = LIBSSH2_ALLOC(session, prefs_len + 1);
4267
0
    if(!newprefs) {
4268
0
        if(tmpprefs) {
4269
0
            LIBSSH2_FREE(session, tmpprefs);
4270
0
        }
4271
0
        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
4272
0
                              "Error allocated space for method preferences");
4273
0
    }
4274
0
    memcpy(s, prefs, prefs_len + 1);
4275
4276
0
    while(s && *s && mlist) {
4277
0
        char *p = strchr(s, ',');
4278
0
        size_t method_len = (p ? (size_t)(p - s) : strlen(s));
4279
4280
0
        if(!kex_get_method_by_name(s, method_len, mlist)) {
4281
            /* Strip out unsupported method */
4282
0
            if(p) {
4283
0
                memmove(s, p + 1, strlen(s) - method_len);
4284
0
            }
4285
0
            else {
4286
0
                if(s > newprefs) {
4287
0
                    *(--s) = '\0';
4288
0
                }
4289
0
                else {
4290
0
                    *s = '\0';
4291
0
                }
4292
0
            }
4293
0
        }
4294
0
        else {
4295
0
            s = p ? (p + 1) : NULL;
4296
0
        }
4297
0
    }
4298
4299
0
    if(tmpprefs) {
4300
0
        LIBSSH2_FREE(session, tmpprefs);
4301
0
    }
4302
4303
0
    if(!*newprefs) {
4304
0
        LIBSSH2_FREE(session, newprefs);
4305
0
        return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
4306
0
                              "The requested method(s) are not currently "
4307
0
                              "supported");
4308
0
    }
4309
4310
    /* add method kex extension to the start of the user list */
4311
0
    if(method_type == LIBSSH2_METHOD_KEX) {
4312
0
        const char *kex_extensions =
4313
0
                    "ext-info-c,kex-strict-c-v00@openssh.com,";
4314
0
        size_t kex_extensions_len = strlen(kex_extensions);
4315
0
        size_t tmp_len = kex_extensions_len + strlen(newprefs);
4316
0
        tmpprefs = LIBSSH2_ALLOC(session, tmp_len + 1);
4317
0
        if(!tmpprefs) {
4318
0
            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
4319
0
                                  "Error allocated space for kex method"
4320
0
                                  " preferences");
4321
0
        }
4322
4323
0
        memcpy(tmpprefs, kex_extensions, kex_extensions_len);
4324
0
        memcpy(tmpprefs + kex_extensions_len, newprefs, strlen(newprefs));
4325
0
        tmpprefs[tmp_len] = '\0';
4326
4327
0
        LIBSSH2_FREE(session, newprefs);
4328
0
        newprefs = tmpprefs;
4329
0
    }
4330
4331
0
    if(*prefvar) {
4332
0
        LIBSSH2_FREE(session, *prefvar);
4333
0
    }
4334
0
    *prefvar = newprefs;
4335
4336
0
    return 0;
4337
0
}
4338
4339
/*
4340
 * libssh2_session_supported_algs
4341
 * returns a number of returned algorithms (a positive number) on success,
4342
 * a negative number on failure
4343
 */
4344
4345
LIBSSH2_API int libssh2_session_supported_algs(LIBSSH2_SESSION* session,
4346
                                               int method_type,
4347
                                               const char ***algs)
4348
0
{
4349
0
    unsigned int i;
4350
0
    unsigned int j;
4351
0
    unsigned int ialg;
4352
0
    const LIBSSH2_COMMON_METHOD **mlist;
4353
4354
    /* to prevent coredumps due to dereferencing of NULL */
4355
0
    if(!algs)
4356
0
        return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
4357
0
                              "algs must not be NULL");
4358
4359
0
    switch(method_type) {
4360
0
    case LIBSSH2_METHOD_KEX:
4361
0
        mlist = (const LIBSSH2_COMMON_METHOD **)libssh2_kex_methods;
4362
0
        break;
4363
4364
0
    case LIBSSH2_METHOD_HOSTKEY:
4365
0
        mlist = (const LIBSSH2_COMMON_METHOD **)libssh2_hostkey_methods();
4366
0
        break;
4367
4368
0
    case LIBSSH2_METHOD_CRYPT_CS:
4369
0
    case LIBSSH2_METHOD_CRYPT_SC:
4370
0
        mlist = (const LIBSSH2_COMMON_METHOD **)libssh2_crypt_methods();
4371
0
        break;
4372
4373
0
    case LIBSSH2_METHOD_MAC_CS:
4374
0
    case LIBSSH2_METHOD_MAC_SC:
4375
0
        mlist = (const LIBSSH2_COMMON_METHOD **)_libssh2_mac_methods();
4376
0
        break;
4377
4378
0
    case LIBSSH2_METHOD_COMP_CS:
4379
0
    case LIBSSH2_METHOD_COMP_SC:
4380
0
        mlist = (const LIBSSH2_COMMON_METHOD **)_libssh2_comp_methods(session);
4381
0
        break;
4382
4383
0
    case LIBSSH2_METHOD_SIGN_ALGO:
4384
        /* no built-in supported list due to backend support */
4385
0
        mlist = NULL;
4386
0
        break;
4387
4388
0
    default:
4389
0
        return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
4390
0
                              "Unknown method type");
4391
0
    }  /* switch */
4392
4393
    /* weird situation */
4394
0
    if(!mlist)
4395
0
        return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
4396
0
                              "No algorithm found");
4397
4398
    /*
4399
      mlist is looped through twice. The first time to find the number od
4400
      supported algorithms (needed to allocate the proper size of array) and
4401
      the second time to actually copy the pointers.  Typically this function
4402
      will not be called often (typically at the beginning of a session) and
4403
      the number of algorithms (i.e. number of iterations in one loop) will
4404
      not be high (typically it will not exceed 20) for quite a long time.
4405
4406
      So double looping really shouldn't be an issue and it is definitely a
4407
      better solution than reallocation several times.
4408
    */
4409
4410
    /* count the number of supported algorithms */
4411
0
    for(i = 0, ialg = 0; mlist[i]; i++) {
4412
        /* do not count fields with NULL name */
4413
0
        if(mlist[i]->name)
4414
0
            ialg++;
4415
0
    }
4416
4417
    /* weird situation, no algorithm found */
4418
0
    if(ialg == 0)
4419
0
        return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
4420
0
                              "No algorithm found");
4421
4422
    /* allocate buffer */
4423
0
    *algs = (const char **) LIBSSH2_ALLOC(session, ialg*sizeof(const char *));
4424
0
    if(!*algs) {
4425
0
        return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
4426
0
                              "Memory allocation failed");
4427
0
    }
4428
    /* Past this point *algs must be deallocated in case of an error! */
4429
4430
    /* copy non-NULL pointers only */
4431
0
    for(i = 0, j = 0; mlist[i] && j < ialg; i++) {
4432
0
        if(!mlist[i]->name) {
4433
            /* maybe a weird situation but if it occurs, do not include NULL
4434
               pointers */
4435
0
            continue;
4436
0
        }
4437
4438
        /* note that [] has higher priority than * (dereferencing) */
4439
0
        (*algs)[j++] = mlist[i]->name;
4440
0
    }
4441
4442
    /* correct number of pointers copied? (test the code above) */
4443
0
    if(j != ialg) {
4444
        /* deallocate buffer */
4445
0
        LIBSSH2_FREE(session, (void *)*algs);
4446
0
        *algs = NULL;
4447
4448
0
        return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
4449
0
                              "Internal error");
4450
0
    }
4451
4452
0
    return ialg;
4453
0
}