diff options
-rw-r--r-- | sshd.c | 104 |
1 files changed, 47 insertions, 57 deletions
@@ -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); |