diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | rsa.c | 15 | ||||
-rw-r--r-- | rsa.h | 4 | ||||
-rw-r--r-- | ssh-agent.c | 7 | ||||
-rw-r--r-- | sshconnect1.c | 11 | ||||
-rw-r--r-- | sshd.c | 57 |
6 files changed, 63 insertions, 35 deletions
@@ -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 | ||
10 | 20000129 | 14 | 20000129 |
11 | - (stevesk) sftp-server.c: use %lld vs. %qd | 15 | - (stevesk) sftp-server.c: use %lld vs. %qd |
@@ -60,7 +60,7 @@ | |||
60 | */ | 60 | */ |
61 | 61 | ||
62 | #include "includes.h" | 62 | #include "includes.h" |
63 | RCSID("$OpenBSD: rsa.c,v 1.19 2001/01/21 19:05:54 markus Exp $"); | 63 | RCSID("$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 | ||
97 | void | 97 | int |
98 | rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key) | 98 | rsa_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 | } |
@@ -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 | ||
22 | void rsa_public_encrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv)); | 22 | void rsa_public_encrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv)); |
23 | void rsa_private_decrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv)); | 23 | int 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" |
40 | RCSID("$OpenBSD: ssh-agent.c,v 1.48 2001/01/25 08:06:33 deraadt Exp $"); | 40 | RCSID("$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" |
16 | RCSID("$OpenBSD: sshconnect1.c,v 1.20 2001/01/22 23:06:40 markus Exp $"); | 16 | RCSID("$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); |
@@ -40,7 +40,7 @@ | |||
40 | */ | 40 | */ |
41 | 41 | ||
42 | #include "includes.h" | 42 | #include "includes.h" |
43 | RCSID("$OpenBSD: sshd.c,v 1.158 2001/01/28 10:37:26 markus Exp $"); | 43 | RCSID("$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 | ||