@@ -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
5675struct 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 * */
646752static 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
0 commit comments