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