LCOV - code coverage report
Current view: top level - drivers/common/dpaax/caamflib/desc - ipsec.h (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 190 0.0 %
Date: 2025-02-01 18:54:23 Functions: 0 7 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 94 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
       2                 :            :  *
       3                 :            :  * Copyright 2008-2016 Freescale Semiconductor Inc.
       4                 :            :  * Copyright 2016,2019-2022 NXP
       5                 :            :  *
       6                 :            :  */
       7                 :            : 
       8                 :            : #ifndef __DESC_IPSEC_H__
       9                 :            : #define __DESC_IPSEC_H__
      10                 :            : 
      11                 :            : #include "rta.h"
      12                 :            : #include "common.h"
      13                 :            : 
      14                 :            : /**
      15                 :            :  * DOC: IPsec Shared Descriptor Constructors
      16                 :            :  *
      17                 :            :  * Shared descriptors for IPsec protocol.
      18                 :            :  */
      19                 :            : 
      20                 :            : /* General IPSec ESP encap / decap PDB options */
      21                 :            : 
      22                 :            : /**
      23                 :            :  * PDBOPTS_ESP_ESN - Extended sequence included
      24                 :            :  */
      25                 :            : #define PDBOPTS_ESP_ESN         0x10
      26                 :            : 
      27                 :            : /**
      28                 :            :  * PDBOPTS_ESP_IPVSN - Process IPv6 header
      29                 :            :  *
      30                 :            :  * Valid only for IPsec legacy mode.
      31                 :            :  */
      32                 :            : #define PDBOPTS_ESP_IPVSN       0x02
      33                 :            : 
      34                 :            : /**
      35                 :            :  * PDBOPTS_ESP_TUNNEL - Tunnel mode next-header byte
      36                 :            :  *
      37                 :            :  * Valid only for IPsec legacy mode.
      38                 :            :  */
      39                 :            : #define PDBOPTS_ESP_TUNNEL      0x01
      40                 :            : 
      41                 :            : /* IPSec ESP Encap PDB options */
      42                 :            : 
      43                 :            : /**
      44                 :            :  * PDBOPTS_ESP_UPDATE_CSUM - Update ip header checksum
      45                 :            :  *
      46                 :            :  * Valid only for IPsec legacy mode.
      47                 :            :  */
      48                 :            : #define PDBOPTS_ESP_UPDATE_CSUM 0x80
      49                 :            : 
      50                 :            : /**
      51                 :            :  * PDBOPTS_ESP_DIFFSERV - Copy TOS/TC from inner iphdr
      52                 :            :  *
      53                 :            :  * Valid only for IPsec legacy mode.
      54                 :            :  */
      55                 :            : #define PDBOPTS_ESP_DIFFSERV    0x40
      56                 :            : 
      57                 :            : /**
      58                 :            :  * PDBOPTS_ESP_IVSRC - IV comes from internal random gen
      59                 :            :  */
      60                 :            : #define PDBOPTS_ESP_IVSRC       0x20
      61                 :            : 
      62                 :            : /**
      63                 :            :  * PDBOPTS_ESP_IPHDRSRC - IP header comes from PDB
      64                 :            :  *
      65                 :            :  * Valid only for IPsec legacy mode.
      66                 :            :  */
      67                 :            : #define PDBOPTS_ESP_IPHDRSRC    0x08
      68                 :            : 
      69                 :            : /**
      70                 :            :  * PDBOPTS_ESP_INCIPHDR - Prepend IP header to output frame
      71                 :            :  *
      72                 :            :  * Valid only for IPsec legacy mode.
      73                 :            :  */
      74                 :            : #define PDBOPTS_ESP_INCIPHDR    0x04
      75                 :            : 
      76                 :            : /**
      77                 :            :  * PDBOPTS_ESP_OIHI_MASK - Mask for Outer IP Header Included
      78                 :            :  *
      79                 :            :  * Valid only for IPsec new mode.
      80                 :            :  */
      81                 :            : #define PDBOPTS_ESP_OIHI_MASK   0x0c
      82                 :            : 
      83                 :            : /**
      84                 :            :  * PDBOPTS_ESP_OIHI_PDB_INL - Prepend IP header to output frame from PDB (where
      85                 :            :  *                            it is inlined).
      86                 :            :  *
      87                 :            :  * Valid only for IPsec new mode.
      88                 :            :  */
      89                 :            : #define PDBOPTS_ESP_OIHI_PDB_INL 0x0c
      90                 :            : 
      91                 :            : /**
      92                 :            :  * PDBOPTS_ESP_OIHI_PDB_REF - Prepend IP header to output frame from PDB
      93                 :            :  *                            (referenced by pointer).
      94                 :            :  *
      95                 :            :  * Vlid only for IPsec new mode.
      96                 :            :  */
      97                 :            : #define PDBOPTS_ESP_OIHI_PDB_REF 0x08
      98                 :            : 
      99                 :            : /**
     100                 :            :  * PDBOPTS_ESP_OIHI_IF - Prepend IP header to output frame from input frame
     101                 :            :  *
     102                 :            :  * Valid only for IPsec new mode.
     103                 :            :  */
     104                 :            : #define PDBOPTS_ESP_OIHI_IF     0x04
     105                 :            : 
     106                 :            : /**
     107                 :            :  * PDBOPTS_ESP_NAT - Enable RFC 3948 UDP-encapsulated-ESP
     108                 :            :  *
     109                 :            :  * Valid only for IPsec new mode.
     110                 :            :  */
     111                 :            : #define PDBOPTS_ESP_NAT         0x02
     112                 :            : 
     113                 :            : /**
     114                 :            :  * PDBOPTS_ESP_NUC - Enable NAT UDP Checksum
     115                 :            :  *
     116                 :            :  * Valid only for IPsec new mode.
     117                 :            :  */
     118                 :            : #define PDBOPTS_ESP_NUC         0x01
     119                 :            : 
     120                 :            : /* IPSec ESP Decap PDB options */
     121                 :            : 
     122                 :            : /**
     123                 :            :  * PDBOPTS_ESP_ARS_MASK_ERA10 - antireplay window mask
     124                 :            :  * for SEC_ERA >= 10
     125                 :            :  */
     126                 :            : #define PDBOPTS_ESP_ARS_MASK_ERA10      0xc8
     127                 :            : 
     128                 :            : /**
     129                 :            :  * PDBOPTS_ESP_ARS_MASK - antireplay window mask
     130                 :            :  * for SEC_ERA < 10
     131                 :            :  */
     132                 :            : #define PDBOPTS_ESP_ARS_MASK    0xc0
     133                 :            : 
     134                 :            : /**
     135                 :            :  * PDBOPTS_ESP_ARSNONE - No antireplay window
     136                 :            :  */
     137                 :            : #define PDBOPTS_ESP_ARSNONE     0x00
     138                 :            : 
     139                 :            : /**
     140                 :            :  * PDBOPTS_ESP_ARS64 - 64-entry antireplay window
     141                 :            :  */
     142                 :            : #define PDBOPTS_ESP_ARS64       0xc0
     143                 :            : 
     144                 :            : /**
     145                 :            :  * PDBOPTS_ESP_ARS128 - 128-entry antireplay window
     146                 :            :  *
     147                 :            :  * Valid only for IPsec new mode.
     148                 :            :  */
     149                 :            : #define PDBOPTS_ESP_ARS128      0x80
     150                 :            : 
     151                 :            : /**
     152                 :            :  * PDBOPTS_ESP_ARS256 - 256-entry antireplay window
     153                 :            :  *
     154                 :            :  * Valid only for IPsec new mode.
     155                 :            :  */
     156                 :            : #define PDBOPTS_ESP_ARS256      0x08
     157                 :            : 
     158                 :            : /**
     159                 :            :  * PDBOPTS_ESP_ARS512 - 512-entry antireplay window
     160                 :            :  *
     161                 :            :  * Valid only for IPsec new mode.
     162                 :            :  */
     163                 :            : #define PDBOPTS_ESP_ARS512      0x48
     164                 :            : 
     165                 :            : /**
     166                 :            :  * PDBOPTS_ESP_ARS1024 - 1024-entry antireplay window
     167                 :            :  *
     168                 :            :  * Valid only for IPsec new mode.
     169                 :            :  */
     170                 :            : #define PDBOPTS_ESP_ARS1024     0x88
     171                 :            : 
     172                 :            : /**
     173                 :            :  * PDBOPTS_ESP_ARS32 - 32-entry antireplay window
     174                 :            :  */
     175                 :            : #define PDBOPTS_ESP_ARS32       0x40
     176                 :            : 
     177                 :            : /**
     178                 :            :  * PDBOPTS_ESP_VERIFY_CSUM - Validate ip header checksum
     179                 :            :  *
     180                 :            :  * Valid only for IPsec legacy mode.
     181                 :            :  */
     182                 :            : #define PDBOPTS_ESP_VERIFY_CSUM 0x20
     183                 :            : 
     184                 :            : /**
     185                 :            :  * PDBOPTS_ESP_TECN - Implement RRFC6040 ECN tunneling from outer header to
     186                 :            :  *                    inner header.
     187                 :            :  *
     188                 :            :  * Valid only for IPsec new mode.
     189                 :            :  */
     190                 :            : #define PDBOPTS_ESP_TECN        0x20
     191                 :            : 
     192                 :            : /**
     193                 :            :  * PDBOPTS_ESP_OUTFMT - Output only decapsulation
     194                 :            :  *
     195                 :            :  * Valid only for IPsec legacy mode.
     196                 :            :  */
     197                 :            : #define PDBOPTS_ESP_OUTFMT      0x08
     198                 :            : 
     199                 :            : /**
     200                 :            :  * PDBOPTS_ESP_AOFL - Adjust out frame len
     201                 :            :  *
     202                 :            :  * Valid only for IPsec legacy mode and for SEC >= 5.3.
     203                 :            :  */
     204                 :            : #define PDBOPTS_ESP_AOFL        0x04
     205                 :            : 
     206                 :            : /**
     207                 :            :  * PDBOPTS_ESP_ETU - EtherType Update
     208                 :            :  *
     209                 :            :  * Add corresponding ethertype (0x0800 for IPv4, 0x86dd for IPv6) in the output
     210                 :            :  * frame.
     211                 :            :  * Valid only for IPsec new mode.
     212                 :            :  */
     213                 :            : #define PDBOPTS_ESP_ETU         0x01
     214                 :            : 
     215                 :            : #define PDBHMO_ESP_DECAP_SHIFT          28
     216                 :            : #define PDBHMO_ESP_ENCAP_SHIFT          28
     217                 :            : #define PDBNH_ESP_ENCAP_SHIFT           16
     218                 :            : #define PDBNH_ESP_ENCAP_MASK            (0xff << PDBNH_ESP_ENCAP_SHIFT)
     219                 :            : #define PDBHDRLEN_ESP_DECAP_SHIFT       16
     220                 :            : #define PDBHDRLEN_MASK                  (0x0fff << PDBHDRLEN_ESP_DECAP_SHIFT)
     221                 :            : #define PDB_NH_OFFSET_SHIFT             8
     222                 :            : #define PDB_NH_OFFSET_MASK              (0xff << PDB_NH_OFFSET_SHIFT)
     223                 :            : 
     224                 :            : /**
     225                 :            :  * PDBHMO_ESP_DECAP_DTTL - IPsec ESP decrement TTL (IPv4) / Hop limit (IPv6)
     226                 :            :  *                         HMO option.
     227                 :            :  */
     228                 :            : #define PDBHMO_ESP_DECAP_DTTL   (0x02 << PDBHMO_ESP_DECAP_SHIFT)
     229                 :            : 
     230                 :            : /**
     231                 :            :  * PDBHMO_ESP_ENCAP_DTTL - IPsec ESP increment TTL (IPv4) / Hop limit (IPv6)
     232                 :            :  *                         HMO option.
     233                 :            :  */
     234                 :            : #define PDBHMO_ESP_ENCAP_DTTL   (0x02 << PDBHMO_ESP_ENCAP_SHIFT)
     235                 :            : 
     236                 :            : /**
     237                 :            :  * PDBHMO_ESP_DIFFSERV - (Decap) DiffServ Copy - Copy the IPv4 TOS or IPv6
     238                 :            :  *                       Traffic Class byte from the outer IP header to the
     239                 :            :  *                       inner IP header.
     240                 :            :  */
     241                 :            : #define PDBHMO_ESP_DIFFSERV     (0x01 << PDBHMO_ESP_DECAP_SHIFT)
     242                 :            : 
     243                 :            : /**
     244                 :            :  * PDBHMO_ESP_SNR - (Encap) - Sequence Number Rollover control
     245                 :            :  *
     246                 :            :  * Configures behaviour in case of SN / ESN rollover:
     247                 :            :  * error if SNR = 1, rollover allowed if SNR = 0.
     248                 :            :  * Valid only for IPsec new mode.
     249                 :            :  */
     250                 :            : #define PDBHMO_ESP_SNR          (0x01 << PDBHMO_ESP_ENCAP_SHIFT)
     251                 :            : 
     252                 :            : /**
     253                 :            :  * PDBHMO_ESP_DFBIT - (Encap) Copy DF bit - if an IPv4 tunnel mode outer IP
     254                 :            :  *                    header is coming from the PDB, copy the DF bit from the
     255                 :            :  *                    inner IP header to the outer IP header.
     256                 :            :  */
     257                 :            : #define PDBHMO_ESP_DFBIT        (0x04 << PDBHMO_ESP_ENCAP_SHIFT)
     258                 :            : 
     259                 :            : /**
     260                 :            :  * PDBHMO_ESP_DFV - (Decap) - DF bit value
     261                 :            :  *
     262                 :            :  * If ODF = 1, DF bit in output frame is replaced by DFV.
     263                 :            :  * Valid only from SEC Era 5 onwards.
     264                 :            :  */
     265                 :            : #define PDBHMO_ESP_DFV          (0x04 << PDBHMO_ESP_DECAP_SHIFT)
     266                 :            : 
     267                 :            : /**
     268                 :            :  * PDBHMO_ESP_ODF - (Decap) Override DF bit in IPv4 header of decapsulated
     269                 :            :  *                  output frame.
     270                 :            :  *
     271                 :            :  * If ODF = 1, DF is replaced with the value of DFV bit.
     272                 :            :  * Valid only from SEC Era 5 onwards.
     273                 :            :  */
     274                 :            : #define PDBHMO_ESP_ODF          (0x08 << PDBHMO_ESP_DECAP_SHIFT)
     275                 :            : 
     276                 :            : /**
     277                 :            :  * struct ipsec_encap_cbc - PDB part for IPsec CBC encapsulation
     278                 :            :  * @iv: 16-byte array initialization vector
     279                 :            :  */
     280                 :            : struct ipsec_encap_cbc {
     281                 :            :         uint8_t iv[16];
     282                 :            : };
     283                 :            : 
     284                 :            : 
     285                 :            : /**
     286                 :            :  * struct ipsec_encap_ctr - PDB part for IPsec CTR encapsulation
     287                 :            :  * @ctr_nonce: 4-byte nonce
     288                 :            :  * @ctr_initial: initial count constant
     289                 :            :  * @iv: initialization vector
     290                 :            :  */
     291                 :            : struct ipsec_encap_ctr {
     292                 :            :         uint32_t ctr_nonce;
     293                 :            :         uint32_t ctr_initial;
     294                 :            :         uint8_t iv[8];
     295                 :            : };
     296                 :            : 
     297                 :            : /**
     298                 :            :  * struct ipsec_encap_ccm - PDB part for IPsec CCM encapsulation
     299                 :            :  * @salt: 3-byte array salt (lower 24 bits)
     300                 :            :  * @ccm_opt: CCM algorithm options - MSB-LSB description:
     301                 :            :  *  b0_flags (8b) - CCM B0; use 0x5B for 8-byte ICV, 0x6B for 12-byte ICV,
     302                 :            :  *    0x7B for 16-byte ICV (cf. RFC4309, RFC3610)
     303                 :            :  *  ctr_flags (8b) - counter flags; constant equal to 0x3
     304                 :            :  *  ctr_initial (16b) - initial count constant
     305                 :            :  * @iv: initialization vector
     306                 :            :  */
     307                 :            : struct ipsec_encap_ccm {
     308                 :            :         uint8_t salt[4];
     309                 :            :         uint32_t ccm_opt;
     310                 :            :         uint64_t iv;
     311                 :            : };
     312                 :            : 
     313                 :            : /**
     314                 :            :  * struct ipsec_encap_gcm - PDB part for IPsec GCM encapsulation
     315                 :            :  * @salt: 3-byte array salt (lower 24 bits)
     316                 :            :  * @rsvd: reserved, do not use
     317                 :            :  * @iv: initialization vector
     318                 :            :  */
     319                 :            : struct ipsec_encap_gcm {
     320                 :            :         uint8_t salt[4];
     321                 :            :         uint32_t rsvd;
     322                 :            :         uint64_t iv;
     323                 :            : };
     324                 :            : 
     325                 :            : /**
     326                 :            :  * struct ipsec_encap_pdb - PDB for IPsec encapsulation
     327                 :            :  * @options: MSB-LSB description (both for legacy and new modes)
     328                 :            :  *  hmo (header manipulation options) - 4b
     329                 :            :  *  reserved - 4b
     330                 :            :  *  next header (legacy) / reserved (new) - 8b
     331                 :            :  *  next header offset (legacy) / AOIPHO (actual outer IP header offset) - 8b
     332                 :            :  *  option flags (depend on selected algorithm) - 8b
     333                 :            :  * @seq_num_ext_hi: (optional) IPsec Extended Sequence Number (ESN)
     334                 :            :  * @seq_num: IPsec sequence number
     335                 :            :  * @spi: IPsec SPI (Security Parameters Index)
     336                 :            :  * @ip_hdr_len: optional IP Header length (in bytes)
     337                 :            :  *  IP header must follow directly after ipsec_encap_pdb
     338                 :            :  */
     339                 :            : struct ipsec_encap_pdb {
     340                 :            :         uint32_t options;
     341                 :            :         uint32_t seq_num_ext_hi;
     342                 :            :         uint32_t seq_num;
     343                 :            :         union {
     344                 :            :                 struct ipsec_encap_cbc cbc;
     345                 :            :                 struct ipsec_encap_ctr ctr;
     346                 :            :                 struct ipsec_encap_ccm ccm;
     347                 :            :                 struct ipsec_encap_gcm gcm;
     348                 :            :         };
     349                 :            :         uint32_t spi;
     350                 :            :         uint32_t ip_hdr_len;
     351                 :            : };
     352                 :            : 
     353                 :            : static inline unsigned int
     354                 :          0 : __rta_copy_ipsec_encap_pdb(struct program *program,
     355                 :            :                            struct ipsec_encap_pdb *pdb,
     356                 :            :                            uint32_t algtype)
     357                 :            : {
     358                 :          0 :         unsigned int start_pc = program->current_pc;
     359                 :            : 
     360                 :          0 :         __rta_out32(program, pdb->options);
     361                 :          0 :         __rta_out32(program, pdb->seq_num_ext_hi);
     362                 :          0 :         __rta_out32(program, pdb->seq_num);
     363                 :            : 
     364   [ #  #  #  #  :          0 :         switch (algtype & OP_PCL_IPSEC_CIPHER_MASK) {
                      # ]
     365                 :          0 :         case OP_PCL_IPSEC_DES_IV64:
     366                 :            :         case OP_PCL_IPSEC_DES:
     367                 :            :         case OP_PCL_IPSEC_3DES:
     368                 :            :         case OP_PCL_IPSEC_AES_CBC:
     369                 :            :         case OP_PCL_IPSEC_NULL:
     370                 :          0 :                 rta_copy_data(program, pdb->cbc.iv, sizeof(pdb->cbc.iv));
     371                 :            :                 break;
     372                 :            : 
     373                 :          0 :         case OP_PCL_IPSEC_AES_CTR:
     374                 :          0 :                 rta_copy_data(program, (uint8_t *)&pdb->ctr.ctr_nonce, 4);
     375                 :          0 :                 __rta_out32(program, pdb->ctr.ctr_initial);
     376                 :          0 :                 rta_copy_data(program, pdb->ctr.iv, sizeof(pdb->ctr.iv));
     377                 :            :                 break;
     378                 :            : 
     379                 :          0 :         case OP_PCL_IPSEC_AES_CCM8:
     380                 :            :         case OP_PCL_IPSEC_AES_CCM12:
     381                 :            :         case OP_PCL_IPSEC_AES_CCM16:
     382                 :          0 :                 rta_copy_data(program, pdb->ccm.salt, sizeof(pdb->ccm.salt));
     383                 :          0 :                 __rta_out32(program, pdb->ccm.ccm_opt);
     384                 :          0 :                 __rta_out64(program, true, pdb->ccm.iv);
     385                 :          0 :                 break;
     386                 :            : 
     387                 :          0 :         case OP_PCL_IPSEC_AES_GCM8:
     388                 :            :         case OP_PCL_IPSEC_AES_GCM12:
     389                 :            :         case OP_PCL_IPSEC_AES_GCM16:
     390                 :            :         case OP_PCL_IPSEC_AES_NULL_WITH_GMAC:
     391                 :          0 :                 rta_copy_data(program, pdb->gcm.salt, sizeof(pdb->gcm.salt));
     392                 :          0 :                 __rta_out32(program, pdb->gcm.rsvd);
     393                 :          0 :                 __rta_out64(program, true, pdb->gcm.iv);
     394                 :          0 :                 break;
     395                 :            :         }
     396                 :            : 
     397                 :          0 :         __rta_out32(program, pdb->spi);
     398                 :          0 :         __rta_out32(program, pdb->ip_hdr_len);
     399                 :            : 
     400                 :          0 :         return start_pc;
     401                 :            : }
     402                 :            : 
     403                 :            : /**
     404                 :            :  * struct ipsec_decap_cbc - PDB part for IPsec CBC decapsulation
     405                 :            :  * @rsvd: reserved, do not use
     406                 :            :  */
     407                 :            : struct ipsec_decap_cbc {
     408                 :            :         uint32_t rsvd[2];
     409                 :            : };
     410                 :            : 
     411                 :            : /**
     412                 :            :  * struct ipsec_decap_ctr - PDB part for IPsec CTR decapsulation
     413                 :            :  * @ctr_nonce: 4-byte nonce
     414                 :            :  * @ctr_initial: initial count constant
     415                 :            :  */
     416                 :            : struct ipsec_decap_ctr {
     417                 :            :         uint32_t ctr_nonce;
     418                 :            :         uint32_t ctr_initial;
     419                 :            : };
     420                 :            : 
     421                 :            : /**
     422                 :            :  * struct ipsec_decap_ccm - PDB part for IPsec CCM decapsulation
     423                 :            :  * @salt: 3-byte salt (lower 24 bits)
     424                 :            :  * @ccm_opt: CCM algorithm options - MSB-LSB description:
     425                 :            :  *  b0_flags (8b) - CCM B0; use 0x5B for 8-byte ICV, 0x6B for 12-byte ICV,
     426                 :            :  *    0x7B for 16-byte ICV (cf. RFC4309, RFC3610)
     427                 :            :  *  ctr_flags (8b) - counter flags; constant equal to 0x3
     428                 :            :  *  ctr_initial (16b) - initial count constant
     429                 :            :  */
     430                 :            : struct ipsec_decap_ccm {
     431                 :            :         uint8_t salt[4];
     432                 :            :         uint32_t ccm_opt;
     433                 :            : };
     434                 :            : 
     435                 :            : /**
     436                 :            :  * struct ipsec_decap_gcm - PDB part for IPsec GCN decapsulation
     437                 :            :  * @salt: 4-byte salt
     438                 :            :  * @rsvd: reserved, do not use
     439                 :            :  */
     440                 :            : struct ipsec_decap_gcm {
     441                 :            :         uint8_t salt[4];
     442                 :            :         uint32_t rsvd;
     443                 :            : };
     444                 :            : 
     445                 :            : /**
     446                 :            :  * struct ipsec_decap_pdb - PDB for IPsec decapsulation
     447                 :            :  * @options: MSB-LSB description (both for legacy and new modes)
     448                 :            :  *  hmo (header manipulation options) - 4b
     449                 :            :  *  IP header length - 12b
     450                 :            :  *  next header offset (legacy) / AOIPHO (actual outer IP header offset) - 8b
     451                 :            :  *  option flags (depend on selected algorithm) - 8b
     452                 :            :  * @seq_num_ext_hi: (optional) IPsec Extended Sequence Number (ESN)
     453                 :            :  * @seq_num: IPsec sequence number
     454                 :            :  * @anti_replay: Anti-replay window; size depends on ARS (option flags);
     455                 :            :  *  format must be Big Endian, irrespective of platform
     456                 :            :  */
     457                 :            : struct ipsec_decap_pdb {
     458                 :            :         uint32_t options;
     459                 :            :         union {
     460                 :            :                 struct ipsec_decap_cbc cbc;
     461                 :            :                 struct ipsec_decap_ctr ctr;
     462                 :            :                 struct ipsec_decap_ccm ccm;
     463                 :            :                 struct ipsec_decap_gcm gcm;
     464                 :            :         };
     465                 :            :         uint32_t seq_num_ext_hi;
     466                 :            :         uint32_t seq_num;
     467                 :            :         uint32_t anti_replay[32];
     468                 :            : };
     469                 :            : 
     470                 :            : static inline unsigned int
     471                 :          0 : __rta_copy_ipsec_decap_pdb(struct program *program,
     472                 :            :                            struct ipsec_decap_pdb *pdb,
     473                 :            :                            uint32_t algtype)
     474                 :            : {
     475                 :          0 :         unsigned int start_pc = program->current_pc;
     476                 :            :         unsigned int i, ars;
     477                 :            :         uint8_t mask;
     478                 :            : 
     479                 :          0 :         __rta_out32(program, pdb->options);
     480                 :            : 
     481   [ #  #  #  #  :          0 :         switch (algtype & OP_PCL_IPSEC_CIPHER_MASK) {
                      # ]
     482                 :          0 :         case OP_PCL_IPSEC_DES_IV64:
     483                 :            :         case OP_PCL_IPSEC_DES:
     484                 :            :         case OP_PCL_IPSEC_3DES:
     485                 :            :         case OP_PCL_IPSEC_AES_CBC:
     486                 :            :         case OP_PCL_IPSEC_NULL:
     487                 :          0 :                 __rta_out32(program, pdb->cbc.rsvd[0]);
     488                 :          0 :                 __rta_out32(program, pdb->cbc.rsvd[1]);
     489                 :          0 :                 break;
     490                 :            : 
     491                 :          0 :         case OP_PCL_IPSEC_AES_CTR:
     492                 :          0 :                 rta_copy_data(program, (uint8_t *)&pdb->ctr.ctr_nonce, 4);
     493                 :          0 :                 __rta_out32(program, pdb->ctr.ctr_initial);
     494                 :          0 :                 break;
     495                 :            : 
     496                 :          0 :         case OP_PCL_IPSEC_AES_CCM8:
     497                 :            :         case OP_PCL_IPSEC_AES_CCM12:
     498                 :            :         case OP_PCL_IPSEC_AES_CCM16:
     499                 :          0 :                 rta_copy_data(program, pdb->ccm.salt, sizeof(pdb->ccm.salt));
     500                 :          0 :                 __rta_out32(program, pdb->ccm.ccm_opt);
     501                 :          0 :                 break;
     502                 :            : 
     503                 :          0 :         case OP_PCL_IPSEC_AES_GCM8:
     504                 :            :         case OP_PCL_IPSEC_AES_GCM12:
     505                 :            :         case OP_PCL_IPSEC_AES_GCM16:
     506                 :            :         case OP_PCL_IPSEC_AES_NULL_WITH_GMAC:
     507                 :          0 :                 rta_copy_data(program, pdb->gcm.salt, sizeof(pdb->gcm.salt));
     508                 :          0 :                 __rta_out32(program, pdb->gcm.rsvd);
     509                 :          0 :                 break;
     510                 :            :         }
     511                 :            : 
     512                 :          0 :         __rta_out32(program, pdb->seq_num_ext_hi);
     513                 :          0 :         __rta_out32(program, pdb->seq_num);
     514                 :            : 
     515         [ #  # ]:          0 :         if (rta_sec_era < RTA_SEC_ERA_10)
     516                 :            :                 mask = PDBOPTS_ESP_ARS_MASK;
     517                 :            :         else
     518                 :            :                 mask = PDBOPTS_ESP_ARS_MASK_ERA10;
     519   [ #  #  #  #  :          0 :         switch (pdb->options & mask) {
                #  #  # ]
     520                 :            :         case PDBOPTS_ESP_ARS1024:
     521                 :            :                 ars = 32;
     522                 :            :                 break;
     523                 :          0 :         case PDBOPTS_ESP_ARS512:
     524                 :            :                 ars = 16;
     525                 :          0 :                 break;
     526                 :          0 :         case PDBOPTS_ESP_ARS256:
     527                 :            :                 ars = 8;
     528                 :          0 :                 break;
     529                 :          0 :         case PDBOPTS_ESP_ARS128:
     530                 :            :                 ars = 4;
     531                 :          0 :                 break;
     532                 :          0 :         case PDBOPTS_ESP_ARS64:
     533                 :            :                 ars = 2;
     534                 :          0 :                 break;
     535                 :          0 :         case PDBOPTS_ESP_ARS32:
     536                 :            :                 ars = 1;
     537                 :          0 :                 break;
     538                 :          0 :         case PDBOPTS_ESP_ARSNONE:
     539                 :            :         default:
     540                 :            :                 ars = 0;
     541                 :          0 :                 break;
     542                 :            :         }
     543                 :            : 
     544         [ #  # ]:          0 :         for (i = 0; i < ars; i++)
     545                 :          0 :                 __rta_out_be32(program, pdb->anti_replay[i]);
     546                 :            : 
     547                 :          0 :         return start_pc;
     548                 :            : }
     549                 :            : 
     550                 :            : /**
     551                 :            :  * enum ipsec_icv_size - Type selectors for icv size in IPsec protocol
     552                 :            :  * @IPSEC_ICV_MD5_SIZE: full-length MD5 ICV
     553                 :            :  * @IPSEC_ICV_MD5_TRUNC_SIZE: truncated MD5 ICV
     554                 :            :  */
     555                 :            : enum ipsec_icv_size {
     556                 :            :         IPSEC_ICV_MD5_SIZE = 16,
     557                 :            :         IPSEC_ICV_MD5_TRUNC_SIZE = 12
     558                 :            : };
     559                 :            : 
     560                 :            : /*
     561                 :            :  * IPSec ESP Datapath Protocol Override Register (DPOVRD)
     562                 :            :  * IPSEC_N_* defines are for IPsec new mode.
     563                 :            :  */
     564                 :            : 
     565                 :            : /**
     566                 :            :  * IPSEC_DPOVRD_USE - DPOVRD will override values specified in the PDB
     567                 :            :  */
     568                 :            : #define IPSEC_DPOVRD_USE        BIT(31)
     569                 :            : 
     570                 :            : /**
     571                 :            :  * IPSEC_DPOVRD_ECN_SHIFT - Explicit Congestion Notification
     572                 :            :  *
     573                 :            :  * If set, MSB of the 4 bits indicates that the 2 LSBs will replace the ECN bits
     574                 :            :  * in the IP header.
     575                 :            :  */
     576                 :            : #define IPSEC_DPOVRD_ECN_SHIFT          24
     577                 :            : 
     578                 :            : /**
     579                 :            :  * IPSEC_DPOVRD_ECN_MASK - See IPSEC_DPOVRD_ECN_SHIFT
     580                 :            :  */
     581                 :            : #define IPSEC_DPOVRD_ECN_MASK           (0xf << IPSEC_ENCAP_DPOVRD_ECN_SHIFT)
     582                 :            : 
     583                 :            : /**
     584                 :            :  * IPSEC_DPOVRD_IP_HDR_LEN_SHIFT - The length (in bytes) of the portion of the
     585                 :            :  *                                 IP header that is not encrypted
     586                 :            :  */
     587                 :            : #define IPSEC_DPOVRD_IP_HDR_LEN_SHIFT   16
     588                 :            : 
     589                 :            : /**
     590                 :            :  * IPSEC_DPOVRD_IP_HDR_LEN_MASK - See IPSEC_DPOVRD_IP_HDR_LEN_SHIFT
     591                 :            :  */
     592                 :            : #define IPSEC_DPOVRD_IP_HDR_LEN_MASK    (0xff << IPSEC_DPOVRD_IP_HDR_LEN_SHIFT)
     593                 :            : 
     594                 :            : /**
     595                 :            :  * IPSEC_DPOVRD_NH_OFFSET_SHIFT - The location of the next header field within
     596                 :            :  *                                the IP header of the transport mode packet
     597                 :            :  *
     598                 :            :  * Encap:
     599                 :            :  *      ESP_Trailer_NH <-- IP_Hdr[DPOVRD[NH_OFFSET]]
     600                 :            :  *      IP_Hdr[DPOVRD[NH_OFFSET]] <-- DPOVRD[NH]
     601                 :            :  *Decap:
     602                 :            :  *      IP_Hdr[DPOVRD[NH_OFFSET]] <-- ESP_Trailer_NH
     603                 :            :  */
     604                 :            : #define IPSEC_DPOVRD_NH_OFFSET_SHIFT    8
     605                 :            : 
     606                 :            : /**
     607                 :            :  * IPSEC_DPOVRD_NH_OFFSET_MASK - See IPSEC_DPOVRD_NH_OFFSET_SHIFT
     608                 :            :  */
     609                 :            : #define IPSEC_DPOVRD_NH_OFFSET_MASK     (0xff << IPSEC_DPOVRD_NH_OFFSET_SHIFT)
     610                 :            : 
     611                 :            : /**
     612                 :            :  * IPSEC_DPOVRD_NH_MASK - See IPSEC_DPOVRD_NH_OFFSET_SHIFT
     613                 :            :  *                        Valid only for encapsulation.
     614                 :            :  */
     615                 :            : #define IPSEC_DPOVRD_NH_MASK            0xff
     616                 :            : 
     617                 :            : /**
     618                 :            :  * IPSEC_N_ENCAP_DPOVRD_OIM_LEN_SHIFT - Outer IP header Material length (encap)
     619                 :            :  *                                      Valid only if L2_COPY is not set.
     620                 :            :  */
     621                 :            : #define IPSEC_N_ENCAP_DPOVRD_OIM_LEN_SHIFT      16
     622                 :            : 
     623                 :            : /**
     624                 :            :  * IPSEC_N_ENCAP_DPOVRD_OIM_LEN_MASK - See IPSEC_N_ENCAP_DPOVRD_OIM_LEN_SHIFT
     625                 :            :  */
     626                 :            : #define IPSEC_N_ENCAP_DPOVRD_OIM_LEN_MASK \
     627                 :            :         (0xfff << IPSEC_N_ENCAP_DPOVRD_OIM_LEN_SHIFT)
     628                 :            : 
     629                 :            : /**
     630                 :            :  * IPSEC_N_ENCAP_DPOVRD_L2_LEN_SHIFT - L2 header length
     631                 :            :  *                                     Valid only if L2_COPY is set.
     632                 :            :  */
     633                 :            : #define IPSEC_N_ENCAP_DPOVRD_L2_LEN_SHIFT       16
     634                 :            : 
     635                 :            : /**
     636                 :            :  * IPSEC_N_ENCAP_DPOVRD_L2_LEN_MASK - See IPSEC_N_ENCAP_DPOVRD_L2_LEN_SHIFT
     637                 :            :  */
     638                 :            : #define IPSEC_N_ENCAP_DPOVRD_L2_LEN_MASK \
     639                 :            :         (0xff << IPSEC_N_ENCAP_DPOVRD_L2_LEN_SHIFT)
     640                 :            : 
     641                 :            : /**
     642                 :            :  * IPSEC_N_ENCAP_DPOVRD_OIMIF -  Outer IP header Material in Input Frame
     643                 :            :  */
     644                 :            : #define IPSEC_N_ENCAP_DPOVRD_OIMIF              BIT(15)
     645                 :            : 
     646                 :            : /**
     647                 :            :  * IPSEC_N_ENCAP_DPOVRD_L2_COPY - L2 header present in input frame
     648                 :            :  *
     649                 :            :  * Note: For Era <= 8, this bit is reserved (not used) by HW.
     650                 :            :  */
     651                 :            : #define IPSEC_N_ENCAP_DPOVRD_L2_COPY            BIT(14)
     652                 :            : 
     653                 :            : /**
     654                 :            :  * IPSEC_N_ENCAP_DPOVRD_AOIPHO_SHIFT - Actual Outer IP Header Offset (encap)
     655                 :            :  */
     656                 :            : #define IPSEC_N_ENCAP_DPOVRD_AOIPHO_SHIFT       8
     657                 :            : 
     658                 :            : /**
     659                 :            :  * IPSEC_N_ENCAP_DPOVRD_AOIPHO_MASK - See IPSEC_N_ENCAP_DPOVRD_AOIPHO_SHIFT
     660                 :            :  */
     661                 :            : #define IPSEC_N_ENCAP_DPOVRD_AOIPHO_MASK \
     662                 :            :         (0x3c << IPSEC_N_ENCAP_DPOVRD_AOIPHO_SHIFT)
     663                 :            : 
     664                 :            : /**
     665                 :            :  * IPSEC_N_ENCAP_DPOVRD_NH_MASK -  Next Header
     666                 :            :  *
     667                 :            :  * Used in the Next Header field of the encapsulated payload.
     668                 :            :  */
     669                 :            : #define IPSEC_N_ENCAP_DPOVRD_NH_MASK            0xff
     670                 :            : 
     671                 :            : /**
     672                 :            :  * IPSEC_N_DECAP_DPOVRD_AOIPHO_SHIFT - Actual Outer IP Header Offset (decap)
     673                 :            :  */
     674                 :            : #define IPSEC_N_DECAP_DPOVRD_AOIPHO_SHIFT       12
     675                 :            : 
     676                 :            : /**
     677                 :            :  * IPSEC_N_DECAP_DPOVRD_AOIPHO_MASK - See IPSEC_N_DECAP_DPOVRD_AOIPHO_SHIFT
     678                 :            :  */
     679                 :            : #define IPSEC_N_DECAP_DPOVRD_AOIPHO_MASK \
     680                 :            :         (0xff << IPSEC_N_DECAP_DPOVRD_AOIPHO_SHIFT)
     681                 :            : 
     682                 :            : /**
     683                 :            :  * IPSEC_N_DECAP_DPOVRD_OIM_LEN_MASK - Outer IP header Material length (decap)
     684                 :            :  */
     685                 :            : #define IPSEC_N_DECAP_DPOVRD_OIM_LEN_MASK       0xfff
     686                 :            : 
     687                 :          0 : static inline void __gen_auth_key(struct program *program,
     688                 :            :                                   struct alginfo *authdata)
     689                 :            : {
     690                 :            :         uint32_t dkp_protid;
     691                 :            : 
     692   [ #  #  #  #  :          0 :         switch (authdata->algtype & OP_PCL_IPSEC_AUTH_MASK) {
                #  #  # ]
     693                 :            :         case OP_PCL_IPSEC_HMAC_MD5_96:
     694                 :            :         case OP_PCL_IPSEC_HMAC_MD5_128:
     695                 :            :                 dkp_protid = OP_PCLID_DKP_MD5;
     696                 :            :                 break;
     697                 :          0 :         case OP_PCL_IPSEC_HMAC_SHA1_96:
     698                 :            :         case OP_PCL_IPSEC_HMAC_SHA1_160:
     699                 :            :                 dkp_protid = OP_PCLID_DKP_SHA1;
     700                 :          0 :                 break;
     701                 :          0 :         case OP_PCL_IPSEC_HMAC_SHA2_256_128:
     702                 :            :                 dkp_protid = OP_PCLID_DKP_SHA256;
     703                 :          0 :                 break;
     704                 :          0 :         case OP_PCL_IPSEC_HMAC_SHA2_384_192:
     705                 :            :                 dkp_protid = OP_PCLID_DKP_SHA384;
     706                 :          0 :                 break;
     707                 :          0 :         case OP_PCL_IPSEC_HMAC_SHA2_512_256:
     708                 :            :                 dkp_protid = OP_PCLID_DKP_SHA512;
     709                 :          0 :                 break;
     710                 :          0 :         case OP_PCL_IPSEC_HMAC_SHA2_224_96:
     711                 :            :         case OP_PCL_IPSEC_HMAC_SHA2_224_112:
     712                 :            :         case OP_PCL_IPSEC_HMAC_SHA2_224_224:
     713                 :            :                 dkp_protid = OP_PCLID_DKP_SHA224;
     714                 :          0 :                 break;
     715                 :          0 :         default:
     716                 :          0 :                 KEY(program, KEY2, authdata->key_enc_flags, authdata->key,
     717                 :            :                     authdata->keylen, INLINE_KEY(authdata));
     718                 :          0 :                 return;
     719                 :            :         }
     720                 :            : 
     721         [ #  # ]:          0 :         if (authdata->key_type == RTA_DATA_PTR)
     722                 :          0 :                 DKP_PROTOCOL(program, dkp_protid, OP_PCL_DKP_SRC_PTR,
     723                 :            :                              OP_PCL_DKP_DST_PTR, (uint16_t)authdata->keylen,
     724                 :            :                              authdata->key, authdata->key_type);
     725                 :            :         else
     726                 :          0 :                 DKP_PROTOCOL(program, dkp_protid, OP_PCL_DKP_SRC_IMM,
     727                 :            :                              OP_PCL_DKP_DST_IMM, (uint16_t)authdata->keylen,
     728                 :            :                              authdata->key, authdata->key_type);
     729                 :            : }
     730                 :            : 
     731                 :            : /**
     732                 :            :  * rta_inline_ipsec_query() - Provide indications on which data items can be inlined
     733                 :            :  *                      and which shall be referenced in IPsec shared descriptor.
     734                 :            :  * @sd_base_len: Shared descriptor base length - bytes consumed by the commands,
     735                 :            :  *               excluding the data items to be inlined (or corresponding
     736                 :            :  *               pointer if an item is not inlined). Each cnstr_* function that
     737                 :            :  *               generates descriptors should have a define mentioning
     738                 :            :  *               corresponding length.
     739                 :            :  * @jd_len: Maximum length of the job descriptor(s) that will be used
     740                 :            :  *          together with the shared descriptor.
     741                 :            :  * @data_len: Array of lengths of the data items trying to be inlined
     742                 :            :  * @inl_mask: 32bit mask with bit x = 1 if data item x can be inlined, 0
     743                 :            :  *            otherwise.
     744                 :            :  * @count: Number of data items (size of @data_len array); must be <= 32
     745                 :            :  * @auth_algtype: Authentication algorithm type.
     746                 :            :  * @auth_index: Index value of data_len for authentication key length.
     747                 :            :  *              -1 if authentication key length is not present in data_len.
     748                 :            :  *
     749                 :            :  * Return: 0 if data can be inlined / referenced, negative value if not. If 0,
     750                 :            :  *         check @inl_mask for details.
     751                 :            :  */
     752                 :            : static inline int
     753                 :          0 : rta_inline_ipsec_query(unsigned int sd_base_len,
     754                 :            :                        unsigned int jd_len,
     755                 :            :                        unsigned int *data_len,
     756                 :            :                        uint32_t *inl_mask,
     757                 :            :                        unsigned int count,
     758                 :            :                        uint32_t auth_algtype,
     759                 :            :                        int32_t auth_index)
     760                 :            : {
     761                 :            :         uint32_t dkp_protid;
     762                 :            : 
     763   [ #  #  #  #  :          0 :         switch (auth_algtype & OP_PCL_IPSEC_AUTH_MASK) {
                #  #  # ]
     764                 :            :         case OP_PCL_IPSEC_HMAC_MD5_96:
     765                 :            :         case OP_PCL_IPSEC_HMAC_MD5_128:
     766                 :            :                 dkp_protid = OP_PCLID_DKP_MD5;
     767                 :            :                 break;
     768                 :          0 :         case OP_PCL_IPSEC_HMAC_SHA1_96:
     769                 :            :         case OP_PCL_IPSEC_HMAC_SHA1_160:
     770                 :            :                 dkp_protid = OP_PCLID_DKP_SHA1;
     771                 :          0 :                 break;
     772                 :          0 :         case OP_PCL_IPSEC_HMAC_SHA2_256_128:
     773                 :            :                 dkp_protid = OP_PCLID_DKP_SHA256;
     774                 :          0 :                 break;
     775                 :          0 :         case OP_PCL_IPSEC_HMAC_SHA2_384_192:
     776                 :            :                 dkp_protid = OP_PCLID_DKP_SHA384;
     777                 :          0 :                 break;
     778                 :          0 :         case OP_PCL_IPSEC_HMAC_SHA2_512_256:
     779                 :            :                 dkp_protid = OP_PCLID_DKP_SHA512;
     780                 :          0 :                 break;
     781                 :          0 :         case OP_PCL_IPSEC_HMAC_SHA2_224_96:
     782                 :            :         case OP_PCL_IPSEC_HMAC_SHA2_224_112:
     783                 :            :         case OP_PCL_IPSEC_HMAC_SHA2_224_224:
     784                 :            :                 dkp_protid = OP_PCLID_DKP_SHA224;
     785                 :          0 :                 break;
     786                 :          0 :         default:
     787                 :          0 :                 return rta_inline_query(sd_base_len,
     788                 :            :                                        jd_len,
     789                 :            :                                        data_len,
     790                 :            :                                        inl_mask, count);
     791                 :            :         }
     792                 :            : 
     793                 :            :         /* Updating the maximum supported inline key length */
     794         [ #  # ]:          0 :         if (auth_index != -1) {
     795         [ #  # ]:          0 :                 if (split_key_len(dkp_protid) > data_len[auth_index])
     796                 :          0 :                         data_len[auth_index] = split_key_len(dkp_protid);
     797                 :            :         }
     798                 :          0 :         return rta_inline_query(sd_base_len,
     799                 :            :                                jd_len,
     800                 :            :                                data_len,
     801                 :            :                                inl_mask, count);
     802                 :            : }
     803                 :            : 
     804                 :            : /**
     805                 :            :  * cnstr_shdsc_ipsec_encap - IPSec ESP encapsulation protocol-level shared
     806                 :            :  *                           descriptor.
     807                 :            :  * @descbuf: pointer to buffer used for descriptor construction
     808                 :            :  * @ps: if 36/40bit addressing is desired, this parameter must be true
     809                 :            :  * @swap: if true, perform descriptor byte swapping on a 4-byte boundary
     810                 :            :  * @share: sharing type of shared descriptor
     811                 :            :  * @pdb: pointer to the PDB to be used with this descriptor
     812                 :            :  *       This structure will be copied inline to the descriptor under
     813                 :            :  *       construction. No error checking will be made. Refer to the
     814                 :            :  *       block guide for a details of the encapsulation PDB.
     815                 :            :  * @cipherdata: pointer to block cipher transform definitions
     816                 :            :  *              Valid algorithm values - one of OP_PCL_IPSEC_*
     817                 :            :  * @authdata: pointer to authentication transform definitions
     818                 :            :  *            If an authentication key is required by the protocol:
     819                 :            :  *            -For SEC Eras 1-5, an MDHA split key must be provided;
     820                 :            :  *            Note that the size of the split key itself must be specified.
     821                 :            :  *            -For SEC Eras 6+, a "normal" key must be provided; DKP (Derived
     822                 :            :  *            Key Protocol) will be used to compute MDHA on the fly in HW.
     823                 :            :  *            Valid algorithm values - one of OP_PCL_IPSEC_*
     824                 :            :  *
     825                 :            :  * Return: size of descriptor written in words or negative number on error
     826                 :            :  */
     827                 :            : static inline int
     828                 :            : cnstr_shdsc_ipsec_encap(uint32_t *descbuf, bool ps, bool swap,
     829                 :            :                                           enum rta_share_type share,
     830                 :            :                         struct ipsec_encap_pdb *pdb,
     831                 :            :                         struct alginfo *cipherdata,
     832                 :            :                         struct alginfo *authdata)
     833                 :            : {
     834                 :            :         struct program prg;
     835                 :            :         struct program *p = &prg;
     836                 :            : 
     837                 :            :         LABEL(keyjmp);
     838                 :            :         REFERENCE(pkeyjmp);
     839                 :            :         LABEL(hdr);
     840                 :            :         REFERENCE(phdr);
     841                 :            : 
     842                 :            :         PROGRAM_CNTXT_INIT(p, descbuf, 0);
     843                 :            :         if (swap)
     844                 :            :                 PROGRAM_SET_BSWAP(p);
     845                 :            :         if (ps)
     846                 :            :                 PROGRAM_SET_36BIT_ADDR(p);
     847                 :            :         phdr = SHR_HDR(p, share, hdr, 0);
     848                 :            :         __rta_copy_ipsec_encap_pdb(p, pdb, cipherdata->algtype);
     849                 :            : 
     850                 :            :         /* IP header if any follows the encap_pdb */
     851                 :            :         if (pdb->ip_hdr_len > 0) {
     852                 :            :                 void *ip_hdr = pdb + 1;
     853                 :            :                 COPY_DATA(p, ip_hdr, pdb->ip_hdr_len);
     854                 :            :         }
     855                 :            :         SET_LABEL(p, hdr);
     856                 :            :         pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, BOTH|SHRD);
     857                 :            :         if (authdata->keylen)
     858                 :            :                 __gen_auth_key(p, authdata);
     859                 :            : 
     860                 :            :         if (cipherdata->keylen)
     861                 :            :                 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
     862                 :            :                     cipherdata->keylen, INLINE_KEY(cipherdata));
     863                 :            :         SET_LABEL(p, keyjmp);
     864                 :            :         PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
     865                 :            :                  OP_PCLID_IPSEC,
     866                 :            :                  (uint16_t)(cipherdata->algtype | authdata->algtype));
     867                 :            :         PATCH_JUMP(p, pkeyjmp, keyjmp);
     868                 :            :         PATCH_HDR(p, phdr, hdr);
     869                 :            :         return PROGRAM_FINALIZE(p);
     870                 :            : }
     871                 :            : 
     872                 :            : /**
     873                 :            :  * cnstr_shdsc_ipsec_decap - IPSec ESP decapsulation protocol-level shared
     874                 :            :  *                           descriptor.
     875                 :            :  * @descbuf: pointer to buffer used for descriptor construction
     876                 :            :  * @ps: if 36/40bit addressing is desired, this parameter must be true
     877                 :            :  * @swap: if true, perform descriptor byte swapping on a 4-byte boundary
     878                 :            :  * @share: sharing type of shared descriptor
     879                 :            :  * @pdb: pointer to the PDB to be used with this descriptor
     880                 :            :  *       This structure will be copied inline to the descriptor under
     881                 :            :  *       construction. No error checking will be made. Refer to the
     882                 :            :  *       block guide for details about the decapsulation PDB.
     883                 :            :  * @cipherdata: pointer to block cipher transform definitions.
     884                 :            :  *              Valid algorithm values - one of OP_PCL_IPSEC_*
     885                 :            :  * @authdata: pointer to authentication transform definitions
     886                 :            :  *            If an authentication key is required by the protocol:
     887                 :            :  *            -For SEC Eras 1-5, an MDHA split key must be provided;
     888                 :            :  *            Note that the size of the split key itself must be specified.
     889                 :            :  *            -For SEC Eras 6+, a "normal" key must be provided; DKP (Derived
     890                 :            :  *            Key Protocol) will be used to compute MDHA on the fly in HW.
     891                 :            :  *            Valid algorithm values - one of OP_PCL_IPSEC_*
     892                 :            :  *
     893                 :            :  * Return: size of descriptor written in words or negative number on error
     894                 :            :  */
     895                 :            : static inline int
     896                 :            : cnstr_shdsc_ipsec_decap(uint32_t *descbuf, bool ps, bool swap,
     897                 :            :                         enum rta_share_type share,
     898                 :            :                         struct ipsec_decap_pdb *pdb,
     899                 :            :                         struct alginfo *cipherdata,
     900                 :            :                         struct alginfo *authdata)
     901                 :            : {
     902                 :            :         struct program prg;
     903                 :            :         struct program *p = &prg;
     904                 :            : 
     905                 :            :         LABEL(keyjmp);
     906                 :            :         REFERENCE(pkeyjmp);
     907                 :            :         LABEL(hdr);
     908                 :            :         REFERENCE(phdr);
     909                 :            : 
     910                 :            :         PROGRAM_CNTXT_INIT(p, descbuf, 0);
     911                 :            :         if (swap)
     912                 :            :                 PROGRAM_SET_BSWAP(p);
     913                 :            :         if (ps)
     914                 :            :                 PROGRAM_SET_36BIT_ADDR(p);
     915                 :            :         phdr = SHR_HDR(p, share, hdr, 0);
     916                 :            :         __rta_copy_ipsec_decap_pdb(p, pdb, cipherdata->algtype);
     917                 :            :         SET_LABEL(p, hdr);
     918                 :            :         pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, BOTH|SHRD);
     919                 :            :         if (authdata->keylen)
     920                 :            :                 __gen_auth_key(p, authdata);
     921                 :            : 
     922                 :            :         if (cipherdata->keylen)
     923                 :            :                 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
     924                 :            :                     cipherdata->keylen, INLINE_KEY(cipherdata));
     925                 :            :         SET_LABEL(p, keyjmp);
     926                 :            :         PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
     927                 :            :                  OP_PCLID_IPSEC,
     928                 :            :                  (uint16_t)(cipherdata->algtype | authdata->algtype));
     929                 :            :         PATCH_JUMP(p, pkeyjmp, keyjmp);
     930                 :            :         PATCH_HDR(p, phdr, hdr);
     931                 :            :         return PROGRAM_FINALIZE(p);
     932                 :            : }
     933                 :            : 
     934                 :            : /**
     935                 :            :  * cnstr_shdsc_ipsec_encap_des_aes_xcbc - IPSec DES-CBC/3DES-CBC and
     936                 :            :  *     AES-XCBC-MAC-96 ESP encapsulation shared descriptor.
     937                 :            :  * @descbuf: pointer to buffer used for descriptor construction
     938                 :            :  * @share: sharing type of shared descriptor
     939                 :            :  * @pdb: pointer to the PDB to be used with this descriptor
     940                 :            :  *       This structure will be copied inline to the descriptor under
     941                 :            :  *       construction. No error checking will be made. Refer to the
     942                 :            :  *       block guide for a details of the encapsulation PDB.
     943                 :            :  * @cipherdata: pointer to block cipher transform definitions
     944                 :            :  *              Valid algorithm values - OP_PCL_IPSEC_DES, OP_PCL_IPSEC_3DES.
     945                 :            :  * @authdata: pointer to authentication transform definitions
     946                 :            :  *            Valid algorithm value: OP_PCL_IPSEC_AES_XCBC_MAC_96.
     947                 :            :  *
     948                 :            :  * Supported only for platforms with 32-bit address pointers and SEC ERA 4 or
     949                 :            :  * higher. The tunnel/transport mode of the IPsec ESP is supported only if the
     950                 :            :  * Outer/Transport IP Header is present in the encapsulation output packet.
     951                 :            :  * The descriptor performs DES-CBC/3DES-CBC & HMAC-MD5-96 and then rereads
     952                 :            :  * the input packet to do the AES-XCBC-MAC-96 calculation and to overwrite
     953                 :            :  * the MD5 ICV.
     954                 :            :  * The descriptor uses all the benefits of the built-in protocol by computing
     955                 :            :  * the IPsec ESP with a hardware supported algorithms combination
     956                 :            :  * (DES-CBC/3DES-CBC & HMAC-MD5-96). The HMAC-MD5 authentication algorithm
     957                 :            :  * was chosen in order to speed up the computational time for this intermediate
     958                 :            :  * step.
     959                 :            :  * Warning: The user must allocate at least 32 bytes for the authentication key
     960                 :            :  * (in order to use it also with HMAC-MD5-96),even when using a shorter key
     961                 :            :  * for the AES-XCBC-MAC-96.
     962                 :            :  *
     963                 :            :  * Return: size of descriptor written in words or negative number on error
     964                 :            :  */
     965                 :            : static inline int
     966                 :            : cnstr_shdsc_ipsec_encap_des_aes_xcbc(uint32_t *descbuf,
     967                 :            :                                      enum rta_share_type share,
     968                 :            :                                      struct ipsec_encap_pdb *pdb,
     969                 :            :                                      struct alginfo *cipherdata,
     970                 :            :                                      struct alginfo *authdata)
     971                 :            : {
     972                 :            :         struct program prg;
     973                 :            :         struct program *p = &prg;
     974                 :            : 
     975                 :            :         LABEL(hdr);
     976                 :            :         LABEL(shd_ptr);
     977                 :            :         LABEL(keyjump);
     978                 :            :         LABEL(outptr);
     979                 :            :         LABEL(swapped_seqin_fields);
     980                 :            :         LABEL(swapped_seqin_ptr);
     981                 :            :         REFERENCE(phdr);
     982                 :            :         REFERENCE(pkeyjump);
     983                 :            :         REFERENCE(move_outlen);
     984                 :            :         REFERENCE(move_seqout_ptr);
     985                 :            :         REFERENCE(swapped_seqin_ptr_jump);
     986                 :            :         REFERENCE(write_swapped_seqin_ptr);
     987                 :            : 
     988                 :            :         PROGRAM_CNTXT_INIT(p, descbuf, 0);
     989                 :            :         phdr = SHR_HDR(p, share, hdr, 0);
     990                 :            :         __rta_copy_ipsec_encap_pdb(p, pdb, cipherdata->algtype);
     991                 :            : 
     992                 :            :         /* IP header if any follows the encap_pdb */
     993                 :            :         if (pdb->ip_hdr_len > 0) {
     994                 :            :                 void *ip_hdr = pdb + 1;
     995                 :            :                 COPY_DATA(p, ip_hdr, pdb->ip_hdr_len);
     996                 :            :         }
     997                 :            : 
     998                 :            :         SET_LABEL(p, hdr);
     999                 :            :         pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF);
    1000                 :            :         /*
    1001                 :            :          * Hard-coded KEY arguments. The descriptor uses all the benefits of
    1002                 :            :          * the built-in protocol by computing the IPsec ESP with a hardware
    1003                 :            :          * supported algorithms combination (DES-CBC/3DES-CBC & HMAC-MD5-96).
    1004                 :            :          * The HMAC-MD5 authentication algorithm was chosen with
    1005                 :            :          * the keys options from below in order to speed up the computational
    1006                 :            :          * time for this intermediate step.
    1007                 :            :          * Warning: The user must allocate at least 32 bytes for
    1008                 :            :          * the authentication key (in order to use it also with HMAC-MD5-96),
    1009                 :            :          * even when using a shorter key for the AES-XCBC-MAC-96.
    1010                 :            :          */
    1011                 :            :         KEY(p, MDHA_SPLIT_KEY, 0, authdata->key, 32, INLINE_KEY(authdata));
    1012                 :            :         SET_LABEL(p, keyjump);
    1013                 :            :         LOAD(p, LDST_SRCDST_WORD_CLRW | CLRW_CLR_C1MODE | CLRW_CLR_C1DATAS |
    1014                 :            :              CLRW_CLR_C1CTX | CLRW_CLR_C1KEY | CLRW_RESET_CLS1_CHA, CLRW, 0, 4,
    1015                 :            :              IMMED);
    1016                 :            :         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
    1017                 :            :             cipherdata->keylen, INLINE_KEY(cipherdata));
    1018                 :            :         PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL, OP_PCLID_IPSEC,
    1019                 :            :                  (uint16_t)(cipherdata->algtype | OP_PCL_IPSEC_HMAC_MD5_96));
    1020                 :            :         /* Swap SEQINPTR to SEQOUTPTR. */
    1021                 :            :         move_seqout_ptr = MOVE(p, DESCBUF, 0, MATH1, 0, 16, WAITCOMP | IMMED);
    1022                 :            :         MATHB(p, MATH1, AND, ~(CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR), MATH1,
    1023                 :            :               8, IFB | IMMED2);
    1024                 :            : /*
    1025                 :            :  * TODO: RTA currently doesn't support creating a LOAD command
    1026                 :            :  * with another command as IMM.
    1027                 :            :  * To be changed when proper support is added in RTA.
    1028                 :            :  */
    1029                 :            :         LOAD(p, 0xa00000e5, MATH3, 4, 4, IMMED);
    1030                 :            :         MATHB(p, MATH3, SHLD, MATH3, MATH3,  8, 0);
    1031                 :            :         write_swapped_seqin_ptr = MOVE(p, MATH1, 0, DESCBUF, 0, 20, WAITCOMP |
    1032                 :            :                                        IMMED);
    1033                 :            :         swapped_seqin_ptr_jump = JUMP(p, swapped_seqin_ptr, LOCAL_JUMP,
    1034                 :            :                                       ALL_TRUE, 0);
    1035                 :            :         LOAD(p, LDST_SRCDST_WORD_CLRW | CLRW_CLR_C1MODE | CLRW_CLR_C1DATAS |
    1036                 :            :              CLRW_CLR_C1CTX | CLRW_CLR_C1KEY | CLRW_RESET_CLS1_CHA, CLRW, 0, 4,
    1037                 :            :              0);
    1038                 :            :         SEQOUTPTR(p, 0, 65535, RTO);
    1039                 :            :         move_outlen = MOVE(p, DESCBUF, 0, MATH0, 4, 8, WAITCOMP | IMMED);
    1040                 :            :         MATHB(p, MATH0, SUB,
    1041                 :            :               (uint64_t)(pdb->ip_hdr_len + IPSEC_ICV_MD5_TRUNC_SIZE),
    1042                 :            :               VSEQINSZ, 4, IMMED2);
    1043                 :            :         MATHB(p, MATH0, SUB, IPSEC_ICV_MD5_TRUNC_SIZE, VSEQOUTSZ, 4, IMMED2);
    1044                 :            :         KEY(p, KEY1, authdata->key_enc_flags, authdata->key, authdata->keylen,
    1045                 :            :             0);
    1046                 :            :         ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_XCBC_MAC,
    1047                 :            :                       OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
    1048                 :            :         SEQFIFOLOAD(p, SKIP, pdb->ip_hdr_len, 0);
    1049                 :            :         SEQFIFOLOAD(p, MSG1, 0, VLF | FLUSH1 | LAST1);
    1050                 :            :         SEQFIFOSTORE(p, SKIP, 0, 0, VLF);
    1051                 :            :         SEQSTORE(p, CONTEXT1, 0, IPSEC_ICV_MD5_TRUNC_SIZE, 0);
    1052                 :            : /*
    1053                 :            :  * TODO: RTA currently doesn't support adding labels in or after Job Descriptor.
    1054                 :            :  * To be changed when proper support is added in RTA.
    1055                 :            :  */
    1056                 :            :         /* Label the Shared Descriptor Pointer */
    1057                 :            :         SET_LABEL(p, shd_ptr);
    1058                 :            :         shd_ptr += 1;
    1059                 :            :         /* Label the Output Pointer */
    1060                 :            :         SET_LABEL(p, outptr);
    1061                 :            :         outptr += 3;
    1062                 :            :         /* Label the first word after JD */
    1063                 :            :         SET_LABEL(p, swapped_seqin_fields);
    1064                 :            :         swapped_seqin_fields += 8;
    1065                 :            :         /* Label the second word after JD */
    1066                 :            :         SET_LABEL(p, swapped_seqin_ptr);
    1067                 :            :         swapped_seqin_ptr += 9;
    1068                 :            : 
    1069                 :            :         PATCH_HDR(p, phdr, hdr);
    1070                 :            :         PATCH_JUMP(p, pkeyjump, keyjump);
    1071                 :            :         PATCH_JUMP(p, swapped_seqin_ptr_jump, swapped_seqin_ptr);
    1072                 :            :         PATCH_MOVE(p, move_outlen, outptr);
    1073                 :            :         PATCH_MOVE(p, move_seqout_ptr, shd_ptr);
    1074                 :            :         PATCH_MOVE(p, write_swapped_seqin_ptr, swapped_seqin_fields);
    1075                 :            :         return PROGRAM_FINALIZE(p);
    1076                 :            : }
    1077                 :            : 
    1078                 :            : /**
    1079                 :            :  * cnstr_shdsc_ipsec_decap_des_aes_xcbc - IPSec DES-CBC/3DES-CBC and
    1080                 :            :  *     AES-XCBC-MAC-96 ESP decapsulation shared descriptor.
    1081                 :            :  * @descbuf: pointer to buffer used for descriptor construction
    1082                 :            :  * @share: sharing type of shared descriptor
    1083                 :            :  * @pdb: pointer to the PDB to be used with this descriptor
    1084                 :            :  *       This structure will be copied inline to the descriptor under
    1085                 :            :  *       construction. No error checking will be made. Refer to the
    1086                 :            :  *       block guide for a details of the encapsulation PDB.
    1087                 :            :  * @cipherdata: pointer to block cipher transform definitions
    1088                 :            :  *              Valid algorithm values - OP_PCL_IPSEC_DES, OP_PCL_IPSEC_3DES.
    1089                 :            :  * @authdata: pointer to authentication transform definitions
    1090                 :            :  *            Valid algorithm value: OP_PCL_IPSEC_AES_XCBC_MAC_96.
    1091                 :            :  *
    1092                 :            :  * Supported only for platforms with 32-bit address pointers and SEC ERA 4 or
    1093                 :            :  * higher. The tunnel/transport mode of the IPsec ESP is supported only if the
    1094                 :            :  * Outer/Transport IP Header is present in the decapsulation input packet.
    1095                 :            :  * The descriptor computes the AES-XCBC-MAC-96 to check if the received ICV
    1096                 :            :  * is correct, rereads the input packet to compute the MD5 ICV, overwrites
    1097                 :            :  * the XCBC ICV, and then sends the modified input packet to the
    1098                 :            :  * DES-CBC/3DES-CBC & HMAC-MD5-96 IPsec.
    1099                 :            :  * The descriptor uses all the benefits of the built-in protocol by computing
    1100                 :            :  * the IPsec ESP with a hardware supported algorithms combination
    1101                 :            :  * (DES-CBC/3DES-CBC & HMAC-MD5-96). The HMAC-MD5 authentication algorithm
    1102                 :            :  * was chosen in order to speed up the computational time for this intermediate
    1103                 :            :  * step.
    1104                 :            :  * Warning: The user must allocate at least 32 bytes for the authentication key
    1105                 :            :  * (in order to use it also with HMAC-MD5-96),even when using a shorter key
    1106                 :            :  * for the AES-XCBC-MAC-96.
    1107                 :            :  *
    1108                 :            :  * Return: size of descriptor written in words or negative number on error
    1109                 :            :  */
    1110                 :            : static inline int
    1111                 :            : cnstr_shdsc_ipsec_decap_des_aes_xcbc(uint32_t *descbuf,
    1112                 :            :                                      enum rta_share_type share,
    1113                 :            :                                      struct ipsec_decap_pdb *pdb,
    1114                 :            :                                      struct alginfo *cipherdata,
    1115                 :            :                                      struct alginfo *authdata)
    1116                 :            : {
    1117                 :            :         struct program prg;
    1118                 :            :         struct program *p = &prg;
    1119                 :            :         uint32_t ip_hdr_len = (pdb->options & PDBHDRLEN_MASK) >>
    1120                 :            :                                 PDBHDRLEN_ESP_DECAP_SHIFT;
    1121                 :            : 
    1122                 :            :         LABEL(hdr);
    1123                 :            :         LABEL(jump_cmd);
    1124                 :            :         LABEL(keyjump);
    1125                 :            :         LABEL(outlen);
    1126                 :            :         LABEL(seqin_ptr);
    1127                 :            :         LABEL(seqout_ptr);
    1128                 :            :         LABEL(swapped_seqout_fields);
    1129                 :            :         LABEL(swapped_seqout_ptr);
    1130                 :            :         REFERENCE(seqout_ptr_jump);
    1131                 :            :         REFERENCE(phdr);
    1132                 :            :         REFERENCE(pkeyjump);
    1133                 :            :         REFERENCE(move_jump);
    1134                 :            :         REFERENCE(move_jump_back);
    1135                 :            :         REFERENCE(move_seqin_ptr);
    1136                 :            :         REFERENCE(swapped_seqout_ptr_jump);
    1137                 :            :         REFERENCE(write_swapped_seqout_ptr);
    1138                 :            : 
    1139                 :            :         PROGRAM_CNTXT_INIT(p, descbuf, 0);
    1140                 :            :         phdr = SHR_HDR(p, share, hdr, 0);
    1141                 :            :         __rta_copy_ipsec_decap_pdb(p, pdb, cipherdata->algtype);
    1142                 :            :         SET_LABEL(p, hdr);
    1143                 :            :         pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF);
    1144                 :            :         /*
    1145                 :            :          * Hard-coded KEY arguments. The descriptor uses all the benefits of
    1146                 :            :          * the built-in protocol by computing the IPsec ESP with a hardware
    1147                 :            :          * supported algorithms combination (DES-CBC/3DES-CBC & HMAC-MD5-96).
    1148                 :            :          * The HMAC-MD5 authentication algorithm was chosen with
    1149                 :            :          * the keys options from bellow in order to speed up the computational
    1150                 :            :          * time for this intermediate step.
    1151                 :            :          * Warning: The user must allocate at least 32 bytes for
    1152                 :            :          * the authentication key (in order to use it also with HMAC-MD5-96),
    1153                 :            :          * even when using a shorter key for the AES-XCBC-MAC-96.
    1154                 :            :          */
    1155                 :            :         KEY(p, MDHA_SPLIT_KEY, 0, authdata->key, 32, INLINE_KEY(authdata));
    1156                 :            :         SET_LABEL(p, keyjump);
    1157                 :            :         LOAD(p, LDST_SRCDST_WORD_CLRW | CLRW_CLR_C1MODE | CLRW_CLR_C1DATAS |
    1158                 :            :              CLRW_CLR_C1CTX | CLRW_CLR_C1KEY | CLRW_RESET_CLS1_CHA, CLRW, 0, 4,
    1159                 :            :              0);
    1160                 :            :         KEY(p, KEY1, authdata->key_enc_flags, authdata->key, authdata->keylen,
    1161                 :            :             INLINE_KEY(authdata));
    1162                 :            :         MATHB(p, SEQINSZ, SUB,
    1163                 :            :               (uint64_t)(ip_hdr_len + IPSEC_ICV_MD5_TRUNC_SIZE), MATH0, 4,
    1164                 :            :               IMMED2);
    1165                 :            :         MATHB(p, MATH0, SUB, ZERO, VSEQINSZ, 4, 0);
    1166                 :            :         ALG_OPERATION(p, OP_ALG_ALGSEL_MD5, OP_ALG_AAI_HMAC_PRECOMP,
    1167                 :            :                       OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
    1168                 :            :         ALG_OPERATION(p, OP_ALG_ALGSEL_AES, OP_ALG_AAI_XCBC_MAC,
    1169                 :            :                       OP_ALG_AS_INITFINAL, ICV_CHECK_ENABLE, DIR_DEC);
    1170                 :            :         SEQFIFOLOAD(p, SKIP, ip_hdr_len, 0);
    1171                 :            :         SEQFIFOLOAD(p, MSG1, 0, VLF | FLUSH1);
    1172                 :            :         SEQFIFOLOAD(p, ICV1, IPSEC_ICV_MD5_TRUNC_SIZE, FLUSH1 | LAST1);
    1173                 :            :         /* Swap SEQOUTPTR to SEQINPTR. */
    1174                 :            :         move_seqin_ptr = MOVE(p, DESCBUF, 0, MATH1, 0, 16, WAITCOMP | IMMED);
    1175                 :            :         MATHB(p, MATH1, OR, CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR, MATH1, 8,
    1176                 :            :               IFB | IMMED2);
    1177                 :            : /*
    1178                 :            :  * TODO: RTA currently doesn't support creating a LOAD command
    1179                 :            :  * with another command as IMM.
    1180                 :            :  * To be changed when proper support is added in RTA.
    1181                 :            :  */
    1182                 :            :         LOAD(p, 0xA00000e1, MATH3, 4, 4, IMMED);
    1183                 :            :         MATHB(p, MATH3, SHLD, MATH3, MATH3,  8, 0);
    1184                 :            :         write_swapped_seqout_ptr = MOVE(p, MATH1, 0, DESCBUF, 0, 20, WAITCOMP |
    1185                 :            :                                         IMMED);
    1186                 :            :         swapped_seqout_ptr_jump = JUMP(p, swapped_seqout_ptr, LOCAL_JUMP,
    1187                 :            :                                        ALL_TRUE, 0);
    1188                 :            : /*
    1189                 :            :  * TODO: To be changed when proper support is added in RTA (can't load
    1190                 :            :  * a command that is also written by RTA).
    1191                 :            :  * Change when proper RTA support is added.
    1192                 :            :  */
    1193                 :            :         SET_LABEL(p, jump_cmd);
    1194                 :            :         WORD(p, 0xA00000f3);
    1195                 :            :         SEQINPTR(p, 0, 65535, RTO);
    1196                 :            :         MATHB(p, MATH0, SUB, ZERO, VSEQINSZ, 4, 0);
    1197                 :            :         MATHB(p, MATH0, ADD, ip_hdr_len, VSEQOUTSZ, 4, IMMED2);
    1198                 :            :         move_jump = MOVE(p, DESCBUF, 0, OFIFO, 0, 8, WAITCOMP | IMMED);
    1199                 :            :         move_jump_back = MOVE(p, OFIFO, 0, DESCBUF, 0, 8, IMMED);
    1200                 :            :         SEQFIFOLOAD(p, SKIP, ip_hdr_len, 0);
    1201                 :            :         SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2);
    1202                 :            :         SEQFIFOSTORE(p, SKIP, 0, 0, VLF);
    1203                 :            :         SEQSTORE(p, CONTEXT2, 0, IPSEC_ICV_MD5_TRUNC_SIZE, 0);
    1204                 :            :         seqout_ptr_jump = JUMP(p, seqout_ptr, LOCAL_JUMP, ALL_TRUE, CALM);
    1205                 :            : 
    1206                 :            :         LOAD(p, LDST_SRCDST_WORD_CLRW | CLRW_CLR_C1MODE | CLRW_CLR_C1DATAS |
    1207                 :            :              CLRW_CLR_C1CTX | CLRW_CLR_C1KEY | CLRW_CLR_C2MODE |
    1208                 :            :              CLRW_CLR_C2DATAS | CLRW_CLR_C2CTX | CLRW_RESET_CLS1_CHA, CLRW, 0,
    1209                 :            :              4, 0);
    1210                 :            :         SEQINPTR(p, 0, 65535, RTO);
    1211                 :            :         MATHB(p, MATH0, ADD,
    1212                 :            :               (uint64_t)(ip_hdr_len + IPSEC_ICV_MD5_TRUNC_SIZE), SEQINSZ, 4,
    1213                 :            :               IMMED2);
    1214                 :            :         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
    1215                 :            :             cipherdata->keylen, INLINE_KEY(cipherdata));
    1216                 :            :         PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL, OP_PCLID_IPSEC,
    1217                 :            :                  (uint16_t)(cipherdata->algtype | OP_PCL_IPSEC_HMAC_MD5_96));
    1218                 :            : /*
    1219                 :            :  * TODO: RTA currently doesn't support adding labels in or after Job Descriptor.
    1220                 :            :  * To be changed when proper support is added in RTA.
    1221                 :            :  */
    1222                 :            :         /* Label the SEQ OUT PTR */
    1223                 :            :         SET_LABEL(p, seqout_ptr);
    1224                 :            :         seqout_ptr += 2;
    1225                 :            :         /* Label the Output Length */
    1226                 :            :         SET_LABEL(p, outlen);
    1227                 :            :         outlen += 4;
    1228                 :            :         /* Label the SEQ IN PTR */
    1229                 :            :         SET_LABEL(p, seqin_ptr);
    1230                 :            :         seqin_ptr += 5;
    1231                 :            :         /* Label the first word after JD */
    1232                 :            :         SET_LABEL(p, swapped_seqout_fields);
    1233                 :            :         swapped_seqout_fields += 8;
    1234                 :            :         /* Label the second word after JD */
    1235                 :            :         SET_LABEL(p, swapped_seqout_ptr);
    1236                 :            :         swapped_seqout_ptr += 9;
    1237                 :            : 
    1238                 :            :         PATCH_HDR(p, phdr, hdr);
    1239                 :            :         PATCH_JUMP(p, pkeyjump, keyjump);
    1240                 :            :         PATCH_JUMP(p, seqout_ptr_jump, seqout_ptr);
    1241                 :            :         PATCH_JUMP(p, swapped_seqout_ptr_jump, swapped_seqout_ptr);
    1242                 :            :         PATCH_MOVE(p, move_jump, jump_cmd);
    1243                 :            :         PATCH_MOVE(p, move_jump_back, seqin_ptr);
    1244                 :            :         PATCH_MOVE(p, move_seqin_ptr, outlen);
    1245                 :            :         PATCH_MOVE(p, write_swapped_seqout_ptr, swapped_seqout_fields);
    1246                 :            :         return PROGRAM_FINALIZE(p);
    1247                 :            : }
    1248                 :            : 
    1249                 :            : /**
    1250                 :            :  * IPSEC_NEW_ENC_BASE_DESC_LEN - IPsec new mode encap shared descriptor length
    1251                 :            :  *
    1252                 :            :  * Accounts only for the "base" commands and is intended to be used by upper
    1253                 :            :  * layers to determine whether Outer IP Header and/or keys can be inlined or
    1254                 :            :  * not. To be used as first parameter of rta_inline_query().
    1255                 :            :  */
    1256                 :            : #define IPSEC_NEW_ENC_BASE_DESC_LEN     (12 * CAAM_CMD_SZ + \
    1257                 :            :                                          sizeof(struct ipsec_encap_pdb))
    1258                 :            : 
    1259                 :            : /**
    1260                 :            :  * IPSEC_NEW_NULL_ENC_BASE_DESC_LEN - IPsec new mode encap shared descriptor
    1261                 :            :  *                                    length for the case of
    1262                 :            :  *                                    NULL encryption / authentication
    1263                 :            :  *
    1264                 :            :  * Accounts only for the "base" commands and is intended to be used by upper
    1265                 :            :  * layers to determine whether Outer IP Header and/or key can be inlined or
    1266                 :            :  * not. To be used as first parameter of rta_inline_query().
    1267                 :            :  */
    1268                 :            : #define IPSEC_NEW_NULL_ENC_BASE_DESC_LEN        (11 * CAAM_CMD_SZ + \
    1269                 :            :                                                  sizeof(struct ipsec_encap_pdb))
    1270                 :            : 
    1271                 :            : /**
    1272                 :            :  * cnstr_shdsc_ipsec_new_encap -  IPSec new mode ESP encapsulation
    1273                 :            :  *     protocol-level shared descriptor.
    1274                 :            :  * @descbuf: pointer to buffer used for descriptor construction
    1275                 :            :  * @ps: if 36/40bit addressing is desired, this parameter must be true
    1276                 :            :  * @swap: must be true when core endianness doesn't match SEC endianness
    1277                 :            :  * @share: sharing type of shared descriptor
    1278                 :            :  * @pdb: pointer to the PDB to be used with this descriptor
    1279                 :            :  *       This structure will be copied inline to the descriptor under
    1280                 :            :  *       construction. No error checking will be made. Refer to the
    1281                 :            :  *       block guide for details about the encapsulation PDB.
    1282                 :            :  * @opt_ip_hdr:  pointer to Optional IP Header
    1283                 :            :  *     -if OIHI = PDBOPTS_ESP_OIHI_PDB_INL, opt_ip_hdr points to the buffer to
    1284                 :            :  *     be inlined in the PDB. Number of bytes (buffer size) copied is provided
    1285                 :            :  *     in pdb->ip_hdr_len.
    1286                 :            :  *     -if OIHI = PDBOPTS_ESP_OIHI_PDB_REF, opt_ip_hdr points to the address of
    1287                 :            :  *     the Optional IP Header. The address will be inlined in the PDB verbatim.
    1288                 :            :  *     -for other values of OIHI options field, opt_ip_hdr is not used.
    1289                 :            :  * @cipherdata: pointer to block cipher transform definitions
    1290                 :            :  *              Valid algorithm values - one of OP_PCL_IPSEC_*
    1291                 :            :  * @authdata: pointer to authentication transform definitions.
    1292                 :            :  *            If an authentication key is required by the protocol, a "normal"
    1293                 :            :  *            key must be provided; DKP (Derived Key Protocol) will be used to
    1294                 :            :  *            compute MDHA on the fly in HW.
    1295                 :            :  *            Valid algorithm values - one of OP_PCL_IPSEC_*
    1296                 :            :  *
    1297                 :            :  * Note: L2 header copy functionality is implemented assuming that bits 14
    1298                 :            :  * (currently reserved) and 16-23 (part of Outer IP Header Material Length)
    1299                 :            :  * in DPOVRD register are not used (which is usually the case when L3 header
    1300                 :            :  * is provided in PDB).
    1301                 :            :  * When DPOVRD[14] is set, frame starts with an L2 header; in this case, the
    1302                 :            :  * L2 header length is found at DPOVRD[23:16]. SEC uses this length to copy
    1303                 :            :  * the header and then it deletes DPOVRD[23:16] (so there is no side effect
    1304                 :            :  * when later running IPsec protocol).
    1305                 :            :  *
    1306                 :            :  * Return: size of descriptor written in words or negative number on error
    1307                 :            :  */
    1308                 :            : static inline int
    1309         [ #  # ]:          0 : cnstr_shdsc_ipsec_new_encap(uint32_t *descbuf, bool ps,
    1310                 :            :                             bool swap,
    1311                 :            :                             enum rta_share_type share,
    1312                 :            :                             struct ipsec_encap_pdb *pdb,
    1313                 :            :                             uint8_t *opt_ip_hdr,
    1314                 :            :                             struct alginfo *cipherdata,
    1315                 :            :                             struct alginfo *authdata)
    1316                 :            : {
    1317                 :            :         struct program prg;
    1318                 :            :         struct program *p = &prg;
    1319                 :            : 
    1320                 :            :         LABEL(keyjmp);
    1321                 :            :         REFERENCE(pkeyjmp);
    1322                 :            :         LABEL(hdr);
    1323                 :            :         REFERENCE(phdr);
    1324                 :            :         LABEL(l2copy);
    1325                 :            :         REFERENCE(pl2copy);
    1326                 :            : 
    1327                 :            :         PROGRAM_CNTXT_INIT(p, descbuf, 0);
    1328         [ #  # ]:          0 :         if (swap)
    1329                 :            :                 PROGRAM_SET_BSWAP(p);
    1330         [ #  # ]:          0 :         if (ps)
    1331                 :            :                 PROGRAM_SET_36BIT_ADDR(p);
    1332                 :          0 :         phdr = SHR_HDR(p, share, hdr, 0);
    1333                 :            : 
    1334                 :          0 :         __rta_copy_ipsec_encap_pdb(p, pdb, cipherdata->algtype);
    1335                 :            : 
    1336      [ #  #  # ]:          0 :         switch (pdb->options & PDBOPTS_ESP_OIHI_MASK) {
    1337                 :          0 :         case PDBOPTS_ESP_OIHI_PDB_INL:
    1338                 :          0 :                 COPY_DATA(p, opt_ip_hdr, pdb->ip_hdr_len);
    1339                 :            :                 break;
    1340                 :          0 :         case PDBOPTS_ESP_OIHI_PDB_REF:
    1341         [ #  # ]:          0 :                 if (ps)
    1342                 :            :                         COPY_DATA(p, opt_ip_hdr, 8);
    1343                 :            :                 else
    1344                 :            :                         COPY_DATA(p, opt_ip_hdr, 4);
    1345                 :            :                 break;
    1346                 :            :         default:
    1347                 :            :                 break;
    1348                 :            :         }
    1349                 :            :         SET_LABEL(p, hdr);
    1350                 :            : 
    1351                 :          0 :         MATHB(p, DPOVRD, AND, IPSEC_N_ENCAP_DPOVRD_L2_COPY, NONE, 4, IMMED2);
    1352                 :          0 :         pl2copy = JUMP(p, l2copy, LOCAL_JUMP, ALL_TRUE, MATH_Z);
    1353                 :          0 :         MATHI(p, DPOVRD, RSHIFT, IPSEC_N_ENCAP_DPOVRD_L2_LEN_SHIFT, VSEQOUTSZ,
    1354                 :            :               1, 0);
    1355                 :          0 :         MATHB(p, DPOVRD, AND, ~IPSEC_N_ENCAP_DPOVRD_L2_LEN_MASK, DPOVRD, 4,
    1356                 :            :               IMMED2);
    1357                 :            :         /* TODO: CLASS2 corresponds to AUX=2'b10; add more intuitive defines */
    1358                 :          0 :         SEQFIFOSTORE(p, METADATA, 0, 0, CLASS2 | VLF);
    1359                 :            :         SET_LABEL(p, l2copy);
    1360                 :            : 
    1361                 :          0 :         pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
    1362         [ #  # ]:          0 :         if (authdata->keylen)
    1363                 :          0 :                 __gen_auth_key(p, authdata);
    1364         [ #  # ]:          0 :         if (cipherdata->keylen)
    1365                 :          0 :                 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
    1366                 :            :                     cipherdata->keylen, INLINE_KEY(cipherdata));
    1367                 :            :         SET_LABEL(p, keyjmp);
    1368                 :          0 :         PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
    1369                 :            :                  OP_PCLID_IPSEC_NEW,
    1370                 :            :                  (uint16_t)(cipherdata->algtype | authdata->algtype));
    1371                 :          0 :         PATCH_JUMP(p, pl2copy, l2copy);
    1372                 :          0 :         PATCH_JUMP(p, pkeyjmp, keyjmp);
    1373                 :          0 :         PATCH_HDR(p, phdr, hdr);
    1374                 :          0 :         return PROGRAM_FINALIZE(p);
    1375                 :            : }
    1376                 :            : 
    1377                 :            : /**
    1378                 :            :  * IPSEC_NEW_DEC_BASE_DESC_LEN - IPsec new mode decap shared descriptor length
    1379                 :            :  *
    1380                 :            :  * Accounts only for the "base" commands and is intended to be used by upper
    1381                 :            :  * layers to determine whether keys can be inlined or not. To be used as first
    1382                 :            :  * parameter of rta_inline_query().
    1383                 :            :  */
    1384                 :            : #define IPSEC_NEW_DEC_BASE_DESC_LEN     (5 * CAAM_CMD_SZ + \
    1385                 :            :                                          sizeof(struct ipsec_decap_pdb))
    1386                 :            : 
    1387                 :            : /**
    1388                 :            :  * IPSEC_NEW_NULL_DEC_BASE_DESC_LEN - IPsec new mode decap shared descriptor
    1389                 :            :  *                                    length for the case of
    1390                 :            :  *                                    NULL decryption / authentication
    1391                 :            :  *
    1392                 :            :  * Accounts only for the "base" commands and is intended to be used by upper
    1393                 :            :  * layers to determine whether key can be inlined or not. To be used as first
    1394                 :            :  * parameter of rta_inline_query().
    1395                 :            :  */
    1396                 :            : #define IPSEC_NEW_NULL_DEC_BASE_DESC_LEN        (4 * CAAM_CMD_SZ + \
    1397                 :            :                                                  sizeof(struct ipsec_decap_pdb))
    1398                 :            : 
    1399                 :            : /**
    1400                 :            :  * cnstr_shdsc_ipsec_new_decap - IPSec new mode ESP decapsulation protocol-level
    1401                 :            :  *     shared descriptor.
    1402                 :            :  * @descbuf: pointer to buffer used for descriptor construction
    1403                 :            :  * @ps: if 36/40bit addressing is desired, this parameter must be true
    1404                 :            :  * @swap: must be true when core endianness doesn't match SEC endianness
    1405                 :            :  * @share: sharing type of shared descriptor
    1406                 :            :  * @pdb: pointer to the PDB to be used with this descriptor
    1407                 :            :  *       This structure will be copied inline to the descriptor under
    1408                 :            :  *       construction. No error checking will be made. Refer to the
    1409                 :            :  *       block guide for details about the decapsulation PDB.
    1410                 :            :  * @cipherdata: pointer to block cipher transform definitions
    1411                 :            :  *              Valid algorithm values 0 one of OP_PCL_IPSEC_*
    1412                 :            :  * @authdata: pointer to authentication transform definitions.
    1413                 :            :  *            If an authentication key is required by the protocol, a "normal"
    1414                 :            :  *            key must be provided; DKP (Derived Key Protocol) will be used to
    1415                 :            :  *            compute MDHA on the fly in HW.
    1416                 :            :  *            Valid algorithm values - one of OP_PCL_IPSEC_*
    1417                 :            :  *
    1418                 :            :  * Return: size of descriptor written in words or negative number on error
    1419                 :            :  */
    1420                 :            : static inline int
    1421         [ #  # ]:          0 : cnstr_shdsc_ipsec_new_decap(uint32_t *descbuf, bool ps,
    1422                 :            :                             bool swap,
    1423                 :            :                             enum rta_share_type share,
    1424                 :            :                             struct ipsec_decap_pdb *pdb,
    1425                 :            :                             struct alginfo *cipherdata,
    1426                 :            :                             struct alginfo *authdata)
    1427                 :            : {
    1428                 :            :         struct program prg;
    1429                 :            :         struct program *p = &prg;
    1430                 :            : 
    1431                 :            :         LABEL(keyjmp);
    1432                 :            :         REFERENCE(pkeyjmp);
    1433                 :            :         LABEL(hdr);
    1434                 :            :         REFERENCE(phdr);
    1435                 :            : 
    1436                 :            :         PROGRAM_CNTXT_INIT(p, descbuf, 0);
    1437         [ #  # ]:          0 :         if (swap)
    1438                 :            :                 PROGRAM_SET_BSWAP(p);
    1439         [ #  # ]:          0 :         if (ps)
    1440                 :            :                 PROGRAM_SET_36BIT_ADDR(p);
    1441                 :          0 :         phdr = SHR_HDR(p, share, hdr, 0);
    1442                 :          0 :         __rta_copy_ipsec_decap_pdb(p, pdb, cipherdata->algtype);
    1443                 :            :         SET_LABEL(p, hdr);
    1444                 :          0 :         pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
    1445         [ #  # ]:          0 :         if (authdata->keylen)
    1446                 :          0 :                 __gen_auth_key(p, authdata);
    1447         [ #  # ]:          0 :         if (cipherdata->keylen)
    1448                 :          0 :                 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
    1449                 :            :                     cipherdata->keylen, INLINE_KEY(cipherdata));
    1450                 :            :         SET_LABEL(p, keyjmp);
    1451                 :          0 :         PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
    1452                 :            :                  OP_PCLID_IPSEC_NEW,
    1453                 :            :                  (uint16_t)(cipherdata->algtype | authdata->algtype));
    1454                 :          0 :         PATCH_JUMP(p, pkeyjmp, keyjmp);
    1455                 :          0 :         PATCH_HDR(p, phdr, hdr);
    1456                 :          0 :         return PROGRAM_FINALIZE(p);
    1457                 :            : }
    1458                 :            : 
    1459                 :            : /**
    1460                 :            :  * IPSEC_AUTH_VAR_BASE_DESC_LEN - IPsec encap/decap shared descriptor length
    1461                 :            :  *                              for the case of variable-length authentication
    1462                 :            :  *                              only data.
    1463                 :            :  *                              Note: Only for SoCs with SEC_ERA >= 3.
    1464                 :            :  *
    1465                 :            :  * Accounts only for the "base" commands and is intended to be used by upper
    1466                 :            :  * layers to determine whether keys can be inlined or not. To be used as first
    1467                 :            :  * parameter of rta_inline_query().
    1468                 :            :  */
    1469                 :            : #define IPSEC_AUTH_VAR_BASE_DESC_LEN    (31 * CAAM_CMD_SZ)
    1470                 :            : 
    1471                 :            : /**
    1472                 :            :  * IPSEC_AUTH_VAR_AES_DEC_BASE_DESC_LEN - IPsec AES decap shared descriptor
    1473                 :            :  *                              length for variable-length authentication only
    1474                 :            :  *                              data.
    1475                 :            :  *                              Note: Only for SoCs with SEC_ERA >= 3.
    1476                 :            :  *
    1477                 :            :  * Accounts only for the "base" commands and is intended to be used by upper
    1478                 :            :  * layers to determine whether key can be inlined or not. To be used as first
    1479                 :            :  * parameter of rta_inline_query().
    1480                 :            :  */
    1481                 :            : #define IPSEC_AUTH_VAR_AES_DEC_BASE_DESC_LEN    \
    1482                 :            :                                 (IPSEC_AUTH_VAR_BASE_DESC_LEN + CAAM_CMD_SZ)
    1483                 :            : 
    1484                 :            : /**
    1485                 :            :  * IPSEC_AUTH_BASE_DESC_LEN - IPsec encap/decap shared descriptor length
    1486                 :            :  *
    1487                 :            :  * Accounts only for the "base" commands and is intended to be used by upper
    1488                 :            :  * layers to determine whether key can be inlined or not. To be used as first
    1489                 :            :  * parameter of rta_inline_query().
    1490                 :            :  */
    1491                 :            : #define IPSEC_AUTH_BASE_DESC_LEN        (19 * CAAM_CMD_SZ)
    1492                 :            : 
    1493                 :            : /**
    1494                 :            :  * IPSEC_AUTH_AES_DEC_BASE_DESC_LEN - IPsec AES decap shared descriptor length
    1495                 :            :  *
    1496                 :            :  * Accounts only for the "base" commands and is intended to be used by upper
    1497                 :            :  * layers to determine whether key can be inlined or not. To be used as first
    1498                 :            :  * parameter of rta_inline_query().
    1499                 :            :  */
    1500                 :            : #define IPSEC_AUTH_AES_DEC_BASE_DESC_LEN        (IPSEC_AUTH_BASE_DESC_LEN + \
    1501                 :            :                                                 CAAM_CMD_SZ)
    1502                 :            : 
    1503                 :            : /**
    1504                 :            :  * cnstr_shdsc_authenc - authenc-like descriptor
    1505                 :            :  * @descbuf: pointer to buffer used for descriptor construction
    1506                 :            :  * @ps: if 36/40bit addressing is desired, this parameter must be true
    1507                 :            :  * @swap: if true, perform descriptor byte swapping on a 4-byte boundary
    1508                 :            :  * @share: sharing type of shared descriptor
    1509                 :            :  * @cipherdata: pointer to block cipher transform definitions.
    1510                 :            :  *              Valid algorithm values one of OP_ALG_ALGSEL_* {DES, 3DES, AES}
    1511                 :            :  *              Valid modes for:
    1512                 :            :  *                  AES: OP_ALG_AAI_* {CBC, CTR}
    1513                 :            :  *                  DES, 3DES: OP_ALG_AAI_CBC
    1514                 :            :  * @authdata: pointer to authentication transform definitions.
    1515                 :            :  *            Valid algorithm values - one of OP_ALG_ALGSEL_* {MD5, SHA1,
    1516                 :            :  *            SHA224, SHA256, SHA384, SHA512}
    1517                 :            :  * Note: The key for authentication is supposed to be given as plain text.
    1518                 :            :  * Note: There's no support for keys longer than the block size of the
    1519                 :            :  *       underlying hash function, according to the selected algorithm.
    1520                 :            :  *
    1521                 :            :  * @ivlen: length of the IV to be read from the input frame, before any data
    1522                 :            :  *         to be processed
    1523                 :            :  *
    1524                 :            :  * @trunc_len: the length of the ICV to be written to the output frame. If 0,
    1525                 :            :  *             then the corresponding length of the digest, according to the
    1526                 :            :  *             selected algorithm shall be used.
    1527                 :            :  * @dir: Protocol direction, encapsulation or decapsulation (DIR_ENC/DIR_DEC)
    1528                 :            :  *
    1529                 :            :  * Note: Here's how the input frame needs to be formatted so that the processing
    1530                 :            :  *       will be done correctly:
    1531                 :            :  * For encapsulation:
    1532                 :            :  *     Input:
    1533                 :            :  * +----+----------------+-----------------------------------------------+
    1534                 :            :  * | IV | Auth-only head | Padded data to be auth & Enc | Auth-only tail |
    1535                 :            :  * +----+----------------+-----------------------------------------------+
    1536                 :            :  *     Output:
    1537                 :            :  * +--------------------------------------+
    1538                 :            :  * | Authenticated & Encrypted data | ICV |
    1539                 :            :  * +--------------------------------+-----+
    1540                 :            :  *
    1541                 :            :  * For decapsulation:
    1542                 :            :  *     Input:
    1543                 :            :  * +----+----------------+-----------------+----------------------+
    1544                 :            :  * | IV | Auth-only head | Auth & Enc data | Auth-only tail | ICV |
    1545                 :            :  * +----+----------------+-----------------+----------------------+
    1546                 :            :  *     Output:
    1547                 :            :  * +----+---------------------------+
    1548                 :            :  * | Decrypted & authenticated data |
    1549                 :            :  * +----+---------------------------+
    1550                 :            :  *
    1551                 :            :  * Note: This descriptor can use per-packet commands, encoded as below in the
    1552                 :            :  *       DPOVRD register:
    1553                 :            :  * 32    28               16             1
    1554                 :            :  * +------+------------------------------+
    1555                 :            :  * | 0x8  | auth_tail_len | auth_hdr_len |
    1556                 :            :  * +------+------------------------------+
    1557                 :            :  *
    1558                 :            :  * This mechanism is available only for SoCs having SEC ERA >= 3. In other
    1559                 :            :  * words, this will not work for P4080TO2
    1560                 :            :  *
    1561                 :            :  * Note: The descriptor does not add any kind of padding to the input data,
    1562                 :            :  *       so the upper layer needs to ensure that the data is padded properly,
    1563                 :            :  *       according to the selected cipher. Failure to do so will result in
    1564                 :            :  *       the descriptor failing with a data-size error.
    1565                 :            :  *
    1566                 :            :  * Return: size of descriptor written in words or negative number on error
    1567                 :            :  */
    1568                 :            : static inline int
    1569                 :          0 : cnstr_shdsc_authenc(uint32_t *descbuf, bool ps, bool swap,
    1570                 :            :                     enum rta_share_type share,
    1571                 :            :                     struct alginfo *cipherdata,
    1572                 :            :                     struct alginfo *authdata,
    1573                 :            :                     uint16_t ivlen,
    1574                 :            :                     uint8_t trunc_len, uint8_t dir)
    1575                 :            : {
    1576                 :            :         struct program prg;
    1577                 :            :         struct program *p = &prg;
    1578         [ #  # ]:          0 :         const bool need_dk = (dir == DIR_DEC) &&
    1579   [ #  #  #  # ]:          0 :                              (cipherdata->algtype == OP_ALG_ALGSEL_AES) &&
    1580         [ #  # ]:          0 :                              (cipherdata->algmode == OP_ALG_AAI_CBC);
    1581                 :            :         int data_type;
    1582                 :            : 
    1583                 :            :         LABEL(keyjmp);
    1584                 :            :         LABEL(skipkeys);
    1585                 :            :         LABEL(proc_icv);
    1586                 :            :         LABEL(no_auth_tail);
    1587                 :            :         REFERENCE(pkeyjmp);
    1588                 :            :         REFERENCE(pskipkeys);
    1589                 :            :         REFERENCE(p_proc_icv);
    1590                 :            :         REFERENCE(p_no_auth_tail);
    1591                 :            : 
    1592                 :            :         PROGRAM_CNTXT_INIT(p, descbuf, 0);
    1593                 :            : 
    1594         [ #  # ]:          0 :         if (swap)
    1595                 :            :                 PROGRAM_SET_BSWAP(p);
    1596         [ #  # ]:          0 :         if (ps)
    1597                 :            :                 PROGRAM_SET_36BIT_ADDR(p);
    1598                 :            : 
    1599                 :            :         /*
    1600                 :            :          * Since we currently assume that key length is equal to hash digest
    1601                 :            :          * size, it's ok to truncate keylen value.
    1602                 :            :          */
    1603   [ #  #  #  # ]:          0 :         trunc_len = trunc_len && (trunc_len < authdata->keylen) ?
    1604                 :          0 :                         trunc_len : (uint8_t)authdata->keylen;
    1605                 :            : 
    1606                 :          0 :         SHR_HDR(p, share, 1, SC);
    1607                 :            : 
    1608                 :            :         /* Collect the (auth_tail || auth_hdr) len from DPOVRD */
    1609                 :          0 :         MATHB(p, DPOVRD, ADD, 0x80000000, MATH2, 4, IMMED2);
    1610                 :            : 
    1611                 :            :         /* Get auth_hdr len in MATH0 */
    1612                 :          0 :         MATHB(p, MATH2, AND, 0xFFFF, MATH0, 4, IMMED2);
    1613                 :            : 
    1614                 :            :         /* Get auth_tail len in MATH2 */
    1615                 :          0 :         MATHB(p, MATH2, AND, 0xFFF0000, MATH2, 4, IMMED2);
    1616                 :          0 :         MATHI(p, MATH2, RSHIFT, 16, MATH2, 4, IMMED2);
    1617                 :            : 
    1618                 :          0 :         pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
    1619                 :            : 
    1620                 :          0 :         KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
    1621                 :            :             INLINE_KEY(authdata));
    1622                 :            : 
    1623                 :            :         /* Insert Key */
    1624                 :          0 :         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
    1625                 :            :             cipherdata->keylen, INLINE_KEY(cipherdata));
    1626                 :            : 
    1627                 :            :         /* Do operation */
    1628                 :          0 :         ALG_OPERATION(p, authdata->algtype, authdata->algmode,
    1629                 :            :                       OP_ALG_AS_INITFINAL,
    1630                 :            :                       dir == DIR_ENC ? ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
    1631                 :            :                       dir);
    1632                 :            : 
    1633         [ #  # ]:          0 :         if (need_dk)
    1634                 :          0 :                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, cipherdata->algmode,
    1635                 :            :                               OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
    1636                 :          0 :         pskipkeys = JUMP(p, skipkeys, LOCAL_JUMP, ALL_TRUE, 0);
    1637                 :            : 
    1638                 :            :         SET_LABEL(p, keyjmp);
    1639                 :            : 
    1640         [ #  # ]:          0 :         if (authdata->algmode == OP_ALG_AAI_HMAC)
    1641                 :          0 :                 ALG_OPERATION(p, authdata->algtype, OP_ALG_AAI_HMAC_PRECOMP,
    1642                 :            :                       OP_ALG_AS_INITFINAL,
    1643                 :            :                       dir == DIR_ENC ? ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
    1644                 :            :                       dir);
    1645                 :            :         else
    1646                 :          0 :                 ALG_OPERATION(p, authdata->algtype, authdata->algmode,
    1647                 :            :                       OP_ALG_AS_INITFINAL,
    1648                 :            :                       dir == DIR_ENC ? ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
    1649                 :            :                       dir);
    1650                 :            : 
    1651         [ #  # ]:          0 :         if (need_dk) {
    1652                 :          0 :                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, cipherdata->algmode |
    1653                 :            :                               OP_ALG_AAI_DK, OP_ALG_AS_INITFINAL,
    1654                 :            :                               ICV_CHECK_DISABLE, dir);
    1655                 :            :                 SET_LABEL(p, skipkeys);
    1656                 :            :         } else {
    1657                 :            :                 SET_LABEL(p, skipkeys);
    1658                 :          0 :                 ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode,
    1659                 :            :                               OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
    1660                 :            :         }
    1661                 :            : 
    1662                 :            :         /* Read IV */
    1663         [ #  # ]:          0 :         if (cipherdata->algmode == OP_ALG_AAI_CTR)
    1664                 :          0 :                 SEQLOAD(p, CONTEXT1, 16, ivlen, 0);
    1665                 :            :         else
    1666                 :          0 :                 SEQLOAD(p, CONTEXT1, 0, ivlen, 0);
    1667                 :            : 
    1668                 :            :         /*
    1669                 :            :          * authenticate auth_hdr data
    1670                 :            :          */
    1671                 :          0 :         MATHB(p, MATH0, ADD, ZERO, VSEQINSZ, 4, 0);
    1672                 :          0 :         SEQFIFOLOAD(p, MSG2, 0, VLF);
    1673                 :            : 
    1674                 :            :         /*
    1675                 :            :          * Prepare the length of the data to be both encrypted/decrypted
    1676                 :            :          * and authenticated/checked
    1677                 :            :          */
    1678                 :          0 :         MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
    1679         [ #  # ]:          0 :         if (dir == DIR_DEC) {
    1680                 :          0 :                 MATHB(p, VSEQINSZ, SUB, trunc_len, VSEQINSZ, 4, IMMED2);
    1681                 :            :                 data_type = MSGINSNOOP;
    1682                 :            :         } else {
    1683                 :            :                 data_type = MSGOUTSNOOP;
    1684                 :            :         }
    1685                 :            : 
    1686                 :          0 :         MATHB(p, VSEQINSZ, ADD, ZERO, VSEQOUTSZ, 4, 0);
    1687                 :            : 
    1688                 :            :         /* Prepare for writing the output frame */
    1689                 :          0 :         SEQFIFOSTORE(p, MSG, 0, 0, VLF);
    1690                 :            : 
    1691                 :            : 
    1692                 :            :         /* Check if there is no auth-tail */
    1693                 :          0 :         MATHB(p, MATH2, ADD, ZERO, MATH2, 4, 0);
    1694                 :          0 :         p_no_auth_tail = JUMP(p, no_auth_tail, LOCAL_JUMP, ALL_TRUE, MATH_Z);
    1695                 :            : 
    1696                 :            :         /*
    1697                 :            :          * Read input plain/cipher text, encrypt/decrypt & auth & write
    1698                 :            :          * to output
    1699                 :            :          */
    1700                 :          0 :         SEQFIFOLOAD(p, data_type, 0, VLF | LAST1 | FLUSH1);
    1701                 :            : 
    1702                 :            :         /* Authenticate auth tail */
    1703                 :          0 :         MATHB(p, MATH2, ADD, ZERO, VSEQINSZ, 4, 0);
    1704                 :          0 :         SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2);
    1705                 :            : 
    1706                 :            :         /* Jump to process icv */
    1707                 :          0 :         p_proc_icv = JUMP(p, proc_icv, LOCAL_JUMP, ALL_FALSE, MATH_Z);
    1708                 :            : 
    1709                 :            :         SET_LABEL(p, no_auth_tail);
    1710                 :            : 
    1711                 :          0 :         SEQFIFOLOAD(p, data_type, 0, VLF | LAST1 | LAST2 | FLUSH1);
    1712                 :            : 
    1713                 :            :         SET_LABEL(p, proc_icv);
    1714                 :            : 
    1715         [ #  # ]:          0 :         if (dir == DIR_ENC)
    1716                 :            :                 /* Finally, write the ICV */
    1717                 :          0 :                 SEQSTORE(p, CONTEXT2, 0, trunc_len, 0);
    1718                 :            :         else
    1719                 :            :                 /* Read the ICV to check */
    1720                 :          0 :                 SEQFIFOLOAD(p, ICV2, trunc_len, LAST2);
    1721                 :            : 
    1722                 :          0 :         PATCH_JUMP(p, pkeyjmp, keyjmp);
    1723                 :          0 :         PATCH_JUMP(p, pskipkeys, skipkeys);
    1724                 :          0 :         PATCH_JUMP(p, p_no_auth_tail, no_auth_tail);
    1725                 :          0 :         PATCH_JUMP(p, p_proc_icv, proc_icv);
    1726                 :          0 :         return PROGRAM_FINALIZE(p);
    1727                 :            : }
    1728                 :            : 
    1729                 :            : #endif /* __DESC_IPSEC_H__ */

Generated by: LCOV version 1.14