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