2 * Copyright 2008-2016 Freescale Semiconductor, Inc.
4 * SPDX-License-Identifier: BSD-3-Clause or GPL-2.0+
7 #ifndef __DESC_IPSEC_H__
8 #define __DESC_IPSEC_H__
14 * DOC: IPsec Shared Descriptor Constructors
16 * Shared descriptors for IPsec protocol.
19 /* General IPSec ESP encap / decap PDB options */
22 * PDBOPTS_ESP_ESN - Extended sequence included
24 #define PDBOPTS_ESP_ESN 0x10
27 * PDBOPTS_ESP_IPVSN - Process IPv6 header
29 * Valid only for IPsec legacy mode.
31 #define PDBOPTS_ESP_IPVSN 0x02
34 * PDBOPTS_ESP_TUNNEL - Tunnel mode next-header byte
36 * Valid only for IPsec legacy mode.
38 #define PDBOPTS_ESP_TUNNEL 0x01
40 /* IPSec ESP Encap PDB options */
43 * PDBOPTS_ESP_UPDATE_CSUM - Update ip header checksum
45 * Valid only for IPsec legacy mode.
47 #define PDBOPTS_ESP_UPDATE_CSUM 0x80
50 * PDBOPTS_ESP_DIFFSERV - Copy TOS/TC from inner iphdr
52 * Valid only for IPsec legacy mode.
54 #define PDBOPTS_ESP_DIFFSERV 0x40
57 * PDBOPTS_ESP_IVSRC - IV comes from internal random gen
59 #define PDBOPTS_ESP_IVSRC 0x20
62 * PDBOPTS_ESP_IPHDRSRC - IP header comes from PDB
64 * Valid only for IPsec legacy mode.
66 #define PDBOPTS_ESP_IPHDRSRC 0x08
69 * PDBOPTS_ESP_INCIPHDR - Prepend IP header to output frame
71 * Valid only for IPsec legacy mode.
73 #define PDBOPTS_ESP_INCIPHDR 0x04
76 * PDBOPTS_ESP_OIHI_MASK - Mask for Outer IP Header Included
78 * Valid only for IPsec new mode.
80 #define PDBOPTS_ESP_OIHI_MASK 0x0c
83 * PDBOPTS_ESP_OIHI_PDB_INL - Prepend IP header to output frame from PDB (where
86 * Valid only for IPsec new mode.
88 #define PDBOPTS_ESP_OIHI_PDB_INL 0x0c
91 * PDBOPTS_ESP_OIHI_PDB_REF - Prepend IP header to output frame from PDB
92 * (referenced by pointer).
94 * Vlid only for IPsec new mode.
96 #define PDBOPTS_ESP_OIHI_PDB_REF 0x08
99 * PDBOPTS_ESP_OIHI_IF - Prepend IP header to output frame from input frame
101 * Valid only for IPsec new mode.
103 #define PDBOPTS_ESP_OIHI_IF 0x04
106 * PDBOPTS_ESP_NAT - Enable RFC 3948 UDP-encapsulated-ESP
108 * Valid only for IPsec new mode.
110 #define PDBOPTS_ESP_NAT 0x02
113 * PDBOPTS_ESP_NUC - Enable NAT UDP Checksum
115 * Valid only for IPsec new mode.
117 #define PDBOPTS_ESP_NUC 0x01
119 /* IPSec ESP Decap PDB options */
122 * PDBOPTS_ESP_ARS_MASK - antireplay window mask
124 #define PDBOPTS_ESP_ARS_MASK 0xc0
127 * PDBOPTS_ESP_ARSNONE - No antireplay window
129 #define PDBOPTS_ESP_ARSNONE 0x00
132 * PDBOPTS_ESP_ARS64 - 64-entry antireplay window
134 #define PDBOPTS_ESP_ARS64 0xc0
137 * PDBOPTS_ESP_ARS128 - 128-entry antireplay window
139 * Valid only for IPsec new mode.
141 #define PDBOPTS_ESP_ARS128 0x80
144 * PDBOPTS_ESP_ARS32 - 32-entry antireplay window
146 #define PDBOPTS_ESP_ARS32 0x40
149 * PDBOPTS_ESP_VERIFY_CSUM - Validate ip header checksum
151 * Valid only for IPsec legacy mode.
153 #define PDBOPTS_ESP_VERIFY_CSUM 0x20
156 * PDBOPTS_ESP_TECN - Implement RRFC6040 ECN tunneling from outer header to
159 * Valid only for IPsec new mode.
161 #define PDBOPTS_ESP_TECN 0x20
164 * PDBOPTS_ESP_OUTFMT - Output only decapsulation
166 * Valid only for IPsec legacy mode.
168 #define PDBOPTS_ESP_OUTFMT 0x08
171 * PDBOPTS_ESP_AOFL - Adjust out frame len
173 * Valid only for IPsec legacy mode and for SEC >= 5.3.
175 #define PDBOPTS_ESP_AOFL 0x04
178 * PDBOPTS_ESP_ETU - EtherType Update
180 * Add corresponding ethertype (0x0800 for IPv4, 0x86dd for IPv6) in the output
182 * Valid only for IPsec new mode.
184 #define PDBOPTS_ESP_ETU 0x01
186 #define PDBHMO_ESP_DECAP_SHIFT 28
187 #define PDBHMO_ESP_ENCAP_SHIFT 28
188 #define PDBNH_ESP_ENCAP_SHIFT 16
189 #define PDBNH_ESP_ENCAP_MASK (0xff << PDBNH_ESP_ENCAP_SHIFT)
190 #define PDBHDRLEN_ESP_DECAP_SHIFT 16
191 #define PDBHDRLEN_MASK (0x0fff << PDBHDRLEN_ESP_DECAP_SHIFT)
192 #define PDB_NH_OFFSET_SHIFT 8
193 #define PDB_NH_OFFSET_MASK (0xff << PDB_NH_OFFSET_SHIFT)
196 * PDBHMO_ESP_DECAP_DTTL - IPsec ESP decrement TTL (IPv4) / Hop limit (IPv6)
199 #define PDBHMO_ESP_DECAP_DTTL (0x02 << PDBHMO_ESP_DECAP_SHIFT)
202 * PDBHMO_ESP_ENCAP_DTTL - IPsec ESP increment TTL (IPv4) / Hop limit (IPv6)
205 #define PDBHMO_ESP_ENCAP_DTTL (0x02 << PDBHMO_ESP_ENCAP_SHIFT)
208 * PDBHMO_ESP_DIFFSERV - (Decap) DiffServ Copy - Copy the IPv4 TOS or IPv6
209 * Traffic Class byte from the outer IP header to the
212 #define PDBHMO_ESP_DIFFSERV (0x01 << PDBHMO_ESP_DECAP_SHIFT)
215 * PDBHMO_ESP_SNR - (Encap) - Sequence Number Rollover control
217 * Configures behaviour in case of SN / ESN rollover:
218 * error if SNR = 1, rollover allowed if SNR = 0.
219 * Valid only for IPsec new mode.
221 #define PDBHMO_ESP_SNR (0x01 << PDBHMO_ESP_ENCAP_SHIFT)
224 * PDBHMO_ESP_DFBIT - (Encap) Copy DF bit - if an IPv4 tunnel mode outer IP
225 * header is coming from the PDB, copy the DF bit from the
226 * inner IP header to the outer IP header.
228 #define PDBHMO_ESP_DFBIT (0x04 << PDBHMO_ESP_ENCAP_SHIFT)
231 * PDBHMO_ESP_DFV - (Decap) - DF bit value
233 * If ODF = 1, DF bit in output frame is replaced by DFV.
234 * Valid only from SEC Era 5 onwards.
236 #define PDBHMO_ESP_DFV (0x04 << PDBHMO_ESP_DECAP_SHIFT)
239 * PDBHMO_ESP_ODF - (Decap) Override DF bit in IPv4 header of decapsulated
242 * If ODF = 1, DF is replaced with the value of DFV bit.
243 * Valid only from SEC Era 5 onwards.
245 #define PDBHMO_ESP_ODF (0x08 << PDBHMO_ESP_DECAP_SHIFT)
248 * struct ipsec_encap_cbc - PDB part for IPsec CBC encapsulation
249 * @iv: 16-byte array initialization vector
251 struct ipsec_encap_cbc {
257 * struct ipsec_encap_ctr - PDB part for IPsec CTR encapsulation
258 * @ctr_nonce: 4-byte array nonce
259 * @ctr_initial: initial count constant
260 * @iv: initialization vector
262 struct ipsec_encap_ctr {
263 uint8_t ctr_nonce[4];
264 uint32_t ctr_initial;
269 * struct ipsec_encap_ccm - PDB part for IPsec CCM encapsulation
270 * @salt: 3-byte array salt (lower 24 bits)
271 * @ccm_opt: CCM algorithm options - MSB-LSB description:
272 * b0_flags (8b) - CCM B0; use 0x5B for 8-byte ICV, 0x6B for 12-byte ICV,
273 * 0x7B for 16-byte ICV (cf. RFC4309, RFC3610)
274 * ctr_flags (8b) - counter flags; constant equal to 0x3
275 * ctr_initial (16b) - initial count constant
276 * @iv: initialization vector
278 struct ipsec_encap_ccm {
285 * struct ipsec_encap_gcm - PDB part for IPsec GCM encapsulation
286 * @salt: 3-byte array salt (lower 24 bits)
287 * @rsvd: reserved, do not use
288 * @iv: initialization vector
290 struct ipsec_encap_gcm {
297 * struct ipsec_encap_pdb - PDB for IPsec encapsulation
298 * @options: MSB-LSB description (both for legacy and new modes)
299 * hmo (header manipulation options) - 4b
301 * next header (legacy) / reserved (new) - 8b
302 * next header offset (legacy) / AOIPHO (actual outer IP header offset) - 8b
303 * option flags (depend on selected algorithm) - 8b
304 * @seq_num_ext_hi: (optional) IPsec Extended Sequence Number (ESN)
305 * @seq_num: IPsec sequence number
306 * @spi: IPsec SPI (Security Parameters Index)
307 * @ip_hdr_len: optional IP Header length (in bytes)
309 * Opt. IP Hdr Len - 16b
310 * @ip_hdr: optional IP Header content (only for IPsec legacy mode)
312 struct ipsec_encap_pdb {
314 uint32_t seq_num_ext_hi;
317 struct ipsec_encap_cbc cbc;
318 struct ipsec_encap_ctr ctr;
319 struct ipsec_encap_ccm ccm;
320 struct ipsec_encap_gcm gcm;
327 static inline unsigned int
328 __rta_copy_ipsec_encap_pdb(struct program *program,
329 struct ipsec_encap_pdb *pdb,
332 unsigned int start_pc = program->current_pc;
334 __rta_out32(program, pdb->options);
335 __rta_out32(program, pdb->seq_num_ext_hi);
336 __rta_out32(program, pdb->seq_num);
338 switch (algtype & OP_PCL_IPSEC_CIPHER_MASK) {
339 case OP_PCL_IPSEC_DES_IV64:
340 case OP_PCL_IPSEC_DES:
341 case OP_PCL_IPSEC_3DES:
342 case OP_PCL_IPSEC_AES_CBC:
343 case OP_PCL_IPSEC_NULL:
344 rta_copy_data(program, pdb->cbc.iv, sizeof(pdb->cbc.iv));
347 case OP_PCL_IPSEC_AES_CTR:
348 rta_copy_data(program, pdb->ctr.ctr_nonce,
349 sizeof(pdb->ctr.ctr_nonce));
350 __rta_out32(program, pdb->ctr.ctr_initial);
351 __rta_out64(program, true, pdb->ctr.iv);
354 case OP_PCL_IPSEC_AES_CCM8:
355 case OP_PCL_IPSEC_AES_CCM12:
356 case OP_PCL_IPSEC_AES_CCM16:
357 rta_copy_data(program, pdb->ccm.salt, sizeof(pdb->ccm.salt));
358 __rta_out32(program, pdb->ccm.ccm_opt);
359 __rta_out64(program, true, pdb->ccm.iv);
362 case OP_PCL_IPSEC_AES_GCM8:
363 case OP_PCL_IPSEC_AES_GCM12:
364 case OP_PCL_IPSEC_AES_GCM16:
365 case OP_PCL_IPSEC_AES_NULL_WITH_GMAC:
366 rta_copy_data(program, pdb->gcm.salt, sizeof(pdb->gcm.salt));
367 __rta_out32(program, pdb->gcm.rsvd);
368 __rta_out64(program, true, pdb->gcm.iv);
372 __rta_out32(program, pdb->spi);
373 __rta_out32(program, pdb->ip_hdr_len);
379 * struct ipsec_decap_cbc - PDB part for IPsec CBC decapsulation
380 * @rsvd: reserved, do not use
382 struct ipsec_decap_cbc {
387 * struct ipsec_decap_ctr - PDB part for IPsec CTR decapsulation
388 * @ctr_nonce: 4-byte array nonce
389 * @ctr_initial: initial count constant
391 struct ipsec_decap_ctr {
392 uint8_t ctr_nonce[4];
393 uint32_t ctr_initial;
397 * struct ipsec_decap_ccm - PDB part for IPsec CCM decapsulation
398 * @salt: 3-byte salt (lower 24 bits)
399 * @ccm_opt: CCM algorithm options - MSB-LSB description:
400 * b0_flags (8b) - CCM B0; use 0x5B for 8-byte ICV, 0x6B for 12-byte ICV,
401 * 0x7B for 16-byte ICV (cf. RFC4309, RFC3610)
402 * ctr_flags (8b) - counter flags; constant equal to 0x3
403 * ctr_initial (16b) - initial count constant
405 struct ipsec_decap_ccm {
411 * struct ipsec_decap_gcm - PDB part for IPsec GCN decapsulation
413 * @rsvd: reserved, do not use
415 struct ipsec_decap_gcm {
421 * struct ipsec_decap_pdb - PDB for IPsec decapsulation
422 * @options: MSB-LSB description (both for legacy and new modes)
423 * hmo (header manipulation options) - 4b
424 * IP header length - 12b
425 * next header offset (legacy) / AOIPHO (actual outer IP header offset) - 8b
426 * option flags (depend on selected algorithm) - 8b
427 * @seq_num_ext_hi: (optional) IPsec Extended Sequence Number (ESN)
428 * @seq_num: IPsec sequence number
429 * @anti_replay: Anti-replay window; size depends on ARS (option flags);
430 * format must be Big Endian, irrespective of platform
432 struct ipsec_decap_pdb {
435 struct ipsec_decap_cbc cbc;
436 struct ipsec_decap_ctr ctr;
437 struct ipsec_decap_ccm ccm;
438 struct ipsec_decap_gcm gcm;
440 uint32_t seq_num_ext_hi;
442 uint32_t anti_replay[4];
445 static inline unsigned int
446 __rta_copy_ipsec_decap_pdb(struct program *program,
447 struct ipsec_decap_pdb *pdb,
450 unsigned int start_pc = program->current_pc;
453 __rta_out32(program, pdb->options);
455 switch (algtype & OP_PCL_IPSEC_CIPHER_MASK) {
456 case OP_PCL_IPSEC_DES_IV64:
457 case OP_PCL_IPSEC_DES:
458 case OP_PCL_IPSEC_3DES:
459 case OP_PCL_IPSEC_AES_CBC:
460 case OP_PCL_IPSEC_NULL:
461 __rta_out32(program, pdb->cbc.rsvd[0]);
462 __rta_out32(program, pdb->cbc.rsvd[1]);
465 case OP_PCL_IPSEC_AES_CTR:
466 rta_copy_data(program, pdb->ctr.ctr_nonce,
467 sizeof(pdb->ctr.ctr_nonce));
468 __rta_out32(program, pdb->ctr.ctr_initial);
471 case OP_PCL_IPSEC_AES_CCM8:
472 case OP_PCL_IPSEC_AES_CCM12:
473 case OP_PCL_IPSEC_AES_CCM16:
474 rta_copy_data(program, pdb->ccm.salt, sizeof(pdb->ccm.salt));
475 __rta_out32(program, pdb->ccm.ccm_opt);
478 case OP_PCL_IPSEC_AES_GCM8:
479 case OP_PCL_IPSEC_AES_GCM12:
480 case OP_PCL_IPSEC_AES_GCM16:
481 case OP_PCL_IPSEC_AES_NULL_WITH_GMAC:
482 rta_copy_data(program, pdb->gcm.salt, sizeof(pdb->gcm.salt));
483 __rta_out32(program, pdb->gcm.rsvd);
487 __rta_out32(program, pdb->seq_num_ext_hi);
488 __rta_out32(program, pdb->seq_num);
490 switch (pdb->options & PDBOPTS_ESP_ARS_MASK) {
491 case PDBOPTS_ESP_ARS128:
494 case PDBOPTS_ESP_ARS64:
497 case PDBOPTS_ESP_ARS32:
500 case PDBOPTS_ESP_ARSNONE:
506 for (i = 0; i < ars; i++)
507 __rta_out_be32(program, pdb->anti_replay[i]);
513 * enum ipsec_icv_size - Type selectors for icv size in IPsec protocol
514 * @IPSEC_ICV_MD5_SIZE: full-length MD5 ICV
515 * @IPSEC_ICV_MD5_TRUNC_SIZE: truncated MD5 ICV
517 enum ipsec_icv_size {
518 IPSEC_ICV_MD5_SIZE = 16,
519 IPSEC_ICV_MD5_TRUNC_SIZE = 12
523 * IPSec ESP Datapath Protocol Override Register (DPOVRD)
526 #define IPSEC_DECO_DPOVRD_USE 0x80
528 struct ipsec_deco_dpovrd {
533 uint8_t next_header; /* next header if encap */
534 uint8_t rsvd; /* reserved if decap */
538 struct ipsec_new_encap_deco_dpovrd {
539 #define IPSEC_NEW_ENCAP_DECO_DPOVRD_USE 0x8000
540 uint16_t ovrd_ip_hdr_len; /* OVRD + outer IP header material
543 #define IPSEC_NEW_ENCAP_OIMIF 0x80
544 uint8_t oimif_aoipho; /* OIMIF + actual outer IP header
550 struct ipsec_new_decap_deco_dpovrd {
552 uint8_t aoipho_hi; /* upper nibble of actual outer IP
555 uint16_t aoipho_lo_ip_hdr_len; /* lower nibble of actual outer IP
556 * header + outer IP header material
561 __gen_auth_key(struct program *program, struct alginfo *authdata)
565 switch (authdata->algtype & OP_PCL_IPSEC_AUTH_MASK) {
566 case OP_PCL_IPSEC_HMAC_MD5_96:
567 case OP_PCL_IPSEC_HMAC_MD5_128:
568 dkp_protid = OP_PCLID_DKP_MD5;
570 case OP_PCL_IPSEC_HMAC_SHA1_96:
571 case OP_PCL_IPSEC_HMAC_SHA1_160:
572 dkp_protid = OP_PCLID_DKP_SHA1;
574 case OP_PCL_IPSEC_HMAC_SHA2_256_128:
575 dkp_protid = OP_PCLID_DKP_SHA256;
577 case OP_PCL_IPSEC_HMAC_SHA2_384_192:
578 dkp_protid = OP_PCLID_DKP_SHA384;
580 case OP_PCL_IPSEC_HMAC_SHA2_512_256:
581 dkp_protid = OP_PCLID_DKP_SHA512;
584 KEY(program, KEY2, authdata->key_enc_flags, authdata->key,
585 authdata->keylen, INLINE_KEY(authdata));
589 if (authdata->key_type == RTA_DATA_PTR)
590 DKP_PROTOCOL(program, dkp_protid, OP_PCL_DKP_SRC_PTR,
591 OP_PCL_DKP_DST_PTR, (uint16_t)authdata->keylen,
592 authdata->key, authdata->key_type);
594 DKP_PROTOCOL(program, dkp_protid, OP_PCL_DKP_SRC_IMM,
595 OP_PCL_DKP_DST_IMM, (uint16_t)authdata->keylen,
596 authdata->key, authdata->key_type);
600 * cnstr_shdsc_ipsec_encap - IPSec ESP encapsulation protocol-level shared
602 * @descbuf: pointer to buffer used for descriptor construction
603 * @ps: if 36/40bit addressing is desired, this parameter must be true
604 * @swap: if true, perform descriptor byte swapping on a 4-byte boundary
605 * @pdb: pointer to the PDB to be used with this descriptor
606 * This structure will be copied inline to the descriptor under
607 * construction. No error checking will be made. Refer to the
608 * block guide for a details of the encapsulation PDB.
609 * @cipherdata: pointer to block cipher transform definitions
610 * Valid algorithm values - one of OP_PCL_IPSEC_*
611 * @authdata: pointer to authentication transform definitions
612 * If an authentication key is required by the protocol:
613 * -For SEC Eras 1-5, an MDHA split key must be provided;
614 * Note that the size of the split key itself must be specified.
615 * -For SEC Eras 6+, a "normal" key must be provided; DKP (Derived
616 * Key Protocol) will be used to compute MDHA on the fly in HW.
617 * Valid algorithm values - one of OP_PCL_IPSEC_*
619 * Return: size of descriptor written in words or negative number on error
622 cnstr_shdsc_ipsec_encap(uint32_t *descbuf, bool ps, bool swap,
623 struct ipsec_encap_pdb *pdb,
624 struct alginfo *cipherdata,
625 struct alginfo *authdata)
628 struct program *p = &prg;
635 PROGRAM_CNTXT_INIT(p, descbuf, 0);
637 PROGRAM_SET_BSWAP(p);
639 PROGRAM_SET_36BIT_ADDR(p);
640 phdr = SHR_HDR(p, SHR_SERIAL, hdr, 0);
641 __rta_copy_ipsec_encap_pdb(p, pdb, cipherdata->algtype);
642 COPY_DATA(p, pdb->ip_hdr, pdb->ip_hdr_len);
644 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, BOTH|SHRD);
645 if (authdata->keylen) {
646 if (rta_sec_era < RTA_SEC_ERA_6)
647 KEY(p, MDHA_SPLIT_KEY, authdata->key_enc_flags,
648 authdata->key, authdata->keylen,
649 INLINE_KEY(authdata));
651 __gen_auth_key(p, authdata);
653 if (cipherdata->keylen)
654 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
655 cipherdata->keylen, INLINE_KEY(cipherdata));
656 SET_LABEL(p, keyjmp);
657 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
659 (uint16_t)(cipherdata->algtype | authdata->algtype));
660 PATCH_JUMP(p, pkeyjmp, keyjmp);
661 PATCH_HDR(p, phdr, hdr);
662 return PROGRAM_FINALIZE(p);
666 * cnstr_shdsc_ipsec_decap - IPSec ESP decapsulation protocol-level shared
668 * @descbuf: pointer to buffer used for descriptor construction
669 * @ps: if 36/40bit addressing is desired, this parameter must be true
670 * @swap: if true, perform descriptor byte swapping on a 4-byte boundary
671 * @pdb: pointer to the PDB to be used with this descriptor
672 * This structure will be copied inline to the descriptor under
673 * construction. No error checking will be made. Refer to the
674 * block guide for details about the decapsulation PDB.
675 * @cipherdata: pointer to block cipher transform definitions.
676 * Valid algorithm values - one of OP_PCL_IPSEC_*
677 * @authdata: pointer to authentication transform definitions
678 * If an authentication key is required by the protocol:
679 * -For SEC Eras 1-5, an MDHA split key must be provided;
680 * Note that the size of the split key itself must be specified.
681 * -For SEC Eras 6+, a "normal" key must be provided; DKP (Derived
682 * Key Protocol) will be used to compute MDHA on the fly in HW.
683 * Valid algorithm values - one of OP_PCL_IPSEC_*
685 * Return: size of descriptor written in words or negative number on error
688 cnstr_shdsc_ipsec_decap(uint32_t *descbuf, bool ps, bool swap,
689 struct ipsec_decap_pdb *pdb,
690 struct alginfo *cipherdata,
691 struct alginfo *authdata)
694 struct program *p = &prg;
701 PROGRAM_CNTXT_INIT(p, descbuf, 0);
703 PROGRAM_SET_BSWAP(p);
705 PROGRAM_SET_36BIT_ADDR(p);
706 phdr = SHR_HDR(p, SHR_SERIAL, hdr, 0);
707 __rta_copy_ipsec_decap_pdb(p, pdb, cipherdata->algtype);
709 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, BOTH|SHRD);
710 if (authdata->keylen) {
711 if (rta_sec_era < RTA_SEC_ERA_6)
712 KEY(p, MDHA_SPLIT_KEY, authdata->key_enc_flags,
713 authdata->key, authdata->keylen,
714 INLINE_KEY(authdata));
716 __gen_auth_key(p, authdata);
718 if (cipherdata->keylen)
719 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
720 cipherdata->keylen, INLINE_KEY(cipherdata));
721 SET_LABEL(p, keyjmp);
722 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
724 (uint16_t)(cipherdata->algtype | authdata->algtype));
725 PATCH_JUMP(p, pkeyjmp, keyjmp);
726 PATCH_HDR(p, phdr, hdr);
727 return PROGRAM_FINALIZE(p);
731 * cnstr_shdsc_ipsec_encap_des_aes_xcbc - IPSec DES-CBC/3DES-CBC and
732 * AES-XCBC-MAC-96 ESP encapsulation shared descriptor.
733 * @descbuf: pointer to buffer used for descriptor construction
734 * @pdb: pointer to the PDB to be used with this descriptor
735 * This structure will be copied inline to the descriptor under
736 * construction. No error checking will be made. Refer to the
737 * block guide for a details of the encapsulation PDB.
738 * @cipherdata: pointer to block cipher transform definitions
739 * Valid algorithm values - OP_PCL_IPSEC_DES, OP_PCL_IPSEC_3DES.
740 * @authdata: pointer to authentication transform definitions
741 * Valid algorithm value: OP_PCL_IPSEC_AES_XCBC_MAC_96.
743 * Supported only for platforms with 32-bit address pointers and SEC ERA 4 or
744 * higher. The tunnel/transport mode of the IPsec ESP is supported only if the
745 * Outer/Transport IP Header is present in the encapsulation output packet.
746 * The descriptor performs DES-CBC/3DES-CBC & HMAC-MD5-96 and then rereads
747 * the input packet to do the AES-XCBC-MAC-96 calculation and to overwrite
749 * The descriptor uses all the benefits of the built-in protocol by computing
750 * the IPsec ESP with a hardware supported algorithms combination
751 * (DES-CBC/3DES-CBC & HMAC-MD5-96). The HMAC-MD5 authentication algorithm
752 * was chosen in order to speed up the computational time for this intermediate
754 * Warning: The user must allocate at least 32 bytes for the authentication key
755 * (in order to use it also with HMAC-MD5-96),even when using a shorter key
756 * for the AES-XCBC-MAC-96.
758 * Return: size of descriptor written in words or negative number on error
761 cnstr_shdsc_ipsec_encap_des_aes_xcbc(uint32_t *descbuf,
762 struct ipsec_encap_pdb *pdb,
763 struct alginfo *cipherdata,
764 struct alginfo *authdata)
767 struct program *p = &prg;
773 LABEL(swapped_seqin_fields);
774 LABEL(swapped_seqin_ptr);
777 REFERENCE(move_outlen);
778 REFERENCE(move_seqout_ptr);
779 REFERENCE(swapped_seqin_ptr_jump);
780 REFERENCE(write_swapped_seqin_ptr);
782 PROGRAM_CNTXT_INIT(p, descbuf, 0);
783 phdr = SHR_HDR(p, SHR_SERIAL, hdr, 0);
784 __rta_copy_ipsec_encap_pdb(p, pdb, cipherdata->algtype);
785 COPY_DATA(p, pdb->ip_hdr, pdb->ip_hdr_len);
787 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF);
789 * Hard-coded KEY arguments. The descriptor uses all the benefits of
790 * the built-in protocol by computing the IPsec ESP with a hardware
791 * supported algorithms combination (DES-CBC/3DES-CBC & HMAC-MD5-96).
792 * The HMAC-MD5 authentication algorithm was chosen with
793 * the keys options from below in order to speed up the computational
794 * time for this intermediate step.
795 * Warning: The user must allocate at least 32 bytes for
796 * the authentication key (in order to use it also with HMAC-MD5-96),
797 * even when using a shorter key for the AES-XCBC-MAC-96.
799 KEY(p, MDHA_SPLIT_KEY, 0, authdata->key, 32, INLINE_KEY(authdata));
800 SET_LABEL(p, keyjump);
801 LOAD(p, LDST_SRCDST_WORD_CLRW | CLRW_CLR_C1MODE | CLRW_CLR_C1DATAS |
802 CLRW_CLR_C1CTX | CLRW_CLR_C1KEY | CLRW_RESET_CLS1_CHA, CLRW, 0, 4,
804 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
805 cipherdata->keylen, INLINE_KEY(cipherdata));
806 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL, OP_PCLID_IPSEC,
807 (uint16_t)(cipherdata->algtype | OP_PCL_IPSEC_HMAC_MD5_96));
808 /* Swap SEQINPTR to SEQOUTPTR. */
809 move_seqout_ptr = MOVE(p, DESCBUF, 0, MATH1, 0, 16, WAITCOMP | IMMED);
810 MATHB(p, MATH1, AND, ~(CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR), MATH1,
813 * TODO: RTA currently doesn't support creating a LOAD command
814 * with another command as IMM.
815 * To be changed when proper support is added in RTA.
817 LOAD(p, 0xa00000e5, MATH3, 4, 4, IMMED);
818 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
819 write_swapped_seqin_ptr = MOVE(p, MATH1, 0, DESCBUF, 0, 20, WAITCOMP |
821 swapped_seqin_ptr_jump = JUMP(p, swapped_seqin_ptr, LOCAL_JUMP,
823 LOAD(p, LDST_SRCDST_WORD_CLRW | CLRW_CLR_C1MODE | CLRW_CLR_C1DATAS |
824 CLRW_CLR_C1CTX | CLRW_CLR_C1KEY | CLRW_RESET_CLS1_CHA, CLRW, 0, 4,
826 SEQOUTPTR(p, 0, 65535, RTO);
827 move_outlen = MOVE(p, DESCBUF, 0, MATH0, 4, 8, WAITCOMP | IMMED);
829 (uint64_t)(pdb->ip_hdr_len + IPSEC_ICV_MD5_TRUNC_SIZE),
830 VSEQINSZ, 4, IMMED2);
831 MATHB(p, MATH0, SUB, IPSEC_ICV_MD5_TRUNC_SIZE, VSEQOUTSZ, 4, IMMED2);
832 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, authdata->keylen,
834 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_XCBC_MAC,
835 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
836 SEQFIFOLOAD(p, SKIP, pdb->ip_hdr_len, 0);
837 SEQFIFOLOAD(p, MSG1, 0, VLF | FLUSH1 | LAST1);
838 SEQFIFOSTORE(p, SKIP, 0, 0, VLF);
839 SEQSTORE(p, CONTEXT1, 0, IPSEC_ICV_MD5_TRUNC_SIZE, 0);
841 * TODO: RTA currently doesn't support adding labels in or after Job Descriptor.
842 * To be changed when proper support is added in RTA.
844 /* Label the Shared Descriptor Pointer */
845 SET_LABEL(p, shd_ptr);
847 /* Label the Output Pointer */
848 SET_LABEL(p, outptr);
850 /* Label the first word after JD */
851 SET_LABEL(p, swapped_seqin_fields);
852 swapped_seqin_fields += 8;
853 /* Label the second word after JD */
854 SET_LABEL(p, swapped_seqin_ptr);
855 swapped_seqin_ptr += 9;
857 PATCH_HDR(p, phdr, hdr);
858 PATCH_JUMP(p, pkeyjump, keyjump);
859 PATCH_JUMP(p, swapped_seqin_ptr_jump, swapped_seqin_ptr);
860 PATCH_MOVE(p, move_outlen, outptr);
861 PATCH_MOVE(p, move_seqout_ptr, shd_ptr);
862 PATCH_MOVE(p, write_swapped_seqin_ptr, swapped_seqin_fields);
863 return PROGRAM_FINALIZE(p);
867 * cnstr_shdsc_ipsec_decap_des_aes_xcbc - IPSec DES-CBC/3DES-CBC and
868 * AES-XCBC-MAC-96 ESP decapsulation shared descriptor.
869 * @descbuf: pointer to buffer used for descriptor construction
870 * @pdb: pointer to the PDB to be used with this descriptor
871 * This structure will be copied inline to the descriptor under
872 * construction. No error checking will be made. Refer to the
873 * block guide for a details of the encapsulation PDB.
874 * @cipherdata: pointer to block cipher transform definitions
875 * Valid algorithm values - OP_PCL_IPSEC_DES, OP_PCL_IPSEC_3DES.
876 * @authdata: pointer to authentication transform definitions
877 * Valid algorithm value: OP_PCL_IPSEC_AES_XCBC_MAC_96.
879 * Supported only for platforms with 32-bit address pointers and SEC ERA 4 or
880 * higher. The tunnel/transport mode of the IPsec ESP is supported only if the
881 * Outer/Transport IP Header is present in the decapsulation input packet.
882 * The descriptor computes the AES-XCBC-MAC-96 to check if the received ICV
883 * is correct, rereads the input packet to compute the MD5 ICV, overwrites
884 * the XCBC ICV, and then sends the modified input packet to the
885 * DES-CBC/3DES-CBC & HMAC-MD5-96 IPsec.
886 * The descriptor uses all the benefits of the built-in protocol by computing
887 * the IPsec ESP with a hardware supported algorithms combination
888 * (DES-CBC/3DES-CBC & HMAC-MD5-96). The HMAC-MD5 authentication algorithm
889 * was chosen in order to speed up the computational time for this intermediate
891 * Warning: The user must allocate at least 32 bytes for the authentication key
892 * (in order to use it also with HMAC-MD5-96),even when using a shorter key
893 * for the AES-XCBC-MAC-96.
895 * Return: size of descriptor written in words or negative number on error
898 cnstr_shdsc_ipsec_decap_des_aes_xcbc(uint32_t *descbuf,
899 struct ipsec_decap_pdb *pdb,
900 struct alginfo *cipherdata,
901 struct alginfo *authdata)
904 struct program *p = &prg;
905 uint32_t ip_hdr_len = (pdb->options & PDBHDRLEN_MASK) >>
906 PDBHDRLEN_ESP_DECAP_SHIFT;
914 LABEL(swapped_seqout_fields);
915 LABEL(swapped_seqout_ptr);
916 REFERENCE(seqout_ptr_jump);
919 REFERENCE(move_jump);
920 REFERENCE(move_jump_back);
921 REFERENCE(move_seqin_ptr);
922 REFERENCE(swapped_seqout_ptr_jump);
923 REFERENCE(write_swapped_seqout_ptr);
925 PROGRAM_CNTXT_INIT(p, descbuf, 0);
926 phdr = SHR_HDR(p, SHR_SERIAL, hdr, 0);
927 __rta_copy_ipsec_decap_pdb(p, pdb, cipherdata->algtype);
929 pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF);
931 * Hard-coded KEY arguments. The descriptor uses all the benefits of
932 * the built-in protocol by computing the IPsec ESP with a hardware
933 * supported algorithms combination (DES-CBC/3DES-CBC & HMAC-MD5-96).
934 * The HMAC-MD5 authentication algorithm was chosen with
935 * the keys options from bellow in order to speed up the computational
936 * time for this intermediate step.
937 * Warning: The user must allocate at least 32 bytes for
938 * the authentication key (in order to use it also with HMAC-MD5-96),
939 * even when using a shorter key for the AES-XCBC-MAC-96.
941 KEY(p, MDHA_SPLIT_KEY, 0, authdata->key, 32, INLINE_KEY(authdata));
942 SET_LABEL(p, keyjump);
943 LOAD(p, LDST_SRCDST_WORD_CLRW | CLRW_CLR_C1MODE | CLRW_CLR_C1DATAS |
944 CLRW_CLR_C1CTX | CLRW_CLR_C1KEY | CLRW_RESET_CLS1_CHA, CLRW, 0, 4,
946 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, authdata->keylen,
947 INLINE_KEY(authdata));
948 MATHB(p, SEQINSZ, SUB,
949 (uint64_t)(ip_hdr_len + IPSEC_ICV_MD5_TRUNC_SIZE), MATH0, 4,
951 MATHB(p, MATH0, SUB, ZERO, VSEQINSZ, 4, 0);
952 ALG_OPERATION(p, OP_ALG_ALGSEL_MD5, OP_ALG_AAI_HMAC_PRECOMP,
953 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
954 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_XCBC_MAC,
955 OP_ALG_AS_INITFINAL, ICV_CHECK_ENABLE, DIR_DEC);
956 SEQFIFOLOAD(p, SKIP, ip_hdr_len, 0);
957 SEQFIFOLOAD(p, MSG1, 0, VLF | FLUSH1);
958 SEQFIFOLOAD(p, ICV1, IPSEC_ICV_MD5_TRUNC_SIZE, FLUSH1 | LAST1);
959 /* Swap SEQOUTPTR to SEQINPTR. */
960 move_seqin_ptr = MOVE(p, DESCBUF, 0, MATH1, 0, 16, WAITCOMP | IMMED);
961 MATHB(p, MATH1, OR, CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR, MATH1, 8,
964 * TODO: RTA currently doesn't support creating a LOAD command
965 * with another command as IMM.
966 * To be changed when proper support is added in RTA.
968 LOAD(p, 0xA00000e1, MATH3, 4, 4, IMMED);
969 MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
970 write_swapped_seqout_ptr = MOVE(p, MATH1, 0, DESCBUF, 0, 20, WAITCOMP |
972 swapped_seqout_ptr_jump = JUMP(p, swapped_seqout_ptr, LOCAL_JUMP,
975 * TODO: To be changed when proper support is added in RTA (can't load
976 * a command that is also written by RTA).
977 * Change when proper RTA support is added.
979 SET_LABEL(p, jump_cmd);
981 SEQINPTR(p, 0, 65535, RTO);
982 MATHB(p, MATH0, SUB, ZERO, VSEQINSZ, 4, 0);
983 MATHB(p, MATH0, ADD, ip_hdr_len, VSEQOUTSZ, 4, IMMED2);
984 move_jump = MOVE(p, DESCBUF, 0, OFIFO, 0, 8, WAITCOMP | IMMED);
985 move_jump_back = MOVE(p, OFIFO, 0, DESCBUF, 0, 8, IMMED);
986 SEQFIFOLOAD(p, SKIP, ip_hdr_len, 0);
987 SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2);
988 SEQFIFOSTORE(p, SKIP, 0, 0, VLF);
989 SEQSTORE(p, CONTEXT2, 0, IPSEC_ICV_MD5_TRUNC_SIZE, 0);
990 seqout_ptr_jump = JUMP(p, seqout_ptr, LOCAL_JUMP, ALL_TRUE, CALM);
992 LOAD(p, LDST_SRCDST_WORD_CLRW | CLRW_CLR_C1MODE | CLRW_CLR_C1DATAS |
993 CLRW_CLR_C1CTX | CLRW_CLR_C1KEY | CLRW_CLR_C2MODE |
994 CLRW_CLR_C2DATAS | CLRW_CLR_C2CTX | CLRW_RESET_CLS1_CHA, CLRW, 0,
996 SEQINPTR(p, 0, 65535, RTO);
998 (uint64_t)(ip_hdr_len + IPSEC_ICV_MD5_TRUNC_SIZE), SEQINSZ, 4,
1000 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1001 cipherdata->keylen, INLINE_KEY(cipherdata));
1002 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL, OP_PCLID_IPSEC,
1003 (uint16_t)(cipherdata->algtype | OP_PCL_IPSEC_HMAC_MD5_96));
1005 * TODO: RTA currently doesn't support adding labels in or after Job Descriptor.
1006 * To be changed when proper support is added in RTA.
1008 /* Label the SEQ OUT PTR */
1009 SET_LABEL(p, seqout_ptr);
1011 /* Label the Output Length */
1012 SET_LABEL(p, outlen);
1014 /* Label the SEQ IN PTR */
1015 SET_LABEL(p, seqin_ptr);
1017 /* Label the first word after JD */
1018 SET_LABEL(p, swapped_seqout_fields);
1019 swapped_seqout_fields += 8;
1020 /* Label the second word after JD */
1021 SET_LABEL(p, swapped_seqout_ptr);
1022 swapped_seqout_ptr += 9;
1024 PATCH_HDR(p, phdr, hdr);
1025 PATCH_JUMP(p, pkeyjump, keyjump);
1026 PATCH_JUMP(p, seqout_ptr_jump, seqout_ptr);
1027 PATCH_JUMP(p, swapped_seqout_ptr_jump, swapped_seqout_ptr);
1028 PATCH_MOVE(p, move_jump, jump_cmd);
1029 PATCH_MOVE(p, move_jump_back, seqin_ptr);
1030 PATCH_MOVE(p, move_seqin_ptr, outlen);
1031 PATCH_MOVE(p, write_swapped_seqout_ptr, swapped_seqout_fields);
1032 return PROGRAM_FINALIZE(p);
1036 * IPSEC_NEW_ENC_BASE_DESC_LEN - IPsec new mode encap shared descriptor length
1038 * Accounts only for the "base" commands and is intended to be used by upper
1039 * layers to determine whether Outer IP Header and/or keys can be inlined or
1040 * not. To be used as first parameter of rta_inline_query().
1042 #define IPSEC_NEW_ENC_BASE_DESC_LEN (5 * CAAM_CMD_SZ + \
1043 sizeof(struct ipsec_encap_pdb))
1046 * IPSEC_NEW_NULL_ENC_BASE_DESC_LEN - IPsec new mode encap shared descriptor
1047 * length for the case of
1048 * NULL encryption / authentication
1050 * Accounts only for the "base" commands and is intended to be used by upper
1051 * layers to determine whether Outer IP Header and/or key can be inlined or
1052 * not. To be used as first parameter of rta_inline_query().
1054 #define IPSEC_NEW_NULL_ENC_BASE_DESC_LEN (4 * CAAM_CMD_SZ + \
1055 sizeof(struct ipsec_encap_pdb))
1058 * cnstr_shdsc_ipsec_new_encap - IPSec new mode ESP encapsulation
1059 * protocol-level shared descriptor.
1060 * @descbuf: pointer to buffer used for descriptor construction
1061 * @ps: if 36/40bit addressing is desired, this parameter must be true
1062 * @swap: must be true when core endianness doesn't match SEC endianness
1063 * @pdb: pointer to the PDB to be used with this descriptor
1064 * This structure will be copied inline to the descriptor under
1065 * construction. No error checking will be made. Refer to the
1066 * block guide for details about the encapsulation PDB.
1067 * @opt_ip_hdr: pointer to Optional IP Header
1068 * -if OIHI = PDBOPTS_ESP_OIHI_PDB_INL, opt_ip_hdr points to the buffer to
1069 * be inlined in the PDB. Number of bytes (buffer size) copied is provided
1070 * in pdb->ip_hdr_len.
1071 * -if OIHI = PDBOPTS_ESP_OIHI_PDB_REF, opt_ip_hdr points to the address of
1072 * the Optional IP Header. The address will be inlined in the PDB verbatim.
1073 * -for other values of OIHI options field, opt_ip_hdr is not used.
1074 * @cipherdata: pointer to block cipher transform definitions
1075 * Valid algorithm values - one of OP_PCL_IPSEC_*
1076 * @authdata: pointer to authentication transform definitions.
1077 * If an authentication key is required by the protocol, a "normal"
1078 * key must be provided; DKP (Derived Key Protocol) will be used to
1079 * compute MDHA on the fly in HW.
1080 * Valid algorithm values - one of OP_PCL_IPSEC_*
1082 * Return: size of descriptor written in words or negative number on error
1085 cnstr_shdsc_ipsec_new_encap(uint32_t *descbuf, bool ps,
1087 struct ipsec_encap_pdb *pdb,
1088 uint8_t *opt_ip_hdr,
1089 struct alginfo *cipherdata,
1090 struct alginfo *authdata)
1093 struct program *p = &prg;
1100 if (rta_sec_era < RTA_SEC_ERA_8) {
1101 pr_err("IPsec new mode encap: available only for Era %d or above\n",
1102 USER_SEC_ERA(RTA_SEC_ERA_8));
1106 PROGRAM_CNTXT_INIT(p, descbuf, 0);
1108 PROGRAM_SET_BSWAP(p);
1110 PROGRAM_SET_36BIT_ADDR(p);
1111 phdr = SHR_HDR(p, SHR_SERIAL, hdr, 0);
1113 __rta_copy_ipsec_encap_pdb(p, pdb, cipherdata->algtype);
1115 switch (pdb->options & PDBOPTS_ESP_OIHI_MASK) {
1116 case PDBOPTS_ESP_OIHI_PDB_INL:
1117 COPY_DATA(p, opt_ip_hdr, pdb->ip_hdr_len);
1119 case PDBOPTS_ESP_OIHI_PDB_REF:
1121 COPY_DATA(p, opt_ip_hdr, 8);
1123 COPY_DATA(p, opt_ip_hdr, 4);
1130 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
1131 if (authdata->keylen)
1132 __gen_auth_key(p, authdata);
1133 if (cipherdata->keylen)
1134 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1135 cipherdata->keylen, INLINE_KEY(cipherdata));
1136 SET_LABEL(p, keyjmp);
1137 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
1139 (uint16_t)(cipherdata->algtype | authdata->algtype));
1140 PATCH_JUMP(p, pkeyjmp, keyjmp);
1141 PATCH_HDR(p, phdr, hdr);
1142 return PROGRAM_FINALIZE(p);
1146 * IPSEC_NEW_DEC_BASE_DESC_LEN - IPsec new mode decap shared descriptor length
1148 * Accounts only for the "base" commands and is intended to be used by upper
1149 * layers to determine whether keys can be inlined or not. To be used as first
1150 * parameter of rta_inline_query().
1152 #define IPSEC_NEW_DEC_BASE_DESC_LEN (5 * CAAM_CMD_SZ + \
1153 sizeof(struct ipsec_decap_pdb))
1156 * IPSEC_NEW_NULL_DEC_BASE_DESC_LEN - IPsec new mode decap shared descriptor
1157 * length for the case of
1158 * NULL decryption / authentication
1160 * Accounts only for the "base" commands and is intended to be used by upper
1161 * layers to determine whether key can be inlined or not. To be used as first
1162 * parameter of rta_inline_query().
1164 #define IPSEC_NEW_NULL_DEC_BASE_DESC_LEN (4 * CAAM_CMD_SZ + \
1165 sizeof(struct ipsec_decap_pdb))
1168 * cnstr_shdsc_ipsec_new_decap - IPSec new mode ESP decapsulation protocol-level
1169 * shared descriptor.
1170 * @descbuf: pointer to buffer used for descriptor construction
1171 * @ps: if 36/40bit addressing is desired, this parameter must be true
1172 * @swap: must be true when core endianness doesn't match SEC endianness
1173 * @pdb: pointer to the PDB to be used with this descriptor
1174 * This structure will be copied inline to the descriptor under
1175 * construction. No error checking will be made. Refer to the
1176 * block guide for details about the decapsulation PDB.
1177 * @cipherdata: pointer to block cipher transform definitions
1178 * Valid algorithm values 0 one of OP_PCL_IPSEC_*
1179 * @authdata: pointer to authentication transform definitions.
1180 * If an authentication key is required by the protocol, a "normal"
1181 * key must be provided; DKP (Derived Key Protocol) will be used to
1182 * compute MDHA on the fly in HW.
1183 * Valid algorithm values - one of OP_PCL_IPSEC_*
1185 * Return: size of descriptor written in words or negative number on error
1188 cnstr_shdsc_ipsec_new_decap(uint32_t *descbuf, bool ps,
1190 struct ipsec_decap_pdb *pdb,
1191 struct alginfo *cipherdata,
1192 struct alginfo *authdata)
1195 struct program *p = &prg;
1202 if (rta_sec_era < RTA_SEC_ERA_8) {
1203 pr_err("IPsec new mode decap: available only for Era %d or above\n",
1204 USER_SEC_ERA(RTA_SEC_ERA_8));
1208 PROGRAM_CNTXT_INIT(p, descbuf, 0);
1210 PROGRAM_SET_BSWAP(p);
1212 PROGRAM_SET_36BIT_ADDR(p);
1213 phdr = SHR_HDR(p, SHR_SERIAL, hdr, 0);
1214 __rta_copy_ipsec_decap_pdb(p, pdb, cipherdata->algtype);
1216 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
1217 if (authdata->keylen)
1218 __gen_auth_key(p, authdata);
1219 if (cipherdata->keylen)
1220 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1221 cipherdata->keylen, INLINE_KEY(cipherdata));
1222 SET_LABEL(p, keyjmp);
1223 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
1225 (uint16_t)(cipherdata->algtype | authdata->algtype));
1226 PATCH_JUMP(p, pkeyjmp, keyjmp);
1227 PATCH_HDR(p, phdr, hdr);
1228 return PROGRAM_FINALIZE(p);
1232 * IPSEC_AUTH_VAR_BASE_DESC_LEN - IPsec encap/decap shared descriptor length
1233 * for the case of variable-length authentication
1235 * Note: Only for SoCs with SEC_ERA >= 3.
1237 * Accounts only for the "base" commands and is intended to be used by upper
1238 * layers to determine whether keys can be inlined or not. To be used as first
1239 * parameter of rta_inline_query().
1241 #define IPSEC_AUTH_VAR_BASE_DESC_LEN (27 * CAAM_CMD_SZ)
1244 * IPSEC_AUTH_VAR_AES_DEC_BASE_DESC_LEN - IPsec AES decap shared descriptor
1245 * length for variable-length authentication only
1247 * Note: Only for SoCs with SEC_ERA >= 3.
1249 * Accounts only for the "base" commands and is intended to be used by upper
1250 * layers to determine whether key can be inlined or not. To be used as first
1251 * parameter of rta_inline_query().
1253 #define IPSEC_AUTH_VAR_AES_DEC_BASE_DESC_LEN \
1254 (IPSEC_AUTH_VAR_BASE_DESC_LEN + CAAM_CMD_SZ)
1257 * IPSEC_AUTH_BASE_DESC_LEN - IPsec encap/decap shared descriptor length
1259 * Accounts only for the "base" commands and is intended to be used by upper
1260 * layers to determine whether key can be inlined or not. To be used as first
1261 * parameter of rta_inline_query().
1263 #define IPSEC_AUTH_BASE_DESC_LEN (19 * CAAM_CMD_SZ)
1266 * IPSEC_AUTH_AES_DEC_BASE_DESC_LEN - IPsec AES decap shared descriptor length
1268 * Accounts only for the "base" commands and is intended to be used by upper
1269 * layers to determine whether key can be inlined or not. To be used as first
1270 * parameter of rta_inline_query().
1272 #define IPSEC_AUTH_AES_DEC_BASE_DESC_LEN (IPSEC_AUTH_BASE_DESC_LEN + \
1276 * cnstr_shdsc_authenc - authenc-like descriptor
1277 * @descbuf: pointer to buffer used for descriptor construction
1278 * @ps: if 36/40bit addressing is desired, this parameter must be true
1279 * @swap: if true, perform descriptor byte swapping on a 4-byte boundary
1280 * @cipherdata: ointer to block cipher transform definitions.
1281 * Valid algorithm values one of OP_ALG_ALGSEL_* {DES, 3DES, AES}
1282 * @authdata: pointer to authentication transform definitions.
1283 * Valid algorithm values - one of OP_ALG_ALGSEL_* {MD5, SHA1,
1284 * SHA224, SHA256, SHA384, SHA512}
1285 * Note: The key for authentication is supposed to be given as plain text.
1286 * Note: There's no support for keys longer than the block size of the
1287 * underlying hash function, according to the selected algorithm.
1289 * @ivlen: length of the IV to be read from the input frame, before any data
1291 * @auth_only_len: length of the data to be authenticated-only (commonly IP
1292 * header, IV, Sequence number and SPI)
1293 * Note: Extended Sequence Number processing is NOT supported
1295 * @trunc_len: the length of the ICV to be written to the output frame. If 0,
1296 * then the corresponding length of the digest, according to the
1297 * selected algorithm shall be used.
1298 * @dir: Protocol direction, encapsulation or decapsulation (DIR_ENC/DIR_DEC)
1300 * Note: Here's how the input frame needs to be formatted so that the processing
1301 * will be done correctly:
1302 * For encapsulation:
1304 * +----+----------------+---------------------------------------------+
1305 * | IV | Auth-only data | Padded data to be authenticated & Encrypted |
1306 * +----+----------------+---------------------------------------------+
1308 * +--------------------------------------+
1309 * | Authenticated & Encrypted data | ICV |
1310 * +--------------------------------+-----+
1312 * For decapsulation:
1314 * +----+----------------+--------------------------------+-----+
1315 * | IV | Auth-only data | Authenticated & Encrypted data | ICV |
1316 * +----+----------------+--------------------------------+-----+
1318 * +----+--------------------------+
1319 * | Decrypted & authenticated data |
1320 * +----+--------------------------+
1322 * Note: This descriptor can use per-packet commands, encoded as below in the
1325 * +------+---------------------+
1326 * | 0x80 | 0x00| auth_only_len |
1327 * +------+---------------------+
1329 * This mechanism is available only for SoCs having SEC ERA >= 3. In other
1330 * words, this will not work for P4080TO2
1332 * Note: The descriptor does not add any kind of padding to the input data,
1333 * so the upper layer needs to ensure that the data is padded properly,
1334 * according to the selected cipher. Failure to do so will result in
1335 * the descriptor failing with a data-size error.
1337 * Return: size of descriptor written in words or negative number on error
1340 cnstr_shdsc_authenc(uint32_t *descbuf, bool ps, bool swap,
1341 struct alginfo *cipherdata,
1342 struct alginfo *authdata,
1343 uint16_t ivlen, uint16_t auth_only_len,
1344 uint8_t trunc_len, uint8_t dir)
1347 struct program *p = &prg;
1348 const bool is_aes_dec = (dir == DIR_DEC) &&
1349 (cipherdata->algtype == OP_ALG_ALGSEL_AES);
1351 LABEL(skip_patch_len);
1354 LABEL(aonly_len_offset);
1355 REFERENCE(pskip_patch_len);
1357 REFERENCE(pskipkeys);
1358 REFERENCE(read_len);
1359 REFERENCE(write_len);
1361 PROGRAM_CNTXT_INIT(p, descbuf, 0);
1364 PROGRAM_SET_BSWAP(p);
1366 PROGRAM_SET_36BIT_ADDR(p);
1369 * Since we currently assume that key length is equal to hash digest
1370 * size, it's ok to truncate keylen value.
1372 trunc_len = trunc_len && (trunc_len < authdata->keylen) ?
1373 trunc_len : (uint8_t)authdata->keylen;
1375 SHR_HDR(p, SHR_SERIAL, 1, SC);
1378 * M0 will contain the value provided by the user when creating
1379 * the shared descriptor. If the user provided an override in
1380 * DPOVRD, then M0 will contain that value
1382 MATHB(p, MATH0, ADD, auth_only_len, MATH0, 4, IMMED2);
1384 if (rta_sec_era >= RTA_SEC_ERA_3) {
1386 * Check if the user wants to override the auth-only len
1388 MATHB(p, DPOVRD, ADD, 0x80000000, MATH2, 4, IMMED2);
1391 * No need to patch the length of the auth-only data read if
1392 * the user did not override it
1394 pskip_patch_len = JUMP(p, skip_patch_len, LOCAL_JUMP, ALL_TRUE,
1397 /* Get auth-only len in M0 */
1398 MATHB(p, MATH2, AND, 0xFFFF, MATH0, 4, IMMED2);
1401 * Since M0 is used in calculations, don't mangle it, copy
1402 * its content to M1 and use this for patching.
1404 MATHB(p, MATH0, ADD, MATH1, MATH1, 4, 0);
1406 read_len = MOVE(p, DESCBUF, 0, MATH1, 0, 6, WAITCOMP | IMMED);
1407 write_len = MOVE(p, MATH1, 0, DESCBUF, 0, 8, WAITCOMP | IMMED);
1409 SET_LABEL(p, skip_patch_len);
1412 * MATH0 contains the value in DPOVRD w/o the MSB, or the initial
1413 * value, as provided by the user at descriptor creation time
1416 MATHB(p, MATH0, ADD, ivlen, MATH0, 4, IMMED2);
1418 MATHB(p, MATH0, ADD, ivlen + trunc_len, MATH0, 4, IMMED2);
1420 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
1422 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1423 INLINE_KEY(authdata));
1426 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1427 cipherdata->keylen, INLINE_KEY(cipherdata));
1430 ALG_OPERATION(p, authdata->algtype, OP_ALG_AAI_HMAC,
1431 OP_ALG_AS_INITFINAL,
1432 dir == DIR_ENC ? ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1436 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, cipherdata->algmode,
1437 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
1438 pskipkeys = JUMP(p, skipkeys, LOCAL_JUMP, ALL_TRUE, 0);
1440 SET_LABEL(p, keyjmp);
1442 ALG_OPERATION(p, authdata->algtype, OP_ALG_AAI_HMAC_PRECOMP,
1443 OP_ALG_AS_INITFINAL,
1444 dir == DIR_ENC ? ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1448 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, cipherdata->algmode |
1449 OP_ALG_AAI_DK, OP_ALG_AS_INITFINAL,
1450 ICV_CHECK_DISABLE, dir);
1451 SET_LABEL(p, skipkeys);
1453 SET_LABEL(p, skipkeys);
1454 ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode,
1455 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
1459 * Prepare the length of the data to be both encrypted/decrypted
1460 * and authenticated/checked
1462 MATHB(p, SEQINSZ, SUB, MATH0, VSEQINSZ, 4, 0);
1464 MATHB(p, VSEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
1466 /* Prepare for writing the output frame */
1467 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1469 SET_LABEL(p, aonly_len_offset);
1472 SEQLOAD(p, CONTEXT1, 0, ivlen, 0);
1475 * Read data needed only for authentication. This is overwritten above
1476 * if the user requested it.
1478 SEQFIFOLOAD(p, MSG2, auth_only_len, 0);
1480 if (dir == DIR_ENC) {
1482 * Read input plaintext, encrypt and authenticate & write to
1485 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
1487 /* Finally, write the ICV */
1488 SEQSTORE(p, CONTEXT2, 0, trunc_len, 0);
1491 * Read input ciphertext, decrypt and authenticate & write to
1494 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
1496 /* Read the ICV to check */
1497 SEQFIFOLOAD(p, ICV2, trunc_len, LAST2);
1500 PATCH_JUMP(p, pkeyjmp, keyjmp);
1501 PATCH_JUMP(p, pskipkeys, skipkeys);
1502 PATCH_JUMP(p, pskipkeys, skipkeys);
1504 if (rta_sec_era >= RTA_SEC_ERA_3) {
1505 PATCH_JUMP(p, pskip_patch_len, skip_patch_len);
1506 PATCH_MOVE(p, read_len, aonly_len_offset);
1507 PATCH_MOVE(p, write_len, aonly_len_offset);
1510 return PROGRAM_FINALIZE(p);
1513 #endif /* __DESC_IPSEC_H__ */