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