summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2001-01-30 09:27:26 +1100
committerDamien Miller <djm@mindrot.org>2001-01-30 09:27:26 +1100
commit7650bc68420a227212ba0ff5cd4a0d133471b872 (patch)
tree55d8d15e4cdd7407b7086e9c3cf9597539c81071
parentd83ff35d66e11978e0b821ecbfa07011ddcb8868 (diff)
- (djm) OpenBSD CVS Sync:
- markus@cvs.openbsd.org 2001/01/29 12:47:32 [rsa.c rsa.h ssh-agent.c sshconnect1.c sshd.c] handle rsa_private_decrypt failures; helps against the Bleichenbacher pkcs#1 attack
-rw-r--r--ChangeLog4
-rw-r--r--rsa.c15
-rw-r--r--rsa.h4
-rw-r--r--ssh-agent.c7
-rw-r--r--sshconnect1.c11
-rw-r--r--sshd.c57
6 files changed, 63 insertions, 35 deletions
diff --git a/ChangeLog b/ChangeLog
index 250ab58af..9c97a1287 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,10 @@
6 - markus@cvs.openbsd.org 2001/01/29 12:42:35 6 - markus@cvs.openbsd.org 2001/01/29 12:42:35
7 [canohost.c canohost.h channels.c clientloop.c] 7 [canohost.c canohost.h channels.c clientloop.c]
8 add get_peer_ipaddr(socket), x11-fwd in ssh2 requires ipaddr, not DNS 8 add get_peer_ipaddr(socket), x11-fwd in ssh2 requires ipaddr, not DNS
9 - markus@cvs.openbsd.org 2001/01/29 12:47:32
10 [rsa.c rsa.h ssh-agent.c sshconnect1.c sshd.c]
11 handle rsa_private_decrypt failures; helps against the Bleichenbacher
12 pkcs#1 attack
9 13
1020000129 1420000129
11 - (stevesk) sftp-server.c: use %lld vs. %qd 15 - (stevesk) sftp-server.c: use %lld vs. %qd
diff --git a/rsa.c b/rsa.c
index 04bb239e5..100524607 100644
--- a/rsa.c
+++ b/rsa.c
@@ -60,7 +60,7 @@
60 */ 60 */
61 61
62#include "includes.h" 62#include "includes.h"
63RCSID("$OpenBSD: rsa.c,v 1.19 2001/01/21 19:05:54 markus Exp $"); 63RCSID("$OpenBSD: rsa.c,v 1.20 2001/01/29 19:47:30 markus Exp $");
64 64
65#include "rsa.h" 65#include "rsa.h"
66#include "log.h" 66#include "log.h"
@@ -94,7 +94,7 @@ rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
94 xfree(inbuf); 94 xfree(inbuf);
95} 95}
96 96
97void 97int
98rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key) 98rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
99{ 99{
100 u_char *inbuf, *outbuf; 100 u_char *inbuf, *outbuf;
@@ -108,13 +108,14 @@ rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
108 BN_bn2bin(in, inbuf); 108 BN_bn2bin(in, inbuf);
109 109
110 if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key, 110 if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key,
111 RSA_PKCS1_PADDING)) <= 0) 111 RSA_PKCS1_PADDING)) <= 0) {
112 fatal("rsa_private_decrypt() failed"); 112 error("rsa_private_decrypt() failed");
113 113 } else {
114 BN_bin2bn(outbuf, len, out); 114 BN_bin2bn(outbuf, len, out);
115 115 }
116 memset(outbuf, 0, olen); 116 memset(outbuf, 0, olen);
117 memset(inbuf, 0, ilen); 117 memset(inbuf, 0, ilen);
118 xfree(outbuf); 118 xfree(outbuf);
119 xfree(inbuf); 119 xfree(inbuf);
120 return len;
120} 121}
diff --git a/rsa.h b/rsa.h
index 57d72cc78..713d31281 100644
--- a/rsa.h
+++ b/rsa.h
@@ -11,7 +11,7 @@
11 * called by a name other than "ssh" or "Secure Shell". 11 * called by a name other than "ssh" or "Secure Shell".
12 */ 12 */
13 13
14/* RCSID("$OpenBSD: rsa.h,v 1.9 2000/11/12 19:50:38 markus Exp $"); */ 14/* RCSID("$OpenBSD: rsa.h,v 1.10 2001/01/29 19:47:30 markus Exp $"); */
15 15
16#ifndef RSA_H 16#ifndef RSA_H
17#define RSA_H 17#define RSA_H
@@ -20,6 +20,6 @@
20#include <openssl/rsa.h> 20#include <openssl/rsa.h>
21 21
22void rsa_public_encrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv)); 22void rsa_public_encrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
23void rsa_private_decrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv)); 23int rsa_private_decrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
24 24
25#endif /* RSA_H */ 25#endif /* RSA_H */
diff --git a/ssh-agent.c b/ssh-agent.c
index 539f8ce7d..deed3ecae 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-agent.c,v 1.48 2001/01/25 08:06:33 deraadt Exp $ */ 1/* $OpenBSD: ssh-agent.c,v 1.49 2001/01/29 19:47:31 markus Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -37,7 +37,7 @@
37 */ 37 */
38 38
39#include "includes.h" 39#include "includes.h"
40RCSID("$OpenBSD: ssh-agent.c,v 1.48 2001/01/25 08:06:33 deraadt Exp $"); 40RCSID("$OpenBSD: ssh-agent.c,v 1.49 2001/01/29 19:47:31 markus Exp $");
41 41
42#include <openssl/evp.h> 42#include <openssl/evp.h>
43#include <openssl/md5.h> 43#include <openssl/md5.h>
@@ -198,7 +198,8 @@ process_authentication_challenge1(SocketEntry *e)
198 private = lookup_private_key(key, NULL, 1); 198 private = lookup_private_key(key, NULL, 1);
199 if (private != NULL) { 199 if (private != NULL) {
200 /* Decrypt the challenge using the private key. */ 200 /* Decrypt the challenge using the private key. */
201 rsa_private_decrypt(challenge, challenge, private->rsa); 201 if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0)
202 goto failure;
202 203
203 /* The response is MD5 of decrypted challenge plus session id. */ 204 /* The response is MD5 of decrypted challenge plus session id. */
204 len = BN_num_bytes(challenge); 205 len = BN_num_bytes(challenge);
diff --git a/sshconnect1.c b/sshconnect1.c
index 5a5a22227..e732806f3 100644
--- a/sshconnect1.c
+++ b/sshconnect1.c
@@ -13,7 +13,7 @@
13 */ 13 */
14 14
15#include "includes.h" 15#include "includes.h"
16RCSID("$OpenBSD: sshconnect1.c,v 1.20 2001/01/22 23:06:40 markus Exp $"); 16RCSID("$OpenBSD: sshconnect1.c,v 1.21 2001/01/29 19:47:31 markus Exp $");
17 17
18#include <openssl/bn.h> 18#include <openssl/bn.h>
19#include <openssl/evp.h> 19#include <openssl/evp.h>
@@ -163,14 +163,17 @@ respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv)
163 int i, len; 163 int i, len;
164 164
165 /* Decrypt the challenge using the private key. */ 165 /* Decrypt the challenge using the private key. */
166 rsa_private_decrypt(challenge, challenge, prv); 166 /* XXX think about Bleichenbacher, too */
167 if (rsa_private_decrypt(challenge, challenge, prv) <= 0)
168 packet_disconnect(
169 "respond_to_rsa_challenge: rsa_private_decrypt failed");
167 170
168 /* Compute the response. */ 171 /* Compute the response. */
169 /* The response is MD5 of decrypted challenge plus session id. */ 172 /* The response is MD5 of decrypted challenge plus session id. */
170 len = BN_num_bytes(challenge); 173 len = BN_num_bytes(challenge);
171 if (len <= 0 || len > sizeof(buf)) 174 if (len <= 0 || len > sizeof(buf))
172 packet_disconnect("respond_to_rsa_challenge: bad challenge length %d", 175 packet_disconnect(
173 len); 176 "respond_to_rsa_challenge: bad challenge length %d", len);
174 177
175 memset(buf, 0, sizeof(buf)); 178 memset(buf, 0, sizeof(buf));
176 BN_bn2bin(challenge, buf + sizeof(buf) - len); 179 BN_bn2bin(challenge, buf + sizeof(buf) - len);
diff --git a/sshd.c b/sshd.c
index d46e4aa8b..02fe2ec42 100644
--- a/sshd.c
+++ b/sshd.c
@@ -40,7 +40,7 @@
40 */ 40 */
41 41
42#include "includes.h" 42#include "includes.h"
43RCSID("$OpenBSD: sshd.c,v 1.158 2001/01/28 10:37:26 markus Exp $"); 43RCSID("$OpenBSD: sshd.c,v 1.159 2001/01/29 19:47:31 markus Exp $");
44 44
45#include <openssl/dh.h> 45#include <openssl/dh.h>
46#include <openssl/bn.h> 46#include <openssl/bn.h>
@@ -1186,6 +1186,7 @@ do_ssh1_kex(void)
1186{ 1186{
1187 int i, len; 1187 int i, len;
1188 int plen, slen; 1188 int plen, slen;
1189 int rsafail = 0;
1189 BIGNUM *session_key_int; 1190 BIGNUM *session_key_int;
1190 u_char session_key[SSH_SESSION_KEY_LENGTH]; 1191 u_char session_key[SSH_SESSION_KEY_LENGTH];
1191 u_char cookie[8]; 1192 u_char cookie[8];
@@ -1296,7 +1297,7 @@ do_ssh1_kex(void)
1296 * with larger modulus first). 1297 * with larger modulus first).
1297 */ 1298 */
1298 if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) { 1299 if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) {
1299 /* Private key has bigger modulus. */ 1300 /* Server key has bigger modulus. */
1300 if (BN_num_bits(sensitive_data.server_key->rsa->n) < 1301 if (BN_num_bits(sensitive_data.server_key->rsa->n) <
1301 BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) { 1302 BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
1302 fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d", 1303 fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
@@ -1305,10 +1306,12 @@ do_ssh1_kex(void)
1305 BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), 1306 BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
1306 SSH_KEY_BITS_RESERVED); 1307 SSH_KEY_BITS_RESERVED);
1307 } 1308 }
1308 rsa_private_decrypt(session_key_int, session_key_int, 1309 if (rsa_private_decrypt(session_key_int, session_key_int,
1309 sensitive_data.server_key->rsa); 1310 sensitive_data.server_key->rsa) <= 0)
1310 rsa_private_decrypt(session_key_int, session_key_int, 1311 rsafail++;
1311 sensitive_data.ssh1_host_key->rsa); 1312 if (rsa_private_decrypt(session_key_int, session_key_int,
1313 sensitive_data.ssh1_host_key->rsa) <= 0)
1314 rsafail++;
1312 } else { 1315 } else {
1313 /* Host key has bigger modulus (or they are equal). */ 1316 /* Host key has bigger modulus (or they are equal). */
1314 if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) < 1317 if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
@@ -1319,10 +1322,12 @@ do_ssh1_kex(void)
1319 BN_num_bits(sensitive_data.server_key->rsa->n), 1322 BN_num_bits(sensitive_data.server_key->rsa->n),
1320 SSH_KEY_BITS_RESERVED); 1323 SSH_KEY_BITS_RESERVED);
1321 } 1324 }
1322 rsa_private_decrypt(session_key_int, session_key_int, 1325 if (rsa_private_decrypt(session_key_int, session_key_int,
1323 sensitive_data.ssh1_host_key->rsa); 1326 sensitive_data.ssh1_host_key->rsa) < 0)
1324 rsa_private_decrypt(session_key_int, session_key_int, 1327 rsafail++;
1325 sensitive_data.server_key->rsa); 1328 if (rsa_private_decrypt(session_key_int, session_key_int,
1329 sensitive_data.server_key->rsa) < 0)
1330 rsafail++;
1326 } 1331 }
1327 1332
1328 compute_session_id(session_id, cookie, 1333 compute_session_id(session_id, cookie,
@@ -1337,15 +1342,29 @@ do_ssh1_kex(void)
1337 * least significant 256 bits of the integer; the first byte of the 1342 * least significant 256 bits of the integer; the first byte of the
1338 * key is in the highest bits. 1343 * key is in the highest bits.
1339 */ 1344 */
1340 BN_mask_bits(session_key_int, sizeof(session_key) * 8); 1345 if (!rsafail) {
1341 len = BN_num_bytes(session_key_int); 1346 BN_mask_bits(session_key_int, sizeof(session_key) * 8);
1342 if (len < 0 || len > sizeof(session_key)) 1347 len = BN_num_bytes(session_key_int);
1343 fatal("do_connection: bad len from %s: session_key_int %d > sizeof(session_key) %d", 1348 if (len < 0 || len > sizeof(session_key)) {
1344 get_remote_ipaddr(), 1349 error("do_connection: bad session key len from %s: "
1345 len, sizeof(session_key)); 1350 "session_key_int %d > sizeof(session_key) %d",
1346 memset(session_key, 0, sizeof(session_key)); 1351 get_remote_ipaddr(), len, sizeof(session_key));
1347 BN_bn2bin(session_key_int, session_key + sizeof(session_key) - len); 1352 rsafail++;
1348 1353 } else {
1354 memset(session_key, 0, sizeof(session_key));
1355 BN_bn2bin(session_key_int,
1356 session_key + sizeof(session_key) - len);
1357 }
1358 }
1359 if (rsafail) {
1360 log("do_connection: generating a fake encryption key");
1361 for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) {
1362 if (i % 4 == 0)
1363 rand = arc4random();
1364 session_key[i] = rand & 0xff;
1365 rand >>= 8;
1366 }
1367 }
1349 /* Destroy the decrypted integer. It is no longer needed. */ 1368 /* Destroy the decrypted integer. It is no longer needed. */
1350 BN_clear_free(session_key_int); 1369 BN_clear_free(session_key_int);
1351 1370