Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : :
5 : : #include <rte_udp.h>
6 : :
7 : : #include "cnxk_security.h"
8 : :
9 : : #include "roc_api.h"
10 : :
11 : : static int
12 : 0 : ot_ipsec_sa_common_param_fill(union roc_ot_ipsec_sa_word2 *w2, uint8_t *cipher_key,
13 : : uint8_t *salt_key, uint8_t *hmac_opad_ipad,
14 : : struct rte_security_ipsec_xform *ipsec_xfrm,
15 : : struct rte_crypto_sym_xform *crypto_xfrm)
16 : : {
17 : : struct rte_crypto_sym_xform *auth_xfrm, *cipher_xfrm;
18 : : const uint8_t *key = NULL;
19 : : uint8_t ccm_flag = 0;
20 : : uint32_t *tmp_salt;
21 : : uint64_t *tmp_key;
22 : : int i, length = 0;
23 : :
24 : : /* Set direction */
25 [ # # ]: 0 : if (ipsec_xfrm->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
26 : 0 : w2->s.dir = ROC_IE_SA_DIR_OUTBOUND;
27 : : else
28 : 0 : w2->s.dir = ROC_IE_SA_DIR_INBOUND;
29 : :
30 [ # # ]: 0 : if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
31 : : auth_xfrm = crypto_xfrm;
32 : 0 : cipher_xfrm = crypto_xfrm->next;
33 : : } else {
34 : : cipher_xfrm = crypto_xfrm;
35 : 0 : auth_xfrm = crypto_xfrm->next;
36 : : }
37 : :
38 : : /* Set protocol - ESP vs AH */
39 [ # # # ]: 0 : switch (ipsec_xfrm->proto) {
40 : 0 : case RTE_SECURITY_IPSEC_SA_PROTO_ESP:
41 : 0 : w2->s.protocol = ROC_IE_SA_PROTOCOL_ESP;
42 : 0 : break;
43 : 0 : case RTE_SECURITY_IPSEC_SA_PROTO_AH:
44 : 0 : w2->s.protocol = ROC_IE_SA_PROTOCOL_AH;
45 : 0 : break;
46 : : default:
47 : : return -EINVAL;
48 : : }
49 : :
50 : : /* Set mode - transport vs tunnel */
51 [ # # # ]: 0 : switch (ipsec_xfrm->mode) {
52 : 0 : case RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT:
53 : 0 : w2->s.mode = ROC_IE_SA_MODE_TRANSPORT;
54 : 0 : break;
55 : 0 : case RTE_SECURITY_IPSEC_SA_MODE_TUNNEL:
56 : 0 : w2->s.mode = ROC_IE_SA_MODE_TUNNEL;
57 : 0 : break;
58 : : default:
59 : : return -EINVAL;
60 : : }
61 : :
62 : : /* Set encryption algorithm */
63 [ # # ]: 0 : if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
64 : 0 : key = crypto_xfrm->aead.key.data;
65 : 0 : length = crypto_xfrm->aead.key.length;
66 : :
67 [ # # # ]: 0 : switch (crypto_xfrm->aead.algo) {
68 : 0 : case RTE_CRYPTO_AEAD_AES_GCM:
69 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_AES_GCM;
70 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_NULL;
71 [ # # ]: 0 : memcpy(salt_key, &ipsec_xfrm->salt, 4);
72 : : tmp_salt = (uint32_t *)salt_key;
73 [ # # ]: 0 : *tmp_salt = rte_be_to_cpu_32(*tmp_salt);
74 : 0 : break;
75 : 0 : case RTE_CRYPTO_AEAD_AES_CCM:
76 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_AES_CCM;
77 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_NULL;
78 : : ccm_flag = 0x07 & ~ROC_CPT_AES_CCM_CTR_LEN;
79 : 0 : *salt_key = ccm_flag;
80 [ # # ]: 0 : memcpy(PLT_PTR_ADD(salt_key, 1), &ipsec_xfrm->salt, 3);
81 : : tmp_salt = (uint32_t *)salt_key;
82 [ # # ]: 0 : *tmp_salt = rte_be_to_cpu_32(*tmp_salt);
83 : 0 : break;
84 : : default:
85 : : return -ENOTSUP;
86 : : }
87 : : } else {
88 [ # # ]: 0 : if (cipher_xfrm != NULL) {
89 [ # # # # : 0 : switch (cipher_xfrm->cipher.algo) {
# ]
90 : 0 : case RTE_CRYPTO_CIPHER_NULL:
91 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_NULL;
92 : 0 : break;
93 : 0 : case RTE_CRYPTO_CIPHER_AES_CBC:
94 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_AES_CBC;
95 : 0 : break;
96 : 0 : case RTE_CRYPTO_CIPHER_AES_CTR:
97 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_AES_CTR;
98 : 0 : break;
99 : 0 : case RTE_CRYPTO_CIPHER_3DES_CBC:
100 : 0 : w2->s.enc_type = ROC_IE_SA_ENC_3DES_CBC;
101 : 0 : break;
102 : : default:
103 : : return -ENOTSUP;
104 : : }
105 : :
106 : 0 : key = cipher_xfrm->cipher.key.data;
107 : 0 : length = cipher_xfrm->cipher.key.length;
108 : : }
109 : :
110 [ # # # # : 0 : switch (auth_xfrm->auth.algo) {
# # # # ]
111 : 0 : case RTE_CRYPTO_AUTH_NULL:
112 [ # # # # ]: 0 : if (w2->s.dir == ROC_IE_SA_DIR_INBOUND && ipsec_xfrm->replay_win_sz) {
113 : 0 : plt_err("anti-replay can't be supported with integrity service disabled");
114 : 0 : return -EINVAL;
115 : : }
116 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_NULL;
117 : 0 : break;
118 : 0 : case RTE_CRYPTO_AUTH_SHA1_HMAC:
119 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_SHA1;
120 : 0 : break;
121 : 0 : case RTE_CRYPTO_AUTH_SHA256_HMAC:
122 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_SHA2_256;
123 : 0 : break;
124 : 0 : case RTE_CRYPTO_AUTH_SHA384_HMAC:
125 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_SHA2_384;
126 : 0 : break;
127 : 0 : case RTE_CRYPTO_AUTH_SHA512_HMAC:
128 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_SHA2_512;
129 : 0 : break;
130 : 0 : case RTE_CRYPTO_AUTH_AES_XCBC_MAC:
131 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_AES_XCBC_128;
132 : 0 : break;
133 : 0 : case RTE_CRYPTO_AUTH_AES_GMAC:
134 : 0 : w2->s.auth_type = ROC_IE_SA_AUTH_AES_GMAC;
135 : 0 : key = auth_xfrm->auth.key.data;
136 : 0 : length = auth_xfrm->auth.key.length;
137 [ # # ]: 0 : memcpy(salt_key, &ipsec_xfrm->salt, 4);
138 : : tmp_salt = (uint32_t *)salt_key;
139 [ # # ]: 0 : *tmp_salt = rte_be_to_cpu_32(*tmp_salt);
140 : 0 : break;
141 : : default:
142 : : return -ENOTSUP;
143 : : }
144 : :
145 [ # # ]: 0 : if (auth_xfrm->auth.algo == RTE_CRYPTO_AUTH_AES_XCBC_MAC) {
146 : 0 : const uint8_t *auth_key = auth_xfrm->auth.key.data;
147 : 0 : roc_aes_xcbc_key_derive(auth_key, hmac_opad_ipad);
148 : : } else {
149 : 0 : roc_se_hmac_opad_ipad_gen(w2->s.auth_type, auth_xfrm->auth.key.data,
150 : 0 : auth_xfrm->auth.key.length, &hmac_opad_ipad[0],
151 : : ROC_SE_IPSEC);
152 : : }
153 : :
154 : : tmp_key = (uint64_t *)hmac_opad_ipad;
155 : : for (i = 0;
156 [ # # ]: 0 : i < (int)(ROC_CTX_MAX_OPAD_IPAD_LEN / sizeof(uint64_t));
157 : 0 : i++)
158 [ # # ]: 0 : tmp_key[i] = rte_be_to_cpu_64(tmp_key[i]);
159 : :
160 : : }
161 : :
162 : : /* Set encapsulation type */
163 [ # # ]: 0 : if (ipsec_xfrm->options.udp_encap)
164 : 0 : w2->s.encap_type = ROC_IE_OT_SA_ENCAP_UDP;
165 : :
166 : 0 : w2->s.spi = ipsec_xfrm->spi;
167 : :
168 [ # # ]: 0 : if (key != NULL && length != 0) {
169 : : /* Copy encryption key */
170 : 0 : memcpy(cipher_key, key, length);
171 : : tmp_key = (uint64_t *)cipher_key;
172 [ # # ]: 0 : for (i = 0; i < (int)(ROC_CTX_MAX_CKEY_LEN / sizeof(uint64_t)); i++)
173 [ # # ]: 0 : tmp_key[i] = rte_be_to_cpu_64(tmp_key[i]);
174 : : }
175 : :
176 : : /* Set AES key length */
177 : 0 : if (w2->s.enc_type == ROC_IE_SA_ENC_AES_CBC ||
178 : : w2->s.enc_type == ROC_IE_SA_ENC_AES_CTR ||
179 [ # # ]: 0 : w2->s.enc_type == ROC_IE_SA_ENC_AES_GCM ||
180 : 0 : w2->s.enc_type == ROC_IE_SA_ENC_AES_CCM ||
181 [ # # ]: 0 : w2->s.auth_type == ROC_IE_SA_AUTH_AES_GMAC) {
182 [ # # # # ]: 0 : switch (length) {
183 : 0 : case ROC_CPT_AES128_KEY_LEN:
184 : 0 : w2->s.aes_key_len = ROC_IE_SA_AES_KEY_LEN_128;
185 : 0 : break;
186 : 0 : case ROC_CPT_AES192_KEY_LEN:
187 : 0 : w2->s.aes_key_len = ROC_IE_SA_AES_KEY_LEN_192;
188 : 0 : break;
189 : 0 : case ROC_CPT_AES256_KEY_LEN:
190 : 0 : w2->s.aes_key_len = ROC_IE_SA_AES_KEY_LEN_256;
191 : 0 : break;
192 : 0 : default:
193 : 0 : plt_err("Invalid AES key length");
194 : 0 : return -EINVAL;
195 : : }
196 : : }
197 : :
198 [ # # ]: 0 : if (ipsec_xfrm->life.packets_soft_limit != 0 ||
199 [ # # ]: 0 : ipsec_xfrm->life.packets_hard_limit != 0) {
200 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_soft_limit != 0 ||
201 [ # # ]: 0 : ipsec_xfrm->life.bytes_hard_limit != 0) {
202 : 0 : plt_err("Expiry tracking with both packets & bytes is not supported");
203 : 0 : return -EINVAL;
204 : : }
205 : 0 : w2->s.life_unit = ROC_IE_OT_SA_LIFE_UNIT_PKTS;
206 : : }
207 : :
208 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_soft_limit != 0 ||
209 [ # # ]: 0 : ipsec_xfrm->life.bytes_hard_limit != 0) {
210 [ # # ]: 0 : if (ipsec_xfrm->life.packets_soft_limit != 0 ||
211 [ # # ]: 0 : ipsec_xfrm->life.packets_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_OCTETS;
216 : : }
217 : :
218 : : return 0;
219 : : }
220 : :
221 : : static size_t
222 : : ot_ipsec_inb_ctx_size(struct roc_ot_ipsec_inb_sa *sa)
223 : : {
224 : : size_t size;
225 : :
226 : : /* Variable based on Anti-replay Window */
227 : : size = offsetof(struct roc_ot_ipsec_inb_sa, ctx) +
228 : : offsetof(struct roc_ot_ipsec_inb_ctx_update_reg, ar_winbits);
229 : :
230 : 0 : if (sa->w0.s.ar_win)
231 : 0 : size += (1 << (sa->w0.s.ar_win - 1)) * sizeof(uint64_t);
232 : :
233 : : return size;
234 : : }
235 : :
236 : : static void
237 : 0 : ot_ipsec_update_ipv6_addr_endianness(uint64_t *addr)
238 : : {
239 [ # # ]: 0 : *addr = rte_be_to_cpu_64(*addr);
240 : : addr++;
241 [ # # ]: 0 : *addr = rte_be_to_cpu_64(*addr);
242 : 0 : }
243 : :
244 : : static int
245 : 0 : ot_ipsec_inb_tunnel_hdr_fill(struct roc_ot_ipsec_inb_sa *sa,
246 : : struct rte_security_ipsec_xform *ipsec_xfrm)
247 : : {
248 : : struct rte_security_ipsec_tunnel_param *tunnel;
249 : :
250 [ # # ]: 0 : if (ipsec_xfrm->mode != RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
251 : : return 0;
252 : :
253 [ # # ]: 0 : if (ipsec_xfrm->options.tunnel_hdr_verify == 0)
254 : : return 0;
255 : :
256 : : tunnel = &ipsec_xfrm->tunnel;
257 : :
258 [ # # # ]: 0 : switch (tunnel->type) {
259 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_IPV4:
260 : 0 : sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_4;
261 [ # # ]: 0 : memcpy(&sa->outer_hdr.ipv4.src_addr, &tunnel->ipv4.src_ip,
262 : : sizeof(struct in_addr));
263 : 0 : memcpy(&sa->outer_hdr.ipv4.dst_addr, &tunnel->ipv4.dst_ip,
264 : : sizeof(struct in_addr));
265 : :
266 : : /* IP Source and Dest are in LE/CPU endian */
267 : 0 : sa->outer_hdr.ipv4.src_addr =
268 [ # # ]: 0 : rte_be_to_cpu_32(sa->outer_hdr.ipv4.src_addr);
269 : 0 : sa->outer_hdr.ipv4.dst_addr =
270 [ # # ]: 0 : rte_be_to_cpu_32(sa->outer_hdr.ipv4.dst_addr);
271 : :
272 : 0 : break;
273 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_IPV6:
274 : 0 : sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_6;
275 : 0 : memcpy(&sa->outer_hdr.ipv6.src_addr, &tunnel->ipv6.src_addr,
276 : : sizeof(sa->outer_hdr.ipv6.src_addr));
277 : 0 : memcpy(&sa->outer_hdr.ipv6.dst_addr, &tunnel->ipv6.dst_addr,
278 : : sizeof(sa->outer_hdr.ipv6.dst_addr));
279 : :
280 : : /* IP Source and Dest are in LE/CPU endian */
281 : 0 : ot_ipsec_update_ipv6_addr_endianness((uint64_t *)&sa->outer_hdr.ipv6.src_addr);
282 : 0 : ot_ipsec_update_ipv6_addr_endianness((uint64_t *)&sa->outer_hdr.ipv6.dst_addr);
283 : :
284 : 0 : break;
285 : : default:
286 : : return -EINVAL;
287 : : }
288 : :
289 [ # # # ]: 0 : switch (ipsec_xfrm->options.tunnel_hdr_verify) {
290 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_VERIFY_DST_ADDR:
291 : 0 : sa->w2.s.ip_hdr_verify = ROC_IE_OT_SA_IP_HDR_VERIFY_DST_ADDR;
292 : 0 : break;
293 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_VERIFY_SRC_DST_ADDR:
294 : 0 : sa->w2.s.ip_hdr_verify =
295 : : ROC_IE_OT_SA_IP_HDR_VERIFY_SRC_DST_ADDR;
296 : 0 : break;
297 : : default:
298 : : return -ENOTSUP;
299 : : }
300 : :
301 : : return 0;
302 : : }
303 : :
304 : : int
305 : 0 : cnxk_ot_ipsec_inb_sa_fill(struct roc_ot_ipsec_inb_sa *sa,
306 : : struct rte_security_ipsec_xform *ipsec_xfrm,
307 : : struct rte_crypto_sym_xform *crypto_xfrm,
308 : : bool is_inline)
309 : : {
310 : : uint16_t sport = 4500, dport = 4500;
311 : : union roc_ot_ipsec_sa_word2 w2;
312 : : uint32_t replay_win_sz;
313 : : size_t offset;
314 : : int rc;
315 : :
316 : : /* Initialize the SA */
317 : 0 : roc_ot_ipsec_inb_sa_init(sa, is_inline);
318 : :
319 : 0 : w2.u64 = 0;
320 : 0 : rc = ot_ipsec_sa_common_param_fill(&w2, sa->cipher_key, sa->w8.s.salt,
321 : 0 : sa->hmac_opad_ipad, ipsec_xfrm,
322 : : crypto_xfrm);
323 [ # # ]: 0 : if (rc)
324 : : return rc;
325 : :
326 : : /* Updata common word2 data */
327 : 0 : sa->w2.u64 = w2.u64;
328 : :
329 : : /* Only support power-of-two window sizes supported */
330 : 0 : replay_win_sz = ipsec_xfrm->replay_win_sz;
331 [ # # ]: 0 : if (replay_win_sz) {
332 [ # # ]: 0 : if (!rte_is_power_of_2(replay_win_sz) ||
333 : : replay_win_sz > ROC_AR_WIN_SIZE_MAX)
334 : : return -ENOTSUP;
335 : :
336 : 0 : sa->w0.s.ar_win = rte_log2_u32(replay_win_sz) - 5;
337 : : }
338 : :
339 : 0 : rc = ot_ipsec_inb_tunnel_hdr_fill(sa, ipsec_xfrm);
340 [ # # ]: 0 : if (rc)
341 : : return rc;
342 : :
343 : : /* Default options for pkt_out and pkt_fmt are with
344 : : * second pass meta and no defrag.
345 : : */
346 : 0 : sa->w0.s.pkt_format = ROC_IE_OT_SA_PKT_FMT_META;
347 : 0 : sa->w0.s.pkt_output = ROC_IE_OT_SA_PKT_OUTPUT_NO_FRAG;
348 : 0 : sa->w0.s.pkind = ROC_IE_OT_CPT_PKIND;
349 : :
350 [ # # ]: 0 : if (ipsec_xfrm->options.ip_reassembly_en)
351 : 0 : sa->w0.s.pkt_output = ROC_IE_OT_SA_PKT_OUTPUT_HW_BASED_DEFRAG;
352 : :
353 : : /* ESN */
354 : 0 : sa->w2.s.esn_en = !!ipsec_xfrm->options.esn;
355 [ # # ]: 0 : if (ipsec_xfrm->options.udp_encap) {
356 [ # # ]: 0 : if (ipsec_xfrm->udp.sport)
357 : : sport = ipsec_xfrm->udp.sport;
358 : :
359 [ # # ]: 0 : if (ipsec_xfrm->udp.dport)
360 : : dport = ipsec_xfrm->udp.dport;
361 : :
362 : 0 : sa->w10.s.udp_src_port = sport;
363 : 0 : sa->w10.s.udp_dst_port = dport;
364 : : }
365 : :
366 [ # # ]: 0 : if (ipsec_xfrm->options.udp_ports_verify)
367 : 0 : sa->w2.s.udp_ports_verify = 1;
368 : :
369 : : offset = offsetof(struct roc_ot_ipsec_inb_sa, ctx);
370 : : /* Word offset for HW managed SA field */
371 : 0 : sa->w0.s.hw_ctx_off = offset / 8;
372 : : /* Context push size for inbound spans up to hw_ctx including
373 : : * ar_base field, in 8b units
374 : : */
375 [ # # ]: 0 : sa->w0.s.ctx_push_size = sa->w0.s.hw_ctx_off + 1;
376 : : /* Entire context size in 128B units */
377 : 0 : sa->w0.s.ctx_size =
378 : 0 : (PLT_ALIGN_CEIL(ot_ipsec_inb_ctx_size(sa), ROC_CTX_UNIT_128B) /
379 : 0 : ROC_CTX_UNIT_128B) -
380 : : 1;
381 : :
382 : : /**
383 : : * CPT MC triggers expiry when counter value changes from 2 to 1. To
384 : : * mitigate this behaviour add 1 to the life counter values provided.
385 : : */
386 : :
387 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_soft_limit) {
388 : 0 : sa->ctx.soft_life = ipsec_xfrm->life.bytes_soft_limit + 1;
389 : 0 : sa->w0.s.soft_life_dec = 1;
390 : : }
391 : :
392 [ # # ]: 0 : if (ipsec_xfrm->life.packets_soft_limit) {
393 : 0 : sa->ctx.soft_life = ipsec_xfrm->life.packets_soft_limit + 1;
394 : 0 : sa->w0.s.soft_life_dec = 1;
395 : : }
396 : :
397 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_hard_limit) {
398 : 0 : sa->ctx.hard_life = ipsec_xfrm->life.bytes_hard_limit + 1;
399 : 0 : sa->w0.s.hard_life_dec = 1;
400 : : }
401 : :
402 [ # # ]: 0 : if (ipsec_xfrm->life.packets_hard_limit) {
403 : 0 : sa->ctx.hard_life = ipsec_xfrm->life.packets_hard_limit + 1;
404 : 0 : sa->w0.s.hard_life_dec = 1;
405 : : }
406 : :
407 : : rte_wmb();
408 : :
409 : : /* Enable SA */
410 : 0 : sa->w2.s.valid = 1;
411 : 0 : return 0;
412 : : }
413 : :
414 : : int
415 : 0 : cnxk_ot_ipsec_outb_sa_fill(struct roc_ot_ipsec_outb_sa *sa,
416 : : struct rte_security_ipsec_xform *ipsec_xfrm,
417 : : struct rte_crypto_sym_xform *crypto_xfrm)
418 : : {
419 : : struct rte_security_ipsec_tunnel_param *tunnel = &ipsec_xfrm->tunnel;
420 : : uint16_t sport = 4500, dport = 4500;
421 : : union roc_ot_ipsec_sa_word2 w2;
422 : : size_t offset;
423 : : int rc;
424 : :
425 : : /* Initialize the SA */
426 : 0 : roc_ot_ipsec_outb_sa_init(sa);
427 : :
428 : 0 : w2.u64 = 0;
429 : 0 : rc = ot_ipsec_sa_common_param_fill(&w2, sa->cipher_key, sa->iv.s.salt,
430 : 0 : sa->hmac_opad_ipad, ipsec_xfrm,
431 : : crypto_xfrm);
432 [ # # ]: 0 : if (rc)
433 : : return rc;
434 : :
435 : : /* Update common word2 data */
436 : 0 : sa->w2.u64 = w2.u64;
437 : :
438 [ # # ]: 0 : if (ipsec_xfrm->mode != RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
439 : 0 : goto skip_tunnel_info;
440 : :
441 : : /* Tunnel header info */
442 [ # # # ]: 0 : switch (tunnel->type) {
443 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_IPV4:
444 : 0 : sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_4;
445 [ # # ]: 0 : memcpy(&sa->outer_hdr.ipv4.src_addr, &tunnel->ipv4.src_ip,
446 : : sizeof(struct in_addr));
447 : 0 : memcpy(&sa->outer_hdr.ipv4.dst_addr, &tunnel->ipv4.dst_ip,
448 : : sizeof(struct in_addr));
449 : :
450 : : /* IP Source and Dest seems to be in LE/CPU endian */
451 : 0 : sa->outer_hdr.ipv4.src_addr =
452 [ # # ]: 0 : rte_be_to_cpu_32(sa->outer_hdr.ipv4.src_addr);
453 : 0 : sa->outer_hdr.ipv4.dst_addr =
454 [ # # ]: 0 : rte_be_to_cpu_32(sa->outer_hdr.ipv4.dst_addr);
455 : :
456 : : /* Outer header DF bit source */
457 [ # # ]: 0 : if (!ipsec_xfrm->options.copy_df) {
458 : 0 : sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
459 : : ROC_IE_OT_SA_COPY_FROM_SA;
460 : 0 : sa->w10.s.ipv4_df_or_ipv6_flw_lbl = tunnel->ipv4.df;
461 : : } else {
462 : 0 : sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
463 : : ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
464 : : }
465 : :
466 : : /* Outer header DSCP source */
467 [ # # ]: 0 : if (!ipsec_xfrm->options.copy_dscp) {
468 : 0 : sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_SA;
469 : 0 : sa->w10.s.dscp = tunnel->ipv4.dscp;
470 : : } else {
471 : 0 : sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
472 : : }
473 : : break;
474 : 0 : case RTE_SECURITY_IPSEC_TUNNEL_IPV6:
475 : 0 : sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_6;
476 : 0 : memcpy(&sa->outer_hdr.ipv6.src_addr, &tunnel->ipv6.src_addr,
477 : : sizeof(sa->outer_hdr.ipv6.src_addr));
478 : 0 : memcpy(&sa->outer_hdr.ipv6.dst_addr, &tunnel->ipv6.dst_addr,
479 : : sizeof(sa->outer_hdr.ipv6.dst_addr));
480 : :
481 : : /* IP Source and Dest are in LE/CPU endian */
482 : 0 : ot_ipsec_update_ipv6_addr_endianness((uint64_t *)&sa->outer_hdr.ipv6.src_addr);
483 : 0 : ot_ipsec_update_ipv6_addr_endianness((uint64_t *)&sa->outer_hdr.ipv6.dst_addr);
484 : :
485 : : /* Outer header flow label source */
486 [ # # ]: 0 : if (!ipsec_xfrm->options.copy_flabel) {
487 : 0 : sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
488 : : ROC_IE_OT_SA_COPY_FROM_SA;
489 : :
490 : 0 : sa->w10.s.ipv4_df_or_ipv6_flw_lbl = tunnel->ipv6.flabel;
491 : : } else {
492 : 0 : sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
493 : : ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
494 : : }
495 : :
496 : : /* Outer header DSCP source */
497 [ # # ]: 0 : if (!ipsec_xfrm->options.copy_dscp) {
498 : 0 : sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_SA;
499 : 0 : sa->w10.s.dscp = tunnel->ipv6.dscp;
500 : : } else {
501 : 0 : sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
502 : : }
503 : : break;
504 : : default:
505 : : return -EINVAL;
506 : : }
507 : :
508 : 0 : skip_tunnel_info:
509 : : /* ESN */
510 : 0 : sa->w0.s.esn_en = !!ipsec_xfrm->options.esn;
511 : :
512 [ # # ]: 0 : if (ipsec_xfrm->esn.value)
513 : 0 : sa->ctx.esn_val = ipsec_xfrm->esn.value - 1;
514 : :
515 [ # # ]: 0 : if (ipsec_xfrm->options.udp_encap) {
516 [ # # ]: 0 : if (ipsec_xfrm->udp.sport)
517 : : sport = ipsec_xfrm->udp.sport;
518 : :
519 [ # # ]: 0 : if (ipsec_xfrm->udp.dport)
520 : : dport = ipsec_xfrm->udp.dport;
521 : :
522 : 0 : sa->w10.s.udp_src_port = sport;
523 : 0 : sa->w10.s.udp_dst_port = dport;
524 : : }
525 : :
526 : : offset = offsetof(struct roc_ot_ipsec_outb_sa, ctx);
527 : : /* Word offset for HW managed SA field */
528 : 0 : sa->w0.s.hw_ctx_off = offset / 8;
529 : :
530 : : /* Context push size is up to err ctl in HW ctx */
531 : 0 : sa->w0.s.ctx_push_size = sa->w0.s.hw_ctx_off + 1;
532 : :
533 : : /* Entire context size in 128B units */
534 : : offset = sizeof(struct roc_ot_ipsec_outb_sa);
535 : 0 : sa->w0.s.ctx_size = (PLT_ALIGN_CEIL(offset, ROC_CTX_UNIT_128B) /
536 : : ROC_CTX_UNIT_128B) -
537 : : 1;
538 : :
539 : : /* IPID gen */
540 : 0 : sa->w2.s.ipid_gen = 1;
541 : :
542 : : /**
543 : : * CPT MC triggers expiry when counter value changes from 2 to 1. To
544 : : * mitigate this behaviour add 1 to the life counter values provided.
545 : : */
546 : :
547 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_soft_limit) {
548 : 0 : sa->ctx.soft_life = ipsec_xfrm->life.bytes_soft_limit + 1;
549 : 0 : sa->w0.s.soft_life_dec = 1;
550 : : }
551 : :
552 [ # # ]: 0 : if (ipsec_xfrm->life.packets_soft_limit) {
553 : 0 : sa->ctx.soft_life = ipsec_xfrm->life.packets_soft_limit + 1;
554 : 0 : sa->w0.s.soft_life_dec = 1;
555 : : }
556 : :
557 [ # # ]: 0 : if (ipsec_xfrm->life.bytes_hard_limit) {
558 : 0 : sa->ctx.hard_life = ipsec_xfrm->life.bytes_hard_limit + 1;
559 : 0 : sa->w0.s.hard_life_dec = 1;
560 : : }
561 : :
562 [ # # ]: 0 : if (ipsec_xfrm->life.packets_hard_limit) {
563 : 0 : sa->ctx.hard_life = ipsec_xfrm->life.packets_hard_limit + 1;
564 : 0 : sa->w0.s.hard_life_dec = 1;
565 : : }
566 : :
567 : : /* There are two words of CPT_CTX_HW_S for ucode to skip */
568 : 0 : sa->w0.s.ctx_hdr_size = 1;
569 : 0 : sa->w0.s.aop_valid = 1;
570 : :
571 : : rte_wmb();
572 : :
573 : : /* Enable SA */
574 : 0 : sa->w2.s.valid = 1;
575 : 0 : return 0;
576 : : }
577 : :
578 : : bool
579 : 0 : cnxk_ot_ipsec_inb_sa_valid(struct roc_ot_ipsec_inb_sa *sa)
580 : : {
581 : 0 : return !!sa->w2.s.valid;
582 : : }
583 : :
584 : : bool
585 : 0 : cnxk_ot_ipsec_outb_sa_valid(struct roc_ot_ipsec_outb_sa *sa)
586 : : {
587 : 0 : return !!sa->w2.s.valid;
588 : : }
589 : :
590 : : uint8_t
591 : 0 : cnxk_ipsec_ivlen_get(enum rte_crypto_cipher_algorithm c_algo,
592 : : enum rte_crypto_auth_algorithm a_algo,
593 : : enum rte_crypto_aead_algorithm aead_algo)
594 : : {
595 : : uint8_t ivlen = 0;
596 : :
597 [ # # ]: 0 : if ((aead_algo == RTE_CRYPTO_AEAD_AES_GCM) || (aead_algo == RTE_CRYPTO_AEAD_AES_CCM))
598 : : ivlen = 8;
599 : :
600 [ # # # # ]: 0 : switch (c_algo) {
601 : 0 : case RTE_CRYPTO_CIPHER_AES_CTR:
602 : : ivlen = 8;
603 : 0 : break;
604 : 0 : case RTE_CRYPTO_CIPHER_DES_CBC:
605 : : case RTE_CRYPTO_CIPHER_3DES_CBC:
606 : : ivlen = ROC_CPT_DES_BLOCK_LENGTH;
607 : 0 : break;
608 : 0 : case RTE_CRYPTO_CIPHER_AES_CBC:
609 : : ivlen = ROC_CPT_AES_BLOCK_LENGTH;
610 : 0 : break;
611 : : default:
612 : : break;
613 : : }
614 : :
615 [ # # ]: 0 : switch (a_algo) {
616 : 0 : case RTE_CRYPTO_AUTH_AES_GMAC:
617 : : ivlen = 8;
618 : 0 : break;
619 : : default:
620 : : break;
621 : : }
622 : :
623 : 0 : return ivlen;
624 : : }
625 : :
626 : : uint8_t
627 [ # # ]: 0 : cnxk_ipsec_icvlen_get(enum rte_crypto_cipher_algorithm c_algo,
628 : : enum rte_crypto_auth_algorithm a_algo,
629 : : enum rte_crypto_aead_algorithm aead_algo)
630 : : {
631 : : uint8_t icv = 0;
632 : :
633 : : (void)c_algo;
634 : :
635 : : switch (a_algo) {
636 : : case RTE_CRYPTO_AUTH_NULL:
637 : : icv = 0;
638 : : break;
639 : : case RTE_CRYPTO_AUTH_MD5_HMAC:
640 : : case RTE_CRYPTO_AUTH_SHA1_HMAC:
641 : : icv = 12;
642 : : break;
643 : : case RTE_CRYPTO_AUTH_SHA256_HMAC:
644 : : case RTE_CRYPTO_AUTH_AES_GMAC:
645 : : icv = 16;
646 : : break;
647 : : case RTE_CRYPTO_AUTH_SHA384_HMAC:
648 : : icv = 24;
649 : : break;
650 : : case RTE_CRYPTO_AUTH_SHA512_HMAC:
651 : : icv = 32;
652 : : break;
653 : : case RTE_CRYPTO_AUTH_AES_XCBC_MAC:
654 : : icv = 12;
655 : : break;
656 : : default:
657 : : break;
658 : : }
659 : :
660 [ # # ]: 0 : switch (aead_algo) {
661 : 0 : case RTE_CRYPTO_AEAD_AES_GCM:
662 : : case RTE_CRYPTO_AEAD_AES_CCM:
663 : : icv = 16;
664 : 0 : break;
665 : : default:
666 : : break;
667 : : }
668 : :
669 : 0 : return icv;
670 : : }
671 : :
672 : : uint8_t
673 : 0 : cnxk_ipsec_outb_roundup_byte(enum rte_crypto_cipher_algorithm c_algo,
674 : : enum rte_crypto_aead_algorithm aead_algo)
675 : : {
676 : : uint8_t roundup_byte = 4;
677 : :
678 [ # # ]: 0 : if ((aead_algo == RTE_CRYPTO_AEAD_AES_GCM) || (aead_algo == RTE_CRYPTO_AEAD_AES_CCM))
679 : : return roundup_byte;
680 : :
681 [ # # # ]: 0 : switch (c_algo) {
682 : : case RTE_CRYPTO_CIPHER_AES_CTR:
683 : : roundup_byte = 4;
684 : : break;
685 : 0 : case RTE_CRYPTO_CIPHER_AES_CBC:
686 : : roundup_byte = 16;
687 : 0 : break;
688 : 0 : case RTE_CRYPTO_CIPHER_DES_CBC:
689 : : case RTE_CRYPTO_CIPHER_3DES_CBC:
690 : : roundup_byte = 8;
691 : 0 : break;
692 : : case RTE_CRYPTO_CIPHER_NULL:
693 : : roundup_byte = 4;
694 : : break;
695 : : default:
696 : : break;
697 : : }
698 : :
699 : : return roundup_byte;
700 : : }
701 : :
702 : : int
703 [ # # ]: 0 : cnxk_ipsec_outb_rlens_get(struct cnxk_ipsec_outb_rlens *rlens,
704 : : struct rte_security_ipsec_xform *ipsec_xfrm,
705 : : struct rte_crypto_sym_xform *crypto_xfrm)
706 : : {
707 : : struct rte_security_ipsec_tunnel_param *tunnel = &ipsec_xfrm->tunnel;
708 : : enum rte_crypto_cipher_algorithm c_algo = RTE_CRYPTO_CIPHER_NULL;
709 : : enum rte_crypto_auth_algorithm a_algo = RTE_CRYPTO_AUTH_NULL;
710 : : enum rte_crypto_aead_algorithm aead_algo = 0;
711 : : uint16_t partial_len = 0;
712 : : uint8_t roundup_byte = 0;
713 : : int8_t roundup_len = 0;
714 : :
715 : : memset(rlens, 0, sizeof(struct cnxk_ipsec_outb_rlens));
716 : :
717 : : /* Get Cipher and Auth algo */
718 [ # # ]: 0 : if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
719 : 0 : aead_algo = crypto_xfrm->aead.algo;
720 : : } else {
721 [ # # ]: 0 : if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_CIPHER)
722 : 0 : c_algo = crypto_xfrm->cipher.algo;
723 : : else
724 : 0 : a_algo = crypto_xfrm->auth.algo;
725 : :
726 [ # # ]: 0 : if (crypto_xfrm->next) {
727 [ # # ]: 0 : if (crypto_xfrm->next->type ==
728 : : RTE_CRYPTO_SYM_XFORM_CIPHER)
729 : 0 : c_algo = crypto_xfrm->next->cipher.algo;
730 : : else
731 : 0 : a_algo = crypto_xfrm->next->auth.algo;
732 : : }
733 : : }
734 : :
735 [ # # ]: 0 : if (ipsec_xfrm->proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP) {
736 : : partial_len = ROC_CPT_ESP_HDR_LEN;
737 : : roundup_len = ROC_CPT_ESP_TRL_LEN;
738 : : } else {
739 : : partial_len = ROC_CPT_AH_HDR_LEN;
740 : : }
741 : :
742 [ # # ]: 0 : if (ipsec_xfrm->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
743 [ # # ]: 0 : if (tunnel->type == RTE_SECURITY_IPSEC_TUNNEL_IPV4)
744 : 0 : partial_len += ROC_CPT_TUNNEL_IPV4_HDR_LEN;
745 : : else
746 : 0 : partial_len += ROC_CPT_TUNNEL_IPV6_HDR_LEN;
747 : : }
748 : :
749 : 0 : partial_len += cnxk_ipsec_ivlen_get(c_algo, a_algo, aead_algo);
750 : 0 : partial_len += cnxk_ipsec_icvlen_get(c_algo, a_algo, aead_algo);
751 : 0 : roundup_byte = cnxk_ipsec_outb_roundup_byte(c_algo, aead_algo);
752 : :
753 [ # # ]: 0 : if (ipsec_xfrm->options.udp_encap)
754 : 0 : partial_len += sizeof(struct rte_udp_hdr);
755 : :
756 : 0 : rlens->partial_len = partial_len;
757 : 0 : rlens->roundup_len = roundup_len;
758 : 0 : rlens->roundup_byte = roundup_byte;
759 : 0 : rlens->max_extended_len = partial_len + roundup_len + roundup_byte;
760 : 0 : return 0;
761 : : }
762 : :
763 : : static inline int
764 : 0 : on_ipsec_sa_ctl_set(struct rte_security_ipsec_xform *ipsec,
765 : : struct rte_crypto_sym_xform *crypto_xform,
766 : : struct roc_ie_on_sa_ctl *ctl)
767 : : {
768 : : struct rte_crypto_sym_xform *cipher_xform, *auth_xform;
769 : : int aes_key_len = 0;
770 : :
771 [ # # ]: 0 : if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
772 : : auth_xform = crypto_xform;
773 : 0 : cipher_xform = crypto_xform->next;
774 : : } else {
775 : : cipher_xform = crypto_xform;
776 : 0 : auth_xform = crypto_xform->next;
777 : : }
778 : :
779 [ # # ]: 0 : if (ipsec->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
780 : 0 : ctl->direction = ROC_IE_SA_DIR_OUTBOUND;
781 : : else
782 : 0 : ctl->direction = ROC_IE_SA_DIR_INBOUND;
783 : :
784 [ # # ]: 0 : if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
785 [ # # ]: 0 : if (ipsec->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV4)
786 : 0 : ctl->outer_ip_ver = ROC_IE_SA_IP_VERSION_4;
787 [ # # ]: 0 : else if (ipsec->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV6)
788 : 0 : ctl->outer_ip_ver = ROC_IE_SA_IP_VERSION_6;
789 : : else
790 : : return -EINVAL;
791 : : }
792 : :
793 [ # # ]: 0 : if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT) {
794 : 0 : ctl->ipsec_mode = ROC_IE_SA_MODE_TRANSPORT;
795 : 0 : ctl->outer_ip_ver = ROC_IE_SA_IP_VERSION_4;
796 [ # # ]: 0 : } else if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
797 : 0 : ctl->ipsec_mode = ROC_IE_SA_MODE_TUNNEL;
798 : : else
799 : : return -EINVAL;
800 : :
801 [ # # ]: 0 : if (ipsec->proto == RTE_SECURITY_IPSEC_SA_PROTO_AH)
802 : 0 : ctl->ipsec_proto = ROC_IE_SA_PROTOCOL_AH;
803 [ # # ]: 0 : else if (ipsec->proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP)
804 : 0 : ctl->ipsec_proto = ROC_IE_SA_PROTOCOL_ESP;
805 : : else
806 : : return -EINVAL;
807 : :
808 [ # # ]: 0 : if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
809 [ # # # ]: 0 : switch (crypto_xform->aead.algo) {
810 : 0 : case RTE_CRYPTO_AEAD_AES_GCM:
811 : 0 : ctl->enc_type = ROC_IE_SA_ENC_AES_GCM;
812 : 0 : aes_key_len = crypto_xform->aead.key.length;
813 : 0 : break;
814 : 0 : case RTE_CRYPTO_AEAD_AES_CCM:
815 : 0 : ctl->enc_type = ROC_IE_SA_ENC_AES_CCM;
816 : 0 : aes_key_len = crypto_xform->aead.key.length;
817 : 0 : break;
818 : 0 : default:
819 : 0 : plt_err("Unsupported AEAD algorithm");
820 : 0 : return -ENOTSUP;
821 : : }
822 : : } else {
823 [ # # ]: 0 : if (cipher_xform != NULL) {
824 [ # # # # : 0 : switch (cipher_xform->cipher.algo) {
# # ]
825 : 0 : case RTE_CRYPTO_CIPHER_NULL:
826 : 0 : ctl->enc_type = ROC_IE_SA_ENC_NULL;
827 : 0 : break;
828 : 0 : case RTE_CRYPTO_CIPHER_DES_CBC:
829 : 0 : ctl->enc_type = ROC_IE_SA_ENC_DES_CBC;
830 : 0 : break;
831 : 0 : case RTE_CRYPTO_CIPHER_3DES_CBC:
832 : 0 : ctl->enc_type = ROC_IE_SA_ENC_3DES_CBC;
833 : 0 : break;
834 : 0 : case RTE_CRYPTO_CIPHER_AES_CBC:
835 : 0 : ctl->enc_type = ROC_IE_SA_ENC_AES_CBC;
836 : 0 : aes_key_len = cipher_xform->cipher.key.length;
837 : 0 : break;
838 : 0 : case RTE_CRYPTO_CIPHER_AES_CTR:
839 : 0 : ctl->enc_type = ROC_IE_SA_ENC_AES_CTR;
840 : 0 : aes_key_len = cipher_xform->cipher.key.length;
841 : 0 : break;
842 : 0 : default:
843 : 0 : plt_err("Unsupported cipher algorithm");
844 : 0 : return -ENOTSUP;
845 : : }
846 : : }
847 : :
848 [ # # # # : 0 : switch (auth_xform->auth.algo) {
# # # # #
# ]
849 : 0 : case RTE_CRYPTO_AUTH_NULL:
850 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_NULL;
851 : 0 : break;
852 : 0 : case RTE_CRYPTO_AUTH_MD5_HMAC:
853 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_MD5;
854 : 0 : break;
855 : 0 : case RTE_CRYPTO_AUTH_SHA1_HMAC:
856 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_SHA1;
857 : 0 : break;
858 : 0 : case RTE_CRYPTO_AUTH_SHA224_HMAC:
859 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_SHA2_224;
860 : 0 : break;
861 : 0 : case RTE_CRYPTO_AUTH_SHA256_HMAC:
862 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_SHA2_256;
863 : 0 : break;
864 : 0 : case RTE_CRYPTO_AUTH_SHA384_HMAC:
865 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_SHA2_384;
866 : 0 : break;
867 : 0 : case RTE_CRYPTO_AUTH_SHA512_HMAC:
868 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_SHA2_512;
869 : 0 : break;
870 : 0 : case RTE_CRYPTO_AUTH_AES_GMAC:
871 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_AES_GMAC;
872 : 0 : aes_key_len = auth_xform->auth.key.length;
873 : 0 : break;
874 : 0 : case RTE_CRYPTO_AUTH_AES_XCBC_MAC:
875 : 0 : ctl->auth_type = ROC_IE_SA_AUTH_AES_XCBC_128;
876 : 0 : break;
877 : 0 : default:
878 : 0 : plt_err("Unsupported auth algorithm");
879 : 0 : return -ENOTSUP;
880 : : }
881 : : }
882 : :
883 : : /* Set AES key length */
884 : 0 : if (ctl->enc_type == ROC_IE_SA_ENC_AES_CBC ||
885 : : ctl->enc_type == ROC_IE_SA_ENC_AES_CTR ||
886 [ # # ]: 0 : ctl->enc_type == ROC_IE_SA_ENC_AES_GCM ||
887 : 0 : ctl->enc_type == ROC_IE_SA_ENC_AES_CCM ||
888 [ # # ]: 0 : ctl->auth_type == ROC_IE_SA_AUTH_AES_GMAC) {
889 [ # # # # ]: 0 : switch (aes_key_len) {
890 : 0 : case 16:
891 : 0 : ctl->aes_key_len = ROC_IE_SA_AES_KEY_LEN_128;
892 : 0 : break;
893 : 0 : case 24:
894 : 0 : ctl->aes_key_len = ROC_IE_SA_AES_KEY_LEN_192;
895 : 0 : break;
896 : 0 : case 32:
897 : 0 : ctl->aes_key_len = ROC_IE_SA_AES_KEY_LEN_256;
898 : 0 : break;
899 : 0 : default:
900 : 0 : plt_err("Invalid AES key length");
901 : 0 : return -EINVAL;
902 : : }
903 : : }
904 : :
905 [ # # ]: 0 : if (ipsec->options.esn)
906 : 0 : ctl->esn_en = 1;
907 : :
908 [ # # ]: 0 : if (ipsec->options.udp_encap == 1)
909 : 0 : ctl->encap_type = ROC_IE_ON_SA_ENCAP_UDP;
910 : :
911 : 0 : ctl->copy_df = ipsec->options.copy_df;
912 : :
913 [ # # ]: 0 : ctl->spi = rte_cpu_to_be_32(ipsec->spi);
914 : :
915 : 0 : rte_io_wmb();
916 : :
917 : 0 : ctl->valid = 1;
918 : :
919 : 0 : return 0;
920 : : }
921 : :
922 : : static inline int
923 : 0 : on_fill_ipsec_common_sa(struct rte_security_ipsec_xform *ipsec,
924 : : struct rte_crypto_sym_xform *crypto_xform,
925 : : struct roc_ie_on_common_sa *common_sa)
926 : : {
927 : : struct rte_crypto_sym_xform *cipher_xform, *auth_xform;
928 : : const uint8_t *cipher_key;
929 : : int cipher_key_len = 0;
930 : : uint8_t ccm_flag = 0;
931 : : int ret;
932 : :
933 : 0 : ret = on_ipsec_sa_ctl_set(ipsec, crypto_xform, &common_sa->ctl);
934 [ # # ]: 0 : if (ret)
935 : : return ret;
936 : :
937 [ # # ]: 0 : if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
938 : : auth_xform = crypto_xform;
939 : 0 : cipher_xform = crypto_xform->next;
940 : : } else {
941 : : cipher_xform = crypto_xform;
942 : 0 : auth_xform = crypto_xform->next;
943 : : }
944 : :
945 [ # # ]: 0 : if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
946 [ # # ]: 0 : if (crypto_xform->aead.algo == RTE_CRYPTO_AEAD_AES_GCM)
947 : 0 : memcpy(common_sa->iv.gcm.nonce, &ipsec->salt, 4);
948 [ # # ]: 0 : else if (crypto_xform->aead.algo == RTE_CRYPTO_AEAD_AES_CCM) {
949 : : ccm_flag = 0x07 & ~ROC_CPT_AES_CCM_CTR_LEN;
950 : 0 : *common_sa->iv.gcm.nonce = ccm_flag;
951 : 0 : memcpy(PLT_PTR_ADD(common_sa->iv.gcm.nonce, 1), &ipsec->salt, 3);
952 : : }
953 : 0 : cipher_key = crypto_xform->aead.key.data;
954 : 0 : cipher_key_len = crypto_xform->aead.key.length;
955 : : } else {
956 [ # # ]: 0 : if (cipher_xform) {
957 : 0 : cipher_key = cipher_xform->cipher.key.data;
958 : 0 : cipher_key_len = cipher_xform->cipher.key.length;
959 : : }
960 : :
961 [ # # ]: 0 : if (auth_xform->auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
962 : 0 : memcpy(common_sa->iv.gcm.nonce, &ipsec->salt, 4);
963 : 0 : cipher_key = auth_xform->auth.key.data;
964 : 0 : cipher_key_len = auth_xform->auth.key.length;
965 : : }
966 : : }
967 : :
968 [ # # ]: 0 : if (cipher_key_len != 0)
969 : 0 : memcpy(common_sa->cipher_key, cipher_key, cipher_key_len);
970 : :
971 : : return 0;
972 : : }
973 : :
974 : : int
975 : 0 : cnxk_on_ipsec_outb_sa_create(struct rte_security_ipsec_xform *ipsec,
976 : : struct rte_crypto_sym_xform *crypto_xform,
977 : : struct roc_ie_on_outb_sa *out_sa)
978 : : {
979 : : struct roc_ie_on_ip_template *template = NULL;
980 : : struct rte_crypto_sym_xform *auth_xform;
981 : : struct roc_ie_on_sa_ctl *ctl;
982 : : struct rte_ipv6_hdr *ip6;
983 : : struct rte_ipv4_hdr *ip4;
984 : : uint16_t sport, dport;
985 : : size_t ctx_len;
986 : : int ret;
987 : :
988 : : ctl = &out_sa->common_sa.ctl;
989 : :
990 [ # # ]: 0 : if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AUTH)
991 : : auth_xform = crypto_xform;
992 : : else
993 : 0 : auth_xform = crypto_xform->next;
994 : :
995 : 0 : ret = on_fill_ipsec_common_sa(ipsec, crypto_xform, &out_sa->common_sa);
996 [ # # ]: 0 : if (ret)
997 : : return ret;
998 : :
999 [ # # ]: 0 : if (ctl->enc_type == ROC_IE_SA_ENC_AES_GCM || ctl->enc_type == ROC_IE_SA_ENC_AES_CCM ||
1000 [ # # # # ]: 0 : ctl->auth_type == ROC_IE_SA_AUTH_NULL || ctl->auth_type == ROC_IE_SA_AUTH_AES_GMAC) {
1001 : 0 : template = &out_sa->aes_gcm.template;
1002 : 0 : ctx_len = offsetof(struct roc_ie_on_outb_sa, aes_gcm.template);
1003 : : } else {
1004 [ # # # # ]: 0 : switch (ctl->auth_type) {
1005 : 0 : case ROC_IE_SA_AUTH_MD5:
1006 : : case ROC_IE_SA_AUTH_SHA1:
1007 : 0 : template = &out_sa->sha1.template;
1008 : : ctx_len = offsetof(struct roc_ie_on_outb_sa, sha1.template);
1009 : 0 : break;
1010 : 0 : case ROC_IE_SA_AUTH_SHA2_256:
1011 : : case ROC_IE_SA_AUTH_SHA2_384:
1012 : : case ROC_IE_SA_AUTH_SHA2_512:
1013 : 0 : template = &out_sa->sha2.template;
1014 : : ctx_len = offsetof(struct roc_ie_on_outb_sa, sha2.template);
1015 : 0 : break;
1016 : 0 : case ROC_IE_SA_AUTH_AES_XCBC_128:
1017 : 0 : template = &out_sa->aes_xcbc.template;
1018 : : ctx_len = offsetof(struct roc_ie_on_outb_sa, aes_xcbc.template);
1019 : 0 : break;
1020 : 0 : default:
1021 : 0 : plt_err("Unsupported auth algorithm");
1022 : 0 : return -EINVAL;
1023 : : }
1024 : : }
1025 : :
1026 : : ip4 = (struct rte_ipv4_hdr *)&template->ip4.ipv4_hdr;
1027 : :
1028 : : sport = 4500;
1029 : : dport = 4500;
1030 : :
1031 : : /* If custom port values are provided, Overwrite default port values. */
1032 [ # # ]: 0 : if (ipsec->options.udp_encap) {
1033 : :
1034 [ # # ]: 0 : if (ipsec->udp.sport)
1035 : : sport = ipsec->udp.sport;
1036 : :
1037 [ # # ]: 0 : if (ipsec->udp.dport)
1038 : : dport = ipsec->udp.dport;
1039 : :
1040 : 0 : ip4->next_proto_id = IPPROTO_UDP;
1041 [ # # ]: 0 : template->ip4.udp_src = rte_be_to_cpu_16(sport);
1042 [ # # ]: 0 : template->ip4.udp_dst = rte_be_to_cpu_16(dport);
1043 : : } else {
1044 [ # # ]: 0 : if (ipsec->proto == RTE_SECURITY_IPSEC_SA_PROTO_AH)
1045 : 0 : ip4->next_proto_id = IPPROTO_AH;
1046 : : else
1047 : 0 : ip4->next_proto_id = IPPROTO_ESP;
1048 : : }
1049 : :
1050 [ # # ]: 0 : if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
1051 [ # # ]: 0 : if (ipsec->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
1052 : : uint16_t frag_off = 0;
1053 : :
1054 : 0 : ctx_len += sizeof(template->ip4);
1055 : :
1056 : 0 : ip4->version_ihl = RTE_IPV4_VHL_DEF;
1057 [ # # ]: 0 : ip4->time_to_live = ipsec->tunnel.ipv4.ttl ?
1058 : : ipsec->tunnel.ipv4.ttl :
1059 : : 0x40;
1060 : 0 : ip4->type_of_service |= (ipsec->tunnel.ipv4.dscp << 2);
1061 [ # # ]: 0 : if (ipsec->tunnel.ipv4.df)
1062 : : frag_off |= RTE_IPV4_HDR_DF_FLAG;
1063 [ # # ]: 0 : ip4->fragment_offset = rte_cpu_to_be_16(frag_off);
1064 : :
1065 : 0 : memcpy(&ip4->src_addr, &ipsec->tunnel.ipv4.src_ip,
1066 : : sizeof(struct in_addr));
1067 : 0 : memcpy(&ip4->dst_addr, &ipsec->tunnel.ipv4.dst_ip,
1068 : : sizeof(struct in_addr));
1069 [ # # ]: 0 : } else if (ipsec->tunnel.type ==
1070 : : RTE_SECURITY_IPSEC_TUNNEL_IPV6) {
1071 : 0 : ctx_len += sizeof(template->ip6);
1072 : :
1073 : : ip6 = (struct rte_ipv6_hdr *)&template->ip6.ipv6_hdr;
1074 [ # # ]: 0 : if (ipsec->options.udp_encap) {
1075 : 0 : ip6->proto = IPPROTO_UDP;
1076 [ # # ]: 0 : template->ip6.udp_src = rte_be_to_cpu_16(sport);
1077 [ # # ]: 0 : template->ip6.udp_dst = rte_be_to_cpu_16(dport);
1078 : : } else {
1079 [ # # ]: 0 : ip6->proto = (ipsec->proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP) ?
1080 : : IPPROTO_ESP :
1081 : : IPPROTO_AH;
1082 : : }
1083 : 0 : ip6->vtc_flow =
1084 [ # # ]: 0 : rte_cpu_to_be_32(0x60000000 |
1085 : : ((ipsec->tunnel.ipv6.dscp
1086 : : << RTE_IPV6_HDR_TC_SHIFT) &
1087 : : RTE_IPV6_HDR_TC_MASK) |
1088 : : ((ipsec->tunnel.ipv6.flabel
1089 : : << RTE_IPV6_HDR_FL_SHIFT) &
1090 : : RTE_IPV6_HDR_FL_MASK));
1091 [ # # ]: 0 : ip6->hop_limits = ipsec->tunnel.ipv6.hlimit ?
1092 : : ipsec->tunnel.ipv6.hlimit :
1093 : : 0x40;
1094 : 0 : ip6->src_addr = ipsec->tunnel.ipv6.src_addr;
1095 : 0 : ip6->dst_addr = ipsec->tunnel.ipv6.dst_addr;
1096 : : }
1097 : : } else
1098 : 0 : ctx_len += sizeof(template->ip4);
1099 : :
1100 : 0 : ctx_len = RTE_ALIGN_CEIL(ctx_len, 8);
1101 : :
1102 [ # # ]: 0 : if (crypto_xform->type != RTE_CRYPTO_SYM_XFORM_AEAD) {
1103 : 0 : uint8_t *hmac_opad_ipad = (uint8_t *)&out_sa->sha2;
1104 : :
1105 [ # # ]: 0 : if (auth_xform->auth.algo == RTE_CRYPTO_AUTH_AES_XCBC_MAC) {
1106 : 0 : const uint8_t *auth_key = auth_xform->auth.key.data;
1107 : :
1108 : 0 : roc_aes_xcbc_key_derive(auth_key, hmac_opad_ipad);
1109 [ # # ]: 0 : } else if (auth_xform->auth.algo != RTE_CRYPTO_AUTH_NULL) {
1110 : 0 : roc_se_hmac_opad_ipad_gen(
1111 : 0 : out_sa->common_sa.ctl.auth_type, auth_xform->auth.key.data,
1112 : 0 : auth_xform->auth.key.length, &hmac_opad_ipad[0], ROC_SE_IPSEC);
1113 : : }
1114 : : }
1115 : :
1116 : 0 : return ctx_len;
1117 : : }
1118 : :
1119 : : int
1120 : 0 : cnxk_on_ipsec_inb_sa_create(struct rte_security_ipsec_xform *ipsec,
1121 : : struct rte_crypto_sym_xform *crypto_xform,
1122 : : struct roc_ie_on_inb_sa *in_sa)
1123 : : {
1124 : : struct rte_crypto_sym_xform *auth_xform = crypto_xform;
1125 : : const uint8_t *auth_key;
1126 : : int auth_key_len = 0;
1127 : : size_t ctx_len = 0;
1128 : : int ret;
1129 : :
1130 : 0 : ret = on_fill_ipsec_common_sa(ipsec, crypto_xform, &in_sa->common_sa);
1131 [ # # ]: 0 : if (ret)
1132 : : return ret;
1133 : :
1134 [ # # ]: 0 : if (crypto_xform->type != RTE_CRYPTO_SYM_XFORM_AEAD &&
1135 [ # # # # ]: 0 : crypto_xform->auth.algo == RTE_CRYPTO_AUTH_NULL && ipsec->replay_win_sz) {
1136 : 0 : plt_err("anti-replay can't be supported with integrity service disabled");
1137 : 0 : return -EINVAL;
1138 : : }
1139 [ # # ]: 0 : if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD ||
1140 [ # # # # ]: 0 : auth_xform->auth.algo == RTE_CRYPTO_AUTH_NULL ||
1141 : : auth_xform->auth.algo == RTE_CRYPTO_AUTH_AES_GMAC) {
1142 : : ctx_len = offsetof(struct roc_ie_on_inb_sa, sha1_or_gcm.hmac_key[0]);
1143 : : } else {
1144 : 0 : uint8_t *hmac_opad_ipad = (uint8_t *)&in_sa->sha2;
1145 : 0 : auth_key = auth_xform->auth.key.data;
1146 : 0 : auth_key_len = auth_xform->auth.key.length;
1147 : :
1148 [ # # # # ]: 0 : switch (auth_xform->auth.algo) {
1149 : : case RTE_CRYPTO_AUTH_NULL:
1150 : : break;
1151 : 0 : case RTE_CRYPTO_AUTH_MD5_HMAC:
1152 : : case RTE_CRYPTO_AUTH_SHA1_HMAC:
1153 : 0 : memcpy(in_sa->sha1_or_gcm.hmac_key, auth_key,
1154 : : auth_key_len);
1155 : : ctx_len = offsetof(struct roc_ie_on_inb_sa,
1156 : : sha1_or_gcm.selector);
1157 : 0 : break;
1158 : 0 : case RTE_CRYPTO_AUTH_SHA256_HMAC:
1159 : : case RTE_CRYPTO_AUTH_SHA384_HMAC:
1160 : : case RTE_CRYPTO_AUTH_SHA512_HMAC:
1161 : 0 : memcpy(in_sa->sha2.hmac_key, auth_key, auth_key_len);
1162 : : ctx_len = offsetof(struct roc_ie_on_inb_sa,
1163 : : sha2.selector);
1164 : 0 : break;
1165 : 0 : case RTE_CRYPTO_AUTH_AES_XCBC_MAC:
1166 : 0 : memcpy(in_sa->aes_xcbc.key, auth_key, auth_key_len);
1167 : : ctx_len = offsetof(struct roc_ie_on_inb_sa,
1168 : : aes_xcbc.selector);
1169 : 0 : break;
1170 : 0 : default:
1171 : 0 : plt_err("Unsupported auth algorithm %u", auth_xform->auth.algo);
1172 : 0 : return -ENOTSUP;
1173 : : }
1174 [ # # ]: 0 : if (auth_xform->auth.algo == RTE_CRYPTO_AUTH_AES_XCBC_MAC) {
1175 : 0 : const uint8_t *auth_key = auth_xform->auth.key.data;
1176 : :
1177 : 0 : roc_aes_xcbc_key_derive(auth_key, hmac_opad_ipad);
1178 [ # # ]: 0 : } else if (auth_xform->auth.algo != RTE_CRYPTO_AUTH_NULL) {
1179 : 0 : roc_se_hmac_opad_ipad_gen(
1180 : 0 : in_sa->common_sa.ctl.auth_type, auth_xform->auth.key.data,
1181 : 0 : auth_xform->auth.key.length, &hmac_opad_ipad[0], ROC_SE_IPSEC);
1182 : : }
1183 : : }
1184 : :
1185 : 0 : return ctx_len;
1186 : : }
|