summaryrefslogtreecommitdiff
path: root/sshd.c
diff options
context:
space:
mode:
authortedu@openbsd.org <tedu@openbsd.org>2015-01-07 18:15:07 +0000
committerDamien Miller <djm@mindrot.org>2015-01-09 00:13:35 +1100
commitfebbe09e4e9aff579b0c5cc1623f756862e4757d (patch)
tree2d969e9b4a63d5c1c6a5cec212749255c679f013 /sshd.c
parent5191df927db282d3123ca2f34a04d8d96153911a (diff)
upstream commit
workaround for the Meyer, et al, Bleichenbacher Side Channel Attack. fake up a bignum key before RSA decryption. discussed/ok djm markus
Diffstat (limited to 'sshd.c')
-rw-r--r--sshd.c104
1 files changed, 47 insertions, 57 deletions
diff --git a/sshd.c b/sshd.c
index a957ce005..d59e2555b 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshd.c,v 1.430 2014/12/22 07:55:51 djm Exp $ */ 1/* $OpenBSD: sshd.c,v 1.431 2015/01/07 18:15:07 tedu Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -2254,8 +2254,10 @@ do_ssh1_kex(void)
2254{ 2254{
2255 int i, len; 2255 int i, len;
2256 int rsafail = 0; 2256 int rsafail = 0;
2257 BIGNUM *session_key_int; 2257 BIGNUM *session_key_int, *fake_key_int, *real_key_int;
2258 u_char session_key[SSH_SESSION_KEY_LENGTH]; 2258 u_char session_key[SSH_SESSION_KEY_LENGTH];
2259 u_char fake_key_bytes[4096 / 8];
2260 size_t fake_key_len;
2259 u_char cookie[8]; 2261 u_char cookie[8];
2260 u_int cipher_type, auth_mask, protocol_flags; 2262 u_int cipher_type, auth_mask, protocol_flags;
2261 2263
@@ -2333,74 +2335,61 @@ do_ssh1_kex(void)
2333 debug("Encryption type: %.200s", cipher_name(cipher_type)); 2335 debug("Encryption type: %.200s", cipher_name(cipher_type));
2334 2336
2335 /* Get the encrypted integer. */ 2337 /* Get the encrypted integer. */
2336 if ((session_key_int = BN_new()) == NULL) 2338 if ((real_key_int = BN_new()) == NULL)
2337 fatal("do_ssh1_kex: BN_new failed"); 2339 fatal("do_ssh1_kex: BN_new failed");
2338 packet_get_bignum(session_key_int); 2340 packet_get_bignum(real_key_int);
2339 2341
2340 protocol_flags = packet_get_int(); 2342 protocol_flags = packet_get_int();
2341 packet_set_protocol_flags(protocol_flags); 2343 packet_set_protocol_flags(protocol_flags);
2342 packet_check_eom(); 2344 packet_check_eom();
2343 2345
2344 /* Decrypt session_key_int using host/server keys */ 2346 /* Setup a fake key in case RSA decryption fails */
2345 rsafail = PRIVSEP(ssh1_session_key(session_key_int)); 2347 if ((fake_key_int = BN_new()) == NULL)
2348 fatal("do_ssh1_kex: BN_new failed");
2349 fake_key_len = BN_num_bytes(real_key_int);
2350 if (fake_key_len > sizeof(fake_key_bytes))
2351 fake_key_len = sizeof(fake_key_bytes);
2352 arc4random_buf(fake_key_bytes, fake_key_len);
2353 if (BN_bin2bn(fake_key_bytes, fake_key_len, fake_key_int) == NULL)
2354 fatal("do_ssh1_kex: BN_bin2bn failed");
2355
2356 /* Decrypt real_key_int using host/server keys */
2357 rsafail = PRIVSEP(ssh1_session_key(real_key_int));
2358 /* If decryption failed, use the fake key. Else, the real key. */
2359 if (rsafail)
2360 session_key_int = fake_key_int;
2361 else
2362 session_key_int = real_key_int;
2346 2363
2347 /* 2364 /*
2348 * Extract session key from the decrypted integer. The key is in the 2365 * Extract session key from the decrypted integer. The key is in the
2349 * least significant 256 bits of the integer; the first byte of the 2366 * least significant 256 bits of the integer; the first byte of the
2350 * key is in the highest bits. 2367 * key is in the highest bits.
2351 */ 2368 */
2352 if (!rsafail) { 2369 (void) BN_mask_bits(session_key_int, sizeof(session_key) * 8);
2353 (void) BN_mask_bits(session_key_int, sizeof(session_key) * 8); 2370 len = BN_num_bytes(session_key_int);
2354 len = BN_num_bytes(session_key_int); 2371 if (len < 0 || (u_int)len > sizeof(session_key)) {
2355 if (len < 0 || (u_int)len > sizeof(session_key)) { 2372 error("do_ssh1_kex: bad session key len from %s: "
2356 error("do_ssh1_kex: bad session key len from %s: " 2373 "session_key_int %d > sizeof(session_key) %lu",
2357 "session_key_int %d > sizeof(session_key) %lu", 2374 get_remote_ipaddr(), len, (u_long)sizeof(session_key));
2358 get_remote_ipaddr(), len, (u_long)sizeof(session_key)); 2375 rsafail++;
2359 rsafail++; 2376 } else {
2360 } else { 2377 explicit_bzero(session_key, sizeof(session_key));
2361 explicit_bzero(session_key, sizeof(session_key)); 2378 BN_bn2bin(session_key_int,
2362 BN_bn2bin(session_key_int, 2379 session_key + sizeof(session_key) - len);
2363 session_key + sizeof(session_key) - len); 2380
2364 2381 derive_ssh1_session_id(
2365 derive_ssh1_session_id( 2382 sensitive_data.ssh1_host_key->rsa->n,
2366 sensitive_data.ssh1_host_key->rsa->n, 2383 sensitive_data.server_key->rsa->n,
2367 sensitive_data.server_key->rsa->n, 2384 cookie, session_id);
2368 cookie, session_id); 2385 /*
2369 /* 2386 * Xor the first 16 bytes of the session key with the
2370 * Xor the first 16 bytes of the session key with the 2387 * session id.
2371 * session id. 2388 */
2372 */
2373 for (i = 0; i < 16; i++)
2374 session_key[i] ^= session_id[i];
2375 }
2376 }
2377 if (rsafail) {
2378 int bytes = BN_num_bytes(session_key_int);
2379 u_char *buf = xmalloc(bytes);
2380 struct ssh_digest_ctx *md;
2381
2382 logit("do_connection: generating a fake encryption key");
2383 BN_bn2bin(session_key_int, buf);
2384 if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL ||
2385 ssh_digest_update(md, buf, bytes) < 0 ||
2386 ssh_digest_update(md, sensitive_data.ssh1_cookie,
2387 SSH_SESSION_KEY_LENGTH) < 0 ||
2388 ssh_digest_final(md, session_key, sizeof(session_key)) < 0)
2389 fatal("%s: md5 failed", __func__);
2390 ssh_digest_free(md);
2391 if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL ||
2392 ssh_digest_update(md, session_key, 16) < 0 ||
2393 ssh_digest_update(md, sensitive_data.ssh1_cookie,
2394 SSH_SESSION_KEY_LENGTH) < 0 ||
2395 ssh_digest_final(md, session_key + 16,
2396 sizeof(session_key) - 16) < 0)
2397 fatal("%s: md5 failed", __func__);
2398 ssh_digest_free(md);
2399 explicit_bzero(buf, bytes);
2400 free(buf);
2401 for (i = 0; i < 16; i++) 2389 for (i = 0; i < 16; i++)
2402 session_id[i] = session_key[i] ^ session_key[i + 16]; 2390 session_key[i] ^= session_id[i];
2403 } 2391 }
2392
2404 /* Destroy the private and public keys. No longer. */ 2393 /* Destroy the private and public keys. No longer. */
2405 destroy_sensitive_data(); 2394 destroy_sensitive_data();
2406 2395
@@ -2408,7 +2397,8 @@ do_ssh1_kex(void)
2408 mm_ssh1_session_id(session_id); 2397 mm_ssh1_session_id(session_id);
2409 2398
2410 /* Destroy the decrypted integer. It is no longer needed. */ 2399 /* Destroy the decrypted integer. It is no longer needed. */
2411 BN_clear_free(session_key_int); 2400 BN_clear_free(real_key_int);
2401 BN_clear_free(fake_key_int);
2412 2402
2413 /* Set the session key. From this on all communications will be encrypted. */ 2403 /* Set the session key. From this on all communications will be encrypted. */
2414 packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, cipher_type); 2404 packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, cipher_type);