Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
19 changes: 17 additions & 2 deletions src/test/unit/unit_esp.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ static uint8_t spi_a[4] = { 0x11, 0x22, 0x33, 0x44 };
static uint8_t spi_b[4] = { 0x55, 0x66, 0x77, 0x88 };
static uint8_t spi_c[4] = { 0x99, 0xAA, 0xBB, 0xCC };
static uint8_t spi_d[4] = { 0xFF, 0xEE, 0xDD, 0xCC }; /* overflows pool */
static uint8_t spi_bad[4] = { 0x00, 0x00, 0x00, 0x00 };

/* Test IP addresses. */
#define T_SRC "192.168.1.1"
Expand Down Expand Up @@ -206,6 +207,14 @@ START_TEST(test_sa_hmac_bad)
int ret;
esp_setup();

/* everything good but spi */
ret = wolfIP_esp_sa_new_hmac(1, (uint8_t *)spi_bad,
atoip4(T_SRC), atoip4(T_DST),
ESP_AUTH_SHA256_RFC4868,
(uint8_t *)k_auth16, sizeof(k_auth16),
ESP_ICVLEN_HMAC_128);
ck_assert_int_eq(ret, -1);

/* auth with wrong icv len */
ret = wolfIP_esp_sa_new_hmac(1, (uint8_t *)spi_a,
atoip4(T_SRC), atoip4(T_DST),
Expand Down Expand Up @@ -255,6 +264,12 @@ START_TEST(test_sa_cbc_hmac_bad)
{
int ret;
esp_setup();
ret = wolfIP_esp_sa_new_cbc_hmac(1, (uint8_t *)spi_bad,
atoip4(T_SRC), atoip4(T_DST),
(uint8_t *)k_aes128, sizeof(k_aes128),
ESP_AUTH_NONE, NULL, 0, 0);
ck_assert_int_eq(ret, -1);

ret = wolfIP_esp_sa_new_cbc_hmac(1, (uint8_t *)spi_a,
atoip4(T_SRC), atoip4(T_DST),
(uint8_t *)k_aes128, sizeof(k_aes128),
Expand Down Expand Up @@ -1248,8 +1263,8 @@ END_TEST

/*
* no matching outbound SA (esp_transport_wrap returns 1)
* */
/* When no outbound SA matches ip->dst, wrap must return 1 (caller should
*
* When no outbound SA matches ip->dst, wrap must return 1 (caller should
* send plaintext). */
START_TEST(test_wrap_no_matching_sa)
{
Expand Down
116 changes: 102 additions & 14 deletions src/wolfesp.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,19 @@ void wolfIP_esp_sa_del_all(void)
return;
}

static const uint8_t zero_spi[ESP_SPI_LEN] = {0x00, 0x00, 0x00, 0x00};

/* Get an SA by spi.
* If spi is null, return the first empty slot (an SA with all zero SPI).
* */
static inline wolfIP_esp_sa *
esp_sa_get(int in, const uint8_t * spi)
{
uint8_t empty_sa[4] = {0x00, 0x00, 0x00, 0x00};
wolfIP_esp_sa * list = NULL;
size_t i = 0;

if (spi == NULL) {
spi = empty_sa;
spi = zero_spi;
}

in = (in == 0 ? 0 : 1);
Expand Down Expand Up @@ -109,6 +113,30 @@ void wolfIP_esp_sa_del(int in, uint8_t * spi)
return;
}

/* return 0 if valid spi number.
* return -1 if invalid
* */
static inline int
esp_spi_valid(const uint8_t * spi)
{
if (spi == NULL) {
return -1;
}
/* RFC4303:
* The SPI value of zero (0) is reserved for local,
* implementation-specific use and MUST NOT be sent on the wire.
* */
if (memcmp(spi, zero_spi, ESP_SPI_LEN) == 0) {
ESP_LOG("info: invalid zero (0) value spi\n");
return -1;
}

/* SPI values 1 through 255 are reserved by IANA, and technically we
* could check and reject them. Probably not worth being this fastidious.
* */
return 0;
}

/* Configure a new Security Association based on either
* enc = ESP_ENC_GCM_RFC4106 (gcm), or enc = ESP_AUTH_GCM_RFC4543 (gmac).
* */
Expand All @@ -120,6 +148,10 @@ int wolfIP_esp_sa_new_gcm(int in, uint8_t * spi, ip4 src, ip4 dst,
int err = 0;
esp_auth_t auth = 0;

if (esp_spi_valid(spi) < 0) {
return -1;
}

new_sa = esp_sa_get(in, NULL);
if (new_sa == NULL) {
ESP_LOG("error: sa %s pool is full\n", in == 1 ? "in" : "out");
Expand Down Expand Up @@ -233,6 +265,10 @@ int wolfIP_esp_sa_new_hmac(int in, uint8_t * spi, ip4 src, ip4 dst,
{
wolfIP_esp_sa * new_sa = NULL;

if (esp_spi_valid(spi) < 0) {
return -1;
}

new_sa = esp_sa_get(in, NULL);
if (new_sa == NULL) {
ESP_LOG("error: sa %s pool is full\n", in == 1 ? "in" : "out");
Expand Down Expand Up @@ -275,6 +311,10 @@ int wolfIP_esp_sa_new_cbc_hmac(int in, uint8_t * spi, ip4 src, ip4 dst,
{
wolfIP_esp_sa * new_sa = NULL;

if (esp_spi_valid(spi) < 0) {
return -1;
}

new_sa = esp_sa_get(in, NULL);
if (new_sa == NULL) {
ESP_LOG("error: sa %s pool is full\n", in == 1 ? "in" : "out");
Expand Down Expand Up @@ -329,6 +369,10 @@ wolfIP_esp_sa_new_des3_hmac(int in, uint8_t * spi, ip4 src, ip4 dst,
{
wolfIP_esp_sa * new_sa = NULL;

if (esp_spi_valid(spi) < 0) {
return -1;
}

new_sa = esp_sa_get(in, NULL);
if (new_sa == NULL) {
ESP_LOG("error: sa %s pool is full\n", in == 1 ? "in" : "out");
Expand Down Expand Up @@ -1312,13 +1356,42 @@ esp_transport_unwrap(struct wolfIP_ip_packet *ip, uint32_t * frame_len)
memcpy(&seq, ip->data + ESP_SPI_LEN, sizeof(seq));
seq = ee32(seq);

if (esp_spi_valid(spi) < 0) {
return -1;
}

/* ESP SA lookup:
* - If user configured {spi, src, dst}, then match on full triplet.
* - If either src or dst are 0, don't require a full match.
* - The spi must always match.
* */
for (size_t i = 0; i < in_sa_num; ++i) {
if (memcmp(spi, in_sa_list[i].spi, sizeof(spi)) == 0) {
ESP_DEBUG("info: found sa: 0x%02x%02x%02x%02x\n",
spi[0], spi[1], spi[2], spi[3]);
esp_sa = &in_sa_list[i];
break;
if (esp_spi_valid(out_sa_list[i].spi) < 0) {
/* skip empty slots */
continue;
}
Comment thread
philljj marked this conversation as resolved.

if (memcmp(spi, in_sa_list[i].spi, sizeof(spi)) != 0) {
Comment thread
philljj marked this conversation as resolved.
/* SPI doesn't match */
continue;
}

if (in_sa_list[i].dst != 0 &&
ip->dst != ee32(in_sa_list[i].dst)) {
/* SA ip dst is configured, and doesn't match */
continue;
}

if (in_sa_list[i].src != 0 &&
ip->src != ee32(in_sa_list[i].src)) {
/* SA ip src is configured, and doesn't match */
continue;
}

ESP_DEBUG("info: found sa: 0x%02x%02x%02x%02x\n",
spi[0], spi[1], spi[2], spi[3]);
esp_sa = &in_sa_list[i];
break;
}

if (esp_sa == NULL) {
Expand Down Expand Up @@ -1521,15 +1594,30 @@ esp_transport_wrap(struct wolfIP_ip_packet *ip, uint16_t * ip_len)
}

/* todo: priority, proto / port filtering. currently this grabs
* the first dst match. */
* the first dst and src match. */
for (size_t i = 0; i < out_sa_num; ++i) {
if (ip->dst == ee32(out_sa_list[i].dst)) {
esp_sa = &out_sa_list[i];
ESP_DEBUG("info: found out sa: 0x%02x%02x%02x%02x\n",
esp_sa->spi[0], esp_sa->spi[1], esp_sa->spi[2],
esp_sa->spi[3]);
break;
if (esp_spi_valid(out_sa_list[i].spi) < 0) {
/* skip empty slots */
continue;
}
Comment thread
philljj marked this conversation as resolved.

if (out_sa_list[i].dst != 0 &&
ip->dst != ee32(out_sa_list[i].dst)) {
/* SA ip dst is configured, and doesn't match */
continue;
}
Comment thread
philljj marked this conversation as resolved.

if (out_sa_list[i].src != 0 &&
ip->src != ee32(out_sa_list[i].src)) {
/* SA ip src is configured, and doesn't match */
continue;
}

esp_sa = &out_sa_list[i];
ESP_DEBUG("info: found out sa: 0x%02x%02x%02x%02x\n",
esp_sa->spi[0], esp_sa->spi[1], esp_sa->spi[2],
esp_sa->spi[3]);
break;
}

if (esp_sa == NULL) {
Expand Down
Loading