diff options
Diffstat (limited to 'packet.c')
-rw-r--r-- | packet.c | 132 |
1 files changed, 91 insertions, 41 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: packet.c,v 1.176 2012/01/25 19:40:09 markus Exp $ */ | 1 | /* $OpenBSD: packet.c,v 1.181 2013/02/10 23:35:24 djm 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, 0); |
713 | 713 | ||
714 | #ifdef PACKET_DEBUG | 714 | #ifdef PACKET_DEBUG |
715 | fprintf(stderr, "encrypted: "); | 715 | fprintf(stderr, "encrypted: "); |
@@ -757,6 +757,9 @@ set_newkeys(int mode) | |||
757 | mac = &active_state->newkeys[mode]->mac; | 757 | mac = &active_state->newkeys[mode]->mac; |
758 | comp = &active_state->newkeys[mode]->comp; | 758 | comp = &active_state->newkeys[mode]->comp; |
759 | mac_clear(mac); | 759 | mac_clear(mac); |
760 | memset(enc->iv, 0, enc->iv_len); | ||
761 | memset(enc->key, 0, enc->key_len); | ||
762 | memset(mac->key, 0, mac->key_len); | ||
760 | xfree(enc->name); | 763 | xfree(enc->name); |
761 | xfree(enc->iv); | 764 | xfree(enc->iv); |
762 | xfree(enc->key); | 765 | xfree(enc->key); |
@@ -771,11 +774,11 @@ set_newkeys(int mode) | |||
771 | enc = &active_state->newkeys[mode]->enc; | 774 | enc = &active_state->newkeys[mode]->enc; |
772 | mac = &active_state->newkeys[mode]->mac; | 775 | mac = &active_state->newkeys[mode]->mac; |
773 | comp = &active_state->newkeys[mode]->comp; | 776 | comp = &active_state->newkeys[mode]->comp; |
774 | if (mac_init(mac) == 0) | 777 | if (cipher_authlen(enc->cipher) == 0 && mac_init(mac) == 0) |
775 | mac->enabled = 1; | 778 | mac->enabled = 1; |
776 | DBG(debug("cipher_init_context: %d", mode)); | 779 | DBG(debug("cipher_init_context: %d", mode)); |
777 | cipher_init(cc, enc->cipher, enc->key, enc->key_len, | 780 | cipher_init(cc, enc->cipher, enc->key, enc->key_len, |
778 | enc->iv, enc->block_size, crypt_type); | 781 | enc->iv, enc->iv_len, crypt_type); |
779 | /* Deleting the keys does not gain extra security */ | 782 | /* Deleting the keys does not gain extra security */ |
780 | /* memset(enc->iv, 0, enc->block_size); | 783 | /* memset(enc->iv, 0, enc->block_size); |
781 | memset(enc->key, 0, enc->key_len); | 784 | memset(enc->key, 0, enc->key_len); |
@@ -842,9 +845,8 @@ static void | |||
842 | packet_send2_wrapped(void) | 845 | packet_send2_wrapped(void) |
843 | { | 846 | { |
844 | u_char type, *cp, *macbuf = NULL; | 847 | u_char type, *cp, *macbuf = NULL; |
845 | u_char padlen, pad; | 848 | u_char padlen, pad = 0; |
846 | u_int packet_length = 0; | 849 | u_int i, len, authlen = 0, aadlen = 0; |
847 | u_int i, len; | ||
848 | u_int32_t rnd = 0; | 850 | u_int32_t rnd = 0; |
849 | Enc *enc = NULL; | 851 | Enc *enc = NULL; |
850 | Mac *mac = NULL; | 852 | Mac *mac = NULL; |
@@ -855,8 +857,12 @@ packet_send2_wrapped(void) | |||
855 | enc = &active_state->newkeys[MODE_OUT]->enc; | 857 | enc = &active_state->newkeys[MODE_OUT]->enc; |
856 | mac = &active_state->newkeys[MODE_OUT]->mac; | 858 | mac = &active_state->newkeys[MODE_OUT]->mac; |
857 | comp = &active_state->newkeys[MODE_OUT]->comp; | 859 | comp = &active_state->newkeys[MODE_OUT]->comp; |
860 | /* disable mac for authenticated encryption */ | ||
861 | if ((authlen = cipher_authlen(enc->cipher)) != 0) | ||
862 | mac = NULL; | ||
858 | } | 863 | } |
859 | block_size = enc ? enc->block_size : 8; | 864 | block_size = enc ? enc->block_size : 8; |
865 | aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0; | ||
860 | 866 | ||
861 | cp = buffer_ptr(&active_state->outgoing_packet); | 867 | cp = buffer_ptr(&active_state->outgoing_packet); |
862 | type = cp[5]; | 868 | type = cp[5]; |
@@ -889,6 +895,7 @@ packet_send2_wrapped(void) | |||
889 | * calc size of padding, alloc space, get random data, | 895 | * calc size of padding, alloc space, get random data, |
890 | * minimum padding is 4 bytes | 896 | * minimum padding is 4 bytes |
891 | */ | 897 | */ |
898 | len -= aadlen; /* packet length is not encrypted for EtM modes */ | ||
892 | padlen = block_size - (len % block_size); | 899 | padlen = block_size - (len % block_size); |
893 | if (padlen < 4) | 900 | if (padlen < 4) |
894 | padlen += block_size; | 901 | padlen += block_size; |
@@ -916,29 +923,37 @@ packet_send2_wrapped(void) | |||
916 | /* clear padding */ | 923 | /* clear padding */ |
917 | memset(cp, 0, padlen); | 924 | memset(cp, 0, padlen); |
918 | } | 925 | } |
919 | /* packet_length includes payload, padding and padding length field */ | 926 | /* sizeof (packet_len + pad_len + payload + padding) */ |
920 | packet_length = buffer_len(&active_state->outgoing_packet) - 4; | 927 | len = buffer_len(&active_state->outgoing_packet); |
921 | cp = buffer_ptr(&active_state->outgoing_packet); | 928 | cp = buffer_ptr(&active_state->outgoing_packet); |
922 | put_u32(cp, packet_length); | 929 | /* packet_length includes payload, padding and padding length field */ |
930 | put_u32(cp, len - 4); | ||
923 | cp[4] = padlen; | 931 | cp[4] = padlen; |
924 | DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen)); | 932 | DBG(debug("send: len %d (includes padlen %d, aadlen %d)", |
933 | len, padlen, aadlen)); | ||
925 | 934 | ||
926 | /* compute MAC over seqnr and packet(length fields, payload, padding) */ | 935 | /* compute MAC over seqnr and packet(length fields, payload, padding) */ |
927 | if (mac && mac->enabled) { | 936 | if (mac && mac->enabled && !mac->etm) { |
928 | macbuf = mac_compute(mac, active_state->p_send.seqnr, | 937 | macbuf = mac_compute(mac, active_state->p_send.seqnr, |
929 | buffer_ptr(&active_state->outgoing_packet), | 938 | buffer_ptr(&active_state->outgoing_packet), len); |
930 | buffer_len(&active_state->outgoing_packet)); | ||
931 | DBG(debug("done calc MAC out #%d", active_state->p_send.seqnr)); | 939 | DBG(debug("done calc MAC out #%d", active_state->p_send.seqnr)); |
932 | } | 940 | } |
933 | /* encrypt packet and append to output buffer. */ | 941 | /* encrypt packet and append to output buffer. */ |
934 | cp = buffer_append_space(&active_state->output, | 942 | cp = buffer_append_space(&active_state->output, len + authlen); |
935 | buffer_len(&active_state->outgoing_packet)); | ||
936 | cipher_crypt(&active_state->send_context, cp, | 943 | cipher_crypt(&active_state->send_context, cp, |
937 | buffer_ptr(&active_state->outgoing_packet), | 944 | buffer_ptr(&active_state->outgoing_packet), |
938 | buffer_len(&active_state->outgoing_packet)); | 945 | len - aadlen, aadlen, authlen); |
939 | /* append unencrypted MAC */ | 946 | /* append unencrypted MAC */ |
940 | if (mac && mac->enabled) | 947 | if (mac && mac->enabled) { |
948 | if (mac->etm) { | ||
949 | /* EtM: compute mac over aadlen + cipher text */ | ||
950 | macbuf = mac_compute(mac, | ||
951 | active_state->p_send.seqnr, cp, len); | ||
952 | DBG(debug("done calc MAC(EtM) out #%d", | ||
953 | active_state->p_send.seqnr)); | ||
954 | } | ||
941 | buffer_append(&active_state->output, macbuf, mac->mac_len); | 955 | buffer_append(&active_state->output, macbuf, mac->mac_len); |
956 | } | ||
942 | #ifdef PACKET_DEBUG | 957 | #ifdef PACKET_DEBUG |
943 | fprintf(stderr, "encrypted: "); | 958 | fprintf(stderr, "encrypted: "); |
944 | buffer_dump(&active_state->output); | 959 | buffer_dump(&active_state->output); |
@@ -949,8 +964,8 @@ packet_send2_wrapped(void) | |||
949 | if (++active_state->p_send.packets == 0) | 964 | if (++active_state->p_send.packets == 0) |
950 | if (!(datafellows & SSH_BUG_NOREKEY)) | 965 | if (!(datafellows & SSH_BUG_NOREKEY)) |
951 | fatal("XXX too many packets with same key"); | 966 | fatal("XXX too many packets with same key"); |
952 | active_state->p_send.blocks += (packet_length + 4) / block_size; | 967 | active_state->p_send.blocks += len / block_size; |
953 | active_state->p_send.bytes += packet_length + 4; | 968 | active_state->p_send.bytes += len; |
954 | buffer_clear(&active_state->outgoing_packet); | 969 | buffer_clear(&active_state->outgoing_packet); |
955 | 970 | ||
956 | if (type == SSH2_MSG_NEWKEYS) | 971 | if (type == SSH2_MSG_NEWKEYS) |
@@ -1187,7 +1202,7 @@ packet_read_poll1(void) | |||
1187 | buffer_clear(&active_state->incoming_packet); | 1202 | buffer_clear(&active_state->incoming_packet); |
1188 | cp = buffer_append_space(&active_state->incoming_packet, padded_len); | 1203 | cp = buffer_append_space(&active_state->incoming_packet, padded_len); |
1189 | cipher_crypt(&active_state->receive_context, cp, | 1204 | cipher_crypt(&active_state->receive_context, cp, |
1190 | buffer_ptr(&active_state->input), padded_len); | 1205 | buffer_ptr(&active_state->input), padded_len, 0, 0); |
1191 | 1206 | ||
1192 | buffer_consume(&active_state->input, padded_len); | 1207 | buffer_consume(&active_state->input, padded_len); |
1193 | 1208 | ||
@@ -1235,8 +1250,8 @@ static int | |||
1235 | packet_read_poll2(u_int32_t *seqnr_p) | 1250 | packet_read_poll2(u_int32_t *seqnr_p) |
1236 | { | 1251 | { |
1237 | u_int padlen, need; | 1252 | u_int padlen, need; |
1238 | u_char *macbuf, *cp, type; | 1253 | u_char *macbuf = NULL, *cp, type; |
1239 | u_int maclen, block_size; | 1254 | u_int maclen, authlen = 0, aadlen = 0, block_size; |
1240 | Enc *enc = NULL; | 1255 | Enc *enc = NULL; |
1241 | Mac *mac = NULL; | 1256 | Mac *mac = NULL; |
1242 | Comp *comp = NULL; | 1257 | Comp *comp = NULL; |
@@ -1248,11 +1263,29 @@ packet_read_poll2(u_int32_t *seqnr_p) | |||
1248 | enc = &active_state->newkeys[MODE_IN]->enc; | 1263 | enc = &active_state->newkeys[MODE_IN]->enc; |
1249 | mac = &active_state->newkeys[MODE_IN]->mac; | 1264 | mac = &active_state->newkeys[MODE_IN]->mac; |
1250 | comp = &active_state->newkeys[MODE_IN]->comp; | 1265 | comp = &active_state->newkeys[MODE_IN]->comp; |
1266 | /* disable mac for authenticated encryption */ | ||
1267 | if ((authlen = cipher_authlen(enc->cipher)) != 0) | ||
1268 | mac = NULL; | ||
1251 | } | 1269 | } |
1252 | maclen = mac && mac->enabled ? mac->mac_len : 0; | 1270 | maclen = mac && mac->enabled ? mac->mac_len : 0; |
1253 | block_size = enc ? enc->block_size : 8; | 1271 | block_size = enc ? enc->block_size : 8; |
1272 | aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0; | ||
1254 | 1273 | ||
1255 | if (active_state->packlen == 0) { | 1274 | if (aadlen && active_state->packlen == 0) { |
1275 | if (buffer_len(&active_state->input) < 4) | ||
1276 | return SSH_MSG_NONE; | ||
1277 | cp = buffer_ptr(&active_state->input); | ||
1278 | active_state->packlen = get_u32(cp); | ||
1279 | if (active_state->packlen < 1 + 4 || | ||
1280 | active_state->packlen > PACKET_MAX_SIZE) { | ||
1281 | #ifdef PACKET_DEBUG | ||
1282 | buffer_dump(&active_state->input); | ||
1283 | #endif | ||
1284 | logit("Bad packet length %u.", active_state->packlen); | ||
1285 | packet_disconnect("Packet corrupt"); | ||
1286 | } | ||
1287 | buffer_clear(&active_state->incoming_packet); | ||
1288 | } else if (active_state->packlen == 0) { | ||
1256 | /* | 1289 | /* |
1257 | * check if input size is less than the cipher block size, | 1290 | * check if input size is less than the cipher block size, |
1258 | * decrypt first block and extract length of incoming packet | 1291 | * decrypt first block and extract length of incoming packet |
@@ -1263,7 +1296,7 @@ packet_read_poll2(u_int32_t *seqnr_p) | |||
1263 | cp = buffer_append_space(&active_state->incoming_packet, | 1296 | cp = buffer_append_space(&active_state->incoming_packet, |
1264 | block_size); | 1297 | block_size); |
1265 | cipher_crypt(&active_state->receive_context, cp, | 1298 | cipher_crypt(&active_state->receive_context, cp, |
1266 | buffer_ptr(&active_state->input), block_size); | 1299 | buffer_ptr(&active_state->input), block_size, 0, 0); |
1267 | cp = buffer_ptr(&active_state->incoming_packet); | 1300 | cp = buffer_ptr(&active_state->incoming_packet); |
1268 | active_state->packlen = get_u32(cp); | 1301 | active_state->packlen = get_u32(cp); |
1269 | if (active_state->packlen < 1 + 4 || | 1302 | if (active_state->packlen < 1 + 4 || |
@@ -1276,13 +1309,21 @@ packet_read_poll2(u_int32_t *seqnr_p) | |||
1276 | PACKET_MAX_SIZE); | 1309 | PACKET_MAX_SIZE); |
1277 | return SSH_MSG_NONE; | 1310 | return SSH_MSG_NONE; |
1278 | } | 1311 | } |
1279 | DBG(debug("input: packet len %u", active_state->packlen+4)); | ||
1280 | buffer_consume(&active_state->input, block_size); | 1312 | buffer_consume(&active_state->input, block_size); |
1281 | } | 1313 | } |
1282 | /* we have a partial packet of block_size bytes */ | 1314 | DBG(debug("input: packet len %u", active_state->packlen+4)); |
1283 | need = 4 + active_state->packlen - block_size; | 1315 | if (aadlen) { |
1284 | DBG(debug("partial packet %d, need %d, maclen %d", block_size, | 1316 | /* only the payload is encrypted */ |
1285 | need, maclen)); | 1317 | need = active_state->packlen; |
1318 | } else { | ||
1319 | /* | ||
1320 | * the payload size and the payload are encrypted, but we | ||
1321 | * have a partial packet of block_size bytes | ||
1322 | */ | ||
1323 | need = 4 + active_state->packlen - block_size; | ||
1324 | } | ||
1325 | DBG(debug("partial packet: block %d, need %d, maclen %d, authlen %d," | ||
1326 | " aadlen %d", block_size, need, maclen, authlen, aadlen)); | ||
1286 | if (need % block_size != 0) { | 1327 | if (need % block_size != 0) { |
1287 | logit("padding error: need %d block %d mod %d", | 1328 | logit("padding error: need %d block %d mod %d", |
1288 | need, block_size, need % block_size); | 1329 | need, block_size, need % block_size); |
@@ -1292,26 +1333,35 @@ packet_read_poll2(u_int32_t *seqnr_p) | |||
1292 | } | 1333 | } |
1293 | /* | 1334 | /* |
1294 | * check if the entire packet has been received and | 1335 | * check if the entire packet has been received and |
1295 | * decrypt into incoming_packet | 1336 | * decrypt into incoming_packet: |
1337 | * 'aadlen' bytes are unencrypted, but authenticated. | ||
1338 | * 'need' bytes are encrypted, followed by either | ||
1339 | * 'authlen' bytes of authentication tag or | ||
1340 | * 'maclen' bytes of message authentication code. | ||
1296 | */ | 1341 | */ |
1297 | if (buffer_len(&active_state->input) < need + maclen) | 1342 | if (buffer_len(&active_state->input) < aadlen + need + authlen + maclen) |
1298 | return SSH_MSG_NONE; | 1343 | return SSH_MSG_NONE; |
1299 | #ifdef PACKET_DEBUG | 1344 | #ifdef PACKET_DEBUG |
1300 | fprintf(stderr, "read_poll enc/full: "); | 1345 | fprintf(stderr, "read_poll enc/full: "); |
1301 | buffer_dump(&active_state->input); | 1346 | buffer_dump(&active_state->input); |
1302 | #endif | 1347 | #endif |
1303 | cp = buffer_append_space(&active_state->incoming_packet, need); | 1348 | /* EtM: compute mac over encrypted input */ |
1349 | if (mac && mac->enabled && mac->etm) | ||
1350 | macbuf = mac_compute(mac, active_state->p_read.seqnr, | ||
1351 | buffer_ptr(&active_state->input), aadlen + need); | ||
1352 | cp = buffer_append_space(&active_state->incoming_packet, aadlen + need); | ||
1304 | cipher_crypt(&active_state->receive_context, cp, | 1353 | cipher_crypt(&active_state->receive_context, cp, |
1305 | buffer_ptr(&active_state->input), need); | 1354 | buffer_ptr(&active_state->input), need, aadlen, authlen); |
1306 | buffer_consume(&active_state->input, need); | 1355 | buffer_consume(&active_state->input, aadlen + need + authlen); |
1307 | /* | 1356 | /* |
1308 | * compute MAC over seqnr and packet, | 1357 | * compute MAC over seqnr and packet, |
1309 | * increment sequence number for incoming packet | 1358 | * increment sequence number for incoming packet |
1310 | */ | 1359 | */ |
1311 | if (mac && mac->enabled) { | 1360 | if (mac && mac->enabled) { |
1312 | macbuf = mac_compute(mac, active_state->p_read.seqnr, | 1361 | if (!mac->etm) |
1313 | buffer_ptr(&active_state->incoming_packet), | 1362 | macbuf = mac_compute(mac, active_state->p_read.seqnr, |
1314 | buffer_len(&active_state->incoming_packet)); | 1363 | buffer_ptr(&active_state->incoming_packet), |
1364 | buffer_len(&active_state->incoming_packet)); | ||
1315 | if (timingsafe_bcmp(macbuf, buffer_ptr(&active_state->input), | 1365 | if (timingsafe_bcmp(macbuf, buffer_ptr(&active_state->input), |
1316 | mac->mac_len) != 0) { | 1366 | mac->mac_len) != 0) { |
1317 | logit("Corrupted MAC on input."); | 1367 | logit("Corrupted MAC on input."); |
@@ -1410,7 +1460,7 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p) | |||
1410 | case SSH2_MSG_DISCONNECT: | 1460 | case SSH2_MSG_DISCONNECT: |
1411 | reason = packet_get_int(); | 1461 | reason = packet_get_int(); |
1412 | msg = packet_get_string(NULL); | 1462 | msg = packet_get_string(NULL); |
1413 | logit("Received disconnect from %s: %u: %.400s", | 1463 | error("Received disconnect from %s: %u: %.400s", |
1414 | get_remote_ipaddr(), reason, msg); | 1464 | get_remote_ipaddr(), reason, msg); |
1415 | xfree(msg); | 1465 | xfree(msg); |
1416 | cleanup_exit(255); | 1466 | cleanup_exit(255); |
@@ -1435,7 +1485,7 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p) | |||
1435 | break; | 1485 | break; |
1436 | case SSH_MSG_DISCONNECT: | 1486 | case SSH_MSG_DISCONNECT: |
1437 | msg = packet_get_string(NULL); | 1487 | msg = packet_get_string(NULL); |
1438 | logit("Received disconnect from %s: %.400s", | 1488 | error("Received disconnect from %s: %.400s", |
1439 | get_remote_ipaddr(), msg); | 1489 | get_remote_ipaddr(), msg); |
1440 | cleanup_exit(255); | 1490 | cleanup_exit(255); |
1441 | break; | 1491 | break; |