Skip to content

Commit c8e05b8

Browse files
committed
outbound aes cbc encryption working.
1 parent 1216dcd commit c8e05b8

3 files changed

Lines changed: 175 additions & 15 deletions

File tree

scripts/ip-xfrm/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Some convience scripts and config for testing IPsec with wolfIP:
1414
Build wolfssl with:
1515

1616
```sh
17-
./configure --enable-cryptonly --enable-sha --enable-sha256 --enable-md5
17+
./configure --enable-cryptonly --enable-sha --enable-sha256 --enable-md5 --enable-des3
1818
make
1919
sudo make install
2020
```

src/wolfesp.c

Lines changed: 166 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,25 @@ struct wolfIP_esp_sa {
5151
uint8_t icv_len;
5252
};
5353

54+
static WC_RNG wc_rng;
55+
static uint8_t rng_inited = 0;
56+
57+
static void
58+
esp_init(void)
59+
{
60+
if (rng_inited == 0) {
61+
int ret = wc_InitRng_ex(&wc_rng, NULL, INVALID_DEVID);
62+
63+
if (ret) {
64+
printf("error: wc_InitRng_ex returned: %d\n", ret);
65+
}
66+
67+
rng_inited = 1;
68+
}
69+
70+
return;
71+
}
72+
5473
/* Static pre-defined SA lists.*/
5574

5675
struct wolfIP_esp_sa in_sa_list[WOLFIP_ESP_NUM_SA] =
@@ -91,7 +110,7 @@ struct wolfIP_esp_sa out_sa_list[WOLFIP_ESP_NUM_SA] =
91110
{
92111
{0xf6, 0xe9, 0xb8, 0x0d}, /* spi */
93112
0x020A0A0A, /* src */
94-
0x010A0A0A, /* dst */
113+
0x030A0A0A, /* dst */
95114
0,0, /* oseq, seq */
96115
0, /* iv len */
97116
0, {0}, 0, /* null enc */
@@ -258,6 +277,31 @@ static void wolfIP_print_esp(const struct wolfIP_esp_sa * esp_sa,
258277
}
259278
#endif /* WOLFIP_DEBUG_ESP */
260279

280+
uint8_t
281+
esp_block_len_from_enc(esp_enc_t enc)
282+
{
283+
uint8_t block_len = 0;
284+
285+
switch (enc) {
286+
case ESP_ENC_NONE:
287+
block_len = 0;
288+
break;
289+
case ESP_ENC_CBC_AES:
290+
block_len = WC_AES_BLOCK_SIZE;
291+
break;
292+
case ESP_ENC_CBC_DES3:
293+
block_len = DES_BLOCK_SIZE;
294+
break;
295+
case ESP_ENC_GCM_RFC4106:
296+
case ESP_ENC_GCM_RFC4543:
297+
default:
298+
block_len = 0;
299+
break;
300+
}
301+
302+
return block_len;
303+
}
304+
261305
/*
262306
* esp_data covers from start of ESP header to end of ESP trailer, but does not
263307
* include the ESP ICV after trailer.
@@ -415,6 +459,68 @@ esp_aes_rfc3602_dec(const struct wolfIP_esp_sa * esp_sa, uint8_t * esp_data,
415459
return ret;
416460
}
417461

462+
static int
463+
esp_aes_rfc3602_enc(const struct wolfIP_esp_sa * esp_sa, uint8_t * esp_data,
464+
uint32_t esp_len)
465+
{
466+
Aes cbc_enc;
467+
int ret = -1;
468+
uint8_t icv_len = esp_sa->icv_len;
469+
uint8_t iv_len = esp_sa->iv_len;
470+
uint8_t * enc_payload = NULL;
471+
uint8_t * iv = NULL;
472+
uint16_t enc_len = 0;
473+
uint8_t inited = 0;
474+
475+
#ifdef WOLFIP_DEBUG_ESP
476+
printf("info: aes cbc enc\n");
477+
#endif /* WOLFIP_DEBUG_ESP */
478+
479+
enc_len = esp_enc_len(esp_len, iv_len, icv_len);
480+
enc_payload = esp_enc_payload(esp_data, iv_len);
481+
iv = esp_enc_iv(esp_data, iv_len);
482+
483+
/* Generate random iv block for cbc method. */
484+
ret = wc_RNG_GenerateBlock(&wc_rng, iv, iv_len);
485+
486+
if (ret) {
487+
printf("error: wc_RNG_GenerateBlock returned: %d\n", ret);
488+
goto aes_enc_out;
489+
}
490+
491+
ret = wc_AesInit(&cbc_enc, NULL, INVALID_DEVID);
492+
493+
if (ret != 0) {
494+
printf("error: wc_AesInit returned: %d\n", ret);
495+
goto aes_enc_out;
496+
}
497+
498+
inited = 1;
499+
ret = wc_AesSetKey(&cbc_enc, esp_sa->enc_key, AES_BLOCK_SIZE,
500+
iv, AES_ENCRYPTION);
501+
502+
if (ret != 0) {
503+
printf("error: wc_AesSetKey returned: %d\n", ret);
504+
goto aes_enc_out;
505+
}
506+
507+
ret = wc_AesCbcEncrypt(&cbc_enc, enc_payload, enc_payload, enc_len);
508+
509+
if (ret != 0) {
510+
printf("error: wc_AesCbcEncrypt returned: %d\n", ret);
511+
goto aes_enc_out;
512+
}
513+
514+
aes_enc_out:
515+
if (inited) {
516+
wc_AesFree(&cbc_enc);
517+
inited = 0;
518+
}
519+
520+
return ret;
521+
}
522+
523+
418524
/**
419525
* esp_data covers from start of ESP header to end of ESP trailer, but does not
420526
* include the ESP ICV after trailer.
@@ -645,15 +751,17 @@ static int esp_unwrap(struct wolfIP *s, struct wolfIP_ip_packet *ip,
645751
* */
646752
static int esp_wrap(struct wolfIP_ip_packet *ip, uint16_t * ip_len)
647753
{
754+
uint8_t block_len = 0;
648755
uint16_t orig_ip_len = *ip_len;
649756
uint16_t orig_payload_len = orig_ip_len - IP_HEADER_LEN;
650-
uint16_t payload_len = orig_ip_len - IP_HEADER_LEN;
757+
uint16_t payload_len = 0;
651758
uint8_t * payload = ip->data;
652759
uint8_t pad_len = 0;
653760
uint32_t seq_n = 0; /* sequence num in network order */
654761
uint16_t icv_offset = 0;
655762
struct wolfIP_esp_sa * esp_sa = NULL;
656763

764+
/* TODO: priority, tcp/udp port-filtering? */
657765
for (size_t i = 0; i < WOLFIP_ESP_NUM_SA; ++i) {
658766
if (ip->dst == out_sa_list[i].dst) {
659767
esp_sa = &out_sa_list[i];
@@ -685,7 +793,7 @@ static int esp_wrap(struct wolfIP_ip_packet *ip, uint16_t * ip_len)
685793
return 0;
686794
#endif
687795

688-
/* move ip payload back to make room for ESP header (SPI, SEQ, IV). */
796+
/* move ip payload back to make room for ESP header (SPI, SEQ) + IV. */
689797
memmove(ip->data + ESP_SPI_LEN + ESP_SEQ_LEN + esp_sa->iv_len,
690798
ip->data, orig_payload_len);
691799

@@ -699,25 +807,43 @@ static int esp_wrap(struct wolfIP_ip_packet *ip, uint16_t * ip_len)
699807
payload += ESP_SEQ_LEN;
700808

701809
if (esp_sa->iv_len) {
810+
/* skip iv field, will generate later. */
702811
payload += esp_sa->iv_len;
703812
}
704813

705-
payload_len += ESP_SPI_LEN + ESP_SEQ_LEN + esp_sa->iv_len;
814+
block_len = esp_block_len_from_enc(esp_sa->enc);
815+
816+
if (block_len) {
817+
/* Block cipher. Calculate padding and encrypted length, then
818+
* icv_offset. */
819+
uint32_t enc_len = 0;
820+
enc_len = esp_sa->iv_len + orig_payload_len + pad_len
821+
+ ESP_PADDING_LEN + ESP_NEXT_HEADER_LEN;
822+
823+
/* Determine padding. This needs to be flexible for
824+
* des3 (8 byte) or aes (16 byte) block sizes.*/
825+
if (enc_len % block_len) {
826+
pad_len = block_len - (enc_len % block_len);
827+
}
706828

707-
{
708-
/* Stream cipher or auth-only. Calculate the icv offset. */
829+
icv_offset = ESP_SPI_LEN + ESP_SEQ_LEN + esp_sa->iv_len
830+
+ orig_payload_len + pad_len + ESP_PADDING_LEN
831+
+ ESP_NEXT_HEADER_LEN;
832+
}
833+
else {
834+
/* Stream cipher or auth-only. Calculate the icv offset directly. */
709835
icv_offset = ESP_SPI_LEN + ESP_SEQ_LEN + esp_sa->iv_len
710836
+ orig_payload_len + pad_len + ESP_PADDING_LEN
711837
+ ESP_NEXT_HEADER_LEN;
712838

713839
/* Determine padding. */
714840
if (icv_offset % ESP_ICV_ALIGNMENT) {
715-
pad_len = ESP_ICV_ALIGNMENT - (icv_offset % ESP_ICV_ALIGNMENT);
716-
icv_offset += pad_len;
841+
pad_len = ESP_ICV_ALIGNMENT - (icv_offset % ESP_ICV_ALIGNMENT);
842+
icv_offset += pad_len;
717843
}
718844
}
719845

720-
/* Skip past the original payload. */
846+
/* Skip past the original payload, add padding. */
721847
payload += orig_payload_len;
722848

723849
if (pad_len) {
@@ -727,22 +853,48 @@ static int esp_wrap(struct wolfIP_ip_packet *ip, uint16_t * ip_len)
727853
}
728854

729855
payload += pad_len;
730-
payload_len += pad_len;
731856
}
732857

733-
/* Copy in padding len and next header. */
858+
/* ESP trailer. Copy in padding len and next header fields. */
734859
memcpy(payload, &pad_len, ESP_PADDING_LEN);
735860
payload += ESP_PADDING_LEN;
736-
payload_len += ESP_PADDING_LEN;
737861

738862
memcpy(payload, &ip->proto, ESP_NEXT_HEADER_LEN);
739863
payload += ESP_NEXT_HEADER_LEN;
740-
payload_len += ESP_NEXT_HEADER_LEN;
864+
865+
/* calculate final esp payload length. */
866+
payload_len = orig_ip_len - IP_HEADER_LEN;
867+
payload_len += ESP_SPI_LEN + ESP_SEQ_LEN + esp_sa->iv_len +
868+
pad_len + ESP_PADDING_LEN + ESP_NEXT_HEADER_LEN +
869+
esp_sa->icv_len;
870+
871+
/* encrypt from payload to end of ESP trailer. */
872+
if (esp_sa->iv_len) {
873+
int err = -1;
874+
875+
switch(esp_sa->enc) {
876+
case ESP_ENC_CBC_AES:
877+
err = esp_aes_rfc3602_enc(esp_sa, ip->data, payload_len);
878+
break;
879+
880+
case ESP_ENC_NONE:
881+
default:
882+
printf("error: encrypt: invalid enc: %d\n", esp_sa->enc);
883+
err = -1;
884+
break;
885+
}
886+
887+
if (err) {
888+
printf("error: esp_encrypt(%02x) returned: %d\n", esp_sa->enc, err);
889+
return -1;
890+
}
891+
892+
/* Payload is now encrypted. Now calculate ICV. */
893+
}
741894

742895
if (esp_sa->icv_len) {
743896
uint8_t * icv = NULL;
744897
int rc = 0;
745-
payload_len += esp_sa->icv_len;
746898

747899
icv = ip->data + icv_offset;
748900

src/wolfip.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1993,6 +1993,10 @@ static int arp_lookup(struct wolfIP *s, ip4 ip, uint8_t *mac)
19931993
void wolfIP_init(struct wolfIP *s)
19941994
{
19951995
memset(s, 0, sizeof(struct wolfIP));
1996+
1997+
#ifdef WOLFIP_ESP
1998+
esp_init();
1999+
#endif /* WOLFIP_ESP */
19962000
}
19972001

19982002
struct ll *wolfIP_getdev(struct wolfIP *s)
@@ -2007,6 +2011,10 @@ void wolfIP_init_static(struct wolfIP **s)
20072011
return;
20082012
wolfIP_init(&wolfIP_static);
20092013
*s = &wolfIP_static;
2014+
2015+
#ifdef WOLFIP_ESP
2016+
esp_init();
2017+
#endif /* WOLFIP_ESP */
20102018
}
20112019

20122020
#ifdef DEBUG_IP

0 commit comments

Comments
 (0)