diff options
Diffstat (limited to 'packet.c')
-rw-r--r-- | packet.c | 113 |
1 files changed, 76 insertions, 37 deletions
@@ -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."); |