diff options
author | kris <kris@FreeBSD.org> | 2001-02-12 06:44:51 +0000 |
---|---|---|
committer | kris <kris@FreeBSD.org> | 2001-02-12 06:44:51 +0000 |
commit | 94cb6038949d701e15fdcd8a3c53a7c4e6d18488 (patch) | |
tree | 7844f14a2a195a5bf5d54a9da68a9cf9a05b6a2b /crypto/openssh/sshd.c | |
parent | 8befe8802dfa82b634876d02d08448bd076b476b (diff) | |
download | FreeBSD-src-94cb6038949d701e15fdcd8a3c53a7c4e6d18488.zip FreeBSD-src-94cb6038949d701e15fdcd8a3c53a7c4e6d18488.tar.gz |
Patches backported from later development version of OpenSSH which prevent
(instead of just mitigating through connection limits) the Bleichenbacher
attack which can lead to guessing of the server key (not host key) by
regenerating it when an RSA failure is detected.
Reviewed by: rwatson
Diffstat (limited to 'crypto/openssh/sshd.c')
-rw-r--r-- | crypto/openssh/sshd.c | 54 |
1 files changed, 37 insertions, 17 deletions
diff --git a/crypto/openssh/sshd.c b/crypto/openssh/sshd.c index ad69883..5073465 100644 --- a/crypto/openssh/sshd.c +++ b/crypto/openssh/sshd.c @@ -1108,6 +1108,7 @@ do_ssh1_kex() { int i, len; int plen, slen; + int rsafail = 0; BIGNUM *session_key_int; unsigned char session_key[SSH_SESSION_KEY_LENGTH]; unsigned char cookie[8]; @@ -1229,7 +1230,7 @@ do_ssh1_kex() * with larger modulus first). */ if (BN_cmp(sensitive_data.private_key->n, sensitive_data.host_key->n) > 0) { - /* Private key has bigger modulus. */ + /* Server key has bigger modulus. */ if (BN_num_bits(sensitive_data.private_key->n) < BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED) { fatal("do_connection: %s: private_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d", @@ -1238,10 +1239,12 @@ do_ssh1_kex() BN_num_bits(sensitive_data.host_key->n), SSH_KEY_BITS_RESERVED); } - rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.private_key); - rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.host_key); + if (rsa_private_decrypt(session_key_int, session_key_int, + sensitive_data.private_key) <= 0) + rsafail++; + if (rsa_private_decrypt(session_key_int, session_key_int, + sensitive_data.host_key) <= 0) + rsafail++; } else { /* Host key has bigger modulus (or they are equal). */ if (BN_num_bits(sensitive_data.host_key->n) < @@ -1252,10 +1255,12 @@ do_ssh1_kex() BN_num_bits(sensitive_data.private_key->n), SSH_KEY_BITS_RESERVED); } - rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.host_key); - rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.private_key); + if (rsa_private_decrypt(session_key_int, session_key_int, + sensitive_data.host_key) < 0) + rsafail++; + if (rsa_private_decrypt(session_key_int, session_key_int, + sensitive_data.private_key) < 0) + rsafail++; } compute_session_id(session_id, cookie, @@ -1270,14 +1275,29 @@ do_ssh1_kex() * least significant 256 bits of the integer; the first byte of the * key is in the highest bits. */ - BN_mask_bits(session_key_int, sizeof(session_key) * 8); - len = BN_num_bytes(session_key_int); - if (len < 0 || len > sizeof(session_key)) - fatal("do_connection: bad len from %s: session_key_int %d > sizeof(session_key) %d", - get_remote_ipaddr(), - len, sizeof(session_key)); - memset(session_key, 0, sizeof(session_key)); - BN_bn2bin(session_key_int, session_key + sizeof(session_key) - len); + if (!rsafail) { + BN_mask_bits(session_key_int, sizeof(session_key) * 8); + len = BN_num_bytes(session_key_int); + if (len < 0 || len > sizeof(session_key)) { + error("do_connection: bad session key len from %s: " + "session_key_int %d > sizeof(session_key) %d", + get_remote_ipaddr(), len, sizeof(session_key)); + rsafail++; + } else { + memset(session_key, 0, sizeof(session_key)); + BN_bn2bin(session_key_int, + session_key + sizeof(session_key) - len); + } + } + if (rsafail) { + log("do_connection: generating a fake encryption key"); + for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) { + if (i % 4 == 0) + rand = arc4random(); + session_key[i] = rand & 0xff; + rand >>= 8; + } + } /* Destroy the decrypted integer. It is no longer needed. */ BN_clear_free(session_key_int); |