mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
[CRYPTO] hmac: Avoid calling virt_to_page on key
When HMAC gets a key longer than the block size of the hash, it needs to feed it as input to the hash to reduce it to a fixed length. As it is HMAC converts the key to a scatter and gather list. However, this doesn't work on certain platforms if the key is not allocated via kmalloc. For example, the keys from tcrypt are stored in the rodata section and this causes it to fail with HMAC on x86-64. This patch fixes this by copying the key to memory obtained via kmalloc before hashing it. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
parent
c0a18111e5
commit
67412f0e78
1 changed files with 23 additions and 2 deletions
|
@ -57,14 +57,35 @@ static int hmac_setkey(struct crypto_hash *parent,
|
||||||
if (keylen > bs) {
|
if (keylen > bs) {
|
||||||
struct hash_desc desc;
|
struct hash_desc desc;
|
||||||
struct scatterlist tmp;
|
struct scatterlist tmp;
|
||||||
|
int tmplen;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
desc.tfm = tfm;
|
desc.tfm = tfm;
|
||||||
desc.flags = crypto_hash_get_flags(parent);
|
desc.flags = crypto_hash_get_flags(parent);
|
||||||
desc.flags &= CRYPTO_TFM_REQ_MAY_SLEEP;
|
desc.flags &= CRYPTO_TFM_REQ_MAY_SLEEP;
|
||||||
sg_init_one(&tmp, inkey, keylen);
|
|
||||||
|
|
||||||
err = crypto_hash_digest(&desc, &tmp, keylen, digest);
|
err = crypto_hash_init(&desc);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
tmplen = bs * 2 + ds;
|
||||||
|
sg_init_one(&tmp, ipad, tmplen);
|
||||||
|
|
||||||
|
for (; keylen > tmplen; inkey += tmplen, keylen -= tmplen) {
|
||||||
|
memcpy(ipad, inkey, tmplen);
|
||||||
|
err = crypto_hash_update(&desc, &tmp, tmplen);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keylen) {
|
||||||
|
memcpy(ipad, inkey, keylen);
|
||||||
|
err = crypto_hash_update(&desc, &tmp, keylen);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = crypto_hash_final(&desc, digest);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue