summaryrefslogtreecommitdiff
path: root/packet.c
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 /packet.c
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@
Diffstat (limited to 'packet.c')
-rw-r--r--packet.c113
1 files changed, 76 insertions, 37 deletions
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.");