summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2012-12-12 10:46:31 +1100
committerDamien Miller <djm@mindrot.org>2012-12-12 10:46:31 +1100
commitaf43a7ac2d77c57112b48f34c7a72be2adb761bc (patch)
tree4381616492fbbca62d39c042f16221f681c1d37f
parent6a1937eac5da5bdcf33aaa922ce5de0c764e37ed (diff)
- markus@cvs.openbsd.org 2012/12/11 22:31:18
[PROTOCOL authfile.c cipher.c cipher.h kex.h mac.c myproposal.h] [packet.c ssh_config.5 sshd_config.5] add encrypt-then-mac (EtM) modes to openssh by defining new mac algorithms that change the packet format and compute the MAC over the encrypted message (including the packet size) instead of the plaintext data; these EtM modes are considered more secure and used by default. feedback and ok djm@
-rw-r--r--ChangeLog8
-rw-r--r--PROTOCOL29
-rw-r--r--authfile.c6
-rw-r--r--cipher.c22
-rw-r--r--cipher.h4
-rw-r--r--kex.h3
-rw-r--r--mac.c40
-rw-r--r--myproposal.h11
-rw-r--r--packet.c113
-rw-r--r--ssh_config.513
-rw-r--r--sshd_config.513
11 files changed, 196 insertions, 66 deletions
diff --git a/ChangeLog b/ChangeLog
index b96329ef2..df6d03207 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,14 @@
4 [monitor.c] 4 [monitor.c]
5 drain the log messages after receiving the keystate from the unpriv 5 drain the log messages after receiving the keystate from the unpriv
6 child. otherwise it might block while sending. ok djm@ 6 child. otherwise it might block while sending. ok djm@
7 - markus@cvs.openbsd.org 2012/12/11 22:31:18
8 [PROTOCOL authfile.c cipher.c cipher.h kex.h mac.c myproposal.h]
9 [packet.c ssh_config.5 sshd_config.5]
10 add encrypt-then-mac (EtM) modes to openssh by defining new mac algorithms
11 that change the packet format and compute the MAC over the encrypted
12 message (including the packet size) instead of the plaintext data;
13 these EtM modes are considered more secure and used by default.
14 feedback and ok djm@
7 15
820121207 1620121207
9 - (dtucker) OpenBSD CVS Sync 17 - (dtucker) OpenBSD CVS Sync
diff --git a/PROTOCOL b/PROTOCOL
index c28196011..834716cc9 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -51,6 +51,33 @@ and ecdsa-sha2-nistp521 curves over GF(p) are supported. Elliptic
51curve points encoded using point compression are NOT accepted or 51curve points encoded using point compression are NOT accepted or
52generated. 52generated.
53 53
541.5 transport: Protocol 2 Encrypt-then-MAC MAC algorithms
55
56OpenSSH supports MAC algorithms, whose names contain "-etm", that
57perform the calculations in a different order to that defined in RFC
584253. These variants use the so-called "encrypt then MAC" ordering,
59calculating the MAC over the packet ciphertext rather than the
60plaintext. This ordering closes a security flaw in the SSH transport
61protocol, where decryption of unauthenticated ciphertext provided a
62"decryption oracle" that could, in conjunction with cipher flaws, reveal
63session plaintext.
64
65Specifically, the "-etm" MAC algorithms modify the transport protocol
66to calculate the MAC over the packet ciphertext and to send the packet
67length unencrypted. This is necessary for the transport to obtain the
68length of the packet and location of the MAC tag so that it may be
69verified without decrypting unauthenticated data.
70
71As such, the MAC covers:
72
73 mac = MAC(key, sequence_number || encrypted_packet)
74
75where "encrypted_packet" contains:
76
77 byte padding_length
78 byte[n1] payload; n1 = packet_length - padding_length - 1
79 byte[n2] random padding; n2 = padding_length
80
542. Connection protocol changes 812. Connection protocol changes
55 82
562.1. connection: Channel write close extension "eow@openssh.com" 832.1. connection: Channel write close extension "eow@openssh.com"
@@ -291,4 +318,4 @@ link(oldpath, newpath) and will respond with a SSH_FXP_STATUS message.
291This extension is advertised in the SSH_FXP_VERSION hello with version 318This extension is advertised in the SSH_FXP_VERSION hello with version
292"1". 319"1".
293 320
294$OpenBSD: PROTOCOL,v 1.17 2010/12/04 00:18:01 djm Exp $ 321$OpenBSD: PROTOCOL,v 1.18 2012/12/11 22:31:18 markus Exp $
diff --git a/authfile.c b/authfile.c
index 7dd449690..d9ee4ca65 100644
--- a/authfile.c
+++ b/authfile.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: authfile.c,v 1.93 2012/01/25 19:36:31 markus Exp $ */ 1/* $OpenBSD: authfile.c,v 1.94 2012/12/11 22:31:18 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
@@ -150,7 +150,7 @@ key_private_rsa1_to_blob(Key *key, Buffer *blob, const char *passphrase,
150 cipher_set_key_string(&ciphercontext, cipher, passphrase, 150 cipher_set_key_string(&ciphercontext, cipher, passphrase,
151 CIPHER_ENCRYPT); 151 CIPHER_ENCRYPT);
152 cipher_crypt(&ciphercontext, cp, 152 cipher_crypt(&ciphercontext, cp,
153 buffer_ptr(&buffer), buffer_len(&buffer)); 153 buffer_ptr(&buffer), buffer_len(&buffer), 0);
154 cipher_cleanup(&ciphercontext); 154 cipher_cleanup(&ciphercontext);
155 memset(&ciphercontext, 0, sizeof(ciphercontext)); 155 memset(&ciphercontext, 0, sizeof(ciphercontext));
156 156
@@ -474,7 +474,7 @@ key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp)
474 cipher_set_key_string(&ciphercontext, cipher, passphrase, 474 cipher_set_key_string(&ciphercontext, cipher, passphrase,
475 CIPHER_DECRYPT); 475 CIPHER_DECRYPT);
476 cipher_crypt(&ciphercontext, cp, 476 cipher_crypt(&ciphercontext, cp,
477 buffer_ptr(&copy), buffer_len(&copy)); 477 buffer_ptr(&copy), buffer_len(&copy), 0);
478 cipher_cleanup(&ciphercontext); 478 cipher_cleanup(&ciphercontext);
479 memset(&ciphercontext, 0, sizeof(ciphercontext)); 479 memset(&ciphercontext, 0, sizeof(ciphercontext));
480 buffer_free(&copy); 480 buffer_free(&copy);
diff --git a/cipher.c b/cipher.c
index bb5c0ac3a..2116b55b1 100644
--- a/cipher.c
+++ b/cipher.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: cipher.c,v 1.82 2009/01/26 09:58:15 markus Exp $ */ 1/* $OpenBSD: cipher.c,v 1.83 2012/12/11 22:31:18 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
@@ -273,13 +273,25 @@ cipher_init(CipherContext *cc, Cipher *cipher,
273 } 273 }
274} 274}
275 275
276/*
277 * cipher_crypt() operates as following:
278 * Copy 'aadlen' bytes (without en/decryption) from 'src' to 'dest'.
279 * Theses bytes are treated as additional authenticated data for
280 * authenticated encryption modes.
281 * En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'.
282 * Both 'aadlen' and 'authlen' can be set to 0.
283 */
276void 284void
277cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) 285cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src,
286 u_int len, u_int aadlen)
278{ 287{
288 if (aadlen)
289 memcpy(dest, src, aadlen);
279 if (len % cc->cipher->block_size) 290 if (len % cc->cipher->block_size)
280 fatal("cipher_encrypt: bad plaintext length %d", len); 291 fatal("%s: bad plaintext length %d", __func__, len);
281 if (EVP_Cipher(&cc->evp, dest, (u_char *)src, len) == 0) 292 if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen,
282 fatal("evp_crypt: EVP_Cipher failed"); 293 len) < 0)
294 fatal("%s: EVP_Cipher failed", __func__);
283} 295}
284 296
285void 297void
diff --git a/cipher.h b/cipher.h
index 3dd2270bb..78972fea5 100644
--- a/cipher.h
+++ b/cipher.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: cipher.h,v 1.37 2009/01/26 09:58:15 markus Exp $ */ 1/* $OpenBSD: cipher.h,v 1.38 2012/12/11 22:31:18 markus Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -76,7 +76,7 @@ char *cipher_name(int);
76int ciphers_valid(const char *); 76int ciphers_valid(const char *);
77void cipher_init(CipherContext *, Cipher *, const u_char *, u_int, 77void cipher_init(CipherContext *, Cipher *, const u_char *, u_int,
78 const u_char *, u_int, int); 78 const u_char *, u_int, int);
79void cipher_crypt(CipherContext *, u_char *, const u_char *, u_int); 79void cipher_crypt(CipherContext *, u_char *, const u_char *, u_int, u_int);
80void cipher_cleanup(CipherContext *); 80void cipher_cleanup(CipherContext *);
81void cipher_set_key_string(CipherContext *, Cipher *, const char *, int); 81void cipher_set_key_string(CipherContext *, Cipher *, const char *, int);
82u_int cipher_blocksize(const Cipher *); 82u_int cipher_blocksize(const Cipher *);
diff --git a/kex.h b/kex.h
index 7373d3c78..03b984cc8 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.h,v 1.52 2010/09/22 05:01:29 djm Exp $ */ 1/* $OpenBSD: kex.h,v 1.53 2012/12/11 22:31:18 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -100,6 +100,7 @@ struct Mac {
100 u_char *key; 100 u_char *key;
101 u_int key_len; 101 u_int key_len;
102 int type; 102 int type;
103 int etm; /* Encrypt-then-MAC */
103 const EVP_MD *evp_md; 104 const EVP_MD *evp_md;
104 HMAC_CTX evp_ctx; 105 HMAC_CTX evp_ctx;
105 struct umac_ctx *umac_ctx; 106 struct umac_ctx *umac_ctx;
diff --git a/mac.c b/mac.c
index 47db127f5..0ece2e55d 100644
--- a/mac.c
+++ b/mac.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: mac.c,v 1.19 2012/10/04 13:21:50 markus Exp $ */ 1/* $OpenBSD: mac.c,v 1.20 2012/12/11 22:31:18 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -58,19 +58,34 @@ struct {
58 int key_len; /* just for UMAC */ 58 int key_len; /* just for UMAC */
59 int len; /* just for UMAC */ 59 int len; /* just for UMAC */
60} macs[] = { 60} macs[] = {
61 { "hmac-sha1", SSH_EVP, EVP_sha1, 0, -1, -1 }, 61 /* Encrypt-and-MAC (encrypt-and-authenticate) variants */
62 { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, -1, -1 }, 62 { "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0, 0, 0 },
63 { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, 0, 0, 0 },
63#ifdef HAVE_EVP_SHA256 64#ifdef HAVE_EVP_SHA256
64 { "hmac-sha2-256", SSH_EVP, EVP_sha256, 0, -1, -1 }, 65 { "hmac-sha2-256", SSH_EVP, EVP_sha256, 0, 0, 0, 0 },
65 { "hmac-sha2-512", SSH_EVP, EVP_sha512, 0, -1, -1 }, 66 { "hmac-sha2-512", SSH_EVP, EVP_sha512, 0, 0, 0, 0 },
66#endif 67#endif
67 { "hmac-md5", SSH_EVP, EVP_md5, 0, -1, -1 }, 68 { "hmac-md5", SSH_EVP, EVP_md5, 0, 0, 0, 0 },
68 { "hmac-md5-96", SSH_EVP, EVP_md5, 96, -1, -1 }, 69 { "hmac-md5-96", SSH_EVP, EVP_md5, 96, 0, 0, 0 },
69 { "hmac-ripemd160", SSH_EVP, EVP_ripemd160, 0, -1, -1 }, 70 { "hmac-ripemd160", SSH_EVP, EVP_ripemd160, 0, 0, 0, 0 },
70 { "hmac-ripemd160@openssh.com", SSH_EVP, EVP_ripemd160, 0, -1, -1 }, 71 { "hmac-ripemd160@openssh.com", SSH_EVP, EVP_ripemd160, 0, 0, 0, 0 },
71 { "umac-64@openssh.com", SSH_UMAC, NULL, 0, 128, 64 }, 72 { "umac-64@openssh.com", SSH_UMAC, NULL, 0, 128, 64, 0 },
72 { "umac-128@openssh.com", SSH_UMAC128, NULL, 0, 128, 128 }, 73 { "umac-128@openssh.com", SSH_UMAC128, NULL, 0, 128, 128, 0 },
73 { NULL, 0, NULL, 0, -1, -1 } 74
75 /* Encrypt-then-MAC variants */
76 { "hmac-sha1-etm@openssh.com", SSH_EVP, EVP_sha1, 0, 0, 0, 1 },
77 { "hmac-sha1-96-etm@openssh.com", SSH_EVP, EVP_sha1, 96, 0, 0, 1 },
78#ifdef HAVE_EVP_SHA256
79 { "hmac-sha2-256-etm@openssh.com", SSH_EVP, EVP_sha256, 0, 0, 0, 1 },
80 { "hmac-sha2-512-etm@openssh.com", SSH_EVP, EVP_sha512, 0, 0, 0, 1 },
81#endif
82 { "hmac-md5-etm@openssh.com", SSH_EVP, EVP_md5, 0, 0, 0, 1 },
83 { "hmac-md5-96-etm@openssh.com", SSH_EVP, EVP_md5, 96, 0, 0, 1 },
84 { "hmac-ripemd160-tem@openssh.com", SSH_EVP, EVP_ripemd160, 0, 0, 0, 1 },
85 { "umac-64-etm@openssh.com", SSH_UMAC, NULL, 0, 128, 64, 1 },
86 { "umac-128-etm@openssh.com", SSH_UMAC128, NULL, 0, 128, 128, 1 },
87
88 { NULL, 0, NULL, 0, 0, 0, 0 }
74}; 89};
75 90
76static void 91static void
@@ -90,6 +105,7 @@ mac_setup_by_id(Mac *mac, int which)
90 } 105 }
91 if (macs[which].truncatebits != 0) 106 if (macs[which].truncatebits != 0)
92 mac->mac_len = macs[which].truncatebits / 8; 107 mac->mac_len = macs[which].truncatebits / 8;
108 mac->etm = macs[which].etm;
93} 109}
94 110
95int 111int
diff --git a/myproposal.h b/myproposal.h
index 5e2b99857..d98f4b051 100644
--- a/myproposal.h
+++ b/myproposal.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: myproposal.h,v 1.30 2012/10/04 13:21:50 markus Exp $ */ 1/* $OpenBSD: myproposal.h,v 1.31 2012/12/11 22:31:18 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -83,6 +83,15 @@
83# define SHA2_HMAC_MODES 83# define SHA2_HMAC_MODES
84#endif 84#endif
85#define KEX_DEFAULT_MAC \ 85#define KEX_DEFAULT_MAC \
86 "hmac-md5-etm@openssh.com," \
87 "hmac-sha1-etm@openssh.com," \
88 "umac-64-etm@openssh.com," \
89 "umac-128-etm@openssh.com," \
90 "hmac-sha2-256-etm@openssh.com," \
91 "hmac-sha2-512-etm@openssh.com," \
92 "hmac-ripemd160-etm@openssh.com," \
93 "hmac-sha1-96-etm@openssh.com," \
94 "hmac-md5-96-etm@openssh.com," \
86 "hmac-md5," \ 95 "hmac-md5," \
87 "hmac-sha1," \ 96 "hmac-sha1," \
88 "umac-64@openssh.com," \ 97 "umac-64@openssh.com," \
diff --git a/packet.c b/packet.c
index b75c081f0..be8907854 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.c,v 1.177 2012/09/17 13:04:11 markus Exp $ */ 1/* $OpenBSD: packet.c,v 1.178 2012/12/11 22:31:18 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
@@ -275,7 +275,7 @@ packet_stop_discard(void)
275static void 275static void
276packet_start_discard(Enc *enc, Mac *mac, u_int packet_length, u_int discard) 276packet_start_discard(Enc *enc, Mac *mac, u_int packet_length, u_int discard)
277{ 277{
278 if (enc == NULL || !cipher_is_cbc(enc->cipher)) 278 if (enc == NULL || !cipher_is_cbc(enc->cipher) || (mac && mac->etm))
279 packet_disconnect("Packet corrupt"); 279 packet_disconnect("Packet corrupt");
280 if (packet_length != PACKET_MAX_SIZE && mac && mac->enabled) 280 if (packet_length != PACKET_MAX_SIZE && mac && mac->enabled)
281 active_state->packet_discard_mac = mac; 281 active_state->packet_discard_mac = mac;
@@ -709,7 +709,7 @@ packet_send1(void)
709 buffer_len(&active_state->outgoing_packet)); 709 buffer_len(&active_state->outgoing_packet));
710 cipher_crypt(&active_state->send_context, cp, 710 cipher_crypt(&active_state->send_context, cp,
711 buffer_ptr(&active_state->outgoing_packet), 711 buffer_ptr(&active_state->outgoing_packet),
712 buffer_len(&active_state->outgoing_packet)); 712 buffer_len(&active_state->outgoing_packet), 0);
713 713
714#ifdef PACKET_DEBUG 714#ifdef PACKET_DEBUG
715 fprintf(stderr, "encrypted: "); 715 fprintf(stderr, "encrypted: ");
@@ -845,9 +845,8 @@ static void
845packet_send2_wrapped(void) 845packet_send2_wrapped(void)
846{ 846{
847 u_char type, *cp, *macbuf = NULL; 847 u_char type, *cp, *macbuf = NULL;
848 u_char padlen, pad; 848 u_char padlen, pad = 0;
849 u_int packet_length = 0; 849 u_int i, len, aadlen = 0;
850 u_int i, len;
851 u_int32_t rnd = 0; 850 u_int32_t rnd = 0;
852 Enc *enc = NULL; 851 Enc *enc = NULL;
853 Mac *mac = NULL; 852 Mac *mac = NULL;
@@ -860,6 +859,7 @@ packet_send2_wrapped(void)
860 comp = &active_state->newkeys[MODE_OUT]->comp; 859 comp = &active_state->newkeys[MODE_OUT]->comp;
861 } 860 }
862 block_size = enc ? enc->block_size : 8; 861 block_size = enc ? enc->block_size : 8;
862 aadlen = mac && mac->enabled && mac->etm ? 4 : 0;
863 863
864 cp = buffer_ptr(&active_state->outgoing_packet); 864 cp = buffer_ptr(&active_state->outgoing_packet);
865 type = cp[5]; 865 type = cp[5];
@@ -892,6 +892,7 @@ packet_send2_wrapped(void)
892 * calc size of padding, alloc space, get random data, 892 * calc size of padding, alloc space, get random data,
893 * minimum padding is 4 bytes 893 * minimum padding is 4 bytes
894 */ 894 */
895 len -= aadlen; /* packet length is not encrypted for EtM modes */
895 padlen = block_size - (len % block_size); 896 padlen = block_size - (len % block_size);
896 if (padlen < 4) 897 if (padlen < 4)
897 padlen += block_size; 898 padlen += block_size;
@@ -919,29 +920,37 @@ packet_send2_wrapped(void)
919 /* clear padding */ 920 /* clear padding */
920 memset(cp, 0, padlen); 921 memset(cp, 0, padlen);
921 } 922 }
922 /* packet_length includes payload, padding and padding length field */ 923 /* sizeof (packet_len + pad_len + payload + padding) */
923 packet_length = buffer_len(&active_state->outgoing_packet) - 4; 924 len = buffer_len(&active_state->outgoing_packet);
924 cp = buffer_ptr(&active_state->outgoing_packet); 925 cp = buffer_ptr(&active_state->outgoing_packet);
925 put_u32(cp, packet_length); 926 /* packet_length includes payload, padding and padding length field */
927 put_u32(cp, len - 4);
926 cp[4] = padlen; 928 cp[4] = padlen;
927 DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen)); 929 DBG(debug("send: len %d (includes padlen %d, aadlen %d)",
930 len, padlen, aadlen));
928 931
929 /* compute MAC over seqnr and packet(length fields, payload, padding) */ 932 /* compute MAC over seqnr and packet(length fields, payload, padding) */
930 if (mac && mac->enabled) { 933 if (mac && mac->enabled && !mac->etm) {
931 macbuf = mac_compute(mac, active_state->p_send.seqnr, 934 macbuf = mac_compute(mac, active_state->p_send.seqnr,
932 buffer_ptr(&active_state->outgoing_packet), 935 buffer_ptr(&active_state->outgoing_packet), len);
933 buffer_len(&active_state->outgoing_packet));
934 DBG(debug("done calc MAC out #%d", active_state->p_send.seqnr)); 936 DBG(debug("done calc MAC out #%d", active_state->p_send.seqnr));
935 } 937 }
936 /* encrypt packet and append to output buffer. */ 938 /* encrypt packet and append to output buffer. */
937 cp = buffer_append_space(&active_state->output, 939 cp = buffer_append_space(&active_state->output, len);
938 buffer_len(&active_state->outgoing_packet));
939 cipher_crypt(&active_state->send_context, cp, 940 cipher_crypt(&active_state->send_context, cp,
940 buffer_ptr(&active_state->outgoing_packet), 941 buffer_ptr(&active_state->outgoing_packet),
941 buffer_len(&active_state->outgoing_packet)); 942 len - aadlen, aadlen);
942 /* append unencrypted MAC */ 943 /* append unencrypted MAC */
943 if (mac && mac->enabled) 944 if (mac && mac->enabled) {
945 if (mac->etm) {
946 /* EtM: compute mac over aadlen + cipher text */
947 macbuf = mac_compute(mac,
948 active_state->p_send.seqnr, cp, len);
949 DBG(debug("done calc MAC(EtM) out #%d",
950 active_state->p_send.seqnr));
951 }
944 buffer_append(&active_state->output, macbuf, mac->mac_len); 952 buffer_append(&active_state->output, macbuf, mac->mac_len);
953 }
945#ifdef PACKET_DEBUG 954#ifdef PACKET_DEBUG
946 fprintf(stderr, "encrypted: "); 955 fprintf(stderr, "encrypted: ");
947 buffer_dump(&active_state->output); 956 buffer_dump(&active_state->output);
@@ -952,8 +961,8 @@ packet_send2_wrapped(void)
952 if (++active_state->p_send.packets == 0) 961 if (++active_state->p_send.packets == 0)
953 if (!(datafellows & SSH_BUG_NOREKEY)) 962 if (!(datafellows & SSH_BUG_NOREKEY))
954 fatal("XXX too many packets with same key"); 963 fatal("XXX too many packets with same key");
955 active_state->p_send.blocks += (packet_length + 4) / block_size; 964 active_state->p_send.blocks += len / block_size;
956 active_state->p_send.bytes += packet_length + 4; 965 active_state->p_send.bytes += len;
957 buffer_clear(&active_state->outgoing_packet); 966 buffer_clear(&active_state->outgoing_packet);
958 967
959 if (type == SSH2_MSG_NEWKEYS) 968 if (type == SSH2_MSG_NEWKEYS)
@@ -1190,7 +1199,7 @@ packet_read_poll1(void)
1190 buffer_clear(&active_state->incoming_packet); 1199 buffer_clear(&active_state->incoming_packet);
1191 cp = buffer_append_space(&active_state->incoming_packet, padded_len); 1200 cp = buffer_append_space(&active_state->incoming_packet, padded_len);
1192 cipher_crypt(&active_state->receive_context, cp, 1201 cipher_crypt(&active_state->receive_context, cp,
1193 buffer_ptr(&active_state->input), padded_len); 1202 buffer_ptr(&active_state->input), padded_len, 0);
1194 1203
1195 buffer_consume(&active_state->input, padded_len); 1204 buffer_consume(&active_state->input, padded_len);
1196 1205
@@ -1238,8 +1247,8 @@ static int
1238packet_read_poll2(u_int32_t *seqnr_p) 1247packet_read_poll2(u_int32_t *seqnr_p)
1239{ 1248{
1240 u_int padlen, need; 1249 u_int padlen, need;
1241 u_char *macbuf, *cp, type; 1250 u_char *macbuf = NULL, *cp, type;
1242 u_int maclen, block_size; 1251 u_int maclen, aadlen = 0, block_size;
1243 Enc *enc = NULL; 1252 Enc *enc = NULL;
1244 Mac *mac = NULL; 1253 Mac *mac = NULL;
1245 Comp *comp = NULL; 1254 Comp *comp = NULL;
@@ -1254,8 +1263,22 @@ packet_read_poll2(u_int32_t *seqnr_p)
1254 } 1263 }
1255 maclen = mac && mac->enabled ? mac->mac_len : 0; 1264 maclen = mac && mac->enabled ? mac->mac_len : 0;
1256 block_size = enc ? enc->block_size : 8; 1265 block_size = enc ? enc->block_size : 8;
1266 aadlen = mac && mac->enabled && mac->etm ? 4 : 0;
1257 1267
1258 if (active_state->packlen == 0) { 1268 if (aadlen && active_state->packlen == 0) {
1269 if (buffer_len(&active_state->input) < 4)
1270 return SSH_MSG_NONE;
1271 cp = buffer_ptr(&active_state->input);
1272 active_state->packlen = get_u32(cp);
1273 if (active_state->packlen < 1 + 4 ||
1274 active_state->packlen > PACKET_MAX_SIZE) {
1275#ifdef PACKET_DEBUG
1276 buffer_dump(&active_state->input);
1277#endif
1278 logit("Bad packet length %u.", active_state->packlen);
1279 packet_disconnect("Packet corrupt");
1280 }
1281 } else if (active_state->packlen == 0) {
1259 /* 1282 /*
1260 * check if input size is less than the cipher block size, 1283 * check if input size is less than the cipher block size,
1261 * decrypt first block and extract length of incoming packet 1284 * decrypt first block and extract length of incoming packet
@@ -1266,7 +1289,7 @@ packet_read_poll2(u_int32_t *seqnr_p)
1266 cp = buffer_append_space(&active_state->incoming_packet, 1289 cp = buffer_append_space(&active_state->incoming_packet,
1267 block_size); 1290 block_size);
1268 cipher_crypt(&active_state->receive_context, cp, 1291 cipher_crypt(&active_state->receive_context, cp,
1269 buffer_ptr(&active_state->input), block_size); 1292 buffer_ptr(&active_state->input), block_size, 0);
1270 cp = buffer_ptr(&active_state->incoming_packet); 1293 cp = buffer_ptr(&active_state->incoming_packet);
1271 active_state->packlen = get_u32(cp); 1294 active_state->packlen = get_u32(cp);
1272 if (active_state->packlen < 1 + 4 || 1295 if (active_state->packlen < 1 + 4 ||
@@ -1279,13 +1302,21 @@ packet_read_poll2(u_int32_t *seqnr_p)
1279 PACKET_MAX_SIZE); 1302 PACKET_MAX_SIZE);
1280 return SSH_MSG_NONE; 1303 return SSH_MSG_NONE;
1281 } 1304 }
1282 DBG(debug("input: packet len %u", active_state->packlen+4));
1283 buffer_consume(&active_state->input, block_size); 1305 buffer_consume(&active_state->input, block_size);
1284 } 1306 }
1285 /* we have a partial packet of block_size bytes */ 1307 DBG(debug("input: packet len %u", active_state->packlen+4));
1286 need = 4 + active_state->packlen - block_size; 1308 if (aadlen) {
1287 DBG(debug("partial packet %d, need %d, maclen %d", block_size, 1309 /* only the payload is encrypted */
1288 need, maclen)); 1310 need = active_state->packlen;
1311 } else {
1312 /*
1313 * the payload size and the payload are encrypted, but we
1314 * have a partial packet of block_size bytes
1315 */
1316 need = 4 + active_state->packlen - block_size;
1317 }
1318 DBG(debug("partial packet: block %d, need %d, maclen %d, aadlen %d",
1319 block_size, need, maclen, aadlen));
1289 if (need % block_size != 0) { 1320 if (need % block_size != 0) {
1290 logit("padding error: need %d block %d mod %d", 1321 logit("padding error: need %d block %d mod %d",
1291 need, block_size, need % block_size); 1322 need, block_size, need % block_size);
@@ -1295,26 +1326,34 @@ packet_read_poll2(u_int32_t *seqnr_p)
1295 } 1326 }
1296 /* 1327 /*
1297 * check if the entire packet has been received and 1328 * check if the entire packet has been received and
1298 * decrypt into incoming_packet 1329 * decrypt into incoming_packet:
1330 * 'aadlen' bytes are unencrypted, but authenticated.
1331 * 'need' bytes are encrypted, followed by
1332 * 'maclen' bytes of message authentication code.
1299 */ 1333 */
1300 if (buffer_len(&active_state->input) < need + maclen) 1334 if (buffer_len(&active_state->input) < aadlen + need + maclen)
1301 return SSH_MSG_NONE; 1335 return SSH_MSG_NONE;
1302#ifdef PACKET_DEBUG 1336#ifdef PACKET_DEBUG
1303 fprintf(stderr, "read_poll enc/full: "); 1337 fprintf(stderr, "read_poll enc/full: ");
1304 buffer_dump(&active_state->input); 1338 buffer_dump(&active_state->input);
1305#endif 1339#endif
1306 cp = buffer_append_space(&active_state->incoming_packet, need); 1340 /* EtM: compute mac over encrypted input */
1341 if (mac && mac->enabled && mac->etm)
1342 macbuf = mac_compute(mac, active_state->p_read.seqnr,
1343 buffer_ptr(&active_state->input), aadlen + need);
1344 cp = buffer_append_space(&active_state->incoming_packet, aadlen + need);
1307 cipher_crypt(&active_state->receive_context, cp, 1345 cipher_crypt(&active_state->receive_context, cp,
1308 buffer_ptr(&active_state->input), need); 1346 buffer_ptr(&active_state->input), need, aadlen);
1309 buffer_consume(&active_state->input, need); 1347 buffer_consume(&active_state->input, aadlen + need);
1310 /* 1348 /*
1311 * compute MAC over seqnr and packet, 1349 * compute MAC over seqnr and packet,
1312 * increment sequence number for incoming packet 1350 * increment sequence number for incoming packet
1313 */ 1351 */
1314 if (mac && mac->enabled) { 1352 if (mac && mac->enabled) {
1315 macbuf = mac_compute(mac, active_state->p_read.seqnr, 1353 if (!mac->etm)
1316 buffer_ptr(&active_state->incoming_packet), 1354 macbuf = mac_compute(mac, active_state->p_read.seqnr,
1317 buffer_len(&active_state->incoming_packet)); 1355 buffer_ptr(&active_state->incoming_packet),
1356 buffer_len(&active_state->incoming_packet));
1318 if (timingsafe_bcmp(macbuf, buffer_ptr(&active_state->input), 1357 if (timingsafe_bcmp(macbuf, buffer_ptr(&active_state->input),
1319 mac->mac_len) != 0) { 1358 mac->mac_len) != 0) {
1320 logit("Corrupted MAC on input."); 1359 logit("Corrupted MAC on input.");
diff --git a/ssh_config.5 b/ssh_config.5
index 09a3cf035..ee466d800 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -33,8 +33,8 @@
33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35.\" 35.\"
36.\" $OpenBSD: ssh_config.5,v 1.159 2012/12/02 20:26:10 djm Exp $ 36.\" $OpenBSD: ssh_config.5,v 1.160 2012/12/11 22:31:18 markus Exp $
37.Dd $Mdocdate: December 2 2012 $ 37.Dd $Mdocdate: December 11 2012 $
38.Dt SSH_CONFIG 5 38.Dt SSH_CONFIG 5
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -792,8 +792,17 @@ in order of preference.
792The MAC algorithm is used in protocol version 2 792The MAC algorithm is used in protocol version 2
793for data integrity protection. 793for data integrity protection.
794Multiple algorithms must be comma-separated. 794Multiple algorithms must be comma-separated.
795The algorithms that contain
796.Dq -etm
797calculate the MAC after encryption (encrypt-then-mac).
798These are considered safer and their use recommended.
795The default is: 799The default is:
796.Bd -literal -offset indent 800.Bd -literal -offset indent
801hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,
802umac-64-etm@openssh.com,umac-128-etm@openssh.com,
803hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
804hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com,
805hmac-md5-96-etm@openssh.com,
797hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com, 806hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com,
798hmac-sha2-256,hmac-sha2-512,hmac-ripemd160, 807hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,
799hmac-sha1-96,hmac-md5-96 808hmac-sha1-96,hmac-md5-96
diff --git a/sshd_config.5 b/sshd_config.5
index ad3692b38..0f4aa639d 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -33,8 +33,8 @@
33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35.\" 35.\"
36.\" $OpenBSD: sshd_config.5,v 1.151 2012/12/03 08:33:03 jmc Exp $ 36.\" $OpenBSD: sshd_config.5,v 1.152 2012/12/11 22:31:18 markus Exp $
37.Dd $Mdocdate: December 3 2012 $ 37.Dd $Mdocdate: December 11 2012 $
38.Dt SSHD_CONFIG 5 38.Dt SSHD_CONFIG 5
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -706,8 +706,17 @@ Specifies the available MAC (message authentication code) algorithms.
706The MAC algorithm is used in protocol version 2 706The MAC algorithm is used in protocol version 2
707for data integrity protection. 707for data integrity protection.
708Multiple algorithms must be comma-separated. 708Multiple algorithms must be comma-separated.
709The algorithms that contain
710.Dq -etm
711calculate the MAC after encryption (encrypt-then-mac).
712These are considered safer and their use recommended.
709The default is: 713The default is:
710.Bd -literal -offset indent 714.Bd -literal -offset indent
715hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,
716umac-64-etm@openssh.com,umac-128-etm@openssh.com,
717hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
718hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com,
719hmac-md5-96-etm@openssh.com,
711hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com, 720hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com,
712hmac-sha2-256,hmac-sha2-512,hmac-ripemd160, 721hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,
713hmac-sha1-96,hmac-md5-96 722hmac-sha1-96,hmac-md5-96