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.
41 #include <openssl/bn.h>
42 #include <openssl/dh.h>
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>
53 kex_init(char *myproposal[PROPOSAL_MAX])
56 unsigned char cookie[16];
59 Buffer *ki = xmalloc(sizeof(*ki));
60 for (i = 0; i < 16; i++) {
63 cookie[i] = rand & 0xff;
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) */
75 /* diffie-hellman-group1-sha1 */
78 dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
81 int n = BN_num_bits(dh_pub);
84 /* we only accept g==2 */
85 if (!BN_is_word(dh->g, 2)) {
86 log("invalid DH base != 2");
90 log("invalid public DH value: negativ");
93 for (i = 0; i <= n; i++)
94 if (BN_is_bit_set(dh_pub, i))
96 debug("bits set: %d/%d", bits_set, BN_num_bits(dh->p));
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))
101 log("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p));
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";
120 ret = BN_hex2bn(&dh->p, group1);
126 BN_set_word(dh->g, 2);
128 if (DH_generate_key(dh) == 0)
129 fatal("DH_generate_key");
131 fatal("dh_new_group1: too many bad keys: giving up");
132 } while (!dh_pub_is_valid(dh, dh->pub_key));
137 bignum_print(BIGNUM *b)
139 BN_print_fp(stderr,b);
143 dump_digest(unsigned char *digest, int len)
146 for (i = 0; i< len; i++){
147 fprintf(stderr, "%02x", digest[i]);
149 fprintf(stderr, " ");
151 fprintf(stderr, "\n");
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)
166 static unsigned char digest[EVP_MAX_MD_SIZE];
167 EVP_MD *evp_md = EVP_sha1();
171 buffer_put_string(&b, client_version_string, strlen(client_version_string));
172 buffer_put_string(&b, server_version_string, strlen(server_version_string));
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);
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);
191 EVP_DigestInit(&md, evp_md);
192 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
193 EVP_DigestFinal(&md, digest, NULL);
198 dump_digest(digest, evp_md->md_size);
204 derive_key(int id, int need, char unsigned *hash, BIGNUM *shared_secret)
207 EVP_MD *evp_md = EVP_sha1();
211 int mdsz = evp_md->md_size;
212 unsigned char *digest = xmalloc(((need+mdsz-1)/mdsz)*mdsz);
215 buffer_put_bignum2(&b, shared_secret);
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);
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);
234 fprintf(stderr, "Digest '%c'== ", c);
235 dump_digest(digest, need);
246 get_match(char *client, char *server)
248 char *sproposals[MAX_PROP];
250 int i, j, nproposals;
252 for ((p = strtok(server, SEP)), i=0; p; (p = strtok(NULL, SEP)), i++) {
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)
268 choose_enc(Enc *enc, char *client, char *server)
270 char *name = get_match(client, server);
272 fatal("no matching cipher found: client %s server %s", client, server);
273 enc->type = cipher_number(name);
276 case SSH_CIPHER_3DES_CBC:
281 case SSH_CIPHER_BLOWFISH_CBC:
282 case SSH_CIPHER_CAST128_CBC:
287 case SSH_CIPHER_ARCFOUR:
293 fatal("unsupported cipher %s", name);
301 choose_mac(Mac *mac, char *client, char *server)
303 char *name = get_match(client, server);
305 fatal("no matching mac found: client %s server %s", client, server);
306 if (strcmp(name, "hmac-md5") == 0) {
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();
313 fatal("unsupported mac %s", name);
316 mac->mac_len = mac->md->md_size;
317 mac->key_len = (datafellows & SSH_BUG_HMAC) ? 16 : mac->mac_len;
322 choose_comp(Comp *comp, char *client, char *server)
324 char *name = get_match(client, server);
326 fatal("no matching comp found: client %s server %s", client, server);
327 if (strcmp(name, "zlib") == 0) {
329 } else if (strcmp(name, "none") == 0) {
332 fatal("unsupported comp %s", name);
337 choose_kex(Kex *k, char *client, char *server)
339 k->name = get_match(client, server);
342 if (strcmp(k->name, KEX_DH1) != 0)
343 fatal("bad kex alg %s", k->name);
346 choose_hostkeyalg(Kex *k, char *client, char *server)
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);
356 kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server)
360 int ctos; /* direction: if true client-to-server */
364 k = xmalloc(sizeof(*k));
365 memset(k, 0, sizeof(*k));
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",
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++) {
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;
401 k->we_need = WE_NEED;
407 kex_derive_keys(Kex *k, unsigned char *hash, BIGNUM *shared_secret)
412 unsigned char *keys[NKEYS];
414 for (i = 0; i < NKEYS; i++)
415 keys[i] = derive_key('A'+i, k->we_need, hash, shared_secret);
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];