aboutsummaryrefslogtreecommitdiff
path: root/packet.c
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2013-03-22 11:19:48 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2013-03-22 11:19:48 +0000
commit9b81c128761e4627fc5291f371e0d07903eb4e72 (patch)
tree7ff06aa6c4c960e7fe13b294a9c2eaddce18a2f1 /packet.c
parent925f1fb7e466dbf645650dc4ea9d2a34e728ef9c (diff)
downloadsrc-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.c132
1 files changed, 91 insertions, 41 deletions
diff --git a/packet.c b/packet.c
index d0c66fe57cb8..9326ddea6d64 100644
--- a/packet.c
+++ b/packet.c
@@ -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;