Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 48 additions & 21 deletions src/wolfesp.c
Original file line number Diff line number Diff line change
Expand Up @@ -532,32 +532,44 @@ esp_iv_len_from_enc(esp_enc_t enc)

#ifdef DEBUG_ESP
#define esp_print_sep \
LOG("+------------------+\n")
ESP_LOG("+------------------+\n")
#define esp_str_4hex \
"| %02x %02x %02x %02x |"
#define esp_str_skip \
"| .. .. .. .. |"
#define esp_pad_fld \
"| %02x%02x | %02d | 0x%02x |"

/* Prints an esp packet field (spi, seq, iv, payload, etc).
* The majority of these are minimum 4 bytes, or 4 byte multiple.
* */
static inline void
esp_print_field(const char * fld, const uint8_t * val,
uint32_t val_len)
{
esp_print_sep;
LOG(esp_str_4hex " (%s, %d bytes)\n",
val[0], val[1], val[2], val[3], fld, val_len);
if (val_len > 4) {
for (size_t i = 4; i < val_len; i += 4) {
if (i > 16 || (i + 4) > val_len) {
LOG(esp_str_skip "\n");
break;
}
if (val_len < 4) {
/* short field */
ESP_LOG(esp_str_skip " (%s, %u bytes)\n", fld, val_len);
}
Comment thread
philljj marked this conversation as resolved.
else {
/* print first 4 bytes, and subsequent full multiples of 4. */
ESP_LOG(esp_str_4hex " (%s, %u bytes)\n",
val[0], val[1], val[2], val[3], fld, val_len);
if (val_len > 4) {
for (size_t i = 4; i < val_len; i += 4) {
if (i > 16 || (i + 4) > val_len) {
/* short remainder */
ESP_LOG(esp_str_skip "\n");
break;
}

LOG(esp_str_4hex"\n",
val[0 + i], val[1 + i], val[2 + i], val[3 + i]);
ESP_LOG(esp_str_4hex"\n",
val[0 + i], val[1 + i], val[2 + i], val[3 + i]);
}
}
}

return;
}

Expand Down Expand Up @@ -599,7 +611,7 @@ static void wolfIP_print_esp(const wolfIP_esp_sa * esp_sa,

/* last 2 bytes of padding */
padding = esp_data + esp_len - esp_sa->icv_len - 4;
LOG("esp packet: (%d bytes)\n", esp_len);
ESP_LOG("esp packet: (%u bytes)\n", esp_len);

/** ESP header
* ______________
Expand All @@ -623,8 +635,8 @@ static void wolfIP_print_esp(const wolfIP_esp_sa * esp_sa,
* | (variable length) | Length | Header |
* ------------------------------------- */
esp_print_sep;
LOG(esp_pad_fld " (padding last 2 bytes, pad len, nxt hdr)\n",
padding[0], padding[1], pad_len, nxt_hdr);
ESP_LOG(esp_pad_fld " (padding last 2 bytes, pad len, nxt hdr)\n",
padding[0], padding[1], pad_len, nxt_hdr);

if (icv) {
esp_print_field("icv", icv, esp_sa->icv_len);
Expand Down Expand Up @@ -1689,6 +1701,7 @@ esp_transport_wrap(struct wolfIP_ip_packet *ip, uint16_t * ip_len)
uint16_t icv_offset = 0;
wolfIP_esp_sa * esp_sa = NULL;
uint8_t iv_len = 0;
uint32_t oseq = 0;

if (ip_hdr_len < IP_HEADER_LEN || orig_ip_len < ip_hdr_len) {
ESP_LOG("error: ip_len below header: %u\n", orig_ip_len);
Expand Down Expand Up @@ -1744,14 +1757,15 @@ esp_transport_wrap(struct wolfIP_ip_packet *ip, uint16_t * ip_len)
memcpy(payload, esp_sa->spi, sizeof(esp_sa->spi));
payload += ESP_SPI_LEN;

esp_sa->replay.oseq++;
if (esp_sa->replay.oseq == 0) {
esp_sa->replay.oseq--;
oseq = esp_sa->replay.oseq;
oseq++;

if (oseq == 0) {
ESP_LOG("error: oseq overflow\n");
return -1;
}
esp_state_save(esp_sa);
seq_n = ee32(esp_sa->replay.oseq);

seq_n = ee32(oseq);
memcpy(payload, &seq_n, sizeof(seq_n));
payload += ESP_SEQ_LEN;

Expand Down Expand Up @@ -1900,6 +1914,10 @@ esp_transport_wrap(struct wolfIP_ip_packet *ip, uint16_t * ip_len)
wolfIP_print_esp(esp_sa, esp_base, payload_len, pad_len, ip->proto);
#endif /* DEBUG_ESP */

/* finally, commit the esp state */
esp_sa->replay.oseq = oseq;
esp_state_save(esp_sa);

/* update len, set proto to ESP 0x32 (50), recalculate iphdr checksum. */
ip->len = ee16(*ip_len);
ip->proto = 0x32;
Expand All @@ -1920,7 +1938,7 @@ esp_transport_wrap(struct wolfIP_ip_packet *ip, uint16_t * ip_len)
* Returns -1 on error.
* */
static int
esp_send(struct wolfIP_ll_dev * ll_dev, const struct wolfIP_ip_packet *ip,
esp_send(struct wolfIP_ll_dev * ll_dev, const struct wolfIP_ip_packet * ip,
uint16_t len)
{
/**
Expand All @@ -1937,8 +1955,17 @@ esp_send(struct wolfIP_ll_dev * ll_dev, const struct wolfIP_ip_packet *ip,
uint16_t ip_final_len = len;
int esp_rc = 0;

if (!ll_dev || ll_dev->non_ethernet)
if (!ll_dev || ll_dev->non_ethernet) {
ESP_DEBUG("info: esp_wrap: %s\n", !ll_dev ?
"no ll_dev" : "non-ether");
return 1;
}

if ((size_t)(ETH_HEADER_LEN + len) > sizeof(frame)) {
ESP_LOG("error: esp_wrap: ip packet too large: %u > %zu\n",
ETH_HEADER_LEN + len, sizeof(frame));
return -1;
}

esp = (struct wolfIP_ip_packet *) frame;
memcpy(esp, ip, ETH_HEADER_LEN + len);
Expand Down
136 changes: 109 additions & 27 deletions src/wolfip.c
Original file line number Diff line number Diff line change
Expand Up @@ -2416,8 +2416,16 @@ static void wolfIP_send_ttl_exceeded(struct wolfIP *s, unsigned int if_idx,
}
#ifdef WOLFIP_ESP
if (!wolfIP_ll_is_non_ethernet(s, if_idx)) {
if (esp_send(ll, &icmp.ip, (uint16_t)(frame_len - ETH_HEADER_LEN)) == 1) {
int esp_err = esp_send(ll, &icmp.ip,
(uint16_t)(frame_len - ETH_HEADER_LEN));

switch (esp_err) {
case 1: /* send plaintext */
wolfIP_ll_send_frame(s, if_idx, &icmp, frame_len);
case 0: /* success */
break;
default: /* error */
LOG("esp_send: %d\n", esp_err);
}
} else {
wolfIP_ll_send_frame(s, if_idx, &icmp, frame_len);
Expand Down Expand Up @@ -2530,14 +2538,21 @@ static void wolfIP_send_param_problem(struct wolfIP *s, unsigned int if_idx,
#ifdef WOLFIP_ESP
if (!wolfIP_ll_is_non_ethernet(s, if_idx)) {
struct wolfIP_ll_dev *esp_ll = ll;
#if WOLFIP_VLAN
#if WOLFIP_VLAN
/* A VLAN sub-iface has no send function of its own; esp_send needs
* the physical device's send path. */
if (ll->vlan_active && ll->vlan_parent)
esp_ll = ll->vlan_parent;
#endif
if (esp_send(esp_ll, &icmp.ip, (uint16_t)(frame_len - ETH_HEADER_LEN)) == 1) {
#endif
int esp_err = esp_send(esp_ll, &icmp.ip,
(uint16_t)(frame_len - ETH_HEADER_LEN));
switch (esp_err) {
case 1: /* send plaintext */
wolfIP_ll_send_frame(s, if_idx, &icmp, frame_len);
case 0: /* success */
break;
default: /* error */
LOG("esp_send: %d\n", esp_err);
}
} else {
wolfIP_ll_send_frame(s, if_idx, &icmp, frame_len);
Expand Down Expand Up @@ -2659,14 +2674,23 @@ static void wolfIP_send_frag_needed(struct wolfIP *s, unsigned int in_if,
#ifdef WOLFIP_ESP
if (!wolfIP_ll_is_non_ethernet(s, in_if)) {
struct wolfIP_ll_dev *esp_ll = ll;
#if WOLFIP_VLAN
int esp_err = 0;
#if WOLFIP_VLAN
/* A VLAN sub-iface has no send function of its own; esp_send needs
* the physical device's send path. */
if (ll->vlan_active && ll->vlan_parent)
esp_ll = ll->vlan_parent;
#endif
if (esp_send(esp_ll, &icmp.ip, (uint16_t)(frame_len - ETH_HEADER_LEN)) == 1) {
#endif
esp_err = esp_send(esp_ll, &icmp.ip,
(uint16_t)(frame_len - ETH_HEADER_LEN));

switch (esp_err) {
case 1: /* send plaintext */
wolfIP_ll_send_frame(s, in_if, &icmp, frame_len);
case 0: /* success */
break;
default: /* error */
LOG("esp_send: %d\n", esp_err);
}
} else {
wolfIP_ll_send_frame(s, in_if, &icmp, frame_len);
Expand Down Expand Up @@ -2763,8 +2787,15 @@ static void wolfIP_send_port_unreachable(struct wolfIP *s, unsigned int if_idx,
}
#ifdef WOLFIP_ESP
if (!wolfIP_ll_is_non_ethernet(s, if_idx)) {
if (esp_send(ll, &icmp.ip, (uint16_t)(frame_len - ETH_HEADER_LEN)) == 1) {
int esp_err = esp_send(ll, &icmp.ip,
(uint16_t)(frame_len - ETH_HEADER_LEN));
switch (esp_err) {
case 1: /* send plaintext */
wolfIP_ll_send_frame(s, if_idx, &icmp, frame_len);
case 0: /* success */
break;
default: /* error */
LOG("esp_send: %d\n", esp_err);
}
} else {
wolfIP_ll_send_frame(s, if_idx, &icmp, frame_len);
Expand Down Expand Up @@ -4018,10 +4049,16 @@ static int tcp_send_empty_immediate(struct tsocket *t, struct wolfIP_tcp_seg *tc
#ifdef WOLFIP_ESP
if (!wolfIP_ll_is_non_ethernet(t->S, tx_if)) {
struct wolfIP_ll_dev *ll_esp = wolfIP_ll_at(t->S, tx_if);
int esp_err = esp_send(ll_esp, (struct wolfIP_ip_packet *)tcp,
(uint16_t)(frame_len - ETH_HEADER_LEN));
if (esp_err == 1) {
send_ret = esp_send(ll_esp, (struct wolfIP_ip_packet *)tcp,
(uint16_t)(frame_len - ETH_HEADER_LEN));

switch (send_ret) {
case 1: /* send plaintext */
send_ret = wolfIP_ll_send_frame(t->S, tx_if, tcp, frame_len);
case 0: /* success */
break;
default: /* error */
LOG("esp_send: %d\n", send_ret);
}
} else {
send_ret = wolfIP_ll_send_frame(t->S, tx_if, tcp, frame_len);
Expand Down Expand Up @@ -4227,9 +4264,15 @@ static void tcp_send_reset_reply(struct wolfIP *s, unsigned int if_idx,
if (!wolfIP_ll_is_non_ethernet(s, if_idx)) {
struct wolfIP_ll_dev *ll_esp = wolfIP_ll_at(s, if_idx);
int esp_err = esp_send(ll_esp, &out->ip,
(uint16_t)(out_len - ETH_HEADER_LEN));
if (esp_err == 1) {
(uint16_t)(out_len - ETH_HEADER_LEN));

switch (esp_err) {
case 1: /* send plaintext */
wolfIP_ll_send_frame(s, if_idx, &out->ip, out_len);
case 0: /* success */
break;
default: /* error */
LOG("esp_send: %d\n", esp_err);
}
} else {
wolfIP_ll_send_frame(s, if_idx, &out->ip, out_len);
Expand Down Expand Up @@ -4810,9 +4853,16 @@ static int tcp_send_zero_wnd_probe(struct tsocket *t)
if (!wolfIP_ll_is_non_ethernet(t->S, tx_if)) {
struct wolfIP_ll_dev *ll_esp = wolfIP_ll_at(t->S, tx_if);
int esp_err = esp_send(ll_esp, (struct wolfIP_ip_packet *)probe,
(uint16_t)(frame_len - ETH_HEADER_LEN));
if (esp_err == 1) {
(uint16_t)(frame_len - ETH_HEADER_LEN));

switch (esp_err) {
case 1: /* send plaintext */
wolfIP_ll_send_frame(t->S, tx_if, probe, frame_len);
case 0: /* success */
break;
default: /* error */
LOG("esp_send: %d\n", esp_err);
return -1;
}
} else {
wolfIP_ll_send_frame(t->S, tx_if, probe, frame_len);
Expand Down Expand Up @@ -5094,9 +5144,17 @@ static int igmp_send_report(struct wolfIP *s, unsigned int if_idx, ip4 group,
* is configured for 224.0.0.22 so the normal path is unchanged. */
if (!wolfIP_ll_is_non_ethernet(s, if_idx)) {
struct wolfIP_ll_dev *ll = wolfIP_ll_at(s, if_idx);
if (esp_send(ll, ip, ip_len) == 1)
int esp_err = esp_send(ll, ip, ip_len);

switch (esp_err) {
case 1: /* send plaintext */
return wolfIP_ll_send_frame(s, if_idx, frame, sizeof(frame));
return 0;
case 0: /* success */
return 0;
default: /* error */
LOG("esp_send: %d\n", esp_err);
return -1;
}
}
#endif
return wolfIP_ll_send_frame(s, if_idx, frame, sizeof(frame));
Expand Down Expand Up @@ -5356,8 +5414,14 @@ static void wolfIP_forward_packet(struct wolfIP *s, unsigned int out_if,
/* Encapsulate the datagram at its declared length; bytes past
* the IP total length are L2 padding, not payload. */
int esp_err = esp_send(ll_esp, ip, (uint16_t)ee16(ip->len));
if (esp_err == 1) {

switch (esp_err) {
case 1: /* send plaintext */
wolfIP_ll_send_frame(s, out_if, ip, len);
case 0: /* success */
break;
default: /* error */
LOG("esp_send: %d\n", esp_err);
}
} else {
wolfIP_ll_send_frame(s, out_if, ip, len);
Expand Down Expand Up @@ -9393,10 +9457,15 @@ static void icmp_input(struct wolfIP *s, unsigned int if_idx, struct wolfIP_ip_p
struct wolfIP_ll_dev *ll = wolfIP_ll_at(s, if_idx);
/* Encapsulate the datagram at its declared length; bytes past
* the IP total length are L2 padding, not payload. */
if (esp_send(ll, ip, (uint16_t)ee16(ip->len)) == 1) {
/* ipsec not configured on this interface.
* send plaintext. */
int esp_err = esp_send(ll, ip, (uint16_t)ee16(ip->len));

switch (esp_err) {
case 1: /* send plaintext */
wolfIP_ll_send_frame(s, if_idx, ip, len);
case 0: /* success */
break;
default: /* error */
LOG("esp_send: %d\n", esp_err);
}
} else {
wolfIP_ll_send_frame(s, if_idx, ip, len);
Expand Down Expand Up @@ -12775,11 +12844,17 @@ static void flush_tcp_tx(struct wolfIP *s, uint64_t now)
#ifdef WOLFIP_ESP
if (!wolfIP_ll_is_non_ethernet(s, tx_if)) {
struct wolfIP_ll_dev *ll = wolfIP_ll_at(s, tx_if);
int esp_err = esp_send(ll, (struct wolfIP_ip_packet *)tcp, size);
if (esp_err == 1) {
/* ipsec not configured on this interface.
* send plaintext. */
send_ret = wolfIP_ll_send_frame(s, tx_if, tcp, desc->len);
send_ret = esp_send(ll, (struct wolfIP_ip_packet *)tcp,
size);

switch (send_ret) {
case 1: /* send plaintext */
send_ret = wolfIP_ll_send_frame(s, tx_if, tcp,
desc->len);
case 0: /* success */
break;
default: /* error */
LOG("esp_send: %d\n", send_ret);
}
} else {
send_ret = wolfIP_ll_send_frame(s, tx_if, tcp, desc->len);
Expand Down Expand Up @@ -12953,8 +13028,15 @@ static void flush_datagram_tx(struct wolfIP *s, struct tsocket *socks,
/* IPsec not configured on this interface.
* Send plaintext instead.
* */
if (esp_send(ll, ip, (uint16_t)(desc->len - ETH_HEADER_LEN)) == 1)
send_ret = esp_send(ll, ip, (uint16_t)(desc->len - ETH_HEADER_LEN));
switch (send_ret) {
case 1: /* send plaintext */
send_ret = wolfIP_ll_send_frame(s, tx_if, ip, desc->len);
case 0: /* success */
break;
default: /* error */
LOG("esp_send: %d\n", send_ret);
}
} else {
send_ret = wolfIP_ll_send_frame(s, tx_if, ip, desc->len);
}
Expand Down
Loading