summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2001-01-29 19:47:32 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2001-01-29 19:47:32 +0000
commit1fc5e1a14c4ba5dccd70fd6870a028c8a8d1f5f4 (patch)
tree1ddcd979ad0032f04569f4a98208ac97621f3568 /usr.bin
parent24f1c20ecb0c06b27d61876bf9523dd73847444e (diff)
handle rsa_private_decrypt failures; helps against the Bleichenbacher pkcs#1 attack
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/ssh/rsa.c15
-rw-r--r--usr.bin/ssh/rsa.h4
-rw-r--r--usr.bin/ssh/ssh-agent.c7
-rw-r--r--usr.bin/ssh/sshconnect1.c11
-rw-r--r--usr.bin/ssh/sshd.c57
5 files changed, 59 insertions, 35 deletions
diff --git a/usr.bin/ssh/rsa.c b/usr.bin/ssh/rsa.c
index 04bb239e532..1005246077b 100644
--- a/usr.bin/ssh/rsa.c
+++ b/usr.bin/ssh/rsa.c
@@ -60,7 +60,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: rsa.c,v 1.19 2001/01/21 19:05:54 markus Exp $");
+RCSID("$OpenBSD: rsa.c,v 1.20 2001/01/29 19:47:30 markus Exp $");
#include "rsa.h"
#include "log.h"
@@ -94,7 +94,7 @@ rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
xfree(inbuf);
}
-void
+int
rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
{
u_char *inbuf, *outbuf;
@@ -108,13 +108,14 @@ 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;
}
diff --git a/usr.bin/ssh/rsa.h b/usr.bin/ssh/rsa.h
index 57d72cc7892..713d3128191 100644
--- a/usr.bin/ssh/rsa.h
+++ b/usr.bin/ssh/rsa.h
@@ -11,7 +11,7 @@
* called by a name other than "ssh" or "Secure Shell".
*/
-/* RCSID("$OpenBSD: rsa.h,v 1.9 2000/11/12 19:50:38 markus Exp $"); */
+/* RCSID("$OpenBSD: rsa.h,v 1.10 2001/01/29 19:47:30 markus Exp $"); */
#ifndef RSA_H
#define RSA_H
@@ -20,6 +20,6 @@
#include <openssl/rsa.h>
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/usr.bin/ssh/ssh-agent.c b/usr.bin/ssh/ssh-agent.c
index 9eb1615c614..13555c546ee 100644
--- a/usr.bin/ssh/ssh-agent.c
+++ b/usr.bin/ssh/ssh-agent.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-agent.c,v 1.48 2001/01/25 08:06:33 deraadt Exp $ */
+/* $OpenBSD: ssh-agent.c,v 1.49 2001/01/29 19:47:31 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -37,7 +37,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: ssh-agent.c,v 1.48 2001/01/25 08:06:33 deraadt Exp $");
+RCSID("$OpenBSD: ssh-agent.c,v 1.49 2001/01/29 19:47:31 markus Exp $");
#include <openssl/evp.h>
#include <openssl/md5.h>
@@ -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/usr.bin/ssh/sshconnect1.c b/usr.bin/ssh/sshconnect1.c
index 5a5a2222752..e732806f3ff 100644
--- a/usr.bin/ssh/sshconnect1.c
+++ b/usr.bin/ssh/sshconnect1.c
@@ -13,7 +13,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: sshconnect1.c,v 1.20 2001/01/22 23:06:40 markus Exp $");
+RCSID("$OpenBSD: sshconnect1.c,v 1.21 2001/01/29 19:47:31 markus Exp $");
#include <openssl/bn.h>
#include <openssl/evp.h>
@@ -163,14 +163,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/usr.bin/ssh/sshd.c b/usr.bin/ssh/sshd.c
index d6ce689ba8d..c83db129cc6 100644
--- a/usr.bin/ssh/sshd.c
+++ b/usr.bin/ssh/sshd.c
@@ -40,7 +40,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: sshd.c,v 1.158 2001/01/28 10:37:26 markus Exp $");
+RCSID("$OpenBSD: sshd.c,v 1.159 2001/01/29 19:47:31 markus Exp $");
#include <openssl/dh.h>
#include <openssl/bn.h>
@@ -1162,6 +1162,7 @@ do_ssh1_kex(void)
{
int i, len;
int plen, slen;
+ int rsafail = 0;
BIGNUM *session_key_int;
u_char session_key[SSH_SESSION_KEY_LENGTH];
u_char cookie[8];
@@ -1272,7 +1273,7 @@ do_ssh1_kex(void)
* with larger modulus first).
*/
if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) {
- /* Private key has bigger modulus. */
+ /* Server key has bigger modulus. */
if (BN_num_bits(sensitive_data.server_key->rsa->n) <
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
@@ -1281,10 +1282,12 @@ do_ssh1_kex(void)
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
SSH_KEY_BITS_RESERVED);
}
- rsa_private_decrypt(session_key_int, session_key_int,
- sensitive_data.server_key->rsa);
- rsa_private_decrypt(session_key_int, session_key_int,
- sensitive_data.ssh1_host_key->rsa);
+ if (rsa_private_decrypt(session_key_int, session_key_int,
+ sensitive_data.server_key->rsa) <= 0)
+ rsafail++;
+ if (rsa_private_decrypt(session_key_int, session_key_int,
+ sensitive_data.ssh1_host_key->rsa) <= 0)
+ rsafail++;
} else {
/* Host key has bigger modulus (or they are equal). */
if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
@@ -1295,10 +1298,12 @@ do_ssh1_kex(void)
BN_num_bits(sensitive_data.server_key->rsa->n),
SSH_KEY_BITS_RESERVED);
}
- rsa_private_decrypt(session_key_int, session_key_int,
- sensitive_data.ssh1_host_key->rsa);
- rsa_private_decrypt(session_key_int, session_key_int,
- sensitive_data.server_key->rsa);
+ if (rsa_private_decrypt(session_key_int, session_key_int,
+ sensitive_data.ssh1_host_key->rsa) < 0)
+ rsafail++;
+ if (rsa_private_decrypt(session_key_int, session_key_int,
+ sensitive_data.server_key->rsa) < 0)
+ rsafail++;
}
compute_session_id(session_id, cookie,
@@ -1313,15 +1318,29 @@ do_ssh1_kex(void)
* 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);