Imported Upstream version 17.05
[deb_dpdk.git] / drivers / crypto / dpaa2_sec / hw / rta / protocol_cmd.h
diff --git a/drivers/crypto/dpaa2_sec/hw/rta/protocol_cmd.h b/drivers/crypto/dpaa2_sec/hw/rta/protocol_cmd.h
new file mode 100644 (file)
index 0000000..2e7b2f2
--- /dev/null
@@ -0,0 +1,732 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ *   BSD LICENSE
+ *
+ * Copyright 2008-2016 Freescale Semiconductor Inc.
+ * Copyright (c) 2016 NXP.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *   GPL LICENSE SUMMARY
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __RTA_PROTOCOL_CMD_H__
+#define __RTA_PROTOCOL_CMD_H__
+
+extern enum rta_sec_era rta_sec_era;
+
+static inline int
+__rta_ssl_proto(uint16_t protoinfo)
+{
+       switch (protoinfo) {
+       case OP_PCL_SSL30_RC4_40_MD5_2:
+       case OP_PCL_SSL30_RC4_128_MD5_2:
+       case OP_PCL_SSL30_RC4_128_SHA_5:
+       case OP_PCL_SSL30_RC4_40_MD5_3:
+       case OP_PCL_SSL30_RC4_128_MD5_3:
+       case OP_PCL_SSL30_RC4_128_SHA:
+       case OP_PCL_SSL30_RC4_128_MD5:
+       case OP_PCL_SSL30_RC4_40_SHA:
+       case OP_PCL_SSL30_RC4_40_MD5:
+       case OP_PCL_SSL30_RC4_128_SHA_2:
+       case OP_PCL_SSL30_RC4_128_SHA_3:
+       case OP_PCL_SSL30_RC4_128_SHA_4:
+       case OP_PCL_SSL30_RC4_128_SHA_6:
+       case OP_PCL_SSL30_RC4_128_SHA_7:
+       case OP_PCL_SSL30_RC4_128_SHA_8:
+       case OP_PCL_SSL30_RC4_128_SHA_9:
+       case OP_PCL_SSL30_RC4_128_SHA_10:
+       case OP_PCL_TLS_ECDHE_PSK_RC4_128_SHA:
+               if (rta_sec_era == RTA_SEC_ERA_7)
+                       return -EINVAL;
+               /* fall through if not Era 7 */
+       case OP_PCL_SSL30_DES40_CBC_SHA:
+       case OP_PCL_SSL30_DES_CBC_SHA_2:
+       case OP_PCL_SSL30_3DES_EDE_CBC_SHA_5:
+       case OP_PCL_SSL30_DES40_CBC_SHA_2:
+       case OP_PCL_SSL30_DES_CBC_SHA_3:
+       case OP_PCL_SSL30_3DES_EDE_CBC_SHA_6:
+       case OP_PCL_SSL30_DES40_CBC_SHA_3:
+       case OP_PCL_SSL30_DES_CBC_SHA_4:
+       case OP_PCL_SSL30_3DES_EDE_CBC_SHA_7:
+       case OP_PCL_SSL30_DES40_CBC_SHA_4:
+       case OP_PCL_SSL30_DES_CBC_SHA_5:
+       case OP_PCL_SSL30_3DES_EDE_CBC_SHA_8:
+       case OP_PCL_SSL30_DES40_CBC_SHA_5:
+       case OP_PCL_SSL30_DES_CBC_SHA_6:
+       case OP_PCL_SSL30_3DES_EDE_CBC_SHA_9:
+       case OP_PCL_SSL30_DES40_CBC_SHA_6:
+       case OP_PCL_SSL30_DES_CBC_SHA_7:
+       case OP_PCL_SSL30_3DES_EDE_CBC_SHA_10:
+       case OP_PCL_SSL30_DES_CBC_SHA:
+       case OP_PCL_SSL30_3DES_EDE_CBC_SHA:
+       case OP_PCL_SSL30_DES_CBC_MD5:
+       case OP_PCL_SSL30_3DES_EDE_CBC_MD5:
+       case OP_PCL_SSL30_DES40_CBC_SHA_7:
+       case OP_PCL_SSL30_DES40_CBC_MD5:
+       case OP_PCL_SSL30_AES_128_CBC_SHA:
+       case OP_PCL_SSL30_AES_128_CBC_SHA_2:
+       case OP_PCL_SSL30_AES_128_CBC_SHA_3:
+       case OP_PCL_SSL30_AES_128_CBC_SHA_4:
+       case OP_PCL_SSL30_AES_128_CBC_SHA_5:
+       case OP_PCL_SSL30_AES_128_CBC_SHA_6:
+       case OP_PCL_SSL30_AES_256_CBC_SHA:
+       case OP_PCL_SSL30_AES_256_CBC_SHA_2:
+       case OP_PCL_SSL30_AES_256_CBC_SHA_3:
+       case OP_PCL_SSL30_AES_256_CBC_SHA_4:
+       case OP_PCL_SSL30_AES_256_CBC_SHA_5:
+       case OP_PCL_SSL30_AES_256_CBC_SHA_6:
+       case OP_PCL_TLS12_AES_128_CBC_SHA256_2:
+       case OP_PCL_TLS12_AES_128_CBC_SHA256_3:
+       case OP_PCL_TLS12_AES_128_CBC_SHA256_4:
+       case OP_PCL_TLS12_AES_128_CBC_SHA256_5:
+       case OP_PCL_TLS12_AES_256_CBC_SHA256_2:
+       case OP_PCL_TLS12_AES_256_CBC_SHA256_3:
+       case OP_PCL_TLS12_AES_256_CBC_SHA256_4:
+       case OP_PCL_TLS12_AES_256_CBC_SHA256_5:
+       case OP_PCL_TLS12_AES_128_CBC_SHA256_6:
+       case OP_PCL_TLS12_AES_256_CBC_SHA256_6:
+       case OP_PCL_SSL30_3DES_EDE_CBC_SHA_2:
+       case OP_PCL_SSL30_AES_128_CBC_SHA_7:
+       case OP_PCL_SSL30_AES_256_CBC_SHA_7:
+       case OP_PCL_SSL30_3DES_EDE_CBC_SHA_3:
+       case OP_PCL_SSL30_AES_128_CBC_SHA_8:
+       case OP_PCL_SSL30_AES_256_CBC_SHA_8:
+       case OP_PCL_SSL30_3DES_EDE_CBC_SHA_4:
+       case OP_PCL_SSL30_AES_128_CBC_SHA_9:
+       case OP_PCL_SSL30_AES_256_CBC_SHA_9:
+       case OP_PCL_SSL30_AES_128_GCM_SHA256_1:
+       case OP_PCL_SSL30_AES_256_GCM_SHA384_1:
+       case OP_PCL_SSL30_AES_128_GCM_SHA256_2:
+       case OP_PCL_SSL30_AES_256_GCM_SHA384_2:
+       case OP_PCL_SSL30_AES_128_GCM_SHA256_3:
+       case OP_PCL_SSL30_AES_256_GCM_SHA384_3:
+       case OP_PCL_SSL30_AES_128_GCM_SHA256_4:
+       case OP_PCL_SSL30_AES_256_GCM_SHA384_4:
+       case OP_PCL_SSL30_AES_128_GCM_SHA256_5:
+       case OP_PCL_SSL30_AES_256_GCM_SHA384_5:
+       case OP_PCL_SSL30_AES_128_GCM_SHA256_6:
+       case OP_PCL_TLS_DH_ANON_AES_256_GCM_SHA384:
+       case OP_PCL_TLS_PSK_AES_128_GCM_SHA256:
+       case OP_PCL_TLS_PSK_AES_256_GCM_SHA384:
+       case OP_PCL_TLS_DHE_PSK_AES_128_GCM_SHA256:
+       case OP_PCL_TLS_DHE_PSK_AES_256_GCM_SHA384:
+       case OP_PCL_TLS_RSA_PSK_AES_128_GCM_SHA256:
+       case OP_PCL_TLS_RSA_PSK_AES_256_GCM_SHA384:
+       case OP_PCL_TLS_PSK_AES_128_CBC_SHA256:
+       case OP_PCL_TLS_PSK_AES_256_CBC_SHA384:
+       case OP_PCL_TLS_DHE_PSK_AES_128_CBC_SHA256:
+       case OP_PCL_TLS_DHE_PSK_AES_256_CBC_SHA384:
+       case OP_PCL_TLS_RSA_PSK_AES_128_CBC_SHA256:
+       case OP_PCL_TLS_RSA_PSK_AES_256_CBC_SHA384:
+       case OP_PCL_SSL30_3DES_EDE_CBC_SHA_11:
+       case OP_PCL_SSL30_AES_128_CBC_SHA_10:
+       case OP_PCL_SSL30_AES_256_CBC_SHA_10:
+       case OP_PCL_SSL30_3DES_EDE_CBC_SHA_12:
+       case OP_PCL_SSL30_AES_128_CBC_SHA_11:
+       case OP_PCL_SSL30_AES_256_CBC_SHA_11:
+       case OP_PCL_SSL30_AES_128_CBC_SHA_12:
+       case OP_PCL_SSL30_3DES_EDE_CBC_SHA_13:
+       case OP_PCL_SSL30_AES_256_CBC_SHA_12:
+       case OP_PCL_SSL30_3DES_EDE_CBC_SHA_14:
+       case OP_PCL_SSL30_AES_128_CBC_SHA_13:
+       case OP_PCL_SSL30_AES_256_CBC_SHA_13:
+       case OP_PCL_SSL30_3DES_EDE_CBC_SHA_15:
+       case OP_PCL_SSL30_AES_128_CBC_SHA_14:
+       case OP_PCL_SSL30_AES_256_CBC_SHA_14:
+       case OP_PCL_SSL30_3DES_EDE_CBC_SHA_16:
+       case OP_PCL_SSL30_3DES_EDE_CBC_SHA_17:
+       case OP_PCL_SSL30_3DES_EDE_CBC_SHA_18:
+       case OP_PCL_SSL30_AES_128_CBC_SHA_15:
+       case OP_PCL_SSL30_AES_128_CBC_SHA_16:
+       case OP_PCL_SSL30_AES_128_CBC_SHA_17:
+       case OP_PCL_SSL30_AES_256_CBC_SHA_15:
+       case OP_PCL_SSL30_AES_256_CBC_SHA_16:
+       case OP_PCL_SSL30_AES_256_CBC_SHA_17:
+       case OP_PCL_TLS_ECDHE_ECDSA_AES_128_CBC_SHA256:
+       case OP_PCL_TLS_ECDHE_ECDSA_AES_256_CBC_SHA384:
+       case OP_PCL_TLS_ECDH_ECDSA_AES_128_CBC_SHA256:
+       case OP_PCL_TLS_ECDH_ECDSA_AES_256_CBC_SHA384:
+       case OP_PCL_TLS_ECDHE_RSA_AES_128_CBC_SHA256:
+       case OP_PCL_TLS_ECDHE_RSA_AES_256_CBC_SHA384:
+       case OP_PCL_TLS_ECDH_RSA_AES_128_CBC_SHA256:
+       case OP_PCL_TLS_ECDH_RSA_AES_256_CBC_SHA384:
+       case OP_PCL_TLS_ECDHE_ECDSA_AES_128_GCM_SHA256:
+       case OP_PCL_TLS_ECDHE_ECDSA_AES_256_GCM_SHA384:
+       case OP_PCL_TLS_ECDH_ECDSA_AES_128_GCM_SHA256:
+       case OP_PCL_TLS_ECDH_ECDSA_AES_256_GCM_SHA384:
+       case OP_PCL_TLS_ECDHE_RSA_AES_128_GCM_SHA256:
+       case OP_PCL_TLS_ECDHE_RSA_AES_256_GCM_SHA384:
+       case OP_PCL_TLS_ECDH_RSA_AES_128_GCM_SHA256:
+       case OP_PCL_TLS_ECDH_RSA_AES_256_GCM_SHA384:
+       case OP_PCL_TLS_ECDHE_PSK_3DES_EDE_CBC_SHA:
+       case OP_PCL_TLS_ECDHE_PSK_AES_128_CBC_SHA:
+       case OP_PCL_TLS_ECDHE_PSK_AES_256_CBC_SHA:
+       case OP_PCL_TLS_ECDHE_PSK_AES_128_CBC_SHA256:
+       case OP_PCL_TLS_ECDHE_PSK_AES_256_CBC_SHA384:
+       case OP_PCL_TLS12_3DES_EDE_CBC_MD5:
+       case OP_PCL_TLS12_3DES_EDE_CBC_SHA160:
+       case OP_PCL_TLS12_3DES_EDE_CBC_SHA224:
+       case OP_PCL_TLS12_3DES_EDE_CBC_SHA256:
+       case OP_PCL_TLS12_3DES_EDE_CBC_SHA384:
+       case OP_PCL_TLS12_3DES_EDE_CBC_SHA512:
+       case OP_PCL_TLS12_AES_128_CBC_SHA160:
+       case OP_PCL_TLS12_AES_128_CBC_SHA224:
+       case OP_PCL_TLS12_AES_128_CBC_SHA256:
+       case OP_PCL_TLS12_AES_128_CBC_SHA384:
+       case OP_PCL_TLS12_AES_128_CBC_SHA512:
+       case OP_PCL_TLS12_AES_192_CBC_SHA160:
+       case OP_PCL_TLS12_AES_192_CBC_SHA224:
+       case OP_PCL_TLS12_AES_192_CBC_SHA256:
+       case OP_PCL_TLS12_AES_192_CBC_SHA512:
+       case OP_PCL_TLS12_AES_256_CBC_SHA160:
+       case OP_PCL_TLS12_AES_256_CBC_SHA224:
+       case OP_PCL_TLS12_AES_256_CBC_SHA256:
+       case OP_PCL_TLS12_AES_256_CBC_SHA384:
+       case OP_PCL_TLS12_AES_256_CBC_SHA512:
+       case OP_PCL_TLS_PVT_AES_192_CBC_SHA160:
+       case OP_PCL_TLS_PVT_AES_192_CBC_SHA384:
+       case OP_PCL_TLS_PVT_AES_192_CBC_SHA224:
+       case OP_PCL_TLS_PVT_AES_192_CBC_SHA512:
+       case OP_PCL_TLS_PVT_AES_192_CBC_SHA256:
+       case OP_PCL_TLS_PVT_MASTER_SECRET_PRF_FE:
+       case OP_PCL_TLS_PVT_MASTER_SECRET_PRF_FF:
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_ike_proto(uint16_t protoinfo)
+{
+       switch (protoinfo) {
+       case OP_PCL_IKE_HMAC_MD5:
+       case OP_PCL_IKE_HMAC_SHA1:
+       case OP_PCL_IKE_HMAC_AES128_CBC:
+       case OP_PCL_IKE_HMAC_SHA256:
+       case OP_PCL_IKE_HMAC_SHA384:
+       case OP_PCL_IKE_HMAC_SHA512:
+       case OP_PCL_IKE_HMAC_AES128_CMAC:
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_ipsec_proto(uint16_t protoinfo)
+{
+       uint16_t proto_cls1 = protoinfo & OP_PCL_IPSEC_CIPHER_MASK;
+       uint16_t proto_cls2 = protoinfo & OP_PCL_IPSEC_AUTH_MASK;
+
+       switch (proto_cls1) {
+       case OP_PCL_IPSEC_AES_NULL_WITH_GMAC:
+               if (rta_sec_era < RTA_SEC_ERA_2)
+                       return -EINVAL;
+               /* no break */
+       case OP_PCL_IPSEC_AES_CCM8:
+       case OP_PCL_IPSEC_AES_CCM12:
+       case OP_PCL_IPSEC_AES_CCM16:
+       case OP_PCL_IPSEC_AES_GCM8:
+       case OP_PCL_IPSEC_AES_GCM12:
+       case OP_PCL_IPSEC_AES_GCM16:
+               /* CCM, GCM, GMAC require PROTINFO[7:0] = 0 */
+               if (proto_cls2 == OP_PCL_IPSEC_HMAC_NULL)
+                       return 0;
+               return -EINVAL;
+       case OP_PCL_IPSEC_NULL:
+               if (rta_sec_era < RTA_SEC_ERA_2)
+                       return -EINVAL;
+               /* no break */
+       case OP_PCL_IPSEC_DES_IV64:
+       case OP_PCL_IPSEC_DES:
+       case OP_PCL_IPSEC_3DES:
+       case OP_PCL_IPSEC_AES_CBC:
+       case OP_PCL_IPSEC_AES_CTR:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (proto_cls2) {
+       case OP_PCL_IPSEC_HMAC_NULL:
+       case OP_PCL_IPSEC_HMAC_MD5_96:
+       case OP_PCL_IPSEC_HMAC_SHA1_96:
+       case OP_PCL_IPSEC_AES_XCBC_MAC_96:
+       case OP_PCL_IPSEC_HMAC_MD5_128:
+       case OP_PCL_IPSEC_HMAC_SHA1_160:
+       case OP_PCL_IPSEC_AES_CMAC_96:
+       case OP_PCL_IPSEC_HMAC_SHA2_256_128:
+       case OP_PCL_IPSEC_HMAC_SHA2_384_192:
+       case OP_PCL_IPSEC_HMAC_SHA2_512_256:
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_srtp_proto(uint16_t protoinfo)
+{
+       uint16_t proto_cls1 = protoinfo & OP_PCL_SRTP_CIPHER_MASK;
+       uint16_t proto_cls2 = protoinfo & OP_PCL_SRTP_AUTH_MASK;
+
+       switch (proto_cls1) {
+       case OP_PCL_SRTP_AES_CTR:
+               switch (proto_cls2) {
+               case OP_PCL_SRTP_HMAC_SHA1_160:
+                       return 0;
+               }
+               /* no break */
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_macsec_proto(uint16_t protoinfo)
+{
+       switch (protoinfo) {
+       case OP_PCL_MACSEC:
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_wifi_proto(uint16_t protoinfo)
+{
+       switch (protoinfo) {
+       case OP_PCL_WIFI:
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_wimax_proto(uint16_t protoinfo)
+{
+       switch (protoinfo) {
+       case OP_PCL_WIMAX_OFDM:
+       case OP_PCL_WIMAX_OFDMA:
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+/* Allowed blob proto flags for each SEC Era */
+static const uint32_t proto_blob_flags[] = {
+       OP_PCL_BLOB_FORMAT_MASK | OP_PCL_BLOB_BLACK,
+       OP_PCL_BLOB_FORMAT_MASK | OP_PCL_BLOB_BLACK | OP_PCL_BLOB_TKEK |
+               OP_PCL_BLOB_EKT | OP_PCL_BLOB_REG_MASK,
+       OP_PCL_BLOB_FORMAT_MASK | OP_PCL_BLOB_BLACK | OP_PCL_BLOB_TKEK |
+               OP_PCL_BLOB_EKT | OP_PCL_BLOB_REG_MASK,
+       OP_PCL_BLOB_FORMAT_MASK | OP_PCL_BLOB_BLACK | OP_PCL_BLOB_TKEK |
+               OP_PCL_BLOB_EKT | OP_PCL_BLOB_REG_MASK | OP_PCL_BLOB_SEC_MEM,
+       OP_PCL_BLOB_FORMAT_MASK | OP_PCL_BLOB_BLACK | OP_PCL_BLOB_TKEK |
+               OP_PCL_BLOB_EKT | OP_PCL_BLOB_REG_MASK | OP_PCL_BLOB_SEC_MEM
+};
+
+static inline int
+__rta_blob_proto(uint16_t protoinfo)
+{
+       if (protoinfo & ~proto_blob_flags[rta_sec_era])
+               return -EINVAL;
+
+       switch (protoinfo & OP_PCL_BLOB_FORMAT_MASK) {
+       case OP_PCL_BLOB_FORMAT_NORMAL:
+       case OP_PCL_BLOB_FORMAT_MASTER_VER:
+       case OP_PCL_BLOB_FORMAT_TEST:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (protoinfo & OP_PCL_BLOB_REG_MASK) {
+       case OP_PCL_BLOB_AFHA_SBOX:
+               if (rta_sec_era < RTA_SEC_ERA_3)
+                       return -EINVAL;
+               /* no break */
+       case OP_PCL_BLOB_REG_MEMORY:
+       case OP_PCL_BLOB_REG_KEY1:
+       case OP_PCL_BLOB_REG_KEY2:
+       case OP_PCL_BLOB_REG_SPLIT:
+       case OP_PCL_BLOB_REG_PKE:
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_dlc_proto(uint16_t protoinfo)
+{
+       if ((rta_sec_era < RTA_SEC_ERA_2) &&
+           (protoinfo & (OP_PCL_PKPROT_DSA_MSG | OP_PCL_PKPROT_HASH_MASK |
+            OP_PCL_PKPROT_EKT_Z | OP_PCL_PKPROT_DECRYPT_Z |
+            OP_PCL_PKPROT_DECRYPT_PRI)))
+               return -EINVAL;
+
+       switch (protoinfo & OP_PCL_PKPROT_HASH_MASK) {
+       case OP_PCL_PKPROT_HASH_MD5:
+       case OP_PCL_PKPROT_HASH_SHA1:
+       case OP_PCL_PKPROT_HASH_SHA224:
+       case OP_PCL_PKPROT_HASH_SHA256:
+       case OP_PCL_PKPROT_HASH_SHA384:
+       case OP_PCL_PKPROT_HASH_SHA512:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static inline int
+__rta_rsa_enc_proto(uint16_t protoinfo)
+{
+       switch (protoinfo & OP_PCL_RSAPROT_OP_MASK) {
+       case OP_PCL_RSAPROT_OP_ENC_F_IN:
+               if ((protoinfo & OP_PCL_RSAPROT_FFF_MASK) !=
+                   OP_PCL_RSAPROT_FFF_RED)
+                       return -EINVAL;
+               break;
+       case OP_PCL_RSAPROT_OP_ENC_F_OUT:
+               switch (protoinfo & OP_PCL_RSAPROT_FFF_MASK) {
+               case OP_PCL_RSAPROT_FFF_RED:
+               case OP_PCL_RSAPROT_FFF_ENC:
+               case OP_PCL_RSAPROT_FFF_EKT:
+               case OP_PCL_RSAPROT_FFF_TK_ENC:
+               case OP_PCL_RSAPROT_FFF_TK_EKT:
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static inline int
+__rta_rsa_dec_proto(uint16_t protoinfo)
+{
+       switch (protoinfo & OP_PCL_RSAPROT_OP_MASK) {
+       case OP_PCL_RSAPROT_OP_DEC_ND:
+       case OP_PCL_RSAPROT_OP_DEC_PQD:
+       case OP_PCL_RSAPROT_OP_DEC_PQDPDQC:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (protoinfo & OP_PCL_RSAPROT_PPP_MASK) {
+       case OP_PCL_RSAPROT_PPP_RED:
+       case OP_PCL_RSAPROT_PPP_ENC:
+       case OP_PCL_RSAPROT_PPP_EKT:
+       case OP_PCL_RSAPROT_PPP_TK_ENC:
+       case OP_PCL_RSAPROT_PPP_TK_EKT:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (protoinfo & OP_PCL_RSAPROT_FMT_PKCSV15)
+               switch (protoinfo & OP_PCL_RSAPROT_FFF_MASK) {
+               case OP_PCL_RSAPROT_FFF_RED:
+               case OP_PCL_RSAPROT_FFF_ENC:
+               case OP_PCL_RSAPROT_FFF_EKT:
+               case OP_PCL_RSAPROT_FFF_TK_ENC:
+               case OP_PCL_RSAPROT_FFF_TK_EKT:
+                       break;
+               default:
+                       return -EINVAL;
+               }
+
+       return 0;
+}
+
+/*
+ * DKP Protocol - Restrictions on key (SRC,DST) combinations
+ * For e.g. key_in_out[0][0] = 1 means (SRC=IMM,DST=IMM) combination is allowed
+ */
+static const uint8_t key_in_out[4][4] = { {1, 0, 0, 0},
+                                         {1, 1, 1, 1},
+                                         {1, 0, 1, 0},
+                                         {1, 0, 0, 1} };
+
+static inline int
+__rta_dkp_proto(uint16_t protoinfo)
+{
+       int key_src = (protoinfo & OP_PCL_DKP_SRC_MASK) >> OP_PCL_DKP_SRC_SHIFT;
+       int key_dst = (protoinfo & OP_PCL_DKP_DST_MASK) >> OP_PCL_DKP_DST_SHIFT;
+
+       if (!key_in_out[key_src][key_dst]) {
+               pr_err("PROTO_DESC: Invalid DKP key (SRC,DST)\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+
+static inline int
+__rta_3g_dcrc_proto(uint16_t protoinfo)
+{
+       if (rta_sec_era == RTA_SEC_ERA_7)
+               return -EINVAL;
+
+       switch (protoinfo) {
+       case OP_PCL_3G_DCRC_CRC7:
+       case OP_PCL_3G_DCRC_CRC11:
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_3g_rlc_proto(uint16_t protoinfo)
+{
+       if (rta_sec_era == RTA_SEC_ERA_7)
+               return -EINVAL;
+
+       switch (protoinfo) {
+       case OP_PCL_3G_RLC_NULL:
+       case OP_PCL_3G_RLC_KASUMI:
+       case OP_PCL_3G_RLC_SNOW:
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_lte_pdcp_proto(uint16_t protoinfo)
+{
+       if (rta_sec_era == RTA_SEC_ERA_7)
+               return -EINVAL;
+
+       switch (protoinfo) {
+       case OP_PCL_LTE_ZUC:
+               if (rta_sec_era < RTA_SEC_ERA_5)
+                       break;
+       case OP_PCL_LTE_NULL:
+       case OP_PCL_LTE_SNOW:
+       case OP_PCL_LTE_AES:
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static inline int
+__rta_lte_pdcp_mixed_proto(uint16_t protoinfo)
+{
+       switch (protoinfo & OP_PCL_LTE_MIXED_AUTH_MASK) {
+       case OP_PCL_LTE_MIXED_AUTH_NULL:
+       case OP_PCL_LTE_MIXED_AUTH_SNOW:
+       case OP_PCL_LTE_MIXED_AUTH_AES:
+       case OP_PCL_LTE_MIXED_AUTH_ZUC:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (protoinfo & OP_PCL_LTE_MIXED_ENC_MASK) {
+       case OP_PCL_LTE_MIXED_ENC_NULL:
+       case OP_PCL_LTE_MIXED_ENC_SNOW:
+       case OP_PCL_LTE_MIXED_ENC_AES:
+       case OP_PCL_LTE_MIXED_ENC_ZUC:
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+struct proto_map {
+       uint32_t optype;
+       uint32_t protid;
+       int (*protoinfo_func)(uint16_t);
+};
+
+static const struct proto_map proto_table[] = {
+/*1*/  {OP_TYPE_UNI_PROTOCOL,   OP_PCLID_SSL30_PRF,     __rta_ssl_proto},
+       {OP_TYPE_UNI_PROTOCOL,   OP_PCLID_TLS10_PRF,     __rta_ssl_proto},
+       {OP_TYPE_UNI_PROTOCOL,   OP_PCLID_TLS11_PRF,     __rta_ssl_proto},
+       {OP_TYPE_UNI_PROTOCOL,   OP_PCLID_TLS12_PRF,     __rta_ssl_proto},
+       {OP_TYPE_UNI_PROTOCOL,   OP_PCLID_DTLS10_PRF,    __rta_ssl_proto},
+       {OP_TYPE_UNI_PROTOCOL,   OP_PCLID_IKEV1_PRF,     __rta_ike_proto},
+       {OP_TYPE_UNI_PROTOCOL,   OP_PCLID_IKEV2_PRF,     __rta_ike_proto},
+       {OP_TYPE_UNI_PROTOCOL,   OP_PCLID_PUBLICKEYPAIR, __rta_dlc_proto},
+       {OP_TYPE_UNI_PROTOCOL,   OP_PCLID_DSASIGN,       __rta_dlc_proto},
+       {OP_TYPE_UNI_PROTOCOL,   OP_PCLID_DSAVERIFY,     __rta_dlc_proto},
+       {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_IPSEC,         __rta_ipsec_proto},
+       {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_SRTP,          __rta_srtp_proto},
+       {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_SSL30,         __rta_ssl_proto},
+       {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_TLS10,         __rta_ssl_proto},
+       {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_TLS11,         __rta_ssl_proto},
+       {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_TLS12,         __rta_ssl_proto},
+       {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_DTLS10,        __rta_ssl_proto},
+       {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_MACSEC,        __rta_macsec_proto},
+       {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_WIFI,          __rta_wifi_proto},
+       {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_WIMAX,         __rta_wimax_proto},
+/*21*/ {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_BLOB,          __rta_blob_proto},
+       {OP_TYPE_UNI_PROTOCOL,   OP_PCLID_DIFFIEHELLMAN, __rta_dlc_proto},
+       {OP_TYPE_UNI_PROTOCOL,   OP_PCLID_RSAENCRYPT,    __rta_rsa_enc_proto},
+       {OP_TYPE_UNI_PROTOCOL,   OP_PCLID_RSADECRYPT,    __rta_rsa_dec_proto},
+       {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_3G_DCRC,       __rta_3g_dcrc_proto},
+       {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_3G_RLC_PDU,    __rta_3g_rlc_proto},
+       {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_3G_RLC_SDU,    __rta_3g_rlc_proto},
+       {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_LTE_PDCP_USER, __rta_lte_pdcp_proto},
+/*29*/ {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_LTE_PDCP_CTRL, __rta_lte_pdcp_proto},
+       {OP_TYPE_UNI_PROTOCOL,   OP_PCLID_DKP_MD5,       __rta_dkp_proto},
+       {OP_TYPE_UNI_PROTOCOL,   OP_PCLID_DKP_SHA1,      __rta_dkp_proto},
+       {OP_TYPE_UNI_PROTOCOL,   OP_PCLID_DKP_SHA224,    __rta_dkp_proto},
+       {OP_TYPE_UNI_PROTOCOL,   OP_PCLID_DKP_SHA256,    __rta_dkp_proto},
+       {OP_TYPE_UNI_PROTOCOL,   OP_PCLID_DKP_SHA384,    __rta_dkp_proto},
+/*35*/ {OP_TYPE_UNI_PROTOCOL,   OP_PCLID_DKP_SHA512,    __rta_dkp_proto},
+       {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_PUBLICKEYPAIR, __rta_dlc_proto},
+/*37*/ {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_DSASIGN,       __rta_dlc_proto},
+/*38*/ {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_LTE_PDCP_CTRL_MIXED,
+        __rta_lte_pdcp_mixed_proto},
+       {OP_TYPE_DECAP_PROTOCOL, OP_PCLID_IPSEC_NEW,     __rta_ipsec_proto},
+};
+
+/*
+ * Allowed OPERATION protocols for each SEC Era.
+ * Values represent the number of entries from proto_table[] that are supported.
+ */
+static const unsigned int proto_table_sz[] = {21, 29, 29, 29, 29, 35, 37, 39};
+
+static inline int
+rta_proto_operation(struct program *program, uint32_t optype,
+                                     uint32_t protid, uint16_t protoinfo)
+{
+       uint32_t opcode = CMD_OPERATION;
+       unsigned int i, found = 0;
+       uint32_t optype_tmp = optype;
+       unsigned int start_pc = program->current_pc;
+       int ret = -EINVAL;
+
+       for (i = 0; i < proto_table_sz[rta_sec_era]; i++) {
+               /* clear last bit in optype to match also decap proto */
+               optype_tmp &= (uint32_t)~(1 << OP_TYPE_SHIFT);
+               if (optype_tmp == proto_table[i].optype) {
+                       if (proto_table[i].protid == protid) {
+                               /* nothing else to verify */
+                               if (proto_table[i].protoinfo_func == NULL) {
+                                       found = 1;
+                                       break;
+                               }
+                               /* check protoinfo */
+                               ret = (*proto_table[i].protoinfo_func)
+                                               (protoinfo);
+                               if (ret < 0) {
+                                       pr_err("PROTO_DESC: Bad PROTO Type. SEC Program Line: %d\n",
+                                              program->current_pc);
+                                       goto err;
+                               }
+                               found = 1;
+                               break;
+                       }
+               }
+       }
+       if (!found) {
+               pr_err("PROTO_DESC: Operation Type Mismatch. SEC Program Line: %d\n",
+                      program->current_pc);
+               goto err;
+       }
+
+       __rta_out32(program, opcode | optype | protid | protoinfo);
+       program->current_instruction++;
+       return (int)start_pc;
+
+ err:
+       program->first_error_pc = start_pc;
+       program->current_instruction++;
+       return ret;
+}
+
+static inline int
+rta_dkp_proto(struct program *program, uint32_t protid,
+                               uint16_t key_src, uint16_t key_dst,
+                               uint16_t keylen, uint64_t key,
+                               enum rta_data_type key_type)
+{
+       unsigned int start_pc = program->current_pc;
+       unsigned int in_words = 0, out_words = 0;
+       int ret;
+
+       key_src &= OP_PCL_DKP_SRC_MASK;
+       key_dst &= OP_PCL_DKP_DST_MASK;
+       keylen &= OP_PCL_DKP_KEY_MASK;
+
+       ret = rta_proto_operation(program, OP_TYPE_UNI_PROTOCOL, protid,
+                                 key_src | key_dst | keylen);
+       if (ret < 0)
+               return ret;
+
+       if ((key_src == OP_PCL_DKP_SRC_PTR) ||
+           (key_src == OP_PCL_DKP_SRC_SGF)) {
+               __rta_out64(program, program->ps, key);
+               in_words = program->ps ? 2 : 1;
+       } else if (key_src == OP_PCL_DKP_SRC_IMM) {
+               __rta_inline_data(program, key, inline_flags(key_type), keylen);
+               in_words = (unsigned int)((keylen + 3) / 4);
+       }
+
+       if ((key_dst == OP_PCL_DKP_DST_PTR) ||
+           (key_dst == OP_PCL_DKP_DST_SGF)) {
+               out_words = in_words;
+       } else  if (key_dst == OP_PCL_DKP_DST_IMM) {
+               out_words = split_key_len(protid) / 4;
+       }
+
+       if (out_words < in_words) {
+               pr_err("PROTO_DESC: DKP doesn't currently support a smaller descriptor\n");
+               program->first_error_pc = start_pc;
+               return -EINVAL;
+       }
+
+       /* If needed, reserve space in resulting descriptor for derived key */
+       program->current_pc += (out_words - in_words);
+
+       return (int)start_pc;
+}
+
+#endif /* __RTA_PROTOCOL_CMD_H__ */