Coverage Report

Created: 2025-11-24 07:00

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