API Reference Manual  1.46.0
ipsec_crypto/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 
12 #include <odp/helper/ipsec.h>
13 
14 #include <odp_ipsec_cache.h>
15 
17 ipsec_cache_t *ipsec_cache;
18 
19 void init_ipsec_cache(void)
20 {
21  odp_shm_t shm;
22  int i;
23 
24  shm = odp_shm_reserve("shm_ipsec_cache",
25  sizeof(ipsec_cache_t),
26  ODP_CACHE_LINE_SIZE,
27  0);
28  if (shm == ODP_SHM_INVALID) {
29  ODPH_ERR("Error: shared mem alloc 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].state.session =
44 }
45 
46 int create_ipsec_cache_entry(sa_db_entry_t *cipher_sa,
47  sa_db_entry_t *auth_sa,
48  tun_db_entry_t *tun,
49  crypto_api_mode_e api_mode,
50  odp_bool_t in,
51  odp_queue_t completionq,
52  odp_pool_t out_pool)
53 {
55  ipsec_cache_entry_t *entry;
56  odp_crypto_ses_create_err_t ses_create_rc;
57  odp_crypto_session_t session;
58  sa_mode_t mode = IPSEC_SA_MODE_TRANSPORT;
59 
60  /* Verify we have a good entry */
61  entry = &ipsec_cache->array[ipsec_cache->index];
62  if (MAX_DB <= ipsec_cache->index)
63  return -1;
64 
65  /* Verify SA mode match in case of cipher&auth */
66  if (cipher_sa && auth_sa &&
67  (cipher_sa->mode != auth_sa->mode))
68  return -1;
69 
71 
72  /* Setup parameters and call crypto library to create session */
75  params.auth_cipher_text = TRUE;
76  if (CRYPTO_API_SYNC == api_mode) {
77  params.op_mode = ODP_CRYPTO_SYNC;
80  entry->async = FALSE;
81  } else {
82  params.op_mode = ODP_CRYPTO_ASYNC;
83  params.compl_queue = completionq;
84  params.output_pool = out_pool;
85  entry->async = TRUE;
86  }
87 
88  entry->sa_flags = 0;
89 
90  /* Cipher */
91  if (cipher_sa) {
92  params.cipher_alg = cipher_sa->alg.u.cipher;
93  params.cipher_key.data = cipher_sa->key.data;
94  params.cipher_key.length = cipher_sa->key.length;
95  params.cipher_iv_len = cipher_sa->iv_len;
96  mode = cipher_sa->mode;
97  if (cipher_sa->flags & BIT_MODE_CIPHER)
98  entry->sa_flags |= BIT_MODE_CIPHER;
99  } else {
101  params.cipher_iv_len = 0;
102  }
103 
104  /* Auth */
105  if (auth_sa) {
106  params.auth_alg = auth_sa->alg.u.auth;
107  params.auth_key.data = auth_sa->key.data;
108  params.auth_key.length = auth_sa->key.length;
109  params.auth_digest_len = auth_sa->icv_len;
110  mode = auth_sa->mode;
111  params.hash_result_in_auth_range = true;
112  if (auth_sa->flags & BIT_MODE_AUTH)
113  entry->sa_flags |= BIT_MODE_AUTH;
114  } else {
115  params.auth_alg = ODP_AUTH_ALG_NULL;
116  }
117 
118  /* Synchronous session create for now */
119  if (odp_crypto_session_create(&params, &session, &ses_create_rc))
120  return -1;
121  if (ODP_CRYPTO_SES_ERR_NONE != ses_create_rc)
122  return -1;
123 
124  /* Copy remainder */
125  if (cipher_sa) {
126  entry->src_ip = cipher_sa->src_ip;
127  entry->dst_ip = cipher_sa->dst_ip;
128  entry->esp.alg = cipher_sa->alg.u.cipher;
129  entry->esp.spi = cipher_sa->spi;
130  entry->esp.block_len = cipher_sa->block_len;
131  entry->esp.iv_len = cipher_sa->iv_len;
132  memcpy(&entry->esp.key, &cipher_sa->key, sizeof(ipsec_key_t));
133  }
134  if (auth_sa) {
135  entry->src_ip = auth_sa->src_ip;
136  entry->dst_ip = auth_sa->dst_ip;
137  entry->ah.alg = auth_sa->alg.u.auth;
138  entry->ah.spi = auth_sa->spi;
139  entry->ah.icv_len = auth_sa->icv_len;
140  memcpy(&entry->ah.key, &auth_sa->key, sizeof(ipsec_key_t));
141  }
142 
143  if (tun) {
144  entry->tun_src_ip = tun->tun_src_ip;
145  entry->tun_dst_ip = tun->tun_dst_ip;
146  mode = IPSEC_SA_MODE_TUNNEL;
147 
148  int ret;
149 
150  if (!in) {
151  /* init tun hdr id */
152  ret = odp_random_data((uint8_t *)
153  &entry->state.tun_hdr_id,
154  sizeof(entry->state.tun_hdr_id),
155  1);
156  if (ret != sizeof(entry->state.tun_hdr_id))
157  return -1;
158  }
159  }
160  entry->mode = mode;
161 
162  /* Initialize state */
163  entry->state.esp_seq = 0;
164  entry->state.ah_seq = 0;
165  entry->state.session = session;
166 
167  /* Add entry to the appropriate list */
168  ipsec_cache->index++;
169  if (in) {
170  entry->next = ipsec_cache->in_list;
171  ipsec_cache->in_list = entry;
172  } else {
173  entry->next = ipsec_cache->out_list;
174  ipsec_cache->out_list = entry;
175  }
176 
177  return 0;
178 }
179 
180 ipsec_cache_entry_t *find_ipsec_cache_entry_in(uint32_t src_ip,
181  uint32_t dst_ip,
182  odph_ahhdr_t *ah,
183  odph_esphdr_t *esp)
184 {
185  ipsec_cache_entry_t *entry = ipsec_cache->in_list;
186 
187  /* Look for a hit */
188  for (; NULL != entry; entry = entry->next) {
189  if ((entry->src_ip != src_ip) || (entry->dst_ip != dst_ip))
190  if ((entry->tun_src_ip != src_ip) ||
191  (entry->tun_dst_ip != dst_ip))
192  continue;
193  if (ah &&
194  ((!entry->ah.alg) ||
195  (entry->ah.spi != odp_be_to_cpu_32(ah->spi))))
196  continue;
197  if (esp &&
198  ((!entry->esp.alg) ||
199  (entry->esp.spi != odp_be_to_cpu_32(esp->spi))))
200  continue;
201  break;
202  }
203 
204  return entry;
205 }
206 
207 ipsec_cache_entry_t *find_ipsec_cache_entry_out(uint32_t src_ip,
208  uint32_t dst_ip,
209  uint8_t proto ODP_UNUSED)
210 {
211  ipsec_cache_entry_t *entry = ipsec_cache->out_list;
212 
213  /* Look for a hit */
214  for (; NULL != entry; entry = entry->next) {
215  if ((entry->src_ip == src_ip) && (entry->dst_ip == dst_ip))
216  break;
217  }
218  return entry;
219 }
220 
221 int destroy_ipsec_cache(void)
222 {
223  ipsec_cache_entry_t *entry;
224  int i;
225  int ret = 0;
226 
227  for (i = 0; i < MAX_DB; i++) {
228  entry = &ipsec_cache->array[i];
229  if (entry->state.session != ODP_CRYPTO_SESSION_INVALID)
230  ret += odp_crypto_session_destroy(entry->state.session);
231  }
232 
233  return ret;
234 }
#define ODP_UNUSED
Intentionally unused variables of functions.
Definition: spec/hints.h:54
uint32_t odp_be_to_cpu_32(odp_u32be_t be32)
Convert 32bit big endian to cpu native uint32_t.
void odp_crypto_session_param_init(odp_crypto_session_param_t *param)
Initialize crypto session parameters.
uint64_t odp_crypto_session_t
Crypto API opaque session handle.
int odp_crypto_session_create(const odp_crypto_session_param_t *param, odp_crypto_session_t *session, odp_crypto_ses_create_err_t *status)
Crypto session creation.
#define ODP_CRYPTO_SESSION_INVALID
Invalid session handle.
int odp_crypto_session_destroy(odp_crypto_session_t session)
Crypto session destroy.
odp_crypto_ses_create_err_t
Crypto API session creation return code.
@ ODP_CIPHER_ALG_NULL
No cipher algorithm specified.
@ ODP_CRYPTO_OP_TYPE_BASIC
Input packet data and metadata are copied to the output packet and then processed.
@ ODP_AUTH_ALG_NULL
No authentication algorithm specified.
@ ODP_CRYPTO_SES_ERR_NONE
Session created.
@ ODP_CRYPTO_OP_ENCODE
Encrypt and/or compute authentication ICV.
@ ODP_CRYPTO_OP_DECODE
Decrypt and/or verify authentication ICV.
@ ODP_CRYPTO_SYNC
Synchronous, return results immediately.
@ ODP_CRYPTO_ASYNC
Asynchronous, return results via posted event.
#define ODP_POOL_INVALID
Invalid pool.
#define ODP_QUEUE_INVALID
Invalid queue.
int32_t odp_random_data(uint8_t *buf, uint32_t len, odp_random_kind_t kind)
Generate random byte data.
#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.
Crypto API session creation parameters.
odp_bool_t auth_cipher_text
Authenticate cipher vs.
odp_crypto_key_t auth_key
Authentication key.
odp_crypto_op_type_t op_type
Crypto operation type.
odp_crypto_key_t cipher_key
Cipher key.
odp_queue_t compl_queue
Async mode completion event queue.
odp_pool_t output_pool
Output pool.
uint32_t cipher_iv_len
Cipher IV length.
odp_bool_t hash_result_in_auth_range
Hash result location may overlap authentication range.
uint32_t auth_digest_len
Authentication digest length in bytes.
odp_auth_alg_t auth_alg
Authentication algorithm.
odp_crypto_op_mode_t op_mode
Operation mode when using packet interface: sync or async.
odp_cipher_alg_t cipher_alg
Cipher algorithm.
odp_crypto_op_t op
Encode vs.