From: Daniel Kestrel Date: Sun, 6 Jun 2021 19:16:32 +0000 (+0200) Subject: ltq-deu: fix setkey errors and static shared temp for hmac algos X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=85383b311212576e7afd9d01dec49f69ef6fb886;p=openwrt%2Fstaging%2Faparcar.git 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 --- 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, } - };