summaryrefslogtreecommitdiffstats
path: root/kex.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2000-10-14 16:23:11 +1100
committerDamien Miller <djm@mindrot.org>2000-10-14 16:23:11 +1100
commit874d77bb134a21a5cf625956b60173376a993ba8 (patch)
tree93dd73b2ff1fbf0ad5f3978a2c4e0d8438a0bf7c /kex.c
parent89d9796fbedef4eed6956a2c095c7cc25330c28d (diff)
- (djm) Big OpenBSD sync:
- markus@cvs.openbsd.org 2000/09/30 10:27:44 [log.c] allow loglevel debug - markus@cvs.openbsd.org 2000/10/03 11:59:57 [packet.c] hmac->mac - markus@cvs.openbsd.org 2000/10/03 12:03:03 [auth-krb4.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth1.c] move fake-auth from auth1.c to individual auth methods, disables s/key in debug-msg - markus@cvs.openbsd.org 2000/10/03 12:16:48 ssh.c do not resolve canonname, i have no idea why this was added oin ossh - markus@cvs.openbsd.org 2000/10/09 15:30:44 ssh-keygen.1 ssh-keygen.c -X now reads private ssh.com DSA keys, too. - markus@cvs.openbsd.org 2000/10/09 15:32:34 auth-options.c clear options on every call. - markus@cvs.openbsd.org 2000/10/09 15:51:00 authfd.c authfd.h interop with ssh-agent2, from <res@shore.net> - markus@cvs.openbsd.org 2000/10/10 14:20:45 compat.c use rexexp for version string matching - provos@cvs.openbsd.org 2000/10/10 22:02:18 [kex.c kex.h myproposal.h ssh.h ssh2.h sshconnect2.c sshd.c dh.c dh.h] First rough implementation of the diffie-hellman group exchange. The client can ask the server for bigger groups to perform the diffie-hellman in, thus increasing the attack complexity when using ciphers with longer keys. University of Windsor provided network, T the company. - markus@cvs.openbsd.org 2000/10/11 13:59:52 [auth-rsa.c auth2.c] clear auth options unless auth sucessfull - markus@cvs.openbsd.org 2000/10/11 14:00:27 [auth-options.h] clear auth options unless auth sucessfull - markus@cvs.openbsd.org 2000/10/11 14:03:27 [scp.1 scp.c] support 'scp -o' with help from mouring@pconline.com - markus@cvs.openbsd.org 2000/10/11 14:11:35 [dh.c] Wall - markus@cvs.openbsd.org 2000/10/11 14:14:40 [auth.h auth2.c readconf.c readconf.h readpass.c servconf.c servconf.h] [ssh.h sshconnect2.c sshd_config auth2-skey.c cli.c cli.h] add support for s/key (kbd-interactive) to ssh2, based on work by mkiernan@avantgo.com and me - markus@cvs.openbsd.org 2000/10/11 14:27:24 [auth.c auth1.c auth2.c authfile.c cipher.c cipher.h kex.c kex.h] [myproposal.h packet.c readconf.c session.c ssh.c ssh.h sshconnect1.c] [sshconnect2.c sshd.c] new cipher framework - markus@cvs.openbsd.org 2000/10/11 14:45:21 [cipher.c] remove DES - markus@cvs.openbsd.org 2000/10/12 03:59:20 [cipher.c cipher.h sshconnect1.c sshconnect2.c sshd.c] enable DES in SSH-1 clients only - markus@cvs.openbsd.org 2000/10/12 08:21:13 [kex.h packet.c] remove unused - markus@cvs.openbsd.org 2000/10/13 12:34:46 [sshd.c] Kludge for F-Secure Macintosh < 1.0.2; appro@fy.chalmers.se - markus@cvs.openbsd.org 2000/10/13 12:59:15 [cipher.c cipher.h myproposal.h rijndael.c rijndael.h] rijndael/aes support - markus@cvs.openbsd.org 2000/10/13 13:10:54 [sshd.8] more info about -V - markus@cvs.openbsd.org 2000/10/13 13:12:02 [myproposal.h] prefer no compression
Diffstat (limited to 'kex.c')
-rw-r--r--kex.c169
1 files changed, 115 insertions, 54 deletions
diff --git a/kex.c b/kex.c
index 8a83db47..68b9e522 100644
--- a/kex.c
+++ b/kex.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: kex.c,v 1.10 2000/09/07 20:27:51 deraadt Exp $");
+RCSID("$OpenBSD: kex.c,v 1.12 2000/10/11 20:27:23 markus Exp $");
#include "ssh.h"
#include "ssh2.h"
@@ -31,7 +31,6 @@ RCSID("$OpenBSD: kex.c,v 1.10 2000/09/07 20:27:51 deraadt Exp $");
#include "buffer.h"
#include "bufaux.h"
#include "packet.h"
-#include "cipher.h"
#include "compat.h"
#include <openssl/bn.h>
@@ -123,11 +122,6 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
int n = BN_num_bits(dh_pub);
int bits_set = 0;
- /* we only accept g==2 */
- if (!BN_is_word(dh->g, 2)) {
- log("invalid DH base != 2");
- return 0;
- }
if (dh_pub->neg) {
log("invalid public DH value: negativ");
return 0;
@@ -145,27 +139,10 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
}
DH *
-dh_new_group1()
+dh_gen_key(DH *dh)
{
- static char *group1 =
- "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
- "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
- "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
- "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
- "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
- "FFFFFFFF" "FFFFFFFF";
- DH *dh;
- int ret, tries = 0;
- dh = DH_new();
- if(dh == NULL)
- fatal("DH_new");
- ret = BN_hex2bn(&dh->p, group1);
- if(ret<0)
- fatal("BN_hex2bn");
- dh->g = BN_new();
- if(dh->g == NULL)
- fatal("DH_new g");
- BN_set_word(dh->g, 2);
+ int tries = 0;
+
do {
if (DH_generate_key(dh) == 0)
fatal("DH_generate_key");
@@ -175,6 +152,52 @@ dh_new_group1()
return dh;
}
+DH *
+dh_new_group_asc(const char *gen, const char *modulus)
+{
+ DH *dh;
+ int ret;
+
+ dh = DH_new();
+ if (dh == NULL)
+ fatal("DH_new");
+
+ if ((ret = BN_hex2bn(&dh->p, modulus)) < 0)
+ fatal("BN_hex2bn p");
+ if ((ret = BN_hex2bn(&dh->g, gen)) < 0)
+ fatal("BN_hex2bn g");
+
+ return (dh_gen_key(dh));
+}
+
+DH *
+dh_new_group(BIGNUM *gen, BIGNUM *modulus)
+{
+ DH *dh;
+
+ dh = DH_new();
+ if (dh == NULL)
+ fatal("DH_new");
+ dh->p = modulus;
+ dh->g = gen;
+
+ return (dh_gen_key(dh));
+}
+
+DH *
+dh_new_group1()
+{
+ static char *gen = "2", *group1 =
+ "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
+ "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
+ "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
+ "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
+ "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
+ "FFFFFFFF" "FFFFFFFF";
+
+ return (dh_new_group_asc(gen, group1));
+}
+
void
dump_digest(unsigned char *digest, int len)
{
@@ -237,6 +260,59 @@ kex_hash(
}
unsigned char *
+kex_hash_gex(
+ char *client_version_string,
+ char *server_version_string,
+ char *ckexinit, int ckexinitlen,
+ char *skexinit, int skexinitlen,
+ char *serverhostkeyblob, int sbloblen,
+ int minbits, BIGNUM *prime, BIGNUM *gen,
+ BIGNUM *client_dh_pub,
+ BIGNUM *server_dh_pub,
+ BIGNUM *shared_secret)
+{
+ Buffer b;
+ static unsigned char digest[EVP_MAX_MD_SIZE];
+ EVP_MD *evp_md = EVP_sha1();
+ EVP_MD_CTX md;
+
+ buffer_init(&b);
+ buffer_put_string(&b, client_version_string, strlen(client_version_string));
+ buffer_put_string(&b, server_version_string, strlen(server_version_string));
+
+ /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
+ buffer_put_int(&b, ckexinitlen+1);
+ buffer_put_char(&b, SSH2_MSG_KEXINIT);
+ buffer_append(&b, ckexinit, ckexinitlen);
+ buffer_put_int(&b, skexinitlen+1);
+ buffer_put_char(&b, SSH2_MSG_KEXINIT);
+ buffer_append(&b, skexinit, skexinitlen);
+
+ buffer_put_string(&b, serverhostkeyblob, sbloblen);
+ buffer_put_int(&b, minbits);
+ buffer_put_bignum2(&b, prime);
+ buffer_put_bignum2(&b, gen);
+ buffer_put_bignum2(&b, client_dh_pub);
+ buffer_put_bignum2(&b, server_dh_pub);
+ buffer_put_bignum2(&b, shared_secret);
+
+#ifdef DEBUG_KEX
+ buffer_dump(&b);
+#endif
+
+ EVP_DigestInit(&md, evp_md);
+ EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
+ EVP_DigestFinal(&md, digest, NULL);
+
+ buffer_free(&b);
+
+#ifdef DEBUG_KEX
+ dump_digest(digest, evp_md->md_size);
+#endif
+ return digest;
+}
+
+unsigned char *
derive_key(int id, int need, char unsigned *hash, BIGNUM *shared_secret)
{
Buffer b;
@@ -318,28 +394,9 @@ choose_enc(Enc *enc, char *client, char *server)
char *name = get_match(client, server);
if (name == NULL)
fatal("no matching cipher found: client %s server %s", client, server);
- enc->type = cipher_number(name);
-
- switch (enc->type) {
- case SSH_CIPHER_3DES_CBC:
- enc->key_len = 24;
- enc->iv_len = 8;
- enc->block_size = 8;
- break;
- case SSH_CIPHER_BLOWFISH_CBC:
- case SSH_CIPHER_CAST128_CBC:
- enc->key_len = 16;
- enc->iv_len = 8;
- enc->block_size = 8;
- break;
- case SSH_CIPHER_ARCFOUR:
- enc->key_len = 16;
- enc->iv_len = 0;
- enc->block_size = 8;
- break;
- default:
- fatal("unsupported cipher %s", name);
- }
+ enc->cipher = cipher_by_name(name);
+ if (enc->cipher == NULL)
+ fatal("matching cipher is not supported: %s", name);
enc->name = name;
enc->enabled = 0;
enc->iv = NULL;
@@ -387,7 +444,11 @@ choose_kex(Kex *k, char *client, char *server)
k->name = get_match(client, server);
if (k->name == NULL)
fatal("no kex alg");
- if (strcmp(k->name, KEX_DH1) != 0)
+ if (strcmp(k->name, KEX_DH1) == 0) {
+ k->kex_type = DH_GRP1_SHA1;
+ } else if (strcmp(k->name, KEX_DHGEX) == 0) {
+ k->kex_type = DH_GEX_SHA1;
+ } else
fatal("bad kex alg %s", k->name);
}
void
@@ -432,10 +493,10 @@ kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server
sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]);
need = 0;
for (mode = 0; mode < MODE_MAX; mode++) {
- if (need < k->enc[mode].key_len)
- need = k->enc[mode].key_len;
- if (need < k->enc[mode].iv_len)
- need = k->enc[mode].iv_len;
+ if (need < k->enc[mode].cipher->key_len)
+ need = k->enc[mode].cipher->key_len;
+ if (need < k->enc[mode].cipher->block_size)
+ need = k->enc[mode].cipher->block_size;
if (need < k->mac[mode].key_len)
need = k->mac[mode].key_len;
}