diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | PROTOCOL | 29 | ||||
-rw-r--r-- | authfile.c | 6 | ||||
-rw-r--r-- | cipher.c | 22 | ||||
-rw-r--r-- | cipher.h | 4 | ||||
-rw-r--r-- | kex.h | 3 | ||||
-rw-r--r-- | mac.c | 40 | ||||
-rw-r--r-- | myproposal.h | 11 | ||||
-rw-r--r-- | packet.c | 113 | ||||
-rw-r--r-- | ssh_config.5 | 13 | ||||
-rw-r--r-- | sshd_config.5 | 13 |
11 files changed, 196 insertions, 66 deletions
@@ -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 | ||
8 | 20121207 | 16 | 20121207 |
9 | - (dtucker) OpenBSD CVS Sync | 17 | - (dtucker) OpenBSD CVS Sync |
@@ -51,6 +51,33 @@ and ecdsa-sha2-nistp521 curves over GF(p) are supported. Elliptic | |||
51 | curve points encoded using point compression are NOT accepted or | 51 | curve points encoded using point compression are NOT accepted or |
52 | generated. | 52 | generated. |
53 | 53 | ||
54 | 1.5 transport: Protocol 2 Encrypt-then-MAC MAC algorithms | ||
55 | |||
56 | OpenSSH supports MAC algorithms, whose names contain "-etm", that | ||
57 | perform the calculations in a different order to that defined in RFC | ||
58 | 4253. These variants use the so-called "encrypt then MAC" ordering, | ||
59 | calculating the MAC over the packet ciphertext rather than the | ||
60 | plaintext. This ordering closes a security flaw in the SSH transport | ||
61 | protocol, where decryption of unauthenticated ciphertext provided a | ||
62 | "decryption oracle" that could, in conjunction with cipher flaws, reveal | ||
63 | session plaintext. | ||
64 | |||
65 | Specifically, the "-etm" MAC algorithms modify the transport protocol | ||
66 | to calculate the MAC over the packet ciphertext and to send the packet | ||
67 | length unencrypted. This is necessary for the transport to obtain the | ||
68 | length of the packet and location of the MAC tag so that it may be | ||
69 | verified without decrypting unauthenticated data. | ||
70 | |||
71 | As such, the MAC covers: | ||
72 | |||
73 | mac = MAC(key, sequence_number || encrypted_packet) | ||
74 | |||
75 | where "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 | |||
54 | 2. Connection protocol changes | 81 | 2. Connection protocol changes |
55 | 82 | ||
56 | 2.1. connection: Channel write close extension "eow@openssh.com" | 83 | 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. | |||
291 | This extension is advertised in the SSH_FXP_VERSION hello with version | 318 | This 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(©), buffer_len(©)); | 477 | buffer_ptr(©), buffer_len(©), 0); |
478 | cipher_cleanup(&ciphercontext); | 478 | cipher_cleanup(&ciphercontext); |
479 | memset(&ciphercontext, 0, sizeof(ciphercontext)); | 479 | memset(&ciphercontext, 0, sizeof(ciphercontext)); |
480 | buffer_free(©); | 480 | buffer_free(©); |
@@ -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 | */ | ||
276 | void | 284 | void |
277 | cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len) | 285 | cipher_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 | ||
285 | void | 297 | void |
@@ -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); | |||
76 | int ciphers_valid(const char *); | 76 | int ciphers_valid(const char *); |
77 | void cipher_init(CipherContext *, Cipher *, const u_char *, u_int, | 77 | void cipher_init(CipherContext *, Cipher *, const u_char *, u_int, |
78 | const u_char *, u_int, int); | 78 | const u_char *, u_int, int); |
79 | void cipher_crypt(CipherContext *, u_char *, const u_char *, u_int); | 79 | void cipher_crypt(CipherContext *, u_char *, const u_char *, u_int, u_int); |
80 | void cipher_cleanup(CipherContext *); | 80 | void cipher_cleanup(CipherContext *); |
81 | void cipher_set_key_string(CipherContext *, Cipher *, const char *, int); | 81 | void cipher_set_key_string(CipherContext *, Cipher *, const char *, int); |
82 | u_int cipher_blocksize(const Cipher *); | 82 | u_int cipher_blocksize(const Cipher *); |
@@ -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; |
@@ -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 | ||
76 | static void | 91 | static 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 | ||
95 | int | 111 | int |
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," \ |
@@ -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) | |||
275 | static void | 275 | static void |
276 | packet_start_discard(Enc *enc, Mac *mac, u_int packet_length, u_int discard) | 276 | packet_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 | |||
845 | packet_send2_wrapped(void) | 845 | packet_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 | |||
1238 | packet_read_poll2(u_int32_t *seqnr_p) | 1247 | packet_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. | |||
792 | The MAC algorithm is used in protocol version 2 | 792 | The MAC algorithm is used in protocol version 2 |
793 | for data integrity protection. | 793 | for data integrity protection. |
794 | Multiple algorithms must be comma-separated. | 794 | Multiple algorithms must be comma-separated. |
795 | The algorithms that contain | ||
796 | .Dq -etm | ||
797 | calculate the MAC after encryption (encrypt-then-mac). | ||
798 | These are considered safer and their use recommended. | ||
795 | The default is: | 799 | The default is: |
796 | .Bd -literal -offset indent | 800 | .Bd -literal -offset indent |
801 | hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com, | ||
802 | umac-64-etm@openssh.com,umac-128-etm@openssh.com, | ||
803 | hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, | ||
804 | hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com, | ||
805 | hmac-md5-96-etm@openssh.com, | ||
797 | hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com, | 806 | hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com, |
798 | hmac-sha2-256,hmac-sha2-512,hmac-ripemd160, | 807 | hmac-sha2-256,hmac-sha2-512,hmac-ripemd160, |
799 | hmac-sha1-96,hmac-md5-96 | 808 | hmac-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. | |||
706 | The MAC algorithm is used in protocol version 2 | 706 | The MAC algorithm is used in protocol version 2 |
707 | for data integrity protection. | 707 | for data integrity protection. |
708 | Multiple algorithms must be comma-separated. | 708 | Multiple algorithms must be comma-separated. |
709 | The algorithms that contain | ||
710 | .Dq -etm | ||
711 | calculate the MAC after encryption (encrypt-then-mac). | ||
712 | These are considered safer and their use recommended. | ||
709 | The default is: | 713 | The default is: |
710 | .Bd -literal -offset indent | 714 | .Bd -literal -offset indent |
715 | hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com, | ||
716 | umac-64-etm@openssh.com,umac-128-etm@openssh.com, | ||
717 | hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, | ||
718 | hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com, | ||
719 | hmac-md5-96-etm@openssh.com, | ||
711 | hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com, | 720 | hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com, |
712 | hmac-sha2-256,hmac-sha2-512,hmac-ripemd160, | 721 | hmac-sha2-256,hmac-sha2-512,hmac-ripemd160, |
713 | hmac-sha1-96,hmac-md5-96 | 722 | hmac-sha1-96,hmac-md5-96 |