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.
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.
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.
42 # include <openssl/bn.h>
43 # include <openssl/dh.h>
44 # include <openssl/crypto.h>
45 # include <openssl/bio.h>
46 # include <openssl/pem.h>
47 #endif /* HAVE_OPENSSL */
51 # include <ssl/crypto.h>
59 kex_init(char *myproposal[PROPOSAL_MAX])
62 unsigned char cookie[16];
65 Buffer *ki = xmalloc(sizeof(*ki));
66 for (i = 0; i < 16; i++) {
69 cookie[i] = rand & 0xff;
73 buffer_append(ki, (char *)cookie, sizeof cookie);
74 for (i = 0; i < PROPOSAL_MAX; i++)
75 buffer_put_cstring(ki, myproposal[i]);
76 buffer_append(ki, &c, 1); /* boolean first_kex_packet_follows */
77 buffer_put_int(ki, 0); /* uint32 0 (reserved for future extension) */
81 /* diffie-hellman-group1-sha1 */
84 dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
87 int n = BN_num_bits(dh_pub);
90 /* we only accept g==2 */
91 if (!BN_is_word(dh->g, 2)) {
92 log("invalid DH base != 2");
96 log("invalid public DH value: negativ");
99 for (i = 0; i <= n; i++)
100 if (BN_is_bit_set(dh_pub, i))
102 debug("bits set: %d/%d", bits_set, BN_num_bits(dh->p));
104 /* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */
105 if (bits_set > 1 && (BN_cmp(dh_pub, dh->p) == -1))
107 log("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p));
114 static char *group1 =
115 "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
116 "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
117 "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
118 "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
119 "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
120 "FFFFFFFF" "FFFFFFFF";
126 ret = BN_hex2bn(&dh->p, group1);
132 BN_set_word(dh->g, 2);
134 if (DH_generate_key(dh) == 0)
135 fatal("DH_generate_key");
137 fatal("dh_new_group1: too many bad keys: giving up");
138 } while (!dh_pub_is_valid(dh, dh->pub_key));
143 bignum_print(BIGNUM *b)
145 BN_print_fp(stderr,b);
149 dump_digest(unsigned char *digest, int len)
152 for (i = 0; i< len; i++){
153 fprintf(stderr, "%02x", digest[i]);
155 fprintf(stderr, " ");
157 fprintf(stderr, "\n");
162 char *client_version_string,
163 char *server_version_string,
164 char *ckexinit, int ckexinitlen,
165 char *skexinit, int skexinitlen,
166 char *serverhostkeyblob, int sbloblen,
167 BIGNUM *client_dh_pub,
168 BIGNUM *server_dh_pub,
169 BIGNUM *shared_secret)
172 static unsigned char digest[EVP_MAX_MD_SIZE];
173 EVP_MD *evp_md = EVP_sha1();
177 buffer_put_string(&b, client_version_string, strlen(client_version_string));
178 buffer_put_string(&b, server_version_string, strlen(server_version_string));
180 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
181 buffer_put_int(&b, ckexinitlen+1);
182 buffer_put_char(&b, SSH2_MSG_KEXINIT);
183 buffer_append(&b, ckexinit, ckexinitlen);
184 buffer_put_int(&b, skexinitlen+1);
185 buffer_put_char(&b, SSH2_MSG_KEXINIT);
186 buffer_append(&b, skexinit, skexinitlen);
188 buffer_put_string(&b, serverhostkeyblob, sbloblen);
189 buffer_put_bignum2(&b, client_dh_pub);
190 buffer_put_bignum2(&b, server_dh_pub);
191 buffer_put_bignum2(&b, shared_secret);
197 EVP_DigestInit(&md, evp_md);
198 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
199 EVP_DigestFinal(&md, digest, NULL);
204 dump_digest(digest, evp_md->md_size);
210 derive_key(int id, int need, char unsigned *hash, BIGNUM *shared_secret)
213 EVP_MD *evp_md = EVP_sha1();
217 int mdsz = evp_md->md_size;
218 unsigned char *digest = xmalloc(((need+mdsz-1)/mdsz)*mdsz);
221 buffer_put_bignum2(&b, shared_secret);
223 EVP_DigestInit(&md, evp_md);
224 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); /* shared_secret K */
225 EVP_DigestUpdate(&md, hash, mdsz); /* transport-06 */
226 EVP_DigestUpdate(&md, &c, 1); /* key id */
227 EVP_DigestUpdate(&md, hash, mdsz); /* session id */
228 EVP_DigestFinal(&md, digest, NULL);
231 for (have = mdsz; need > have; have += mdsz) {
232 EVP_DigestInit(&md, evp_md);
233 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
234 EVP_DigestUpdate(&md, hash, mdsz);
235 EVP_DigestUpdate(&md, digest, have);
236 EVP_DigestFinal(&md, digest + have, NULL);
240 fprintf(stderr, "Digest '%c'== ", c);
241 dump_digest(digest, need);
252 get_match(char *client, char *server)
254 char *sproposals[MAX_PROP];
256 int i, j, nproposals;
258 for ((p = strtok(server, SEP)), i=0; p; (p = strtok(NULL, SEP)), i++) {
266 for ((p = strtok(client, SEP)), i=0; p; (p = strtok(NULL, SEP)), i++) {
267 for (j = 0; j < nproposals; j++)
268 if (strcmp(p, sproposals[j]) == 0)
274 choose_enc(Enc *enc, char *client, char *server)
276 char *name = get_match(client, server);
278 fatal("no matching cipher found: client %s server %s", client, server);
279 enc->type = cipher_number(name);
282 case SSH_CIPHER_3DES_CBC:
287 case SSH_CIPHER_BLOWFISH_CBC:
288 case SSH_CIPHER_CAST128_CBC:
293 case SSH_CIPHER_ARCFOUR:
299 fatal("unsupported cipher %s", name);
307 choose_mac(Mac *mac, char *client, char *server)
309 char *name = get_match(client, server);
311 fatal("no matching mac found: client %s server %s", client, server);
312 if (strcmp(name, "hmac-md5") == 0) {
314 } else if (strcmp(name, "hmac-sha1") == 0) {
315 mac->md = EVP_sha1();
316 } else if (strcmp(name, "hmac-ripemd160@openssh.com") == 0) {
317 mac->md = EVP_ripemd160();
319 fatal("unsupported mac %s", name);
322 mac->mac_len = mac->md->md_size;
323 mac->key_len = datafellows ? 16 : mac->mac_len;
328 choose_comp(Comp *comp, char *client, char *server)
330 char *name = get_match(client, server);
332 fatal("no matching comp found: client %s server %s", client, server);
333 if (strcmp(name, "zlib") == 0) {
335 } else if (strcmp(name, "none") == 0) {
338 fatal("unsupported comp %s", name);
343 choose_kex(Kex *k, char *client, char *server)
345 k->name = get_match(client, server);
348 if (strcmp(k->name, KEX_DH1) != 0)
349 fatal("bad kex alg %s", k->name);
352 choose_hostkeyalg(Kex *k, char *client, char *server)
354 k->hostkeyalg = get_match(client, server);
355 if (k->hostkeyalg == NULL)
356 fatal("no hostkey alg");
357 if (strcmp(k->hostkeyalg, KEX_DSS) != 0)
358 fatal("bad hostkey alg %s", k->hostkeyalg);
362 kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server)
366 int ctos; /* direction: if true client-to-server */
370 k = xmalloc(sizeof(*k));
371 memset(k, 0, sizeof(*k));
374 for (mode = 0; mode < MODE_MAX; mode++) {
375 int nenc, nmac, ncomp;
376 ctos = (!k->server && mode == MODE_OUT) || (k->server && mode == MODE_IN);
377 nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC;
378 nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC;
379 ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
380 choose_enc (&k->enc [mode], cprop[nenc], sprop[nenc]);
381 choose_mac (&k->mac [mode], cprop[nmac], sprop[nmac]);
382 choose_comp(&k->comp[mode], cprop[ncomp], sprop[ncomp]);
383 debug("kex: %s %s %s %s",
384 ctos ? "client->server" : "server->client",
389 choose_kex(k, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]);
390 choose_hostkeyalg(k, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
391 sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]);
392 for (i = 0; i < PROPOSAL_MAX; i++) {
397 for (mode = 0; mode < MODE_MAX; mode++) {
398 if (need < k->enc[mode].key_len)
399 need = k->enc[mode].key_len;
400 if (need < k->enc[mode].iv_len)
401 need = k->enc[mode].iv_len;
402 if (need < k->mac[mode].key_len)
403 need = k->mac[mode].key_len;
407 k->we_need = WE_NEED;
413 kex_derive_keys(Kex *k, unsigned char *hash, BIGNUM *shared_secret)
418 unsigned char *keys[NKEYS];
420 for (i = 0; i < NKEYS; i++)
421 keys[i] = derive_key('A'+i, k->we_need, hash, shared_secret);
423 for (mode = 0; mode < MODE_MAX; mode++) {
424 ctos = (!k->server && mode == MODE_OUT) || (k->server && mode == MODE_IN);
425 k->enc[mode].iv = keys[ctos ? 0 : 1];
426 k->enc[mode].key = keys[ctos ? 2 : 3];
427 k->mac[mode].key = keys[ctos ? 4 : 5];