From b845b1c682ef88b61bd7fecdfe140c101aa9f54d Mon Sep 17 00:00:00 2001 From: markus Date: Wed, 12 Apr 2000 07:03:05 +0000 Subject: [PATCH] check for reasonable public DH values --- usr.bin/ssh/kex.c | 46 ++++++++++++++++++++++++++++++++++------ usr.bin/ssh/kex.h | 3 ++- usr.bin/ssh/sshconnect.c | 7 ++++-- usr.bin/ssh/sshd.c | 6 ++++-- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/usr.bin/ssh/kex.c b/usr.bin/ssh/kex.c index cc2543a0ea1..2308c9398f5 100644 --- a/usr.bin/ssh/kex.c +++ b/usr.bin/ssh/kex.c @@ -28,7 +28,7 @@ */ #include "includes.h" -RCSID("$Id: kex.c,v 1.2 2000/04/12 06:37:02 markus Exp $"); +RCSID("$Id: kex.c,v 1.3 2000/04/12 07:03:05 markus Exp $"); #include "ssh.h" #include "ssh2.h" @@ -74,8 +74,36 @@ kex_init(char *myproposal[PROPOSAL_MAX]) /* diffie-hellman-group1-sha1 */ +int +dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) +{ + int i; + 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; + } + for (i = 0; i <= n; i++) + if (BN_is_bit_set(dh_pub, i)) + bits_set++; + debug("bits set: %d/%d", bits_set, BN_num_bits(dh->p)); + + /* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */ + if (bits_set > 1 && (BN_cmp(dh_pub, dh->p) == -1)) + return 1; + log("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p)); + return 0; +} + DH * -new_dh_group1() +dh_new_group1() { static char *group1 = "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" @@ -85,19 +113,23 @@ new_dh_group1() "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381" "FFFFFFFF" "FFFFFFFF"; DH *dh; - int ret; + int ret, tries = 0; dh = DH_new(); if(dh == NULL) fatal("DH_new"); - ret = BN_hex2bn(&dh->p,group1); + 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); - if (DH_generate_key(dh) == 0) - fatal("DH_generate_key"); + BN_set_word(dh->g, 2); + do { + if (DH_generate_key(dh) == 0) + fatal("DH_generate_key"); + if (tries++ > 10) + fatal("dh_new_group1: too many bad keys: giving up"); + } while (!dh_pub_is_valid(dh, dh->pub_key)); return dh; } diff --git a/usr.bin/ssh/kex.h b/usr.bin/ssh/kex.h index f9e79994888..5395ebc3f08 100644 --- a/usr.bin/ssh/kex.h +++ b/usr.bin/ssh/kex.h @@ -91,7 +91,8 @@ struct Kex { }; Buffer *kex_init(char *myproposal[PROPOSAL_MAX]); -DH *new_dh_group1(); +int dh_pub_is_valid(DH *dh, BIGNUM *dh_pub); +DH *dh_new_group1(); Kex *kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server); int kex_derive_keys(Kex *k, unsigned char *hash, BIGNUM *shared_secret); void bignum_print(BIGNUM *b); diff --git a/usr.bin/ssh/sshconnect.c b/usr.bin/ssh/sshconnect.c index 3391c33b640..e8b4f16b9ac 100644 --- a/usr.bin/ssh/sshconnect.c +++ b/usr.bin/ssh/sshconnect.c @@ -10,7 +10,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect.c,v 1.62 2000/04/12 06:36:48 markus Exp $"); +RCSID("$OpenBSD: sshconnect.c,v 1.63 2000/04/12 07:03:06 markus Exp $"); #include #include "xmalloc.h" @@ -1393,7 +1393,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) debug("Sending SSH2_MSG_KEXDH_INIT."); /* generate and send 'e', client DH public key */ - dh = new_dh_group1(); + dh = dh_new_group1(); packet_start(SSH2_MSG_KEXDH_INIT); packet_put_bignum2(dh->pub_key); packet_send(); @@ -1440,6 +1440,9 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) /* signed H */ signature = packet_get_string(&slen); + if (!dh_pub_is_valid(dh, dh_server_pub)) + packet_disconnect("bad server public DH value"); + klen = DH_size(dh); kbuf = xmalloc(klen); kout = DH_compute_key(kbuf, dh_server_pub, dh); diff --git a/usr.bin/ssh/sshd.c b/usr.bin/ssh/sshd.c index 7d8963ffa22..088da20c550 100644 --- a/usr.bin/ssh/sshd.c +++ b/usr.bin/ssh/sshd.c @@ -14,7 +14,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshd.c,v 1.100 2000/04/12 06:37:02 markus Exp $"); +RCSID("$OpenBSD: sshd.c,v 1.101 2000/04/12 07:03:06 markus Exp $"); #include "xmalloc.h" #include "rsa.h" @@ -1166,7 +1166,7 @@ do_ssh2_kex() #endif /* generate DH key */ - dh = new_dh_group1(); /* XXX depends on 'kex' */ + dh = dh_new_group1(); /* XXX depends on 'kex' */ #ifdef DEBUG_KEXDH fprintf(stderr, "\np= "); @@ -1177,6 +1177,8 @@ do_ssh2_kex() bignum_print(dh->pub_key); fprintf(stderr, "\n"); #endif + if (!dh_pub_is_valid(dh, dh_client_pub)) + packet_disconnect("bad client public DH value"); klen = DH_size(dh); kbuf = xmalloc(klen); -- 2.20.1