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