summaryrefslogtreecommitdiff
path: root/packet.c
diff options
context:
space:
mode:
authormarkus@openbsd.org <markus@openbsd.org>2016-07-18 11:35:33 +0000
committerDamien Miller <djm@mindrot.org>2016-07-22 13:36:40 +1000
commitb98a2a8348e907b3d71caafd80f0be8fdd075943 (patch)
tree5827ba77ced2efb5136bad0b444356271ee1c853 /packet.c
parentdbf788b4d9d9490a5fff08a7b09888272bb10fcc (diff)
upstream commit
Reduce timing attack against obsolete CBC modes by always computing the MAC over a fixed size of data. Reported by Jean Paul Degabriele, Kenny Paterson, Torben Hansen and Martin Albrecht. ok djm@ Upstream-ID: f20a13279b00ba0afbacbcc1f04e62e9d41c2912
Diffstat (limited to 'packet.c')
-rw-r--r--packet.c37
1 files changed, 23 insertions, 14 deletions
diff --git a/packet.c b/packet.c
index 7290fc714..d6dad2da6 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.c,v 1.233 2016/07/18 06:08:01 djm Exp $ */ 1/* $OpenBSD: packet.c,v 1.234 2016/07/18 11:35:33 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
@@ -196,6 +196,7 @@ struct session_state {
196 196
197 /* XXX discard incoming data after MAC error */ 197 /* XXX discard incoming data after MAC error */
198 u_int packet_discard; 198 u_int packet_discard;
199 size_t packet_discard_mac_already;
199 struct sshmac *packet_discard_mac; 200 struct sshmac *packet_discard_mac;
200 201
201 /* Used in packet_read_poll2() */ 202 /* Used in packet_read_poll2() */
@@ -333,16 +334,18 @@ ssh_packet_stop_discard(struct ssh *ssh)
333 334
334 if (state->packet_discard_mac) { 335 if (state->packet_discard_mac) {
335 char buf[1024]; 336 char buf[1024];
337 size_t dlen = PACKET_MAX_SIZE;
336 338
339 if (dlen > state->packet_discard_mac_already)
340 dlen -= state->packet_discard_mac_already;
337 memset(buf, 'a', sizeof(buf)); 341 memset(buf, 'a', sizeof(buf));
338 while (sshbuf_len(state->incoming_packet) < 342 while (sshbuf_len(state->incoming_packet) < dlen)
339 PACKET_MAX_SIZE)
340 if ((r = sshbuf_put(state->incoming_packet, buf, 343 if ((r = sshbuf_put(state->incoming_packet, buf,
341 sizeof(buf))) != 0) 344 sizeof(buf))) != 0)
342 return r; 345 return r;
343 (void) mac_compute(state->packet_discard_mac, 346 (void) mac_compute(state->packet_discard_mac,
344 state->p_read.seqnr, 347 state->p_read.seqnr,
345 sshbuf_ptr(state->incoming_packet), PACKET_MAX_SIZE, 348 sshbuf_ptr(state->incoming_packet), dlen,
346 NULL, 0); 349 NULL, 0);
347 } 350 }
348 logit("Finished discarding for %.200s port %d", 351 logit("Finished discarding for %.200s port %d",
@@ -352,7 +355,7 @@ ssh_packet_stop_discard(struct ssh *ssh)
352 355
353static int 356static int
354ssh_packet_start_discard(struct ssh *ssh, struct sshenc *enc, 357ssh_packet_start_discard(struct ssh *ssh, struct sshenc *enc,
355 struct sshmac *mac, u_int packet_length, u_int discard) 358 struct sshmac *mac, size_t mac_already, u_int discard)
356{ 359{
357 struct session_state *state = ssh->state; 360 struct session_state *state = ssh->state;
358 int r; 361 int r;
@@ -362,11 +365,16 @@ ssh_packet_start_discard(struct ssh *ssh, struct sshenc *enc,
362 return r; 365 return r;
363 return SSH_ERR_MAC_INVALID; 366 return SSH_ERR_MAC_INVALID;
364 } 367 }
365 if (packet_length != PACKET_MAX_SIZE && mac && mac->enabled) 368 /*
369 * Record number of bytes over which the mac has already
370 * been computed in order to minimize timing attacks.
371 */
372 if (mac && mac->enabled) {
366 state->packet_discard_mac = mac; 373 state->packet_discard_mac = mac;
367 if (sshbuf_len(state->input) >= discard && 374 state->packet_discard_mac_already = mac_already;
368 (r = ssh_packet_stop_discard(ssh)) != 0) 375 }
369 return r; 376 if (sshbuf_len(state->input) >= discard)
377 return ssh_packet_stop_discard(ssh);
370 state->packet_discard = discard - sshbuf_len(state->input); 378 state->packet_discard = discard - sshbuf_len(state->input);
371 return 0; 379 return 0;
372} 380}
@@ -1765,8 +1773,8 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
1765 sshbuf_dump(state->incoming_packet, stderr); 1773 sshbuf_dump(state->incoming_packet, stderr);
1766#endif 1774#endif
1767 logit("Bad packet length %u.", state->packlen); 1775 logit("Bad packet length %u.", state->packlen);
1768 return ssh_packet_start_discard(ssh, enc, mac, 1776 return ssh_packet_start_discard(ssh, enc, mac, 0,
1769 state->packlen, PACKET_MAX_SIZE); 1777 PACKET_MAX_SIZE);
1770 } 1778 }
1771 if ((r = sshbuf_consume(state->input, block_size)) != 0) 1779 if ((r = sshbuf_consume(state->input, block_size)) != 0)
1772 goto out; 1780 goto out;
@@ -1788,8 +1796,8 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
1788 if (need % block_size != 0) { 1796 if (need % block_size != 0) {
1789 logit("padding error: need %d block %d mod %d", 1797 logit("padding error: need %d block %d mod %d",
1790 need, block_size, need % block_size); 1798 need, block_size, need % block_size);
1791 return ssh_packet_start_discard(ssh, enc, mac, 1799 return ssh_packet_start_discard(ssh, enc, mac, 0,
1792 state->packlen, PACKET_MAX_SIZE - block_size); 1800 PACKET_MAX_SIZE - block_size);
1793 } 1801 }
1794 /* 1802 /*
1795 * check if the entire packet has been received and 1803 * check if the entire packet has been received and
@@ -1836,7 +1844,8 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
1836 if (need > PACKET_MAX_SIZE) 1844 if (need > PACKET_MAX_SIZE)
1837 return SSH_ERR_INTERNAL_ERROR; 1845 return SSH_ERR_INTERNAL_ERROR;
1838 return ssh_packet_start_discard(ssh, enc, mac, 1846 return ssh_packet_start_discard(ssh, enc, mac,
1839 state->packlen, PACKET_MAX_SIZE - need); 1847 sshbuf_len(state->incoming_packet),
1848 PACKET_MAX_SIZE - need);
1840 } 1849 }
1841 /* Remove MAC from input buffer */ 1850 /* Remove MAC from input buffer */
1842 DBG(debug("MAC #%d ok", state->p_read.seqnr)); 1851 DBG(debug("MAC #%d ok", state->p_read.seqnr));