diff options
author | Dag-Erling Smørgrav <des@FreeBSD.org> | 2013-03-22 11:19:48 +0000 |
---|---|---|
committer | Dag-Erling Smørgrav <des@FreeBSD.org> | 2013-03-22 11:19:48 +0000 |
commit | 9b81c128761e4627fc5291f371e0d07903eb4e72 (patch) | |
tree | 7ff06aa6c4c960e7fe13b294a9c2eaddce18a2f1 /packet.c | |
parent | 925f1fb7e466dbf645650dc4ea9d2a34e728ef9c (diff) | |
download | src-9b81c128761e4627fc5291f371e0d07903eb4e72.tar.gz src-9b81c128761e4627fc5291f371e0d07903eb4e72.zip |
Vendor import of OpenSSH 6.2p1.vendor/openssh/6.2p1
Notes
Notes:
svn path=/vendor-crypto/openssh/dist/; revision=248613
svn path=/vendor-crypto/openssh/6.2p1/; revision=248614; tag=vendor/openssh/6.2p1
Diffstat (limited to 'packet.c')
-rw-r--r-- | packet.c | 132 |
1 files changed, 91 insertions, 41 deletions
@@ -1,4 +1,4 @@ -/* $OpenBSD: packet.c,v 1.176 2012/01/25 19:40:09 markus Exp $ */ +/* $OpenBSD: packet.c,v 1.181 2013/02/10 23:35:24 djm 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, 0); #ifdef PACKET_DEBUG fprintf(stderr, "encrypted: "); @@ -757,6 +757,9 @@ set_newkeys(int mode) mac = &active_state->newkeys[mode]->mac; comp = &active_state->newkeys[mode]->comp; mac_clear(mac); + memset(enc->iv, 0, enc->iv_len); + memset(enc->key, 0, enc->key_len); + memset(mac->key, 0, mac->key_len); xfree(enc->name); xfree(enc->iv); xfree(enc->key); @@ -771,11 +774,11 @@ set_newkeys(int mode) enc = &active_state->newkeys[mode]->enc; mac = &active_state->newkeys[mode]->mac; comp = &active_state->newkeys[mode]->comp; - if (mac_init(mac) == 0) + if (cipher_authlen(enc->cipher) == 0 && mac_init(mac) == 0) mac->enabled = 1; DBG(debug("cipher_init_context: %d", mode)); cipher_init(cc, enc->cipher, enc->key, enc->key_len, - enc->iv, enc->block_size, crypt_type); + enc->iv, enc->iv_len, crypt_type); /* Deleting the keys does not gain extra security */ /* memset(enc->iv, 0, enc->block_size); memset(enc->key, 0, enc->key_len); @@ -842,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, authlen = 0, aadlen = 0; u_int32_t rnd = 0; Enc *enc = NULL; Mac *mac = NULL; @@ -855,8 +857,12 @@ packet_send2_wrapped(void) enc = &active_state->newkeys[MODE_OUT]->enc; mac = &active_state->newkeys[MODE_OUT]->mac; comp = &active_state->newkeys[MODE_OUT]->comp; + /* disable mac for authenticated encryption */ + if ((authlen = cipher_authlen(enc->cipher)) != 0) + mac = NULL; } block_size = enc ? enc->block_size : 8; + aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0; cp = buffer_ptr(&active_state->outgoing_packet); type = cp[5]; @@ -889,6 +895,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; @@ -916,29 +923,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 + authlen); cipher_crypt(&active_state->send_context, cp, buffer_ptr(&active_state->outgoing_packet), - buffer_len(&active_state->outgoing_packet)); + len - aadlen, aadlen, authlen); /* 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); @@ -949,8 +964,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) @@ -1187,7 +1202,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, 0); buffer_consume(&active_state->input, padded_len); @@ -1235,8 +1250,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, authlen = 0, aadlen = 0, block_size; Enc *enc = NULL; Mac *mac = NULL; Comp *comp = NULL; @@ -1248,11 +1263,29 @@ packet_read_poll2(u_int32_t *seqnr_p) enc = &active_state->newkeys[MODE_IN]->enc; mac = &active_state->newkeys[MODE_IN]->mac; comp = &active_state->newkeys[MODE_IN]->comp; + /* disable mac for authenticated encryption */ + if ((authlen = cipher_authlen(enc->cipher)) != 0) + mac = NULL; } maclen = mac && mac->enabled ? mac->mac_len : 0; block_size = enc ? enc->block_size : 8; + aadlen = (mac && mac->enabled && mac->etm) || authlen ? 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"); + } + buffer_clear(&active_state->incoming_packet); + } 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 @@ -1263,7 +1296,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, 0); cp = buffer_ptr(&active_state->incoming_packet); active_state->packlen = get_u32(cp); if (active_state->packlen < 1 + 4 || @@ -1276,13 +1309,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, authlen %d," + " aadlen %d", block_size, need, maclen, authlen, aadlen)); if (need % block_size != 0) { logit("padding error: need %d block %d mod %d", need, block_size, need % block_size); @@ -1292,26 +1333,35 @@ 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 either + * 'authlen' bytes of authentication tag or + * 'maclen' bytes of message authentication code. */ - if (buffer_len(&active_state->input) < need + maclen) + if (buffer_len(&active_state->input) < aadlen + need + authlen + 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, authlen); + buffer_consume(&active_state->input, aadlen + need + authlen); /* * 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."); @@ -1410,7 +1460,7 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p) case SSH2_MSG_DISCONNECT: reason = packet_get_int(); msg = packet_get_string(NULL); - logit("Received disconnect from %s: %u: %.400s", + error("Received disconnect from %s: %u: %.400s", get_remote_ipaddr(), reason, msg); xfree(msg); cleanup_exit(255); @@ -1435,7 +1485,7 @@ packet_read_poll_seqnr(u_int32_t *seqnr_p) break; case SSH_MSG_DISCONNECT: msg = packet_get_string(NULL); - logit("Received disconnect from %s: %.400s", + error("Received disconnect from %s: %.400s", get_remote_ipaddr(), msg); cleanup_exit(255); break; |