aboutsummaryrefslogtreecommitdiff
path: root/crypto
diff options
context:
space:
mode:
authorKris Kennaway <kris@FreeBSD.org>2001-02-12 06:44:51 +0000
committerKris Kennaway <kris@FreeBSD.org>2001-02-12 06:44:51 +0000
commita09221f83c403c7842e4be74e134de476cdf6b87 (patch)
tree1649df033bb3c73f3a25bc9376da66627be995ae /crypto
parentf1a87e83ee5ba03ffd3ae3fda4b3ee089095720e (diff)
downloadsrc-a09221f83c403c7842e4be74e134de476cdf6b87.tar.gz
src-a09221f83c403c7842e4be74e134de476cdf6b87.zip
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
Notes
Notes: svn path=/head/; revision=72397
Diffstat (limited to 'crypto')
-rw-r--r--crypto/openssh/rsa.c13
-rw-r--r--crypto/openssh/rsa.h2
-rw-r--r--crypto/openssh/ssh-agent.c3
-rw-r--r--crypto/openssh/sshconnect1.c9
-rw-r--r--crypto/openssh/sshd.c54
5 files changed, 53 insertions, 28 deletions
diff --git a/crypto/openssh/rsa.c b/crypto/openssh/rsa.c
index 21eec8f482d0..3dabac1aab42 100644
--- a/crypto/openssh/rsa.c
+++ b/crypto/openssh/rsa.c
@@ -161,7 +161,7 @@ rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
xfree(inbuf);
}
-void
+int
rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
{
unsigned char *inbuf, *outbuf;
@@ -175,15 +175,16 @@ rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
BN_bn2bin(in, inbuf);
if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key,
- RSA_PKCS1_PADDING)) <= 0)
- fatal("rsa_private_decrypt() failed.");
-
- BN_bin2bn(outbuf, len, out);
-
+ RSA_PKCS1_PADDING)) <= 0) {
+ error("rsa_private_decrypt() failed");
+ } else {
+ BN_bin2bn(outbuf, len, out);
+ }
memset(outbuf, 0, olen);
memset(inbuf, 0, ilen);
xfree(outbuf);
xfree(inbuf);
+ return len;
}
/* Set whether to output verbose messages during key generation. */
diff --git a/crypto/openssh/rsa.h b/crypto/openssh/rsa.h
index e8e380356176..152aa9af0ec2 100644
--- a/crypto/openssh/rsa.h
+++ b/crypto/openssh/rsa.h
@@ -32,6 +32,6 @@ void rsa_set_verbose __P((int verbose));
int rsa_alive __P((void));
void rsa_public_encrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
-void rsa_private_decrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
+int rsa_private_decrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
#endif /* RSA_H */
diff --git a/crypto/openssh/ssh-agent.c b/crypto/openssh/ssh-agent.c
index f115d988a284..bbd6a782874a 100644
--- a/crypto/openssh/ssh-agent.c
+++ b/crypto/openssh/ssh-agent.c
@@ -194,7 +194,8 @@ process_authentication_challenge1(SocketEntry *e)
private = lookup_private_key(key, NULL, 1);
if (private != NULL) {
/* Decrypt the challenge using the private key. */
- rsa_private_decrypt(challenge, challenge, private->rsa);
+ if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0)
+ goto failure;
/* The response is MD5 of decrypted challenge plus session id. */
len = BN_num_bytes(challenge);
diff --git a/crypto/openssh/sshconnect1.c b/crypto/openssh/sshconnect1.c
index 96439c467695..5ae46e0fa0a5 100644
--- a/crypto/openssh/sshconnect1.c
+++ b/crypto/openssh/sshconnect1.c
@@ -152,14 +152,17 @@ respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv)
int i, len;
/* Decrypt the challenge using the private key. */
- rsa_private_decrypt(challenge, challenge, prv);
+ /* XXX think about Bleichenbacher, too */
+ if (rsa_private_decrypt(challenge, challenge, prv) <= 0)
+ packet_disconnect(
+ "respond_to_rsa_challenge: rsa_private_decrypt failed");
/* Compute the response. */
/* The response is MD5 of decrypted challenge plus session id. */
len = BN_num_bytes(challenge);
if (len <= 0 || len > sizeof(buf))
- packet_disconnect("respond_to_rsa_challenge: bad challenge length %d",
- len);
+ packet_disconnect(
+ "respond_to_rsa_challenge: bad challenge length %d", len);
memset(buf, 0, sizeof(buf));
BN_bn2bin(challenge, buf + sizeof(buf) - len);
diff --git a/crypto/openssh/sshd.c b/crypto/openssh/sshd.c
index ad69883f0ff1..5073465cd992 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);