summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormarkus@openbsd.org <markus@openbsd.org>2017-05-31 08:09:45 +0000
committerDamien Miller <djm@mindrot.org>2017-06-01 14:54:46 +1000
commit1e0cdf8efb745d0d1116e1aa22bdc99ee731695e (patch)
tree49ffdf3ef98eecd4141610e535f35bab5eea4603
parent92e9fe633130376a95dd533df6e5e6a578c1e6b8 (diff)
upstream commit
clear session keys from memory; ok djm@ Upstream-ID: ecd178819868975affd5fd6637458b7c712b6a0f
-rw-r--r--monitor.c13
-rw-r--r--monitor_wrap.h4
-rw-r--r--opacket.h2
-rw-r--r--packet.c96
-rw-r--r--packet.h4
-rw-r--r--session.c3
-rw-r--r--sshd.c4
-rw-r--r--umac.c8
8 files changed, 92 insertions, 42 deletions
diff --git a/monitor.c b/monitor.c
index 2dee9721d..ef107a2e8 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: monitor.c,v 1.169 2017/05/30 14:10:53 markus Exp $ */ 1/* $OpenBSD: monitor.c,v 1.170 2017/05/31 08:09:45 markus Exp $ */
2/* 2/*
3 * Copyright 2002 Niels Provos <provos@citi.umich.edu> 3 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4 * Copyright 2002 Markus Friedl <markus@openbsd.org> 4 * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -1584,6 +1584,17 @@ mm_answer_audit_command(int socket, Buffer *m)
1584#endif /* SSH_AUDIT_EVENTS */ 1584#endif /* SSH_AUDIT_EVENTS */
1585 1585
1586void 1586void
1587monitor_clear_keystate(struct monitor *pmonitor)
1588{
1589 struct ssh *ssh = active_state; /* XXX */
1590
1591 ssh_clear_newkeys(ssh, MODE_IN);
1592 ssh_clear_newkeys(ssh, MODE_OUT);
1593 sshbuf_free(child_state);
1594 child_state = NULL;
1595}
1596
1597void
1587monitor_apply_keystate(struct monitor *pmonitor) 1598monitor_apply_keystate(struct monitor *pmonitor)
1588{ 1599{
1589 struct ssh *ssh = active_state; /* XXX */ 1600 struct ssh *ssh = active_state; /* XXX */
diff --git a/monitor_wrap.h b/monitor_wrap.h
index 958cdbc92..9e032d204 100644
--- a/monitor_wrap.h
+++ b/monitor_wrap.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: monitor_wrap.h,v 1.34 2017/05/30 14:10:53 markus Exp $ */ 1/* $OpenBSD: monitor_wrap.h,v 1.35 2017/05/31 08:09:45 markus Exp $ */
2 2
3/* 3/*
4 * Copyright 2002 Niels Provos <provos@citi.umich.edu> 4 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@@ -34,7 +34,6 @@ extern int use_privsep;
34enum mm_keytype { MM_NOKEY, MM_HOSTKEY, MM_USERKEY }; 34enum mm_keytype { MM_NOKEY, MM_HOSTKEY, MM_USERKEY };
35 35
36struct monitor; 36struct monitor;
37struct mm_master;
38struct Authctxt; 37struct Authctxt;
39 38
40void mm_log_handler(LogLevel, const char *, void *); 39void mm_log_handler(LogLevel, const char *, void *);
@@ -86,6 +85,7 @@ void mm_session_pty_cleanup2(struct Session *);
86struct newkeys *mm_newkeys_from_blob(u_char *, int); 85struct newkeys *mm_newkeys_from_blob(u_char *, int);
87int mm_newkeys_to_blob(int, u_char **, u_int *); 86int mm_newkeys_to_blob(int, u_char **, u_int *);
88 87
88void monitor_clear_keystate(struct monitor *);
89void monitor_apply_keystate(struct monitor *); 89void monitor_apply_keystate(struct monitor *);
90void mm_get_keystate(struct monitor *); 90void mm_get_keystate(struct monitor *);
91void mm_send_keystate(struct monitor*); 91void mm_send_keystate(struct monitor*);
diff --git a/opacket.h b/opacket.h
index 46d31f805..c49d0c04a 100644
--- a/opacket.h
+++ b/opacket.h
@@ -149,5 +149,7 @@ void packet_disconnect(const char *, ...)
149 ssh_packet_set_mux(active_state) 149 ssh_packet_set_mux(active_state)
150#define packet_get_mux() \ 150#define packet_get_mux() \
151 ssh_packet_get_mux(active_state) 151 ssh_packet_get_mux(active_state)
152#define packet_clear_keys() \
153 ssh_packet_clear_keys(active_state)
152 154
153#endif /* _OPACKET_H */ 155#endif /* _OPACKET_H */
diff --git a/packet.c b/packet.c
index 46dcc5b5f..862aeb052 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.c,v 1.256 2017/05/08 06:03:39 djm Exp $ */ 1/* $OpenBSD: packet.c,v 1.257 2017/05/31 08:09:45 markus 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
@@ -559,8 +559,8 @@ ssh_local_port(struct ssh *ssh)
559 559
560/* Closes the connection and clears and frees internal data structures. */ 560/* Closes the connection and clears and frees internal data structures. */
561 561
562void 562static void
563ssh_packet_close(struct ssh *ssh) 563ssh_packet_close_internal(struct ssh *ssh, int do_close)
564{ 564{
565 struct session_state *state = ssh->state; 565 struct session_state *state = ssh->state;
566 u_int mode; 566 u_int mode;
@@ -568,20 +568,26 @@ ssh_packet_close(struct ssh *ssh)
568 if (!state->initialized) 568 if (!state->initialized)
569 return; 569 return;
570 state->initialized = 0; 570 state->initialized = 0;
571 if (state->connection_in == state->connection_out) { 571 if (do_close) {
572 shutdown(state->connection_out, SHUT_RDWR); 572 if (state->connection_in == state->connection_out) {
573 close(state->connection_out); 573 shutdown(state->connection_out, SHUT_RDWR);
574 } else { 574 close(state->connection_out);
575 close(state->connection_in); 575 } else {
576 close(state->connection_out); 576 close(state->connection_in);
577 close(state->connection_out);
578 }
577 } 579 }
578 sshbuf_free(state->input); 580 sshbuf_free(state->input);
579 sshbuf_free(state->output); 581 sshbuf_free(state->output);
580 sshbuf_free(state->outgoing_packet); 582 sshbuf_free(state->outgoing_packet);
581 sshbuf_free(state->incoming_packet); 583 sshbuf_free(state->incoming_packet);
582 for (mode = 0; mode < MODE_MAX; mode++) 584 for (mode = 0; mode < MODE_MAX; mode++) {
583 kex_free_newkeys(state->newkeys[mode]); 585 kex_free_newkeys(state->newkeys[mode]); /* current keys */
584 if (state->compression_buffer) { 586 state->newkeys[mode] = NULL;
587 ssh_clear_newkeys(ssh, mode); /* next keys */
588 }
589 /* comression state is in shared mem, so we can only release it once */
590 if (do_close && state->compression_buffer) {
585 sshbuf_free(state->compression_buffer); 591 sshbuf_free(state->compression_buffer);
586 if (state->compression_out_started) { 592 if (state->compression_out_started) {
587 z_streamp stream = &state->compression_out_stream; 593 z_streamp stream = &state->compression_out_stream;
@@ -609,10 +615,24 @@ ssh_packet_close(struct ssh *ssh)
609 cipher_free(state->send_context); 615 cipher_free(state->send_context);
610 cipher_free(state->receive_context); 616 cipher_free(state->receive_context);
611 state->send_context = state->receive_context = NULL; 617 state->send_context = state->receive_context = NULL;
612 free(ssh->remote_ipaddr); 618 if (do_close) {
613 ssh->remote_ipaddr = NULL; 619 free(ssh->remote_ipaddr);
614 free(ssh->state); 620 ssh->remote_ipaddr = NULL;
615 ssh->state = NULL; 621 free(ssh->state);
622 ssh->state = NULL;
623 }
624}
625
626void
627ssh_packet_close(struct ssh *ssh)
628{
629 ssh_packet_close_internal(ssh, 1);
630}
631
632void
633ssh_packet_clear_keys(struct ssh *ssh)
634{
635 ssh_packet_close_internal(ssh, 0);
616} 636}
617 637
618/* Sets remote side protocol flags. */ 638/* Sets remote side protocol flags. */
@@ -791,6 +811,15 @@ uncompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out)
791 /* NOTREACHED */ 811 /* NOTREACHED */
792} 812}
793 813
814void
815ssh_clear_newkeys(struct ssh *ssh, int mode)
816{
817 if (ssh->kex && ssh->kex->newkeys) {
818 kex_free_newkeys(ssh->kex->newkeys[mode]);
819 ssh->kex->newkeys[mode] = NULL;
820 }
821}
822
794int 823int
795ssh_set_newkeys(struct ssh *ssh, int mode) 824ssh_set_newkeys(struct ssh *ssh, int mode)
796{ 825{
@@ -820,26 +849,16 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
820 max_blocks = &state->max_blocks_in; 849 max_blocks = &state->max_blocks_in;
821 } 850 }
822 if (state->newkeys[mode] != NULL) { 851 if (state->newkeys[mode] != NULL) {
823 debug("%s: rekeying after %llu %s blocks" 852 debug("set_newkeys: rekeying, input %llu bytes %llu blocks, "
824 " (%llu bytes total)", __func__, 853 "output %llu bytes %llu blocks",
825 (unsigned long long)ps->blocks, dir, 854 (unsigned long long)state->p_read.bytes,
826 (unsigned long long)ps->bytes); 855 (unsigned long long)state->p_read.blocks,
856 (unsigned long long)state->p_send.bytes,
857 (unsigned long long)state->p_send.blocks);
827 cipher_free(*ccp); 858 cipher_free(*ccp);
828 *ccp = NULL; 859 *ccp = NULL;
829 enc = &state->newkeys[mode]->enc; 860 kex_free_newkeys(state->newkeys[mode]);
830 mac = &state->newkeys[mode]->mac; 861 state->newkeys[mode] = NULL;
831 comp = &state->newkeys[mode]->comp;
832 mac_clear(mac);
833 explicit_bzero(enc->iv, enc->iv_len);
834 explicit_bzero(enc->key, enc->key_len);
835 explicit_bzero(mac->key, mac->key_len);
836 free(enc->name);
837 free(enc->iv);
838 free(enc->key);
839 free(mac->name);
840 free(mac->key);
841 free(comp->name);
842 free(state->newkeys[mode]);
843 } 862 }
844 /* note that both bytes and the seqnr are not reset */ 863 /* note that both bytes and the seqnr are not reset */
845 ps->packets = ps->blocks = 0; 864 ps->packets = ps->blocks = 0;
@@ -1784,15 +1803,20 @@ sshpkt_fatal(struct ssh *ssh, const char *tag, int r)
1784 1803
1785 switch (r) { 1804 switch (r) {
1786 case SSH_ERR_CONN_CLOSED: 1805 case SSH_ERR_CONN_CLOSED:
1806 ssh_packet_clear_keys(ssh);
1787 logdie("Connection closed by %s", remote_id); 1807 logdie("Connection closed by %s", remote_id);
1788 case SSH_ERR_CONN_TIMEOUT: 1808 case SSH_ERR_CONN_TIMEOUT:
1809 ssh_packet_clear_keys(ssh);
1789 logdie("Connection %s %s timed out", 1810 logdie("Connection %s %s timed out",
1790 ssh->state->server_side ? "from" : "to", remote_id); 1811 ssh->state->server_side ? "from" : "to", remote_id);
1791 case SSH_ERR_DISCONNECTED: 1812 case SSH_ERR_DISCONNECTED:
1813 ssh_packet_clear_keys(ssh);
1792 logdie("Disconnected from %s", remote_id); 1814 logdie("Disconnected from %s", remote_id);
1793 case SSH_ERR_SYSTEM_ERROR: 1815 case SSH_ERR_SYSTEM_ERROR:
1794 if (errno == ECONNRESET) 1816 if (errno == ECONNRESET) {
1817 ssh_packet_clear_keys(ssh);
1795 logdie("Connection reset by %s", remote_id); 1818 logdie("Connection reset by %s", remote_id);
1819 }
1796 /* FALLTHROUGH */ 1820 /* FALLTHROUGH */
1797 case SSH_ERR_NO_CIPHER_ALG_MATCH: 1821 case SSH_ERR_NO_CIPHER_ALG_MATCH:
1798 case SSH_ERR_NO_MAC_ALG_MATCH: 1822 case SSH_ERR_NO_MAC_ALG_MATCH:
@@ -1800,12 +1824,14 @@ sshpkt_fatal(struct ssh *ssh, const char *tag, int r)
1800 case SSH_ERR_NO_KEX_ALG_MATCH: 1824 case SSH_ERR_NO_KEX_ALG_MATCH:
1801 case SSH_ERR_NO_HOSTKEY_ALG_MATCH: 1825 case SSH_ERR_NO_HOSTKEY_ALG_MATCH:
1802 if (ssh && ssh->kex && ssh->kex->failed_choice) { 1826 if (ssh && ssh->kex && ssh->kex->failed_choice) {
1827 ssh_packet_clear_keys(ssh);
1803 logdie("Unable to negotiate with %s: %s. " 1828 logdie("Unable to negotiate with %s: %s. "
1804 "Their offer: %s", remote_id, ssh_err(r), 1829 "Their offer: %s", remote_id, ssh_err(r),
1805 ssh->kex->failed_choice); 1830 ssh->kex->failed_choice);
1806 } 1831 }
1807 /* FALLTHROUGH */ 1832 /* FALLTHROUGH */
1808 default: 1833 default:
1834 ssh_packet_clear_keys(ssh);
1809 logdie("%s%sConnection %s %s: %s", 1835 logdie("%s%sConnection %s %s: %s",
1810 tag != NULL ? tag : "", tag != NULL ? ": " : "", 1836 tag != NULL ? tag : "", tag != NULL ? ": " : "",
1811 ssh->state->server_side ? "from" : "to", 1837 ssh->state->server_side ? "from" : "to",
diff --git a/packet.h b/packet.h
index 2b8069cd6..6ce6dd560 100644
--- a/packet.h
+++ b/packet.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.h,v 1.80 2017/05/30 14:18:15 markus Exp $ */ 1/* $OpenBSD: packet.h,v 1.81 2017/05/31 08:09:45 markus Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -97,6 +97,8 @@ int ssh_packet_get_connection_in(struct ssh *);
97int ssh_packet_get_connection_out(struct ssh *); 97int ssh_packet_get_connection_out(struct ssh *);
98void ssh_packet_close(struct ssh *); 98void ssh_packet_close(struct ssh *);
99void ssh_packet_set_input_hook(struct ssh *, ssh_packet_hook_fn *, void *); 99void ssh_packet_set_input_hook(struct ssh *, ssh_packet_hook_fn *, void *);
100void ssh_packet_clear_keys(struct ssh *);
101void ssh_clear_newkeys(struct ssh *, int);
100 102
101int ssh_packet_is_rekeying(struct ssh *); 103int ssh_packet_is_rekeying(struct ssh *);
102void ssh_packet_set_protocol_flags(struct ssh *, u_int); 104void ssh_packet_set_protocol_flags(struct ssh *, u_int);
diff --git a/session.c b/session.c
index a08aa69d1..cbd27c689 100644
--- a/session.c
+++ b/session.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: session.c,v 1.286 2016/11/30 03:00:05 djm Exp $ */ 1/* $OpenBSD: session.c,v 1.287 2017/05/31 08:09:45 markus Exp $ */
2/* 2/*
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved 4 * All rights reserved
@@ -1486,6 +1486,7 @@ do_child(Session *s, const char *command)
1486 1486
1487 /* remove hostkey from the child's memory */ 1487 /* remove hostkey from the child's memory */
1488 destroy_sensitive_data(); 1488 destroy_sensitive_data();
1489 packet_clear_keys();
1489 1490
1490 /* Force a password change */ 1491 /* Force a password change */
1491 if (s->authctxt->force_pwchange) { 1492 if (s->authctxt->force_pwchange) {
diff --git a/sshd.c b/sshd.c
index aa3729e7d..06cb81f27 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshd.c,v 1.489 2017/05/31 07:00:13 markus Exp $ */ 1/* $OpenBSD: sshd.c,v 1.490 2017/05/31 08:09:45 markus 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
@@ -649,6 +649,7 @@ privsep_postauth(Authctxt *authctxt)
649 else if (pmonitor->m_pid != 0) { 649 else if (pmonitor->m_pid != 0) {
650 verbose("User child is on pid %ld", (long)pmonitor->m_pid); 650 verbose("User child is on pid %ld", (long)pmonitor->m_pid);
651 buffer_clear(&loginmsg); 651 buffer_clear(&loginmsg);
652 monitor_clear_keystate(pmonitor);
652 monitor_child_postauth(pmonitor); 653 monitor_child_postauth(pmonitor);
653 654
654 /* NEVERREACHED */ 655 /* NEVERREACHED */
@@ -2032,6 +2033,7 @@ main(int ac, char **av)
2032 */ 2033 */
2033 if (use_privsep) { 2034 if (use_privsep) {
2034 mm_send_keystate(pmonitor); 2035 mm_send_keystate(pmonitor);
2036 packet_clear_keys();
2035 exit(0); 2037 exit(0);
2036 } 2038 }
2037 2039
diff --git a/umac.c b/umac.c
index 6eb55b26e..9f2187c9a 100644
--- a/umac.c
+++ b/umac.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: umac.c,v 1.11 2014/07/22 07:13:42 guenther Exp $ */ 1/* $OpenBSD: umac.c,v 1.12 2017/05/31 08:09:45 markus Exp $ */
2/* ----------------------------------------------------------------------- 2/* -----------------------------------------------------------------------
3 * 3 *
4 * umac.c -- C Implementation UMAC Message Authentication 4 * umac.c -- C Implementation UMAC Message Authentication
@@ -203,6 +203,8 @@ static void kdf(void *bufp, aes_int_key key, UINT8 ndx, int nbytes)
203 aes_encryption(in_buf, out_buf, key); 203 aes_encryption(in_buf, out_buf, key);
204 memcpy(dst_buf,out_buf,nbytes); 204 memcpy(dst_buf,out_buf,nbytes);
205 } 205 }
206 explicit_bzero(in_buf, sizeof(in_buf));
207 explicit_bzero(out_buf, sizeof(out_buf));
206} 208}
207 209
208/* The final UHASH result is XOR'd with the output of a pseudorandom 210/* The final UHASH result is XOR'd with the output of a pseudorandom
@@ -227,6 +229,7 @@ static void pdf_init(pdf_ctx *pc, aes_int_key prf_key)
227 /* Initialize pdf and cache */ 229 /* Initialize pdf and cache */
228 memset(pc->nonce, 0, sizeof(pc->nonce)); 230 memset(pc->nonce, 0, sizeof(pc->nonce));
229 aes_encryption(pc->nonce, pc->cache, pc->prf_key); 231 aes_encryption(pc->nonce, pc->cache, pc->prf_key);
232 explicit_bzero(buf, sizeof(buf));
230} 233}
231 234
232static void pdf_gen_xor(pdf_ctx *pc, const UINT8 nonce[8], UINT8 buf[8]) 235static void pdf_gen_xor(pdf_ctx *pc, const UINT8 nonce[8], UINT8 buf[8])
@@ -991,6 +994,7 @@ static void uhash_init(uhash_ctx_t ahc, aes_int_key prf_key)
991 kdf(ahc->ip_trans, prf_key, 4, STREAMS * sizeof(UINT32)); 994 kdf(ahc->ip_trans, prf_key, 4, STREAMS * sizeof(UINT32));
992 endian_convert_if_le(ahc->ip_trans, sizeof(UINT32), 995 endian_convert_if_le(ahc->ip_trans, sizeof(UINT32),
993 STREAMS * sizeof(UINT32)); 996 STREAMS * sizeof(UINT32));
997 explicit_bzero(buf, sizeof(buf));
994} 998}
995 999
996/* ---------------------------------------------------------------------- */ 1000/* ---------------------------------------------------------------------- */
@@ -1200,6 +1204,7 @@ int umac_delete(struct umac_ctx *ctx)
1200 if (ctx) { 1204 if (ctx) {
1201 if (ALLOC_BOUNDARY) 1205 if (ALLOC_BOUNDARY)
1202 ctx = (struct umac_ctx *)ctx->free_ptr; 1206 ctx = (struct umac_ctx *)ctx->free_ptr;
1207 explicit_bzero(ctx, sizeof(*ctx) + ALLOC_BOUNDARY);
1203 free(ctx); 1208 free(ctx);
1204 } 1209 }
1205 return (1); 1210 return (1);
@@ -1227,6 +1232,7 @@ struct umac_ctx *umac_new(const u_char key[])
1227 aes_key_setup(key, prf_key); 1232 aes_key_setup(key, prf_key);
1228 pdf_init(&ctx->pdf, prf_key); 1233 pdf_init(&ctx->pdf, prf_key);
1229 uhash_init(&ctx->hash, prf_key); 1234 uhash_init(&ctx->hash, prf_key);
1235 explicit_bzero(prf_key, sizeof(prf_key));
1230 } 1236 }
1231 1237
1232 return (ctx); 1238 return (ctx);