diff options
Diffstat (limited to 'package/kernel/lantiq/ltq-deu/src/ifxmips_md5_hmac.c')
| -rw-r--r-- | package/kernel/lantiq/ltq-deu/src/ifxmips_md5_hmac.c | 189 |
1 files changed, 115 insertions, 74 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 6cb2e5a4174..109d27cbfbe 100644 --- a/package/kernel/lantiq/ltq-deu/src/ifxmips_md5_hmac.c +++ b/package/kernel/lantiq/ltq-deu/src/ifxmips_md5_hmac.c @@ -63,11 +63,6 @@ #define MD5_HMAC_DBN_TEMP_SIZE 1024 // size in dword, needed for dbn workaround #define HASH_START IFX_HASH_CON -static spinlock_t lock; -#define CRTCL_SECT_INIT spin_lock_init(&lock) -#define CRTCL_SECT_START spin_lock_irqsave(&lock, flag) -#define CRTCL_SECT_END spin_unlock_irqrestore(&lock, flag) - //#define CRYPTO_DEBUG #ifdef CRYPTO_DEBUG extern char debug_level; @@ -84,24 +79,15 @@ struct md5_hmac_ctx { u32 block[MD5_BLOCK_WORDS]; u64 byte_count; u32 dbn; + int started; 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 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]); -} +static int md5_hmac_final_impl(struct shash_desc *desc, u8 *out, bool hash_final); /*! \fn static void md5_hmac_transform(struct crypto_tfm *tfm, u32 const *in) * \ingroup IFX_MD5_HMAC_FUNCTIONS @@ -113,14 +99,14 @@ 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 - mctx->dbn += 1; - - if ( (mctx->dbn<<4) > MD5_HMAC_DBN_TEMP_SIZE ) + if ( ((mctx->dbn<<4)+1) > MD5_HMAC_DBN_TEMP_SIZE ) { - printk("MD5_HMAC_DBN_TEMP_SIZE exceeded\n"); + //printk("MD5_HMAC_DBN_TEMP_SIZE exceeded\n"); + md5_hmac_final_impl(desc, (u8 *)mctx->hash, false); } + memcpy(&mctx->temp[mctx->dbn], in, 64); //dbn workaround + mctx->dbn += 1; } /*! \fn int md5_hmac_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) @@ -133,23 +119,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"; - hash->KIDX |= 0x80000000; // reset all 16 words of the key to '0' - 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; +} /*! \fn int md5_hmac_setkey_hw(const u8 *key, unsigned int keylen) * \ingroup IFX_MD5_HMAC_FUNCTIONS @@ -157,17 +150,15 @@ static int md5_hmac_setkey(struct crypto_shash *tfm, const u8 *key, unsigned int * \param key input key * \param keylen key length greater than 64 bytes IS NOT SUPPORTED */ - 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_START; + hash->KIDX |= 0x80000000; // reset all 16 words of the key to '0' j = 0; for (i = 0; i < keylen; i+=4) { @@ -177,7 +168,6 @@ static int md5_hmac_setkey_hw(const u8 *key, unsigned int keylen) asm("sync"); j++; } - CRTCL_SECT_END; return 0; } @@ -194,11 +184,11 @@ static int md5_hmac_init(struct shash_desc *desc) mctx->dbn = 0; //dbn workaround - md5_hmac_setkey_hw(mctx->key, mctx->keylen); + mctx->started = 0; + mctx->byte_count = 0; return 0; } -EXPORT_SYMBOL(md5_hmac_init); /*! \fn void md5_hmac_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len) * \ingroup IFX_MD5_HMAC_FUNCTIONS @@ -237,16 +227,27 @@ static int md5_hmac_update(struct shash_desc *desc, const u8 *data, unsigned int memcpy(mctx->block, data, len); return 0; } -EXPORT_SYMBOL(md5_hmac_update); -/*! \fn void md5_hmac_final(struct crypto_tfm *tfm, u8 *out) +/*! \fn static int md5_hmac_final(struct crypto_tfm *tfm, u8 *out) * \ingroup IFX_MD5_HMAC_FUNCTIONS - * \brief compute final md5 hmac value + * \brief call md5_hmac_final_impl with hash_final true * \param tfm linux crypto algo transform * \param out final md5 hmac output value */ static int md5_hmac_final(struct shash_desc *desc, u8 *out) { + return md5_hmac_final_impl(desc, out, true); +} + +/*! \fn static int md5_hmac_final_impl(struct crypto_tfm *tfm, u8 *out, bool hash_final) + * \ingroup IFX_MD5_HMAC_FUNCTIONS + * \brief compute final or intermediate md5 hmac value + * \param tfm linux crypto algo transform + * \param out final md5 hmac output value + * \param in finalize or intermediate processing +*/ +static int md5_hmac_final_impl(struct shash_desc *desc, u8 *out, bool hash_final) +{ struct md5_hmac_ctx *mctx = crypto_shash_ctx(desc->tfm); const unsigned int offset = mctx->byte_count & 0x3f; char *p = (char *)mctx->block + offset; @@ -255,27 +256,36 @@ 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]; + + if (hash_final) { + *p++ = 0x80; + if (padding < 0) { + memset(p, 0x00, padding + sizeof (u64)); + md5_hmac_transform(desc, mctx->block); + p = (char *)mctx->block; + padding = 56; + } + memset(p, 0, padding); + mctx->block[14] = le32_to_cpu((mctx->byte_count + 64) << 3); // need to add 512 bit of the IPAD operation + mctx->block[15] = 0x00000000; - *p++ = 0x80; - if (padding < 0) { - memset(p, 0x00, padding + sizeof (u64)); md5_hmac_transform(desc, mctx->block); - p = (char *)mctx->block; - padding = 56; } - 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[15] = 0x00000000; + CRTCL_SECT_HASH_START; - md5_hmac_transform(desc, mctx->block); + MD5_HASH_INIT; - CRTCL_SECT_START; + md5_hmac_setkey_hw(mctx->key, mctx->keylen); //printk("\ndbn = %d\n", mctx->dbn); - hashs->DBN = mctx->dbn; + if (hash_final) { + hashs->DBN = mctx->dbn; + } else { + hashs->DBN = mctx->dbn + 5; + } asm("sync"); *IFX_HASH_CON = 0x0703002D; //khs, go, init, ndc, endi, kyue, hmen, md5 @@ -285,6 +295,15 @@ static int md5_hmac_final(struct shash_desc *desc, u8 *out) // this will not take long } + if (mctx->started) { + hashs->D1R = *((u32 *) mctx->hash + 0); + hashs->D2R = *((u32 *) mctx->hash + 1); + hashs->D3R = *((u32 *) mctx->hash + 2); + hashs->D4R = *((u32 *) mctx->hash + 3); + } else { + mctx->started = 1; + } + for (dbn = 0; dbn < mctx->dbn; dbn++) { for (i = 0; i < 16; i++) { @@ -302,11 +321,12 @@ static int md5_hmac_final(struct shash_desc *desc, u8 *out) 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 @@ -314,26 +334,49 @@ 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; - 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); + CRTCL_SECT_HASH_END; - CRTCL_SECT_END; + if (hash_final) { + /* reset the context after we finish with the hash */ + md5_hmac_init(desc); + } else { + mctx->dbn = 0; + } + 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; + return 0; } -EXPORT_SYMBOL(md5_hmac_final); +/*! \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 */ - static struct shash_alg ifxdeu_md5_hmac_alg = { .digestsize = MD5_DIGEST_SIZE, .init = md5_hmac_init, @@ -345,10 +388,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_flags = CRYPTO_ALG_TYPE_HASH, + .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, } }; @@ -365,8 +410,6 @@ int ifxdeu_init_md5_hmac (void) if ((ret = crypto_register_shash(&ifxdeu_md5_hmac_alg))) goto md5_hmac_err; - CRTCL_SECT_INIT; - printk (KERN_NOTICE "IFX DEU MD5_HMAC initialized%s.\n", disable_deudma ? "" : " (DMA)"); return ret; @@ -383,5 +426,3 @@ void ifxdeu_fini_md5_hmac (void) { crypto_unregister_shash(&ifxdeu_md5_hmac_alg); } - - |
