common/mlx5: fix shared memory region ranges allocation
[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         default:
36                 break;
37         }
38 }
39
40 static int
41 ot_ipsec_sa_common_param_fill(union roc_ot_ipsec_sa_word2 *w2,
42                               uint8_t *cipher_key, uint8_t *salt_key,
43                               uint8_t *hmac_opad_ipad,
44                               struct rte_security_ipsec_xform *ipsec_xfrm,
45                               struct rte_crypto_sym_xform *crypto_xfrm)
46 {
47         struct rte_crypto_sym_xform *auth_xfrm, *cipher_xfrm;
48         const uint8_t *key;
49         uint32_t *tmp_salt;
50         uint64_t *tmp_key;
51         int length, i;
52
53         /* Set direction */
54         switch (ipsec_xfrm->direction) {
55         case RTE_SECURITY_IPSEC_SA_DIR_INGRESS:
56                 w2->s.dir = ROC_IE_SA_DIR_INBOUND;
57                 auth_xfrm = crypto_xfrm;
58                 cipher_xfrm = crypto_xfrm->next;
59                 break;
60         case RTE_SECURITY_IPSEC_SA_DIR_EGRESS:
61                 w2->s.dir = ROC_IE_SA_DIR_OUTBOUND;
62                 cipher_xfrm = crypto_xfrm;
63                 auth_xfrm = crypto_xfrm->next;
64                 break;
65         default:
66                 return -EINVAL;
67         }
68
69         /* Set protocol - ESP vs AH */
70         switch (ipsec_xfrm->proto) {
71         case RTE_SECURITY_IPSEC_SA_PROTO_ESP:
72                 w2->s.protocol = ROC_IE_SA_PROTOCOL_ESP;
73                 break;
74         case RTE_SECURITY_IPSEC_SA_PROTO_AH:
75                 w2->s.protocol = ROC_IE_SA_PROTOCOL_AH;
76                 break;
77         default:
78                 return -EINVAL;
79         }
80
81         /* Set mode - transport vs tunnel */
82         switch (ipsec_xfrm->mode) {
83         case RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT:
84                 w2->s.mode = ROC_IE_SA_MODE_TRANSPORT;
85                 break;
86         case RTE_SECURITY_IPSEC_SA_MODE_TUNNEL:
87                 w2->s.mode = ROC_IE_SA_MODE_TUNNEL;
88                 break;
89         default:
90                 return -EINVAL;
91         }
92
93         /* Set encryption algorithm */
94         if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
95                 key = crypto_xfrm->aead.key.data;
96                 length = crypto_xfrm->aead.key.length;
97
98                 switch (crypto_xfrm->aead.algo) {
99                 case RTE_CRYPTO_AEAD_AES_GCM:
100                         w2->s.enc_type = ROC_IE_OT_SA_ENC_AES_GCM;
101                         w2->s.auth_type = ROC_IE_OT_SA_AUTH_NULL;
102                         memcpy(salt_key, &ipsec_xfrm->salt, 4);
103                         tmp_salt = (uint32_t *)salt_key;
104                         *tmp_salt = rte_be_to_cpu_32(*tmp_salt);
105                         break;
106                 default:
107                         return -ENOTSUP;
108                 }
109         } else {
110                 switch (cipher_xfrm->cipher.algo) {
111                 case RTE_CRYPTO_CIPHER_AES_CBC:
112                         w2->s.enc_type = ROC_IE_OT_SA_ENC_AES_CBC;
113                         break;
114                 default:
115                         return -ENOTSUP;
116                 }
117
118                 switch (auth_xfrm->auth.algo) {
119                 case RTE_CRYPTO_AUTH_NULL:
120                         w2->s.auth_type = ROC_IE_OT_SA_AUTH_NULL;
121                         break;
122                 case RTE_CRYPTO_AUTH_SHA1_HMAC:
123                         w2->s.auth_type = ROC_IE_OT_SA_AUTH_SHA1;
124                         ipsec_hmac_opad_ipad_gen(auth_xfrm, hmac_opad_ipad);
125
126                         tmp_key = (uint64_t *)hmac_opad_ipad;
127                         for (i = 0; i < (int)(ROC_CTX_MAX_OPAD_IPAD_LEN /
128                                               sizeof(uint64_t));
129                              i++)
130                                 tmp_key[i] = rte_be_to_cpu_64(tmp_key[i]);
131                         break;
132                 default:
133                         return -ENOTSUP;
134                 }
135
136                 key = cipher_xfrm->cipher.key.data;
137                 length = cipher_xfrm->cipher.key.length;
138         }
139
140         /* Set encapsulation type */
141         if (ipsec_xfrm->options.udp_encap)
142                 w2->s.encap_type = ROC_IE_OT_SA_ENCAP_UDP;
143
144         w2->s.spi = ipsec_xfrm->spi;
145
146         /* Copy encryption key */
147         memcpy(cipher_key, key, length);
148         tmp_key = (uint64_t *)cipher_key;
149         for (i = 0; i < (int)(ROC_CTX_MAX_CKEY_LEN / sizeof(uint64_t)); i++)
150                 tmp_key[i] = rte_be_to_cpu_64(tmp_key[i]);
151
152         switch (length) {
153         case ROC_CPT_AES128_KEY_LEN:
154                 w2->s.aes_key_len = ROC_IE_SA_AES_KEY_LEN_128;
155                 break;
156         case ROC_CPT_AES192_KEY_LEN:
157                 w2->s.aes_key_len = ROC_IE_SA_AES_KEY_LEN_192;
158                 break;
159         case ROC_CPT_AES256_KEY_LEN:
160                 w2->s.aes_key_len = ROC_IE_SA_AES_KEY_LEN_256;
161                 break;
162         default:
163                 return -EINVAL;
164         }
165
166         if (ipsec_xfrm->life.packets_soft_limit != 0 ||
167             ipsec_xfrm->life.packets_hard_limit != 0) {
168                 if (ipsec_xfrm->life.bytes_soft_limit != 0 ||
169                     ipsec_xfrm->life.bytes_hard_limit != 0) {
170                         plt_err("Expiry tracking with both packets & bytes is not supported");
171                         return -EINVAL;
172                 }
173                 w2->s.life_unit = ROC_IE_OT_SA_LIFE_UNIT_PKTS;
174         }
175
176         if (ipsec_xfrm->life.bytes_soft_limit != 0 ||
177             ipsec_xfrm->life.bytes_hard_limit != 0) {
178                 if (ipsec_xfrm->life.packets_soft_limit != 0 ||
179                     ipsec_xfrm->life.packets_hard_limit != 0) {
180                         plt_err("Expiry tracking with both packets & bytes is not supported");
181                         return -EINVAL;
182                 }
183                 w2->s.life_unit = ROC_IE_OT_SA_LIFE_UNIT_OCTETS;
184         }
185
186         return 0;
187 }
188
189 static size_t
190 ot_ipsec_inb_ctx_size(struct roc_ot_ipsec_inb_sa *sa)
191 {
192         size_t size;
193
194         /* Variable based on Anti-replay Window */
195         size = offsetof(struct roc_ot_ipsec_inb_sa, ctx) +
196                offsetof(struct roc_ot_ipsec_inb_ctx_update_reg, ar_winbits);
197
198         if (sa->w0.s.ar_win)
199                 size += (1 << (sa->w0.s.ar_win - 1)) * sizeof(uint64_t);
200
201         return size;
202 }
203
204 static int
205 ot_ipsec_inb_tunnel_hdr_fill(struct roc_ot_ipsec_inb_sa *sa,
206                              struct rte_security_ipsec_xform *ipsec_xfrm)
207 {
208         struct rte_security_ipsec_tunnel_param *tunnel;
209
210         if (ipsec_xfrm->mode != RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
211                 return 0;
212
213         if (ipsec_xfrm->options.tunnel_hdr_verify == 0)
214                 return 0;
215
216         tunnel = &ipsec_xfrm->tunnel;
217
218         switch (tunnel->type) {
219         case RTE_SECURITY_IPSEC_TUNNEL_IPV4:
220                 sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_4;
221                 memcpy(&sa->outer_hdr.ipv4.src_addr, &tunnel->ipv4.src_ip,
222                        sizeof(struct in_addr));
223                 memcpy(&sa->outer_hdr.ipv4.dst_addr, &tunnel->ipv4.dst_ip,
224                        sizeof(struct in_addr));
225
226                 /* IP Source and Dest are in LE/CPU endian */
227                 sa->outer_hdr.ipv4.src_addr =
228                         rte_be_to_cpu_32(sa->outer_hdr.ipv4.src_addr);
229                 sa->outer_hdr.ipv4.dst_addr =
230                         rte_be_to_cpu_32(sa->outer_hdr.ipv4.dst_addr);
231
232                 break;
233         case RTE_SECURITY_IPSEC_TUNNEL_IPV6:
234                 sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_6;
235                 memcpy(&sa->outer_hdr.ipv6.src_addr, &tunnel->ipv6.src_addr,
236                        sizeof(struct in6_addr));
237                 memcpy(&sa->outer_hdr.ipv6.dst_addr, &tunnel->ipv6.dst_addr,
238                        sizeof(struct in6_addr));
239
240                 break;
241         default:
242                 return -EINVAL;
243         }
244
245         switch (ipsec_xfrm->options.tunnel_hdr_verify) {
246         case RTE_SECURITY_IPSEC_TUNNEL_VERIFY_DST_ADDR:
247                 sa->w2.s.ip_hdr_verify = ROC_IE_OT_SA_IP_HDR_VERIFY_DST_ADDR;
248                 break;
249         case RTE_SECURITY_IPSEC_TUNNEL_VERIFY_SRC_DST_ADDR:
250                 sa->w2.s.ip_hdr_verify =
251                         ROC_IE_OT_SA_IP_HDR_VERIFY_SRC_DST_ADDR;
252                 break;
253         default:
254                 return -ENOTSUP;
255         }
256
257         return 0;
258 }
259
260 int
261 cnxk_ot_ipsec_inb_sa_fill(struct roc_ot_ipsec_inb_sa *sa,
262                           struct rte_security_ipsec_xform *ipsec_xfrm,
263                           struct rte_crypto_sym_xform *crypto_xfrm)
264 {
265         union roc_ot_ipsec_sa_word2 w2;
266         uint32_t replay_win_sz;
267         size_t offset;
268         int rc;
269
270         w2.u64 = 0;
271         rc = ot_ipsec_sa_common_param_fill(&w2, sa->cipher_key, sa->w8.s.salt,
272                                            sa->hmac_opad_ipad, ipsec_xfrm,
273                                            crypto_xfrm);
274         if (rc)
275                 return rc;
276
277         /* Updata common word2 data */
278         sa->w2.u64 = w2.u64;
279
280         /* Only support power-of-two window sizes supported */
281         replay_win_sz = ipsec_xfrm->replay_win_sz;
282         if (replay_win_sz) {
283                 if (!rte_is_power_of_2(replay_win_sz) ||
284                     replay_win_sz > ROC_AR_WIN_SIZE_MAX)
285                         return -ENOTSUP;
286
287                 sa->w0.s.ar_win = rte_log2_u32(replay_win_sz) - 5;
288         }
289
290         rc = ot_ipsec_inb_tunnel_hdr_fill(sa, ipsec_xfrm);
291         if (rc)
292                 return rc;
293
294         /* Default options for pkt_out and pkt_fmt are with
295          * second pass meta and no defrag.
296          */
297         sa->w0.s.pkt_format = ROC_IE_OT_SA_PKT_FMT_META;
298         sa->w0.s.pkt_output = ROC_IE_OT_SA_PKT_OUTPUT_HW_BASED_DEFRAG;
299         sa->w0.s.pkind = ROC_OT_CPT_META_PKIND;
300
301         /* ESN */
302         sa->w2.s.esn_en = !!ipsec_xfrm->options.esn;
303         if (ipsec_xfrm->options.udp_encap) {
304                 sa->w10.s.udp_src_port = 4500;
305                 sa->w10.s.udp_dst_port = 4500;
306         }
307
308         if (ipsec_xfrm->options.udp_ports_verify)
309                 sa->w2.s.udp_ports_verify = 1;
310
311         offset = offsetof(struct roc_ot_ipsec_inb_sa, ctx);
312         /* Word offset for HW managed SA field */
313         sa->w0.s.hw_ctx_off = offset / 8;
314         /* Context push size for inbound spans up to hw_ctx including
315          * ar_base field, in 8b units
316          */
317         sa->w0.s.ctx_push_size = sa->w0.s.hw_ctx_off + 1;
318         /* Entire context size in 128B units */
319         sa->w0.s.ctx_size =
320                 (PLT_ALIGN_CEIL(ot_ipsec_inb_ctx_size(sa), ROC_CTX_UNIT_128B) /
321                  ROC_CTX_UNIT_128B) -
322                 1;
323
324         /**
325          * CPT MC triggers expiry when counter value changes from 2 to 1. To
326          * mitigate this behaviour add 1 to the life counter values provided.
327          */
328
329         if (ipsec_xfrm->life.bytes_soft_limit) {
330                 sa->ctx.soft_life = ipsec_xfrm->life.bytes_soft_limit + 1;
331                 sa->w0.s.soft_life_dec = 1;
332         }
333
334         if (ipsec_xfrm->life.packets_soft_limit) {
335                 sa->ctx.soft_life = ipsec_xfrm->life.packets_soft_limit + 1;
336                 sa->w0.s.soft_life_dec = 1;
337         }
338
339         if (ipsec_xfrm->life.bytes_hard_limit) {
340                 sa->ctx.hard_life = ipsec_xfrm->life.bytes_hard_limit + 1;
341                 sa->w0.s.hard_life_dec = 1;
342         }
343
344         if (ipsec_xfrm->life.packets_hard_limit) {
345                 sa->ctx.hard_life = ipsec_xfrm->life.packets_hard_limit + 1;
346                 sa->w0.s.hard_life_dec = 1;
347         }
348
349         /* There are two words of CPT_CTX_HW_S for ucode to skip */
350         sa->w0.s.ctx_hdr_size = 1;
351         sa->w0.s.aop_valid = 1;
352         sa->w0.s.et_ovrwr = 1;
353
354         rte_wmb();
355
356         /* Enable SA */
357         sa->w2.s.valid = 1;
358         return 0;
359 }
360
361 int
362 cnxk_ot_ipsec_outb_sa_fill(struct roc_ot_ipsec_outb_sa *sa,
363                            struct rte_security_ipsec_xform *ipsec_xfrm,
364                            struct rte_crypto_sym_xform *crypto_xfrm)
365 {
366         struct rte_security_ipsec_tunnel_param *tunnel = &ipsec_xfrm->tunnel;
367         union roc_ot_ipsec_sa_word2 w2;
368         size_t offset;
369         int rc;
370
371         w2.u64 = 0;
372         rc = ot_ipsec_sa_common_param_fill(&w2, sa->cipher_key, sa->iv.s.salt,
373                                            sa->hmac_opad_ipad, ipsec_xfrm,
374                                            crypto_xfrm);
375         if (rc)
376                 return rc;
377
378         /* Update common word2 data */
379         sa->w2.u64 = w2.u64;
380
381         if (ipsec_xfrm->mode != RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
382                 goto skip_tunnel_info;
383
384         /* Tunnel header info */
385         switch (tunnel->type) {
386         case RTE_SECURITY_IPSEC_TUNNEL_IPV4:
387                 sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_4;
388                 memcpy(&sa->outer_hdr.ipv4.src_addr, &tunnel->ipv4.src_ip,
389                        sizeof(struct in_addr));
390                 memcpy(&sa->outer_hdr.ipv4.dst_addr, &tunnel->ipv4.dst_ip,
391                        sizeof(struct in_addr));
392
393                 /* IP Source and Dest seems to be in LE/CPU endian */
394                 sa->outer_hdr.ipv4.src_addr =
395                         rte_be_to_cpu_32(sa->outer_hdr.ipv4.src_addr);
396                 sa->outer_hdr.ipv4.dst_addr =
397                         rte_be_to_cpu_32(sa->outer_hdr.ipv4.dst_addr);
398
399                 /* Outer header DF bit source */
400                 if (!ipsec_xfrm->options.copy_df) {
401                         sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
402                                 ROC_IE_OT_SA_COPY_FROM_SA;
403                         sa->w10.s.ipv4_df_or_ipv6_flw_lbl = tunnel->ipv4.df;
404                 } else {
405                         sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
406                                 ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
407                 }
408
409                 /* Outer header DSCP source */
410                 if (!ipsec_xfrm->options.copy_dscp) {
411                         sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_SA;
412                         sa->w10.s.dscp = tunnel->ipv4.dscp;
413                 } else {
414                         sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
415                 }
416                 break;
417         case RTE_SECURITY_IPSEC_TUNNEL_IPV6:
418                 sa->w2.s.outer_ip_ver = ROC_IE_SA_IP_VERSION_6;
419                 memcpy(&sa->outer_hdr.ipv6.src_addr, &tunnel->ipv6.src_addr,
420                        sizeof(struct in6_addr));
421                 memcpy(&sa->outer_hdr.ipv6.dst_addr, &tunnel->ipv6.dst_addr,
422                        sizeof(struct in6_addr));
423
424                 /* Outer header flow label source */
425                 if (!ipsec_xfrm->options.copy_flabel) {
426                         sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
427                                 ROC_IE_OT_SA_COPY_FROM_SA;
428
429                         sa->w10.s.ipv4_df_or_ipv6_flw_lbl = tunnel->ipv6.flabel;
430                 } else {
431                         sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
432                                 ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
433                 }
434
435                 /* Outer header DSCP source */
436                 if (!ipsec_xfrm->options.copy_dscp) {
437                         sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_SA;
438                         sa->w10.s.dscp = tunnel->ipv6.dscp;
439                 } else {
440                         sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
441                 }
442                 break;
443         default:
444                 return -EINVAL;
445         }
446
447         /* Default options of DSCP and Flow label/DF */
448         sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_SA;
449         sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src = ROC_IE_OT_SA_COPY_FROM_SA;
450
451 skip_tunnel_info:
452         /* ESN */
453         sa->w0.s.esn_en = !!ipsec_xfrm->options.esn;
454
455         if (ipsec_xfrm->options.udp_encap) {
456                 sa->w10.s.udp_src_port = 4500;
457                 sa->w10.s.udp_dst_port = 4500;
458         }
459
460         offset = offsetof(struct roc_ot_ipsec_outb_sa, ctx);
461         /* Word offset for HW managed SA field */
462         sa->w0.s.hw_ctx_off = offset / 8;
463         /* Context push size is up to hmac_opad_ipad */
464         sa->w0.s.ctx_push_size = sa->w0.s.hw_ctx_off;
465         /* Entire context size in 128B units */
466         offset = sizeof(struct roc_ot_ipsec_outb_sa);
467         sa->w0.s.ctx_size = (PLT_ALIGN_CEIL(offset, ROC_CTX_UNIT_128B) /
468                              ROC_CTX_UNIT_128B) -
469                             1;
470
471         /* IPID gen */
472         sa->w2.s.ipid_gen = 1;
473
474         /**
475          * CPT MC triggers expiry when counter value changes from 2 to 1. To
476          * mitigate this behaviour add 1 to the life counter values provided.
477          */
478
479         if (ipsec_xfrm->life.bytes_soft_limit) {
480                 sa->ctx.soft_life = ipsec_xfrm->life.bytes_soft_limit + 1;
481                 sa->w0.s.soft_life_dec = 1;
482         }
483
484         if (ipsec_xfrm->life.packets_soft_limit) {
485                 sa->ctx.soft_life = ipsec_xfrm->life.packets_soft_limit + 1;
486                 sa->w0.s.soft_life_dec = 1;
487         }
488
489         if (ipsec_xfrm->life.bytes_hard_limit) {
490                 sa->ctx.hard_life = ipsec_xfrm->life.bytes_hard_limit + 1;
491                 sa->w0.s.hard_life_dec = 1;
492         }
493
494         if (ipsec_xfrm->life.packets_hard_limit) {
495                 sa->ctx.hard_life = ipsec_xfrm->life.packets_hard_limit + 1;
496                 sa->w0.s.hard_life_dec = 1;
497         }
498
499         /* There are two words of CPT_CTX_HW_S for ucode to skip */
500         sa->w0.s.ctx_hdr_size = 1;
501         sa->w0.s.aop_valid = 1;
502
503         rte_wmb();
504
505         /* Enable SA */
506         sa->w2.s.valid = 1;
507         return 0;
508 }
509
510 bool
511 cnxk_ot_ipsec_inb_sa_valid(struct roc_ot_ipsec_inb_sa *sa)
512 {
513         return !!sa->w2.s.valid;
514 }
515
516 bool
517 cnxk_ot_ipsec_outb_sa_valid(struct roc_ot_ipsec_outb_sa *sa)
518 {
519         return !!sa->w2.s.valid;
520 }
521
522 static inline int
523 ipsec_xfrm_verify(struct rte_security_ipsec_xform *ipsec_xfrm,
524                   struct rte_crypto_sym_xform *crypto_xfrm)
525 {
526         if (crypto_xfrm->next == NULL)
527                 return -EINVAL;
528
529         if (ipsec_xfrm->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
530                 if (crypto_xfrm->type != RTE_CRYPTO_SYM_XFORM_AUTH ||
531                     crypto_xfrm->next->type != RTE_CRYPTO_SYM_XFORM_CIPHER)
532                         return -EINVAL;
533         } else {
534                 if (crypto_xfrm->type != RTE_CRYPTO_SYM_XFORM_CIPHER ||
535                     crypto_xfrm->next->type != RTE_CRYPTO_SYM_XFORM_AUTH)
536                         return -EINVAL;
537         }
538
539         return 0;
540 }
541
542 static int
543 onf_ipsec_sa_common_param_fill(struct roc_ie_onf_sa_ctl *ctl, uint8_t *salt,
544                                uint8_t *cipher_key, uint8_t *hmac_opad_ipad,
545                                struct rte_security_ipsec_xform *ipsec_xfrm,
546                                struct rte_crypto_sym_xform *crypto_xfrm)
547 {
548         struct rte_crypto_sym_xform *auth_xfrm, *cipher_xfrm;
549         int rc, length, auth_key_len;
550         const uint8_t *key = NULL;
551
552         /* Set direction */
553         switch (ipsec_xfrm->direction) {
554         case RTE_SECURITY_IPSEC_SA_DIR_INGRESS:
555                 ctl->direction = ROC_IE_SA_DIR_INBOUND;
556                 auth_xfrm = crypto_xfrm;
557                 cipher_xfrm = crypto_xfrm->next;
558                 break;
559         case RTE_SECURITY_IPSEC_SA_DIR_EGRESS:
560                 ctl->direction = ROC_IE_SA_DIR_OUTBOUND;
561                 cipher_xfrm = crypto_xfrm;
562                 auth_xfrm = crypto_xfrm->next;
563                 break;
564         default:
565                 return -EINVAL;
566         }
567
568         /* Set protocol - ESP vs AH */
569         switch (ipsec_xfrm->proto) {
570         case RTE_SECURITY_IPSEC_SA_PROTO_ESP:
571                 ctl->ipsec_proto = ROC_IE_SA_PROTOCOL_ESP;
572                 break;
573         case RTE_SECURITY_IPSEC_SA_PROTO_AH:
574                 return -ENOTSUP;
575         default:
576                 return -EINVAL;
577         }
578
579         /* Set mode - transport vs tunnel */
580         switch (ipsec_xfrm->mode) {
581         case RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT:
582                 ctl->ipsec_mode = ROC_IE_SA_MODE_TRANSPORT;
583                 break;
584         case RTE_SECURITY_IPSEC_SA_MODE_TUNNEL:
585                 ctl->ipsec_mode = ROC_IE_SA_MODE_TUNNEL;
586                 break;
587         default:
588                 return -EINVAL;
589         }
590
591         /* Set encryption algorithm */
592         if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
593                 length = crypto_xfrm->aead.key.length;
594
595                 switch (crypto_xfrm->aead.algo) {
596                 case RTE_CRYPTO_AEAD_AES_GCM:
597                         ctl->enc_type = ROC_IE_ON_SA_ENC_AES_GCM;
598                         ctl->auth_type = ROC_IE_ON_SA_AUTH_NULL;
599                         memcpy(salt, &ipsec_xfrm->salt, 4);
600                         key = crypto_xfrm->aead.key.data;
601                         break;
602                 default:
603                         return -ENOTSUP;
604                 }
605
606         } else {
607                 rc = ipsec_xfrm_verify(ipsec_xfrm, crypto_xfrm);
608                 if (rc)
609                         return rc;
610
611                 switch (cipher_xfrm->cipher.algo) {
612                 case RTE_CRYPTO_CIPHER_AES_CBC:
613                         ctl->enc_type = ROC_IE_ON_SA_ENC_AES_CBC;
614                         break;
615                 default:
616                         return -ENOTSUP;
617                 }
618
619                 switch (auth_xfrm->auth.algo) {
620                 case RTE_CRYPTO_AUTH_SHA1_HMAC:
621                         ctl->auth_type = ROC_IE_ON_SA_AUTH_SHA1;
622                         break;
623                 default:
624                         return -ENOTSUP;
625                 }
626                 auth_key_len = auth_xfrm->auth.key.length;
627                 if (auth_key_len < 20 || auth_key_len > 64)
628                         return -ENOTSUP;
629
630                 key = cipher_xfrm->cipher.key.data;
631                 length = cipher_xfrm->cipher.key.length;
632
633                 ipsec_hmac_opad_ipad_gen(auth_xfrm, hmac_opad_ipad);
634         }
635
636         switch (length) {
637         case ROC_CPT_AES128_KEY_LEN:
638                 ctl->aes_key_len = ROC_IE_SA_AES_KEY_LEN_128;
639                 break;
640         case ROC_CPT_AES192_KEY_LEN:
641                 ctl->aes_key_len = ROC_IE_SA_AES_KEY_LEN_192;
642                 break;
643         case ROC_CPT_AES256_KEY_LEN:
644                 ctl->aes_key_len = ROC_IE_SA_AES_KEY_LEN_256;
645                 break;
646         default:
647                 return -EINVAL;
648         }
649
650         memcpy(cipher_key, key, length);
651
652         if (ipsec_xfrm->options.esn)
653                 ctl->esn_en = 1;
654
655         ctl->spi = rte_cpu_to_be_32(ipsec_xfrm->spi);
656         return 0;
657 }
658
659 int
660 cnxk_onf_ipsec_inb_sa_fill(struct roc_onf_ipsec_inb_sa *sa,
661                            struct rte_security_ipsec_xform *ipsec_xfrm,
662                            struct rte_crypto_sym_xform *crypto_xfrm)
663 {
664         struct roc_ie_onf_sa_ctl *ctl = &sa->ctl;
665         int rc;
666
667         rc = onf_ipsec_sa_common_param_fill(ctl, sa->nonce, sa->cipher_key,
668                                             sa->hmac_key, ipsec_xfrm,
669                                             crypto_xfrm);
670         if (rc)
671                 return rc;
672
673         rte_wmb();
674
675         /* Enable SA */
676         ctl->valid = 1;
677         return 0;
678 }
679
680 int
681 cnxk_onf_ipsec_outb_sa_fill(struct roc_onf_ipsec_outb_sa *sa,
682                             struct rte_security_ipsec_xform *ipsec_xfrm,
683                             struct rte_crypto_sym_xform *crypto_xfrm)
684 {
685         struct rte_security_ipsec_tunnel_param *tunnel = &ipsec_xfrm->tunnel;
686         struct roc_ie_onf_sa_ctl *ctl = &sa->ctl;
687         int rc;
688
689         /* Fill common params */
690         rc = onf_ipsec_sa_common_param_fill(ctl, sa->nonce, sa->cipher_key,
691                                             sa->hmac_key, ipsec_xfrm,
692                                             crypto_xfrm);
693         if (rc)
694                 return rc;
695
696         if (ipsec_xfrm->mode != RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
697                 goto skip_tunnel_info;
698
699         /* Tunnel header info */
700         switch (tunnel->type) {
701         case RTE_SECURITY_IPSEC_TUNNEL_IPV4:
702                 memcpy(&sa->ip_src, &tunnel->ipv4.src_ip,
703                        sizeof(struct in_addr));
704                 memcpy(&sa->ip_dst, &tunnel->ipv4.dst_ip,
705                        sizeof(struct in_addr));
706                 break;
707         case RTE_SECURITY_IPSEC_TUNNEL_IPV6:
708                 return -ENOTSUP;
709         default:
710                 return -EINVAL;
711         }
712
713 skip_tunnel_info:
714         rte_wmb();
715
716         /* Enable SA */
717         ctl->valid = 1;
718         return 0;
719 }
720
721 bool
722 cnxk_onf_ipsec_inb_sa_valid(struct roc_onf_ipsec_inb_sa *sa)
723 {
724         return !!sa->ctl.valid;
725 }
726
727 bool
728 cnxk_onf_ipsec_outb_sa_valid(struct roc_onf_ipsec_outb_sa *sa)
729 {
730         return !!sa->ctl.valid;
731 }
732
733 uint8_t
734 cnxk_ipsec_ivlen_get(enum rte_crypto_cipher_algorithm c_algo,
735                      enum rte_crypto_auth_algorithm a_algo,
736                      enum rte_crypto_aead_algorithm aead_algo)
737 {
738         uint8_t ivlen = 0;
739
740         if (aead_algo == RTE_CRYPTO_AEAD_AES_GCM)
741                 ivlen = 8;
742
743         switch (c_algo) {
744         case RTE_CRYPTO_CIPHER_AES_CTR:
745                 ivlen = 8;
746                 break;
747         case RTE_CRYPTO_CIPHER_3DES_CBC:
748                 ivlen = ROC_CPT_DES_BLOCK_LENGTH;
749                 break;
750         case RTE_CRYPTO_CIPHER_AES_CBC:
751                 ivlen = ROC_CPT_AES_BLOCK_LENGTH;
752                 break;
753         default:
754                 break;
755         }
756
757         switch (a_algo) {
758         case RTE_CRYPTO_AUTH_AES_GMAC:
759                 ivlen = 8;
760                 break;
761         default:
762                 break;
763         }
764
765         return ivlen;
766 }
767
768 uint8_t
769 cnxk_ipsec_icvlen_get(enum rte_crypto_cipher_algorithm c_algo,
770                       enum rte_crypto_auth_algorithm a_algo,
771                       enum rte_crypto_aead_algorithm aead_algo)
772 {
773         uint8_t icv = 0;
774
775         (void)c_algo;
776
777         switch (a_algo) {
778         case RTE_CRYPTO_AUTH_NULL:
779                 icv = 0;
780                 break;
781         case RTE_CRYPTO_AUTH_SHA1_HMAC:
782                 icv = 12;
783                 break;
784         case RTE_CRYPTO_AUTH_SHA256_HMAC:
785         case RTE_CRYPTO_AUTH_AES_GMAC:
786                 icv = 16;
787                 break;
788         case RTE_CRYPTO_AUTH_SHA384_HMAC:
789                 icv = 24;
790                 break;
791         case RTE_CRYPTO_AUTH_SHA512_HMAC:
792                 icv = 32;
793                 break;
794         default:
795                 break;
796         }
797
798         switch (aead_algo) {
799         case RTE_CRYPTO_AEAD_AES_GCM:
800                 icv = 16;
801                 break;
802         default:
803                 break;
804         }
805
806         return icv;
807 }
808
809 uint8_t
810 cnxk_ipsec_outb_roundup_byte(enum rte_crypto_cipher_algorithm c_algo,
811                              enum rte_crypto_aead_algorithm aead_algo)
812 {
813         uint8_t roundup_byte = 4;
814
815         if (aead_algo == RTE_CRYPTO_AEAD_AES_GCM)
816                 return roundup_byte;
817
818         switch (c_algo) {
819         case RTE_CRYPTO_CIPHER_AES_CTR:
820                 roundup_byte = 4;
821                 break;
822         case RTE_CRYPTO_CIPHER_AES_CBC:
823                 roundup_byte = 16;
824                 break;
825         case RTE_CRYPTO_CIPHER_3DES_CBC:
826                 roundup_byte = 8;
827                 break;
828         case RTE_CRYPTO_CIPHER_NULL:
829                 roundup_byte = 4;
830                 break;
831         default:
832                 break;
833         }
834
835         return roundup_byte;
836 }
837
838 int
839 cnxk_ipsec_outb_rlens_get(struct cnxk_ipsec_outb_rlens *rlens,
840                           struct rte_security_ipsec_xform *ipsec_xfrm,
841                           struct rte_crypto_sym_xform *crypto_xfrm)
842 {
843         struct rte_security_ipsec_tunnel_param *tunnel = &ipsec_xfrm->tunnel;
844         enum rte_crypto_cipher_algorithm c_algo = RTE_CRYPTO_CIPHER_NULL;
845         enum rte_crypto_auth_algorithm a_algo = RTE_CRYPTO_AUTH_NULL;
846         enum rte_crypto_aead_algorithm aead_algo = 0;
847         uint16_t partial_len = 0;
848         uint8_t roundup_byte = 0;
849         int8_t roundup_len = 0;
850
851         memset(rlens, 0, sizeof(struct cnxk_ipsec_outb_rlens));
852
853         /* Get Cipher and Auth algo */
854         if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
855                 aead_algo = crypto_xfrm->aead.algo;
856         } else {
857                 if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_CIPHER)
858                         c_algo = crypto_xfrm->cipher.algo;
859                 else
860                         a_algo = crypto_xfrm->auth.algo;
861
862                 if (crypto_xfrm->next) {
863                         if (crypto_xfrm->next->type ==
864                             RTE_CRYPTO_SYM_XFORM_CIPHER)
865                                 c_algo = crypto_xfrm->next->cipher.algo;
866                         else
867                                 a_algo = crypto_xfrm->next->auth.algo;
868                 }
869         }
870
871         if (ipsec_xfrm->proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP) {
872                 partial_len = ROC_CPT_ESP_HDR_LEN;
873                 roundup_len = ROC_CPT_ESP_TRL_LEN;
874         } else {
875                 partial_len = ROC_CPT_AH_HDR_LEN;
876         }
877
878         if (ipsec_xfrm->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
879                 if (tunnel->type == RTE_SECURITY_IPSEC_TUNNEL_IPV4)
880                         partial_len += ROC_CPT_TUNNEL_IPV4_HDR_LEN;
881                 else
882                         partial_len += ROC_CPT_TUNNEL_IPV6_HDR_LEN;
883         }
884
885         partial_len += cnxk_ipsec_ivlen_get(c_algo, a_algo, aead_algo);
886         partial_len += cnxk_ipsec_icvlen_get(c_algo, a_algo, aead_algo);
887         roundup_byte = cnxk_ipsec_outb_roundup_byte(c_algo, aead_algo);
888
889         if (ipsec_xfrm->options.udp_encap)
890                 partial_len += sizeof(struct rte_udp_hdr);
891
892         rlens->partial_len = partial_len;
893         rlens->roundup_len = roundup_len;
894         rlens->roundup_byte = roundup_byte;
895         rlens->max_extended_len = partial_len + roundup_len + roundup_byte;
896         return 0;
897 }