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_ow_ipsec_inb_sa_valid)
610 : : bool
611 : 0 : cnxk_ow_ipsec_inb_sa_valid(struct roc_ow_ipsec_inb_sa *sa)
612 : : {
613 : 0 : return !!sa->w2.s.valid;
614 : : }
615 : :
616 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ow_ipsec_outb_sa_valid)
617 : : bool
618 : 0 : cnxk_ow_ipsec_outb_sa_valid(struct roc_ow_ipsec_outb_sa *sa)
619 : : {
620 : 0 : return !!sa->w2.s.valid;
621 : : }
622 : :
623 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ipsec_ivlen_get)
624 : : uint8_t
625 : 0 : cnxk_ipsec_ivlen_get(enum rte_crypto_cipher_algorithm c_algo,
626 : : enum rte_crypto_auth_algorithm a_algo,
627 : : enum rte_crypto_aead_algorithm aead_algo)
628 : : {
629 : : uint8_t ivlen = 0;
630 : :
631 [ # # ]: 0 : if ((aead_algo == RTE_CRYPTO_AEAD_AES_GCM) || (aead_algo == RTE_CRYPTO_AEAD_AES_CCM))
632 : : ivlen = 8;
633 : :
634 [ # # # # ]: 0 : switch (c_algo) {
635 : 0 : case RTE_CRYPTO_CIPHER_AES_CTR:
636 : : ivlen = 8;
637 : 0 : break;
638 : 0 : case RTE_CRYPTO_CIPHER_DES_CBC:
639 : : case RTE_CRYPTO_CIPHER_3DES_CBC:
640 : : ivlen = ROC_CPT_DES_BLOCK_LENGTH;
641 : 0 : break;
642 : 0 : case RTE_CRYPTO_CIPHER_AES_CBC:
643 : : ivlen = ROC_CPT_AES_BLOCK_LENGTH;
644 : 0 : break;
645 : : default:
646 : : break;
647 : : }
648 : :
649 [ # # ]: 0 : switch (a_algo) {
650 : 0 : case RTE_CRYPTO_AUTH_AES_GMAC:
651 : : ivlen = 8;
652 : 0 : break;
653 : : default:
654 : : break;
655 : : }
656 : :
657 : 0 : return ivlen;
658 : : }
659 : :
660 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ipsec_icvlen_get)
661 : : uint8_t
662 [ # # ]: 0 : cnxk_ipsec_icvlen_get(enum rte_crypto_cipher_algorithm c_algo,
663 : : enum rte_crypto_auth_algorithm a_algo,
664 : : enum rte_crypto_aead_algorithm aead_algo)
665 : : {
666 : : uint8_t icv = 0;
667 : :
668 : : (void)c_algo;
669 : :
670 : : switch (a_algo) {
671 : : case RTE_CRYPTO_AUTH_NULL:
672 : : icv = 0;
673 : : break;
674 : : case RTE_CRYPTO_AUTH_MD5_HMAC:
675 : : case RTE_CRYPTO_AUTH_SHA1_HMAC:
676 : : icv = 12;
677 : : break;
678 : : case RTE_CRYPTO_AUTH_SHA256_HMAC:
679 : : case RTE_CRYPTO_AUTH_AES_GMAC:
680 : : icv = 16;
681 : : break;
682 : : case RTE_CRYPTO_AUTH_SHA384_HMAC:
683 : : icv = 24;
684 : : break;
685 : : case RTE_CRYPTO_AUTH_SHA512_HMAC:
686 : : icv = 32;
687 : : break;
688 : : case RTE_CRYPTO_AUTH_AES_XCBC_MAC:
689 : : icv = 12;
690 : : break;
691 : : default:
692 : : break;
693 : : }
694 : :
695 [ # # ]: 0 : switch (aead_algo) {
696 : 0 : case RTE_CRYPTO_AEAD_AES_GCM:
697 : : case RTE_CRYPTO_AEAD_AES_CCM:
698 : : icv = 16;
699 : 0 : break;
700 : : default:
701 : : break;
702 : : }
703 : :
704 : 0 : return icv;
705 : : }
706 : :
707 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ipsec_outb_roundup_byte)
708 : : uint8_t
709 : 0 : cnxk_ipsec_outb_roundup_byte(enum rte_crypto_cipher_algorithm c_algo,
710 : : enum rte_crypto_aead_algorithm aead_algo)
711 : : {
712 : : uint8_t roundup_byte = 4;
713 : :
714 [ # # ]: 0 : if ((aead_algo == RTE_CRYPTO_AEAD_AES_GCM) || (aead_algo == RTE_CRYPTO_AEAD_AES_CCM))
715 : : return roundup_byte;
716 : :
717 [ # # # ]: 0 : switch (c_algo) {
718 : : case RTE_CRYPTO_CIPHER_AES_CTR:
719 : : roundup_byte = 4;
720 : : break;
721 : 0 : case RTE_CRYPTO_CIPHER_AES_CBC:
722 : : roundup_byte = 16;
723 : 0 : break;
724 : 0 : case RTE_CRYPTO_CIPHER_DES_CBC:
725 : : case RTE_CRYPTO_CIPHER_3DES_CBC:
726 : : roundup_byte = 8;
727 : 0 : break;
728 : : case RTE_CRYPTO_CIPHER_NULL:
729 : : roundup_byte = 4;
730 : : break;
731 : : default:
732 : : break;
733 : : }
734 : :
735 : : return roundup_byte;
736 : : }
737 : :
738 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ipsec_outb_rlens_get)
739 : : int
740 [ # # ]: 0 : cnxk_ipsec_outb_rlens_get(struct cnxk_ipsec_outb_rlens *rlens,
741 : : struct rte_security_ipsec_xform *ipsec_xfrm,
742 : : struct rte_crypto_sym_xform *crypto_xfrm)
743 : : {
744 : : struct rte_security_ipsec_tunnel_param *tunnel = &ipsec_xfrm->tunnel;
745 : : enum rte_crypto_cipher_algorithm c_algo = RTE_CRYPTO_CIPHER_NULL;
746 : : enum rte_crypto_auth_algorithm a_algo = RTE_CRYPTO_AUTH_NULL;
747 : : enum rte_crypto_aead_algorithm aead_algo = 0;
748 : : uint16_t partial_len = 0;
749 : : uint8_t roundup_byte = 0;
750 : : int8_t roundup_len = 0;
751 : :
752 : : memset(rlens, 0, sizeof(struct cnxk_ipsec_outb_rlens));
753 : :
754 : : /* Get Cipher and Auth algo */
755 [ # # ]: 0 : if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
756 : 0 : aead_algo = crypto_xfrm->aead.algo;
757 : : } else {
758 [ # # ]: 0 : if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_CIPHER)
759 : 0 : c_algo = crypto_xfrm->cipher.algo;
760 : : else
761 : 0 : a_algo = crypto_xfrm->auth.algo;
762 : :
763 [ # # ]: 0 : if (crypto_xfrm->next) {
764 [ # # ]: 0 : if (crypto_xfrm->next->type ==
765 : : RTE_CRYPTO_SYM_XFORM_CIPHER)
766 : 0 : c_algo = crypto_xfrm->next->cipher.algo;
767 : : else
768 : 0 : a_algo = crypto_xfrm->next->auth.algo;
769 : : }
770 : : }
771 : :
772 [ # # ]: 0 : if (ipsec_xfrm->proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP) {
773 : : partial_len = ROC_CPT_ESP_HDR_LEN;
774 : : roundup_len = ROC_CPT_ESP_TRL_LEN;
775 : : } else {
776 : : partial_len = ROC_CPT_AH_HDR_LEN;
777 : : }
778 : :
779 [ # # ]: 0 : if (ipsec_xfrm->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
780 [ # # ]: 0 : if (tunnel->type == RTE_SECURITY_IPSEC_TUNNEL_IPV4)
781 : 0 : partial_len += ROC_CPT_TUNNEL_IPV4_HDR_LEN;
782 : : else
783 : 0 : partial_len += ROC_CPT_TUNNEL_IPV6_HDR_LEN;
784 : : }
785 : :
786 : 0 : partial_len += cnxk_ipsec_ivlen_get(c_algo, a_algo, aead_algo);
787 : 0 : partial_len += cnxk_ipsec_icvlen_get(c_algo, a_algo, aead_algo);
788 : 0 : roundup_byte = cnxk_ipsec_outb_roundup_byte(c_algo, aead_algo);
789 : :
790 [ # # ]: 0 : if (ipsec_xfrm->options.udp_encap)
791 : 0 : partial_len += sizeof(struct rte_udp_hdr);
792 : :
793 : 0 : rlens->partial_len = partial_len;
794 : 0 : rlens->roundup_len = roundup_len;
795 : 0 : rlens->roundup_byte = roundup_byte;
796 : 0 : rlens->max_extended_len = partial_len + roundup_len + roundup_byte;
797 : 0 : return 0;
798 : : }
799 : :
800 : : static inline int
801 : 0 : on_ipsec_sa_ctl_set(struct rte_security_ipsec_xform *ipsec,
802 : : struct rte_crypto_sym_xform *crypto_xform,
803 : : struct roc_ie_on_sa_ctl *ctl)
804 : : {
805 : : struct rte_crypto_sym_xform *cipher_xform, *auth_xform;
806 : : int aes_key_len = 0;
807 : :
808 [ # # ]: 0 : if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
809 : : auth_xform = crypto_xform;
810 : 0 : cipher_xform = crypto_xform->next;
811 : : } else {
812 : : cipher_xform = crypto_xform;
813 : 0 : auth_xform = crypto_xform->next;
814 : : }
815 : :
816 [ # # ]: 0 : if (ipsec->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
817 : 0 : ctl->direction = ROC_IE_SA_DIR_OUTBOUND;
818 : : else
819 : 0 : ctl->direction = ROC_IE_SA_DIR_INBOUND;
820 : :
821 [ # # ]: 0 : if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
822 [ # # ]: 0 : if (ipsec->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV4)
823 : 0 : ctl->outer_ip_ver = ROC_IE_SA_IP_VERSION_4;
824 [ # # ]: 0 : else if (ipsec->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV6)
825 : 0 : ctl->outer_ip_ver = ROC_IE_SA_IP_VERSION_6;
826 : : else
827 : : return -EINVAL;
828 : : }
829 : :
830 [ # # ]: 0 : if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT) {
831 : 0 : ctl->ipsec_mode = ROC_IE_SA_MODE_TRANSPORT;
832 : 0 : ctl->outer_ip_ver = ROC_IE_SA_IP_VERSION_4;
833 [ # # ]: 0 : } else if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
834 : 0 : ctl->ipsec_mode = ROC_IE_SA_MODE_TUNNEL;
835 : : else
836 : : return -EINVAL;
837 : :
838 [ # # ]: 0 : if (ipsec->proto == RTE_SECURITY_IPSEC_SA_PROTO_AH)
839 : 0 : ctl->ipsec_proto = ROC_IE_SA_PROTOCOL_AH;
840 [ # # ]: 0 : else if (ipsec->proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP)
841 : 0 : ctl->ipsec_proto = ROC_IE_SA_PROTOCOL_ESP;
842 : : else
843 : : return -EINVAL;
844 : :
845 [ # # ]: 0 : if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
846 [ # # # ]: 0 : switch (crypto_xform->aead.algo) {
847 : 0 : case RTE_CRYPTO_AEAD_AES_GCM:
848 : 0 : ctl->enc_type = ROC_IE_SA_ENC_AES_GCM;
849 : 0 : aes_key_len = crypto_xform->aead.key.length;
850 : 0 : break;
851 : 0 : case RTE_CRYPTO_AEAD_AES_CCM:
852 : 0 : ctl->enc_type = ROC_IE_SA_ENC_AES_CCM;
853 : 0 : aes_key_len = crypto_xform->aead.key.length;
854 : 0 : break;
855 : 0 : default:
856 : 0 : plt_err("Unsupported AEAD algorithm");
857 : 0 : return -ENOTSUP;
858 : : }
859 : : } else {
860 [ # # ]: 0 : if (cipher_xform != NULL) {
861 [ # # # # : 0 : switch (cipher_xform->cipher.algo) {
# # ]
862 : 0 : case RTE_CRYPTO_CIPHER_NULL:
863 : 0 : ctl->enc_type = ROC_IE_SA_ENC_NULL;
864 : 0 : break;
865 : 0 : case RTE_CRYPTO_CIPHER_DES_CBC:
866 : 0 : ctl->enc_type = ROC_IE_SA_ENC_DES_CBC;
867 : 0 : aes_key_len = cipher_xform->cipher.key.length;
868 : 0 : break;
869 : 0 : case RTE_CRYPTO_CIPHER_3DES_CBC:
870 : 0 : ctl->enc_type = ROC_IE_SA_ENC_3DES_CBC;
871 : 0 : aes_key_len = cipher_xform->cipher.key.length;
872 : 0 : break;
873 : 0 : case RTE_CRYPTO_CIPHER_AES_CBC:
874 : 0 : ctl->enc_type = ROC_IE_SA_ENC_AES_CBC;
875 : 0 : aes_key_len = cipher_xform->cipher.key.length;
876 : 0 : break;
877 : 0 : case RTE_CRYPTO_CIPHER_AES_CTR:
878 : 0 : ctl->enc_type = ROC_IE_SA_ENC_AES_CTR;
879 : 0 : aes_key_len = cipher_xform->cipher.key.length;
880 : 0 : break;
881 : 0 : default:
882 : 0 : plt_err("Unsupported cipher algorithm");
883 : 0 : return -ENOTSUP;
884 : : }
885 : : }
886 : :
887 [ # # # # : 0 : switch (auth_xform->auth.algo) {
# # # # #
# ]
888 : 0 : case RTE_CRYPTO_AUTH_NULL:
889 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_NULL;
890 : 0 : break;
891 : 0 : case RTE_CRYPTO_AUTH_MD5_HMAC:
892 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_MD5;
893 : 0 : break;
894 : 0 : case RTE_CRYPTO_AUTH_SHA1_HMAC:
895 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_SHA1;
896 : 0 : break;
897 : 0 : case RTE_CRYPTO_AUTH_SHA224_HMAC:
898 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_SHA2_224;
899 : 0 : break;
900 : 0 : case RTE_CRYPTO_AUTH_SHA256_HMAC:
901 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_SHA2_256;
902 : 0 : break;
903 : 0 : case RTE_CRYPTO_AUTH_SHA384_HMAC:
904 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_SHA2_384;
905 : 0 : break;
906 : 0 : case RTE_CRYPTO_AUTH_SHA512_HMAC:
907 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_SHA2_512;
908 : 0 : break;
909 : 0 : case RTE_CRYPTO_AUTH_AES_GMAC:
910 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_AES_GMAC;
911 : 0 : aes_key_len = auth_xform->auth.key.length;
912 : 0 : break;
913 : 0 : case RTE_CRYPTO_AUTH_AES_XCBC_MAC:
914 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_AES_XCBC_128;
915 : 0 : break;
916 : 0 : default:
917 : 0 : plt_err("Unsupported auth algorithm");
918 : 0 : return -ENOTSUP;
919 : : }
920 : : }
921 : :
922 : : /* Validate and set AES key length before copy */
923 : 0 : if (ctl->enc_type == ROC_IE_SA_ENC_AES_CBC || ctl->enc_type == ROC_IE_SA_ENC_AES_CTR ||
924 [ # # ]: 0 : ctl->enc_type == ROC_IE_SA_ENC_AES_GCM || ctl->enc_type == ROC_IE_SA_ENC_AES_CCM ||
925 [ # # ]: 0 : ctl->auth_type == ROC_IE_SA_AUTH_AES_GMAC) {
926 [ # # # # ]: 0 : switch (aes_key_len) {
927 : 0 : case ROC_CPT_AES128_KEY_LEN:
928 : 0 : ctl->aes_key_len = ROC_IE_SA_AES_KEY_LEN_128;
929 : 0 : break;
930 : 0 : case ROC_CPT_AES192_KEY_LEN:
931 : 0 : ctl->aes_key_len = ROC_IE_SA_AES_KEY_LEN_192;
932 : 0 : break;
933 : 0 : case ROC_CPT_AES256_KEY_LEN:
934 : 0 : ctl->aes_key_len = ROC_IE_SA_AES_KEY_LEN_256;
935 : 0 : break;
936 : 0 : default:
937 : 0 : plt_err("Invalid AES key length");
938 : 0 : return -EINVAL;
939 : : }
940 : : }
941 [ # # # # ]: 0 : if (ctl->enc_type == ROC_IE_SA_ENC_DES_CBC && aes_key_len != ROC_CPT_DES_KEY_LEN) {
942 : 0 : plt_err("Invalid DES key length");
943 : 0 : return -EINVAL;
944 : : }
945 [ # # # # ]: 0 : if (ctl->enc_type == ROC_IE_SA_ENC_3DES_CBC && aes_key_len != ROC_CPT_DES3_KEY_LEN) {
946 : 0 : plt_err("Invalid 3DES key length");
947 : 0 : return -EINVAL;
948 : : }
949 : :
950 [ # # ]: 0 : if (ipsec->options.esn)
951 : 0 : ctl->esn_en = 1;
952 : :
953 [ # # ]: 0 : if (ipsec->options.udp_encap == 1)
954 : 0 : ctl->encap_type = ROC_IE_ON_SA_ENCAP_UDP;
955 : :
956 : 0 : ctl->copy_df = ipsec->options.copy_df;
957 : :
958 [ # # ]: 0 : ctl->spi = rte_cpu_to_be_32(ipsec->spi);
959 : :
960 : 0 : rte_io_wmb();
961 : :
962 : 0 : ctl->valid = 1;
963 : :
964 : 0 : return 0;
965 : : }
966 : :
967 : : static inline int
968 : 0 : on_fill_ipsec_common_sa(struct rte_security_ipsec_xform *ipsec,
969 : : struct rte_crypto_sym_xform *crypto_xform,
970 : : struct roc_ie_on_common_sa *common_sa)
971 : : {
972 : : struct rte_crypto_sym_xform *cipher_xform, *auth_xform;
973 : : const uint8_t *cipher_key;
974 : : int cipher_key_len = 0;
975 : : uint8_t ccm_flag = 0;
976 : : int ret;
977 : :
978 : 0 : ret = on_ipsec_sa_ctl_set(ipsec, crypto_xform, &common_sa->ctl);
979 [ # # ]: 0 : if (ret)
980 : : return ret;
981 : :
982 [ # # ]: 0 : if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
983 : : auth_xform = crypto_xform;
984 : 0 : cipher_xform = crypto_xform->next;
985 : : } else {
986 : : cipher_xform = crypto_xform;
987 : 0 : auth_xform = crypto_xform->next;
988 : : }
989 : :
990 [ # # ]: 0 : if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
991 [ # # ]: 0 : if (crypto_xform->aead.algo == RTE_CRYPTO_AEAD_AES_GCM)
992 : 0 : memcpy(common_sa->iv.gcm.nonce, &ipsec->salt, 4);
993 [ # # ]: 0 : else if (crypto_xform->aead.algo == RTE_CRYPTO_AEAD_AES_CCM) {
994 : : ccm_flag = 0x07 & ~ROC_CPT_AES_CCM_CTR_LEN;
995 : 0 : *common_sa->iv.gcm.nonce = ccm_flag;
996 : 0 : memcpy(PLT_PTR_ADD(common_sa->iv.gcm.nonce, 1), &ipsec->salt, 3);
997 : : }
998 : 0 : cipher_key = crypto_xform->aead.key.data;
999 : 0 : cipher_key_len = crypto_xform->aead.key.length;
1000 : : } else {
1001 [ # # ]: 0 : if (cipher_xform) {
1002 [ # # ]: 0 : if (cipher_xform->cipher.algo == RTE_CRYPTO_CIPHER_AES_CTR)
1003 : 0 : memcpy(common_sa->iv.gcm.nonce, &ipsec->salt, 4);
1004 : 0 : cipher_key = cipher_xform->cipher.key.data;
1005 : 0 : cipher_key_len = cipher_xform->cipher.key.length;
1006 : : }
1007 : :
1008 [ # # ]: 0 : if (auth_xform->auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
1009 : 0 : memcpy(common_sa->iv.gcm.nonce, &ipsec->salt, 4);
1010 : 0 : cipher_key = auth_xform->auth.key.data;
1011 : 0 : cipher_key_len = auth_xform->auth.key.length;
1012 : : }
1013 : : }
1014 : :
1015 [ # # ]: 0 : if (cipher_key_len != 0)
1016 : 0 : memcpy(common_sa->cipher_key, cipher_key, cipher_key_len);
1017 : :
1018 : : return 0;
1019 : : }
1020 : :
1021 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_on_ipsec_outb_sa_create)
1022 : : int
1023 : 0 : cnxk_on_ipsec_outb_sa_create(struct rte_security_ipsec_xform *ipsec,
1024 : : struct rte_crypto_sym_xform *crypto_xform,
1025 : : struct roc_ie_on_outb_sa *out_sa)
1026 : : {
1027 : : struct roc_ie_on_ip_template *template = NULL;
1028 : : struct rte_crypto_sym_xform *auth_xform;
1029 : : struct roc_ie_on_sa_ctl *ctl;
1030 : : struct rte_ipv6_hdr *ip6;
1031 : : struct rte_ipv4_hdr *ip4;
1032 : : uint16_t sport, dport;
1033 : : size_t ctx_len;
1034 : : int ret;
1035 : :
1036 : : ctl = &out_sa->common_sa.ctl;
1037 : :
1038 [ # # ]: 0 : if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AUTH)
1039 : : auth_xform = crypto_xform;
1040 : : else
1041 : 0 : auth_xform = crypto_xform->next;
1042 : :
1043 : 0 : ret = on_fill_ipsec_common_sa(ipsec, crypto_xform, &out_sa->common_sa);
1044 [ # # ]: 0 : if (ret)
1045 : : return ret;
1046 : :
1047 [ # # ]: 0 : if (ctl->enc_type == ROC_IE_SA_ENC_AES_GCM || ctl->enc_type == ROC_IE_SA_ENC_AES_CCM ||
1048 [ # # # # ]: 0 : ctl->auth_type == ROC_IE_SA_AUTH_NULL || ctl->auth_type == ROC_IE_SA_AUTH_AES_GMAC) {
1049 : 0 : template = &out_sa->aes_gcm.template;
1050 : 0 : ctx_len = offsetof(struct roc_ie_on_outb_sa, aes_gcm.template);
1051 : : } else {
1052 [ # # # # ]: 0 : switch (ctl->auth_type) {
1053 : 0 : case ROC_IE_SA_AUTH_MD5:
1054 : : case ROC_IE_SA_AUTH_SHA1:
1055 : 0 : template = &out_sa->sha1.template;
1056 : : ctx_len = offsetof(struct roc_ie_on_outb_sa, sha1.template);
1057 : 0 : break;
1058 : 0 : case ROC_IE_SA_AUTH_SHA2_256:
1059 : : case ROC_IE_SA_AUTH_SHA2_384:
1060 : : case ROC_IE_SA_AUTH_SHA2_512:
1061 : 0 : template = &out_sa->sha2.template;
1062 : : ctx_len = offsetof(struct roc_ie_on_outb_sa, sha2.template);
1063 : 0 : break;
1064 : 0 : case ROC_IE_SA_AUTH_AES_XCBC_128:
1065 : 0 : template = &out_sa->aes_xcbc.template;
1066 : : ctx_len = offsetof(struct roc_ie_on_outb_sa, aes_xcbc.template);
1067 : 0 : break;
1068 : 0 : default:
1069 : 0 : plt_err("Unsupported auth algorithm");
1070 : 0 : return -EINVAL;
1071 : : }
1072 : : }
1073 : :
1074 : : ip4 = (struct rte_ipv4_hdr *)&template->ip4.ipv4_hdr;
1075 : :
1076 : : sport = 4500;
1077 : : dport = 4500;
1078 : :
1079 : : /* If custom port values are provided, Overwrite default port values. */
1080 [ # # ]: 0 : if (ipsec->options.udp_encap) {
1081 : :
1082 [ # # ]: 0 : if (ipsec->udp.sport)
1083 : : sport = ipsec->udp.sport;
1084 : :
1085 [ # # ]: 0 : if (ipsec->udp.dport)
1086 : : dport = ipsec->udp.dport;
1087 : :
1088 : 0 : ip4->next_proto_id = IPPROTO_UDP;
1089 [ # # ]: 0 : template->ip4.udp_src = rte_be_to_cpu_16(sport);
1090 [ # # ]: 0 : template->ip4.udp_dst = rte_be_to_cpu_16(dport);
1091 : : } else {
1092 [ # # ]: 0 : if (ipsec->proto == RTE_SECURITY_IPSEC_SA_PROTO_AH)
1093 : 0 : ip4->next_proto_id = IPPROTO_AH;
1094 : : else
1095 : 0 : ip4->next_proto_id = IPPROTO_ESP;
1096 : : }
1097 : :
1098 [ # # ]: 0 : if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
1099 [ # # ]: 0 : if (ipsec->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
1100 : : uint16_t frag_off = 0;
1101 : :
1102 : 0 : ctx_len += sizeof(template->ip4);
1103 : :
1104 : 0 : ip4->version_ihl = RTE_IPV4_VHL_DEF;
1105 [ # # ]: 0 : ip4->time_to_live = ipsec->tunnel.ipv4.ttl ?
1106 : : ipsec->tunnel.ipv4.ttl :
1107 : : 0x40;
1108 : 0 : ip4->type_of_service |= (ipsec->tunnel.ipv4.dscp << 2);
1109 [ # # ]: 0 : if (ipsec->tunnel.ipv4.df)
1110 : : frag_off |= RTE_IPV4_HDR_DF_FLAG;
1111 [ # # ]: 0 : ip4->fragment_offset = rte_cpu_to_be_16(frag_off);
1112 : :
1113 : 0 : memcpy(&ip4->src_addr, &ipsec->tunnel.ipv4.src_ip,
1114 : : sizeof(struct in_addr));
1115 : 0 : memcpy(&ip4->dst_addr, &ipsec->tunnel.ipv4.dst_ip,
1116 : : sizeof(struct in_addr));
1117 [ # # ]: 0 : } else if (ipsec->tunnel.type ==
1118 : : RTE_SECURITY_IPSEC_TUNNEL_IPV6) {
1119 : 0 : ctx_len += sizeof(template->ip6);
1120 : :
1121 : : ip6 = (struct rte_ipv6_hdr *)&template->ip6.ipv6_hdr;
1122 [ # # ]: 0 : if (ipsec->options.udp_encap) {
1123 : 0 : ip6->proto = IPPROTO_UDP;
1124 [ # # ]: 0 : template->ip6.udp_src = rte_be_to_cpu_16(sport);
1125 [ # # ]: 0 : template->ip6.udp_dst = rte_be_to_cpu_16(dport);
1126 : : } else {
1127 [ # # ]: 0 : ip6->proto = (ipsec->proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP) ?
1128 : : IPPROTO_ESP :
1129 : : IPPROTO_AH;
1130 : : }
1131 : 0 : ip6->vtc_flow =
1132 [ # # ]: 0 : rte_cpu_to_be_32(0x60000000 |
1133 : : ((ipsec->tunnel.ipv6.dscp
1134 : : << RTE_IPV6_HDR_TC_SHIFT) &
1135 : : RTE_IPV6_HDR_TC_MASK) |
1136 : : ((ipsec->tunnel.ipv6.flabel
1137 : : << RTE_IPV6_HDR_FL_SHIFT) &
1138 : : RTE_IPV6_HDR_FL_MASK));
1139 [ # # ]: 0 : ip6->hop_limits = ipsec->tunnel.ipv6.hlimit ?
1140 : : ipsec->tunnel.ipv6.hlimit :
1141 : : 0x40;
1142 : 0 : ip6->src_addr = ipsec->tunnel.ipv6.src_addr;
1143 : 0 : ip6->dst_addr = ipsec->tunnel.ipv6.dst_addr;
1144 : : }
1145 : : } else
1146 : 0 : ctx_len += sizeof(template->ip4);
1147 : :
1148 : 0 : ctx_len = RTE_ALIGN_CEIL(ctx_len, 8);
1149 : :
1150 [ # # ]: 0 : if (crypto_xform->type != RTE_CRYPTO_SYM_XFORM_AEAD) {
1151 : 0 : uint8_t *hmac_opad_ipad = (uint8_t *)&out_sa->sha2;
1152 : :
1153 [ # # ]: 0 : if (auth_xform->auth.algo == RTE_CRYPTO_AUTH_AES_XCBC_MAC) {
1154 : 0 : const uint8_t *auth_key = auth_xform->auth.key.data;
1155 : :
1156 : 0 : roc_aes_xcbc_key_derive(auth_key, hmac_opad_ipad);
1157 [ # # ]: 0 : } else if (auth_xform->auth.algo != RTE_CRYPTO_AUTH_NULL) {
1158 : 0 : roc_se_hmac_opad_ipad_gen(
1159 : 0 : out_sa->common_sa.ctl.auth_type, auth_xform->auth.key.data,
1160 : 0 : auth_xform->auth.key.length, &hmac_opad_ipad[0], ROC_SE_IPSEC);
1161 : : }
1162 : : }
1163 : :
1164 : 0 : return ctx_len;
1165 : : }
1166 : :
1167 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_on_ipsec_inb_sa_create)
1168 : : int
1169 : 0 : cnxk_on_ipsec_inb_sa_create(struct rte_security_ipsec_xform *ipsec,
1170 : : struct rte_crypto_sym_xform *crypto_xform,
1171 : : struct roc_ie_on_inb_sa *in_sa)
1172 : : {
1173 : : struct rte_crypto_sym_xform *auth_xform = crypto_xform;
1174 : : const uint8_t *auth_key;
1175 : : int auth_key_len = 0;
1176 : : size_t ctx_len = 0;
1177 : : int ret;
1178 : :
1179 : 0 : ret = on_fill_ipsec_common_sa(ipsec, crypto_xform, &in_sa->common_sa);
1180 [ # # ]: 0 : if (ret)
1181 : : return ret;
1182 : :
1183 [ # # ]: 0 : if (crypto_xform->type != RTE_CRYPTO_SYM_XFORM_AEAD &&
1184 [ # # # # ]: 0 : crypto_xform->auth.algo == RTE_CRYPTO_AUTH_NULL && ipsec->replay_win_sz) {
1185 : 0 : plt_err("anti-replay can't be supported with integrity service disabled");
1186 : 0 : return -EINVAL;
1187 : : }
1188 [ # # ]: 0 : if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD ||
1189 [ # # # # ]: 0 : auth_xform->auth.algo == RTE_CRYPTO_AUTH_NULL ||
1190 : : auth_xform->auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
1191 : : ctx_len = offsetof(struct roc_ie_on_inb_sa, sha1_or_gcm.hmac_key[0]);
1192 : : } else {
1193 : 0 : uint8_t *hmac_opad_ipad = (uint8_t *)&in_sa->sha2;
1194 : 0 : auth_key = auth_xform->auth.key.data;
1195 : 0 : auth_key_len = auth_xform->auth.key.length;
1196 : :
1197 [ # # # # ]: 0 : switch (auth_xform->auth.algo) {
1198 : : case RTE_CRYPTO_AUTH_NULL:
1199 : : break;
1200 : 0 : case RTE_CRYPTO_AUTH_MD5_HMAC:
1201 : : case RTE_CRYPTO_AUTH_SHA1_HMAC:
1202 [ # # ]: 0 : if (auth_key_len > (int)sizeof(in_sa->sha1_or_gcm.hmac_key)) {
1203 : 0 : plt_err("Auth key len %d exceeds max %zu for algo %u", auth_key_len,
1204 : : sizeof(in_sa->sha1_or_gcm.hmac_key), auth_xform->auth.algo);
1205 : 0 : return -EINVAL;
1206 : : }
1207 : 0 : memcpy(in_sa->sha1_or_gcm.hmac_key, auth_key, auth_key_len);
1208 : : ctx_len = offsetof(struct roc_ie_on_inb_sa, sha1_or_gcm.selector);
1209 : 0 : break;
1210 : 0 : case RTE_CRYPTO_AUTH_SHA256_HMAC:
1211 : : case RTE_CRYPTO_AUTH_SHA384_HMAC:
1212 : : case RTE_CRYPTO_AUTH_SHA512_HMAC:
1213 [ # # ]: 0 : if (auth_key_len > (int)sizeof(in_sa->sha2.hmac_key)) {
1214 : 0 : plt_err("Auth key len %d exceeds max %zu for algo %u", auth_key_len,
1215 : : sizeof(in_sa->sha2.hmac_key), auth_xform->auth.algo);
1216 : 0 : return -EINVAL;
1217 : : }
1218 : 0 : memcpy(in_sa->sha2.hmac_key, auth_key, auth_key_len);
1219 : : ctx_len = offsetof(struct roc_ie_on_inb_sa, sha2.selector);
1220 : 0 : break;
1221 : 0 : case RTE_CRYPTO_AUTH_AES_XCBC_MAC:
1222 [ # # ]: 0 : if (auth_key_len > (int)sizeof(in_sa->aes_xcbc.key)) {
1223 : 0 : plt_err("Auth key len %d exceeds max %zu for algo %u", auth_key_len,
1224 : : sizeof(in_sa->aes_xcbc.key), auth_xform->auth.algo);
1225 : 0 : return -EINVAL;
1226 : : }
1227 : 0 : memcpy(in_sa->aes_xcbc.key, auth_key, auth_key_len);
1228 : : ctx_len = offsetof(struct roc_ie_on_inb_sa, aes_xcbc.selector);
1229 : 0 : break;
1230 : 0 : default:
1231 : 0 : plt_err("Unsupported auth algorithm %u", auth_xform->auth.algo);
1232 : 0 : return -ENOTSUP;
1233 : : }
1234 [ # # ]: 0 : if (auth_xform->auth.algo == RTE_CRYPTO_AUTH_AES_XCBC_MAC) {
1235 : 0 : const uint8_t *auth_key = auth_xform->auth.key.data;
1236 : :
1237 : 0 : roc_aes_xcbc_key_derive(auth_key, hmac_opad_ipad);
1238 [ # # ]: 0 : } else if (auth_xform->auth.algo != RTE_CRYPTO_AUTH_NULL) {
1239 : 0 : roc_se_hmac_opad_ipad_gen(
1240 : 0 : in_sa->common_sa.ctl.auth_type, auth_xform->auth.key.data,
1241 : 0 : auth_xform->auth.key.length, &hmac_opad_ipad[0], ROC_SE_IPSEC);
1242 : : }
1243 : : }
1244 : :
1245 : 0 : return ctx_len;
1246 : : }
1247 : :
1248 : : static int
1249 : 0 : ow_ipsec_sa_common_param_fill(union roc_ow_ipsec_sa_word2 *w2, uint8_t *cipher_key,
1250 : : uint8_t *salt_key, uint8_t *hmac_opad_ipad,
1251 : : struct rte_security_ipsec_xform *ipsec_xfrm,
1252 : : struct rte_crypto_sym_xform *crypto_xfrm)
1253 : : {
1254 : : struct rte_crypto_sym_xform *auth_xfrm, *cipher_xfrm;
1255 : : const uint8_t *key = NULL;
1256 : : uint8_t ccm_flag = 0;
1257 : : uint32_t *tmp_salt;
1258 : : uint64_t *tmp_key;
1259 : : int i, length = 0;
1260 : :
1261 : : /* Set direction */
1262 [ # # ]: 0 : if (ipsec_xfrm->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
1263 : 0 : w2->s.dir = ROC_IE_SA_DIR_OUTBOUND;
1264 : : else
1265 : 0 : w2->s.dir = ROC_IE_SA_DIR_INBOUND;
1266 : :
1267 [ # # ]: 0 : if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
1268 : : auth_xfrm = crypto_xfrm;
1269 : 0 : cipher_xfrm = crypto_xfrm->next;
1270 : : } else {
1271 : : cipher_xfrm = crypto_xfrm;
1272 : 0 : auth_xfrm = crypto_xfrm->next;
1273 : : }
1274 : :
1275 : : /* Set protocol - ESP vs AH */
1276 [ # # # ]: 0 : switch (ipsec_xfrm->proto) {
1277 : 0 : case RTE_SECURITY_IPSEC_SA_PROTO_ESP:
1278 : 0 : w2->s.protocol = ROC_IE_SA_PROTOCOL_ESP;
1279 : 0 : break;
1280 : 0 : case RTE_SECURITY_IPSEC_SA_PROTO_AH:
1281 : 0 : w2->s.protocol = ROC_IE_SA_PROTOCOL_AH;
1282 : 0 : break;
1283 : : default:
1284 : : return -EINVAL;
1285 : : }
1286 : :
1287 : : /* Set mode - transport vs tunnel */
1288 [ # # # ]: 0 : switch (ipsec_xfrm->mode) {
1289 : 0 : case RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT:
1290 : 0 : w2->s.mode = ROC_IE_SA_MODE_TRANSPORT;
1291 : 0 : break;
1292 : 0 : case RTE_SECURITY_IPSEC_SA_MODE_TUNNEL:
1293 : 0 : w2->s.mode = ROC_IE_SA_MODE_TUNNEL;
1294 : 0 : break;
1295 : : default:
1296 : : return -EINVAL;
1297 : : }
1298 : :
1299 : : /* Set encryption algorithm */
1300 [ # # ]: 0 : if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
1301 : 0 : key = crypto_xfrm->aead.key.data;
1302 : 0 : length = crypto_xfrm->aead.key.length;
1303 : :
1304 [ # # # ]: 0 : switch (crypto_xfrm->aead.algo) {
1305 : 0 : case RTE_CRYPTO_AEAD_AES_GCM:
1306 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_AES_GCM;
1307 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_NULL;
1308 [ # # ]: 0 : memcpy(salt_key, &ipsec_xfrm->salt, 4);
1309 : : tmp_salt = (uint32_t *)salt_key;
1310 [ # # ]: 0 : *tmp_salt = rte_be_to_cpu_32(*tmp_salt);
1311 : 0 : break;
1312 : 0 : case RTE_CRYPTO_AEAD_AES_CCM:
1313 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_AES_CCM;
1314 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_NULL;
1315 : : ccm_flag = 0x07 & ~ROC_CPT_AES_CCM_CTR_LEN;
1316 : 0 : *salt_key = ccm_flag;
1317 [ # # ]: 0 : memcpy(PLT_PTR_ADD(salt_key, 1), &ipsec_xfrm->salt, 3);
1318 : : tmp_salt = (uint32_t *)salt_key;
1319 [ # # ]: 0 : *tmp_salt = rte_be_to_cpu_32(*tmp_salt);
1320 : 0 : break;
1321 : : default:
1322 : : return -ENOTSUP;
1323 : : }
1324 : : } else {
1325 [ # # ]: 0 : if (cipher_xfrm != NULL) {
1326 [ # # # # : 0 : switch (cipher_xfrm->cipher.algo) {
# ]
1327 : 0 : case RTE_CRYPTO_CIPHER_NULL:
1328 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_NULL;
1329 : 0 : break;
1330 : 0 : case RTE_CRYPTO_CIPHER_AES_CBC:
1331 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_AES_CBC;
1332 : 0 : break;
1333 : 0 : case RTE_CRYPTO_CIPHER_AES_CTR:
1334 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_AES_CTR;
1335 [ # # ]: 0 : memcpy(salt_key, &ipsec_xfrm->salt, 4);
1336 : : tmp_salt = (uint32_t *)salt_key;
1337 [ # # ]: 0 : *tmp_salt = rte_be_to_cpu_32(*tmp_salt);
1338 : 0 : break;
1339 : 0 : case RTE_CRYPTO_CIPHER_3DES_CBC:
1340 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_3DES_CBC;
1341 : 0 : break;
1342 : : default:
1343 : : return -ENOTSUP;
1344 : : }
1345 : :
1346 : 0 : key = cipher_xfrm->cipher.key.data;
1347 : 0 : length = cipher_xfrm->cipher.key.length;
1348 : : }
1349 : :
1350 [ # # # # : 0 : switch (auth_xfrm->auth.algo) {
# # # # ]
1351 : 0 : case RTE_CRYPTO_AUTH_NULL:
1352 [ # # # # ]: 0 : if (w2->s.dir == ROC_IE_SA_DIR_INBOUND && ipsec_xfrm->replay_win_sz) {
1353 : 0 : plt_err("anti-replay can't be supported with integrity service disabled");
1354 : 0 : return -EINVAL;
1355 : : }
1356 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_NULL;
1357 : 0 : break;
1358 : 0 : case RTE_CRYPTO_AUTH_SHA1_HMAC:
1359 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_SHA1;
1360 : 0 : break;
1361 : 0 : case RTE_CRYPTO_AUTH_SHA256_HMAC:
1362 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_SHA2_256;
1363 : 0 : break;
1364 : 0 : case RTE_CRYPTO_AUTH_SHA384_HMAC:
1365 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_SHA2_384;
1366 : 0 : break;
1367 : 0 : case RTE_CRYPTO_AUTH_SHA512_HMAC:
1368 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_SHA2_512;
1369 : 0 : break;
1370 : 0 : case RTE_CRYPTO_AUTH_AES_XCBC_MAC:
1371 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_AES_XCBC_128;
1372 : 0 : break;
1373 : 0 : case RTE_CRYPTO_AUTH_AES_GMAC:
1374 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_AES_GMAC;
1375 : 0 : key = auth_xfrm->auth.key.data;
1376 : 0 : length = auth_xfrm->auth.key.length;
1377 [ # # ]: 0 : memcpy(salt_key, &ipsec_xfrm->salt, 4);
1378 : : tmp_salt = (uint32_t *)salt_key;
1379 [ # # ]: 0 : *tmp_salt = rte_be_to_cpu_32(*tmp_salt);
1380 : 0 : break;
1381 : : default:
1382 : : return -ENOTSUP;
1383 : : }
1384 : :
1385 [ # # ]: 0 : if (auth_xfrm->auth.algo == RTE_CRYPTO_AUTH_AES_XCBC_MAC) {
1386 : 0 : const uint8_t *auth_key = auth_xfrm->auth.key.data;
1387 : 0 : roc_aes_xcbc_key_derive(auth_key, hmac_opad_ipad);
1388 : : } else {
1389 : 0 : roc_se_hmac_opad_ipad_gen(w2->s.auth_type, auth_xfrm->auth.key.data,
1390 : 0 : auth_xfrm->auth.key.length, &hmac_opad_ipad[0],
1391 : : ROC_SE_IPSEC);
1392 : : }
1393 : :
1394 : : tmp_key = (uint64_t *)hmac_opad_ipad;
1395 [ # # ]: 0 : for (i = 0; i < (int)(ROC_CTX_MAX_OPAD_IPAD_LEN / sizeof(uint64_t)); i++)
1396 [ # # ]: 0 : tmp_key[i] = rte_be_to_cpu_64(tmp_key[i]);
1397 : : }
1398 : :
1399 : : /* Set encapsulation type */
1400 [ # # ]: 0 : if (ipsec_xfrm->options.udp_encap)
1401 : 0 : w2->s.encap_type = ROC_IE_OT_SA_ENCAP_UDP;
1402 : :
1403 : 0 : w2->s.spi = ipsec_xfrm->spi;
1404 : :
1405 [ # # ]: 0 : if (key != NULL && length != 0) {
1406 : : /* Validate key length and set AES key len before copy to avoid overflow */
1407 : 0 : if (w2->s.enc_type == ROC_IE_SA_ENC_AES_CBC ||
1408 : : w2->s.enc_type == ROC_IE_SA_ENC_AES_CTR ||
1409 [ # # ]: 0 : w2->s.enc_type == ROC_IE_SA_ENC_AES_GCM ||
1410 : 0 : w2->s.enc_type == ROC_IE_SA_ENC_AES_CCM ||
1411 [ # # ]: 0 : w2->s.auth_type == ROC_IE_SA_AUTH_AES_GMAC) {
1412 [ # # # # ]: 0 : switch (length) {
1413 : 0 : case ROC_CPT_AES128_KEY_LEN:
1414 : 0 : w2->s.aes_key_len = ROC_IE_SA_AES_KEY_LEN_128;
1415 : 0 : break;
1416 : 0 : case ROC_CPT_AES192_KEY_LEN:
1417 : 0 : w2->s.aes_key_len = ROC_IE_SA_AES_KEY_LEN_192;
1418 : 0 : break;
1419 : 0 : case ROC_CPT_AES256_KEY_LEN:
1420 : 0 : w2->s.aes_key_len = ROC_IE_SA_AES_KEY_LEN_256;
1421 : 0 : break;
1422 : 0 : default:
1423 : 0 : plt_err("Invalid AES key length");
1424 : 0 : return -EINVAL;
1425 : : }
1426 : : }
1427 [ # # # # ]: 0 : if (w2->s.enc_type == ROC_IE_SA_ENC_DES_CBC && length != ROC_CPT_DES_KEY_LEN) {
1428 : 0 : plt_err("Invalid DES key length");
1429 : 0 : return -EINVAL;
1430 : : }
1431 [ # # # # ]: 0 : if (w2->s.enc_type == ROC_IE_SA_ENC_3DES_CBC && length != ROC_CPT_DES3_KEY_LEN) {
1432 : 0 : plt_err("Invalid 3DES key length");
1433 : 0 : return -EINVAL;
1434 : : }
1435 : : /* Copy encryption key */
1436 : 0 : memcpy(cipher_key, key, length);
1437 : : tmp_key = (uint64_t *)cipher_key;
1438 [ # # ]: 0 : for (i = 0; i < (int)(ROC_CTX_MAX_CKEY_LEN / sizeof(uint64_t)); i++)
1439 [ # # ]: 0 : tmp_key[i] = rte_be_to_cpu_64(tmp_key[i]);
1440 : : }
1441 : :
1442 [ # # # # ]: 0 : if (ipsec_xfrm->life.packets_soft_limit != 0 || ipsec_xfrm->life.packets_hard_limit != 0) {
1443 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_soft_limit != 0 ||
1444 [ # # ]: 0 : ipsec_xfrm->life.bytes_hard_limit != 0) {
1445 : 0 : plt_err("Expiry tracking with both packets & bytes is not supported");
1446 : 0 : return -EINVAL;
1447 : : }
1448 : 0 : w2->s.life_unit = ROC_IE_OT_SA_LIFE_UNIT_PKTS;
1449 : : }
1450 : :
1451 [ # # # # ]: 0 : if (ipsec_xfrm->life.bytes_soft_limit != 0 || ipsec_xfrm->life.bytes_hard_limit != 0) {
1452 [ # # ]: 0 : if (ipsec_xfrm->life.packets_soft_limit != 0 ||
1453 [ # # ]: 0 : ipsec_xfrm->life.packets_hard_limit != 0) {
1454 : 0 : plt_err("Expiry tracking with both packets & bytes is not supported");
1455 : 0 : return -EINVAL;
1456 : : }
1457 : 0 : w2->s.life_unit = ROC_IE_OT_SA_LIFE_UNIT_OCTETS;
1458 : : }
1459 : :
1460 : : return 0;
1461 : : }
1462 : :
1463 : : static size_t
1464 : : ow_ipsec_inb_ctx_size(struct roc_ow_ipsec_inb_sa *sa)
1465 : : {
1466 : : size_t size;
1467 : :
1468 : : /* Variable based on Anti-replay Window */
1469 : : size = offsetof(struct roc_ow_ipsec_inb_sa, ctx) +
1470 : : offsetof(struct roc_ow_ipsec_inb_ctx_update_reg, ar_winbits);
1471 : :
1472 : 0 : if (sa->w0.s.ar_win)
1473 : 0 : size += (1 << (sa->w0.s.ar_win - 1)) * sizeof(uint64_t);
1474 : :
1475 : : return size;
1476 : : }
1477 : :
1478 : : static void
1479 : 0 : ow_ipsec_update_ipv6_addr_endianness(uint64_t *addr)
1480 : : {
1481 [ # # ]: 0 : *addr = rte_be_to_cpu_64(*addr);
1482 : : addr++;
1483 [ # # ]: 0 : *addr = rte_be_to_cpu_64(*addr);
1484 : 0 : }
1485 : :
1486 : : static int
1487 : 0 : ow_ipsec_inb_tunnel_hdr_fill(struct roc_ow_ipsec_inb_sa *sa,
1488 : : struct rte_security_ipsec_xform *ipsec_xfrm)
1489 : : {
1490 : : struct rte_security_ipsec_tunnel_param *tunnel;
1491 : :
1492 [ # # ]: 0 : if (ipsec_xfrm->mode != RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
1493 : : return 0;
1494 : :
1495 [ # # ]: 0 : if (ipsec_xfrm->options.tunnel_hdr_verify == 0)
1496 : : return 0;
1497 : :
1498 : : tunnel = &ipsec_xfrm->tunnel;
1499 : :
1500 [ # # # ]: 0 : switch (tunnel->type) {
1501 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_IPV4:
1502 : 0 : sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_4;
1503 [ # # ]: 0 : memcpy(&sa->outer_hdr.ipv4.src_addr, &tunnel->ipv4.src_ip, sizeof(struct in_addr));
1504 : 0 : memcpy(&sa->outer_hdr.ipv4.dst_addr, &tunnel->ipv4.dst_ip, sizeof(struct in_addr));
1505 : :
1506 : : /* IP Source and Dest are in LE/CPU endian */
1507 [ # # ]: 0 : sa->outer_hdr.ipv4.src_addr = rte_be_to_cpu_32(sa->outer_hdr.ipv4.src_addr);
1508 [ # # ]: 0 : sa->outer_hdr.ipv4.dst_addr = rte_be_to_cpu_32(sa->outer_hdr.ipv4.dst_addr);
1509 : :
1510 : 0 : break;
1511 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_IPV6:
1512 : 0 : sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_6;
1513 : 0 : memcpy(&sa->outer_hdr.ipv6.src_addr, &tunnel->ipv6.src_addr,
1514 : : sizeof(struct in6_addr));
1515 : 0 : memcpy(&sa->outer_hdr.ipv6.dst_addr, &tunnel->ipv6.dst_addr,
1516 : : sizeof(struct in6_addr));
1517 : :
1518 : : /* IP Source and Dest are in LE/CPU endian */
1519 : 0 : ow_ipsec_update_ipv6_addr_endianness((uint64_t *)&sa->outer_hdr.ipv6.src_addr);
1520 : 0 : ow_ipsec_update_ipv6_addr_endianness((uint64_t *)&sa->outer_hdr.ipv6.dst_addr);
1521 : :
1522 : 0 : break;
1523 : : default:
1524 : : return -EINVAL;
1525 : : }
1526 : :
1527 [ # # # ]: 0 : switch (ipsec_xfrm->options.tunnel_hdr_verify) {
1528 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_VERIFY_DST_ADDR:
1529 : 0 : sa->w2.s.ip_hdr_verify = ROC_IE_OT_SA_IP_HDR_VERIFY_DST_ADDR;
1530 : 0 : break;
1531 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_VERIFY_SRC_DST_ADDR:
1532 : 0 : sa->w2.s.ip_hdr_verify = ROC_IE_OT_SA_IP_HDR_VERIFY_SRC_DST_ADDR;
1533 : 0 : break;
1534 : : default:
1535 : : return -ENOTSUP;
1536 : : }
1537 : :
1538 : : return 0;
1539 : : }
1540 : :
1541 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ow_ipsec_inb_sa_fill)
1542 : : int
1543 : 0 : cnxk_ow_ipsec_inb_sa_fill(struct roc_ow_ipsec_inb_sa *sa,
1544 : : struct rte_security_ipsec_xform *ipsec_xfrm,
1545 : : struct rte_crypto_sym_xform *crypto_xfrm, uint8_t ctx_ilen)
1546 : : {
1547 : : uint16_t sport = 4500, dport = 4500;
1548 : : union roc_ow_ipsec_sa_word2 w2;
1549 : : uint32_t replay_win_sz;
1550 : : size_t offset;
1551 : : int rc;
1552 : :
1553 : : /* Initialize the SA */
1554 : 0 : roc_ow_ipsec_inb_sa_init(sa);
1555 : :
1556 : 0 : w2.u64 = 0;
1557 : 0 : rc = ow_ipsec_sa_common_param_fill(&w2, sa->cipher_key, sa->w8.s.salt, sa->hmac_opad_ipad,
1558 : : ipsec_xfrm, crypto_xfrm);
1559 [ # # ]: 0 : if (rc)
1560 : : return rc;
1561 : :
1562 : : /* Updata common word2 data */
1563 : 0 : sa->w2.u64 = w2.u64;
1564 : :
1565 : : /* Only support power-of-two window sizes supported */
1566 : 0 : replay_win_sz = ipsec_xfrm->replay_win_sz;
1567 [ # # ]: 0 : if (replay_win_sz) {
1568 [ # # ]: 0 : if (!rte_is_power_of_2(replay_win_sz) || replay_win_sz > ROC_AR_WIN_SIZE_MAX)
1569 : : return -ENOTSUP;
1570 : :
1571 : 0 : sa->w0.s.ar_win = rte_log2_u32(replay_win_sz) - 5;
1572 : : }
1573 : :
1574 : 0 : rc = ow_ipsec_inb_tunnel_hdr_fill(sa, ipsec_xfrm);
1575 [ # # ]: 0 : if (rc)
1576 : : return rc;
1577 : :
1578 : : /* Default options for pkt_out and pkt_fmt are with
1579 : : * second pass meta and no defrag.
1580 : : */
1581 : 0 : sa->w0.s.pkt_format = ROC_IE_OT_SA_PKT_FMT_META;
1582 : 0 : sa->w0.s.pkt_output = ROC_IE_OT_SA_PKT_OUTPUT_NO_FRAG;
1583 : 0 : sa->w0.s.pkind = ROC_IE_OT_CPT_PKIND;
1584 : :
1585 [ # # ]: 0 : if (ipsec_xfrm->options.ip_reassembly_en)
1586 : 0 : sa->w0.s.pkt_output = ROC_IE_OT_SA_PKT_OUTPUT_HW_BASED_DEFRAG;
1587 : :
1588 : : /* ESN */
1589 : 0 : sa->w2.s.esn_en = !!ipsec_xfrm->options.esn;
1590 [ # # ]: 0 : if (ipsec_xfrm->options.udp_encap) {
1591 [ # # ]: 0 : if (ipsec_xfrm->udp.sport)
1592 : : sport = ipsec_xfrm->udp.sport;
1593 : :
1594 [ # # ]: 0 : if (ipsec_xfrm->udp.dport)
1595 : : dport = ipsec_xfrm->udp.dport;
1596 : :
1597 : 0 : sa->w10.s.udp_src_port = sport;
1598 : 0 : sa->w10.s.udp_dst_port = dport;
1599 : : }
1600 : :
1601 [ # # ]: 0 : if (ipsec_xfrm->options.udp_ports_verify)
1602 : 0 : sa->w2.s.udp_ports_verify = 1;
1603 : :
1604 : : offset = offsetof(struct roc_ow_ipsec_inb_sa, ctx);
1605 : : /* Word offset for HW managed SA field */
1606 : 0 : sa->w0.s.hw_ctx_off = offset / 8;
1607 : : /* Context push size for inbound spans up to hw_ctx including
1608 : : * ar_base field, in 8b units
1609 : : */
1610 [ # # ]: 0 : sa->w0.s.ctx_push_size = sa->w0.s.hw_ctx_off + 1;
1611 : : /* Entire context size in 128B units */
1612 : 0 : sa->w0.s.ctx_size =
1613 : 0 : (PLT_ALIGN_CEIL(ow_ipsec_inb_ctx_size(sa), ROC_CTX_UNIT_128B) / ROC_CTX_UNIT_128B) -
1614 : : 1;
1615 : :
1616 [ # # ]: 0 : if (sa->w0.s.ctx_size < ctx_ilen)
1617 : 0 : sa->w0.s.ctx_size = ctx_ilen;
1618 : :
1619 : : /**
1620 : : * CPT MC triggers expiry when counter value changes from 2 to 1. To
1621 : : * mitigate this behaviour add 1 to the life counter values provided.
1622 : : */
1623 : :
1624 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_soft_limit) {
1625 : 0 : sa->ctx.soft_life = ipsec_xfrm->life.bytes_soft_limit + 1;
1626 : 0 : sa->w0.s.soft_life_dec = 1;
1627 : : }
1628 : :
1629 [ # # ]: 0 : if (ipsec_xfrm->life.packets_soft_limit) {
1630 : 0 : sa->ctx.soft_life = ipsec_xfrm->life.packets_soft_limit + 1;
1631 : 0 : sa->w0.s.soft_life_dec = 1;
1632 : : }
1633 : :
1634 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_hard_limit) {
1635 : 0 : sa->ctx.hard_life = ipsec_xfrm->life.bytes_hard_limit + 1;
1636 : 0 : sa->w0.s.hard_life_dec = 1;
1637 : : }
1638 : :
1639 [ # # ]: 0 : if (ipsec_xfrm->life.packets_hard_limit) {
1640 : 0 : sa->ctx.hard_life = ipsec_xfrm->life.packets_hard_limit + 1;
1641 : 0 : sa->w0.s.hard_life_dec = 1;
1642 : : }
1643 : :
1644 : : rte_wmb();
1645 : :
1646 : : /* Enable SA */
1647 : 0 : sa->w2.s.valid = 1;
1648 : 0 : return 0;
1649 : : }
1650 : :
1651 : : RTE_EXPORT_INTERNAL_SYMBOL(cnxk_ow_ipsec_outb_sa_fill)
1652 : : int
1653 : 0 : cnxk_ow_ipsec_outb_sa_fill(struct roc_ow_ipsec_outb_sa *sa,
1654 : : struct rte_security_ipsec_xform *ipsec_xfrm,
1655 : : struct rte_crypto_sym_xform *crypto_xfrm, uint8_t ctx_ilen)
1656 : : {
1657 : : struct rte_security_ipsec_tunnel_param *tunnel = &ipsec_xfrm->tunnel;
1658 : : uint16_t sport = 4500, dport = 4500;
1659 : : union roc_ow_ipsec_sa_word2 w2;
1660 : : size_t offset;
1661 : : int rc;
1662 : :
1663 : : /* Initialize the SA */
1664 : 0 : roc_ow_ipsec_outb_sa_init(sa);
1665 : :
1666 : 0 : w2.u64 = 0;
1667 : 0 : rc = ow_ipsec_sa_common_param_fill(&w2, sa->cipher_key, sa->iv.s.salt, sa->hmac_opad_ipad,
1668 : : ipsec_xfrm, crypto_xfrm);
1669 [ # # ]: 0 : if (rc)
1670 : : return rc;
1671 : :
1672 : : /* Update common word2 data */
1673 : 0 : sa->w2.u64 = w2.u64;
1674 : :
1675 [ # # ]: 0 : if (ipsec_xfrm->mode != RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
1676 : 0 : goto skip_tunnel_info;
1677 : :
1678 : : /* Tunnel header info */
1679 [ # # # ]: 0 : switch (tunnel->type) {
1680 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_IPV4:
1681 : 0 : sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_4;
1682 [ # # ]: 0 : memcpy(&sa->outer_hdr.ipv4.src_addr, &tunnel->ipv4.src_ip, sizeof(struct in_addr));
1683 : 0 : memcpy(&sa->outer_hdr.ipv4.dst_addr, &tunnel->ipv4.dst_ip, sizeof(struct in_addr));
1684 : :
1685 : : /* IP Source and Dest seems to be in LE/CPU endian */
1686 [ # # ]: 0 : sa->outer_hdr.ipv4.src_addr = rte_be_to_cpu_32(sa->outer_hdr.ipv4.src_addr);
1687 [ # # ]: 0 : sa->outer_hdr.ipv4.dst_addr = rte_be_to_cpu_32(sa->outer_hdr.ipv4.dst_addr);
1688 : :
1689 : : /* Outer header DF bit source */
1690 [ # # ]: 0 : if (!ipsec_xfrm->options.copy_df) {
1691 : 0 : sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src = ROC_IE_OT_SA_COPY_FROM_SA;
1692 : 0 : sa->w10.s.ipv4_df_or_ipv6_flw_lbl = tunnel->ipv4.df;
1693 : : } else {
1694 : 0 : sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
1695 : : ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
1696 : : }
1697 : :
1698 : : /* Outer header DSCP source */
1699 [ # # ]: 0 : if (!ipsec_xfrm->options.copy_dscp) {
1700 : 0 : sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_SA;
1701 : 0 : sa->w10.s.dscp = tunnel->ipv4.dscp;
1702 : : } else {
1703 : 0 : sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
1704 : : }
1705 : : break;
1706 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_IPV6:
1707 : 0 : sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_6;
1708 : 0 : memcpy(&sa->outer_hdr.ipv6.src_addr, &tunnel->ipv6.src_addr,
1709 : : sizeof(struct in6_addr));
1710 : 0 : memcpy(&sa->outer_hdr.ipv6.dst_addr, &tunnel->ipv6.dst_addr,
1711 : : sizeof(struct in6_addr));
1712 : :
1713 : : /* IP Source and Dest are in LE/CPU endian */
1714 : 0 : ow_ipsec_update_ipv6_addr_endianness((uint64_t *)&sa->outer_hdr.ipv6.src_addr);
1715 : 0 : ow_ipsec_update_ipv6_addr_endianness((uint64_t *)&sa->outer_hdr.ipv6.dst_addr);
1716 : :
1717 : : /* Outer header flow label source */
1718 [ # # ]: 0 : if (!ipsec_xfrm->options.copy_flabel) {
1719 : 0 : sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src = ROC_IE_OT_SA_COPY_FROM_SA;
1720 : :
1721 : 0 : sa->w10.s.ipv4_df_or_ipv6_flw_lbl = tunnel->ipv6.flabel;
1722 : : } else {
1723 : 0 : sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
1724 : : ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
1725 : : }
1726 : :
1727 : : /* Outer header DSCP source */
1728 [ # # ]: 0 : if (!ipsec_xfrm->options.copy_dscp) {
1729 : 0 : sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_SA;
1730 : 0 : sa->w10.s.dscp = tunnel->ipv6.dscp;
1731 : : } else {
1732 : 0 : sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
1733 : : }
1734 : : break;
1735 : : default:
1736 : : return -EINVAL;
1737 : : }
1738 : :
1739 : 0 : skip_tunnel_info:
1740 : : /* ESN */
1741 : 0 : sa->w0.s.esn_en = !!ipsec_xfrm->options.esn;
1742 : :
1743 [ # # ]: 0 : if (ipsec_xfrm->esn.value)
1744 : 0 : sa->ctx.esn_val = ipsec_xfrm->esn.value - 1;
1745 : :
1746 [ # # ]: 0 : if (ipsec_xfrm->options.udp_encap) {
1747 [ # # ]: 0 : if (ipsec_xfrm->udp.sport)
1748 : : sport = ipsec_xfrm->udp.sport;
1749 : :
1750 [ # # ]: 0 : if (ipsec_xfrm->udp.dport)
1751 : : dport = ipsec_xfrm->udp.dport;
1752 : :
1753 : 0 : sa->w10.s.udp_src_port = sport;
1754 : 0 : sa->w10.s.udp_dst_port = dport;
1755 : : }
1756 : :
1757 : : offset = offsetof(struct roc_ow_ipsec_outb_sa, ctx);
1758 : : /* Word offset for HW managed SA field */
1759 : 0 : sa->w0.s.hw_ctx_off = offset / 8;
1760 : :
1761 : : /* Context push size is up to err ctl in HW ctx */
1762 : 0 : sa->w0.s.ctx_push_size = sa->w0.s.hw_ctx_off + 1;
1763 : :
1764 : : /* Entire context size in 128B units */
1765 : : offset = sizeof(struct roc_ow_ipsec_outb_sa);
1766 : 0 : sa->w0.s.ctx_size = (PLT_ALIGN_CEIL(offset, ROC_CTX_UNIT_128B) / ROC_CTX_UNIT_128B) - 1;
1767 : :
1768 : : /* IPID gen */
1769 : 0 : sa->w2.s.ipid_gen = 1;
1770 : :
1771 [ # # ]: 0 : if (sa->w0.s.ctx_size < ctx_ilen)
1772 : 0 : sa->w0.s.ctx_size = ctx_ilen;
1773 : :
1774 : : /**
1775 : : * CPT MC triggers expiry when counter value changes from 2 to 1. To
1776 : : * mitigate this behaviour add 1 to the life counter values provided.
1777 : : */
1778 : :
1779 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_soft_limit) {
1780 : 0 : sa->ctx.soft_life = ipsec_xfrm->life.bytes_soft_limit + 1;
1781 : 0 : sa->w0.s.soft_life_dec = 1;
1782 : : }
1783 : :
1784 [ # # ]: 0 : if (ipsec_xfrm->life.packets_soft_limit) {
1785 : 0 : sa->ctx.soft_life = ipsec_xfrm->life.packets_soft_limit + 1;
1786 : 0 : sa->w0.s.soft_life_dec = 1;
1787 : : }
1788 : :
1789 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_hard_limit) {
1790 : 0 : sa->ctx.hard_life = ipsec_xfrm->life.bytes_hard_limit + 1;
1791 : 0 : sa->w0.s.hard_life_dec = 1;
1792 : : }
1793 : :
1794 [ # # ]: 0 : if (ipsec_xfrm->life.packets_hard_limit) {
1795 : 0 : sa->ctx.hard_life = ipsec_xfrm->life.packets_hard_limit + 1;
1796 : 0 : sa->w0.s.hard_life_dec = 1;
1797 : : }
1798 : :
1799 : : /* There are two words of CPT_CTX_HW_S for ucode to skip */
1800 : 0 : sa->w0.s.ctx_hdr_size = 1;
1801 : 0 : sa->w0.s.aop_valid = 1;
1802 : :
1803 : : rte_wmb();
1804 : :
1805 : : /* Enable SA */
1806 : 0 : sa->w2.s.valid = 1;
1807 : 0 : return 0;
1808 : : }
|