2 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 RCSID("$OpenBSD: kex.c,v 1.22 2001/03/05 17:17:20 markus Exp $");
28 #include <openssl/crypto.h>
29 #include <openssl/bio.h>
30 #include <openssl/bn.h>
31 #include <openssl/dh.h>
32 #include <openssl/pem.h>
46 #define KEX_COOKIE_LEN 16
49 kex_init(char *myproposal[PROPOSAL_MAX])
51 int first_kex_packet_follows = 0;
52 u_char cookie[KEX_COOKIE_LEN];
55 Buffer *ki = xmalloc(sizeof(*ki));
56 for (i = 0; i < KEX_COOKIE_LEN; i++) {
59 cookie[i] = rand & 0xff;
63 buffer_append(ki, (char *)cookie, sizeof cookie);
64 for (i = 0; i < PROPOSAL_MAX; i++)
65 buffer_put_cstring(ki, myproposal[i]);
66 buffer_put_char(ki, first_kex_packet_follows);
67 buffer_put_int(ki, 0); /* uint32 reserved */
71 /* send kexinit, parse and save reply */
74 Buffer *my_kexinit, Buffer *peer_kexint,
75 char *peer_proposal[PROPOSAL_MAX])
81 debug("send KEXINIT");
82 packet_start(SSH2_MSG_KEXINIT);
83 packet_put_raw(buffer_ptr(my_kexinit), buffer_len(my_kexinit));
89 * read and save raw KEXINIT payload in buffer. this is used during
90 * computation of the session_id and the session keys.
92 debug("wait KEXINIT");
93 packet_read_expect(&plen, SSH2_MSG_KEXINIT);
94 ptr = packet_get_raw(&plen);
95 buffer_append(peer_kexint, ptr, plen);
97 /* parse packet and save algorithm proposal */
99 for (i = 0; i < KEX_COOKIE_LEN; i++)
101 /* extract kex init proposal strings */
102 for (i = 0; i < PROPOSAL_MAX; i++) {
103 peer_proposal[i] = packet_get_string(NULL);
104 debug("got kexinit: %s", peer_proposal[i]);
106 /* first kex follow / reserved */
107 i = packet_get_char();
108 debug("first kex follow: %d ", i);
109 i = packet_get_int();
110 debug("reserved: %d ", i);
115 /* diffie-hellman-group1-sha1 */
118 dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
121 int n = BN_num_bits(dh_pub);
125 log("invalid public DH value: negativ");
128 for (i = 0; i <= n; i++)
129 if (BN_is_bit_set(dh_pub, i))
131 debug("bits set: %d/%d", bits_set, BN_num_bits(dh->p));
133 /* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */
134 if (bits_set > 1 && (BN_cmp(dh_pub, dh->p) == -1))
136 log("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p));
141 dh_gen_key(DH *dh, int need)
143 int i, bits_set = 0, tries = 0;
146 fatal("dh_gen_key: dh->p == NULL");
147 if (2*need >= BN_num_bits(dh->p))
148 fatal("dh_gen_key: group too small: %d (2*need %d)",
149 BN_num_bits(dh->p), 2*need);
151 if (dh->priv_key != NULL)
152 BN_free(dh->priv_key);
153 dh->priv_key = BN_new();
154 if (dh->priv_key == NULL)
155 fatal("dh_gen_key: BN_new failed");
156 /* generate a 2*need bits random private exponent */
157 if (!BN_rand(dh->priv_key, 2*need, 0, 0))
158 fatal("dh_gen_key: BN_rand failed");
159 if (DH_generate_key(dh) == 0)
160 fatal("DH_generate_key");
161 for (i = 0; i <= BN_num_bits(dh->priv_key); i++)
162 if (BN_is_bit_set(dh->priv_key, i))
164 debug("dh_gen_key: priv key bits set: %d/%d",
165 bits_set, BN_num_bits(dh->priv_key));
167 fatal("dh_gen_key: too many bad keys: giving up");
168 } while (!dh_pub_is_valid(dh, dh->pub_key));
172 dh_new_group_asc(const char *gen, const char *modulus)
181 if ((ret = BN_hex2bn(&dh->p, modulus)) < 0)
182 fatal("BN_hex2bn p");
183 if ((ret = BN_hex2bn(&dh->g, gen)) < 0)
184 fatal("BN_hex2bn g");
190 * This just returns the group, we still need to generate the exchange
195 dh_new_group(BIGNUM *gen, BIGNUM *modulus)
211 static char *gen = "2", *group1 =
212 "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
213 "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
214 "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
215 "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
216 "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
217 "FFFFFFFF" "FFFFFFFF";
219 return (dh_new_group_asc(gen, group1));
224 dump_digest(u_char *digest, int len)
227 for (i = 0; i< len; i++){
228 fprintf(stderr, "%02x", digest[i]);
230 fprintf(stderr, " ");
232 fprintf(stderr, "\n");
238 char *client_version_string,
239 char *server_version_string,
240 char *ckexinit, int ckexinitlen,
241 char *skexinit, int skexinitlen,
242 char *serverhostkeyblob, int sbloblen,
243 BIGNUM *client_dh_pub,
244 BIGNUM *server_dh_pub,
245 BIGNUM *shared_secret)
248 static u_char digest[EVP_MAX_MD_SIZE];
249 EVP_MD *evp_md = EVP_sha1();
253 buffer_put_string(&b, client_version_string, strlen(client_version_string));
254 buffer_put_string(&b, server_version_string, strlen(server_version_string));
256 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
257 buffer_put_int(&b, ckexinitlen+1);
258 buffer_put_char(&b, SSH2_MSG_KEXINIT);
259 buffer_append(&b, ckexinit, ckexinitlen);
260 buffer_put_int(&b, skexinitlen+1);
261 buffer_put_char(&b, SSH2_MSG_KEXINIT);
262 buffer_append(&b, skexinit, skexinitlen);
264 buffer_put_string(&b, serverhostkeyblob, sbloblen);
265 buffer_put_bignum2(&b, client_dh_pub);
266 buffer_put_bignum2(&b, server_dh_pub);
267 buffer_put_bignum2(&b, shared_secret);
273 EVP_DigestInit(&md, evp_md);
274 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
275 EVP_DigestFinal(&md, digest, NULL);
280 dump_digest(digest, evp_md->md_size);
287 char *client_version_string,
288 char *server_version_string,
289 char *ckexinit, int ckexinitlen,
290 char *skexinit, int skexinitlen,
291 char *serverhostkeyblob, int sbloblen,
292 int minbits, BIGNUM *prime, BIGNUM *gen,
293 BIGNUM *client_dh_pub,
294 BIGNUM *server_dh_pub,
295 BIGNUM *shared_secret)
298 static u_char digest[EVP_MAX_MD_SIZE];
299 EVP_MD *evp_md = EVP_sha1();
303 buffer_put_string(&b, client_version_string, strlen(client_version_string));
304 buffer_put_string(&b, server_version_string, strlen(server_version_string));
306 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
307 buffer_put_int(&b, ckexinitlen+1);
308 buffer_put_char(&b, SSH2_MSG_KEXINIT);
309 buffer_append(&b, ckexinit, ckexinitlen);
310 buffer_put_int(&b, skexinitlen+1);
311 buffer_put_char(&b, SSH2_MSG_KEXINIT);
312 buffer_append(&b, skexinit, skexinitlen);
314 buffer_put_string(&b, serverhostkeyblob, sbloblen);
315 buffer_put_int(&b, minbits);
316 buffer_put_bignum2(&b, prime);
317 buffer_put_bignum2(&b, gen);
318 buffer_put_bignum2(&b, client_dh_pub);
319 buffer_put_bignum2(&b, server_dh_pub);
320 buffer_put_bignum2(&b, shared_secret);
326 EVP_DigestInit(&md, evp_md);
327 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
328 EVP_DigestFinal(&md, digest, NULL);
333 dump_digest(digest, evp_md->md_size);
339 derive_key(int id, int need, u_char *hash, BIGNUM *shared_secret)
342 EVP_MD *evp_md = EVP_sha1();
346 int mdsz = evp_md->md_size;
347 u_char *digest = xmalloc(((need+mdsz-1)/mdsz)*mdsz);
350 buffer_put_bignum2(&b, shared_secret);
352 EVP_DigestInit(&md, evp_md);
353 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); /* shared_secret K */
354 EVP_DigestUpdate(&md, hash, mdsz); /* transport-06 */
355 EVP_DigestUpdate(&md, &c, 1); /* key id */
356 EVP_DigestUpdate(&md, hash, mdsz); /* session id */
357 EVP_DigestFinal(&md, digest, NULL);
360 for (have = mdsz; need > have; have += mdsz) {
361 EVP_DigestInit(&md, evp_md);
362 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
363 EVP_DigestUpdate(&md, hash, mdsz);
364 EVP_DigestUpdate(&md, digest, have);
365 EVP_DigestFinal(&md, digest + have, NULL);
369 fprintf(stderr, "Digest '%c'== ", c);
370 dump_digest(digest, need);
381 get_match(char *client, char *server)
383 char *sproposals[MAX_PROP];
384 char *c, *s, *p, *ret, *cp, *sp;
385 int i, j, nproposals;
387 c = cp = xstrdup(client);
388 s = sp = xstrdup(server);
390 for ((p = strsep(&sp, SEP)), i=0; p && *p != '\0';
391 (p = strsep(&sp, SEP)), i++) {
399 for ((p = strsep(&cp, SEP)), i=0; p && *p != '\0';
400 (p = strsep(&cp, SEP)), i++) {
401 for (j = 0; j < nproposals; j++) {
402 if (strcmp(p, sproposals[j]) == 0) {
415 choose_enc(Enc *enc, char *client, char *server)
417 char *name = get_match(client, server);
419 fatal("no matching cipher found: client %s server %s", client, server);
420 enc->cipher = cipher_by_name(name);
421 if (enc->cipher == NULL)
422 fatal("matching cipher is not supported: %s", name);
429 choose_mac(Mac *mac, char *client, char *server)
431 char *name = get_match(client, server);
433 fatal("no matching mac found: client %s server %s", client, server);
434 if (mac_init(mac, name) < 0)
435 fatal("unsupported mac %s", name);
436 /* truncate the key */
437 if (datafellows & SSH_BUG_HMAC)
444 choose_comp(Comp *comp, char *client, char *server)
446 char *name = get_match(client, server);
448 fatal("no matching comp found: client %s server %s", client, server);
449 if (strcmp(name, "zlib") == 0) {
451 } else if (strcmp(name, "none") == 0) {
454 fatal("unsupported comp %s", name);
459 choose_kex(Kex *k, char *client, char *server)
461 k->name = get_match(client, server);
464 if (strcmp(k->name, KEX_DH1) == 0) {
465 k->kex_type = DH_GRP1_SHA1;
466 } else if (strcmp(k->name, KEX_DHGEX) == 0) {
467 k->kex_type = DH_GEX_SHA1;
469 fatal("bad kex alg %s", k->name);
472 choose_hostkeyalg(Kex *k, char *client, char *server)
474 char *hostkeyalg = get_match(client, server);
475 if (hostkeyalg == NULL)
476 fatal("no hostkey alg");
477 k->hostkey_type = key_type_from_name(hostkeyalg);
478 if (k->hostkey_type == KEY_UNSPEC)
479 fatal("bad hostkey alg '%s'", hostkeyalg);
484 kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server)
487 int ctos; /* direction: if true client-to-server */
491 k = xmalloc(sizeof(*k));
492 memset(k, 0, sizeof(*k));
495 for (mode = 0; mode < MODE_MAX; mode++) {
496 int nenc, nmac, ncomp;
497 ctos = (!k->server && mode == MODE_OUT) || (k->server && mode == MODE_IN);
498 nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC;
499 nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC;
500 ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
501 choose_enc (&k->enc [mode], cprop[nenc], sprop[nenc]);
502 choose_mac (&k->mac [mode], cprop[nmac], sprop[nmac]);
503 choose_comp(&k->comp[mode], cprop[ncomp], sprop[ncomp]);
504 debug("kex: %s %s %s %s",
505 ctos ? "client->server" : "server->client",
510 choose_kex(k, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]);
511 choose_hostkeyalg(k, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
512 sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]);
514 for (mode = 0; mode < MODE_MAX; mode++) {
515 if (need < k->enc[mode].cipher->key_len)
516 need = k->enc[mode].cipher->key_len;
517 if (need < k->enc[mode].cipher->block_size)
518 need = k->enc[mode].cipher->block_size;
519 if (need < k->mac[mode].key_len)
520 need = k->mac[mode].key_len;
522 /* XXX need runden? */
528 kex_derive_keys(Kex *k, u_char *hash, BIGNUM *shared_secret)
535 for (i = 0; i < NKEYS; i++)
536 keys[i] = derive_key('A'+i, k->we_need, hash, shared_secret);
538 for (mode = 0; mode < MODE_MAX; mode++) {
539 ctos = (!k->server && mode == MODE_OUT) || (k->server && mode == MODE_IN);
540 k->enc[mode].iv = keys[ctos ? 0 : 1];
541 k->enc[mode].key = keys[ctos ? 2 : 3];
542 k->mac[mode].key = keys[ctos ? 4 : 5];