15 #include <openssl/des.h>
16 #include <openssl/rand.h>
17 #include <openssl/hmac.h>
18 #include <openssl/opensslv.h>
22 #include <odp/helper/odph_api.h>
24 #include <odp_ipsec_stream.h>
26 #define STREAM_MAGIC 0xBABE01234567CAFE
28 #define LOOP_DEQ_COUNT 32
31 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
32 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
43 static const char *shm_name =
"stream_db";
44 stream_db_t *stream_db;
46 void init_stream_db(
void)
56 ODPH_ERR(
"Error: shared mem reserve failed.\n");
62 if (stream_db == NULL) {
63 ODPH_ERR(
"Error: shared mem alloc failed.\n");
66 memset(stream_db, 0,
sizeof(*stream_db));
69 void deinit_stream_db(
void)
71 stream_db_entry_t *stream = NULL;
73 for (stream = stream_db->list; NULL != stream; stream = stream->next) {
74 free(stream->input.intf);
75 free(stream->output.intf);
81 ODPH_ERR(
"Error: shared mem not found.\n");
86 ODPH_ERR(
"Error: shared mem free failed.\n");
91 int create_stream_db_entry(
char *input)
98 stream_db_entry_t *entry = &stream_db->array[stream_db->index];
101 if (MAX_DB <= stream_db->index)
105 local = malloc(strlen(input) + 1);
108 strcpy(local, input);
115 while (NULL != (token = strtok_r(str,
",", &save))) {
121 parse_ipv4_string(token, &entry->src_ip, NULL);
124 parse_ipv4_string(token, &entry->dst_ip, NULL);
127 entry->input.intf = strdup(token);
130 entry->output.intf = strdup(token);
133 entry->count = atoi(token);
136 entry->length = atoi(token);
137 if (entry->length <
sizeof(stream_pkt_hdr_t))
140 entry->length -=
sizeof(stream_pkt_hdr_t);
143 printf(
"ERROR: extra token \"%s\" at position %d\n",
154 printf(
"ERROR: \"%s\" contains %d tokens, expected 6\n",
162 entry->id = stream_db->index++;
163 entry->next = stream_db->list;
164 stream_db->list = entry;
172 const EVP_MD *evp_md;
182 evp_md = EVP_sha256();
191 void resolve_stream_db(
void)
193 stream_db_entry_t *stream = NULL;
196 for (stream = stream_db->list; NULL != stream; stream = stream->next) {
197 ipsec_cache_entry_t *entry;
200 entry = find_ipsec_cache_entry_in(stream->src_ip,
204 stream->input.entry = entry;
209 stream->evp_md = get_evp_md(entry->ah.alg);
212 entry = find_ipsec_cache_entry_out(stream->src_ip,
215 stream->output.entry = entry;
219 if (stream->evp_md == NULL && entry)
220 stream->evp_md = get_evp_md(entry->ah.alg);
224 odp_packet_t create_ipv4_packet(stream_db_entry_t *stream,
229 ipsec_cache_entry_t *entry = NULL;
235 odph_ipv4hdr_t *inner_ip = NULL;
236 odph_ahhdr_t *ah = NULL;
237 odph_esphdr_t *esp = NULL;
238 odph_icmphdr_t *icmp;
239 stream_pkt_hdr_t *test;
242 if (stream->input.entry)
243 entry = stream->input.entry;
244 else if (stream->output.entry)
245 entry = stream->output.entry;
248 if ((stream->length + 200) > max_len) {
249 ODPH_ERR(
"Error: too large test packet\n");
256 ODPH_ERR(
"Error: packet alloc failed\n");
264 eth = (odph_ethhdr_t *)data;
265 data +=
sizeof(*eth);
267 memset((
char *)eth->src.addr, (0x80 | stream->id), ODPH_ETHADDR_LEN);
268 memcpy((
char *)eth->dst.addr, dmac, ODPH_ETHADDR_LEN);
273 ip = (odph_ipv4hdr_t *)data;
277 memset((
char *)ip, 0,
sizeof(*ip));
281 if (entry && entry->mode == IPSEC_SA_MODE_TUNNEL &&
282 (entry == stream->input.entry)) {
283 ip->proto = ODPH_IPV4;
287 ip->proto = ODPH_IPPROTO_ICMPV4;
293 if (entry && (entry == stream->input.entry) &&
300 ah = (odph_ahhdr_t *)data;
302 data += entry->ah.icv_len;
304 memset((
char *)ah, 0,
sizeof(*ah) + entry->ah.icv_len);
305 ah->ah_len = 1 + (entry->ah.icv_len / 4);
311 if (entry && (entry == stream->input.entry) &&
316 esp = (odph_esphdr_t *)data;
317 data +=
sizeof(*esp);
318 data += entry->esp.iv_len;
322 RAND_bytes(esp->iv, 8);
326 if (entry && (entry == stream->input.entry) &&
327 (entry->mode == IPSEC_SA_MODE_TUNNEL)) {
328 inner_ip = (odph_ipv4hdr_t *)data;
329 memset((
char *)inner_ip, 0,
sizeof(*inner_ip));
330 inner_ip->ver_ihl = 0x45;
332 sizeof(odph_icmphdr_t) +
333 sizeof(stream_pkt_hdr_t) +
335 inner_ip->proto = ODPH_IPPROTO_ICMPV4;
339 inner_ip->frag_offset = 0;
344 data +=
sizeof(*inner_ip);
348 icmp = (odph_icmphdr_t *)data;
349 data +=
sizeof(*icmp);
350 icmp->type = ODPH_ICMP_ECHO;
356 test = (stream_pkt_hdr_t *)data;
357 data +=
sizeof(*test);
359 for (i = 0; i < stream->length; i++)
360 *data++ = (uint8_t)i;
368 int payload_len = data - (uint8_t *)icmp;
369 uint8_t *encrypt_start = (uint8_t *)icmp;
371 if (entry->mode == IPSEC_SA_MODE_TUNNEL) {
372 payload_len = data - (uint8_t *)inner_ip;
373 encrypt_start = (uint8_t *)inner_ip;
377 odph_esptrl_t *esp_t;
378 DES_key_schedule ks1, ks2, ks3;
381 memcpy(iv, esp->iv,
sizeof(iv));
383 encrypt_len = ESP_ENCODE_LEN(payload_len +
sizeof(*esp_t),
384 entry->esp.block_len);
385 for (
int n = 0; n < encrypt_len - payload_len; n++)
388 esp_t = (odph_esptrl_t *)(data) - 1;
389 esp_t->pad_len = encrypt_len - payload_len -
sizeof(*esp_t);
390 esp_t->next_header = ip->proto;
391 ip->proto = ODPH_IPPROTO_ESP;
393 DES_set_key((DES_cblock *)&entry->esp.key.data[0], &ks1);
394 DES_set_key((DES_cblock *)&entry->esp.key.data[8], &ks2);
395 DES_set_key((DES_cblock *)&entry->esp.key.data[16], &ks3);
397 DES_ede3_cbc_encrypt(encrypt_start,
412 uint8_t hash[EVP_MAX_MD_SIZE];
413 int auth_len = data - (uint8_t *)ip;
415 ah->next_header = ip->proto;
416 ip->proto = ODPH_IPPROTO_AH;
420 entry->ah.key.length,
426 memcpy(ah->icv, hash, entry->ah.icv_len);
440 odph_ipv4_csum_update(pkt);
444 odp_bool_t verify_ipv4_packet(stream_db_entry_t *stream,
447 ipsec_cache_entry_t *entry = NULL;
450 odph_ahhdr_t *ah = NULL;
451 odph_esphdr_t *esp = NULL;
453 odph_icmphdr_t *icmp;
454 stream_pkt_hdr_t *test;
455 uint32_t src_ip, dst_ip;
457 if (stream->input.entry)
458 entry = stream->input.entry;
459 else if (stream->output.entry)
460 entry = stream->output.entry;
464 ip = (odph_ipv4hdr_t *)data;
466 if (0x45 != ip->ver_ihl)
471 if ((stream->src_ip != src_ip) && stream->output.entry &&
472 (stream->output.entry->tun_src_ip != src_ip))
474 if ((stream->dst_ip != dst_ip) && stream->output.entry &&
475 (stream->output.entry->tun_dst_ip != dst_ip))
478 if ((stream->src_ip != src_ip) && stream->input.entry &&
479 (stream->input.entry->tun_src_ip != src_ip))
481 if ((stream->dst_ip != dst_ip) && stream->input.entry &&
482 (stream->input.entry->tun_dst_ip != dst_ip))
486 hdr_len = locate_ipsec_headers(ip, &ah, &esp);
491 if (((stream->output.entry && (!ah && !esp))) ||
492 (stream->input.entry && (ah || esp)))
522 hdr_len += entry->esp.iv_len;
533 uint16_t ip_frag_offset;
534 uint8_t icv[entry->ah.icv_len];
535 uint8_t hash[EVP_MAX_MD_SIZE];
545 memcpy(icv, ah->icv, entry->ah.icv_len);
546 memset(ah->icv, 0, entry->ah.icv_len);
551 entry->ah.key.length,
557 if (0 != memcmp(icv, hash,
sizeof(icv)))
560 ip->proto = ah->next_header;
568 odph_esptrl_t *esp_t;
569 DES_key_schedule ks1, ks2, ks3;
571 int encrypt_len = ipv4_data_len(ip) - hdr_len;
573 memcpy(iv, esp->iv,
sizeof(iv));
575 DES_set_key((DES_cblock *)&entry->esp.key.data[0], &ks1);
576 DES_set_key((DES_cblock *)&entry->esp.key.data[8], &ks2);
577 DES_set_key((DES_cblock *)&entry->esp.key.data[16], &ks3);
579 DES_ede3_cbc_encrypt((uint8_t *)data,
588 esp_t = (odph_esptrl_t *)(data + encrypt_len) - 1;
589 ip->proto = esp_t->next_header;
594 if (entry && (entry->mode == IPSEC_SA_MODE_TUNNEL) && (ah || esp)) {
595 if (ODPH_IPV4 != ip->proto)
597 odph_ipv4hdr_t *inner_ip = (odph_ipv4hdr_t *)data;
599 icmp = (odph_icmphdr_t *)(inner_ip + 1);
600 data = (uint8_t *)icmp;
602 if (ODPH_IPPROTO_ICMPV4 != ip->proto)
604 icmp = (odph_icmphdr_t *)data;
608 data +=
sizeof(*icmp);
609 if (ODPH_ICMP_ECHO != icmp->type)
615 test = (stream_pkt_hdr_t *)data;
622 int create_stream_db_inputs(
void)
627 stream_db_entry_t *stream = NULL;
633 ODPH_ERR(
"Error: pkt_pool not found\n");
637 ODPH_ERR(
"Error: pool info failed\n");
645 for (stream = stream_db->list; NULL != stream; stream = stream->next) {
648 uint8_t dmac[ODPH_ETHADDR_LEN];
654 ODPH_ERR(
"Error: failed during MAC address get for "
655 "%s\n", stream->input.intf);
661 ODPH_ERR(
"Error: failed to get outqueue for %s\n",
666 for (count = stream->count; count > 0; count--) {
669 pkt = create_ipv4_packet(stream, dmac, pkt_pool, max_len);
671 ODPH_ERR(
"Error: packet buffers exhausted\n");
677 ODPH_ERR(
"Error: queue enqueue failed\n");
682 if (1 == stream->created)
686 if ((stream_db->index > 0) && created == 0) {
687 ODPH_ERR(
"Error: failed to create any input streams\n");
697 stream_db_entry_t *stream = NULL;
700 env = getenv(
"ODP_IPSEC_STREAM_VERIFY_MDEQ");
702 for (stream = stream_db->list; NULL != stream; stream = stream->next) {
711 ODPH_ERR(
"Error: failed to get inqueue for %s\n",
712 stream->output.intf);
728 for (idx = 0; idx < count; idx++) {
734 good = verify_ipv4_packet(stream, pkt);
741 printf(
"Stream %d %d\n", stream->created, stream->verified);
743 if (stream->created != stream->verified)
uint16_t odp_chksum_ones_comp16(const void *data, uint32_t data_len)
Ones' complement sum of 16-bit words.
#define ODP_PACKED
Defines type/struct to be packed.
odp_u16be_t odp_cpu_to_be_16(uint16_t cpu16)
Convert cpu native uint16_t to 16bit big endian.
odp_u64be_t odp_cpu_to_be_64(uint64_t cpu64)
Convert cpu native uint64_t to 64bit big endian.
uint16_t odp_be_to_cpu_16(odp_u16be_t be16)
Convert 16bit big endian to cpu native uint16_t.
uint64_t odp_be_to_cpu_64(odp_u64be_t be64)
Convert 64bit big endian to cpu native uint64_t.
odp_u32be_t odp_cpu_to_be_32(uint32_t cpu32)
Convert cpu native uint32_t to 32bit big endian.
uint64_t odp_u64be_t
unsigned 64bit big endian
uint32_t odp_be_to_cpu_32(odp_u32be_t be32)
Convert 32bit big endian to cpu native uint32_t.
odp_auth_alg_t
Crypto API authentication algorithm.
@ ODP_CIPHER_ALG_3DES_CBC
Triple DES with cipher block chaining.
@ ODP_CIPHER_ALG_NULL
No cipher algorithm specified.
@ ODP_AUTH_ALG_NULL
No authentication algorithm specified.
@ ODP_AUTH_ALG_MD5_HMAC
HMAC-MD5.
@ ODP_AUTH_ALG_SHA1_HMAC
HMAC-SHA-1.
@ ODP_AUTH_ALG_SHA256_HMAC
HMAC-SHA-256.
#define ODP_EVENT_INVALID
Invalid event.
int odp_pktio_mac_addr(odp_pktio_t pktio, void *mac_addr, int size)
Get the default MAC address of a packet IO interface.
odp_pktio_t odp_pktio_lookup(const char *name)
Return a packet IO handle for an already open device.
int odp_pktout_queue(odp_pktio_t pktio, odp_pktout_queue_t queues[], int num)
Direct packet output queues.
int odp_pktin_event_queue(odp_pktio_t pktio, odp_queue_t queues[], int num)
Event queues for packet input.
int odp_pktout_send(odp_pktout_queue_t queue, const odp_packet_t packets[], int num)
Send packets directly to an interface output queue.
int odp_packet_l3_offset_set(odp_packet_t pkt, uint32_t offset)
Set layer 3 start offset.
void * odp_packet_data(odp_packet_t pkt)
Packet data pointer.
int odp_packet_l4_offset_set(odp_packet_t pkt, uint32_t offset)
Set layer 4 start offset.
void odp_packet_has_eth_set(odp_packet_t pkt, int val)
Set flag for Ethernet header.
odp_packet_t odp_packet_alloc(odp_pool_t pool, uint32_t len)
Allocate a packet from a packet pool.
int odp_packet_l2_offset_set(odp_packet_t pkt, uint32_t offset)
Set layer 2 start offset.
odp_packet_t odp_packet_from_event(odp_event_t ev)
Get packet handle from event.
void odp_packet_free(odp_packet_t pkt)
Free packet.
#define ODP_PACKET_INVALID
Invalid packet.
void * odp_packet_l3_ptr(odp_packet_t pkt, uint32_t *len)
Layer 3 start pointer.
void * odp_packet_pull_tail(odp_packet_t pkt, uint32_t len)
Pull in packet tail.
void odp_packet_has_ipv4_set(odp_packet_t pkt, int val)
Set flag for IPv4.
odp_pool_t odp_pool_lookup(const char *name)
Find a pool by name.
int odp_pool_info(odp_pool_t pool, odp_pool_info_t *info)
Retrieve information about a pool.
#define ODP_POOL_INVALID
Invalid pool.
odp_event_t odp_queue_deq(odp_queue_t queue)
Dequeue an event from a queue.
int odp_queue_deq_multi(odp_queue_t queue, odp_event_t events[], int num)
Dequeue multiple events from a queue.
odp_shm_t odp_shm_lookup(const char *name)
Lookup for a block of shared memory.
int odp_shm_free(odp_shm_t shm)
Free a contiguous block of shared memory.
#define ODP_SHM_INVALID
Invalid shared memory block.
void * odp_shm_addr(odp_shm_t shm)
Shared memory block address.
odp_shm_t odp_shm_reserve(const char *name, uint64_t size, uint64_t align, uint32_t flags)
Reserve a contiguous block of shared memory.
bool odp_bool_t
Boolean type.
Pool information struct Used to get information about a pool.
odp_pool_param_t params
Copy of pool parameters.
uint32_t seg_len
Minimum number of packet data bytes that can be stored in the first segment of a newly allocated pack...
struct odp_pool_param_t::@126 pkt
Parameters for packet pools.