4 * HMAC: Keyed-Hashing for Message Authentication (RFC2104).
6 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
8 * The HMAC implementation is derived from USAGI.
9 * Copyright (c) 2002 Kazunori Miyazawa <miyazawa@linux-ipv6.org> / USAGI
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the Free
13 * Software Foundation; either version 2 of the License, or (at your option)
17 #include <linux/crypto.h>
19 #include <linux/highmem.h>
20 #include <asm/scatterlist.h>
23 static void hash_key(struct crypto_tfm *tfm, u8 *key, unsigned int keylen)
25 struct scatterlist tmp;
27 tmp.page = virt_to_page(key);
28 tmp.offset = ((long)key & ~PAGE_MASK);
30 crypto_digest_digest(tfm, &tmp, 1, key);
34 void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen)
37 struct scatterlist tmp;
38 char *ipad = tfm->crt_work_block;
40 if (*keylen > crypto_tfm_alg_blocksize(tfm)) {
41 hash_key(tfm, key, *keylen);
42 *keylen = crypto_tfm_alg_digestsize(tfm);
45 memset(ipad, 0, crypto_tfm_alg_blocksize(tfm) + 1);
46 memcpy(ipad, key, *keylen);
48 for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++)
51 tmp.page = virt_to_page(ipad);
52 tmp.offset = ((long)ipad & ~PAGE_MASK);
53 tmp.length = crypto_tfm_alg_blocksize(tfm);
55 crypto_digest_init(tfm);
56 crypto_digest_update(tfm, &tmp, 1);
59 void crypto_hmac_update(struct crypto_tfm *tfm,
60 struct scatterlist *sg, unsigned int nsg)
62 crypto_digest_update(tfm, sg, nsg);
65 void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key,
66 unsigned int *keylen, u8 *out)
69 struct scatterlist tmp;
70 char *opad = tfm->crt_work_block;
72 if (*keylen > crypto_tfm_alg_blocksize(tfm)) {
73 hash_key(tfm, key, *keylen);
74 *keylen = crypto_tfm_alg_digestsize(tfm);
77 crypto_digest_final(tfm, out);
79 memset(opad, 0, crypto_tfm_alg_blocksize(tfm) + 1);
80 memcpy(opad, key, *keylen);
82 for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++)
85 tmp.page = virt_to_page(opad);
86 tmp.offset = ((long)opad & ~PAGE_MASK);
87 tmp.length = crypto_tfm_alg_blocksize(tfm);
89 crypto_digest_init(tfm);
90 crypto_digest_update(tfm, &tmp, 1);
92 tmp.page = virt_to_page(out);
93 tmp.offset = ((long)out & ~PAGE_MASK);
94 tmp.length = crypto_tfm_alg_digestsize(tfm);
96 crypto_digest_update(tfm, &tmp, 1);
97 crypto_digest_final(tfm, out);
100 void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen,
101 struct scatterlist *sg, unsigned int nsg, u8 *out)
103 crypto_hmac_init(tfm, key, keylen);
104 crypto_hmac_update(tfm, sg, nsg);
105 crypto_hmac_final(tfm, key, keylen, out);
108 EXPORT_SYMBOL_GPL(crypto_hmac_init);
109 EXPORT_SYMBOL_GPL(crypto_hmac_update);
110 EXPORT_SYMBOL_GPL(crypto_hmac_final);
111 EXPORT_SYMBOL_GPL(crypto_hmac);