]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00215492-3: Detect HW features during alg registration
authorSteve Cornelius <steve.cornelius@freescale.com>
Sat, 30 Jun 2012 23:11:00 +0000 (16:11 -0700)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:34:55 +0000 (08:34 +0200)
i.MX6 instantiates a CAAM with a low-power MDHA block, which does not
compute digests larger than 256 bits. Since the driver installs handlers
for hashes longer than 256 bits in several places, added the ability to
read and interpret the CHA version and instantiations registers, and then
only register handlers that it can support.

Signed-off-by: Steve Cornelius <steve.cornelius@freescale.com>
Signed-off-by: Terry Lv <r65388@freescale.com>
drivers/crypto/caam/caamalg.c
drivers/crypto/caam/caamhash.c
drivers/crypto/caam/caamrng.c
drivers/crypto/caam/ctrl.c
drivers/crypto/caam/regs.h

index d26e25cddbb16a576652fb32e7e3c35675094f84..1d3d89aba09e54ff827a14eb9278f34925377f9f 100644 (file)
@@ -2212,7 +2212,9 @@ int caam_algapi_startup(struct platform_device *pdev)
 {
        struct device *ctrldev, **jrdev;
        struct caam_drv_private *priv;
-       int i = 0, err = 0;
+       int i = 0, err = 0, md_limit = 0;
+       int des_inst, aes_inst, md_inst;
+       u64 cha_inst;
 
        ctrldev = &pdev->dev;
        priv = dev_get_drvdata(ctrldev);
@@ -2238,11 +2240,47 @@ int caam_algapi_startup(struct platform_device *pdev)
        priv->algapi_jr = jrdev;
        atomic_set(&priv->tfm_count, -1);
 
-       /* register crypto algorithms the device supports */
+       /*
+        * register crypto algorithms the device supports
+        * first, detect presence of DES, AES, and MD blocks. If MD present,
+        * determine limit of supported digest size
+        */
+       cha_inst = rd_reg64(&priv->ctrl->perfmon.cha_num);
+       des_inst = (cha_inst & CHA_ID_DES_MASK) >> CHA_ID_DES_SHIFT;
+       aes_inst = (cha_inst & CHA_ID_AES_MASK) >> CHA_ID_AES_SHIFT;
+       md_inst = (cha_inst & CHA_ID_MD_MASK) >> CHA_ID_MD_SHIFT;
+       if (md_inst) {
+               md_limit = SHA512_DIGEST_SIZE;
+               if ((rd_reg64(&priv->ctrl->perfmon.cha_id) & CHA_ID_MD_MASK)
+                    == CHA_ID_MD_LP256) /* LP256 limits digest size */
+                       md_limit = SHA256_DIGEST_SIZE;
+       }
+
        for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
-               /* TODO: check if h/w supports alg */
                struct caam_crypto_alg *t_alg;
 
+               /*
+                * All registrable algs in this module require a blockcipher
+                * All aead algs require message digests, so check them for
+                * instantiation and size.
+                */
+               if (driver_algs[i].type == CRYPTO_ALG_TYPE_AEAD) {
+                       /* If no MD instantiated, or MD too small, skip */
+                       if ((!md_inst) ||
+                           (driver_algs[i].template_aead.maxauthsize >
+                            md_limit))
+                               continue;
+               }
+               /* If DES alg, and CHA not instantiated, skip */
+               if ((driver_algs[i].class1_alg_type & OP_ALG_ALGSEL_3DES) ||
+                   (driver_algs[i].class1_alg_type & OP_ALG_ALGSEL_DES))
+                       if (!des_inst)
+                               continue;
+               /* If AES alg, and CHA not instantiated, skip */
+               if (driver_algs[i].class1_alg_type & OP_ALG_ALGSEL_AES)
+                       if (!aes_inst)
+                               continue;
+
                t_alg = caam_alg_alloc(ctrldev, &driver_algs[i]);
                if (IS_ERR(t_alg)) {
                        err = PTR_ERR(t_alg);
index d36582b0c0721d4e020f8259165520f35ecfded6..7d1fd28046cbaf5aef078fc0d656b1a65c860b8a 100644 (file)
@@ -1821,7 +1821,8 @@ int caam_algapi_hash_startup(struct platform_device *pdev)
 {
        struct device *ctrldev;
        struct caam_drv_private *priv;
-       int i = 0, err = 0;
+       int i = 0, err = 0, md_limit = 0, md_inst;
+       u64 cha_inst;
 
        ctrldev = &pdev->dev;
        priv = dev_get_drvdata(ctrldev);
@@ -1830,11 +1831,25 @@ int caam_algapi_hash_startup(struct platform_device *pdev)
 
        atomic_set(&priv->tfm_count, -1);
 
-       /* register crypto algorithms the device supports */
+       /* register algorithms the device supports */
+       cha_inst = rd_reg64(&priv->ctrl->perfmon.cha_num);
+       md_inst = (cha_inst & CHA_ID_MD_MASK) >> CHA_ID_MD_SHIFT;
+       if (md_inst) {
+               md_limit = SHA512_DIGEST_SIZE;
+               if ((rd_reg64(&priv->ctrl->perfmon.cha_id) & CHA_ID_MD_MASK)
+                    == CHA_ID_MD_LP256) /* LP256 limits digest size */
+                       md_limit = SHA256_DIGEST_SIZE;
+       }
+
        for (i = 0; i < ARRAY_SIZE(driver_hash); i++) {
-               /* TODO: check if h/w supports alg */
                struct caam_hash_alg *t_alg;
 
+               /* If no MD instantiated, or MD too small, skip */
+               if ((!md_inst) ||
+                   (driver_hash[i].template_ahash.halg.digestsize >
+                    md_limit))
+                       continue;
+
                /* register hmac version */
                t_alg = caam_hash_alloc(ctrldev, &driver_hash[i], true);
                if (IS_ERR(t_alg)) {
index 3778e0e493af31a0303113ea21575e331143cdca..f992c10b657b0d73728ce07e527c6523abb491fd 100644 (file)
@@ -327,6 +327,10 @@ int caam_rng_startup(struct platform_device *pdev)
        ctrldev = &pdev->dev;
        priv = dev_get_drvdata(ctrldev);
 
+       /* Check instantiated RNG before registration */
+       if (!(rd_reg64(&priv->ctrl->perfmon.cha_num) & CHA_ID_RNG_MASK))
+               return -ENODEV;
+
        caam_init_rng(&rng_ctx, priv->jrdev[0]);
 
 #ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST
index 1b4903313b807cc444990cfa515c55f6845a14f8..d7374aad06e8099ba46e0378872f80cdda37dd13 100644 (file)
@@ -359,8 +359,8 @@ static int caam_probe(struct platform_device *pdev)
         * RNG4 based SECs (v5+ | >= i.MX6) need special initialization prior
         * to executing any descriptors
         */
-       if ((rd_reg64(&topregs->ctrl.perfmon.cha_id) & CHA_VID_RNG_MASK)
-           == CHA_VID_RNG_4) {
+       if ((rd_reg64(&topregs->ctrl.perfmon.cha_id) & CHA_ID_RNG_MASK)
+           == CHA_ID_RNG_4) {
                kick_trng(pdev);
                ret = instantiate_rng(ctrlpriv->jrdev[0]);
                if (ret) {
index 868cf1902a2c49fb227dd7c67142c4d179bff1f8..fd8a2a251b8a6b9d8452c58f649f041c446e2b85 100644 (file)
@@ -113,61 +113,103 @@ struct jr_outentry {
 } __packed;
 
 /*
- * caam_perfmon - Performance Monitor/Secure Memory Status/
- *                CAAM Global Status/Component Version IDs
- *
- * Spans f00-fff wherever instantiated
+ * CHA version ID / instantiation bitfields
+ * Defined for use within cha_id in perfmon
+ * Note that the same shift/mask selectors can be used to pull out number
+ * of instantiated blocks within cha_num in perfmon, the locations are
+ * the same.
  */
 
-/* CHA version IDs for cha_id register */
-#define CHA_VID_JR_SHIFT       60
-#define CHA_VID_JR_MASK                (0xfull << CHA_VID_JR_SHIFT)
-
-#define CHA_VID_DECO_SHIFT     56
-#define CHA_VID_DECO_MASK      (0xfull << CHA_VID_DECO_SHIFT)
+/* Job Ring */
+#define CHA_ID_JR_SHIFT        60
+#define CHA_ID_JR_MASK         (0xfull << CHA_ID_JR_SHIFT)
 
-#define CHA_VID_ZA_SHIFT       44
-#define CHA_VID_ZA_MASK                (0xfull << CHA_VID_ZA_SHIFT)
+/* DEscriptor COntroller */
+#define CHA_ID_DECO_SHIFT      56
+#define CHA_ID_DECO_MASK       (0xfull << CHA_ID_DECO_SHIFT)
+#define CHA_NUM_DECONUM_SHIFT  56 /* legacy definition */
+#define CHA_NUM_DECONUM_MASK   (0xfull << CHA_NUM_DECONUM_SHIFT)
 
-#define CHA_VID_ZE_SHIFT       40
-#define CHA_VID_ZE_MASK                (0xfull << CHA_VID_ZE_SHIFT)
+/* ZUC-Authentication */
+#define CHA_ID_ZA_SHIFT        44
+#define CHA_ID_ZA_MASK         (0xfull << CHA_ID_ZA_SHIFT)
 
-#define CHA_VID_SNW9_SHIFT     36
-#define CHA_VID_SNW9_MASK      (0xfull << CHA_VID_SNW9_SHIFT)
+/* ZUC-Encryption */
+#define CHA_ID_ZE_SHIFT        40
+#define CHA_ID_ZE_MASK         (0xfull << CHA_ID_ZE_SHIFT)
 
-#define CHA_VID_CRC_SHIFT      32
-#define CHA_VID_CRC_MASK       (0xfull << CHA_VID_CRC_SHIFT)
+/* SNOW f9 */
+#define CHA_ID_SNW9_SHIFT      36
+#define CHA_ID_SNW9_MASK       (0xfull << CHA_ID_SNW9_SHIFT)
 
-#define CHA_VID_PK_SHIFT       28
-#define CHA_VID_PK_MASK                (0xfull << CHA_VID_PK_SHIFT)
+/* CRC */
+#define CHA_ID_CRC_SHIFT       32
+#define CHA_ID_CRC_MASK                (0xfull << CHA_ID_CRC_SHIFT)
 
-#define CHA_VID_KAS_SHIFT      24
-#define CHA_VID_KAS_MASK       (0xfull << CHA_VID_KAS_SHIFT)
+/* Public Key */
+#define CHA_ID_PK_SHIFT        28
+#define CHA_ID_PK_MASK         (0xfull << CHA_ID_PK_SHIFT)
 
-#define CHA_VID_SNW8_SHIFT     20
-#define CHA_VID_SNW8_MASK      (0xfull << CHA_VID_SNW8_SHIFT)
+/* Kasumi */
+#define CHA_ID_KAS_SHIFT       24
+#define CHA_ID_KAS_MASK                (0xfull << CHA_ID_KAS_SHIFT)
 
-#define CHA_VID_RNG_SHIFT      16
-#define CHA_VID_RNG_MASK       (0xfull << CHA_VID_RNG_SHIFT)
-#define CHA_VID_RNG_A          (0x1ull << CHA_VID_RNG_SHIFT)
-#define CHA_VID_RNG_B          (0x2ull << CHA_VID_RNG_SHIFT)
-#define CHA_VID_RNG_4          (0x4ull << CHA_VID_RNG_SHIFT)
+/* SNOW f8 */
+#define CHA_ID_SNW8_SHIFT      20
+#define CHA_ID_SNW8_MASK       (0xfull << CHA_ID_SNW8_SHIFT)
 
-#define CHA_VID_MD_SHIFT       12
-#define CHA_VID_MD_MASK                (0xfull << CHA_VID_MD_SHIFT)
+/*
+ * Random Generator
+ * RNG4 = FIPS-verification-compliant, requires init kickstart for use
+ */
+#define CHA_ID_RNG_SHIFT       16
+#define CHA_ID_RNG_MASK                (0xfull << CHA_ID_RNG_SHIFT)
+#define CHA_ID_RNG_A           (0x1ull << CHA_ID_RNG_SHIFT)
+#define CHA_ID_RNG_B           (0x2ull << CHA_ID_RNG_SHIFT)
+#define CHA_ID_RNG_C           (0x3ull << CHA_ID_RNG_SHIFT)
+#define CHA_ID_RNG_4           (0x4ull << CHA_ID_RNG_SHIFT)
 
-#define CHA_VID_ARC4_SHIFT     8
-#define CHA_VID_ARC4_MASK      (0xfull << CHA_VID_ARC4_SHIFT)
+/*
+ * Message Digest
+ * LP256 = Low Power (MD5/SHA1/SHA224/SHA256 + HMAC)
+ * LP512 = Low Power (LP256 + SHA384/SHA512)
+ * HP    = High Power (LP512 + SMAC)
+ */
+#define CHA_ID_MD_SHIFT                12
+#define CHA_ID_MD_MASK         (0xfull << CHA_ID_MD_SHIFT)
+#define CHA_ID_MD_LP256                (0x0ull << CHA_ID_MD_SHIFT)
+#define CHA_ID_MD_LP512                (0x1ull << CHA_ID_MD_SHIFT)
+#define CHA_ID_MD_HP           (0x2ull << CHA_ID_MD_SHIFT)
+
+/* ARC4 Streamcipher */
+#define CHA_ID_ARC4_SHIFT      8
+#define CHA_ID_ARC4_MASK       (0xfull << CHA_ID_ARC4_SHIFT)
+#define CHA_ID_ARC4_LP         (0x0ull << CHA_ID_ARC4_SHIFT)
+#define CHA_ID_ARC4_HP         (0x1ull << CHA_ID_ARC4_SHIFT)
+
+/* DES Blockcipher Accelerator */
+#define CHA_ID_DES_SHIFT       4
+#define CHA_ID_DES_MASK                (0xfull << CHA_ID_DES_SHIFT)
 
-#define CHA_VID_DES_SHIFT      4
-#define CHA_VID_DES_MASK       (0xfull << CHA_VID_DES_SHIFT)
+/*
+ * AES Blockcipher + Combo Mode Accelerator
+ * LP = Low Power (includes ECB/CBC/CFB128/OFB/CTR/CCM/CMAC/XCBC-MAC)
+ * HP = High Power (LP + CBCXCBC/CTRXCBC/XTS/GCM)
+ * DIFFPWR = ORed in if differential-power-analysis resistance implemented
+ */
+#define CHA_ID_AES_SHIFT       0
+#define CHA_ID_AES_MASK                (0xfull << CHA_ID_AES_SHIFT)
+#define CHA_ID_AES_LP          (0x3ull << CHA_ID_AES_SHIFT)
+#define CHA_ID_AES_HP          (0x4ull << CHA_ID_AES_SHIFT)
+#define CHA_ID_AES_DIFFPWR     (0x1ull << CHA_ID_AES_SHIFT)
 
-#define CHA_VID_AES_SHIFT      0
-#define CHA_VID_AES_MASK       (0xfull << CHA_VID_AES_SHIFT)
 
-/* Number of DECOs for cha_num register*/
-#define CHA_NUM_DECONUM_SHIFT  56
-#define CHA_NUM_DECONUM_MASK   (0xfull << CHA_NUM_DECONUM_SHIFT)
+/*
+ * caam_perfmon - Performance Monitor/Secure Memory Status/
+ *                CAAM Global Status/Component Version IDs
+ *
+ * Spans f00-fff wherever instantiated
+ */
 
 struct caam_perfmon {
        /* Performance Monitor Registers                        f00-f9f */