- (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
This commit is contained in:
parent
d83ff35d66
commit
7650bc6842
|
@ -6,6 +6,10 @@
|
||||||
- markus@cvs.openbsd.org 2001/01/29 12:42:35
|
- markus@cvs.openbsd.org 2001/01/29 12:42:35
|
||||||
[canohost.c canohost.h channels.c clientloop.c]
|
[canohost.c canohost.h channels.c clientloop.c]
|
||||||
add get_peer_ipaddr(socket), x11-fwd in ssh2 requires ipaddr, not DNS
|
add get_peer_ipaddr(socket), x11-fwd in ssh2 requires ipaddr, not DNS
|
||||||
|
- 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
|
||||||
|
|
||||||
20000129
|
20000129
|
||||||
- (stevesk) sftp-server.c: use %lld vs. %qd
|
- (stevesk) sftp-server.c: use %lld vs. %qd
|
||||||
|
|
15
rsa.c
15
rsa.c
|
@ -60,7 +60,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "rsa.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
@ -94,7 +94,7 @@ rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
|
||||||
xfree(inbuf);
|
xfree(inbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
|
rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
|
||||||
{
|
{
|
||||||
u_char *inbuf, *outbuf;
|
u_char *inbuf, *outbuf;
|
||||||
|
@ -108,13 +108,14 @@ rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
|
||||||
BN_bn2bin(in, inbuf);
|
BN_bn2bin(in, inbuf);
|
||||||
|
|
||||||
if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key,
|
if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key,
|
||||||
RSA_PKCS1_PADDING)) <= 0)
|
RSA_PKCS1_PADDING)) <= 0) {
|
||||||
fatal("rsa_private_decrypt() failed");
|
error("rsa_private_decrypt() failed");
|
||||||
|
} else {
|
||||||
BN_bin2bn(outbuf, len, out);
|
BN_bin2bn(outbuf, len, out);
|
||||||
|
}
|
||||||
memset(outbuf, 0, olen);
|
memset(outbuf, 0, olen);
|
||||||
memset(inbuf, 0, ilen);
|
memset(inbuf, 0, ilen);
|
||||||
xfree(outbuf);
|
xfree(outbuf);
|
||||||
xfree(inbuf);
|
xfree(inbuf);
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
4
rsa.h
4
rsa.h
|
@ -11,7 +11,7 @@
|
||||||
* called by a name other than "ssh" or "Secure Shell".
|
* 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
|
#ifndef RSA_H
|
||||||
#define RSA_H
|
#define RSA_H
|
||||||
|
@ -20,6 +20,6 @@
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
|
|
||||||
void rsa_public_encrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
|
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 */
|
#endif /* RSA_H */
|
||||||
|
|
|
@ -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>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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/evp.h>
|
||||||
#include <openssl/md5.h>
|
#include <openssl/md5.h>
|
||||||
|
@ -198,7 +198,8 @@ process_authentication_challenge1(SocketEntry *e)
|
||||||
private = lookup_private_key(key, NULL, 1);
|
private = lookup_private_key(key, NULL, 1);
|
||||||
if (private != NULL) {
|
if (private != NULL) {
|
||||||
/* Decrypt the challenge using the private key. */
|
/* 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. */
|
/* The response is MD5 of decrypted challenge plus session id. */
|
||||||
len = BN_num_bytes(challenge);
|
len = BN_num_bytes(challenge);
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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/bn.h>
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
|
@ -163,14 +163,17 @@ respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv)
|
||||||
int i, len;
|
int i, len;
|
||||||
|
|
||||||
/* Decrypt the challenge using the private key. */
|
/* 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. */
|
/* Compute the response. */
|
||||||
/* The response is MD5 of decrypted challenge plus session id. */
|
/* The response is MD5 of decrypted challenge plus session id. */
|
||||||
len = BN_num_bytes(challenge);
|
len = BN_num_bytes(challenge);
|
||||||
if (len <= 0 || len > sizeof(buf))
|
if (len <= 0 || len > sizeof(buf))
|
||||||
packet_disconnect("respond_to_rsa_challenge: bad challenge length %d",
|
packet_disconnect(
|
||||||
len);
|
"respond_to_rsa_challenge: bad challenge length %d", len);
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
BN_bn2bin(challenge, buf + sizeof(buf) - len);
|
BN_bn2bin(challenge, buf + sizeof(buf) - len);
|
||||||
|
|
57
sshd.c
57
sshd.c
|
@ -40,7 +40,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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/dh.h>
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
|
@ -1186,6 +1186,7 @@ do_ssh1_kex(void)
|
||||||
{
|
{
|
||||||
int i, len;
|
int i, len;
|
||||||
int plen, slen;
|
int plen, slen;
|
||||||
|
int rsafail = 0;
|
||||||
BIGNUM *session_key_int;
|
BIGNUM *session_key_int;
|
||||||
u_char session_key[SSH_SESSION_KEY_LENGTH];
|
u_char session_key[SSH_SESSION_KEY_LENGTH];
|
||||||
u_char cookie[8];
|
u_char cookie[8];
|
||||||
|
@ -1296,7 +1297,7 @@ do_ssh1_kex(void)
|
||||||
* with larger modulus first).
|
* with larger modulus first).
|
||||||
*/
|
*/
|
||||||
if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) {
|
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) <
|
if (BN_num_bits(sensitive_data.server_key->rsa->n) <
|
||||||
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
|
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",
|
fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
|
||||||
|
@ -1305,10 +1306,12 @@ do_ssh1_kex(void)
|
||||||
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
|
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
|
||||||
SSH_KEY_BITS_RESERVED);
|
SSH_KEY_BITS_RESERVED);
|
||||||
}
|
}
|
||||||
rsa_private_decrypt(session_key_int, session_key_int,
|
if (rsa_private_decrypt(session_key_int, session_key_int,
|
||||||
sensitive_data.server_key->rsa);
|
sensitive_data.server_key->rsa) <= 0)
|
||||||
rsa_private_decrypt(session_key_int, session_key_int,
|
rsafail++;
|
||||||
sensitive_data.ssh1_host_key->rsa);
|
if (rsa_private_decrypt(session_key_int, session_key_int,
|
||||||
|
sensitive_data.ssh1_host_key->rsa) <= 0)
|
||||||
|
rsafail++;
|
||||||
} else {
|
} else {
|
||||||
/* Host key has bigger modulus (or they are equal). */
|
/* Host key has bigger modulus (or they are equal). */
|
||||||
if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
|
if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
|
||||||
|
@ -1319,10 +1322,12 @@ do_ssh1_kex(void)
|
||||||
BN_num_bits(sensitive_data.server_key->rsa->n),
|
BN_num_bits(sensitive_data.server_key->rsa->n),
|
||||||
SSH_KEY_BITS_RESERVED);
|
SSH_KEY_BITS_RESERVED);
|
||||||
}
|
}
|
||||||
rsa_private_decrypt(session_key_int, session_key_int,
|
if (rsa_private_decrypt(session_key_int, session_key_int,
|
||||||
sensitive_data.ssh1_host_key->rsa);
|
sensitive_data.ssh1_host_key->rsa) < 0)
|
||||||
rsa_private_decrypt(session_key_int, session_key_int,
|
rsafail++;
|
||||||
sensitive_data.server_key->rsa);
|
if (rsa_private_decrypt(session_key_int, session_key_int,
|
||||||
|
sensitive_data.server_key->rsa) < 0)
|
||||||
|
rsafail++;
|
||||||
}
|
}
|
||||||
|
|
||||||
compute_session_id(session_id, cookie,
|
compute_session_id(session_id, cookie,
|
||||||
|
@ -1337,15 +1342,29 @@ do_ssh1_kex(void)
|
||||||
* least significant 256 bits of the integer; the first byte of the
|
* least significant 256 bits of the integer; the first byte of the
|
||||||
* key is in the highest bits.
|
* key is in the highest bits.
|
||||||
*/
|
*/
|
||||||
BN_mask_bits(session_key_int, sizeof(session_key) * 8);
|
if (!rsafail) {
|
||||||
len = BN_num_bytes(session_key_int);
|
BN_mask_bits(session_key_int, sizeof(session_key) * 8);
|
||||||
if (len < 0 || len > sizeof(session_key))
|
len = BN_num_bytes(session_key_int);
|
||||||
fatal("do_connection: bad len from %s: session_key_int %d > sizeof(session_key) %d",
|
if (len < 0 || len > sizeof(session_key)) {
|
||||||
get_remote_ipaddr(),
|
error("do_connection: bad session key len from %s: "
|
||||||
len, sizeof(session_key));
|
"session_key_int %d > sizeof(session_key) %d",
|
||||||
memset(session_key, 0, sizeof(session_key));
|
get_remote_ipaddr(), len, sizeof(session_key));
|
||||||
BN_bn2bin(session_key_int, session_key + sizeof(session_key) - len);
|
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. */
|
/* Destroy the decrypted integer. It is no longer needed. */
|
||||||
BN_clear_free(session_key_int);
|
BN_clear_free(session_key_int);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue