Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : :
5 : : #include <eal_export.h>
6 : : #include <rte_udp.h>
7 : :
8 : : #include "roc_api.h"
9 : :
10 : : #include "cnxk_security.h"
11 : :
12 : : static int
13 : 0 : ot_ipsec_sa_common_param_fill(union roc_ot_ipsec_sa_word2 *w2, uint8_t *cipher_key,
14 : : uint8_t *salt_key, uint8_t *hmac_opad_ipad,
15 : : struct rte_security_ipsec_xform *ipsec_xfrm,
16 : : struct rte_crypto_sym_xform *crypto_xfrm)
17 : : {
18 : : struct rte_crypto_sym_xform *auth_xfrm, *cipher_xfrm;
19 : : const uint8_t *key = NULL;
20 : : uint8_t ccm_flag = 0;
21 : : uint32_t *tmp_salt;
22 : : uint64_t *tmp_key;
23 : : int i, length = 0;
24 : :
25 : : /* Set direction */
26 [ # # ]: 0 : if (ipsec_xfrm->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
27 : 0 : w2->s.dir = ROC_IE_SA_DIR_OUTBOUND;
28 : : else
29 : 0 : w2->s.dir = ROC_IE_SA_DIR_INBOUND;
30 : :
31 [ # # ]: 0 : if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
32 : : auth_xfrm = crypto_xfrm;
33 : 0 : cipher_xfrm = crypto_xfrm->next;
34 : : } else {
35 : : cipher_xfrm = crypto_xfrm;
36 : 0 : auth_xfrm = crypto_xfrm->next;
37 : : }
38 : :
39 : : /* Set protocol - ESP vs AH */
40 [ # # # ]: 0 : switch (ipsec_xfrm->proto) {
41 : 0 : case RTE_SECURITY_IPSEC_SA_PROTO_ESP:
42 : 0 : w2->s.protocol = ROC_IE_SA_PROTOCOL_ESP;
43 : 0 : break;
44 : 0 : case RTE_SECURITY_IPSEC_SA_PROTO_AH:
45 : 0 : w2->s.protocol = ROC_IE_SA_PROTOCOL_AH;
46 : 0 : break;
47 : : default:
48 : : return -EINVAL;
49 : : }
50 : :
51 : : /* Set mode - transport vs tunnel */
52 [ # # # ]: 0 : switch (ipsec_xfrm->mode) {
53 : 0 : case RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT:
54 : 0 : w2->s.mode = ROC_IE_SA_MODE_TRANSPORT;
55 : 0 : break;
56 : 0 : case RTE_SECURITY_IPSEC_SA_MODE_TUNNEL:
57 : 0 : w2->s.mode = ROC_IE_SA_MODE_TUNNEL;
58 : 0 : break;
59 : : default:
60 : : return -EINVAL;
61 : : }
62 : :
63 : : /* Set encryption algorithm */
64 [ # # ]: 0 : if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
65 : 0 : key = crypto_xfrm->aead.key.data;
66 : 0 : length = crypto_xfrm->aead.key.length;
67 : :
68 [ # # # ]: 0 : switch (crypto_xfrm->aead.algo) {
69 : 0 : case RTE_CRYPTO_AEAD_AES_GCM:
70 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_AES_GCM;
71 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_NULL;
72 [ # # ]: 0 : memcpy(salt_key, &ipsec_xfrm->salt, 4);
73 : : tmp_salt = (uint32_t *)salt_key;
74 [ # # ]: 0 : *tmp_salt = rte_be_to_cpu_32(*tmp_salt);
75 : 0 : break;
76 : 0 : case RTE_CRYPTO_AEAD_AES_CCM:
77 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_AES_CCM;
78 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_NULL;
79 : : ccm_flag = 0x07 & ~ROC_CPT_AES_CCM_CTR_LEN;
80 : 0 : *salt_key = ccm_flag;
81 [ # # ]: 0 : memcpy(PLT_PTR_ADD(salt_key, 1), &ipsec_xfrm->salt, 3);
82 : : tmp_salt = (uint32_t *)salt_key;
83 [ # # ]: 0 : *tmp_salt = rte_be_to_cpu_32(*tmp_salt);
84 : 0 : break;
85 : : default:
86 : : return -ENOTSUP;
87 : : }
88 : : } else {
89 [ # # ]: 0 : if (cipher_xfrm != NULL) {
90 [ # # # # : 0 : switch (cipher_xfrm->cipher.algo) {
# ]
91 : 0 : case RTE_CRYPTO_CIPHER_NULL:
92 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_NULL;
93 : 0 : break;
94 : 0 : case RTE_CRYPTO_CIPHER_AES_CBC:
95 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_AES_CBC;
96 : 0 : break;
97 : 0 : case RTE_CRYPTO_CIPHER_AES_CTR:
98 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_AES_CTR;
99 [ # # ]: 0 : memcpy(salt_key, &ipsec_xfrm->salt, 4);
100 : : tmp_salt = (uint32_t *)salt_key;
101 [ # # ]: 0 : *tmp_salt = rte_be_to_cpu_32(*tmp_salt);
102 : 0 : break;
103 : 0 : case RTE_CRYPTO_CIPHER_3DES_CBC:
104 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_3DES_CBC;
105 : 0 : break;
106 : : default:
107 : : return -ENOTSUP;
108 : : }
109 : :
110 : 0 : key = cipher_xfrm->cipher.key.data;
111 : 0 : length = cipher_xfrm->cipher.key.length;
112 : : }
113 : :
114 [ # # # # : 0 : switch (auth_xfrm->auth.algo) {
# # # # ]
115 : 0 : case RTE_CRYPTO_AUTH_NULL:
116 [ # # # # ]: 0 : if (w2->s.dir == ROC_IE_SA_DIR_INBOUND && ipsec_xfrm->replay_win_sz) {
117 : 0 : plt_err("anti-replay can't be supported with integrity service disabled");
118 : 0 : return -EINVAL;
119 : : }
120 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_NULL;
121 : 0 : break;
122 : 0 : case RTE_CRYPTO_AUTH_SHA1_HMAC:
123 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_SHA1;
124 : 0 : break;
125 : 0 : case RTE_CRYPTO_AUTH_SHA256_HMAC:
126 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_SHA2_256;
127 : 0 : break;
128 : 0 : case RTE_CRYPTO_AUTH_SHA384_HMAC:
129 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_SHA2_384;
130 : 0 : break;
131 : 0 : case RTE_CRYPTO_AUTH_SHA512_HMAC:
132 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_SHA2_512;
133 : 0 : break;
134 : 0 : case RTE_CRYPTO_AUTH_AES_XCBC_MAC:
135 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_AES_XCBC_128;
136 : 0 : break;
137 : 0 : case RTE_CRYPTO_AUTH_AES_GMAC:
138 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_AES_GMAC;
139 : 0 : key = auth_xfrm->auth.key.data;
140 : 0 : length = auth_xfrm->auth.key.length;
141 [ # # ]: 0 : memcpy(salt_key, &ipsec_xfrm->salt, 4);
142 : : tmp_salt = (uint32_t *)salt_key;
143 [ # # ]: 0 : *tmp_salt = rte_be_to_cpu_32(*tmp_salt);
144 : 0 : break;
145 : : default:
146 : : return -ENOTSUP;
147 : : }
148 : :
149 [ # # ]: 0 : if (auth_xfrm->auth.algo == RTE_CRYPTO_AUTH_AES_XCBC_MAC) {
150 : 0 : const uint8_t *auth_key = auth_xfrm->auth.key.data;
151 : 0 : roc_aes_xcbc_key_derive(auth_key, hmac_opad_ipad);
152 : : } else {
153 : 0 : roc_se_hmac_opad_ipad_gen(w2->s.auth_type, auth_xfrm->auth.key.data,
154 : 0 : auth_xfrm->auth.key.length, &hmac_opad_ipad[0],
155 : : ROC_SE_IPSEC);
156 : : }
157 : :
158 : : tmp_key = (uint64_t *)hmac_opad_ipad;
159 : : for (i = 0;
160 [ # # ]: 0 : i < (int)(ROC_CTX_MAX_OPAD_IPAD_LEN / sizeof(uint64_t));
161 : 0 : i++)
162 [ # # ]: 0 : tmp_key[i] = rte_be_to_cpu_64(tmp_key[i]);
163 : :
164 : : }
165 : :
166 : : /* Set encapsulation type */
167 [ # # ]: 0 : if (ipsec_xfrm->options.udp_encap)
168 : 0 : w2->s.encap_type = ROC_IE_OT_SA_ENCAP_UDP;
169 : :
170 : 0 : w2->s.spi = ipsec_xfrm->spi;
171 : :
172 [ # # ]: 0 : if (key != NULL && length != 0) {
173 : : /* Validate key length and set AES key len before copy to avoid overflow */
174 : 0 : if (w2->s.enc_type == ROC_IE_SA_ENC_AES_CBC ||
175 : : w2->s.enc_type == ROC_IE_SA_ENC_AES_CTR ||
176 [ # # ]: 0 : w2->s.enc_type == ROC_IE_SA_ENC_AES_GCM ||
177 : 0 : w2->s.enc_type == ROC_IE_SA_ENC_AES_CCM ||
178 [ # # ]: 0 : w2->s.auth_type == ROC_IE_SA_AUTH_AES_GMAC) {
179 [ # # # # ]: 0 : switch (length) {
180 : 0 : case ROC_CPT_AES128_KEY_LEN:
181 : 0 : w2->s.aes_key_len = ROC_IE_SA_AES_KEY_LEN_128;
182 : 0 : break;
183 : 0 : case ROC_CPT_AES192_KEY_LEN:
184 : 0 : w2->s.aes_key_len = ROC_IE_SA_AES_KEY_LEN_192;
185 : 0 : break;
186 : 0 : case ROC_CPT_AES256_KEY_LEN:
187 : 0 : w2->s.aes_key_len = ROC_IE_SA_AES_KEY_LEN_256;
188 : 0 : break;
189 : 0 : default:
190 : 0 : plt_err("Invalid AES key length");
191 : 0 : return -EINVAL;
192 : : }
193 : : }
194 [ # # # # ]: 0 : if (w2->s.enc_type == ROC_IE_SA_ENC_DES_CBC && length != ROC_CPT_DES_KEY_LEN) {
195 : 0 : plt_err("Invalid DES key length");
196 : 0 : return -EINVAL;
197 : : }
198 [ # # # # ]: 0 : if (w2->s.enc_type == ROC_IE_SA_ENC_3DES_CBC && length != ROC_CPT_DES3_KEY_LEN) {
199 : 0 : plt_err("Invalid 3DES key length");
200 : 0 : return -EINVAL;
201 : : }
202 : : /* Copy encryption key */
203 : 0 : memcpy(cipher_key, key, length);
204 : : tmp_key = (uint64_t *)cipher_key;
205 [ # # ]: 0 : for (i = 0; i < (int)(ROC_CTX_MAX_CKEY_LEN / sizeof(uint64_t)); i++)
206 [ # # ]: 0 : tmp_key[i] = rte_be_to_cpu_64(tmp_key[i]);
207 : : }
208 : :
209 [ # # # # ]: 0 : if (ipsec_xfrm->life.packets_soft_limit != 0 || ipsec_xfrm->life.packets_hard_limit != 0) {
210 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_soft_limit != 0 ||
211 [ # # ]: 0 : ipsec_xfrm->life.bytes_hard_limit != 0) {
212 : 0 : plt_err("Expiry tracking with both packets & bytes is not supported");
213 : 0 : return -EINVAL;
214 : : }
215 : 0 : w2->s.life_unit = ROC_IE_OT_SA_LIFE_UNIT_PKTS;
216 : : }
217 : :
218 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_soft_limit != 0 ||
219 [ # # ]: 0 : ipsec_xfrm->life.bytes_hard_limit != 0) {
220 [ # # ]: 0 : if (ipsec_xfrm->life.packets_soft_limit != 0 ||
221 [ # # ]: 0 : ipsec_xfrm->life.packets_hard_limit != 0) {
222 : 0 : plt_err("Expiry tracking with both packets & bytes is not supported");
223 : 0 : return -EINVAL;
224 : : }
225 : 0 : w2->s.life_unit = ROC_IE_OT_SA_LIFE_UNIT_OCTETS;
226 : : }
227 : :
228 : : return 0;
229 : : }
230 : :
231 : : static size_t
232 : : ot_ipsec_inb_ctx_size(struct roc_ot_ipsec_inb_sa *sa)
233 : : {
234 : : size_t size;
235 : :
236 : : /* Variable based on Anti-replay Window */
237 : : size = offsetof(struct roc_ot_ipsec_inb_sa, ctx) +
238 : : offsetof(struct roc_ot_ipsec_inb_ctx_update_reg, ar_winbits);
239 : :
240 : 0 : if (sa->w0.s.ar_win)
241 : 0 : size += (1 << (sa->w0.s.ar_win - 1)) * sizeof(uint64_t);
242 : :
243 : : return size;
244 : : }
245 : :
246 : : static void
247 : 0 : ot_ipsec_update_ipv6_addr_endianness(uint64_t *addr)
248 : : {
249 [ # # ]: 0 : *addr = rte_be_to_cpu_64(*addr);
250 : : addr++;
251 [ # # ]: 0 : *addr = rte_be_to_cpu_64(*addr);
252 : 0 : }
253 : :
254 : : static int
255 : 0 : ot_ipsec_inb_tunnel_hdr_fill(struct roc_ot_ipsec_inb_sa *sa,
256 : : struct rte_security_ipsec_xform *ipsec_xfrm)
257 : : {
258 : : struct rte_security_ipsec_tunnel_param *tunnel;
259 : :
260 [ # # ]: 0 : if (ipsec_xfrm->mode != RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
261 : : return 0;
262 : :
263 [ # # ]: 0 : if (ipsec_xfrm->options.tunnel_hdr_verify == 0)
264 : : return 0;
265 : :
266 : : tunnel = &ipsec_xfrm->tunnel;
267 : :
268 [ # # # ]: 0 : switch (tunnel->type) {
269 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_IPV4:
270 : 0 : sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_4;
271 [ # # ]: 0 : memcpy(&sa->outer_hdr.ipv4.src_addr, &tunnel->ipv4.src_ip,
272 : : sizeof(struct in_addr));
273 : 0 : memcpy(&sa->outer_hdr.ipv4.dst_addr, &tunnel->ipv4.dst_ip,
274 : : sizeof(struct in_addr));
275 : :
276 : : /* IP Source and Dest are in LE/CPU endian */
277 : 0 : sa->outer_hdr.ipv4.src_addr =
278 [ # # ]: 0 : rte_be_to_cpu_32(sa->outer_hdr.ipv4.src_addr);
279 : 0 : sa->outer_hdr.ipv4.dst_addr =
280 [ # # ]: 0 : rte_be_to_cpu_32(sa->outer_hdr.ipv4.dst_addr);
281 : :
282 : 0 : break;
283 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_IPV6:
284 : 0 : sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_6;
285 : 0 : memcpy(&sa->outer_hdr.ipv6.src_addr, &tunnel->ipv6.src_addr,
286 : : sizeof(sa->outer_hdr.ipv6.src_addr));
287 : 0 : memcpy(&sa->outer_hdr.ipv6.dst_addr, &tunnel->ipv6.dst_addr,
288 : : sizeof(sa->outer_hdr.ipv6.dst_addr));
289 : :
290 : : /* IP Source and Dest are in LE/CPU endian */
291 : 0 : ot_ipsec_update_ipv6_addr_endianness((uint64_t *)&sa->outer_hdr.ipv6.src_addr);
292 : 0 : ot_ipsec_update_ipv6_addr_endianness((uint64_t *)&sa->outer_hdr.ipv6.dst_addr);
293 : :
294 : 0 : break;
295 : : default:
296 : : return -EINVAL;
297 : : }
298 : :
299 [ # # # ]: 0 : switch (ipsec_xfrm->options.tunnel_hdr_verify) {
300 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_VERIFY_DST_ADDR:
301 : 0 : sa->w2.s.ip_hdr_verify = ROC_IE_OT_SA_IP_HDR_VERIFY_DST_ADDR;
302 : 0 : break;
303 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_VERIFY_SRC_DST_ADDR:
304 : 0 : sa->w2.s.ip_hdr_verify =
305 : : ROC_IE_OT_SA_IP_HDR_VERIFY_SRC_DST_ADDR;
306 : 0 : break;
307 : : default:
308 : : return -ENOTSUP;
309 : : }
310 : :
311 : : return 0;
312 : : }
313 : :
314 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ot_ipsec_inb_sa_fill)
315 : : int
316 : 0 : cnxk_ot_ipsec_inb_sa_fill(struct roc_ot_ipsec_inb_sa *sa,
317 : : struct rte_security_ipsec_xform *ipsec_xfrm,
318 : : struct rte_crypto_sym_xform *crypto_xfrm, uint8_t ctx_ilen)
319 : : {
320 : : uint16_t sport = 4500, dport = 4500;
321 : : union roc_ot_ipsec_sa_word2 w2;
322 : : uint32_t replay_win_sz;
323 : : size_t offset;
324 : : int rc;
325 : :
326 : : /* Initialize the SA */
327 : 0 : roc_ot_ipsec_inb_sa_init(sa);
328 : :
329 : 0 : w2.u64 = sa->w2.u64;
330 : 0 : rc = ot_ipsec_sa_common_param_fill(&w2, sa->cipher_key, sa->w8.s.salt,
331 : 0 : sa->hmac_opad_ipad, ipsec_xfrm,
332 : : crypto_xfrm);
333 [ # # ]: 0 : if (rc)
334 : : return rc;
335 : :
336 : : /* Updata common word2 data */
337 : 0 : sa->w2.u64 = w2.u64;
338 : :
339 : : /* Only support power-of-two window sizes supported */
340 : 0 : replay_win_sz = ipsec_xfrm->replay_win_sz;
341 [ # # ]: 0 : if (replay_win_sz) {
342 [ # # ]: 0 : if (!rte_is_power_of_2(replay_win_sz) ||
343 : : replay_win_sz > ROC_AR_WIN_SIZE_MAX)
344 : : return -ENOTSUP;
345 : :
346 : 0 : sa->w0.s.ar_win = rte_log2_u32(replay_win_sz) - 5;
347 : : }
348 : :
349 : 0 : rc = ot_ipsec_inb_tunnel_hdr_fill(sa, ipsec_xfrm);
350 [ # # ]: 0 : if (rc)
351 : : return rc;
352 : :
353 : : /* Default options for pkt_out and pkt_fmt are with
354 : : * second pass meta and no defrag.
355 : : */
356 : 0 : sa->w0.s.pkt_format = ROC_IE_OT_SA_PKT_FMT_META;
357 : 0 : sa->w0.s.pkt_output = ROC_IE_OT_SA_PKT_OUTPUT_NO_FRAG;
358 : 0 : sa->w0.s.pkind = ROC_IE_OT_CPT_PKIND;
359 : :
360 [ # # ]: 0 : if (ipsec_xfrm->options.ip_reassembly_en)
361 : 0 : sa->w0.s.pkt_output = ROC_IE_OT_SA_PKT_OUTPUT_HW_BASED_DEFRAG;
362 : :
363 : : /* ESN */
364 : 0 : sa->w2.s.esn_en = !!ipsec_xfrm->options.esn;
365 [ # # ]: 0 : if (ipsec_xfrm->options.udp_encap) {
366 [ # # ]: 0 : if (ipsec_xfrm->udp.sport)
367 : : sport = ipsec_xfrm->udp.sport;
368 : :
369 [ # # ]: 0 : if (ipsec_xfrm->udp.dport)
370 : : dport = ipsec_xfrm->udp.dport;
371 : :
372 : 0 : sa->w10.s.udp_src_port = sport;
373 : 0 : sa->w10.s.udp_dst_port = dport;
374 : : }
375 : :
376 [ # # ]: 0 : if (ipsec_xfrm->options.udp_ports_verify)
377 : 0 : sa->w2.s.udp_ports_verify = 1;
378 : :
379 : : offset = offsetof(struct roc_ot_ipsec_inb_sa, ctx);
380 : : /* Word offset for HW managed SA field */
381 : 0 : sa->w0.s.hw_ctx_off = offset / 8;
382 : : /* Context push size for inbound spans up to hw_ctx including
383 : : * ar_base field, in 8b units
384 : : */
385 [ # # ]: 0 : sa->w0.s.ctx_push_size = sa->w0.s.hw_ctx_off + 1;
386 : : /* Entire context size in 128B units */
387 : 0 : sa->w0.s.ctx_size =
388 : 0 : (PLT_ALIGN_CEIL(ot_ipsec_inb_ctx_size(sa), ROC_CTX_UNIT_128B) /
389 : 0 : ROC_CTX_UNIT_128B) -
390 : : 1;
391 : :
392 [ # # ]: 0 : if (sa->w0.s.ctx_size < ctx_ilen)
393 : 0 : sa->w0.s.ctx_size = ctx_ilen;
394 : :
395 : : /**
396 : : * CPT MC triggers expiry when counter value changes from 2 to 1. To
397 : : * mitigate this behaviour add 1 to the life counter values provided.
398 : : */
399 : :
400 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_soft_limit) {
401 : 0 : sa->ctx.soft_life = ipsec_xfrm->life.bytes_soft_limit + 1;
402 : 0 : sa->w0.s.soft_life_dec = 1;
403 : : }
404 : :
405 [ # # ]: 0 : if (ipsec_xfrm->life.packets_soft_limit) {
406 : 0 : sa->ctx.soft_life = ipsec_xfrm->life.packets_soft_limit + 1;
407 : 0 : sa->w0.s.soft_life_dec = 1;
408 : : }
409 : :
410 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_hard_limit) {
411 : 0 : sa->ctx.hard_life = ipsec_xfrm->life.bytes_hard_limit + 1;
412 : 0 : sa->w0.s.hard_life_dec = 1;
413 : : }
414 : :
415 [ # # ]: 0 : if (ipsec_xfrm->life.packets_hard_limit) {
416 : 0 : sa->ctx.hard_life = ipsec_xfrm->life.packets_hard_limit + 1;
417 : 0 : sa->w0.s.hard_life_dec = 1;
418 : : }
419 : :
420 : : rte_wmb();
421 : :
422 : : /* Enable SA */
423 : 0 : sa->w2.s.valid = 1;
424 : 0 : return 0;
425 : : }
426 : :
427 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ot_ipsec_outb_sa_fill)
428 : : int
429 : 0 : cnxk_ot_ipsec_outb_sa_fill(struct roc_ot_ipsec_outb_sa *sa,
430 : : struct rte_security_ipsec_xform *ipsec_xfrm,
431 : : struct rte_crypto_sym_xform *crypto_xfrm, uint8_t ctx_ilen)
432 : : {
433 : : struct rte_security_ipsec_tunnel_param *tunnel = &ipsec_xfrm->tunnel;
434 : : uint16_t sport = 4500, dport = 4500;
435 : : union roc_ot_ipsec_sa_word2 w2;
436 : : size_t offset;
437 : : int rc;
438 : :
439 : : /* Initialize the SA */
440 : 0 : roc_ot_ipsec_outb_sa_init(sa);
441 : :
442 : 0 : w2.u64 = 0;
443 : 0 : rc = ot_ipsec_sa_common_param_fill(&w2, sa->cipher_key, sa->iv.s.salt,
444 : 0 : sa->hmac_opad_ipad, ipsec_xfrm,
445 : : crypto_xfrm);
446 [ # # ]: 0 : if (rc)
447 : : return rc;
448 : :
449 : : /* Update common word2 data */
450 : 0 : sa->w2.u64 = w2.u64;
451 : :
452 [ # # ]: 0 : if (ipsec_xfrm->mode != RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
453 : 0 : goto skip_tunnel_info;
454 : :
455 : : /* Tunnel header info */
456 [ # # # ]: 0 : switch (tunnel->type) {
457 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_IPV4:
458 : 0 : sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_4;
459 [ # # ]: 0 : memcpy(&sa->outer_hdr.ipv4.src_addr, &tunnel->ipv4.src_ip,
460 : : sizeof(struct in_addr));
461 : 0 : memcpy(&sa->outer_hdr.ipv4.dst_addr, &tunnel->ipv4.dst_ip,
462 : : sizeof(struct in_addr));
463 : :
464 : : /* IP Source and Dest seems to be in LE/CPU endian */
465 : 0 : sa->outer_hdr.ipv4.src_addr =
466 [ # # ]: 0 : rte_be_to_cpu_32(sa->outer_hdr.ipv4.src_addr);
467 : 0 : sa->outer_hdr.ipv4.dst_addr =
468 [ # # ]: 0 : rte_be_to_cpu_32(sa->outer_hdr.ipv4.dst_addr);
469 : :
470 : : /* Outer header DF bit source */
471 [ # # ]: 0 : if (!ipsec_xfrm->options.copy_df) {
472 : 0 : sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
473 : : ROC_IE_OT_SA_COPY_FROM_SA;
474 : 0 : sa->w10.s.ipv4_df_or_ipv6_flw_lbl = tunnel->ipv4.df;
475 : : } else {
476 : 0 : sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
477 : : ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
478 : : }
479 : :
480 : : /* Outer header DSCP source */
481 [ # # ]: 0 : if (!ipsec_xfrm->options.copy_dscp) {
482 : 0 : sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_SA;
483 : 0 : sa->w10.s.dscp = tunnel->ipv4.dscp;
484 : : } else {
485 : 0 : sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
486 : : }
487 : : break;
488 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_IPV6:
489 : 0 : sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_6;
490 : 0 : memcpy(&sa->outer_hdr.ipv6.src_addr, &tunnel->ipv6.src_addr,
491 : : sizeof(sa->outer_hdr.ipv6.src_addr));
492 : 0 : memcpy(&sa->outer_hdr.ipv6.dst_addr, &tunnel->ipv6.dst_addr,
493 : : sizeof(sa->outer_hdr.ipv6.dst_addr));
494 : :
495 : : /* IP Source and Dest are in LE/CPU endian */
496 : 0 : ot_ipsec_update_ipv6_addr_endianness((uint64_t *)&sa->outer_hdr.ipv6.src_addr);
497 : 0 : ot_ipsec_update_ipv6_addr_endianness((uint64_t *)&sa->outer_hdr.ipv6.dst_addr);
498 : :
499 : : /* Outer header flow label source */
500 [ # # ]: 0 : if (!ipsec_xfrm->options.copy_flabel) {
501 : 0 : sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
502 : : ROC_IE_OT_SA_COPY_FROM_SA;
503 : :
504 : 0 : sa->w10.s.ipv4_df_or_ipv6_flw_lbl = tunnel->ipv6.flabel;
505 : : } else {
506 : 0 : sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
507 : : ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
508 : : }
509 : :
510 : : /* Outer header DSCP source */
511 [ # # ]: 0 : if (!ipsec_xfrm->options.copy_dscp) {
512 : 0 : sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_SA;
513 : 0 : sa->w10.s.dscp = tunnel->ipv6.dscp;
514 : : } else {
515 : 0 : sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
516 : : }
517 : : break;
518 : : default:
519 : : return -EINVAL;
520 : : }
521 : :
522 : 0 : skip_tunnel_info:
523 : : /* ESN */
524 : 0 : sa->w0.s.esn_en = !!ipsec_xfrm->options.esn;
525 : :
526 [ # # ]: 0 : if (ipsec_xfrm->esn.value)
527 : 0 : sa->ctx.esn_val = ipsec_xfrm->esn.value - 1;
528 : :
529 [ # # ]: 0 : if (ipsec_xfrm->options.udp_encap) {
530 [ # # ]: 0 : if (ipsec_xfrm->udp.sport)
531 : : sport = ipsec_xfrm->udp.sport;
532 : :
533 [ # # ]: 0 : if (ipsec_xfrm->udp.dport)
534 : : dport = ipsec_xfrm->udp.dport;
535 : :
536 : 0 : sa->w10.s.udp_src_port = sport;
537 : 0 : sa->w10.s.udp_dst_port = dport;
538 : : }
539 : :
540 : : offset = offsetof(struct roc_ot_ipsec_outb_sa, ctx);
541 : : /* Word offset for HW managed SA field */
542 : 0 : sa->w0.s.hw_ctx_off = offset / 8;
543 : :
544 : : /* Context push size is up to err ctl in HW ctx */
545 : 0 : sa->w0.s.ctx_push_size = sa->w0.s.hw_ctx_off + 1;
546 : :
547 : : /* Entire context size in 128B units */
548 : : offset = sizeof(struct roc_ot_ipsec_outb_sa);
549 : 0 : sa->w0.s.ctx_size = (PLT_ALIGN_CEIL(offset, ROC_CTX_UNIT_128B) /
550 : : ROC_CTX_UNIT_128B) -
551 : : 1;
552 : :
553 [ # # ]: 0 : if (sa->w0.s.ctx_size < ctx_ilen)
554 : 0 : sa->w0.s.ctx_size = ctx_ilen;
555 : :
556 : : /* IPID gen */
557 : 0 : sa->w2.s.ipid_gen = 1;
558 : :
559 : : /**
560 : : * CPT MC triggers expiry when counter value changes from 2 to 1. To
561 : : * mitigate this behaviour add 1 to the life counter values provided.
562 : : */
563 : :
564 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_soft_limit) {
565 : 0 : sa->ctx.soft_life = ipsec_xfrm->life.bytes_soft_limit + 1;
566 : 0 : sa->w0.s.soft_life_dec = 1;
567 : : }
568 : :
569 [ # # ]: 0 : if (ipsec_xfrm->life.packets_soft_limit) {
570 : 0 : sa->ctx.soft_life = ipsec_xfrm->life.packets_soft_limit + 1;
571 : 0 : sa->w0.s.soft_life_dec = 1;
572 : : }
573 : :
574 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_hard_limit) {
575 : 0 : sa->ctx.hard_life = ipsec_xfrm->life.bytes_hard_limit + 1;
576 : 0 : sa->w0.s.hard_life_dec = 1;
577 : : }
578 : :
579 [ # # ]: 0 : if (ipsec_xfrm->life.packets_hard_limit) {
580 : 0 : sa->ctx.hard_life = ipsec_xfrm->life.packets_hard_limit + 1;
581 : 0 : sa->w0.s.hard_life_dec = 1;
582 : : }
583 : :
584 : : /* There are two words of CPT_CTX_HW_S for ucode to skip */
585 : 0 : sa->w0.s.ctx_hdr_size = 1;
586 : 0 : sa->w0.s.aop_valid = 1;
587 : :
588 : : rte_wmb();
589 : :
590 : : /* Enable SA */
591 : 0 : sa->w2.s.valid = 1;
592 : 0 : return 0;
593 : : }
594 : :
595 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ot_ipsec_inb_sa_valid)
596 : : bool
597 : 0 : cnxk_ot_ipsec_inb_sa_valid(struct roc_ot_ipsec_inb_sa *sa)
598 : : {
599 : 0 : return !!sa->w2.s.valid;
600 : : }
601 : :
602 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ot_ipsec_outb_sa_valid)
603 : : bool
604 : 0 : cnxk_ot_ipsec_outb_sa_valid(struct roc_ot_ipsec_outb_sa *sa)
605 : : {
606 : 0 : return !!sa->w2.s.valid;
607 : : }
608 : :
609 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ipsec_ivlen_get)
610 : : uint8_t
611 : 0 : cnxk_ipsec_ivlen_get(enum rte_crypto_cipher_algorithm c_algo,
612 : : enum rte_crypto_auth_algorithm a_algo,
613 : : enum rte_crypto_aead_algorithm aead_algo)
614 : : {
615 : : uint8_t ivlen = 0;
616 : :
617 [ # # ]: 0 : if ((aead_algo == RTE_CRYPTO_AEAD_AES_GCM) || (aead_algo == RTE_CRYPTO_AEAD_AES_CCM))
618 : : ivlen = 8;
619 : :
620 [ # # # # ]: 0 : switch (c_algo) {
621 : 0 : case RTE_CRYPTO_CIPHER_AES_CTR:
622 : : ivlen = 8;
623 : 0 : break;
624 : 0 : case RTE_CRYPTO_CIPHER_DES_CBC:
625 : : case RTE_CRYPTO_CIPHER_3DES_CBC:
626 : : ivlen = ROC_CPT_DES_BLOCK_LENGTH;
627 : 0 : break;
628 : 0 : case RTE_CRYPTO_CIPHER_AES_CBC:
629 : : ivlen = ROC_CPT_AES_BLOCK_LENGTH;
630 : 0 : break;
631 : : default:
632 : : break;
633 : : }
634 : :
635 [ # # ]: 0 : switch (a_algo) {
636 : 0 : case RTE_CRYPTO_AUTH_AES_GMAC:
637 : : ivlen = 8;
638 : 0 : break;
639 : : default:
640 : : break;
641 : : }
642 : :
643 : 0 : return ivlen;
644 : : }
645 : :
646 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ipsec_icvlen_get)
647 : : uint8_t
648 [ # # ]: 0 : cnxk_ipsec_icvlen_get(enum rte_crypto_cipher_algorithm c_algo,
649 : : enum rte_crypto_auth_algorithm a_algo,
650 : : enum rte_crypto_aead_algorithm aead_algo)
651 : : {
652 : : uint8_t icv = 0;
653 : :
654 : : (void)c_algo;
655 : :
656 : : switch (a_algo) {
657 : : case RTE_CRYPTO_AUTH_NULL:
658 : : icv = 0;
659 : : break;
660 : : case RTE_CRYPTO_AUTH_MD5_HMAC:
661 : : case RTE_CRYPTO_AUTH_SHA1_HMAC:
662 : : icv = 12;
663 : : break;
664 : : case RTE_CRYPTO_AUTH_SHA256_HMAC:
665 : : case RTE_CRYPTO_AUTH_AES_GMAC:
666 : : icv = 16;
667 : : break;
668 : : case RTE_CRYPTO_AUTH_SHA384_HMAC:
669 : : icv = 24;
670 : : break;
671 : : case RTE_CRYPTO_AUTH_SHA512_HMAC:
672 : : icv = 32;
673 : : break;
674 : : case RTE_CRYPTO_AUTH_AES_XCBC_MAC:
675 : : icv = 12;
676 : : break;
677 : : default:
678 : : break;
679 : : }
680 : :
681 [ # # ]: 0 : switch (aead_algo) {
682 : 0 : case RTE_CRYPTO_AEAD_AES_GCM:
683 : : case RTE_CRYPTO_AEAD_AES_CCM:
684 : : icv = 16;
685 : 0 : break;
686 : : default:
687 : : break;
688 : : }
689 : :
690 : 0 : return icv;
691 : : }
692 : :
693 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ipsec_outb_roundup_byte)
694 : : uint8_t
695 : 0 : cnxk_ipsec_outb_roundup_byte(enum rte_crypto_cipher_algorithm c_algo,
696 : : enum rte_crypto_aead_algorithm aead_algo)
697 : : {
698 : : uint8_t roundup_byte = 4;
699 : :
700 [ # # ]: 0 : if ((aead_algo == RTE_CRYPTO_AEAD_AES_GCM) || (aead_algo == RTE_CRYPTO_AEAD_AES_CCM))
701 : : return roundup_byte;
702 : :
703 [ # # # ]: 0 : switch (c_algo) {
704 : : case RTE_CRYPTO_CIPHER_AES_CTR:
705 : : roundup_byte = 4;
706 : : break;
707 : 0 : case RTE_CRYPTO_CIPHER_AES_CBC:
708 : : roundup_byte = 16;
709 : 0 : break;
710 : 0 : case RTE_CRYPTO_CIPHER_DES_CBC:
711 : : case RTE_CRYPTO_CIPHER_3DES_CBC:
712 : : roundup_byte = 8;
713 : 0 : break;
714 : : case RTE_CRYPTO_CIPHER_NULL:
715 : : roundup_byte = 4;
716 : : break;
717 : : default:
718 : : break;
719 : : }
720 : :
721 : : return roundup_byte;
722 : : }
723 : :
724 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ipsec_outb_rlens_get)
725 : : int
726 [ # # ]: 0 : cnxk_ipsec_outb_rlens_get(struct cnxk_ipsec_outb_rlens *rlens,
727 : : struct rte_security_ipsec_xform *ipsec_xfrm,
728 : : struct rte_crypto_sym_xform *crypto_xfrm)
729 : : {
730 : : struct rte_security_ipsec_tunnel_param *tunnel = &ipsec_xfrm->tunnel;
731 : : enum rte_crypto_cipher_algorithm c_algo = RTE_CRYPTO_CIPHER_NULL;
732 : : enum rte_crypto_auth_algorithm a_algo = RTE_CRYPTO_AUTH_NULL;
733 : : enum rte_crypto_aead_algorithm aead_algo = 0;
734 : : uint16_t partial_len = 0;
735 : : uint8_t roundup_byte = 0;
736 : : int8_t roundup_len = 0;
737 : :
738 : : memset(rlens, 0, sizeof(struct cnxk_ipsec_outb_rlens));
739 : :
740 : : /* Get Cipher and Auth algo */
741 [ # # ]: 0 : if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
742 : 0 : aead_algo = crypto_xfrm->aead.algo;
743 : : } else {
744 [ # # ]: 0 : if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_CIPHER)
745 : 0 : c_algo = crypto_xfrm->cipher.algo;
746 : : else
747 : 0 : a_algo = crypto_xfrm->auth.algo;
748 : :
749 [ # # ]: 0 : if (crypto_xfrm->next) {
750 [ # # ]: 0 : if (crypto_xfrm->next->type ==
751 : : RTE_CRYPTO_SYM_XFORM_CIPHER)
752 : 0 : c_algo = crypto_xfrm->next->cipher.algo;
753 : : else
754 : 0 : a_algo = crypto_xfrm->next->auth.algo;
755 : : }
756 : : }
757 : :
758 [ # # ]: 0 : if (ipsec_xfrm->proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP) {
759 : : partial_len = ROC_CPT_ESP_HDR_LEN;
760 : : roundup_len = ROC_CPT_ESP_TRL_LEN;
761 : : } else {
762 : : partial_len = ROC_CPT_AH_HDR_LEN;
763 : : }
764 : :
765 [ # # ]: 0 : if (ipsec_xfrm->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
766 [ # # ]: 0 : if (tunnel->type == RTE_SECURITY_IPSEC_TUNNEL_IPV4)
767 : 0 : partial_len += ROC_CPT_TUNNEL_IPV4_HDR_LEN;
768 : : else
769 : 0 : partial_len += ROC_CPT_TUNNEL_IPV6_HDR_LEN;
770 : : }
771 : :
772 : 0 : partial_len += cnxk_ipsec_ivlen_get(c_algo, a_algo, aead_algo);
773 : 0 : partial_len += cnxk_ipsec_icvlen_get(c_algo, a_algo, aead_algo);
774 : 0 : roundup_byte = cnxk_ipsec_outb_roundup_byte(c_algo, aead_algo);
775 : :
776 [ # # ]: 0 : if (ipsec_xfrm->options.udp_encap)
777 : 0 : partial_len += sizeof(struct rte_udp_hdr);
778 : :
779 : 0 : rlens->partial_len = partial_len;
780 : 0 : rlens->roundup_len = roundup_len;
781 : 0 : rlens->roundup_byte = roundup_byte;
782 : 0 : rlens->max_extended_len = partial_len + roundup_len + roundup_byte;
783 : 0 : return 0;
784 : : }
785 : :
786 : : static inline int
787 : 0 : on_ipsec_sa_ctl_set(struct rte_security_ipsec_xform *ipsec,
788 : : struct rte_crypto_sym_xform *crypto_xform,
789 : : struct roc_ie_on_sa_ctl *ctl)
790 : : {
791 : : struct rte_crypto_sym_xform *cipher_xform, *auth_xform;
792 : : int aes_key_len = 0;
793 : :
794 [ # # ]: 0 : if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
795 : : auth_xform = crypto_xform;
796 : 0 : cipher_xform = crypto_xform->next;
797 : : } else {
798 : : cipher_xform = crypto_xform;
799 : 0 : auth_xform = crypto_xform->next;
800 : : }
801 : :
802 [ # # ]: 0 : if (ipsec->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
803 : 0 : ctl->direction = ROC_IE_SA_DIR_OUTBOUND;
804 : : else
805 : 0 : ctl->direction = ROC_IE_SA_DIR_INBOUND;
806 : :
807 [ # # ]: 0 : if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
808 [ # # ]: 0 : if (ipsec->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV4)
809 : 0 : ctl->outer_ip_ver = ROC_IE_SA_IP_VERSION_4;
810 [ # # ]: 0 : else if (ipsec->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV6)
811 : 0 : ctl->outer_ip_ver = ROC_IE_SA_IP_VERSION_6;
812 : : else
813 : : return -EINVAL;
814 : : }
815 : :
816 [ # # ]: 0 : if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT) {
817 : 0 : ctl->ipsec_mode = ROC_IE_SA_MODE_TRANSPORT;
818 : 0 : ctl->outer_ip_ver = ROC_IE_SA_IP_VERSION_4;
819 [ # # ]: 0 : } else if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
820 : 0 : ctl->ipsec_mode = ROC_IE_SA_MODE_TUNNEL;
821 : : else
822 : : return -EINVAL;
823 : :
824 [ # # ]: 0 : if (ipsec->proto == RTE_SECURITY_IPSEC_SA_PROTO_AH)
825 : 0 : ctl->ipsec_proto = ROC_IE_SA_PROTOCOL_AH;
826 [ # # ]: 0 : else if (ipsec->proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP)
827 : 0 : ctl->ipsec_proto = ROC_IE_SA_PROTOCOL_ESP;
828 : : else
829 : : return -EINVAL;
830 : :
831 [ # # ]: 0 : if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
832 [ # # # ]: 0 : switch (crypto_xform->aead.algo) {
833 : 0 : case RTE_CRYPTO_AEAD_AES_GCM:
834 : 0 : ctl->enc_type = ROC_IE_SA_ENC_AES_GCM;
835 : 0 : aes_key_len = crypto_xform->aead.key.length;
836 : 0 : break;
837 : 0 : case RTE_CRYPTO_AEAD_AES_CCM:
838 : 0 : ctl->enc_type = ROC_IE_SA_ENC_AES_CCM;
839 : 0 : aes_key_len = crypto_xform->aead.key.length;
840 : 0 : break;
841 : 0 : default:
842 : 0 : plt_err("Unsupported AEAD algorithm");
843 : 0 : return -ENOTSUP;
844 : : }
845 : : } else {
846 [ # # ]: 0 : if (cipher_xform != NULL) {
847 [ # # # # : 0 : switch (cipher_xform->cipher.algo) {
# # ]
848 : 0 : case RTE_CRYPTO_CIPHER_NULL:
849 : 0 : ctl->enc_type = ROC_IE_SA_ENC_NULL;
850 : 0 : break;
851 : 0 : case RTE_CRYPTO_CIPHER_DES_CBC:
852 : 0 : ctl->enc_type = ROC_IE_SA_ENC_DES_CBC;
853 : 0 : aes_key_len = cipher_xform->cipher.key.length;
854 : 0 : break;
855 : 0 : case RTE_CRYPTO_CIPHER_3DES_CBC:
856 : 0 : ctl->enc_type = ROC_IE_SA_ENC_3DES_CBC;
857 : 0 : aes_key_len = cipher_xform->cipher.key.length;
858 : 0 : break;
859 : 0 : case RTE_CRYPTO_CIPHER_AES_CBC:
860 : 0 : ctl->enc_type = ROC_IE_SA_ENC_AES_CBC;
861 : 0 : aes_key_len = cipher_xform->cipher.key.length;
862 : 0 : break;
863 : 0 : case RTE_CRYPTO_CIPHER_AES_CTR:
864 : 0 : ctl->enc_type = ROC_IE_SA_ENC_AES_CTR;
865 : 0 : aes_key_len = cipher_xform->cipher.key.length;
866 : 0 : break;
867 : 0 : default:
868 : 0 : plt_err("Unsupported cipher algorithm");
869 : 0 : return -ENOTSUP;
870 : : }
871 : : }
872 : :
873 [ # # # # : 0 : switch (auth_xform->auth.algo) {
# # # # #
# ]
874 : 0 : case RTE_CRYPTO_AUTH_NULL:
875 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_NULL;
876 : 0 : break;
877 : 0 : case RTE_CRYPTO_AUTH_MD5_HMAC:
878 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_MD5;
879 : 0 : break;
880 : 0 : case RTE_CRYPTO_AUTH_SHA1_HMAC:
881 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_SHA1;
882 : 0 : break;
883 : 0 : case RTE_CRYPTO_AUTH_SHA224_HMAC:
884 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_SHA2_224;
885 : 0 : break;
886 : 0 : case RTE_CRYPTO_AUTH_SHA256_HMAC:
887 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_SHA2_256;
888 : 0 : break;
889 : 0 : case RTE_CRYPTO_AUTH_SHA384_HMAC:
890 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_SHA2_384;
891 : 0 : break;
892 : 0 : case RTE_CRYPTO_AUTH_SHA512_HMAC:
893 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_SHA2_512;
894 : 0 : break;
895 : 0 : case RTE_CRYPTO_AUTH_AES_GMAC:
896 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_AES_GMAC;
897 : 0 : aes_key_len = auth_xform->auth.key.length;
898 : 0 : break;
899 : 0 : case RTE_CRYPTO_AUTH_AES_XCBC_MAC:
900 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_AES_XCBC_128;
901 : 0 : break;
902 : 0 : default:
903 : 0 : plt_err("Unsupported auth algorithm");
904 : 0 : return -ENOTSUP;
905 : : }
906 : : }
907 : :
908 : : /* Validate and set AES key length before copy */
909 : 0 : if (ctl->enc_type == ROC_IE_SA_ENC_AES_CBC || ctl->enc_type == ROC_IE_SA_ENC_AES_CTR ||
910 [ # # ]: 0 : ctl->enc_type == ROC_IE_SA_ENC_AES_GCM || ctl->enc_type == ROC_IE_SA_ENC_AES_CCM ||
911 [ # # ]: 0 : ctl->auth_type == ROC_IE_SA_AUTH_AES_GMAC) {
912 [ # # # # ]: 0 : switch (aes_key_len) {
913 : 0 : case ROC_CPT_AES128_KEY_LEN:
914 : 0 : ctl->aes_key_len = ROC_IE_SA_AES_KEY_LEN_128;
915 : 0 : break;
916 : 0 : case ROC_CPT_AES192_KEY_LEN:
917 : 0 : ctl->aes_key_len = ROC_IE_SA_AES_KEY_LEN_192;
918 : 0 : break;
919 : 0 : case ROC_CPT_AES256_KEY_LEN:
920 : 0 : ctl->aes_key_len = ROC_IE_SA_AES_KEY_LEN_256;
921 : 0 : break;
922 : 0 : default:
923 : 0 : plt_err("Invalid AES key length");
924 : 0 : return -EINVAL;
925 : : }
926 : : }
927 [ # # # # ]: 0 : if (ctl->enc_type == ROC_IE_SA_ENC_DES_CBC && aes_key_len != ROC_CPT_DES_KEY_LEN) {
928 : 0 : plt_err("Invalid DES key length");
929 : 0 : return -EINVAL;
930 : : }
931 [ # # # # ]: 0 : if (ctl->enc_type == ROC_IE_SA_ENC_3DES_CBC && aes_key_len != ROC_CPT_DES3_KEY_LEN) {
932 : 0 : plt_err("Invalid 3DES key length");
933 : 0 : return -EINVAL;
934 : : }
935 : :
936 [ # # ]: 0 : if (ipsec->options.esn)
937 : 0 : ctl->esn_en = 1;
938 : :
939 [ # # ]: 0 : if (ipsec->options.udp_encap == 1)
940 : 0 : ctl->encap_type = ROC_IE_ON_SA_ENCAP_UDP;
941 : :
942 : 0 : ctl->copy_df = ipsec->options.copy_df;
943 : :
944 [ # # ]: 0 : ctl->spi = rte_cpu_to_be_32(ipsec->spi);
945 : :
946 : 0 : rte_io_wmb();
947 : :
948 : 0 : ctl->valid = 1;
949 : :
950 : 0 : return 0;
951 : : }
952 : :
953 : : static inline int
954 : 0 : on_fill_ipsec_common_sa(struct rte_security_ipsec_xform *ipsec,
955 : : struct rte_crypto_sym_xform *crypto_xform,
956 : : struct roc_ie_on_common_sa *common_sa)
957 : : {
958 : : struct rte_crypto_sym_xform *cipher_xform, *auth_xform;
959 : : const uint8_t *cipher_key;
960 : : int cipher_key_len = 0;
961 : : uint8_t ccm_flag = 0;
962 : : int ret;
963 : :
964 : 0 : ret = on_ipsec_sa_ctl_set(ipsec, crypto_xform, &common_sa->ctl);
965 [ # # ]: 0 : if (ret)
966 : : return ret;
967 : :
968 [ # # ]: 0 : if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
969 : : auth_xform = crypto_xform;
970 : 0 : cipher_xform = crypto_xform->next;
971 : : } else {
972 : : cipher_xform = crypto_xform;
973 : 0 : auth_xform = crypto_xform->next;
974 : : }
975 : :
976 [ # # ]: 0 : if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
977 [ # # ]: 0 : if (crypto_xform->aead.algo == RTE_CRYPTO_AEAD_AES_GCM)
978 : 0 : memcpy(common_sa->iv.gcm.nonce, &ipsec->salt, 4);
979 [ # # ]: 0 : else if (crypto_xform->aead.algo == RTE_CRYPTO_AEAD_AES_CCM) {
980 : : ccm_flag = 0x07 & ~ROC_CPT_AES_CCM_CTR_LEN;
981 : 0 : *common_sa->iv.gcm.nonce = ccm_flag;
982 : 0 : memcpy(PLT_PTR_ADD(common_sa->iv.gcm.nonce, 1), &ipsec->salt, 3);
983 : : }
984 : 0 : cipher_key = crypto_xform->aead.key.data;
985 : 0 : cipher_key_len = crypto_xform->aead.key.length;
986 : : } else {
987 [ # # ]: 0 : if (cipher_xform) {
988 [ # # ]: 0 : if (cipher_xform->cipher.algo == RTE_CRYPTO_CIPHER_AES_CTR)
989 : 0 : memcpy(common_sa->iv.gcm.nonce, &ipsec->salt, 4);
990 : 0 : cipher_key = cipher_xform->cipher.key.data;
991 : 0 : cipher_key_len = cipher_xform->cipher.key.length;
992 : : }
993 : :
994 [ # # ]: 0 : if (auth_xform->auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
995 : 0 : memcpy(common_sa->iv.gcm.nonce, &ipsec->salt, 4);
996 : 0 : cipher_key = auth_xform->auth.key.data;
997 : 0 : cipher_key_len = auth_xform->auth.key.length;
998 : : }
999 : : }
1000 : :
1001 [ # # ]: 0 : if (cipher_key_len != 0)
1002 : 0 : memcpy(common_sa->cipher_key, cipher_key, cipher_key_len);
1003 : :
1004 : : return 0;
1005 : : }
1006 : :
1007 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_on_ipsec_outb_sa_create)
1008 : : int
1009 : 0 : cnxk_on_ipsec_outb_sa_create(struct rte_security_ipsec_xform *ipsec,
1010 : : struct rte_crypto_sym_xform *crypto_xform,
1011 : : struct roc_ie_on_outb_sa *out_sa)
1012 : : {
1013 : : struct roc_ie_on_ip_template *template = NULL;
1014 : : struct rte_crypto_sym_xform *auth_xform;
1015 : : struct roc_ie_on_sa_ctl *ctl;
1016 : : struct rte_ipv6_hdr *ip6;
1017 : : struct rte_ipv4_hdr *ip4;
1018 : : uint16_t sport, dport;
1019 : : size_t ctx_len;
1020 : : int ret;
1021 : :
1022 : : ctl = &out_sa->common_sa.ctl;
1023 : :
1024 [ # # ]: 0 : if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AUTH)
1025 : : auth_xform = crypto_xform;
1026 : : else
1027 : 0 : auth_xform = crypto_xform->next;
1028 : :
1029 : 0 : ret = on_fill_ipsec_common_sa(ipsec, crypto_xform, &out_sa->common_sa);
1030 [ # # ]: 0 : if (ret)
1031 : : return ret;
1032 : :
1033 [ # # ]: 0 : if (ctl->enc_type == ROC_IE_SA_ENC_AES_GCM || ctl->enc_type == ROC_IE_SA_ENC_AES_CCM ||
1034 [ # # # # ]: 0 : ctl->auth_type == ROC_IE_SA_AUTH_NULL || ctl->auth_type == ROC_IE_SA_AUTH_AES_GMAC) {
1035 : 0 : template = &out_sa->aes_gcm.template;
1036 : 0 : ctx_len = offsetof(struct roc_ie_on_outb_sa, aes_gcm.template);
1037 : : } else {
1038 [ # # # # ]: 0 : switch (ctl->auth_type) {
1039 : 0 : case ROC_IE_SA_AUTH_MD5:
1040 : : case ROC_IE_SA_AUTH_SHA1:
1041 : 0 : template = &out_sa->sha1.template;
1042 : : ctx_len = offsetof(struct roc_ie_on_outb_sa, sha1.template);
1043 : 0 : break;
1044 : 0 : case ROC_IE_SA_AUTH_SHA2_256:
1045 : : case ROC_IE_SA_AUTH_SHA2_384:
1046 : : case ROC_IE_SA_AUTH_SHA2_512:
1047 : 0 : template = &out_sa->sha2.template;
1048 : : ctx_len = offsetof(struct roc_ie_on_outb_sa, sha2.template);
1049 : 0 : break;
1050 : 0 : case ROC_IE_SA_AUTH_AES_XCBC_128:
1051 : 0 : template = &out_sa->aes_xcbc.template;
1052 : : ctx_len = offsetof(struct roc_ie_on_outb_sa, aes_xcbc.template);
1053 : 0 : break;
1054 : 0 : default:
1055 : 0 : plt_err("Unsupported auth algorithm");
1056 : 0 : return -EINVAL;
1057 : : }
1058 : : }
1059 : :
1060 : : ip4 = (struct rte_ipv4_hdr *)&template->ip4.ipv4_hdr;
1061 : :
1062 : : sport = 4500;
1063 : : dport = 4500;
1064 : :
1065 : : /* If custom port values are provided, Overwrite default port values. */
1066 [ # # ]: 0 : if (ipsec->options.udp_encap) {
1067 : :
1068 [ # # ]: 0 : if (ipsec->udp.sport)
1069 : : sport = ipsec->udp.sport;
1070 : :
1071 [ # # ]: 0 : if (ipsec->udp.dport)
1072 : : dport = ipsec->udp.dport;
1073 : :
1074 : 0 : ip4->next_proto_id = IPPROTO_UDP;
1075 [ # # ]: 0 : template->ip4.udp_src = rte_be_to_cpu_16(sport);
1076 [ # # ]: 0 : template->ip4.udp_dst = rte_be_to_cpu_16(dport);
1077 : : } else {
1078 [ # # ]: 0 : if (ipsec->proto == RTE_SECURITY_IPSEC_SA_PROTO_AH)
1079 : 0 : ip4->next_proto_id = IPPROTO_AH;
1080 : : else
1081 : 0 : ip4->next_proto_id = IPPROTO_ESP;
1082 : : }
1083 : :
1084 [ # # ]: 0 : if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
1085 [ # # ]: 0 : if (ipsec->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
1086 : : uint16_t frag_off = 0;
1087 : :
1088 : 0 : ctx_len += sizeof(template->ip4);
1089 : :
1090 : 0 : ip4->version_ihl = RTE_IPV4_VHL_DEF;
1091 [ # # ]: 0 : ip4->time_to_live = ipsec->tunnel.ipv4.ttl ?
1092 : : ipsec->tunnel.ipv4.ttl :
1093 : : 0x40;
1094 : 0 : ip4->type_of_service |= (ipsec->tunnel.ipv4.dscp << 2);
1095 [ # # ]: 0 : if (ipsec->tunnel.ipv4.df)
1096 : : frag_off |= RTE_IPV4_HDR_DF_FLAG;
1097 [ # # ]: 0 : ip4->fragment_offset = rte_cpu_to_be_16(frag_off);
1098 : :
1099 : 0 : memcpy(&ip4->src_addr, &ipsec->tunnel.ipv4.src_ip,
1100 : : sizeof(struct in_addr));
1101 : 0 : memcpy(&ip4->dst_addr, &ipsec->tunnel.ipv4.dst_ip,
1102 : : sizeof(struct in_addr));
1103 [ # # ]: 0 : } else if (ipsec->tunnel.type ==
1104 : : RTE_SECURITY_IPSEC_TUNNEL_IPV6) {
1105 : 0 : ctx_len += sizeof(template->ip6);
1106 : :
1107 : : ip6 = (struct rte_ipv6_hdr *)&template->ip6.ipv6_hdr;
1108 [ # # ]: 0 : if (ipsec->options.udp_encap) {
1109 : 0 : ip6->proto = IPPROTO_UDP;
1110 [ # # ]: 0 : template->ip6.udp_src = rte_be_to_cpu_16(sport);
1111 [ # # ]: 0 : template->ip6.udp_dst = rte_be_to_cpu_16(dport);
1112 : : } else {
1113 [ # # ]: 0 : ip6->proto = (ipsec->proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP) ?
1114 : : IPPROTO_ESP :
1115 : : IPPROTO_AH;
1116 : : }
1117 : 0 : ip6->vtc_flow =
1118 [ # # ]: 0 : rte_cpu_to_be_32(0x60000000 |
1119 : : ((ipsec->tunnel.ipv6.dscp
1120 : : << RTE_IPV6_HDR_TC_SHIFT) &
1121 : : RTE_IPV6_HDR_TC_MASK) |
1122 : : ((ipsec->tunnel.ipv6.flabel
1123 : : << RTE_IPV6_HDR_FL_SHIFT) &
1124 : : RTE_IPV6_HDR_FL_MASK));
1125 [ # # ]: 0 : ip6->hop_limits = ipsec->tunnel.ipv6.hlimit ?
1126 : : ipsec->tunnel.ipv6.hlimit :
1127 : : 0x40;
1128 : 0 : ip6->src_addr = ipsec->tunnel.ipv6.src_addr;
1129 : 0 : ip6->dst_addr = ipsec->tunnel.ipv6.dst_addr;
1130 : : }
1131 : : } else
1132 : 0 : ctx_len += sizeof(template->ip4);
1133 : :
1134 : 0 : ctx_len = RTE_ALIGN_CEIL(ctx_len, 8);
1135 : :
1136 [ # # ]: 0 : if (crypto_xform->type != RTE_CRYPTO_SYM_XFORM_AEAD) {
1137 : 0 : uint8_t *hmac_opad_ipad = (uint8_t *)&out_sa->sha2;
1138 : :
1139 [ # # ]: 0 : if (auth_xform->auth.algo == RTE_CRYPTO_AUTH_AES_XCBC_MAC) {
1140 : 0 : const uint8_t *auth_key = auth_xform->auth.key.data;
1141 : :
1142 : 0 : roc_aes_xcbc_key_derive(auth_key, hmac_opad_ipad);
1143 [ # # ]: 0 : } else if (auth_xform->auth.algo != RTE_CRYPTO_AUTH_NULL) {
1144 : 0 : roc_se_hmac_opad_ipad_gen(
1145 : 0 : out_sa->common_sa.ctl.auth_type, auth_xform->auth.key.data,
1146 : 0 : auth_xform->auth.key.length, &hmac_opad_ipad[0], ROC_SE_IPSEC);
1147 : : }
1148 : : }
1149 : :
1150 : 0 : return ctx_len;
1151 : : }
1152 : :
1153 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_on_ipsec_inb_sa_create)
1154 : : int
1155 : 0 : cnxk_on_ipsec_inb_sa_create(struct rte_security_ipsec_xform *ipsec,
1156 : : struct rte_crypto_sym_xform *crypto_xform,
1157 : : struct roc_ie_on_inb_sa *in_sa)
1158 : : {
1159 : : struct rte_crypto_sym_xform *auth_xform = crypto_xform;
1160 : : const uint8_t *auth_key;
1161 : : int auth_key_len = 0;
1162 : : size_t ctx_len = 0;
1163 : : int ret;
1164 : :
1165 : 0 : ret = on_fill_ipsec_common_sa(ipsec, crypto_xform, &in_sa->common_sa);
1166 [ # # ]: 0 : if (ret)
1167 : : return ret;
1168 : :
1169 [ # # ]: 0 : if (crypto_xform->type != RTE_CRYPTO_SYM_XFORM_AEAD &&
1170 [ # # # # ]: 0 : crypto_xform->auth.algo == RTE_CRYPTO_AUTH_NULL && ipsec->replay_win_sz) {
1171 : 0 : plt_err("anti-replay can't be supported with integrity service disabled");
1172 : 0 : return -EINVAL;
1173 : : }
1174 [ # # ]: 0 : if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD ||
1175 [ # # # # ]: 0 : auth_xform->auth.algo == RTE_CRYPTO_AUTH_NULL ||
1176 : : auth_xform->auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
1177 : : ctx_len = offsetof(struct roc_ie_on_inb_sa, sha1_or_gcm.hmac_key[0]);
1178 : : } else {
1179 : 0 : uint8_t *hmac_opad_ipad = (uint8_t *)&in_sa->sha2;
1180 : 0 : auth_key = auth_xform->auth.key.data;
1181 : 0 : auth_key_len = auth_xform->auth.key.length;
1182 : :
1183 [ # # # # ]: 0 : switch (auth_xform->auth.algo) {
1184 : : case RTE_CRYPTO_AUTH_NULL:
1185 : : break;
1186 : 0 : case RTE_CRYPTO_AUTH_MD5_HMAC:
1187 : : case RTE_CRYPTO_AUTH_SHA1_HMAC:
1188 : 0 : memcpy(in_sa->sha1_or_gcm.hmac_key, auth_key,
1189 : : auth_key_len);
1190 : : ctx_len = offsetof(struct roc_ie_on_inb_sa,
1191 : : sha1_or_gcm.selector);
1192 : 0 : break;
1193 : 0 : case RTE_CRYPTO_AUTH_SHA256_HMAC:
1194 : : case RTE_CRYPTO_AUTH_SHA384_HMAC:
1195 : : case RTE_CRYPTO_AUTH_SHA512_HMAC:
1196 : 0 : memcpy(in_sa->sha2.hmac_key, auth_key, auth_key_len);
1197 : : ctx_len = offsetof(struct roc_ie_on_inb_sa,
1198 : : sha2.selector);
1199 : 0 : break;
1200 : 0 : case RTE_CRYPTO_AUTH_AES_XCBC_MAC:
1201 : 0 : memcpy(in_sa->aes_xcbc.key, auth_key, auth_key_len);
1202 : : ctx_len = offsetof(struct roc_ie_on_inb_sa,
1203 : : aes_xcbc.selector);
1204 : 0 : break;
1205 : 0 : default:
1206 : 0 : plt_err("Unsupported auth algorithm %u", auth_xform->auth.algo);
1207 : 0 : return -ENOTSUP;
1208 : : }
1209 [ # # ]: 0 : if (auth_xform->auth.algo == RTE_CRYPTO_AUTH_AES_XCBC_MAC) {
1210 : 0 : const uint8_t *auth_key = auth_xform->auth.key.data;
1211 : :
1212 : 0 : roc_aes_xcbc_key_derive(auth_key, hmac_opad_ipad);
1213 [ # # ]: 0 : } else if (auth_xform->auth.algo != RTE_CRYPTO_AUTH_NULL) {
1214 : 0 : roc_se_hmac_opad_ipad_gen(
1215 : 0 : in_sa->common_sa.ctl.auth_type, auth_xform->auth.key.data,
1216 : 0 : auth_xform->auth.key.length, &hmac_opad_ipad[0], ROC_SE_IPSEC);
1217 : : }
1218 : : }
1219 : :
1220 : 0 : return ctx_len;
1221 : : }
1222 : :
1223 : : static int
1224 : 0 : ow_ipsec_sa_common_param_fill(union roc_ow_ipsec_sa_word2 *w2, uint8_t *cipher_key,
1225 : : uint8_t *salt_key, uint8_t *hmac_opad_ipad,
1226 : : struct rte_security_ipsec_xform *ipsec_xfrm,
1227 : : struct rte_crypto_sym_xform *crypto_xfrm)
1228 : : {
1229 : : struct rte_crypto_sym_xform *auth_xfrm, *cipher_xfrm;
1230 : : const uint8_t *key = NULL;
1231 : : uint8_t ccm_flag = 0;
1232 : : uint32_t *tmp_salt;
1233 : : uint64_t *tmp_key;
1234 : : int i, length = 0;
1235 : :
1236 : : /* Set direction */
1237 [ # # ]: 0 : if (ipsec_xfrm->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
1238 : 0 : w2->s.dir = ROC_IE_SA_DIR_OUTBOUND;
1239 : : else
1240 : 0 : w2->s.dir = ROC_IE_SA_DIR_INBOUND;
1241 : :
1242 [ # # ]: 0 : if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
1243 : : auth_xfrm = crypto_xfrm;
1244 : 0 : cipher_xfrm = crypto_xfrm->next;
1245 : : } else {
1246 : : cipher_xfrm = crypto_xfrm;
1247 : 0 : auth_xfrm = crypto_xfrm->next;
1248 : : }
1249 : :
1250 : : /* Set protocol - ESP vs AH */
1251 [ # # # ]: 0 : switch (ipsec_xfrm->proto) {
1252 : 0 : case RTE_SECURITY_IPSEC_SA_PROTO_ESP:
1253 : 0 : w2->s.protocol = ROC_IE_SA_PROTOCOL_ESP;
1254 : 0 : break;
1255 : 0 : case RTE_SECURITY_IPSEC_SA_PROTO_AH:
1256 : 0 : w2->s.protocol = ROC_IE_SA_PROTOCOL_AH;
1257 : 0 : break;
1258 : : default:
1259 : : return -EINVAL;
1260 : : }
1261 : :
1262 : : /* Set mode - transport vs tunnel */
1263 [ # # # ]: 0 : switch (ipsec_xfrm->mode) {
1264 : 0 : case RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT:
1265 : 0 : w2->s.mode = ROC_IE_SA_MODE_TRANSPORT;
1266 : 0 : break;
1267 : 0 : case RTE_SECURITY_IPSEC_SA_MODE_TUNNEL:
1268 : 0 : w2->s.mode = ROC_IE_SA_MODE_TUNNEL;
1269 : 0 : break;
1270 : : default:
1271 : : return -EINVAL;
1272 : : }
1273 : :
1274 : : /* Set encryption algorithm */
1275 [ # # ]: 0 : if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
1276 : 0 : key = crypto_xfrm->aead.key.data;
1277 : 0 : length = crypto_xfrm->aead.key.length;
1278 : :
1279 [ # # # ]: 0 : switch (crypto_xfrm->aead.algo) {
1280 : 0 : case RTE_CRYPTO_AEAD_AES_GCM:
1281 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_AES_GCM;
1282 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_NULL;
1283 [ # # ]: 0 : memcpy(salt_key, &ipsec_xfrm->salt, 4);
1284 : : tmp_salt = (uint32_t *)salt_key;
1285 [ # # ]: 0 : *tmp_salt = rte_be_to_cpu_32(*tmp_salt);
1286 : 0 : break;
1287 : 0 : case RTE_CRYPTO_AEAD_AES_CCM:
1288 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_AES_CCM;
1289 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_NULL;
1290 : : ccm_flag = 0x07 & ~ROC_CPT_AES_CCM_CTR_LEN;
1291 : 0 : *salt_key = ccm_flag;
1292 [ # # ]: 0 : memcpy(PLT_PTR_ADD(salt_key, 1), &ipsec_xfrm->salt, 3);
1293 : : tmp_salt = (uint32_t *)salt_key;
1294 [ # # ]: 0 : *tmp_salt = rte_be_to_cpu_32(*tmp_salt);
1295 : 0 : break;
1296 : : default:
1297 : : return -ENOTSUP;
1298 : : }
1299 : : } else {
1300 [ # # ]: 0 : if (cipher_xfrm != NULL) {
1301 [ # # # # : 0 : switch (cipher_xfrm->cipher.algo) {
# ]
1302 : 0 : case RTE_CRYPTO_CIPHER_NULL:
1303 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_NULL;
1304 : 0 : break;
1305 : 0 : case RTE_CRYPTO_CIPHER_AES_CBC:
1306 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_AES_CBC;
1307 : 0 : break;
1308 : 0 : case RTE_CRYPTO_CIPHER_AES_CTR:
1309 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_AES_CTR;
1310 [ # # ]: 0 : memcpy(salt_key, &ipsec_xfrm->salt, 4);
1311 : : tmp_salt = (uint32_t *)salt_key;
1312 [ # # ]: 0 : *tmp_salt = rte_be_to_cpu_32(*tmp_salt);
1313 : 0 : break;
1314 : 0 : case RTE_CRYPTO_CIPHER_3DES_CBC:
1315 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_3DES_CBC;
1316 : 0 : break;
1317 : : default:
1318 : : return -ENOTSUP;
1319 : : }
1320 : :
1321 : 0 : key = cipher_xfrm->cipher.key.data;
1322 : 0 : length = cipher_xfrm->cipher.key.length;
1323 : : }
1324 : :
1325 [ # # # # : 0 : switch (auth_xfrm->auth.algo) {
# # # # ]
1326 : 0 : case RTE_CRYPTO_AUTH_NULL:
1327 [ # # # # ]: 0 : if (w2->s.dir == ROC_IE_SA_DIR_INBOUND && ipsec_xfrm->replay_win_sz) {
1328 : 0 : plt_err("anti-replay can't be supported with integrity service disabled");
1329 : 0 : return -EINVAL;
1330 : : }
1331 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_NULL;
1332 : 0 : break;
1333 : 0 : case RTE_CRYPTO_AUTH_SHA1_HMAC:
1334 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_SHA1;
1335 : 0 : break;
1336 : 0 : case RTE_CRYPTO_AUTH_SHA256_HMAC:
1337 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_SHA2_256;
1338 : 0 : break;
1339 : 0 : case RTE_CRYPTO_AUTH_SHA384_HMAC:
1340 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_SHA2_384;
1341 : 0 : break;
1342 : 0 : case RTE_CRYPTO_AUTH_SHA512_HMAC:
1343 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_SHA2_512;
1344 : 0 : break;
1345 : 0 : case RTE_CRYPTO_AUTH_AES_XCBC_MAC:
1346 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_AES_XCBC_128;
1347 : 0 : break;
1348 : 0 : case RTE_CRYPTO_AUTH_AES_GMAC:
1349 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_AES_GMAC;
1350 : 0 : key = auth_xfrm->auth.key.data;
1351 : 0 : length = auth_xfrm->auth.key.length;
1352 [ # # ]: 0 : memcpy(salt_key, &ipsec_xfrm->salt, 4);
1353 : : tmp_salt = (uint32_t *)salt_key;
1354 [ # # ]: 0 : *tmp_salt = rte_be_to_cpu_32(*tmp_salt);
1355 : 0 : break;
1356 : : default:
1357 : : return -ENOTSUP;
1358 : : }
1359 : :
1360 [ # # ]: 0 : if (auth_xfrm->auth.algo == RTE_CRYPTO_AUTH_AES_XCBC_MAC) {
1361 : 0 : const uint8_t *auth_key = auth_xfrm->auth.key.data;
1362 : 0 : roc_aes_xcbc_key_derive(auth_key, hmac_opad_ipad);
1363 : : } else {
1364 : 0 : roc_se_hmac_opad_ipad_gen(w2->s.auth_type, auth_xfrm->auth.key.data,
1365 : 0 : auth_xfrm->auth.key.length, &hmac_opad_ipad[0],
1366 : : ROC_SE_IPSEC);
1367 : : }
1368 : :
1369 : : tmp_key = (uint64_t *)hmac_opad_ipad;
1370 [ # # ]: 0 : for (i = 0; i < (int)(ROC_CTX_MAX_OPAD_IPAD_LEN / sizeof(uint64_t)); i++)
1371 [ # # ]: 0 : tmp_key[i] = rte_be_to_cpu_64(tmp_key[i]);
1372 : : }
1373 : :
1374 : : /* Set encapsulation type */
1375 [ # # ]: 0 : if (ipsec_xfrm->options.udp_encap)
1376 : 0 : w2->s.encap_type = ROC_IE_OT_SA_ENCAP_UDP;
1377 : :
1378 : 0 : w2->s.spi = ipsec_xfrm->spi;
1379 : :
1380 [ # # ]: 0 : if (key != NULL && length != 0) {
1381 : : /* Validate key length and set AES key len before copy to avoid overflow */
1382 : 0 : if (w2->s.enc_type == ROC_IE_SA_ENC_AES_CBC ||
1383 : : w2->s.enc_type == ROC_IE_SA_ENC_AES_CTR ||
1384 [ # # ]: 0 : w2->s.enc_type == ROC_IE_SA_ENC_AES_GCM ||
1385 : 0 : w2->s.enc_type == ROC_IE_SA_ENC_AES_CCM ||
1386 [ # # ]: 0 : w2->s.auth_type == ROC_IE_SA_AUTH_AES_GMAC) {
1387 [ # # # # ]: 0 : switch (length) {
1388 : 0 : case ROC_CPT_AES128_KEY_LEN:
1389 : 0 : w2->s.aes_key_len = ROC_IE_SA_AES_KEY_LEN_128;
1390 : 0 : break;
1391 : 0 : case ROC_CPT_AES192_KEY_LEN:
1392 : 0 : w2->s.aes_key_len = ROC_IE_SA_AES_KEY_LEN_192;
1393 : 0 : break;
1394 : 0 : case ROC_CPT_AES256_KEY_LEN:
1395 : 0 : w2->s.aes_key_len = ROC_IE_SA_AES_KEY_LEN_256;
1396 : 0 : break;
1397 : 0 : default:
1398 : 0 : plt_err("Invalid AES key length");
1399 : 0 : return -EINVAL;
1400 : : }
1401 : : }
1402 [ # # # # ]: 0 : if (w2->s.enc_type == ROC_IE_SA_ENC_DES_CBC && length != ROC_CPT_DES_KEY_LEN) {
1403 : 0 : plt_err("Invalid DES key length");
1404 : 0 : return -EINVAL;
1405 : : }
1406 [ # # # # ]: 0 : if (w2->s.enc_type == ROC_IE_SA_ENC_3DES_CBC && length != ROC_CPT_DES3_KEY_LEN) {
1407 : 0 : plt_err("Invalid 3DES key length");
1408 : 0 : return -EINVAL;
1409 : : }
1410 : : /* Copy encryption key */
1411 : 0 : memcpy(cipher_key, key, length);
1412 : : tmp_key = (uint64_t *)cipher_key;
1413 [ # # ]: 0 : for (i = 0; i < (int)(ROC_CTX_MAX_CKEY_LEN / sizeof(uint64_t)); i++)
1414 [ # # ]: 0 : tmp_key[i] = rte_be_to_cpu_64(tmp_key[i]);
1415 : : }
1416 : :
1417 [ # # # # ]: 0 : if (ipsec_xfrm->life.packets_soft_limit != 0 || ipsec_xfrm->life.packets_hard_limit != 0) {
1418 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_soft_limit != 0 ||
1419 [ # # ]: 0 : ipsec_xfrm->life.bytes_hard_limit != 0) {
1420 : 0 : plt_err("Expiry tracking with both packets & bytes is not supported");
1421 : 0 : return -EINVAL;
1422 : : }
1423 : 0 : w2->s.life_unit = ROC_IE_OT_SA_LIFE_UNIT_PKTS;
1424 : : }
1425 : :
1426 [ # # # # ]: 0 : if (ipsec_xfrm->life.bytes_soft_limit != 0 || ipsec_xfrm->life.bytes_hard_limit != 0) {
1427 [ # # ]: 0 : if (ipsec_xfrm->life.packets_soft_limit != 0 ||
1428 [ # # ]: 0 : ipsec_xfrm->life.packets_hard_limit != 0) {
1429 : 0 : plt_err("Expiry tracking with both packets & bytes is not supported");
1430 : 0 : return -EINVAL;
1431 : : }
1432 : 0 : w2->s.life_unit = ROC_IE_OT_SA_LIFE_UNIT_OCTETS;
1433 : : }
1434 : :
1435 : : return 0;
1436 : : }
1437 : :
1438 : : static size_t
1439 : : ow_ipsec_inb_ctx_size(struct roc_ow_ipsec_inb_sa *sa)
1440 : : {
1441 : : size_t size;
1442 : :
1443 : : /* Variable based on Anti-replay Window */
1444 : : size = offsetof(struct roc_ow_ipsec_inb_sa, ctx) +
1445 : : offsetof(struct roc_ow_ipsec_inb_ctx_update_reg, ar_winbits);
1446 : :
1447 : 0 : if (sa->w0.s.ar_win)
1448 : 0 : size += (1 << (sa->w0.s.ar_win - 1)) * sizeof(uint64_t);
1449 : :
1450 : : return size;
1451 : : }
1452 : :
1453 : : static void
1454 : 0 : ow_ipsec_update_ipv6_addr_endianness(uint64_t *addr)
1455 : : {
1456 [ # # ]: 0 : *addr = rte_be_to_cpu_64(*addr);
1457 : : addr++;
1458 [ # # ]: 0 : *addr = rte_be_to_cpu_64(*addr);
1459 : 0 : }
1460 : :
1461 : : static int
1462 : 0 : ow_ipsec_inb_tunnel_hdr_fill(struct roc_ow_ipsec_inb_sa *sa,
1463 : : struct rte_security_ipsec_xform *ipsec_xfrm)
1464 : : {
1465 : : struct rte_security_ipsec_tunnel_param *tunnel;
1466 : :
1467 [ # # ]: 0 : if (ipsec_xfrm->mode != RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
1468 : : return 0;
1469 : :
1470 [ # # ]: 0 : if (ipsec_xfrm->options.tunnel_hdr_verify == 0)
1471 : : return 0;
1472 : :
1473 : : tunnel = &ipsec_xfrm->tunnel;
1474 : :
1475 [ # # # ]: 0 : switch (tunnel->type) {
1476 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_IPV4:
1477 : 0 : sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_4;
1478 [ # # ]: 0 : memcpy(&sa->outer_hdr.ipv4.src_addr, &tunnel->ipv4.src_ip, sizeof(struct in_addr));
1479 : 0 : memcpy(&sa->outer_hdr.ipv4.dst_addr, &tunnel->ipv4.dst_ip, sizeof(struct in_addr));
1480 : :
1481 : : /* IP Source and Dest are in LE/CPU endian */
1482 [ # # ]: 0 : sa->outer_hdr.ipv4.src_addr = rte_be_to_cpu_32(sa->outer_hdr.ipv4.src_addr);
1483 [ # # ]: 0 : sa->outer_hdr.ipv4.dst_addr = rte_be_to_cpu_32(sa->outer_hdr.ipv4.dst_addr);
1484 : :
1485 : 0 : break;
1486 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_IPV6:
1487 : 0 : sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_6;
1488 : 0 : memcpy(&sa->outer_hdr.ipv6.src_addr, &tunnel->ipv6.src_addr,
1489 : : sizeof(struct in6_addr));
1490 : 0 : memcpy(&sa->outer_hdr.ipv6.dst_addr, &tunnel->ipv6.dst_addr,
1491 : : sizeof(struct in6_addr));
1492 : :
1493 : : /* IP Source and Dest are in LE/CPU endian */
1494 : 0 : ow_ipsec_update_ipv6_addr_endianness((uint64_t *)&sa->outer_hdr.ipv6.src_addr);
1495 : 0 : ow_ipsec_update_ipv6_addr_endianness((uint64_t *)&sa->outer_hdr.ipv6.dst_addr);
1496 : :
1497 : 0 : break;
1498 : : default:
1499 : : return -EINVAL;
1500 : : }
1501 : :
1502 [ # # # ]: 0 : switch (ipsec_xfrm->options.tunnel_hdr_verify) {
1503 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_VERIFY_DST_ADDR:
1504 : 0 : sa->w2.s.ip_hdr_verify = ROC_IE_OT_SA_IP_HDR_VERIFY_DST_ADDR;
1505 : 0 : break;
1506 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_VERIFY_SRC_DST_ADDR:
1507 : 0 : sa->w2.s.ip_hdr_verify = ROC_IE_OT_SA_IP_HDR_VERIFY_SRC_DST_ADDR;
1508 : 0 : break;
1509 : : default:
1510 : : return -ENOTSUP;
1511 : : }
1512 : :
1513 : : return 0;
1514 : : }
1515 : :
1516 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ow_ipsec_inb_sa_fill)
1517 : : int
1518 : 0 : cnxk_ow_ipsec_inb_sa_fill(struct roc_ow_ipsec_inb_sa *sa,
1519 : : struct rte_security_ipsec_xform *ipsec_xfrm,
1520 : : struct rte_crypto_sym_xform *crypto_xfrm, uint8_t ctx_ilen)
1521 : : {
1522 : : uint16_t sport = 4500, dport = 4500;
1523 : : union roc_ow_ipsec_sa_word2 w2;
1524 : : uint32_t replay_win_sz;
1525 : : size_t offset;
1526 : : int rc;
1527 : :
1528 : : /* Initialize the SA */
1529 : 0 : roc_ow_ipsec_inb_sa_init(sa);
1530 : :
1531 : 0 : w2.u64 = 0;
1532 : 0 : rc = ow_ipsec_sa_common_param_fill(&w2, sa->cipher_key, sa->w8.s.salt, sa->hmac_opad_ipad,
1533 : : ipsec_xfrm, crypto_xfrm);
1534 [ # # ]: 0 : if (rc)
1535 : : return rc;
1536 : :
1537 : : /* Updata common word2 data */
1538 : 0 : sa->w2.u64 = w2.u64;
1539 : :
1540 : : /* Only support power-of-two window sizes supported */
1541 : 0 : replay_win_sz = ipsec_xfrm->replay_win_sz;
1542 [ # # ]: 0 : if (replay_win_sz) {
1543 [ # # ]: 0 : if (!rte_is_power_of_2(replay_win_sz) || replay_win_sz > ROC_AR_WIN_SIZE_MAX)
1544 : : return -ENOTSUP;
1545 : :
1546 : 0 : sa->w0.s.ar_win = rte_log2_u32(replay_win_sz) - 5;
1547 : : }
1548 : :
1549 : 0 : rc = ow_ipsec_inb_tunnel_hdr_fill(sa, ipsec_xfrm);
1550 [ # # ]: 0 : if (rc)
1551 : : return rc;
1552 : :
1553 : : /* Default options for pkt_out and pkt_fmt are with
1554 : : * second pass meta and no defrag.
1555 : : */
1556 : 0 : sa->w0.s.pkt_format = ROC_IE_OT_SA_PKT_FMT_META;
1557 : 0 : sa->w0.s.pkt_output = ROC_IE_OT_SA_PKT_OUTPUT_NO_FRAG;
1558 : 0 : sa->w0.s.pkind = ROC_IE_OT_CPT_PKIND;
1559 : :
1560 [ # # ]: 0 : if (ipsec_xfrm->options.ip_reassembly_en)
1561 : 0 : sa->w0.s.pkt_output = ROC_IE_OT_SA_PKT_OUTPUT_HW_BASED_DEFRAG;
1562 : :
1563 : : /* ESN */
1564 : 0 : sa->w2.s.esn_en = !!ipsec_xfrm->options.esn;
1565 [ # # ]: 0 : if (ipsec_xfrm->options.udp_encap) {
1566 [ # # ]: 0 : if (ipsec_xfrm->udp.sport)
1567 : : sport = ipsec_xfrm->udp.sport;
1568 : :
1569 [ # # ]: 0 : if (ipsec_xfrm->udp.dport)
1570 : : dport = ipsec_xfrm->udp.dport;
1571 : :
1572 : 0 : sa->w10.s.udp_src_port = sport;
1573 : 0 : sa->w10.s.udp_dst_port = dport;
1574 : : }
1575 : :
1576 [ # # ]: 0 : if (ipsec_xfrm->options.udp_ports_verify)
1577 : 0 : sa->w2.s.udp_ports_verify = 1;
1578 : :
1579 : : offset = offsetof(struct roc_ow_ipsec_inb_sa, ctx);
1580 : : /* Word offset for HW managed SA field */
1581 : 0 : sa->w0.s.hw_ctx_off = offset / 8;
1582 : : /* Context push size for inbound spans up to hw_ctx including
1583 : : * ar_base field, in 8b units
1584 : : */
1585 [ # # ]: 0 : sa->w0.s.ctx_push_size = sa->w0.s.hw_ctx_off + 1;
1586 : : /* Entire context size in 128B units */
1587 : 0 : sa->w0.s.ctx_size =
1588 : 0 : (PLT_ALIGN_CEIL(ow_ipsec_inb_ctx_size(sa), ROC_CTX_UNIT_128B) / ROC_CTX_UNIT_128B) -
1589 : : 1;
1590 : :
1591 [ # # ]: 0 : if (sa->w0.s.ctx_size < ctx_ilen)
1592 : 0 : sa->w0.s.ctx_size = ctx_ilen;
1593 : :
1594 : : /**
1595 : : * CPT MC triggers expiry when counter value changes from 2 to 1. To
1596 : : * mitigate this behaviour add 1 to the life counter values provided.
1597 : : */
1598 : :
1599 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_soft_limit) {
1600 : 0 : sa->ctx.soft_life = ipsec_xfrm->life.bytes_soft_limit + 1;
1601 : 0 : sa->w0.s.soft_life_dec = 1;
1602 : : }
1603 : :
1604 [ # # ]: 0 : if (ipsec_xfrm->life.packets_soft_limit) {
1605 : 0 : sa->ctx.soft_life = ipsec_xfrm->life.packets_soft_limit + 1;
1606 : 0 : sa->w0.s.soft_life_dec = 1;
1607 : : }
1608 : :
1609 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_hard_limit) {
1610 : 0 : sa->ctx.hard_life = ipsec_xfrm->life.bytes_hard_limit + 1;
1611 : 0 : sa->w0.s.hard_life_dec = 1;
1612 : : }
1613 : :
1614 [ # # ]: 0 : if (ipsec_xfrm->life.packets_hard_limit) {
1615 : 0 : sa->ctx.hard_life = ipsec_xfrm->life.packets_hard_limit + 1;
1616 : 0 : sa->w0.s.hard_life_dec = 1;
1617 : : }
1618 : :
1619 : : rte_wmb();
1620 : :
1621 : : /* Enable SA */
1622 : 0 : sa->w2.s.valid = 1;
1623 : 0 : return 0;
1624 : : }
1625 : :
1626 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ow_ipsec_outb_sa_fill)
1627 : : int
1628 : 0 : cnxk_ow_ipsec_outb_sa_fill(struct roc_ow_ipsec_outb_sa *sa,
1629 : : struct rte_security_ipsec_xform *ipsec_xfrm,
1630 : : struct rte_crypto_sym_xform *crypto_xfrm, uint8_t ctx_ilen)
1631 : : {
1632 : : struct rte_security_ipsec_tunnel_param *tunnel = &ipsec_xfrm->tunnel;
1633 : : uint16_t sport = 4500, dport = 4500;
1634 : : union roc_ow_ipsec_sa_word2 w2;
1635 : : size_t offset;
1636 : : int rc;
1637 : :
1638 : : /* Initialize the SA */
1639 : 0 : roc_ow_ipsec_outb_sa_init(sa);
1640 : :
1641 : 0 : w2.u64 = 0;
1642 : 0 : rc = ow_ipsec_sa_common_param_fill(&w2, sa->cipher_key, sa->iv.s.salt, sa->hmac_opad_ipad,
1643 : : ipsec_xfrm, crypto_xfrm);
1644 [ # # ]: 0 : if (rc)
1645 : : return rc;
1646 : :
1647 : : /* Update common word2 data */
1648 : 0 : sa->w2.u64 = w2.u64;
1649 : :
1650 [ # # ]: 0 : if (ipsec_xfrm->mode != RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
1651 : 0 : goto skip_tunnel_info;
1652 : :
1653 : : /* Tunnel header info */
1654 [ # # # ]: 0 : switch (tunnel->type) {
1655 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_IPV4:
1656 : 0 : sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_4;
1657 [ # # ]: 0 : memcpy(&sa->outer_hdr.ipv4.src_addr, &tunnel->ipv4.src_ip, sizeof(struct in_addr));
1658 : 0 : memcpy(&sa->outer_hdr.ipv4.dst_addr, &tunnel->ipv4.dst_ip, sizeof(struct in_addr));
1659 : :
1660 : : /* IP Source and Dest seems to be in LE/CPU endian */
1661 [ # # ]: 0 : sa->outer_hdr.ipv4.src_addr = rte_be_to_cpu_32(sa->outer_hdr.ipv4.src_addr);
1662 [ # # ]: 0 : sa->outer_hdr.ipv4.dst_addr = rte_be_to_cpu_32(sa->outer_hdr.ipv4.dst_addr);
1663 : :
1664 : : /* Outer header DF bit source */
1665 [ # # ]: 0 : if (!ipsec_xfrm->options.copy_df) {
1666 : 0 : sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src = ROC_IE_OT_SA_COPY_FROM_SA;
1667 : 0 : sa->w10.s.ipv4_df_or_ipv6_flw_lbl = tunnel->ipv4.df;
1668 : : } else {
1669 : 0 : sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
1670 : : ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
1671 : : }
1672 : :
1673 : : /* Outer header DSCP source */
1674 [ # # ]: 0 : if (!ipsec_xfrm->options.copy_dscp) {
1675 : 0 : sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_SA;
1676 : 0 : sa->w10.s.dscp = tunnel->ipv4.dscp;
1677 : : } else {
1678 : 0 : sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
1679 : : }
1680 : : break;
1681 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_IPV6:
1682 : 0 : sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_6;
1683 : 0 : memcpy(&sa->outer_hdr.ipv6.src_addr, &tunnel->ipv6.src_addr,
1684 : : sizeof(struct in6_addr));
1685 : 0 : memcpy(&sa->outer_hdr.ipv6.dst_addr, &tunnel->ipv6.dst_addr,
1686 : : sizeof(struct in6_addr));
1687 : :
1688 : : /* IP Source and Dest are in LE/CPU endian */
1689 : 0 : ow_ipsec_update_ipv6_addr_endianness((uint64_t *)&sa->outer_hdr.ipv6.src_addr);
1690 : 0 : ow_ipsec_update_ipv6_addr_endianness((uint64_t *)&sa->outer_hdr.ipv6.dst_addr);
1691 : :
1692 : : /* Outer header flow label source */
1693 [ # # ]: 0 : if (!ipsec_xfrm->options.copy_flabel) {
1694 : 0 : sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src = ROC_IE_OT_SA_COPY_FROM_SA;
1695 : :
1696 : 0 : sa->w10.s.ipv4_df_or_ipv6_flw_lbl = tunnel->ipv6.flabel;
1697 : : } else {
1698 : 0 : sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
1699 : : ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
1700 : : }
1701 : :
1702 : : /* Outer header DSCP source */
1703 [ # # ]: 0 : if (!ipsec_xfrm->options.copy_dscp) {
1704 : 0 : sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_SA;
1705 : 0 : sa->w10.s.dscp = tunnel->ipv6.dscp;
1706 : : } else {
1707 : 0 : sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
1708 : : }
1709 : : break;
1710 : : default:
1711 : : return -EINVAL;
1712 : : }
1713 : :
1714 : 0 : skip_tunnel_info:
1715 : : /* ESN */
1716 : 0 : sa->w0.s.esn_en = !!ipsec_xfrm->options.esn;
1717 : :
1718 [ # # ]: 0 : if (ipsec_xfrm->esn.value)
1719 : 0 : sa->ctx.esn_val = ipsec_xfrm->esn.value - 1;
1720 : :
1721 [ # # ]: 0 : if (ipsec_xfrm->options.udp_encap) {
1722 [ # # ]: 0 : if (ipsec_xfrm->udp.sport)
1723 : : sport = ipsec_xfrm->udp.sport;
1724 : :
1725 [ # # ]: 0 : if (ipsec_xfrm->udp.dport)
1726 : : dport = ipsec_xfrm->udp.dport;
1727 : :
1728 : 0 : sa->w10.s.udp_src_port = sport;
1729 : 0 : sa->w10.s.udp_dst_port = dport;
1730 : : }
1731 : :
1732 : : offset = offsetof(struct roc_ow_ipsec_outb_sa, ctx);
1733 : : /* Word offset for HW managed SA field */
1734 : 0 : sa->w0.s.hw_ctx_off = offset / 8;
1735 : :
1736 : : /* Context push size is up to err ctl in HW ctx */
1737 : 0 : sa->w0.s.ctx_push_size = sa->w0.s.hw_ctx_off + 1;
1738 : :
1739 : : /* Entire context size in 128B units */
1740 : : offset = sizeof(struct roc_ow_ipsec_outb_sa);
1741 : 0 : sa->w0.s.ctx_size = (PLT_ALIGN_CEIL(offset, ROC_CTX_UNIT_128B) / ROC_CTX_UNIT_128B) - 1;
1742 : :
1743 : : /* IPID gen */
1744 : 0 : sa->w2.s.ipid_gen = 1;
1745 : :
1746 [ # # ]: 0 : if (sa->w0.s.ctx_size < ctx_ilen)
1747 : 0 : sa->w0.s.ctx_size = ctx_ilen;
1748 : :
1749 : : /**
1750 : : * CPT MC triggers expiry when counter value changes from 2 to 1. To
1751 : : * mitigate this behaviour add 1 to the life counter values provided.
1752 : : */
1753 : :
1754 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_soft_limit) {
1755 : 0 : sa->ctx.soft_life = ipsec_xfrm->life.bytes_soft_limit + 1;
1756 : 0 : sa->w0.s.soft_life_dec = 1;
1757 : : }
1758 : :
1759 [ # # ]: 0 : if (ipsec_xfrm->life.packets_soft_limit) {
1760 : 0 : sa->ctx.soft_life = ipsec_xfrm->life.packets_soft_limit + 1;
1761 : 0 : sa->w0.s.soft_life_dec = 1;
1762 : : }
1763 : :
1764 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_hard_limit) {
1765 : 0 : sa->ctx.hard_life = ipsec_xfrm->life.bytes_hard_limit + 1;
1766 : 0 : sa->w0.s.hard_life_dec = 1;
1767 : : }
1768 : :
1769 [ # # ]: 0 : if (ipsec_xfrm->life.packets_hard_limit) {
1770 : 0 : sa->ctx.hard_life = ipsec_xfrm->life.packets_hard_limit + 1;
1771 : 0 : sa->w0.s.hard_life_dec = 1;
1772 : : }
1773 : :
1774 : : /* There are two words of CPT_CTX_HW_S for ucode to skip */
1775 : 0 : sa->w0.s.ctx_hdr_size = 1;
1776 : 0 : sa->w0.s.aop_valid = 1;
1777 : :
1778 : : rte_wmb();
1779 : :
1780 : : /* Enable SA */
1781 : 0 : sa->w2.s.valid = 1;
1782 : 0 : return 0;
1783 : : }
|