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