Skip to content
Snippets Groups Projects
Commit 6b577500 authored by Niels Möller's avatar Niels Möller
Browse files

Fix for Bleichenbacher's chosen ciphertext attack. Basically, don't

send an ALERT-messages immediately if decryption of the session key
failes. Continue handshaking as if nothing is wrong.

Either some other invalid message is recieved, and handshaking failes
at that time, or the client sends a change cipher message, followed by
a completely garbled finished-message (as the server and client will
not be using the same keys), or the client will wait for ever for an
answer.

Rev: lib/modules/SSL.pmod/handshake.pike:1.9
parent e367f577
No related branches found
No related tags found
No related merge requests found
/* $Id: handshake.pike,v 1.8 1998/04/21 21:28:57 grubba Exp $ /* $Id: handshake.pike,v 1.9 1998/06/26 22:25:02 nisse Exp $
* *
*/ */
...@@ -32,6 +32,8 @@ int certificate_state; ...@@ -32,6 +32,8 @@ int certificate_state;
int expect_change_cipher; /* Reset to 0 if a change_cipher message is received */ int expect_change_cipher; /* Reset to 0 if a change_cipher message is received */
int rsa_message_was_bad;
int reuse; int reuse;
string my_random; string my_random;
...@@ -194,9 +196,27 @@ string server_derive_master_secret(string data) ...@@ -194,9 +196,27 @@ string server_derive_master_secret(string data)
werror(sprintf("premaster_secret: '%O'\n", s)); werror(sprintf("premaster_secret: '%O'\n", s));
#endif #endif
if (!s || (strlen(s) != 48) || (s[0] != 3)) if (!s || (strlen(s) != 48) || (s[0] != 3))
return 0; {
if (s[1] > 0)
werror("SSL.handshake: Newer version detected in key exchange message.\n"); /* To avoid the chosen ciphertext attack discovered by Daniel
* Bleichenbacher, it is essential not to send any error *
* messages back to the client until after the client's *
* Finished-message (or some other invalid message) has been *
* recieved. */
werror("SSL.handshake: Invalid premaster_secret! "
"A chosen ciphertext attack?\n");
s = context->random(48);
rsa_message_was_bad = 1;
} else {
/* FIXME: When versions beyond 3.0 are supported,
* the version number here must be checked more carefully
* for a version rollback attack. */
if (s[1] > 0)
werror("SSL.handshake: Newer version detected in key exchange message.\n");
}
object sha = mac_sha(); object sha = mac_sha();
object md5 = mac_md5(); object md5 = mac_md5();
foreach( ({ "A", "BB", "CCC" }), string cookie) foreach( ({ "A", "BB", "CCC" }), string cookie)
...@@ -231,7 +251,8 @@ int handle_handshake(int type, string data, string raw) ...@@ -231,7 +251,8 @@ int handle_handshake(int type, string data, string raw)
/* Reset all extra state variables */ /* Reset all extra state variables */
expect_change_cipher = certificate_state = 0; expect_change_cipher = certificate_state = 0;
rsa_message_was_bad = 0;
handshake_messages = raw; handshake_messages = raw;
my_random = sprintf("%4c%s", time(), context->random(28)); my_random = sprintf("%4c%s", time(), context->random(28));
...@@ -268,7 +289,7 @@ int handle_handshake(int type, string data, string raw) ...@@ -268,7 +289,7 @@ int handle_handshake(int type, string data, string raw)
"extra data in hello message ignored\n"); "extra data in hello message ignored\n");
if (version[1] > 0) if (version[1] > 0)
werror(sprintf("SSL.connection->handle_handshake: " werror(sprintf("SSL.handshake->handle_handshake: "
"Version %d.%d hello detected\n", @version)); "Version %d.%d hello detected\n", @version));
#ifdef SSL3_DEBUG #ifdef SSL3_DEBUG
...@@ -379,7 +400,8 @@ int handle_handshake(int type, string data, string raw) ...@@ -379,7 +400,8 @@ int handle_handshake(int type, string data, string raw)
send_packet(Alert(ALERT_fatal, ALERT_unexpected_message)); send_packet(Alert(ALERT_fatal, ALERT_unexpected_message));
return -1; return -1;
} }
if (my_digest != digest) if (rsa_message_was_bad /* Error delayed until now */
|| (my_digest != digest))
{ {
send_packet(Alert(ALERT_fatal, ALERT_unexpected_message)); send_packet(Alert(ALERT_fatal, ALERT_unexpected_message));
return -1; return -1;
...@@ -421,24 +443,21 @@ int handle_handshake(int type, string data, string raw) ...@@ -421,24 +443,21 @@ int handle_handshake(int type, string data, string raw)
backtrace())); backtrace()));
return -1; return -1;
} }
if (!(session->master_secret = server_derive_master_secret(data))) if (!(session->master_secret = server_derive_master_secret(data)))
{ {
throw( ({ "SSL.handshake: internal error\n", backtrace() }) );
} else {
// trace(1);
array res = session->new_server_states(other_random, my_random);
pending_read_state = res[0];
pending_write_state = res[1];
#ifdef SSL3_DEBUG #ifdef SSL3_DEBUG
werror("server_derive_master_secret failed!\n"); werror(sprintf("certificate_state: %d\n", certificate_state));
#endif #endif
send_packet(Alert(ALERT_fatal, ALERT_unexpected_message,
"SSL.session->handle_handshake: unexpected message\n",
backtrace()));
return -1;
} }
// trace(1);
array res = session->new_server_states(other_random, my_random);
pending_read_state = res[0];
pending_write_state = res[1];
#ifdef SSL3_DEBUG
werror(sprintf("certificate_state: %d\n", certificate_state));
#endif
if (certificate_state != CERT_received) if (certificate_state != CERT_received)
{ {
handshake_state = STATE_server_wait_for_finish; handshake_state = STATE_server_wait_for_finish;
...@@ -481,10 +500,13 @@ int handle_handshake(int type, string data, string raw) ...@@ -481,10 +500,13 @@ int handle_handshake(int type, string data, string raw)
backtrace())); backtrace()));
return -1; return -1;
case HANDSHAKE_certificate_verify: case HANDSHAKE_certificate_verify:
session->client_challenge = if (!rsa_message_was_bad)
mac_md5(session->master_secret)->hash_master(handshake_messages) + {
mac_sha(session->master_secret)->hash_master(handshake_messages); session->client_challenge =
session->client_signature = data; mac_md5(session->master_secret)->hash_master(handshake_messages) +
mac_sha(session->master_secret)->hash_master(handshake_messages);
session->client_signature = data;
}
handshake_messages += raw; handshake_messages += raw;
handshake_state = STATE_server_wait_for_finish; handshake_state = STATE_server_wait_for_finish;
expect_change_cipher = 1; expect_change_cipher = 1;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment