crypto: inside-secure - Added support for CRC32
authorPascal van Leeuwen <pascalvanl@gmail.com>
Mon, 9 Sep 2019 11:10:29 +0000 (13:10 +0200)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 4 Oct 2019 15:04:30 +0000 (01:04 +1000)
This patch adds support for the CRC32 "hash" algorithm

Signed-off-by: Pascal van Leeuwen <pvanleeuwen@verimatrix.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/inside-secure/safexcel.c
drivers/crypto/inside-secure/safexcel.h
drivers/crypto/inside-secure/safexcel_hash.c

index 4ab1bde..44cd806 100644 (file)
@@ -1169,6 +1169,7 @@ static struct safexcel_alg_template *safexcel_algs[] = {
        &safexcel_alg_xts_aes,
        &safexcel_alg_gcm,
        &safexcel_alg_ccm,
+       &safexcel_alg_crc32,
 };
 
 static int safexcel_register_algorithms(struct safexcel_crypto_priv *priv)
index 930cc48..6015576 100644 (file)
@@ -362,6 +362,7 @@ struct safexcel_context_record {
 #define CONTEXT_CONTROL_DIGEST_XCM             (0x2 << 21)
 #define CONTEXT_CONTROL_DIGEST_HMAC            (0x3 << 21)
 #define CONTEXT_CONTROL_CRYPTO_ALG_MD5         (0x0 << 23)
+#define CONTEXT_CONTROL_CRYPTO_ALG_CRC32       (0x0 << 23)
 #define CONTEXT_CONTROL_CRYPTO_ALG_SHA1                (0x2 << 23)
 #define CONTEXT_CONTROL_CRYPTO_ALG_SHA224      (0x4 << 23)
 #define CONTEXT_CONTROL_CRYPTO_ALG_SHA256      (0x3 << 23)
@@ -853,5 +854,6 @@ extern struct safexcel_alg_template safexcel_alg_authenc_hmac_sha512_ctr_aes;
 extern struct safexcel_alg_template safexcel_alg_xts_aes;
 extern struct safexcel_alg_template safexcel_alg_gcm;
 extern struct safexcel_alg_template safexcel_alg_ccm;
+extern struct safexcel_alg_template safexcel_alg_crc32;
 
 #endif
index 2effb6d..9d1e8cf 100644 (file)
@@ -82,23 +82,31 @@ static void safexcel_context_control(struct safexcel_ahash_ctx *ctx,
        struct safexcel_crypto_priv *priv = ctx->priv;
        u64 count = 0;
 
-       cdesc->control_data.control0 |= ctx->alg;
+       cdesc->control_data.control0 = ctx->alg;
 
        /*
         * Copy the input digest if needed, and setup the context
         * fields. Do this now as we need it to setup the first command
         * descriptor.
         */
-       if (!req->processed) {
+       if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM)) {
+               ctx->base.ctxr->data[0] = req->state[0];
+
+               cdesc->control_data.control0 |= req->digest |
+                       CONTEXT_CONTROL_TYPE_HASH_OUT  |
+                       CONTEXT_CONTROL_SIZE(4);
+
+               return;
+       } else if (!req->processed) {
                /* First - and possibly only - block of basic hash only */
                if (req->finish) {
-                       cdesc->control_data.control0 |=
+                       cdesc->control_data.control0 |= req->digest |
                                CONTEXT_CONTROL_TYPE_HASH_OUT |
                                CONTEXT_CONTROL_RESTART_HASH  |
                                /* ensure its not 0! */
                                CONTEXT_CONTROL_SIZE(1);
                } else {
-                       cdesc->control_data.control0 |=
+                       cdesc->control_data.control0 |= req->digest |
                                CONTEXT_CONTROL_TYPE_HASH_OUT  |
                                CONTEXT_CONTROL_RESTART_HASH   |
                                CONTEXT_CONTROL_NO_FINISH_HASH |
@@ -238,8 +246,13 @@ static int safexcel_handle_req_result(struct safexcel_crypto_priv *priv,
                        return 1;
                }
 
-               memcpy(areq->result, sreq->state,
-                      crypto_ahash_digestsize(ahash));
+               if (unlikely(sreq->digest == CONTEXT_CONTROL_DIGEST_XCM)) {
+                       /* Undo final XOR with 0xffffffff ...*/
+                       *(u32 *)areq->result = ~sreq->state[0];
+               } else {
+                       memcpy(areq->result, sreq->state,
+                              crypto_ahash_digestsize(ahash));
+               }
        }
 
        cache_len = safexcel_queued_len(sreq);
@@ -599,7 +612,7 @@ static int safexcel_ahash_enqueue(struct ahash_request *areq)
                     /* invalidate for HMAC continuation finish */
                     (req->finish && (req->processed != req->block_sz)) ||
                     /* invalidate for HMAC finish with odigest changed */
-                    (req->finish &&
+                    (req->finish && req->hmac &&
                      memcmp(ctx->base.ctxr->data + (req->state_sz>>2),
                             ctx->opad, req->state_sz))))
                        /*
@@ -693,6 +706,12 @@ static int safexcel_ahash_final(struct ahash_request *areq)
                               SHA512_DIGEST_SIZE);
 
                return 0;
+       } else if (unlikely(req->digest == CONTEXT_CONTROL_DIGEST_XCM &&
+                           ctx->alg == CONTEXT_CONTROL_CRYPTO_ALG_MD5 &&
+                           req->len == sizeof(u32) && !areq->nbytes)) {
+               /* Zero length CRC32 */
+               memcpy(areq->result, ctx->ipad, sizeof(u32));
+               return 0;
        } else if (unlikely(req->hmac &&
                            (req->len == req->block_sz) &&
                            !areq->nbytes)) {
@@ -1740,3 +1759,85 @@ struct safexcel_alg_template safexcel_alg_hmac_md5 = {
                },
        },
 };
+
+static int safexcel_crc32_cra_init(struct crypto_tfm *tfm)
+{
+       struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(tfm);
+       int ret = safexcel_ahash_cra_init(tfm);
+
+       /* Default 'key' is all zeroes */
+       memset(ctx->ipad, 0, sizeof(u32));
+       return ret;
+}
+
+static int safexcel_crc32_init(struct ahash_request *areq)
+{
+       struct safexcel_ahash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(areq));
+       struct safexcel_ahash_req *req = ahash_request_ctx(areq);
+
+       memset(req, 0, sizeof(*req));
+
+       /* Start from loaded key */
+       req->state[0]   = cpu_to_le32(~ctx->ipad[0]);
+       /* Set processed to non-zero to enable invalidation detection */
+       req->len        = sizeof(u32);
+       req->processed  = sizeof(u32);
+
+       ctx->alg = CONTEXT_CONTROL_CRYPTO_ALG_CRC32;
+       req->digest = CONTEXT_CONTROL_DIGEST_XCM;
+       req->state_sz = sizeof(u32);
+       req->block_sz = sizeof(u32);
+
+       return 0;
+}
+
+static int safexcel_crc32_setkey(struct crypto_ahash *tfm, const u8 *key,
+                                unsigned int keylen)
+{
+       struct safexcel_ahash_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
+
+       if (keylen != sizeof(u32)) {
+               crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+               return -EINVAL;
+       }
+
+       memcpy(ctx->ipad, key, sizeof(u32));
+       return 0;
+}
+
+static int safexcel_crc32_digest(struct ahash_request *areq)
+{
+       return safexcel_crc32_init(areq) ?: safexcel_ahash_finup(areq);
+}
+
+struct safexcel_alg_template safexcel_alg_crc32 = {
+       .type = SAFEXCEL_ALG_TYPE_AHASH,
+       .algo_mask = 0,
+       .alg.ahash = {
+               .init = safexcel_crc32_init,
+               .update = safexcel_ahash_update,
+               .final = safexcel_ahash_final,
+               .finup = safexcel_ahash_finup,
+               .digest = safexcel_crc32_digest,
+               .setkey = safexcel_crc32_setkey,
+               .export = safexcel_ahash_export,
+               .import = safexcel_ahash_import,
+               .halg = {
+                       .digestsize = sizeof(u32),
+                       .statesize = sizeof(struct safexcel_ahash_export_state),
+                       .base = {
+                               .cra_name = "crc32",
+                               .cra_driver_name = "safexcel-crc32",
+                               .cra_priority = SAFEXCEL_CRA_PRIORITY,
+                               .cra_flags = CRYPTO_ALG_OPTIONAL_KEY |
+                                            CRYPTO_ALG_ASYNC |
+                                            CRYPTO_ALG_KERN_DRIVER_ONLY,
+                               .cra_blocksize = 1,
+                               .cra_ctxsize = sizeof(struct safexcel_ahash_ctx),
+                               .cra_init = safexcel_crc32_cra_init,
+                               .cra_exit = safexcel_ahash_cra_exit,
+                               .cra_module = THIS_MODULE,
+                       },
+               },
+       },
+};