]> andersk Git - openssh.git/blob - kex.c
- OpenBSD CVS update
[openssh.git] / kex.c
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  * 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.
12  * 3. All advertising materials mentioning features or use of this software
13  *    must display the following acknowledgement:
14  *      This product includes software developed by Markus Friedl.
15  * 4. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "includes.h"
31 RCSID("$Id$");
32
33 #include "ssh.h"
34 #include "ssh2.h"
35 #include "xmalloc.h"
36 #include "buffer.h"
37 #include "bufaux.h"
38 #include "cipher.h"
39 #include "compat.h"
40
41 #include <openssl/bn.h>
42 #include <openssl/dh.h>
43
44 #include <openssl/crypto.h>
45 #include <openssl/bio.h>
46 #include <openssl/bn.h>
47 #include <openssl/dh.h>
48 #include <openssl/pem.h>
49
50 #include "kex.h"
51
52 Buffer *
53 kex_init(char *myproposal[PROPOSAL_MAX])
54 {
55         char c = 0;
56         unsigned char cookie[16];
57         u_int32_t rand = 0;
58         int i;
59         Buffer *ki = xmalloc(sizeof(*ki));
60         for (i = 0; i < 16; i++) {
61                 if (i % 4 == 0)
62                         rand = arc4random();
63                 cookie[i] = rand & 0xff;
64                 rand >>= 8;
65         }
66         buffer_init(ki);
67         buffer_append(ki, (char *)cookie, sizeof cookie);
68         for (i = 0; i < PROPOSAL_MAX; i++)
69                 buffer_put_cstring(ki, myproposal[i]);
70         buffer_append(ki, &c, 1); /* boolean   first_kex_packet_follows */
71         buffer_put_int(ki, 0);    /* uint32    0 (reserved for future extension) */
72         return ki;
73 }
74
75 /* diffie-hellman-group1-sha1 */
76
77 int
78 dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
79 {
80         int i;
81         int n = BN_num_bits(dh_pub);
82         int bits_set = 0;
83
84         /* we only accept g==2 */
85         if (!BN_is_word(dh->g, 2)) {
86                 log("invalid DH base != 2");
87                 return 0;
88         }
89         if (dh_pub->neg) {
90                 log("invalid public DH value: negativ");
91                 return 0;
92         }
93         for (i = 0; i <= n; i++)
94                 if (BN_is_bit_set(dh_pub, i))
95                         bits_set++;
96         debug("bits set: %d/%d", bits_set, BN_num_bits(dh->p));
97
98         /* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */
99         if (bits_set > 1 && (BN_cmp(dh_pub, dh->p) == -1))
100                 return 1;
101         log("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p));
102         return 0;
103 }
104
105 DH *
106 dh_new_group1()
107 {
108         static char *group1 =
109             "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
110             "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
111             "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
112             "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
113             "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
114             "FFFFFFFF" "FFFFFFFF";
115         DH *dh;
116         int ret, tries = 0;
117         dh = DH_new();
118         if(dh == NULL)
119                 fatal("DH_new");
120         ret = BN_hex2bn(&dh->p, group1);
121         if(ret<0)
122                 fatal("BN_hex2bn");
123         dh->g = BN_new();
124         if(dh->g == NULL)
125                 fatal("DH_new g");
126         BN_set_word(dh->g, 2);
127         do {
128                 if (DH_generate_key(dh) == 0)
129                         fatal("DH_generate_key");
130                 if (tries++ > 10)
131                         fatal("dh_new_group1: too many bad keys: giving up");
132         } while (!dh_pub_is_valid(dh, dh->pub_key));
133         return dh;
134 }
135
136 void
137 bignum_print(BIGNUM *b)
138 {
139         BN_print_fp(stderr,b);
140 }
141
142 void
143 dump_digest(unsigned char *digest, int len)
144 {
145         int i;
146         for (i = 0; i< len; i++){
147                 fprintf(stderr, "%02x", digest[i]);
148                 if(i%2!=0)
149                         fprintf(stderr, " ");
150         }
151         fprintf(stderr, "\n");
152 }
153
154 unsigned char *
155 kex_hash(
156     char *client_version_string,
157     char *server_version_string,
158     char *ckexinit, int ckexinitlen,
159     char *skexinit, int skexinitlen,
160     char *serverhostkeyblob, int sbloblen,
161     BIGNUM *client_dh_pub,
162     BIGNUM *server_dh_pub,
163     BIGNUM *shared_secret)
164 {
165         Buffer b;
166         static unsigned char digest[EVP_MAX_MD_SIZE];
167         EVP_MD *evp_md = EVP_sha1();
168         EVP_MD_CTX md;
169
170         buffer_init(&b);
171         buffer_put_string(&b, client_version_string, strlen(client_version_string));
172         buffer_put_string(&b, server_version_string, strlen(server_version_string));
173
174         /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
175         buffer_put_int(&b, ckexinitlen+1);
176         buffer_put_char(&b, SSH2_MSG_KEXINIT);
177         buffer_append(&b, ckexinit, ckexinitlen);
178         buffer_put_int(&b, skexinitlen+1);
179         buffer_put_char(&b, SSH2_MSG_KEXINIT);
180         buffer_append(&b, skexinit, skexinitlen);
181
182         buffer_put_string(&b, serverhostkeyblob, sbloblen);
183         buffer_put_bignum2(&b, client_dh_pub);
184         buffer_put_bignum2(&b, server_dh_pub);
185         buffer_put_bignum2(&b, shared_secret);
186         
187 #ifdef DEBUG_KEX
188         buffer_dump(&b);
189 #endif
190
191         EVP_DigestInit(&md, evp_md);
192         EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
193         EVP_DigestFinal(&md, digest, NULL);
194
195         buffer_free(&b);
196
197 #ifdef DEBUG_KEX
198         dump_digest(digest, evp_md->md_size);
199 #endif
200         return digest;
201 }
202
203 unsigned char *
204 derive_key(int id, int need, char unsigned *hash, BIGNUM *shared_secret)
205 {
206         Buffer b;
207         EVP_MD *evp_md = EVP_sha1();
208         EVP_MD_CTX md;
209         char c = id;
210         int have;
211         int mdsz = evp_md->md_size;
212         unsigned char *digest = xmalloc(((need+mdsz-1)/mdsz)*mdsz);
213
214         buffer_init(&b);
215         buffer_put_bignum2(&b, shared_secret);
216
217         EVP_DigestInit(&md, evp_md);
218         EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));  /* shared_secret K */
219         EVP_DigestUpdate(&md, hash, mdsz);              /* transport-06 */
220         EVP_DigestUpdate(&md, &c, 1);                   /* key id */
221         EVP_DigestUpdate(&md, hash, mdsz);              /* session id */
222         EVP_DigestFinal(&md, digest, NULL);
223
224         /* expand */
225         for (have = mdsz; need > have; have += mdsz) {
226                 EVP_DigestInit(&md, evp_md);
227                 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
228                 EVP_DigestUpdate(&md, hash, mdsz);
229                 EVP_DigestUpdate(&md, digest, have);
230                 EVP_DigestFinal(&md, digest + have, NULL);
231         }
232         buffer_free(&b);
233 #ifdef DEBUG_KEX
234         fprintf(stderr, "Digest '%c'== ", c);
235         dump_digest(digest, need);
236 #endif
237         return digest;
238 }
239
240 #define NKEYS   6
241
242 #define MAX_PROP        20
243 #define SEP     ","
244
245 char *
246 get_match(char *client, char *server)
247 {
248         char *sproposals[MAX_PROP];
249         char *p;
250         int i, j, nproposals;
251
252         for ((p = strtok(server, SEP)), i=0; p; (p = strtok(NULL, SEP)), i++) {
253                 if (i < MAX_PROP)
254                         sproposals[i] = p;
255                 else
256                         break;
257         }
258         nproposals = i;
259
260         for ((p = strtok(client, SEP)), i=0; p; (p = strtok(NULL, SEP)), i++) {
261                 for (j = 0; j < nproposals; j++)
262                         if (strcmp(p, sproposals[j]) == 0)
263                                 return xstrdup(p);
264         }
265         return NULL;
266 }
267 void
268 choose_enc(Enc *enc, char *client, char *server)
269 {
270         char *name = get_match(client, server);
271         if (name == NULL)
272                 fatal("no matching cipher found: client %s server %s", client, server);
273         enc->type = cipher_number(name);
274
275         switch (enc->type) {
276         case SSH_CIPHER_3DES_CBC:
277                 enc->key_len = 24;
278                 enc->iv_len = 8;
279                 enc->block_size = 8;
280                 break;
281         case SSH_CIPHER_BLOWFISH_CBC:
282         case SSH_CIPHER_CAST128_CBC:
283                 enc->key_len = 16;
284                 enc->iv_len = 8;
285                 enc->block_size = 8;
286                 break;
287         case SSH_CIPHER_ARCFOUR:
288                 enc->key_len = 16;
289                 enc->iv_len = 0;
290                 enc->block_size = 8;
291                 break;
292         default:
293                 fatal("unsupported cipher %s", name);
294         }
295         enc->name = name;
296         enc->enabled = 0;
297         enc->iv = NULL;
298         enc->key = NULL;
299 }
300 void
301 choose_mac(Mac *mac, char *client, char *server)
302 {
303         char *name = get_match(client, server);
304         if (name == NULL)
305                 fatal("no matching mac found: client %s server %s", client, server);
306         if (strcmp(name, "hmac-md5") == 0) {
307                 mac->md = EVP_md5();
308         } else if (strcmp(name, "hmac-sha1") == 0) {
309                 mac->md = EVP_sha1();
310         } else if (strcmp(name, "hmac-ripemd160@openssh.com") == 0) {
311                 mac->md = EVP_ripemd160();
312         } else {
313                 fatal("unsupported mac %s", name);
314         }
315         mac->name = name;
316         mac->mac_len = mac->md->md_size;
317         mac->key_len = (datafellows & SSH_BUG_HMAC) ? 16 : mac->mac_len;
318         mac->key = NULL;
319         mac->enabled = 0;
320 }
321 void
322 choose_comp(Comp *comp, char *client, char *server)
323 {
324         char *name = get_match(client, server);
325         if (name == NULL)
326                 fatal("no matching comp found: client %s server %s", client, server);
327         if (strcmp(name, "zlib") == 0) {
328                 comp->type = 1;
329         } else if (strcmp(name, "none") == 0) {
330                 comp->type = 0;
331         } else {
332                 fatal("unsupported comp %s", name);
333         }
334         comp->name = name;
335 }
336 void
337 choose_kex(Kex *k, char *client, char *server)
338 {
339         k->name = get_match(client, server);
340         if (k->name == NULL)
341                 fatal("no kex alg");
342         if (strcmp(k->name, KEX_DH1) != 0)
343                 fatal("bad kex alg %s", k->name);
344 }
345 void
346 choose_hostkeyalg(Kex *k, char *client, char *server)
347 {
348         k->hostkeyalg = get_match(client, server);
349         if (k->hostkeyalg == NULL)
350                 fatal("no hostkey alg");
351         if (strcmp(k->hostkeyalg, KEX_DSS) != 0)
352                 fatal("bad hostkey alg %s", k->hostkeyalg);
353 }
354
355 Kex *
356 kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server)
357 {
358         int i;
359         int mode;
360         int ctos;                               /* direction: if true client-to-server */
361         int need;
362         Kex *k;
363
364         k = xmalloc(sizeof(*k));
365         memset(k, 0, sizeof(*k));
366         k->server = server;
367
368         for (mode = 0; mode < MODE_MAX; mode++) {
369                 int nenc, nmac, ncomp;
370                 ctos = (!k->server && mode == MODE_OUT) || (k->server && mode == MODE_IN);
371                 nenc  = ctos ? PROPOSAL_ENC_ALGS_CTOS  : PROPOSAL_ENC_ALGS_STOC;
372                 nmac  = ctos ? PROPOSAL_MAC_ALGS_CTOS  : PROPOSAL_MAC_ALGS_STOC;
373                 ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
374                 choose_enc (&k->enc [mode], cprop[nenc],  sprop[nenc]);
375                 choose_mac (&k->mac [mode], cprop[nmac],  sprop[nmac]);
376                 choose_comp(&k->comp[mode], cprop[ncomp], sprop[ncomp]);
377                 debug("kex: %s %s %s %s",
378                     ctos ? "client->server" : "server->client",
379                     k->enc[mode].name,
380                     k->mac[mode].name,
381                     k->comp[mode].name);
382         }
383         choose_kex(k, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]);
384         choose_hostkeyalg(k, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
385             sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]);
386         for (i = 0; i < PROPOSAL_MAX; i++) {
387                 xfree(cprop[i]);
388                 xfree(sprop[i]);
389         }
390         need = 0;
391         for (mode = 0; mode < MODE_MAX; mode++) {
392             if (need < k->enc[mode].key_len)
393                     need = k->enc[mode].key_len;
394             if (need < k->enc[mode].iv_len)
395                     need = k->enc[mode].iv_len;
396             if (need < k->mac[mode].key_len)
397                     need = k->mac[mode].key_len;
398         }
399         /* need runden? */
400 #define WE_NEED 32
401         k->we_need = WE_NEED;
402         k->we_need = need;
403         return k;
404 }
405
406 int
407 kex_derive_keys(Kex *k, unsigned char *hash, BIGNUM *shared_secret)
408 {
409         int i;
410         int mode;
411         int ctos;
412         unsigned char *keys[NKEYS];
413
414         for (i = 0; i < NKEYS; i++)
415                 keys[i] = derive_key('A'+i, k->we_need, hash, shared_secret);
416
417         for (mode = 0; mode < MODE_MAX; mode++) {
418                 ctos = (!k->server && mode == MODE_OUT) || (k->server && mode == MODE_IN);
419                 k->enc[mode].iv  = keys[ctos ? 0 : 1];
420                 k->enc[mode].key = keys[ctos ? 2 : 3];
421                 k->mac[mode].key = keys[ctos ? 4 : 5];
422         }
423         return 0;
424 }
This page took 0.062656 seconds and 5 git commands to generate.