ltq-deu: changes for hash multithread callers and md5 endianess
authorDaniel Kestrel <kestrel1974@t-online.de>
Sat, 5 Jun 2021 21:46:58 +0000 (23:46 +0200)
committerHauke Mehrtens <hauke@hauke-m.de>
Wed, 5 Jan 2022 23:22:50 +0000 (00:22 +0100)
The algorithms sha1, sha1_hmac and md5_hmac all use ENDI=1. The md5
algorithm uses ENDI=0 and the endian_swap methods to reverse the
endianess switch by using user CPU time, which is unnecessary overhead.
Danube and AR9 devices do not set endianess for SHA1, so is done for
MD5.
Furthermore the patch replaces endian_swap with le32_to_cpu for md5 and
md5 hmac algorithms and removes endian_swap for them.
The init functions initialize the algorithm in the hardware. The lock is
not used to write to the control register. If another thread calls
another hash algo before update or final, the result will be wrong.
Therefore move the algorithm init to the lock protected sections in the
transform or final methods.
Setting the hw key for the hmac algorithms is now done from within the
lock protected sections in their final methods. The lock protecting is
removed from the _hmac_setkey_hw functions.
In final for md5 and sha1 the lock section is removed, because all the
work was already done in transform (which is called from final). As such
only copying the hash to the output is required.
MD5 and MD5_HMAC produce 16 byte hashes (4 DWORDS) only, therefor
writing register D5R to the hash output is removed for MD5_HMAC.

Signed-off-by: Daniel Kestrel <kestrel1974@t-online.de>
package/kernel/lantiq/ltq-deu/src/ifxmips_deu_ar9.h
package/kernel/lantiq/ltq-deu/src/ifxmips_deu_danube.h
package/kernel/lantiq/ltq-deu/src/ifxmips_md5.c
package/kernel/lantiq/ltq-deu/src/ifxmips_md5_hmac.c
package/kernel/lantiq/ltq-deu/src/ifxmips_sha1.c
package/kernel/lantiq/ltq-deu/src/ifxmips_sha1_hmac.c

index 69414553deae826cc1b65b5d7037c9888e5c5869..2f373589a5caa11762178cffe48dcda8bc5c5c57 100644 (file)
         hash->controlr.INIT = 1;  \
     } while(0)
 
+#define MD5_HASH_INIT                  \
+    do {                               \
+        volatile struct deu_hash_t *hash = (struct deu_hash_t *) HASH_START; \
+        hash->controlr.SM = 1;    \
+        hash->controlr.ALGO = 1;  \
+        hash->controlr.INIT = 1;  \
+    } while(0)
+
 /* DEU Common Structures for AR9*/
  
 struct clc_controlr_t {
index 25efa04a6960aafbde5da133ff56436806328dd4..25561cf6e08a7500a7d506b44d50514728f8f6f1 100644 (file)
         hash->controlr.INIT = 1;  \
     } while(0)
 
+#define MD5_HASH_INIT                  \
+    do {                               \
+        volatile struct deu_hash_t *hash = (struct deu_hash_t *) HASH_START; \
+        hash->controlr.SM = 1;    \
+        hash->controlr.ALGO = 1;  \
+        hash->controlr.INIT = 1;  \
+    } while(0)
+
 /* DEU STRUCTURES */
 
 struct clc_controlr_t {
index f7dbee4fdc74ad9d21569534aacf2f1970f5799c..376ff64d05a3b99083d8815449bbb3f5e2caf218 100644 (file)
@@ -81,18 +81,6 @@ struct md5_ctx {
 
 extern int disable_deudma;
 
-/*! \fn static u32 endian_swap(u32 input)
- *  \ingroup IFX_MD5_FUNCTIONS
- *  \brief perform dword level endian swap   
- *  \param input value of dword that requires to be swapped  
-*/ 
-static u32 endian_swap(u32 input)
-{
-    u8 *ptr = (u8 *)&input;
-    
-    return ((ptr[3] << 24) | (ptr[2] << 16) | (ptr[1] << 8) | ptr[0]);     
-}
-
 /*! \fn static void md5_transform(u32 *hash, u32 const *in)
  *  \ingroup IFX_MD5_FUNCTIONS
  *  \brief main interface to md5 hardware   
@@ -107,16 +95,18 @@ static void md5_transform(struct md5_ctx *mctx, u32 *hash, u32 const *in)
 
     CRTCL_SECT_HASH_START;
 
+    MD5_HASH_INIT;
+
     if (mctx->started) { 
-        hashs->D1R = endian_swap(*((u32 *) hash + 0));
-       hashs->D2R = endian_swap(*((u32 *) hash + 1));
-        hashs->D3R = endian_swap(*((u32 *) hash + 2));
-        hashs->D4R = endian_swap(*((u32 *) hash + 3));
+        hashs->D1R = *((u32 *) hash + 0);
+        hashs->D2R = *((u32 *) hash + 1);
+        hashs->D3R = *((u32 *) hash + 2);
+        hashs->D4R = *((u32 *) hash + 3);
     }
 
     for (i = 0; i < 16; i++) {
-        hashs->MR = endian_swap(in[i]);
-//     printk("in[%d]: %08x\n", i, endian_swap(in[i]));
+        hashs->MR = in[i];
+//      printk("in[%d]: %08x\n", i, in[i]);
     };
 
     //wait for processing
@@ -124,10 +114,10 @@ static void md5_transform(struct md5_ctx *mctx, u32 *hash, u32 const *in)
         // this will not take long
     }
 
-    *((u32 *) hash + 0) = endian_swap (hashs->D1R);
-    *((u32 *) hash + 1) = endian_swap (hashs->D2R);
-    *((u32 *) hash + 2) = endian_swap (hashs->D3R);
-    *((u32 *) hash + 3) = endian_swap (hashs->D4R);
+    *((u32 *) hash + 0) = hashs->D1R;
+    *((u32 *) hash + 1) = hashs->D2R;
+    *((u32 *) hash + 2) = hashs->D3R;
+    *((u32 *) hash + 3) = hashs->D4R;
 
     mctx->started = 1; 
 
@@ -155,11 +145,6 @@ static int md5_init(struct shash_desc *desc)
     struct md5_ctx *mctx = shash_desc_ctx(desc);
     volatile struct deu_hash_t *hash = (struct deu_hash_t *) HASH_START;
 
-    hash->controlr.ENDI = 0;
-    hash->controlr.SM = 1;
-    hash->controlr.ALGO = 1;    // 1 = md5  0 = sha1
-    hash->controlr.INIT = 1;    // Initialize the hash operation by writing a '1' to the INIT bit.
-
     mctx->byte_count = 0;
     mctx->started = 0;
     return 0;
@@ -227,24 +212,12 @@ static int md5_final(struct shash_desc *desc, u8 *out)
     }
 
     memset(p, 0, padding);
-    mctx->block[14] = endian_swap(mctx->byte_count << 3);
-    mctx->block[15] = endian_swap(mctx->byte_count >> 29);
-
-#if 0
-    le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
-                      sizeof(u64)) / sizeof(u32));
-#endif
+    mctx->block[14] = le32_to_cpu(mctx->byte_count << 3);
+    mctx->block[15] = le32_to_cpu(mctx->byte_count >> 29);
 
     md5_transform(mctx, mctx->hash, mctx->block);                                                 
 
-    CRTCL_SECT_HASH_START;
-
-    *((u32 *) out + 0) = endian_swap (hashs->D1R);
-    *((u32 *) out + 1) = endian_swap (hashs->D2R);
-    *((u32 *) out + 2) = endian_swap (hashs->D3R);
-    *((u32 *) out + 3) = endian_swap (hashs->D4R);
-
-    CRTCL_SECT_HASH_END;
+    memcpy(out, mctx->hash, MD5_DIGEST_SIZE);
 
     // Wipe context
     memset(mctx, 0, sizeof(*mctx));
index 9cc6eb7a550f829571c07442c0cedc6f4cb1c42c..277879fbbb83f06c77fa941b0a1bae081fcef14a 100644 (file)
@@ -86,18 +86,6 @@ static u32 temp[MD5_HMAC_DBN_TEMP_SIZE];
 
 extern int disable_deudma;
 
-/*! \fn static u32 endian_swap(u32 input)
- *  \ingroup IFX_MD5_HMAC_FUNCTIONS
- *  \brief perform dword level endian swap   
- *  \param input value of dword that requires to be swapped  
-*/                                 
-static u32 endian_swap(u32 input)
-{
-    u8 *ptr = (u8 *)&input;
-    
-    return ((ptr[3] << 24) | (ptr[2] << 16) | (ptr[1] << 8) | ptr[0]);     
-}
-
 /*! \fn static void md5_hmac_transform(struct crypto_tfm *tfm, u32 const *in)
  *  \ingroup IFX_MD5_HMAC_FUNCTIONS
  *  \brief save input block to context   
@@ -128,7 +116,6 @@ 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;
     //printk("copying keys to context with length %d\n", keylen);
 
     if (keylen > MAX_HASH_KEYLEN) {
@@ -137,7 +124,6 @@ static int md5_hmac_setkey(struct crypto_shash *tfm, const u8 *key, unsigned int
     }
  
 
-    hash->KIDX |= 0x80000000; // reset all 16 words of the key to '0'
     memcpy(&mctx->key, key, keylen);
     mctx->keylen = keylen;
 
@@ -156,13 +142,12 @@ static int md5_hmac_setkey(struct crypto_shash *tfm, const u8 *key, unsigned int
 static int md5_hmac_setkey_hw(const u8 *key, unsigned int keylen)
 {
     volatile struct deu_hash_t *hash = (struct deu_hash_t *) HASH_START;
-    unsigned long flag;
     int i, j;
     u32 *in_key = (u32 *)key;        
 
     //printk("\nsetkey keylen: %d\n key: ", keylen);
     
-    CRTCL_SECT_HASH_START;
+    hash->KIDX |= 0x80000000; // reset all 16 words of the key to '0'
     j = 0;
     for (i = 0; i < keylen; i+=4)
     {
@@ -172,7 +157,6 @@ static int md5_hmac_setkey_hw(const u8 *key, unsigned int keylen)
          asm("sync");
          j++;
     }
-    CRTCL_SECT_HASH_END;
 
     return 0;
 }
@@ -189,7 +173,6 @@ static int md5_hmac_init(struct shash_desc *desc)
     
 
     mctx->dbn = 0; //dbn workaround
-    md5_hmac_setkey_hw(mctx->key, mctx->keylen);
 
     return 0;
 }
@@ -260,13 +243,17 @@ static int md5_hmac_final(struct shash_desc *desc, u8 *out)
     }
 
     memset(p, 0, padding);
-    mctx->block[14] = endian_swap((mctx->byte_count + 64) << 3); // need to add 512 bit of the IPAD operation 
+    mctx->block[14] = le32_to_cpu((mctx->byte_count + 64) << 3); // need to add 512 bit of the IPAD operation 
     mctx->block[15] = 0x00000000;
 
     md5_hmac_transform(desc, mctx->block);
 
     CRTCL_SECT_HASH_START;
 
+    MD5_HASH_INIT;
+
+    md5_hmac_setkey_hw(mctx->key, mctx->keylen);
+
     //printk("\ndbn = %d\n", mctx->dbn); 
     hashs->DBN = mctx->dbn;
     asm("sync");
@@ -307,7 +294,6 @@ static int md5_hmac_final(struct shash_desc *desc, u8 *out)
     *((u32 *) out + 1) = hashs->D2R;
     *((u32 *) out + 2) = hashs->D3R;
     *((u32 *) out + 3) = hashs->D4R;
-    *((u32 *) out + 4) = hashs->D5R;
 
     /* reset the context after we finish with the hash */
     mctx->byte_count = 0;
index 70271b2dd01512168fe4898ecd7be084df86f84f..a139f8d9d4a8562d6d4218ff01c7e89563d4682f 100644 (file)
@@ -101,6 +101,8 @@ static void sha1_transform1 (struct sha1_ctx *sctx, u32 *state, const u32 *in)
 
     CRTCL_SECT_HASH_START;
 
+    SHA_HASH_INIT;
+
     /* For context switching purposes, the previous hash output
      * is loaded back into the output register 
     */
@@ -144,8 +146,6 @@ static int sha1_init1(struct shash_desc *desc)
 {
     struct sha1_ctx *sctx = shash_desc_ctx(desc);
     
-    SHA_HASH_INIT;
-
     sctx->started = 0;
     sctx->count = 0;
     return 0;
@@ -224,15 +224,7 @@ static int sha1_final(struct shash_desc *desc, u8 *out)
     /* Append length */
     sha1_update (desc, bits, sizeof bits);
 
-    CRTCL_SECT_HASH_START;
-
-    *((u32 *) out + 0) = hashs->D1R;
-    *((u32 *) out + 1) = hashs->D2R;
-    *((u32 *) out + 2) = hashs->D3R;
-    *((u32 *) out + 3) = hashs->D4R;
-    *((u32 *) out + 4) = hashs->D5R;
-
-    CRTCL_SECT_HASH_END;
+    memcpy(out, sctx->hash, SHA1_DIGEST_SIZE);
 
     // Wipe context
     memset (sctx, 0, sizeof *sctx);
index a1461e6e5ba8a1acd574c1cc744806083e7ce6b6..cee0041e8f9595aa0dfa88137643473537e5fd36 100644 (file)
@@ -119,7 +119,6 @@ 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 *hashs = (struct deu_hash_t *) HASH_START;
     
     if (keylen > SHA1_HMAC_MAX_KEYLEN) {
        printk("Key length exceeds maximum key length\n");
@@ -128,7 +127,6 @@ static int sha1_hmac_setkey(struct crypto_shash *tfm, const u8 *key, unsigned in
 
     //printk("Setting keys of len: %d\n", keylen);
      
-    hashs->KIDX |= 0x80000000; //reset keys back to 0
     memcpy(&sctx->key, key, keylen);
     sctx->keylen = keylen;
 
@@ -148,12 +146,11 @@ static int sha1_hmac_setkey_hw(const u8 *key, unsigned int keylen)
 {
     volatile struct deu_hash_t *hash = (struct deu_hash_t *) HASH_START;
     int i, j;
-    unsigned long flag;
     u32 *in_key = (u32 *)key;        
 
     j = 0;
 
-    CRTCL_SECT_HASH_START;
+    hash->KIDX |= 0x80000000; //reset keys back to 0
     for (i = 0; i < keylen; i+=4)
     {
          hash->KIDX = j;
@@ -162,7 +159,6 @@ static int sha1_hmac_setkey_hw(const u8 *key, unsigned int keylen)
          j++;
     }
 
-    CRTCL_SECT_HASH_END;
     return 0;
 }
 
@@ -177,7 +173,6 @@ static int sha1_hmac_init(struct shash_desc *desc)
 
     //printk("debug ln: %d, fn: %s\n", __LINE__, __func__);
     sctx->dbn = 0; //dbn workaround
-    sha1_hmac_setkey_hw(sctx->key, sctx->keylen);
 
     return 0;
 }
@@ -261,6 +256,10 @@ static int sha1_hmac_final(struct shash_desc *desc, u8 *out)
     sha1_hmac_update (desc, bits, sizeof bits);
 
     CRTCL_SECT_HASH_START;
+
+    SHA_HASH_INIT;
+
+    sha1_hmac_setkey_hw(sctx->key, sctx->keylen);
     
     hashs->DBN = sctx->dbn;