Coverage Report

Created: 2026-02-14 07:16

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