diff options
Diffstat (limited to 'example/ipsec/odp_ipsec_stream.c')
-rw-r--r-- | example/ipsec/odp_ipsec_stream.c | 635 |
1 files changed, 0 insertions, 635 deletions
diff --git a/example/ipsec/odp_ipsec_stream.c b/example/ipsec/odp_ipsec_stream.c deleted file mode 100644 index e37fbee29..000000000 --- a/example/ipsec/odp_ipsec_stream.c +++ /dev/null @@ -1,635 +0,0 @@ -/* Copyright (c) 2014, Linaro Limited - * All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/* enable strtok */ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#include <stdlib.h> -#include <string.h> - -#include <openssl/des.h> -#include <openssl/rand.h> -#include <openssl/hmac.h> -#include <openssl/evp.h> - -#include <example_debug.h> - -#include <odp_api.h> - -#include <odp/helper/odph_api.h> - -#include <odp_ipsec_stream.h> -#include <odp_ipsec_loop_db.h> - -#define STREAM_MAGIC 0xBABE01234567CAFE - -#define LOOP_DEQ_COUNT 32 /**< packets to dequeue at once */ - -/** - * Stream packet header - */ -typedef struct ODP_PACKED stream_pkt_hdr_s { - odp_u64be_t magic; /**< Stream magic value for verification */ - uint8_t data[0]; /**< Incrementing data stream */ -} stream_pkt_hdr_t; - -stream_db_t *stream_db; - -void init_stream_db(void) -{ - odp_shm_t shm; - - shm = odp_shm_reserve("stream_db", - sizeof(stream_db_t), - ODP_CACHE_LINE_SIZE, - 0); - - stream_db = odp_shm_addr(shm); - - if (stream_db == NULL) { - EXAMPLE_ERR("Error: shared mem alloc failed.\n"); - exit(EXIT_FAILURE); - } - memset(stream_db, 0, sizeof(*stream_db)); -} - -int create_stream_db_entry(char *input) -{ - int pos = 0; - char *local; - char *str; - char *save; - char *token; - stream_db_entry_t *entry = &stream_db->array[stream_db->index]; - - /* Verify we have a good entry */ - if (MAX_DB <= stream_db->index) - return -1; - - /* Make a local copy */ - local = malloc(strlen(input) + 1); - if (NULL == local) - return -1; - strcpy(local, input); - - /* Setup for using "strtok_r" to search input string */ - str = local; - save = NULL; - - /* Parse tokens separated by ':' */ - while (NULL != (token = strtok_r(str, ":", &save))) { - str = NULL; /* reset str for subsequent strtok_r calls */ - - /* Parse token based on its position */ - switch (pos) { - case 0: - parse_ipv4_string(token, &entry->src_ip, NULL); - break; - case 1: - parse_ipv4_string(token, &entry->dst_ip, NULL); - break; - case 2: - entry->input.loop = loop_if_index(token); - if (entry->input.loop < 0) { - EXAMPLE_ERR("Error: stream must have input" - " loop\n"); - exit(EXIT_FAILURE); - } - break; - case 3: - entry->output.loop = loop_if_index(token); - break; - case 4: - entry->count = atoi(token); - break; - case 5: - entry->length = atoi(token); - if (entry->length < sizeof(stream_pkt_hdr_t)) - entry->length = 0; - else - entry->length -= sizeof(stream_pkt_hdr_t); - break; - default: - printf("ERROR: extra token \"%s\" at position %d\n", - token, pos); - break; - } - - /* Advance to next position */ - pos++; - } - - /* Verify we parsed exactly the number of tokens we expected */ - if (6 != pos) { - printf("ERROR: \"%s\" contains %d tokens, expected 6\n", - input, - pos); - free(local); - return -1; - } - - /* Add stream to the list */ - entry->id = stream_db->index++; - entry->next = stream_db->list; - stream_db->list = entry; - - free(local); - return 0; -} - -void resolve_stream_db(void) -{ - stream_db_entry_t *stream = NULL; - - /* For each stream look for input and output IPsec entries */ - for (stream = stream_db->list; NULL != stream; stream = stream->next) { - ipsec_cache_entry_t *entry; - - /* Lookup input entry */ - entry = find_ipsec_cache_entry_in(stream->src_ip, - stream->dst_ip, - NULL, - NULL); - stream->input.entry = entry; - - /* Lookup output entry */ - entry = find_ipsec_cache_entry_out(stream->src_ip, - stream->dst_ip, - 0); - stream->output.entry = entry; - } -} - -odp_packet_t create_ipv4_packet(stream_db_entry_t *stream, - uint8_t *dmac, - odp_pool_t pkt_pool) -{ - ipsec_cache_entry_t *entry = NULL; - odp_packet_t pkt; - uint8_t *base; - uint8_t *data; - odph_ethhdr_t *eth; - odph_ipv4hdr_t *ip; - odph_ipv4hdr_t *inner_ip = NULL; - odph_ahhdr_t *ah = NULL; - odph_esphdr_t *esp = NULL; - odph_icmphdr_t *icmp; - stream_pkt_hdr_t *test; - unsigned i; - - if (stream->input.entry) - entry = stream->input.entry; - else if (stream->output.entry) - entry = stream->output.entry; - - /* Get packet */ - pkt = odp_packet_alloc(pkt_pool, 0); - if (ODP_PACKET_INVALID == pkt) - return ODP_PACKET_INVALID; - base = odp_packet_data(pkt); - data = odp_packet_data(pkt); - - /* Ethernet */ - odp_packet_has_eth_set(pkt, 1); - eth = (odph_ethhdr_t *)data; - data += sizeof(*eth); - - memset((char *)eth->src.addr, (0x80 | stream->id), ODPH_ETHADDR_LEN); - memcpy((char *)eth->dst.addr, dmac, ODPH_ETHADDR_LEN); - eth->type = odp_cpu_to_be_16(ODPH_ETHTYPE_IPV4); - - /* IPv4 */ - odp_packet_has_ipv4_set(pkt, 1); - ip = (odph_ipv4hdr_t *)data; - data += sizeof(*ip); - - /* Wait until almost finished to fill in mutable fields */ - memset((char *)ip, 0, sizeof(*ip)); - ip->ver_ihl = 0x45; - ip->id = odp_cpu_to_be_16(stream->id); - /* Outer IP header in tunnel mode */ - if (entry && entry->mode == IPSEC_SA_MODE_TUNNEL && - (entry == stream->input.entry)) { - ip->proto = ODPH_IPV4; - ip->src_addr = odp_cpu_to_be_32(entry->tun_src_ip); - ip->dst_addr = odp_cpu_to_be_32(entry->tun_dst_ip); - } else { - ip->proto = ODPH_IPPROTO_ICMPv4; - ip->src_addr = odp_cpu_to_be_32(stream->src_ip); - ip->dst_addr = odp_cpu_to_be_32(stream->dst_ip); - } - - /* AH (if specified) */ - if (entry && (entry == stream->input.entry) && - (ODP_AUTH_ALG_NULL != entry->ah.alg)) { - if (entry->ah.alg != ODP_AUTH_ALG_MD5_HMAC && - entry->ah.alg != ODP_AUTH_ALG_SHA256_HMAC) - abort(); - - ah = (odph_ahhdr_t *)data; - data += sizeof(*ah); - data += entry->ah.icv_len; - - memset((char *)ah, 0, sizeof(*ah) + entry->ah.icv_len); - ah->ah_len = 1 + (entry->ah.icv_len / 4); - ah->spi = odp_cpu_to_be_32(entry->ah.spi); - ah->seq_no = odp_cpu_to_be_32(stream->input.ah_seq++); - } - - /* ESP (if specified) */ - if (entry && (entry == stream->input.entry) && - (ODP_CIPHER_ALG_NULL != entry->esp.alg)) { - if (ODP_CIPHER_ALG_3DES_CBC != entry->esp.alg) - abort(); - - esp = (odph_esphdr_t *)data; - data += sizeof(*esp); - data += entry->esp.iv_len; - - esp->spi = odp_cpu_to_be_32(entry->esp.spi); - esp->seq_no = odp_cpu_to_be_32(stream->input.esp_seq++); - RAND_bytes(esp->iv, 8); - } - - /* Inner IP header in tunnel mode */ - if (entry && (entry == stream->input.entry) && - (entry->mode == IPSEC_SA_MODE_TUNNEL)) { - inner_ip = (odph_ipv4hdr_t *)data; - memset((char *)inner_ip, 0, sizeof(*inner_ip)); - inner_ip->ver_ihl = 0x45; - inner_ip->proto = ODPH_IPPROTO_ICMPv4; - inner_ip->id = odp_cpu_to_be_16(stream->id); - inner_ip->ttl = 64; - inner_ip->tos = 0; - inner_ip->frag_offset = 0; - inner_ip->src_addr = odp_cpu_to_be_32(stream->src_ip); - inner_ip->dst_addr = odp_cpu_to_be_32(stream->dst_ip); - inner_ip->chksum = odph_chksum(inner_ip, sizeof(*inner_ip)); - data += sizeof(*inner_ip); - } - - /* ICMP header so we can see it on wireshark */ - icmp = (odph_icmphdr_t *)data; - data += sizeof(*icmp); - icmp->type = ICMP_ECHO; - icmp->code = 0; - icmp->un.echo.id = odp_cpu_to_be_16(0x1234); - icmp->un.echo.sequence = odp_cpu_to_be_16(stream->created); - - /* Packet payload of incrementing bytes */ - test = (stream_pkt_hdr_t *)data; - data += sizeof(*test); - test->magic = odp_cpu_to_be_64(STREAM_MAGIC); - for (i = 0; i < stream->length; i++) - *data++ = (uint8_t)i; - - /* Close ICMP */ - icmp->chksum = 0; - icmp->chksum = odph_chksum(icmp, data - (uint8_t *)icmp); - - /* Close ESP if specified */ - if (esp) { - int payload_len = data - (uint8_t *)icmp; - uint8_t *encrypt_start = (uint8_t *)icmp; - - if (entry->mode == IPSEC_SA_MODE_TUNNEL) { - payload_len = data - (uint8_t *)inner_ip; - encrypt_start = (uint8_t *)inner_ip; - } - - int encrypt_len; - odph_esptrl_t *esp_t; - DES_key_schedule ks1, ks2, ks3; - uint8_t iv[8]; - - memcpy(iv, esp->iv, sizeof(iv)); - - encrypt_len = ESP_ENCODE_LEN(payload_len + sizeof(*esp_t), - entry->esp.block_len); - memset(data, 0, encrypt_len - payload_len); - data += encrypt_len - payload_len; - - esp_t = (odph_esptrl_t *)(data) - 1; - esp_t->pad_len = encrypt_len - payload_len - sizeof(*esp_t); - esp_t->next_header = ip->proto; - ip->proto = ODPH_IPPROTO_ESP; - - DES_set_key((DES_cblock *)&entry->esp.key.data[0], &ks1); - DES_set_key((DES_cblock *)&entry->esp.key.data[8], &ks2); - DES_set_key((DES_cblock *)&entry->esp.key.data[16], &ks3); - - DES_ede3_cbc_encrypt(encrypt_start, - encrypt_start, - encrypt_len, - &ks1, - &ks2, - &ks3, - (DES_cblock *)iv, - 1); - } - - /* Since ESP can pad we can now fix IP length */ - ip->tot_len = odp_cpu_to_be_16(data - (uint8_t *)ip); - - /* Close AH if specified */ - if (ah) { - uint8_t hash[EVP_MAX_MD_SIZE]; - int auth_len = data - (uint8_t *)ip; - - ah->next_header = ip->proto; - ip->proto = ODPH_IPPROTO_AH; - - HMAC(EVP_md5(), - entry->ah.key.data, - entry->ah.key.length, - (uint8_t *)ip, - auth_len, - hash, - NULL); - - memcpy(ah->icv, hash, 12); - } - - /* Correct set packet length offsets */ - odp_packet_push_tail(pkt, data - base); - odp_packet_l2_offset_set(pkt, (uint8_t *)eth - base); - odp_packet_l3_offset_set(pkt, (uint8_t *)ip - base); - odp_packet_l4_offset_set(pkt, ((uint8_t *)ip - base) + sizeof(*ip)); - - /* Now fill in final IP header fields */ - ip->ttl = 64; - ip->tos = 0; - ip->frag_offset = 0; - ip->chksum = 0; - odph_ipv4_csum_update(pkt); - return pkt; -} - -odp_bool_t verify_ipv4_packet(stream_db_entry_t *stream, - odp_packet_t pkt) -{ - ipsec_cache_entry_t *entry = NULL; - uint8_t *data; - odph_ipv4hdr_t *ip; - odph_ahhdr_t *ah = NULL; - odph_esphdr_t *esp = NULL; - int hdr_len; - odph_icmphdr_t *icmp; - stream_pkt_hdr_t *test; - uint32_t src_ip, dst_ip; - - if (stream->input.entry) - entry = stream->input.entry; - else if (stream->output.entry) - entry = stream->output.entry; - - /* Basic IPv4 verify (add checksum verification) */ - data = odp_packet_l3_ptr(pkt, NULL); - ip = (odph_ipv4hdr_t *)data; - data += sizeof(*ip); - if (0x45 != ip->ver_ihl) - return FALSE; - - src_ip = odp_be_to_cpu_32(ip->src_addr); - dst_ip = odp_be_to_cpu_32(ip->dst_addr); - if ((stream->src_ip != src_ip) && stream->output.entry && - (stream->output.entry->tun_src_ip != src_ip)) - return FALSE; - if ((stream->dst_ip != dst_ip) && stream->output.entry && - (stream->output.entry->tun_dst_ip != dst_ip)) - return FALSE; - - if ((stream->src_ip != src_ip) && stream->input.entry && - (stream->input.entry->tun_src_ip != src_ip)) - return FALSE; - if ((stream->dst_ip != dst_ip) && stream->input.entry && - (stream->input.entry->tun_dst_ip != dst_ip)) - return FALSE; - - /* Find IPsec headers if any and compare against entry */ - hdr_len = locate_ipsec_headers(ip, &ah, &esp); - - /* Cleartext packet */ - if (!ah && !esp) - goto clear_packet; - if (ah) { - if (!entry) - return FALSE; - if (ODP_AUTH_ALG_NULL == entry->ah.alg) - return FALSE; - if (odp_be_to_cpu_32(ah->spi) != entry->ah.spi) - return FALSE; - if (ODP_AUTH_ALG_MD5_HMAC != entry->ah.alg) - abort(); - } else { - if (entry && (ODP_AUTH_ALG_NULL != entry->ah.alg)) - return FALSE; - } - if (esp) { - if (!entry) - return FALSE; - if (ODP_CIPHER_ALG_NULL == entry->esp.alg) - return FALSE; - if (odp_be_to_cpu_32(esp->spi) != entry->esp.spi) - return FALSE; - if (ODP_CIPHER_ALG_3DES_CBC != entry->esp.alg) - abort(); - hdr_len += entry->esp.iv_len; - } else { - if (entry && (ODP_CIPHER_ALG_NULL != entry->esp.alg)) - return FALSE; - } - data += hdr_len; - - /* Verify authentication (if present) */ - if (ah) { - uint8_t ip_tos; - uint8_t ip_ttl; - uint16_t ip_frag_offset; - uint8_t icv[12]; - uint8_t hash[EVP_MAX_MD_SIZE]; - - /* Save/clear mutable fields */ - ip_tos = ip->tos; - ip_ttl = ip->ttl; - ip_frag_offset = odp_be_to_cpu_16(ip->frag_offset); - ip->tos = 0; - ip->ttl = 0; - ip->frag_offset = 0; - ip->chksum = 0; - memcpy(icv, ah->icv, 12); - memset(ah->icv, 0, 12); - - /* Calculate HMAC and compare */ - HMAC(EVP_md5(), - entry->ah.key.data, - entry->ah.key.length, - (uint8_t *)ip, - odp_be_to_cpu_16(ip->tot_len), - hash, - NULL); - - if (0 != memcmp(icv, hash, sizeof(icv))) - return FALSE; - - ip->proto = ah->next_header; - ip->tos = ip_tos; - ip->ttl = ip_ttl; - ip->frag_offset = odp_cpu_to_be_16(ip_frag_offset); - } - - /* Decipher if present */ - if (esp) { - odph_esptrl_t *esp_t; - DES_key_schedule ks1, ks2, ks3; - uint8_t iv[8]; - int encrypt_len = ipv4_data_len(ip) - hdr_len; - - memcpy(iv, esp->iv, sizeof(iv)); - - DES_set_key((DES_cblock *)&entry->esp.key.data[0], &ks1); - DES_set_key((DES_cblock *)&entry->esp.key.data[8], &ks2); - DES_set_key((DES_cblock *)&entry->esp.key.data[16], &ks3); - - DES_ede3_cbc_encrypt((uint8_t *)data, - (uint8_t *)data, - encrypt_len, - &ks1, - &ks2, - &ks3, - (DES_cblock *)iv, - 0); - - esp_t = (odph_esptrl_t *)(data + encrypt_len) - 1; - ip->proto = esp_t->next_header; - } - -clear_packet: - /* Verify IP/ICMP packet */ - if (entry && (entry->mode == IPSEC_SA_MODE_TUNNEL) && (ah || esp)) { - if (ODPH_IPV4 != ip->proto) - return FALSE; - odph_ipv4hdr_t *inner_ip = (odph_ipv4hdr_t *)data; - - icmp = (odph_icmphdr_t *)(inner_ip + 1); - data = (uint8_t *)icmp; - } else { - if (ODPH_IPPROTO_ICMPv4 != ip->proto) - return FALSE; - icmp = (odph_icmphdr_t *)data; - } - - /* Verify ICMP header */ - data += sizeof(*icmp); - if (ICMP_ECHO != icmp->type) - return FALSE; - if (0x1234 != odp_be_to_cpu_16(icmp->un.echo.id)) - return FALSE; - - /* Now check our packet */ - test = (stream_pkt_hdr_t *)data; - if (STREAM_MAGIC != odp_be_to_cpu_64(test->magic)) - return FALSE; - - return TRUE; -} - -int create_stream_db_inputs(void) -{ - int created = 0; - odp_pool_t pkt_pool; - stream_db_entry_t *stream = NULL; - - /* Lookup the packet pool */ - pkt_pool = odp_pool_lookup("packet_pool"); - if (pkt_pool == ODP_POOL_INVALID) { - EXAMPLE_ERR("Error: pkt_pool not found\n"); - exit(EXIT_FAILURE); - } - - /* For each stream create corresponding input packets */ - for (stream = stream_db->list; NULL != stream; stream = stream->next) { - int count; - uint8_t *dmac = query_loopback_db_mac(stream->input.loop); - odp_queue_t queue = query_loopback_db_inq(stream->input.loop); - - for (count = stream->count; count > 0; count--) { - odp_packet_t pkt; - - pkt = create_ipv4_packet(stream, dmac, pkt_pool); - if (ODP_PACKET_INVALID == pkt) { - printf("Packet buffers exhausted\n"); - break; - } - stream->created++; - if (odp_queue_enq(queue, odp_packet_to_event(pkt))) { - odp_packet_free(pkt); - printf("Queue enqueue failed\n"); - break; - } - - /* Count this stream when we create first packet */ - if (1 == stream->created) - created++; - } - } - - return created; -} - -odp_bool_t verify_stream_db_outputs(void) -{ - odp_bool_t done = TRUE; - stream_db_entry_t *stream = NULL; - const char *env; - - env = getenv("ODP_IPSEC_STREAM_VERIFY_MDEQ"); - /* For each stream look for output packets */ - for (stream = stream_db->list; NULL != stream; stream = stream->next) { - int idx; - int count; - odp_queue_t queue; - odp_event_t ev_tbl[LOOP_DEQ_COUNT]; - - queue = query_loopback_db_outq(stream->output.loop); - - if (ODP_QUEUE_INVALID == queue) - continue; - - for (;;) { - if (env) { - count = odp_queue_deq_multi(queue, - ev_tbl, - LOOP_DEQ_COUNT); - } else { - ev_tbl[0] = odp_queue_deq(queue); - count = (ev_tbl[0] != ODP_EVENT_INVALID) ? - 1 : 0; - } - if (!count) - break; - for (idx = 0; idx < count; idx++) { - odp_bool_t good; - odp_packet_t pkt; - - pkt = odp_packet_from_event(ev_tbl[idx]); - - good = verify_ipv4_packet(stream, pkt); - if (good) - stream->verified++; - odp_packet_free(pkt); - } - } - - printf("Stream %d %d\n", stream->created, stream->verified); - - if (stream->created != stream->verified) - done = FALSE; - } - return done; -} |