kernel: bump 5.10 to 5.10.218
[openwrt/openwrt.git] / package / kernel / lantiq / ltq-deu / src / ifxmips_sha1_hmac.c
index a1461e6e5ba8a1acd574c1cc744806083e7ce6b6..69504efe93102890a760d8d064870a97b68833e7 100644 (file)
@@ -38,7 +38,6 @@
   \brief ifx sha1 hmac functions
 */
 
-
 /* Project header */
 #include <linux/init.h>
 #include <linux/module.h>
@@ -60,6 +59,8 @@
 #endif
 
 #define SHA1_DIGEST_SIZE    20
+#define SHA1_BLOCK_WORDS    16
+#define SHA1_HASH_WORDS     5
 #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
@@ -78,16 +79,19 @@ struct sha1_hmac_ctx {
 
     u8 buffer[SHA1_HMAC_BLOCK_SIZE];
     u8 key[SHA1_HMAC_MAX_KEYLEN];
-    u32 state[5];
+    u32 hash[SHA1_HASH_WORDS];
     u32 dbn;
+    int started;
     u64 count;
 
+    struct shash_desc *desc;
+    u32 (*temp)[SHA1_BLOCK_WORDS];
 };
 
-static u32 temp[SHA1_HMAC_DBN_TEMP_SIZE];  
-
 extern int disable_deudma;
 
+static int sha1_hmac_final_impl(struct shash_desc *desc, u8 *out, bool hash_final);
+
 /*! \fn static void sha1_hmac_transform(struct crypto_tfm *tfm, u32 const *in)
  *  \ingroup IFX_SHA1_HMAC_FUNCTIONS
  *  \brief save input block to context   
@@ -98,14 +102,15 @@ 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
-    sctx->dbn += 1;
-    
-    if ( (sctx->dbn<<4) > SHA1_HMAC_DBN_TEMP_SIZE )
+    if ( ((sctx->dbn<<4)+1) > SHA1_HMAC_DBN_TEMP_SIZE )
     {
-        printk("SHA1_HMAC_DBN_TEMP_SIZE exceeded\n");
+        //printk("SHA1_HMAC_DBN_TEMP_SIZE exceeded\n");
+        sha1_hmac_final_impl(desc, (u8 *)sctx->hash, false);
     }
-   
+
+    memcpy(&sctx->temp[sctx->dbn], in, 64); //dbn workaround
+    sctx->dbn += 1;
+
     return 0;
 }
 
@@ -119,24 +124,32 @@ 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;
-    
+    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);
-     
-    hashs->KIDX |= 0x80000000; //reset keys back to 0
-    memcpy(&sctx->key, key, keylen);
-    sctx->keylen = keylen;
 
     return 0;
-         
 }
 
-
 /*! \fn int sha1_hmac_setkey_hw(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
  *  \ingroup IFX_SHA1_HMAC_FUNCTIONS
  *  \brief sets sha1 hmac key  into hw registers 
@@ -148,12 +161,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 +174,6 @@ static int sha1_hmac_setkey_hw(const u8 *key, unsigned int keylen)
          j++;
     }
 
-    CRTCL_SECT_HASH_END;
     return 0;
 }
 
@@ -177,7 +188,8 @@ 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);
+    sctx->started = 0;
+    sctx->count = 0;
 
     return 0;
 }
@@ -215,15 +227,26 @@ static int sha1_hmac_update(struct shash_desc *desc, const u8 *data,
     return 0;
 }
 
-/*! \fn static void sha1_hmac_final(struct crypto_tfm *tfm, u8 *out)
+/*! \fn static int sha1_hmac_final(struct crypto_tfm *tfm, u8 *out)
  *  \ingroup IFX_SHA1_HMAC_FUNCTIONS
- *  \brief ompute final sha1 hmac value   
+ *  \brief call sha1_hmac_final_impl with hash_final true   
  *  \param tfm linux crypto algo transform  
  *  \param out final sha1 hmac output value  
 */                                 
 static int sha1_hmac_final(struct shash_desc *desc, u8 *out)
 {
-    //struct sha1_hmac_ctx *sctx = shash_desc_ctx(desc);
+    return sha1_hmac_final_impl(desc, out, true);
+}
+
+/*! \fn static int sha1_hmac_final_impl(struct crypto_tfm *tfm, u8 *out, bool hash_final)
+ *  \ingroup IFX_SHA1_HMAC_FUNCTIONS
+ *  \brief ompute final or intermediate sha1 hmac value   
+ *  \param tfm linux crypto algo transform  
+ *  \param out final sha1 hmac output value  
+ *  \param in finalize or intermediate processing  
+*/                                 
+static int sha1_hmac_final_impl(struct shash_desc *desc, u8 *out, bool hash_final)
+{
     struct sha1_hmac_ctx *sctx =  crypto_shash_ctx(desc->tfm);
     u32 index, padlen;
     u64 t;
@@ -233,37 +256,48 @@ static int sha1_hmac_final(struct shash_desc *desc, u8 *out)
     unsigned long flag;
     int i = 0;
     int dbn;
-    u32 *in = &temp[0];
-        
-    t = sctx->count + 512; // need to add 512 bit of the IPAD operation
-    bits[7] = 0xff & t;
-    t >>= 8;
-    bits[6] = 0xff & t;
-    t >>= 8;
-    bits[5] = 0xff & t;
-    t >>= 8;
-    bits[4] = 0xff & t;
-    t >>= 8;
-    bits[3] = 0xff & t;
-    t >>= 8;
-    bits[2] = 0xff & t;
-    t >>= 8;
-    bits[1] = 0xff & t;
-    t >>= 8;
-    bits[0] = 0xff & t;
-
-    /* Pad out to 56 mod 64 */
-    index = (sctx->count >> 3) & 0x3f;
-    padlen = (index < 56) ? (56 - index) : ((64 + 56) - index);
-    sha1_hmac_update (desc, padding, padlen);
-
-    /* Append length */
-    sha1_hmac_update (desc, bits, sizeof bits);
+    u32 *in = sctx->temp[0];
+
+    if (hash_final) {
+        t = sctx->count + 512; // need to add 512 bit of the IPAD operation
+        bits[7] = 0xff & t;
+        t >>= 8;
+        bits[6] = 0xff & t;
+        t >>= 8;
+        bits[5] = 0xff & t;
+        t >>= 8;
+        bits[4] = 0xff & t;
+        t >>= 8;
+        bits[3] = 0xff & t;
+        t >>= 8;
+        bits[2] = 0xff & t;
+        t >>= 8;
+        bits[1] = 0xff & t;
+        t >>= 8;
+        bits[0] = 0xff & t;
+
+        /* Pad out to 56 mod 64 */
+        index = (sctx->count >> 3) & 0x3f;
+        padlen = (index < 56) ? (56 - index) : ((64 + 56) - index);
+        sha1_hmac_update (desc, padding, padlen);
+
+        /* Append length */
+        sha1_hmac_update (desc, bits, sizeof bits);
+    }
 
     CRTCL_SECT_HASH_START;
-    
-    hashs->DBN = sctx->dbn;
-    
+
+    SHA_HASH_INIT;
+
+    sha1_hmac_setkey_hw(sctx->key, sctx->keylen);
+
+    if (hash_final) {
+        hashs->DBN = sctx->dbn;
+    } else {
+        hashs->DBN = sctx->dbn + 5;
+    }
+    asm("sync");
+
     //for vr9 change, ENDI = 1
     *IFX_HASH_CON = HASH_CON_VALUE; 
 
@@ -272,28 +306,40 @@ static int sha1_hmac_final(struct shash_desc *desc, u8 *out)
         // this will not take long
     }
 
+    if (sctx->started) {
+        hashs->D1R = *((u32 *) sctx->hash + 0);
+        hashs->D2R = *((u32 *) sctx->hash + 1);
+        hashs->D3R = *((u32 *) sctx->hash + 2);
+        hashs->D4R = *((u32 *) sctx->hash + 3);
+        hashs->D5R = *((u32 *) sctx->hash + 4);
+    } else {
+        sctx->started = 1;
+    }
+
     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
-    //wait for digest ready
-    while (! hashs->controlr.DGRY) {
-        // this will not take long
+    if (hash_final) {
+        //wait for digest ready
+        while (! hashs->controlr.DGRY) {
+            // this will not take long
+        }
     }
 #endif
 
@@ -303,40 +349,71 @@ static int sha1_hmac_final(struct shash_desc *desc, u8 *out)
     *((u32 *) out + 3) = hashs->D4R;
     *((u32 *) out + 4) = hashs->D5R;
 
-    memset(&sctx->buffer[0], 0, SHA1_HMAC_BLOCK_SIZE);
-    sctx->count = 0; 
-    //printk("debug ln: %d, fn: %s\n", __LINE__, __func__);
     CRTCL_SECT_HASH_END;
 
+    if (hash_final) {
+        sha1_hmac_init(desc);
+    } else {
+        sctx->dbn = 0;
+    }
+    //printk("debug ln: %d, fn: %s\n", __LINE__, __func__);
+
+    return 0;
+
+}
+
+/*! \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
+/* 
+ * \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,
         }
-
 };
 
-
 /*! \fn int ifxdeu_init_sha1_hmac (void)
  *  \ingroup IFX_SHA1_HMAC_FUNCTIONS
  *  \brief initialize sha1 hmac driver    
@@ -369,4 +446,3 @@ void ifxdeu_fini_sha1_hmac (void)
 
 
 }
-