1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2021 Marvell.
7 #include "cnxk_security.h"
10 ot_ipsec_sa_common_param_fill(union roc_ot_ipsec_sa_word2 *w2,
11 uint8_t *cipher_key, uint8_t *salt_key,
12 struct rte_security_ipsec_xform *ipsec_xfrm,
13 struct rte_crypto_sym_xform *crypto_xfrm)
21 switch (ipsec_xfrm->direction) {
22 case RTE_SECURITY_IPSEC_SA_DIR_INGRESS:
23 w2->s.dir = ROC_IE_OT_SA_DIR_INBOUND;
25 case RTE_SECURITY_IPSEC_SA_DIR_EGRESS:
26 w2->s.dir = ROC_IE_OT_SA_DIR_OUTBOUND;
32 /* Set protocol - ESP vs AH */
33 switch (ipsec_xfrm->proto) {
34 case RTE_SECURITY_IPSEC_SA_PROTO_ESP:
35 w2->s.protocol = ROC_IE_OT_SA_PROTOCOL_ESP;
37 case RTE_SECURITY_IPSEC_SA_PROTO_AH:
38 w2->s.protocol = ROC_IE_OT_SA_PROTOCOL_AH;
44 /* Set mode - transport vs tunnel */
45 switch (ipsec_xfrm->mode) {
46 case RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT:
47 w2->s.mode = ROC_IE_OT_SA_MODE_TRANSPORT;
49 case RTE_SECURITY_IPSEC_SA_MODE_TUNNEL:
50 w2->s.mode = ROC_IE_OT_SA_MODE_TUNNEL;
56 /* Set encryption algorithm */
57 if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
58 key = crypto_xfrm->aead.key.data;
59 length = crypto_xfrm->aead.key.length;
61 switch (crypto_xfrm->aead.algo) {
62 case RTE_CRYPTO_AEAD_AES_GCM:
63 w2->s.enc_type = ROC_IE_OT_SA_ENC_AES_GCM;
64 w2->s.auth_type = ROC_IE_OT_SA_AUTH_NULL;
65 memcpy(salt_key, &ipsec_xfrm->salt, 4);
66 tmp_salt = (uint32_t *)salt_key;
67 *tmp_salt = rte_be_to_cpu_32(*tmp_salt);
76 /* Set encapsulation type */
77 if (ipsec_xfrm->options.udp_encap)
78 w2->s.encap_type = ROC_IE_OT_SA_ENCAP_UDP;
80 w2->s.spi = ipsec_xfrm->spi;
82 /* Copy encryption key */
83 memcpy(cipher_key, key, length);
84 tmp_key = (uint64_t *)cipher_key;
85 for (i = 0; i < (int)(ROC_CTX_MAX_CKEY_LEN / sizeof(uint64_t)); i++)
86 tmp_key[i] = rte_be_to_cpu_64(tmp_key[i]);
89 case ROC_CPT_AES128_KEY_LEN:
90 w2->s.aes_key_len = ROC_IE_OT_SA_AES_KEY_LEN_128;
92 case ROC_CPT_AES192_KEY_LEN:
93 w2->s.aes_key_len = ROC_IE_OT_SA_AES_KEY_LEN_192;
95 case ROC_CPT_AES256_KEY_LEN:
96 w2->s.aes_key_len = ROC_IE_OT_SA_AES_KEY_LEN_256;
106 ot_ipsec_inb_ctx_size(struct roc_ot_ipsec_inb_sa *sa)
110 /* Variable based on Anti-replay Window */
111 size = offsetof(struct roc_ot_ipsec_inb_sa, ctx) +
112 offsetof(struct roc_ot_ipsec_inb_ctx_update_reg, ar_winbits);
115 size += (1 << (sa->w0.s.ar_win - 1)) * sizeof(uint64_t);
121 cnxk_ot_ipsec_inb_sa_fill(struct roc_ot_ipsec_inb_sa *sa,
122 struct rte_security_ipsec_xform *ipsec_xfrm,
123 struct rte_crypto_sym_xform *crypto_xfrm)
125 union roc_ot_ipsec_sa_word2 w2;
126 uint32_t replay_win_sz;
131 rc = ot_ipsec_sa_common_param_fill(&w2, sa->cipher_key, sa->w8.s.salt,
132 ipsec_xfrm, crypto_xfrm);
136 /* Updata common word2 data */
139 /* Only support power-of-two window sizes supported */
140 replay_win_sz = ipsec_xfrm->replay_win_sz;
142 if (!rte_is_power_of_2(replay_win_sz) ||
143 replay_win_sz > ROC_AR_WIN_SIZE_MAX)
146 sa->w0.s.ar_win = rte_log2_u32(replay_win_sz) - 5;
149 /* Default options for pkt_out and pkt_fmt are with
150 * second pass meta and no defrag.
152 sa->w0.s.pkt_format = ROC_IE_OT_SA_PKT_FMT_META;
153 sa->w0.s.pkt_output = ROC_IE_OT_SA_PKT_OUTPUT_HW_BASED_DEFRAG;
154 sa->w0.s.pkind = ROC_OT_CPT_META_PKIND;
157 sa->w2.s.esn_en = !!ipsec_xfrm->options.esn;
158 if (ipsec_xfrm->options.udp_encap) {
159 sa->w10.s.udp_src_port = 4500;
160 sa->w10.s.udp_dst_port = 4500;
163 offset = offsetof(struct roc_ot_ipsec_inb_sa, ctx);
164 /* Word offset for HW managed SA field */
165 sa->w0.s.hw_ctx_off = offset / 8;
166 /* Context push size for inbound spans up to hw_ctx including
167 * ar_base field, in 8b units
169 sa->w0.s.ctx_push_size = sa->w0.s.hw_ctx_off + 1;
170 /* Entire context size in 128B units */
172 (PLT_ALIGN_CEIL(ot_ipsec_inb_ctx_size(sa), ROC_CTX_UNIT_128B) /
176 /* There are two words of CPT_CTX_HW_S for ucode to skip */
177 sa->w0.s.ctx_hdr_size = 1;
178 sa->w0.s.aop_valid = 1;
188 cnxk_ot_ipsec_outb_sa_fill(struct roc_ot_ipsec_outb_sa *sa,
189 struct rte_security_ipsec_xform *ipsec_xfrm,
190 struct rte_crypto_sym_xform *crypto_xfrm)
192 struct rte_security_ipsec_tunnel_param *tunnel = &ipsec_xfrm->tunnel;
193 union roc_ot_ipsec_sa_word2 w2;
198 rc = ot_ipsec_sa_common_param_fill(&w2, sa->cipher_key, sa->iv.s.salt,
199 ipsec_xfrm, crypto_xfrm);
203 /* Update common word2 data */
206 if (ipsec_xfrm->mode != RTE_SECURITY_IPSEC_SA_MODE_TUNNEL)
207 goto skip_tunnel_info;
209 /* Tunnel header info */
210 switch (tunnel->type) {
211 case RTE_SECURITY_IPSEC_TUNNEL_IPV4:
212 sa->w2.s.outer_ip_ver = ROC_IE_OT_SA_IP_VERSION_4;
213 memcpy(&sa->outer_hdr.ipv4.src_addr, &tunnel->ipv4.src_ip,
214 sizeof(struct in_addr));
215 memcpy(&sa->outer_hdr.ipv4.dst_addr, &tunnel->ipv4.dst_ip,
216 sizeof(struct in_addr));
218 /* IP Source and Dest seems to be in LE/CPU endian */
219 sa->outer_hdr.ipv4.src_addr =
220 rte_be_to_cpu_32(sa->outer_hdr.ipv4.src_addr);
221 sa->outer_hdr.ipv4.dst_addr =
222 rte_be_to_cpu_32(sa->outer_hdr.ipv4.dst_addr);
224 /* Outer header DF bit source */
225 if (!ipsec_xfrm->options.copy_df) {
226 sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
227 ROC_IE_OT_SA_COPY_FROM_SA;
228 sa->w10.s.ipv4_df_or_ipv6_flw_lbl = tunnel->ipv4.df;
230 sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
231 ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
234 /* Outer header DSCP source */
235 if (!ipsec_xfrm->options.copy_dscp) {
236 sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_SA;
237 sa->w10.s.dscp = tunnel->ipv4.dscp;
239 sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
242 case RTE_SECURITY_IPSEC_TUNNEL_IPV6:
243 sa->w2.s.outer_ip_ver = ROC_IE_OT_SA_IP_VERSION_6;
244 memcpy(&sa->outer_hdr.ipv6.src_addr, &tunnel->ipv6.src_addr,
245 sizeof(struct in6_addr));
246 memcpy(&sa->outer_hdr.ipv6.dst_addr, &tunnel->ipv6.dst_addr,
247 sizeof(struct in6_addr));
249 /* Outer header flow label source */
250 if (!ipsec_xfrm->options.copy_flabel) {
251 sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
252 ROC_IE_OT_SA_COPY_FROM_SA;
254 sa->w10.s.ipv4_df_or_ipv6_flw_lbl = tunnel->ipv6.flabel;
256 sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src =
257 ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
260 /* Outer header DSCP source */
261 if (!ipsec_xfrm->options.copy_dscp) {
262 sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_SA;
263 sa->w10.s.dscp = tunnel->ipv6.dscp;
265 sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_INNER_IP_HDR;
272 /* Default options of DSCP and Flow label/DF */
273 sa->w2.s.dscp_src = ROC_IE_OT_SA_COPY_FROM_SA;
274 sa->w2.s.ipv4_df_src_or_ipv6_flw_lbl_src = ROC_IE_OT_SA_COPY_FROM_SA;
278 sa->w0.s.esn_en = !!ipsec_xfrm->options.esn;
280 if (ipsec_xfrm->options.udp_encap) {
281 sa->w10.s.udp_src_port = 4500;
282 sa->w10.s.udp_dst_port = 4500;
285 offset = offsetof(struct roc_ot_ipsec_outb_sa, ctx);
286 /* Word offset for HW managed SA field */
287 sa->w0.s.hw_ctx_off = offset / 8;
288 /* Context push size is up to hmac_opad_ipad */
289 sa->w0.s.ctx_push_size = sa->w0.s.hw_ctx_off;
290 /* Entire context size in 128B units */
291 offset = sizeof(struct roc_ot_ipsec_outb_sa);
292 sa->w0.s.ctx_size = (PLT_ALIGN_CEIL(offset, ROC_CTX_UNIT_128B) /
297 sa->w2.s.ipid_gen = 1;
299 /* There are two words of CPT_CTX_HW_S for ucode to skip */
300 sa->w0.s.ctx_hdr_size = 1;
301 sa->w0.s.aop_valid = 1;
311 cnxk_ot_ipsec_inb_sa_valid(struct roc_ot_ipsec_inb_sa *sa)
313 return !!sa->w2.s.valid;
317 cnxk_ot_ipsec_outb_sa_valid(struct roc_ot_ipsec_outb_sa *sa)
319 return !!sa->w2.s.valid;
323 cnxk_ipsec_ivlen_get(enum rte_crypto_cipher_algorithm c_algo,
324 enum rte_crypto_auth_algorithm a_algo,
325 enum rte_crypto_aead_algorithm aead_algo)
329 if (aead_algo == RTE_CRYPTO_AEAD_AES_GCM)
333 case RTE_CRYPTO_CIPHER_AES_CTR:
336 case RTE_CRYPTO_CIPHER_3DES_CBC:
337 ivlen = ROC_CPT_DES_BLOCK_LENGTH;
339 case RTE_CRYPTO_CIPHER_AES_CBC:
340 ivlen = ROC_CPT_AES_BLOCK_LENGTH;
347 case RTE_CRYPTO_AUTH_AES_GMAC:
358 cnxk_ipsec_icvlen_get(enum rte_crypto_cipher_algorithm c_algo,
359 enum rte_crypto_auth_algorithm a_algo,
360 enum rte_crypto_aead_algorithm aead_algo)
367 case RTE_CRYPTO_AUTH_NULL:
370 case RTE_CRYPTO_AUTH_SHA1_HMAC:
373 case RTE_CRYPTO_AUTH_SHA256_HMAC:
374 case RTE_CRYPTO_AUTH_AES_GMAC:
377 case RTE_CRYPTO_AUTH_SHA384_HMAC:
380 case RTE_CRYPTO_AUTH_SHA512_HMAC:
388 case RTE_CRYPTO_AEAD_AES_GCM:
399 cnxk_ipsec_outb_roundup_byte(enum rte_crypto_cipher_algorithm c_algo,
400 enum rte_crypto_aead_algorithm aead_algo)
402 uint8_t roundup_byte = 4;
404 if (aead_algo == RTE_CRYPTO_AEAD_AES_GCM)
408 case RTE_CRYPTO_CIPHER_AES_CTR:
411 case RTE_CRYPTO_CIPHER_AES_CBC:
414 case RTE_CRYPTO_CIPHER_3DES_CBC:
417 case RTE_CRYPTO_CIPHER_NULL:
428 cnxk_ipsec_outb_rlens_get(struct cnxk_ipsec_outb_rlens *rlens,
429 struct rte_security_ipsec_xform *ipsec_xfrm,
430 struct rte_crypto_sym_xform *crypto_xfrm)
432 struct rte_security_ipsec_tunnel_param *tunnel = &ipsec_xfrm->tunnel;
433 enum rte_crypto_cipher_algorithm c_algo = RTE_CRYPTO_CIPHER_NULL;
434 enum rte_crypto_auth_algorithm a_algo = RTE_CRYPTO_AUTH_NULL;
435 enum rte_crypto_aead_algorithm aead_algo = 0;
436 uint16_t partial_len = 0;
437 uint8_t roundup_byte = 0;
438 int8_t roundup_len = 0;
440 memset(rlens, 0, sizeof(struct cnxk_ipsec_outb_rlens));
442 /* Get Cipher and Auth algo */
443 if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
444 aead_algo = crypto_xfrm->aead.algo;
446 if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_CIPHER)
447 c_algo = crypto_xfrm->cipher.algo;
449 a_algo = crypto_xfrm->auth.algo;
451 if (crypto_xfrm->next) {
452 if (crypto_xfrm->next->type ==
453 RTE_CRYPTO_SYM_XFORM_CIPHER)
454 c_algo = crypto_xfrm->next->cipher.algo;
456 a_algo = crypto_xfrm->next->auth.algo;
460 if (ipsec_xfrm->proto == RTE_SECURITY_IPSEC_SA_PROTO_ESP) {
461 partial_len = ROC_CPT_ESP_HDR_LEN;
462 roundup_len = ROC_CPT_ESP_TRL_LEN;
464 partial_len = ROC_CPT_AH_HDR_LEN;
467 if (ipsec_xfrm->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
468 if (tunnel->type == RTE_SECURITY_IPSEC_TUNNEL_IPV4)
469 partial_len += ROC_CPT_TUNNEL_IPV4_HDR_LEN;
471 partial_len += ROC_CPT_TUNNEL_IPV6_HDR_LEN;
474 partial_len += cnxk_ipsec_ivlen_get(c_algo, a_algo, aead_algo);
475 partial_len += cnxk_ipsec_icvlen_get(c_algo, a_algo, aead_algo);
476 roundup_byte = cnxk_ipsec_outb_roundup_byte(c_algo, aead_algo);
478 if (ipsec_xfrm->options.udp_encap)
479 partial_len += sizeof(struct rte_udp_hdr);
481 rlens->partial_len = partial_len;
482 rlens->roundup_len = roundup_len;
483 rlens->roundup_byte = roundup_byte;
484 rlens->max_extended_len = partial_len + roundup_len + roundup_byte;