API Reference Manual  1.46.0
ipsec_api/odp_ipsec_cache.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2014-2018 Linaro Limited
3  */
4 
7 #include <stdlib.h>
8 #include <string.h>
9 
10 #include <odp_api.h>
11 #include <odp/helper/odph_api.h>
12 
13 #include <odp_ipsec_cache.h>
14 
16 ipsec_cache_t *ipsec_cache;
17 
18 void init_ipsec_cache(void)
19 {
20  odp_shm_t shm;
21  int i;
22 
23  shm = odp_shm_reserve("shm_ipsec_cache",
24  sizeof(ipsec_cache_t),
25  ODP_CACHE_LINE_SIZE,
26  0);
27 
28  if (shm == ODP_SHM_INVALID) {
29  ODPH_ERR("Error: shared mem reserve failed.\n");
30  exit(EXIT_FAILURE);
31  }
32 
33  ipsec_cache = odp_shm_addr(shm);
34 
35  if (ipsec_cache == NULL) {
36  ODPH_ERR("Error: shared mem alloc failed.\n");
37  exit(EXIT_FAILURE);
38  }
39  memset(ipsec_cache, 0, sizeof(*ipsec_cache));
40 
41  for (i = 0; i < MAX_DB; i++)
42  ipsec_cache->array[i].ipsec_sa = ODP_IPSEC_SA_INVALID;
43 }
44 
45 int create_ipsec_cache_entry(sa_db_entry_t *cipher_sa,
46  sa_db_entry_t *auth_sa,
47  tun_db_entry_t *tun,
48  odp_bool_t in,
49  odp_queue_t completionq)
50 {
52  ipsec_cache_entry_t *entry;
53  odp_ipsec_sa_t ipsec_sa;
54  uint32_t tun_src_ip, tun_dst_ip;
55  sa_mode_t mode = IPSEC_SA_MODE_TRANSPORT;
56 
57  /* Verify we have a good entry */
58  entry = &ipsec_cache->array[ipsec_cache->index];
59  if (MAX_DB <= ipsec_cache->index)
60  return -1;
61 
64  param.inbound.lookup_mode = in ? ODP_IPSEC_LOOKUP_SPI :
66  param.proto = cipher_sa ? ODP_IPSEC_ESP : ODP_IPSEC_AH;
67 
69 
70  param.dest_queue = completionq;
71 
72  /* Cipher */
73  if (cipher_sa) {
74  param.crypto.cipher_alg = cipher_sa->alg.u.cipher;
75  param.crypto.cipher_key.data = cipher_sa->key.data;
76  param.crypto.cipher_key.length = cipher_sa->key.length;
77  param.spi = cipher_sa->spi;
78  } else {
80  }
81 
82  /* Auth */
83  if (auth_sa) {
84  param.crypto.auth_alg = auth_sa->alg.u.auth;
85  param.crypto.auth_key.data = auth_sa->key.data;
86  param.crypto.auth_key.length = auth_sa->key.length;
87  param.spi = auth_sa->spi;
88  } else {
90  }
91 
92  if (ODP_IPSEC_MODE_TUNNEL == param.mode) {
93  tun_src_ip = odp_cpu_to_be_32(tun->tun_src_ip);
94  tun_dst_ip = odp_cpu_to_be_32(tun->tun_dst_ip);
95  param.outbound.tunnel.type = ODP_IPSEC_TUNNEL_IPV4;
96  param.outbound.tunnel.ipv4.src_addr = &tun_src_ip;
97  param.outbound.tunnel.ipv4.dst_addr = &tun_dst_ip;
98  }
99 
100  ipsec_sa = odp_ipsec_sa_create(&param);
101  if (ODP_IPSEC_SA_INVALID == ipsec_sa) {
102  ODPH_ERR("Error: SA creation failed\n");
103  exit(EXIT_FAILURE);
104  }
105 
106  /* Copy remainder */
107  if (cipher_sa) {
108  entry->src_ip = cipher_sa->src_ip;
109  entry->dst_ip = cipher_sa->dst_ip;
110  entry->esp.alg = cipher_sa->alg.u.cipher;
111  entry->esp.spi = cipher_sa->spi;
112  entry->esp.block_len = cipher_sa->block_len;
113  entry->esp.iv_len = cipher_sa->iv_len;
114  memcpy(&entry->esp.key, &cipher_sa->key, sizeof(ipsec_key_t));
115  }
116  if (auth_sa) {
117  entry->src_ip = auth_sa->src_ip;
118  entry->dst_ip = auth_sa->dst_ip;
119  entry->ah.alg = auth_sa->alg.u.auth;
120  entry->ah.spi = auth_sa->spi;
121  entry->ah.icv_len = auth_sa->icv_len;
122  memcpy(&entry->ah.key, &auth_sa->key, sizeof(ipsec_key_t));
123  }
124 
125  if (tun) {
126  entry->tun_src_ip = tun->tun_src_ip;
127  entry->tun_dst_ip = tun->tun_dst_ip;
128  mode = IPSEC_SA_MODE_TUNNEL;
129  }
130  entry->mode = mode;
131 
132  /* Add entry to the appropriate list */
133  ipsec_cache->index++;
134  if (in) {
135  entry->next = ipsec_cache->in_list;
136  ipsec_cache->in_list = entry;
137  } else {
138  entry->next = ipsec_cache->out_list;
139  ipsec_cache->out_list = entry;
140  }
141 
142  entry->ipsec_sa = ipsec_sa;
143 
144  return 0;
145 }
146 
147 ipsec_cache_entry_t *find_ipsec_cache_entry_in(uint32_t src_ip,
148  uint32_t dst_ip,
149  odph_ahhdr_t *ah,
150  odph_esphdr_t *esp)
151 {
152  ipsec_cache_entry_t *entry = ipsec_cache->in_list;
153 
154  /* Look for a hit */
155  for (; NULL != entry; entry = entry->next) {
156  if ((entry->src_ip != src_ip) || (entry->dst_ip != dst_ip))
157  if ((entry->tun_src_ip != src_ip) ||
158  (entry->tun_dst_ip != dst_ip))
159  continue;
160  if (ah &&
161  ((!entry->ah.alg) ||
162  (entry->ah.spi != odp_be_to_cpu_32(ah->spi))))
163  continue;
164  if (esp &&
165  ((!entry->esp.alg) ||
166  (entry->esp.spi != odp_be_to_cpu_32(esp->spi))))
167  continue;
168  break;
169  }
170 
171  return entry;
172 }
173 
174 ipsec_cache_entry_t *find_ipsec_cache_entry_out(uint32_t src_ip,
175  uint32_t dst_ip,
176  uint8_t proto ODP_UNUSED)
177 {
178  ipsec_cache_entry_t *entry = ipsec_cache->out_list;
179 
180  /* Look for a hit */
181  for (; NULL != entry; entry = entry->next) {
182  if ((entry->src_ip == src_ip) && (entry->dst_ip == dst_ip))
183  break;
184  }
185  return entry;
186 }
187 
188 int destroy_ipsec_cache(void)
189 {
190  ipsec_cache_entry_t *entry;
191  int i;
192  int ret = 0;
193 
194  for (i = 0; i < MAX_DB; i++) {
195  entry = &ipsec_cache->array[i];
196  if (entry->ipsec_sa != ODP_IPSEC_SA_INVALID) {
197  ret += odp_ipsec_sa_disable(entry->ipsec_sa);
198  ret += odp_ipsec_sa_destroy(entry->ipsec_sa);
199  }
200  }
201 
202  return ret;
203 }
#define ODP_UNUSED
Intentionally unused variables of functions.
Definition: spec/hints.h:54
odp_u32be_t odp_cpu_to_be_32(uint32_t cpu32)
Convert cpu native uint32_t to 32bit big endian.
uint32_t odp_be_to_cpu_32(odp_u32be_t be32)
Convert 32bit big endian to cpu native uint32_t.
@ ODP_CIPHER_ALG_NULL
No cipher algorithm specified.
@ ODP_AUTH_ALG_NULL
No authentication algorithm specified.
void odp_ipsec_sa_param_init(odp_ipsec_sa_param_t *param)
Initialize IPSEC SA parameters.
int odp_ipsec_sa_disable(odp_ipsec_sa_t sa)
Disable IPSEC SA.
#define ODP_IPSEC_SA_INVALID
Invalid IPSEC SA.
odp_ipsec_sa_t odp_ipsec_sa_create(const odp_ipsec_sa_param_t *param)
Create IPSEC SA.
int odp_ipsec_sa_destroy(odp_ipsec_sa_t sa)
Destroy IPSEC SA.
@ ODP_IPSEC_LOOKUP_SPI
Inbound SA lookup is enabled.
@ ODP_IPSEC_LOOKUP_DISABLED
Inbound SA lookup is disabled for the SA.
@ ODP_IPSEC_AH
AH protocol.
@ ODP_IPSEC_ESP
ESP protocol.
@ ODP_IPSEC_TUNNEL_IPV4
Outer header is IPv4.
@ ODP_IPSEC_MODE_TRANSPORT
IPSEC transport mode.
@ ODP_IPSEC_MODE_TUNNEL
IPSEC tunnel mode.
@ ODP_IPSEC_DIR_OUTBOUND
Outbound IPSEC SA.
@ ODP_IPSEC_DIR_INBOUND
Inbound IPSEC SA.
#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.
The OpenDataPlane API.
uint8_t * data
Key data.
uint32_t length
Key length in bytes.
odp_crypto_key_t auth_key
Authentication key.
odp_auth_alg_t auth_alg
Authentication algorithm.
odp_cipher_alg_t cipher_alg
Cipher algorithm.
odp_crypto_key_t cipher_key
Cipher key.
IPSEC Security Association (SA) parameters.
uint32_t spi
SPI value.
odp_ipsec_crypto_param_t crypto
Parameters for crypto and authentication algorithms.
odp_queue_t dest_queue
Destination queue for IPSEC events.
odp_ipsec_mode_t mode
IPSEC protocol mode: transport or tunnel.
struct odp_ipsec_sa_param_t::@47::@49 inbound
Inbound specific parameters.
odp_ipsec_dir_t dir
IPSEC SA direction: inbound or outbound.
struct odp_ipsec_sa_param_t::@47::@50 outbound
Outbound specific parameters.
odp_ipsec_protocol_t proto
IPSEC protocol: ESP or AH.