[openwrt/openwrt] ltq-deu: fix setkey errors and static shared temp for hmac algos

LEDE Commits lede-commits at lists.infradead.org
Wed Jan 5 17:10:27 PST 2022


hauke pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/85383b311212576e7afd9d01dec49f69ef6fb886

commit 85383b311212576e7afd9d01dec49f69ef6fb886
Author: Daniel Kestrel <kestrel1974 at t-online.de>
AuthorDate: Sun Jun 6 21:16:32 2021 +0200

    ltq-deu: fix setkey errors and static shared temp for hmac algos
    
    The hmac algorithms state, that keys larger than the key size should be
    hashed with the underlying hash algorithms and then those hashes are to
    be used as keys. This patch implements this. In order to avoid allocating
    a descriptor during setkey, a shash_desc pointer is added to the context.
    Another issue for multithreaded callers is the shared temp array.
    The temp array is static and as such would be shared among multithreaded
    callers, which obviously would neither work nor produce correct results.
    The temp array (4k size) is moved to the context and since the size of
    the context is limited, it can only be defined as pointer otherwise the
    initialisation of the hash algorithm fails.
    The allocations and freeing of both the temp and the desc pointer in the
    context are done by implementing cra_init and cra_exit functions for
    the hmac algorithms.
    Also improved indentation in some areas.
    
    Signed-off-by: Daniel Kestrel <kestrel1974 at t-online.de>
---
 .../kernel/lantiq/ltq-deu/src/ifxmips_md5_hmac.c   |  68 +++++++++---
 .../kernel/lantiq/ltq-deu/src/ifxmips_sha1_hmac.c  | 121 ++++++++++++++-------
 2 files changed, 137 insertions(+), 52 deletions(-)

diff --git a/package/kernel/lantiq/ltq-deu/src/ifxmips_md5_hmac.c b/package/kernel/lantiq/ltq-deu/src/ifxmips_md5_hmac.c
index 277879fbbb..092b0581cc 100644
--- a/package/kernel/lantiq/ltq-deu/src/ifxmips_md5_hmac.c
+++ b/package/kernel/lantiq/ltq-deu/src/ifxmips_md5_hmac.c
@@ -80,10 +80,10 @@ struct md5_hmac_ctx {
     u64 byte_count;
     u32 dbn;
     unsigned int keylen;
+    struct shash_desc *desc;
+    u32 (*temp)[MD5_BLOCK_WORDS];
 };
 
-static u32 temp[MD5_HMAC_DBN_TEMP_SIZE];
-
 extern int disable_deudma;
 
 /*! \fn static void md5_hmac_transform(struct crypto_tfm *tfm, u32 const *in)
@@ -96,7 +96,7 @@ static void md5_hmac_transform(struct shash_desc *desc, u32 const *in)
 {
     struct md5_hmac_ctx *mctx = crypto_shash_ctx(desc->tfm);
 
-    memcpy(&temp[mctx->dbn<<4], in, 64); //dbn workaround
+    memcpy(&mctx->temp[mctx->dbn], in, 64); //dbn workaround
     mctx->dbn += 1;
     
     if ( (mctx->dbn<<4) > MD5_HMAC_DBN_TEMP_SIZE )
@@ -116,19 +116,30 @@ static void md5_hmac_transform(struct shash_desc *desc, u32 const *in)
 static int md5_hmac_setkey(struct crypto_shash *tfm, const u8 *key, unsigned int keylen) 
 {
     struct md5_hmac_ctx *mctx = crypto_shash_ctx(tfm);
+    volatile struct deu_hash_t *hash = (struct deu_hash_t *) HASH_START;
+    int err;
     //printk("copying keys to context with length %d\n", keylen);
 
     if (keylen > MAX_HASH_KEYLEN) {
-	printk("Key length more than what DEU hash can handle\n");
-	return -EINVAL;
-    }
- 
+        char *hash_alg_name = "md5";
 
-    memcpy(&mctx->key, key, keylen);
-    mctx->keylen = keylen;
+        mctx->desc->tfm = crypto_alloc_shash(hash_alg_name, 0, 0);
+        if (IS_ERR(mctx->desc->tfm)) return PTR_ERR(mctx->desc->tfm);
 
-    return 0;
+        memset(mctx->key, 0, MAX_HASH_KEYLEN);
+        err = crypto_shash_digest(mctx->desc, key, keylen, mctx->key);
+        if (err) return err;
+
+        mctx->keylen = MD5_DIGEST_SIZE;
 
+        crypto_free_shash(mctx->desc->tfm);
+    } else {
+        memcpy(mctx->key, key, keylen);
+        mctx->keylen = keylen;
+    }
+    memset(mctx->key + mctx->keylen, 0, MAX_HASH_KEYLEN - mctx->keylen);
+
+    return 0;
 }
 
 
@@ -231,7 +242,7 @@ static int md5_hmac_final(struct shash_desc *desc, u8 *out)
     unsigned long flag;
     int i = 0;
     int dbn;
-    u32 *in = &temp[0];
+    u32 *in = mctx->temp[0];
 
 
     *p++ = 0x80;
@@ -299,7 +310,7 @@ static int md5_hmac_final(struct shash_desc *desc, u8 *out)
     mctx->byte_count = 0;
     memset(&mctx->hash[0], 0, sizeof(MD5_HASH_WORDS));
     memset(&mctx->block[0], 0, sizeof(MD5_BLOCK_WORDS));
-    memset(&temp[0], 0, MD5_HMAC_DBN_TEMP_SIZE);
+    memset(&mctx->temp[0], 0, MD5_HMAC_DBN_TEMP_SIZE);
 
     CRTCL_SECT_HASH_END;
 
@@ -307,6 +318,35 @@ static int md5_hmac_final(struct shash_desc *desc, u8 *out)
    return 0;
 }
 
+/*! \fn void md5_hmac_init_tfm(struct crypto_tfm *tfm)
+ *  \ingroup IFX_MD5_HMAC_FUNCTIONS
+ *  \brief initialize pointers in md5_hmac_ctx
+ *  \param tfm linux crypto algo transform
+*/
+static int md5_hmac_init_tfm(struct crypto_tfm *tfm)
+{
+    struct md5_hmac_ctx *mctx = crypto_tfm_ctx(tfm);
+    mctx->temp = kzalloc(4 * MD5_HMAC_DBN_TEMP_SIZE, GFP_KERNEL);
+    if (IS_ERR(mctx->temp)) return PTR_ERR(mctx->temp);
+    mctx->desc = kzalloc(sizeof(struct shash_desc), GFP_KERNEL);
+    if (IS_ERR(mctx->desc)) return PTR_ERR(mctx->desc);
+
+    return 0;
+}
+
+/*! \fn void md5_hmac_exit_tfm(struct crypto_tfm *tfm)
+ *  \ingroup IFX_MD5_HMAC_FUNCTIONS
+ *  \brief free pointers in md5_hmac_ctx
+ *  \param tfm linux crypto algo transform
+*/
+static void md5_hmac_exit_tfm(struct crypto_tfm *tfm)
+{
+    struct md5_hmac_ctx *mctx = crypto_tfm_ctx(tfm);
+    kfree(mctx->temp);
+    kfree(mctx->desc);
+}
+
+
 /* 
  * \brief MD5_HMAC function mappings
 */
@@ -322,10 +362,12 @@ static struct shash_alg ifxdeu_md5_hmac_alg = {
         .cra_name       =       "hmac(md5)",
         .cra_driver_name=       "ifxdeu-md5_hmac",
         .cra_priority   =       400,
-        .cra_ctxsize    =	sizeof(struct md5_hmac_ctx),
+        .cra_ctxsize    =       sizeof(struct md5_hmac_ctx),
         .cra_flags      =       CRYPTO_ALG_TYPE_HASH | CRYPTO_ALG_KERN_DRIVER_ONLY,
         .cra_blocksize  =       MD5_HMAC_BLOCK_SIZE,
         .cra_module     =       THIS_MODULE,
+        .cra_init       =       md5_hmac_init_tfm,
+        .cra_exit       =       md5_hmac_exit_tfm,
         }
 };
 
diff --git a/package/kernel/lantiq/ltq-deu/src/ifxmips_sha1_hmac.c b/package/kernel/lantiq/ltq-deu/src/ifxmips_sha1_hmac.c
index cee0041e8f..a9e1d64d6f 100644
--- a/package/kernel/lantiq/ltq-deu/src/ifxmips_sha1_hmac.c
+++ b/package/kernel/lantiq/ltq-deu/src/ifxmips_sha1_hmac.c
@@ -60,6 +60,7 @@
 #endif
 
 #define SHA1_DIGEST_SIZE    20
+#define SHA1_BLOCK_WORDS    16
 #define SHA1_HMAC_BLOCK_SIZE    64
 #define SHA1_HMAC_DBN_TEMP_SIZE 1024 // size in dword, needed for dbn workaround 
 #define HASH_START   IFX_HASH_CON
@@ -82,10 +83,10 @@ struct sha1_hmac_ctx {
     u32 dbn;
     u64 count;
 
+    struct shash_desc *desc;
+    u32 (*temp)[SHA1_BLOCK_WORDS];
 };
 
-static u32 temp[SHA1_HMAC_DBN_TEMP_SIZE];  
-
 extern int disable_deudma;
 
 /*! \fn static void sha1_hmac_transform(struct crypto_tfm *tfm, u32 const *in)
@@ -98,7 +99,7 @@ static int sha1_hmac_transform(struct shash_desc *desc, u32 const *in)
 {
     struct sha1_hmac_ctx *sctx =  crypto_shash_ctx(desc->tfm);
 
-    memcpy(&temp[sctx->dbn<<4], in, 64); //dbn workaround
+    memcpy(&sctx->temp[sctx->dbn], in, 64); //dbn workaround
     sctx->dbn += 1;
     
     if ( (sctx->dbn<<4) > SHA1_HMAC_DBN_TEMP_SIZE )
@@ -119,19 +120,31 @@ static int sha1_hmac_transform(struct shash_desc *desc, u32 const *in)
 static int sha1_hmac_setkey(struct crypto_shash *tfm, const u8 *key, unsigned int keylen)
 {
     struct sha1_hmac_ctx *sctx = crypto_shash_ctx(tfm);
-    
+    volatile struct deu_hash_t *hash = (struct deu_hash_t *) HASH_START;
+    int err;
+
     if (keylen > SHA1_HMAC_MAX_KEYLEN) {
-	printk("Key length exceeds maximum key length\n");
-	return -EINVAL;
+        char *hash_alg_name = "sha1";
+
+        sctx->desc->tfm = crypto_alloc_shash(hash_alg_name, 0, 0);
+        if (IS_ERR(sctx->desc->tfm)) return PTR_ERR(sctx->desc->tfm);
+
+        memset(sctx->key, 0, SHA1_HMAC_MAX_KEYLEN);
+        err = crypto_shash_digest(sctx->desc, key, keylen, sctx->key);
+        if (err) return err;
+
+        sctx->keylen = SHA1_DIGEST_SIZE;
+
+        crypto_free_shash(sctx->desc->tfm);
+    } else {
+        memcpy(sctx->key, key, keylen);
+        sctx->keylen = keylen;
     }
+    memset(sctx->key + sctx->keylen, 0, SHA1_HMAC_MAX_KEYLEN - sctx->keylen);
 
     //printk("Setting keys of len: %d\n", keylen);
-     
-    memcpy(&sctx->key, key, keylen);
-    sctx->keylen = keylen;
 
     return 0;
-         
 }
 
 
@@ -218,7 +231,6 @@ static int sha1_hmac_update(struct shash_desc *desc, const u8 *data,
 */                                 
 static int sha1_hmac_final(struct shash_desc *desc, u8 *out)
 {
-    //struct sha1_hmac_ctx *sctx = shash_desc_ctx(desc);
     struct sha1_hmac_ctx *sctx =  crypto_shash_ctx(desc->tfm);
     u32 index, padlen;
     u64 t;
@@ -228,7 +240,7 @@ static int sha1_hmac_final(struct shash_desc *desc, u8 *out)
     unsigned long flag;
     int i = 0;
     int dbn;
-    u32 *in = &temp[0];
+    u32 *in = sctx->temp[0];
         
     t = sctx->count + 512; // need to add 512 bit of the IPAD operation
     bits[7] = 0xff & t;
@@ -273,20 +285,20 @@ static int sha1_hmac_final(struct shash_desc *desc, u8 *out)
 
     for (dbn = 0; dbn < sctx->dbn; dbn++)
     {
-    for (i = 0; i < 16; i++) {
-        hashs->MR = in[i];
-    };
+        for (i = 0; i < 16; i++) {
+            hashs->MR = in[i];
+        };
 
-    hashs->controlr.GO = 1;
-    asm("sync");
+        hashs->controlr.GO = 1;
+        asm("sync");
 
-    //wait for processing
-    while (hashs->controlr.BSY) {
+        //wait for processing
+        while (hashs->controlr.BSY) {
             // this will not take long
-    }
+        }
     
-    in += 16;
-}
+        in += 16;
+    }
 
 
 #if 1
@@ -313,26 +325,57 @@ static int sha1_hmac_final(struct shash_desc *desc, u8 *out)
 
 }
 
-/*
- * \brief SHA1-HMAC function mappings
+/*! \fn void sha1_hmac_init_tfm(struct crypto_tfm *tfm)
+ *  \ingroup IFX_SHA1_HMAC_FUNCTIONS
+ *  \brief initialize pointers in sha1_hmac_ctx
+ *  \param tfm linux crypto algo transform
 */
+static int sha1_hmac_init_tfm(struct crypto_tfm *tfm)
+{
+    struct sha1_hmac_ctx *sctx = crypto_tfm_ctx(tfm);
+    sctx->temp = kzalloc(4 * SHA1_HMAC_DBN_TEMP_SIZE, GFP_KERNEL);
+    if (IS_ERR(sctx->temp)) return PTR_ERR(sctx->temp);
+    sctx->desc = kzalloc(sizeof(struct shash_desc), GFP_KERNEL);
+    if (IS_ERR(sctx->desc)) return PTR_ERR(sctx->desc);
+
+    return 0;
+}
+
+/*! \fn void sha1_hmac_exit_tfm(struct crypto_tfm *tfm)
+ *  \ingroup IFX_SHA1_HMAC_FUNCTIONS
+ *  \brief free pointers in sha1_hmac_ctx
+ *  \param tfm linux crypto algo transform
+*/
+static void sha1_hmac_exit_tfm(struct crypto_tfm *tfm)
+{
+    struct sha1_hmac_ctx *sctx = crypto_tfm_ctx(tfm);
+    kfree(sctx->temp);
+    kfree(sctx->desc);
+}
+
+
+/* 
+ * \brief SHA1_HMAC function mappings
+*/
+
 static struct shash_alg ifxdeu_sha1_hmac_alg = {
-        .digestsize     =       SHA1_DIGEST_SIZE,
-        .init           =       sha1_hmac_init,
-        .update         =       sha1_hmac_update,
-        .final          =       sha1_hmac_final,
-        .setkey         =       sha1_hmac_setkey,
-        .descsize       =       sizeof(struct sha1_hmac_ctx),
-        .base           =       {
-                .cra_name       =       "hmac(sha1)",
-                .cra_driver_name=       "ifxdeu-sha1_hmac",
-                .cra_priority   =       400,
-		.cra_ctxsize    =	sizeof(struct sha1_hmac_ctx),
-                .cra_flags      =       CRYPTO_ALG_TYPE_HASH | CRYPTO_ALG_KERN_DRIVER_ONLY,
-                .cra_blocksize  =       SHA1_HMAC_BLOCK_SIZE,
-                .cra_module     =       THIS_MODULE,
+    .digestsize         =       SHA1_DIGEST_SIZE,
+    .init               =       sha1_hmac_init,
+    .update             =       sha1_hmac_update,
+    .final              =       sha1_hmac_final,
+    .setkey             =       sha1_hmac_setkey,
+    .descsize           =       sizeof(struct sha1_hmac_ctx),
+    .base               =       {
+        .cra_name       =       "hmac(sha1)",
+        .cra_driver_name=       "ifxdeu-sha1_hmac",
+        .cra_priority   =       400,
+        .cra_ctxsize    =       sizeof(struct sha1_hmac_ctx),
+        .cra_flags      =       CRYPTO_ALG_TYPE_HASH | CRYPTO_ALG_KERN_DRIVER_ONLY,
+        .cra_blocksize  =       SHA1_HMAC_BLOCK_SIZE,
+        .cra_module     =       THIS_MODULE,
+        .cra_init       =       sha1_hmac_init_tfm,
+        .cra_exit       =       sha1_hmac_exit_tfm,
         }
-
 };
 
 



More information about the lede-commits mailing list