diff options
-rw-r--r-- | mac.c | 23 | ||||
-rw-r--r-- | mac.h | 4 | ||||
-rw-r--r-- | packet.c | 35 |
3 files changed, 41 insertions, 21 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mac.c,v 1.32 2015/01/15 18:32:54 naddy Exp $ */ | 1 | /* $OpenBSD: mac.c,v 1.33 2016/07/08 03:44:42 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -167,7 +167,8 @@ mac_init(struct sshmac *mac) | |||
167 | } | 167 | } |
168 | 168 | ||
169 | int | 169 | int |
170 | mac_compute(struct sshmac *mac, u_int32_t seqno, const u_char *data, int datalen, | 170 | mac_compute(struct sshmac *mac, u_int32_t seqno, |
171 | const u_char *data, int datalen, | ||
171 | u_char *digest, size_t dlen) | 172 | u_char *digest, size_t dlen) |
172 | { | 173 | { |
173 | static union { | 174 | static union { |
@@ -211,6 +212,24 @@ mac_compute(struct sshmac *mac, u_int32_t seqno, const u_char *data, int datalen | |||
211 | return 0; | 212 | return 0; |
212 | } | 213 | } |
213 | 214 | ||
215 | int | ||
216 | mac_check(struct sshmac *mac, u_int32_t seqno, | ||
217 | const u_char *data, size_t dlen, | ||
218 | const u_char *theirmac, size_t mlen) | ||
219 | { | ||
220 | u_char ourmac[SSH_DIGEST_MAX_LENGTH]; | ||
221 | int r; | ||
222 | |||
223 | if (mac->mac_len > mlen) | ||
224 | return SSH_ERR_INVALID_ARGUMENT; | ||
225 | if ((r = mac_compute(mac, seqno, data, dlen, | ||
226 | ourmac, sizeof(ourmac))) != 0) | ||
227 | return r; | ||
228 | if (timingsafe_bcmp(ourmac, theirmac, mac->mac_len) != 0) | ||
229 | return SSH_ERR_MAC_INVALID; | ||
230 | return 0; | ||
231 | } | ||
232 | |||
214 | void | 233 | void |
215 | mac_clear(struct sshmac *mac) | 234 | mac_clear(struct sshmac *mac) |
216 | { | 235 | { |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mac.h,v 1.9 2015/01/13 19:31:40 markus Exp $ */ | 1 | /* $OpenBSD: mac.h,v 1.10 2016/07/08 03:44:42 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -46,6 +46,8 @@ int mac_setup(struct sshmac *, char *); | |||
46 | int mac_init(struct sshmac *); | 46 | int mac_init(struct sshmac *); |
47 | int mac_compute(struct sshmac *, u_int32_t, const u_char *, int, | 47 | int mac_compute(struct sshmac *, u_int32_t, const u_char *, int, |
48 | u_char *, size_t); | 48 | u_char *, size_t); |
49 | int mac_check(struct sshmac *, u_int32_t, const u_char *, size_t, | ||
50 | const u_char *, size_t); | ||
49 | void mac_clear(struct sshmac *); | 51 | void mac_clear(struct sshmac *); |
50 | 52 | ||
51 | #endif /* SSHMAC_H */ | 53 | #endif /* SSHMAC_H */ |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: packet.c,v 1.230 2016/03/07 19:02:43 djm Exp $ */ | 1 | /* $OpenBSD: packet.c,v 1.231 2016/07/08 03:44:42 djm 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 |
@@ -1690,7 +1690,7 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) | |||
1690 | { | 1690 | { |
1691 | struct session_state *state = ssh->state; | 1691 | struct session_state *state = ssh->state; |
1692 | u_int padlen, need; | 1692 | u_int padlen, need; |
1693 | u_char *cp, macbuf[SSH_DIGEST_MAX_LENGTH]; | 1693 | u_char *cp; |
1694 | u_int maclen, aadlen = 0, authlen = 0, block_size; | 1694 | u_int maclen, aadlen = 0, authlen = 0, block_size; |
1695 | struct sshenc *enc = NULL; | 1695 | struct sshenc *enc = NULL; |
1696 | struct sshmac *mac = NULL; | 1696 | struct sshmac *mac = NULL; |
@@ -1790,17 +1790,21 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) | |||
1790 | * 'maclen' bytes of message authentication code. | 1790 | * 'maclen' bytes of message authentication code. |
1791 | */ | 1791 | */ |
1792 | if (sshbuf_len(state->input) < aadlen + need + authlen + maclen) | 1792 | if (sshbuf_len(state->input) < aadlen + need + authlen + maclen) |
1793 | return 0; | 1793 | return 0; /* packet is incomplete */ |
1794 | #ifdef PACKET_DEBUG | 1794 | #ifdef PACKET_DEBUG |
1795 | fprintf(stderr, "read_poll enc/full: "); | 1795 | fprintf(stderr, "read_poll enc/full: "); |
1796 | sshbuf_dump(state->input, stderr); | 1796 | sshbuf_dump(state->input, stderr); |
1797 | #endif | 1797 | #endif |
1798 | /* EtM: compute mac over encrypted input */ | 1798 | /* EtM: check mac over encrypted input */ |
1799 | if (mac && mac->enabled && mac->etm) { | 1799 | if (mac && mac->enabled && mac->etm) { |
1800 | if ((r = mac_compute(mac, state->p_read.seqnr, | 1800 | if ((r = mac_check(mac, state->p_read.seqnr, |
1801 | sshbuf_ptr(state->input), aadlen + need, | 1801 | sshbuf_ptr(state->input), aadlen + need, |
1802 | macbuf, sizeof(macbuf))) != 0) | 1802 | sshbuf_ptr(state->input) + aadlen + need + authlen, |
1803 | maclen)) != 0) { | ||
1804 | if (r == SSH_ERR_MAC_INVALID) | ||
1805 | logit("Corrupted MAC on input."); | ||
1803 | goto out; | 1806 | goto out; |
1807 | } | ||
1804 | } | 1808 | } |
1805 | if ((r = sshbuf_reserve(state->incoming_packet, aadlen + need, | 1809 | if ((r = sshbuf_reserve(state->incoming_packet, aadlen + need, |
1806 | &cp)) != 0) | 1810 | &cp)) != 0) |
@@ -1810,26 +1814,21 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) | |||
1810 | goto out; | 1814 | goto out; |
1811 | if ((r = sshbuf_consume(state->input, aadlen + need + authlen)) != 0) | 1815 | if ((r = sshbuf_consume(state->input, aadlen + need + authlen)) != 0) |
1812 | goto out; | 1816 | goto out; |
1813 | /* | ||
1814 | * compute MAC over seqnr and packet, | ||
1815 | * increment sequence number for incoming packet | ||
1816 | */ | ||
1817 | if (mac && mac->enabled) { | 1817 | if (mac && mac->enabled) { |
1818 | if (!mac->etm) | 1818 | /* Not EtM: check MAC over cleartext */ |
1819 | if ((r = mac_compute(mac, state->p_read.seqnr, | 1819 | if (!mac->etm && (r = mac_check(mac, state->p_read.seqnr, |
1820 | sshbuf_ptr(state->incoming_packet), | 1820 | sshbuf_ptr(state->incoming_packet), |
1821 | sshbuf_len(state->incoming_packet), | 1821 | sshbuf_len(state->incoming_packet), |
1822 | macbuf, sizeof(macbuf))) != 0) | 1822 | sshbuf_ptr(state->input), maclen)) != 0) { |
1823 | if (r != SSH_ERR_MAC_INVALID) | ||
1823 | goto out; | 1824 | goto out; |
1824 | if (timingsafe_bcmp(macbuf, sshbuf_ptr(state->input), | ||
1825 | mac->mac_len) != 0) { | ||
1826 | logit("Corrupted MAC on input."); | 1825 | logit("Corrupted MAC on input."); |
1827 | if (need > PACKET_MAX_SIZE) | 1826 | if (need > PACKET_MAX_SIZE) |
1828 | return SSH_ERR_INTERNAL_ERROR; | 1827 | return SSH_ERR_INTERNAL_ERROR; |
1829 | return ssh_packet_start_discard(ssh, enc, mac, | 1828 | return ssh_packet_start_discard(ssh, enc, mac, |
1830 | state->packlen, PACKET_MAX_SIZE - need); | 1829 | state->packlen, PACKET_MAX_SIZE - need); |
1831 | } | 1830 | } |
1832 | 1831 | /* Remove MAC from input buffer */ | |
1833 | DBG(debug("MAC #%d ok", state->p_read.seqnr)); | 1832 | DBG(debug("MAC #%d ok", state->p_read.seqnr)); |
1834 | if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0) | 1833 | if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0) |
1835 | goto out; | 1834 | goto out; |