summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 b96329ef..df6d0320 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,14 @@
[monitor.c]
drain the log messages after receiving the keystate from the unpriv
child. otherwise it might block while sending. ok djm@
+ - 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@
20121207
- (dtucker) OpenBSD CVS Sync
diff --git a/PROTOCOL b/PROTOCOL
index c2819601..834716cc 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -51,6 +51,33 @@ and ecdsa-sha2-nistp521 curves over GF(p) are supported. Elliptic
curve points encoded using point compression are NOT accepted or
generated.
+1.5 transport: Protocol 2 Encrypt-then-MAC MAC algorithms
+
+OpenSSH supports MAC algorithms, whose names contain "-etm", that
+perform the calculations in a different order to that defined in RFC
+4253. These variants use the so-called "encrypt then MAC" ordering,
+calculating the MAC over the packet ciphertext rather than the
+plaintext. This ordering closes a security flaw in the SSH transport
+protocol, where decryption of unauthenticated ciphertext provided a
+"decryption oracle" that could, in conjunction with cipher flaws, reveal
+session plaintext.
+
+Specifically, the "-etm" MAC algorithms modify the transport protocol
+to calculate the MAC over the packet ciphertext and to send the packet
+length unencrypted. This is necessary for the transport to obtain the
+length of the packet and location of the MAC tag so that it may be
+verified without decrypting unauthenticated data.
+
+As such, the MAC covers:
+
+ mac = MAC(key, sequence_number || encrypted_packet)
+
+where "encrypted_packet" contains:
+
+ byte padding_length
+ byte[n1] payload; n1 = packet_length - padding_length - 1
+ byte[n2] random padding; n2 = padding_length
+
2. Connection protocol changes
2.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.
This extension is advertised in the SSH_FXP_VERSION hello with version
"1".
-$OpenBSD: PROTOCOL,v 1.17 2010/12/04 00:18:01 djm Exp $
+$OpenBSD: PROTOCOL,v 1.18 2012/12/11 22:31:18 markus Exp $
diff --git a/authfile.c b/authfile.c
index 7dd44969..d9ee4ca6 100644
--- a/authfile.c
+++ b/authfile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfile.c,v 1.93 2012/01/25 19:36:31 markus Exp $ */
+/* $OpenBSD: authfile.c,v 1.94 2012/12/11 22:31:18 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* 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,
cipher_set_key_string(&ciphercontext, cipher, passphrase,
CIPHER_ENCRYPT);
cipher_crypt(&ciphercontext, cp,
- buffer_ptr(&buffer), buffer_len(&buffer));
+ buffer_ptr(&buffer), buffer_len(&buffer), 0);
cipher_cleanup(&ciphercontext);
memset(&ciphercontext, 0, sizeof(ciphercontext));
@@ -474,7 +474,7 @@ key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp)
cipher_set_key_string(&ciphercontext, cipher, passphrase,
CIPHER_DECRYPT);
cipher_crypt(&ciphercontext, cp,
- buffer_ptr(&copy), buffer_len(&copy));
+ buffer_ptr(&copy), buffer_len(&copy), 0);
cipher_cleanup(&ciphercontext);
memset(&ciphercontext, 0, sizeof(ciphercontext));
buffer_free(&copy);
diff --git a/cipher.c b/cipher.c
index bb5c0ac3..2116b55b 100644
--- a/cipher.c
+++ b/cipher.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cipher.c,v 1.82 2009/01/26 09:58:15 markus Exp $ */
+/* $OpenBSD: cipher.c,v 1.83 2012/12/11 22:31:18 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -273,13 +273,25 @@ cipher_init(CipherContext *cc, Cipher *cipher,
}
}
+/*
+ * cipher_crypt() operates as following:
+ * Copy 'aadlen' bytes (without en/decryption) from 'src' to 'dest'.
+ * Theses bytes are treated as additional authenticated data for
+ * authenticated encryption modes.
+ * En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'.
+ * Both 'aadlen' and 'authlen' can be set to 0.
+ */
void
-cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
+cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src,
+ u_int len, u_int aadlen)
{
+ if (aadlen)
+ memcpy(dest, src, aadlen);
if (len % cc->cipher->block_size)
- fatal("cipher_encrypt: bad plaintext length %d", len);
- if (EVP_Cipher(&cc->evp, dest, (u_char *)src, len) == 0)
- fatal("evp_crypt: EVP_Cipher failed");
+ fatal("%s: bad plaintext length %d", __func__, len);
+ if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen,
+ len) < 0)
+ fatal("%s: EVP_Cipher failed", __func__);
}
void
diff --git a/cipher.h b/cipher.h
index 3dd2270b..78972fea 100644
--- a/cipher.h
+++ b/cipher.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cipher.h,v 1.37 2009/01/26 09:58:15 markus Exp $ */
+/* $OpenBSD: cipher.h,v 1.38 2012/12/11 22:31:18 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -76,7 +76,7 @@ char *cipher_name(int);
int ciphers_valid(const char *);
void cipher_init(CipherContext *, Cipher *, const u_char *, u_int,
const u_char *, u_int, int);
-void cipher_crypt(CipherContext *, u_char *, const u_char *, u_int);
+void cipher_crypt(CipherContext *, u_char *, const u_char *, u_int, u_int);
void cipher_cleanup(CipherContext *);
void cipher_set_key_string(CipherContext *, Cipher *, const char *, int);
u_int cipher_blocksize(const Cipher *);
diff --git a/kex.h b/kex.h
index 7373d3c7..03b984cc 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.h,v 1.52 2010/09/22 05:01:29 djm Exp $ */
+/* $OpenBSD: kex.h,v 1.53 2012/12/11 22:31:18 markus Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -100,6 +100,7 @@ struct Mac {
u_char *key;
u_int key_len;
int type;
+ int etm; /* Encrypt-then-MAC */
const EVP_MD *evp_md;
HMAC_CTX evp_ctx;
struct umac_ctx *umac_ctx;
diff --git a/mac.c b/mac.c
index 47db127f..0ece2e55 100644
--- a/mac.c
+++ b/mac.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mac.c,v 1.19 2012/10/04 13:21:50 markus Exp $ */
+/* $OpenBSD: mac.c,v 1.20 2012/12/11 22:31:18 markus Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
@@ -58,19 +58,34 @@ struct {
int key_len; /* just for UMAC */
int len; /* just for UMAC */
} macs[] = {
- { "hmac-sha1", SSH_EVP, EVP_sha1, 0, -1, -1 },
- { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, -1, -1 },
+ /* Encrypt-and-MAC (encrypt-and-authenticate) variants */
+ { "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0, 0, 0 },
+ { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, 0, 0, 0 },
#ifdef HAVE_EVP_SHA256
- { "hmac-sha2-256", SSH_EVP, EVP_sha256, 0, -1, -1 },
- { "hmac-sha2-512", SSH_EVP, EVP_sha512, 0, -1, -1 },
+ { "hmac-sha2-256", SSH_EVP, EVP_sha256, 0, 0, 0, 0 },
+ { "hmac-sha2-512", SSH_EVP, EVP_sha512, 0, 0, 0, 0 },
#endif
- { "hmac-md5", SSH_EVP, EVP_md5, 0, -1, -1 },
- { "hmac-md5-96", SSH_EVP, EVP_md5, 96, -1, -1 },
- { "hmac-ripemd160", SSH_EVP, EVP_ripemd160, 0, -1, -1 },
- { "hmac-ripemd160@openssh.com", SSH_EVP, EVP_ripemd160, 0, -1, -1 },
- { "umac-64@openssh.com", SSH_UMAC, NULL, 0, 128, 64 },
- { "umac-128@openssh.com", SSH_UMAC128, NULL, 0, 128, 128 },
- { NULL, 0, NULL, 0, -1, -1 }
+ { "hmac-md5", SSH_EVP, EVP_md5, 0, 0, 0, 0 },
+ { "hmac-md5-96", SSH_EVP, EVP_md5, 96, 0, 0, 0 },
+ { "hmac-ripemd160", SSH_EVP, EVP_ripemd160, 0, 0, 0, 0 },
+ { "hmac-ripemd160@openssh.com", SSH_EVP, EVP_ripemd160, 0, 0, 0, 0 },
+ { "umac-64@openssh.com", SSH_UMAC, NULL, 0, 128, 64, 0 },
+ { "umac-128@openssh.com", SSH_UMAC128, NULL, 0, 128, 128, 0 },
+
+ /* Encrypt-then-MAC variants */
+ { "hmac-sha1-etm@openssh.com", SSH_EVP, EVP_sha1, 0, 0, 0, 1 },
+ { "hmac-sha1-96-etm@openssh.com", SSH_EVP, EVP_sha1, 96, 0, 0, 1 },
+#ifdef HAVE_EVP_SHA256
+ { "hmac-sha2-256-etm@openssh.com", SSH_EVP, EVP_sha256, 0, 0, 0, 1 },
+ { "hmac-sha2-512-etm@openssh.com", SSH_EVP, EVP_sha512, 0, 0, 0, 1 },
+#endif
+ { "hmac-md5-etm@openssh.com", SSH_EVP, EVP_md5, 0, 0, 0, 1 },
+ { "hmac-md5-96-etm@openssh.com", SSH_EVP, EVP_md5, 96, 0, 0, 1 },
+ { "hmac-ripemd160-tem@openssh.com", SSH_EVP, EVP_ripemd160, 0, 0, 0, 1 },
+ { "umac-64-etm@openssh.com", SSH_UMAC, NULL, 0, 128, 64, 1 },
+ { "umac-128-etm@openssh.com", SSH_UMAC128, NULL, 0, 128, 128, 1 },
+
+ { NULL, 0, NULL, 0, 0, 0, 0 }
};
static void
@@ -90,6 +105,7 @@ mac_setup_by_id(Mac *mac, int which)
}
if (macs[which].truncatebits != 0)
mac->mac_len = macs[which].truncatebits / 8;
+ mac->etm = macs[which].etm;
}
int
diff --git a/myproposal.h b/myproposal.h
index 5e2b9985..d98f4b05 100644
--- a/myproposal.h
+++ b/myproposal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: myproposal.h,v 1.30 2012/10/04 13:21:50 markus Exp $ */
+/* $OpenBSD: myproposal.h,v 1.31 2012/12/11 22:31:18 markus Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -83,6 +83,15 @@
# define SHA2_HMAC_MODES
#endif
#define KEX_DEFAULT_MAC \
+ "hmac-md5-etm@openssh.com," \
+ "hmac-sha1-etm@openssh.com," \
+ "umac-64-etm@openssh.com," \
+ "umac-128-etm@openssh.com," \
+ "hmac-sha2-256-etm@openssh.com," \
+ "hmac-sha2-512-etm@openssh.com," \
+ "hmac-ripemd160-etm@openssh.com," \
+ "hmac-sha1-96-etm@openssh.com," \
+ "hmac-md5-96-etm@openssh.com," \
"hmac-md5," \
"hmac-sha1," \
"umac-64@openssh.com," \
diff --git a/packet.c b/packet.c
index b75c081f..be890785 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.177 2012/09/17 13:04:11 markus Exp $ */
+/* $OpenBSD: packet.c,v 1.178 2012/12/11 22:31:18 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -275,7 +275,7 @@ packet_stop_discard(void)
static void
packet_start_discard(Enc *enc, Mac *mac, u_int packet_length, u_int discard)
{
- if (enc == NULL || !cipher_is_cbc(enc->cipher))
+ if (enc == NULL || !cipher_is_cbc(enc->cipher) || (mac && mac->etm))
packet_disconnect("Packet corrupt");
if (packet_length != PACKET_MAX_SIZE && mac && mac->enabled)
active_state->packet_discard_mac = mac;
@@ -709,7 +709,7 @@ packet_send1(void)
buffer_len(&active_state->outgoing_packet));
cipher_crypt(&active_state->send_context, cp,
buffer_ptr(&active_state->outgoing_packet),
- buffer_len(&active_state->outgoing_packet));
+ buffer_len(&active_state->outgoing_packet), 0);
#ifdef PACKET_DEBUG
fprintf(stderr, "encrypted: ");
@@ -845,9 +845,8 @@ static void
packet_send2_wrapped(void)
{
u_char type, *cp, *macbuf = NULL;
- u_char padlen, pad;
- u_int packet_length = 0;
- u_int i, len;
+ u_char padlen, pad = 0;
+ u_int i, len, aadlen = 0;
u_int32_t rnd = 0;
Enc *enc = NULL;
Mac *mac = NULL;
@@ -860,6 +859,7 @@ packet_send2_wrapped(void)
comp = &active_state->newkeys[MODE_OUT]->comp;
}
block_size = enc ? enc->block_size : 8;
+ aadlen = mac && mac->enabled && mac->etm ? 4 : 0;
cp = buffer_ptr(&active_state->outgoing_packet);
type = cp[5];
@@ -892,6 +892,7 @@ packet_send2_wrapped(void)
* calc size of padding, alloc space, get random data,
* minimum padding is 4 bytes
*/
+ len -= aadlen; /* packet length is not encrypted for EtM modes */
padlen = block_size - (len % block_size);
if (padlen < 4)
padlen += block_size;
@@ -919,29 +920,37 @@ packet_send2_wrapped(void)
/* clear padding */
memset(cp, 0, padlen);
}
- /* packet_length includes payload, padding and padding length field */
- packet_length = buffer_len(&active_state->outgoing_packet) - 4;
+ /* sizeof (packet_len + pad_len + payload + padding) */
+ len = buffer_len(&active_state->outgoing_packet);
cp = buffer_ptr(&active_state->outgoing_packet);
- put_u32(cp, packet_length);
+ /* packet_length includes payload, padding and padding length field */
+ put_u32(cp, len - 4);
cp[4] = padlen;
- DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen));
+ DBG(debug("send: len %d (includes padlen %d, aadlen %d)",
+ len, padlen, aadlen));
/* compute MAC over seqnr and packet(length fields, payload, padding) */
- if (mac && mac->enabled) {
+ if (mac && mac->enabled && !mac->etm) {
macbuf = mac_compute(mac, active_state->p_send.seqnr,
- buffer_ptr(&active_state->outgoing_packet),
- buffer_len(&active_state->outgoing_packet));
+ buffer_ptr(&active_state->outgoing_packet), len);
DBG(debug("done calc MAC out #%d", active_state->p_send.seqnr));
}
/* encrypt packet and append to output buffer. */
- cp = buffer_append_space(&active_state->output,
- buffer_len(&active_state->outgoing_packet));
+ cp = buffer_append_space(&active_state->output, len);
cipher_crypt(&active_state->send_context, cp,
buffer_ptr(&active_state->outgoing_packet),
- buffer_len(&active_state->outgoing_packet));
+ len - aadlen, aadlen);
/* append unencrypted MAC */
- if (mac && mac->enabled)
+ if (mac && mac->enabled) {
+ if (mac->etm) {
+ /* EtM: compute mac over aadlen + cipher text */
+ macbuf = mac_compute(mac,
+ active_state->p_send.seqnr, cp, len);
+ DBG(debug("done calc MAC(EtM) out #%d",
+ active_state->p_send.seqnr));
+ }
buffer_append(&active_state->output, macbuf, mac->mac_len);
+ }
#ifdef PACKET_DEBUG
fprintf(stderr, "encrypted: ");
buffer_dump(&active_state->output);
@@ -952,8 +961,8 @@ packet_send2_wrapped(void)
if (++active_state->p_send.packets == 0)
if (!(datafellows & SSH_BUG_NOREKEY))
fatal("XXX too many packets with same key");
- active_state->p_send.blocks += (packet_length + 4) / block_size;
- active_state->p_send.bytes += packet_length + 4;
+ active_state->p_send.blocks += len / block_size;
+ active_state->p_send.bytes += len;
buffer_clear(&active_state->outgoing_packet);
if (type == SSH2_MSG_NEWKEYS)
@@ -1190,7 +1199,7 @@ packet_read_poll1(void)
buffer_clear(&active_state->incoming_packet);
cp = buffer_append_space(&active_state->incoming_packet, padded_len);
cipher_crypt(&active_state->receive_context, cp,
- buffer_ptr(&active_state->input), padded_len);
+ buffer_ptr(&active_state->input), padded_len, 0);
buffer_consume(&active_state->input, padded_len);
@@ -1238,8 +1247,8 @@ static int
packet_read_poll2(u_int32_t *seqnr_p)
{
u_int padlen, need;
- u_char *macbuf, *cp, type;
- u_int maclen, block_size;
+ u_char *macbuf = NULL, *cp, type;
+ u_int maclen, aadlen = 0, block_size;
Enc *enc = NULL;
Mac *mac = NULL;
Comp *comp = NULL;
@@ -1254,8 +1263,22 @@ packet_read_poll2(u_int32_t *seqnr_p)
}
maclen = mac && mac->enabled ? mac->mac_len : 0;
block_size = enc ? enc->block_size : 8;
+ aadlen = mac && mac->enabled && mac->etm ? 4 : 0;
- if (active_state->packlen == 0) {
+ if (aadlen && active_state->packlen == 0) {
+ if (buffer_len(&active_state->input) < 4)
+ return SSH_MSG_NONE;
+ cp = buffer_ptr(&active_state->input);
+ active_state->packlen = get_u32(cp);
+ if (active_state->packlen < 1 + 4 ||
+ active_state->packlen > PACKET_MAX_SIZE) {
+#ifdef PACKET_DEBUG
+ buffer_dump(&active_state->input);
+#endif
+ logit("Bad packet length %u.", active_state->packlen);
+ packet_disconnect("Packet corrupt");
+ }
+ } else if (active_state->packlen == 0) {
/*
* check if input size is less than the cipher block size,
* decrypt first block and extract length of incoming packet
@@ -1266,7 +1289,7 @@ packet_read_poll2(u_int32_t *seqnr_p)
cp = buffer_append_space(&active_state->incoming_packet,
block_size);
cipher_crypt(&active_state->receive_context, cp,
- buffer_ptr(&active_state->input), block_size);
+ buffer_ptr(&active_state->input), block_size, 0);
cp = buffer_ptr(&active_state->incoming_packet);
active_state->packlen = get_u32(cp);
if (active_state->packlen < 1 + 4 ||
@@ -1279,13 +1302,21 @@ packet_read_poll2(u_int32_t *seqnr_p)
PACKET_MAX_SIZE);
return SSH_MSG_NONE;
}
- DBG(debug("input: packet len %u", active_state->packlen+4));
buffer_consume(&active_state->input, block_size);
}
- /* we have a partial packet of block_size bytes */
- need = 4 + active_state->packlen - block_size;
- DBG(debug("partial packet %d, need %d, maclen %d", block_size,
- need, maclen));
+ DBG(debug("input: packet len %u", active_state->packlen+4));
+ if (aadlen) {
+ /* only the payload is encrypted */
+ need = active_state->packlen;
+ } else {
+ /*
+ * the payload size and the payload are encrypted, but we
+ * have a partial packet of block_size bytes
+ */
+ need = 4 + active_state->packlen - block_size;
+ }
+ DBG(debug("partial packet: block %d, need %d, maclen %d, aadlen %d",
+ block_size, need, maclen, aadlen));
if (need % block_size != 0) {
logit("padding error: need %d block %d mod %d",
need, block_size, need % block_size);
@@ -1295,26 +1326,34 @@ packet_read_poll2(u_int32_t *seqnr_p)
}
/*
* check if the entire packet has been received and
- * decrypt into incoming_packet
+ * decrypt into incoming_packet:
+ * 'aadlen' bytes are unencrypted, but authenticated.
+ * 'need' bytes are encrypted, followed by
+ * 'maclen' bytes of message authentication code.
*/
- if (buffer_len(&active_state->input) < need + maclen)
+ if (buffer_len(&active_state->input) < aadlen + need + maclen)
return SSH_MSG_NONE;
#ifdef PACKET_DEBUG
fprintf(stderr, "read_poll enc/full: ");
buffer_dump(&active_state->input);
#endif
- cp = buffer_append_space(&active_state->incoming_packet, need);
+ /* EtM: compute mac over encrypted input */
+ if (mac && mac->enabled && mac->etm)
+ macbuf = mac_compute(mac, active_state->p_read.seqnr,
+ buffer_ptr(&active_state->input), aadlen + need);
+ cp = buffer_append_space(&active_state->incoming_packet, aadlen + need);
cipher_crypt(&active_state->receive_context, cp,
- buffer_ptr(&active_state->input), need);
- buffer_consume(&active_state->input, need);
+ buffer_ptr(&active_state->input), need, aadlen);
+ buffer_consume(&active_state->input, aadlen + need);
/*
* compute MAC over seqnr and packet,
* increment sequence number for incoming packet
*/
if (mac && mac->enabled) {
- macbuf = mac_compute(mac, active_state->p_read.seqnr,
- buffer_ptr(&active_state->incoming_packet),
- buffer_len(&active_state->incoming_packet));
+ if (!mac->etm)
+ macbuf = mac_compute(mac, active_state->p_read.seqnr,
+ buffer_ptr(&active_state->incoming_packet),
+ buffer_len(&active_state->incoming_packet));
if (timingsafe_bcmp(macbuf, buffer_ptr(&active_state->input),
mac->mac_len) != 0) {
logit("Corrupted MAC on input.");
diff --git a/ssh_config.5 b/ssh_config.5
index 09a3cf03..ee466d80 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $OpenBSD: ssh_config.5,v 1.159 2012/12/02 20:26:10 djm Exp $
-.Dd $Mdocdate: December 2 2012 $
+.\" $OpenBSD: ssh_config.5,v 1.160 2012/12/11 22:31:18 markus Exp $
+.Dd $Mdocdate: December 11 2012 $
.Dt SSH_CONFIG 5
.Os
.Sh NAME
@@ -792,8 +792,17 @@ in order of preference.
The MAC algorithm is used in protocol version 2
for data integrity protection.
Multiple algorithms must be comma-separated.
+The algorithms that contain
+.Dq -etm
+calculate the MAC after encryption (encrypt-then-mac).
+These are considered safer and their use recommended.
The default is:
.Bd -literal -offset indent
+hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,
+umac-64-etm@openssh.com,umac-128-etm@openssh.com,
+hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
+hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com,
+hmac-md5-96-etm@openssh.com,
hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com,
hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,
hmac-sha1-96,hmac-md5-96
diff --git a/sshd_config.5 b/sshd_config.5
index ad3692b3..0f4aa639 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $OpenBSD: sshd_config.5,v 1.151 2012/12/03 08:33:03 jmc Exp $
-.Dd $Mdocdate: December 3 2012 $
+.\" $OpenBSD: sshd_config.5,v 1.152 2012/12/11 22:31:18 markus Exp $
+.Dd $Mdocdate: December 11 2012 $
.Dt SSHD_CONFIG 5
.Os
.Sh NAME
@@ -706,8 +706,17 @@ Specifies the available MAC (message authentication code) algorithms.
The MAC algorithm is used in protocol version 2
for data integrity protection.
Multiple algorithms must be comma-separated.
+The algorithms that contain
+.Dq -etm
+calculate the MAC after encryption (encrypt-then-mac).
+These are considered safer and their use recommended.
The default is:
.Bd -literal -offset indent
+hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,
+umac-64-etm@openssh.com,umac-128-etm@openssh.com,
+hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
+hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com,
+hmac-md5-96-etm@openssh.com,
hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com,
hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,
hmac-sha1-96,hmac-md5-96