Deleted Added
full compact
kex.c (69587) kex.c (76259)
1/*
2 * Copyright (c) 2000 Markus Friedl. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.

--- 9 unchanged lines hidden (view full) ---

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.
23 */
24
25#include "includes.h"
1/*
2 * Copyright (c) 2000 Markus Friedl. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.

--- 9 unchanged lines hidden (view full) ---

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.
23 */
24
25#include "includes.h"
26RCSID("$OpenBSD: kex.c,v 1.12 2000/10/11 20:27:23 markus Exp $");
26RCSID("$OpenBSD: kex.c,v 1.33 2001/04/05 10:42:50 markus Exp $");
27
27
28#include "ssh.h"
28#include <openssl/crypto.h>
29
29#include "ssh2.h"
30#include "xmalloc.h"
31#include "buffer.h"
32#include "bufaux.h"
33#include "packet.h"
34#include "compat.h"
30#include "ssh2.h"
31#include "xmalloc.h"
32#include "buffer.h"
33#include "bufaux.h"
34#include "packet.h"
35#include "compat.h"
35
36#include <openssl/bn.h>
37#include <openssl/dh.h>
38
39#include <openssl/crypto.h>
40#include <openssl/bio.h>
41#include <openssl/bn.h>
42#include <openssl/dh.h>
43#include <openssl/pem.h>
44
36#include "cipher.h"
45#include "kex.h"
37#include "kex.h"
38#include "key.h"
39#include "log.h"
40#include "mac.h"
41#include "match.h"
42#include "dispatch.h"
46
47#define KEX_COOKIE_LEN 16
48
43
44#define KEX_COOKIE_LEN 16
45
49Buffer *
50kex_init(char *myproposal[PROPOSAL_MAX])
46void kex_kexinit_finish(Kex *kex);
47void kex_choose_conf(Kex *k);
48
49/* put algorithm proposal into buffer */
50void
51kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX])
51{
52{
52 int first_kex_packet_follows = 0;
53 unsigned char cookie[KEX_COOKIE_LEN];
54 u_int32_t rand = 0;
55 int i;
53 u_int32_t rand = 0;
54 int i;
56 Buffer *ki = xmalloc(sizeof(*ki));
55
56 buffer_clear(b);
57 for (i = 0; i < KEX_COOKIE_LEN; i++) {
58 if (i % 4 == 0)
59 rand = arc4random();
57 for (i = 0; i < KEX_COOKIE_LEN; i++) {
58 if (i % 4 == 0)
59 rand = arc4random();
60 cookie[i] = rand & 0xff;
60 buffer_put_char(b, rand & 0xff);
61 rand >>= 8;
62 }
61 rand >>= 8;
62 }
63 buffer_init(ki);
64 buffer_append(ki, (char *)cookie, sizeof cookie);
65 for (i = 0; i < PROPOSAL_MAX; i++)
63 for (i = 0; i < PROPOSAL_MAX; i++)
66 buffer_put_cstring(ki, myproposal[i]);
67 buffer_put_char(ki, first_kex_packet_follows);
68 buffer_put_int(ki, 0); /* uint32 reserved */
69 return ki;
64 buffer_put_cstring(b, proposal[i]);
65 buffer_put_char(b, 0); /* first_kex_packet_follows */
66 buffer_put_int(b, 0); /* uint32 reserved */
70}
71
67}
68
72/* send kexinit, parse and save reply */
73void
74kex_exchange_kexinit(
75 Buffer *my_kexinit, Buffer *peer_kexint,
76 char *peer_proposal[PROPOSAL_MAX])
69/* parse buffer and return algorithm proposal */
70char **
71kex_buf2prop(Buffer *raw)
77{
72{
73 Buffer b;
78 int i;
74 int i;
79 char *ptr;
80 int plen;
75 char **proposal;
81
76
82 debug("send KEXINIT");
83 packet_start(SSH2_MSG_KEXINIT);
84 packet_put_raw(buffer_ptr(my_kexinit), buffer_len(my_kexinit));
85 packet_send();
86 packet_write_wait();
87 debug("done");
77 proposal = xmalloc(PROPOSAL_MAX * sizeof(char *));
88
78
89 /*
90 * read and save raw KEXINIT payload in buffer. this is used during
91 * computation of the session_id and the session keys.
92 */
93 debug("wait KEXINIT");
94 packet_read_expect(&plen, SSH2_MSG_KEXINIT);
95 ptr = packet_get_raw(&plen);
96 buffer_append(peer_kexint, ptr, plen);
97
98 /* parse packet and save algorithm proposal */
79 buffer_init(&b);
80 buffer_append(&b, buffer_ptr(raw), buffer_len(raw));
99 /* skip cookie */
100 for (i = 0; i < KEX_COOKIE_LEN; i++)
81 /* skip cookie */
82 for (i = 0; i < KEX_COOKIE_LEN; i++)
101 packet_get_char();
83 buffer_get_char(&b);
102 /* extract kex init proposal strings */
103 for (i = 0; i < PROPOSAL_MAX; i++) {
84 /* extract kex init proposal strings */
85 for (i = 0; i < PROPOSAL_MAX; i++) {
104 peer_proposal[i] = packet_get_string(NULL);
105 debug("got kexinit: %s", peer_proposal[i]);
86 proposal[i] = buffer_get_string(&b,NULL);
87 debug2("kex_parse_kexinit: %s", proposal[i]);
106 }
88 }
107 /* first kex follow / reserved */
108 i = packet_get_char();
109 debug("first kex follow: %d ", i);
110 i = packet_get_int();
111 debug("reserved: %d ", i);
112 packet_done();
113 debug("done");
89 /* first kex follows / reserved */
90 i = buffer_get_char(&b);
91 debug2("kex_parse_kexinit: first_kex_follows %d ", i);
92 i = buffer_get_int(&b);
93 debug2("kex_parse_kexinit: reserved %d ", i);
94 buffer_free(&b);
95 return proposal;
114}
115
96}
97
116/* diffie-hellman-group1-sha1 */
117
118int
119dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
98void
99kex_prop_free(char **proposal)
120{
121 int i;
100{
101 int i;
122 int n = BN_num_bits(dh_pub);
123 int bits_set = 0;
124
102
125 if (dh_pub->neg) {
126 log("invalid public DH value: negativ");
127 return 0;
128 }
129 for (i = 0; i <= n; i++)
130 if (BN_is_bit_set(dh_pub, i))
131 bits_set++;
132 debug("bits set: %d/%d", bits_set, BN_num_bits(dh->p));
133
134 /* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */
135 if (bits_set > 1 && (BN_cmp(dh_pub, dh->p) == -1))
136 return 1;
137 log("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p));
138 return 0;
103 for (i = 0; i < PROPOSAL_MAX; i++)
104 xfree(proposal[i]);
105 xfree(proposal);
139}
140
106}
107
141DH *
142dh_gen_key(DH *dh)
108void
109kex_protocol_error(int type, int plen, void *ctxt)
143{
110{
144 int tries = 0;
145
146 do {
147 if (DH_generate_key(dh) == 0)
148 fatal("DH_generate_key");
149 if (tries++ > 10)
150 fatal("dh_new_group1: too many bad keys: giving up");
151 } while (!dh_pub_is_valid(dh, dh->pub_key));
152 return dh;
111 error("Hm, kex protocol error: type %d plen %d", type, plen);
153}
154
112}
113
155DH *
156dh_new_group_asc(const char *gen, const char *modulus)
114void
115kex_clear_dispatch(void)
157{
116{
158 DH *dh;
159 int ret;
117 int i;
160
118
161 dh = DH_new();
162 if (dh == NULL)
163 fatal("DH_new");
164
165 if ((ret = BN_hex2bn(&dh->p, modulus)) < 0)
166 fatal("BN_hex2bn p");
167 if ((ret = BN_hex2bn(&dh->g, gen)) < 0)
168 fatal("BN_hex2bn g");
169
170 return (dh_gen_key(dh));
119 /* Numbers 30-49 are used for kex packets */
120 for (i = 30; i <= 49; i++)
121 dispatch_set(i, &kex_protocol_error);
171}
172
122}
123
173DH *
174dh_new_group(BIGNUM *gen, BIGNUM *modulus)
124void
125kex_finish(Kex *kex)
175{
126{
176 DH *dh;
127 int plen;
177
128
178 dh = DH_new();
179 if (dh == NULL)
180 fatal("DH_new");
181 dh->p = modulus;
182 dh->g = gen;
129 kex_clear_dispatch();
183
130
184 return (dh_gen_key(dh));
185}
131 packet_start(SSH2_MSG_NEWKEYS);
132 packet_send();
133 /* packet_write_wait(); */
134 debug("SSH2_MSG_NEWKEYS sent");
186
135
187DH *
188dh_new_group1()
189{
190 static char *gen = "2", *group1 =
191 "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
192 "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
193 "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
194 "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
195 "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
196 "FFFFFFFF" "FFFFFFFF";
136 debug("waiting for SSH2_MSG_NEWKEYS");
137 packet_read_expect(&plen, SSH2_MSG_NEWKEYS);
138 debug("SSH2_MSG_NEWKEYS received");
197
139
198 return (dh_new_group_asc(gen, group1));
140 kex->done = 1;
141 buffer_clear(&kex->peer);
142 /* buffer_clear(&kex->my); */
143 kex->flags &= ~KEX_INIT_SENT;
144 xfree(kex->name);
145 kex->name = NULL;
199}
200
201void
146}
147
148void
202dump_digest(unsigned char *digest, int len)
149kex_send_kexinit(Kex *kex)
203{
150{
204 int i;
205 for (i = 0; i< len; i++){
206 fprintf(stderr, "%02x", digest[i]);
207 if(i%2!=0)
208 fprintf(stderr, " ");
151 if (kex == NULL) {
152 error("kex_send_kexinit: no kex, cannot rekey");
153 return;
209 }
154 }
210 fprintf(stderr, "\n");
155 if (kex->flags & KEX_INIT_SENT) {
156 debug("KEX_INIT_SENT");
157 return;
158 }
159 kex->done = 0;
160 packet_start(SSH2_MSG_KEXINIT);
161 packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my));
162 packet_send();
163 debug("SSH2_MSG_KEXINIT sent");
164 kex->flags |= KEX_INIT_SENT;
211}
212
165}
166
213unsigned char *
214kex_hash(
215 char *client_version_string,
216 char *server_version_string,
217 char *ckexinit, int ckexinitlen,
218 char *skexinit, int skexinitlen,
219 char *serverhostkeyblob, int sbloblen,
220 BIGNUM *client_dh_pub,
221 BIGNUM *server_dh_pub,
222 BIGNUM *shared_secret)
167void
168kex_input_kexinit(int type, int plen, void *ctxt)
223{
169{
224 Buffer b;
225 static unsigned char digest[EVP_MAX_MD_SIZE];
226 EVP_MD *evp_md = EVP_sha1();
227 EVP_MD_CTX md;
170 char *ptr;
171 int dlen;
172 int i;
173 Kex *kex = (Kex *)ctxt;
228
174
229 buffer_init(&b);
230 buffer_put_string(&b, client_version_string, strlen(client_version_string));
231 buffer_put_string(&b, server_version_string, strlen(server_version_string));
175 debug("SSH2_MSG_KEXINIT received");
176 if (kex == NULL)
177 fatal("kex_input_kexinit: no kex, cannot rekey");
232
178
233 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
234 buffer_put_int(&b, ckexinitlen+1);
235 buffer_put_char(&b, SSH2_MSG_KEXINIT);
236 buffer_append(&b, ckexinit, ckexinitlen);
237 buffer_put_int(&b, skexinitlen+1);
238 buffer_put_char(&b, SSH2_MSG_KEXINIT);
239 buffer_append(&b, skexinit, skexinitlen);
179 ptr = packet_get_raw(&dlen);
180 buffer_append(&kex->peer, ptr, dlen);
240
181
241 buffer_put_string(&b, serverhostkeyblob, sbloblen);
242 buffer_put_bignum2(&b, client_dh_pub);
243 buffer_put_bignum2(&b, server_dh_pub);
244 buffer_put_bignum2(&b, shared_secret);
245
246#ifdef DEBUG_KEX
247 buffer_dump(&b);
248#endif
182 /* discard packet */
183 for (i = 0; i < KEX_COOKIE_LEN; i++)
184 packet_get_char();
185 for (i = 0; i < PROPOSAL_MAX; i++)
186 xfree(packet_get_string(NULL));
187 packet_get_char();
188 packet_get_int();
189 packet_done();
249
190
250 EVP_DigestInit(&md, evp_md);
251 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
252 EVP_DigestFinal(&md, digest, NULL);
253
254 buffer_free(&b);
255
256#ifdef DEBUG_KEX
257 dump_digest(digest, evp_md->md_size);
258#endif
259 return digest;
191 kex_kexinit_finish(kex);
260}
261
192}
193
262unsigned char *
263kex_hash_gex(
264 char *client_version_string,
265 char *server_version_string,
266 char *ckexinit, int ckexinitlen,
267 char *skexinit, int skexinitlen,
268 char *serverhostkeyblob, int sbloblen,
269 int minbits, BIGNUM *prime, BIGNUM *gen,
270 BIGNUM *client_dh_pub,
271 BIGNUM *server_dh_pub,
272 BIGNUM *shared_secret)
194Kex *
195kex_setup(char *proposal[PROPOSAL_MAX])
273{
196{
274 Buffer b;
275 static unsigned char digest[EVP_MAX_MD_SIZE];
276 EVP_MD *evp_md = EVP_sha1();
277 EVP_MD_CTX md;
197 Kex *kex;
278
198
279 buffer_init(&b);
280 buffer_put_string(&b, client_version_string, strlen(client_version_string));
281 buffer_put_string(&b, server_version_string, strlen(server_version_string));
199 kex = xmalloc(sizeof(*kex));
200 memset(kex, 0, sizeof(*kex));
201 buffer_init(&kex->peer);
202 buffer_init(&kex->my);
203 kex_prop2buf(&kex->my, proposal);
204 kex->done = 0;
282
205
283 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
284 buffer_put_int(&b, ckexinitlen+1);
285 buffer_put_char(&b, SSH2_MSG_KEXINIT);
286 buffer_append(&b, ckexinit, ckexinitlen);
287 buffer_put_int(&b, skexinitlen+1);
288 buffer_put_char(&b, SSH2_MSG_KEXINIT);
289 buffer_append(&b, skexinit, skexinitlen);
206 kex_send_kexinit(kex); /* we start */
207 kex_clear_dispatch();
208 dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
290
209
291 buffer_put_string(&b, serverhostkeyblob, sbloblen);
292 buffer_put_int(&b, minbits);
293 buffer_put_bignum2(&b, prime);
294 buffer_put_bignum2(&b, gen);
295 buffer_put_bignum2(&b, client_dh_pub);
296 buffer_put_bignum2(&b, server_dh_pub);
297 buffer_put_bignum2(&b, shared_secret);
298
299#ifdef DEBUG_KEX
300 buffer_dump(&b);
301#endif
302
303 EVP_DigestInit(&md, evp_md);
304 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
305 EVP_DigestFinal(&md, digest, NULL);
306
307 buffer_free(&b);
308
309#ifdef DEBUG_KEX
310 dump_digest(digest, evp_md->md_size);
311#endif
312 return digest;
210 return kex;
313}
314
211}
212
315unsigned char *
316derive_key(int id, int need, char unsigned *hash, BIGNUM *shared_secret)
213void
214kex_kexinit_finish(Kex *kex)
317{
215{
318 Buffer b;
319 EVP_MD *evp_md = EVP_sha1();
320 EVP_MD_CTX md;
321 char c = id;
322 int have;
323 int mdsz = evp_md->md_size;
324 unsigned char *digest = xmalloc(((need+mdsz-1)/mdsz)*mdsz);
216 if (!(kex->flags & KEX_INIT_SENT))
217 kex_send_kexinit(kex);
325
218
326 buffer_init(&b);
327 buffer_put_bignum2(&b, shared_secret);
219 kex_choose_conf(kex);
328
220
329 EVP_DigestInit(&md, evp_md);
330 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); /* shared_secret K */
331 EVP_DigestUpdate(&md, hash, mdsz); /* transport-06 */
332 EVP_DigestUpdate(&md, &c, 1); /* key id */
333 EVP_DigestUpdate(&md, hash, mdsz); /* session id */
334 EVP_DigestFinal(&md, digest, NULL);
335
336 /* expand */
337 for (have = mdsz; need > have; have += mdsz) {
338 EVP_DigestInit(&md, evp_md);
339 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
340 EVP_DigestUpdate(&md, hash, mdsz);
341 EVP_DigestUpdate(&md, digest, have);
342 EVP_DigestFinal(&md, digest + have, NULL);
221 switch(kex->kex_type) {
222 case DH_GRP1_SHA1:
223 kexdh(kex);
224 break;
225 case DH_GEX_SHA1:
226 kexgex(kex);
227 break;
228 default:
229 fatal("Unsupported key exchange %d", kex->kex_type);
343 }
230 }
344 buffer_free(&b);
345#ifdef DEBUG_KEX
346 fprintf(stderr, "Digest '%c'== ", c);
347 dump_digest(digest, need);
348#endif
349 return digest;
350}
351
231}
232
352#define NKEYS 6
353
354#define MAX_PROP 20
355#define SEP ","
356
357char *
358get_match(char *client, char *server)
359{
360 char *sproposals[MAX_PROP];
361 char *c, *s, *p, *ret, *cp, *sp;
362 int i, j, nproposals;
363
364 c = cp = xstrdup(client);
365 s = sp = xstrdup(server);
366
367 for ((p = strsep(&sp, SEP)), i=0; p && *p != '\0';
368 (p = strsep(&sp, SEP)), i++) {
369 if (i < MAX_PROP)
370 sproposals[i] = p;
371 else
372 break;
373 }
374 nproposals = i;
375
376 for ((p = strsep(&cp, SEP)), i=0; p && *p != '\0';
377 (p = strsep(&cp, SEP)), i++) {
378 for (j = 0; j < nproposals; j++) {
379 if (strcmp(p, sproposals[j]) == 0) {
380 ret = xstrdup(p);
381 xfree(c);
382 xfree(s);
383 return ret;
384 }
385 }
386 }
387 xfree(c);
388 xfree(s);
389 return NULL;
390}
391void
392choose_enc(Enc *enc, char *client, char *server)
393{
233void
234choose_enc(Enc *enc, char *client, char *server)
235{
394 char *name = get_match(client, server);
236 char *name = match_list(client, server, NULL);
395 if (name == NULL)
396 fatal("no matching cipher found: client %s server %s", client, server);
397 enc->cipher = cipher_by_name(name);
398 if (enc->cipher == NULL)
399 fatal("matching cipher is not supported: %s", name);
400 enc->name = name;
401 enc->enabled = 0;
402 enc->iv = NULL;
403 enc->key = NULL;
404}
405void
406choose_mac(Mac *mac, char *client, char *server)
407{
237 if (name == NULL)
238 fatal("no matching cipher found: client %s server %s", client, server);
239 enc->cipher = cipher_by_name(name);
240 if (enc->cipher == NULL)
241 fatal("matching cipher is not supported: %s", name);
242 enc->name = name;
243 enc->enabled = 0;
244 enc->iv = NULL;
245 enc->key = NULL;
246}
247void
248choose_mac(Mac *mac, char *client, char *server)
249{
408 char *name = get_match(client, server);
250 char *name = match_list(client, server, NULL);
409 if (name == NULL)
410 fatal("no matching mac found: client %s server %s", client, server);
251 if (name == NULL)
252 fatal("no matching mac found: client %s server %s", client, server);
411 if (strcmp(name, "hmac-md5") == 0) {
412 mac->md = EVP_md5();
413 } else if (strcmp(name, "hmac-sha1") == 0) {
414 mac->md = EVP_sha1();
415 } else if (strcmp(name, "hmac-ripemd160@openssh.com") == 0) {
416 mac->md = EVP_ripemd160();
417 } else {
253 if (mac_init(mac, name) < 0)
418 fatal("unsupported mac %s", name);
254 fatal("unsupported mac %s", name);
419 }
255 /* truncate the key */
256 if (datafellows & SSH_BUG_HMAC)
257 mac->key_len = 16;
420 mac->name = name;
258 mac->name = name;
421 mac->mac_len = mac->md->md_size;
422 mac->key_len = (datafellows & SSH_BUG_HMAC) ? 16 : mac->mac_len;
423 mac->key = NULL;
424 mac->enabled = 0;
425}
426void
427choose_comp(Comp *comp, char *client, char *server)
428{
259 mac->key = NULL;
260 mac->enabled = 0;
261}
262void
263choose_comp(Comp *comp, char *client, char *server)
264{
429 char *name = get_match(client, server);
265 char *name = match_list(client, server, NULL);
430 if (name == NULL)
431 fatal("no matching comp found: client %s server %s", client, server);
432 if (strcmp(name, "zlib") == 0) {
433 comp->type = 1;
434 } else if (strcmp(name, "none") == 0) {
435 comp->type = 0;
436 } else {
437 fatal("unsupported comp %s", name);
438 }
439 comp->name = name;
440}
441void
442choose_kex(Kex *k, char *client, char *server)
443{
266 if (name == NULL)
267 fatal("no matching comp found: client %s server %s", client, server);
268 if (strcmp(name, "zlib") == 0) {
269 comp->type = 1;
270 } else if (strcmp(name, "none") == 0) {
271 comp->type = 0;
272 } else {
273 fatal("unsupported comp %s", name);
274 }
275 comp->name = name;
276}
277void
278choose_kex(Kex *k, char *client, char *server)
279{
444 k->name = get_match(client, server);
280 k->name = match_list(client, server, NULL);
445 if (k->name == NULL)
446 fatal("no kex alg");
447 if (strcmp(k->name, KEX_DH1) == 0) {
448 k->kex_type = DH_GRP1_SHA1;
449 } else if (strcmp(k->name, KEX_DHGEX) == 0) {
450 k->kex_type = DH_GEX_SHA1;
451 } else
452 fatal("bad kex alg %s", k->name);
453}
454void
455choose_hostkeyalg(Kex *k, char *client, char *server)
456{
281 if (k->name == NULL)
282 fatal("no kex alg");
283 if (strcmp(k->name, KEX_DH1) == 0) {
284 k->kex_type = DH_GRP1_SHA1;
285 } else if (strcmp(k->name, KEX_DHGEX) == 0) {
286 k->kex_type = DH_GEX_SHA1;
287 } else
288 fatal("bad kex alg %s", k->name);
289}
290void
291choose_hostkeyalg(Kex *k, char *client, char *server)
292{
457 k->hostkeyalg = get_match(client, server);
458 if (k->hostkeyalg == NULL)
293 char *hostkeyalg = match_list(client, server, NULL);
294 if (hostkeyalg == NULL)
459 fatal("no hostkey alg");
295 fatal("no hostkey alg");
460 if (strcmp(k->hostkeyalg, KEX_DSS) != 0)
461 fatal("bad hostkey alg %s", k->hostkeyalg);
296 k->hostkey_type = key_type_from_name(hostkeyalg);
297 if (k->hostkey_type == KEY_UNSPEC)
298 fatal("bad hostkey alg '%s'", hostkeyalg);
299 xfree(hostkeyalg);
462}
463
300}
301
464Kex *
465kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server)
302void
303kex_choose_conf(Kex *kex)
466{
304{
305 Newkeys *newkeys;
306 char **my, **peer;
307 char **cprop, **sprop;
308 int nenc, nmac, ncomp;
467 int mode;
468 int ctos; /* direction: if true client-to-server */
469 int need;
309 int mode;
310 int ctos; /* direction: if true client-to-server */
311 int need;
470 Kex *k;
471
312
472 k = xmalloc(sizeof(*k));
473 memset(k, 0, sizeof(*k));
474 k->server = server;
313 my = kex_buf2prop(&kex->my);
314 peer = kex_buf2prop(&kex->peer);
475
315
316 if (kex->server) {
317 cprop=peer;
318 sprop=my;
319 } else {
320 cprop=my;
321 sprop=peer;
322 }
323
324 /* Algorithm Negotiation */
476 for (mode = 0; mode < MODE_MAX; mode++) {
325 for (mode = 0; mode < MODE_MAX; mode++) {
477 int nenc, nmac, ncomp;
478 ctos = (!k->server && mode == MODE_OUT) || (k->server && mode == MODE_IN);
326 newkeys = xmalloc(sizeof(*newkeys));
327 memset(newkeys, 0, sizeof(*newkeys));
328 kex->newkeys[mode] = newkeys;
329 ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN);
479 nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC;
480 nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC;
481 ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
330 nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC;
331 nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC;
332 ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
482 choose_enc (&k->enc [mode], cprop[nenc], sprop[nenc]);
483 choose_mac (&k->mac [mode], cprop[nmac], sprop[nmac]);
484 choose_comp(&k->comp[mode], cprop[ncomp], sprop[ncomp]);
333 choose_enc (&newkeys->enc, cprop[nenc], sprop[nenc]);
334 choose_mac (&newkeys->mac, cprop[nmac], sprop[nmac]);
335 choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]);
485 debug("kex: %s %s %s %s",
486 ctos ? "client->server" : "server->client",
336 debug("kex: %s %s %s %s",
337 ctos ? "client->server" : "server->client",
487 k->enc[mode].name,
488 k->mac[mode].name,
489 k->comp[mode].name);
338 newkeys->enc.name,
339 newkeys->mac.name,
340 newkeys->comp.name);
490 }
341 }
491 choose_kex(k, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]);
492 choose_hostkeyalg(k, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
342 choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]);
343 choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
493 sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]);
494 need = 0;
495 for (mode = 0; mode < MODE_MAX; mode++) {
344 sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]);
345 need = 0;
346 for (mode = 0; mode < MODE_MAX; mode++) {
496 if (need < k->enc[mode].cipher->key_len)
497 need = k->enc[mode].cipher->key_len;
498 if (need < k->enc[mode].cipher->block_size)
499 need = k->enc[mode].cipher->block_size;
500 if (need < k->mac[mode].key_len)
501 need = k->mac[mode].key_len;
347 newkeys = kex->newkeys[mode];
348 if (need < newkeys->enc.cipher->key_len)
349 need = newkeys->enc.cipher->key_len;
350 if (need < newkeys->enc.cipher->block_size)
351 need = newkeys->enc.cipher->block_size;
352 if (need < newkeys->mac.key_len)
353 need = newkeys->mac.key_len;
502 }
503 /* XXX need runden? */
354 }
355 /* XXX need runden? */
504 k->we_need = need;
505 return k;
356 kex->we_need = need;
357
358 kex_prop_free(my);
359 kex_prop_free(peer);
506}
507
360}
361
508int
509kex_derive_keys(Kex *k, unsigned char *hash, BIGNUM *shared_secret)
362u_char *
363derive_key(Kex *kex, int id, int need, u_char *hash, BIGNUM *shared_secret)
510{
364{
511 int i;
512 int mode;
513 int ctos;
514 unsigned char *keys[NKEYS];
365 Buffer b;
366 EVP_MD *evp_md = EVP_sha1();
367 EVP_MD_CTX md;
368 char c = id;
369 int have;
370 int mdsz = evp_md->md_size;
371 u_char *digest = xmalloc(roundup(need, mdsz));
515
372
373 buffer_init(&b);
374 buffer_put_bignum2(&b, shared_secret);
375
376 /* K1 = HASH(K || H || "A" || session_id) */
377 EVP_DigestInit(&md, evp_md);
378 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
379 EVP_DigestUpdate(&md, hash, mdsz);
380 EVP_DigestUpdate(&md, &c, 1);
381 EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len);
382 EVP_DigestFinal(&md, digest, NULL);
383
384 /*
385 * expand key:
386 * Kn = HASH(K || H || K1 || K2 || ... || Kn-1)
387 * Key = K1 || K2 || ... || Kn
388 */
389 for (have = mdsz; need > have; have += mdsz) {
390 EVP_DigestInit(&md, evp_md);
391 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
392 EVP_DigestUpdate(&md, hash, mdsz);
393 EVP_DigestUpdate(&md, digest, have);
394 EVP_DigestFinal(&md, digest + have, NULL);
395 }
396 buffer_free(&b);
397#ifdef DEBUG_KEX
398 fprintf(stderr, "key '%c'== ", c);
399 dump_digest("key", digest, need);
400#endif
401 return digest;
402}
403
404Newkeys *current_keys[MODE_MAX];
405
406#define NKEYS 6
407void
408kex_derive_keys(Kex *kex, u_char *hash, BIGNUM *shared_secret)
409{
410 u_char *keys[NKEYS];
411 int i, mode, ctos;
412
516 for (i = 0; i < NKEYS; i++)
413 for (i = 0; i < NKEYS; i++)
517 keys[i] = derive_key('A'+i, k->we_need, hash, shared_secret);
414 keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, shared_secret);
518
415
416 debug("kex_derive_keys");
519 for (mode = 0; mode < MODE_MAX; mode++) {
417 for (mode = 0; mode < MODE_MAX; mode++) {
520 ctos = (!k->server && mode == MODE_OUT) || (k->server && mode == MODE_IN);
521 k->enc[mode].iv = keys[ctos ? 0 : 1];
522 k->enc[mode].key = keys[ctos ? 2 : 3];
523 k->mac[mode].key = keys[ctos ? 4 : 5];
418 current_keys[mode] = kex->newkeys[mode];
419 kex->newkeys[mode] = NULL;
420 ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN);
421 current_keys[mode]->enc.iv = keys[ctos ? 0 : 1];
422 current_keys[mode]->enc.key = keys[ctos ? 2 : 3];
423 current_keys[mode]->mac.key = keys[ctos ? 4 : 5];
524 }
424 }
525 return 0;
526}
425}
426
427Newkeys *
428kex_get_newkeys(int mode)
429{
430 Newkeys *ret;
431
432 ret = current_keys[mode];
433 current_keys[mode] = NULL;
434 return ret;
435}
436
437#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH)
438void
439dump_digest(char *msg, u_char *digest, int len)
440{
441 int i;
442
443 fprintf(stderr, "%s\n", msg);
444 for (i = 0; i< len; i++){
445 fprintf(stderr, "%02x", digest[i]);
446 if (i%32 == 31)
447 fprintf(stderr, "\n");
448 else if (i%8 == 7)
449 fprintf(stderr, " ");
450 }
451 fprintf(stderr, "\n");
452}
453#endif