| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
#include <linux/crypto.h> |
|---|
| 18 |
#include <linux/mm.h> |
|---|
| 19 |
#include <linux/highmem.h> |
|---|
| 20 |
#include <linux/slab.h> |
|---|
| 21 |
#include <asm/scatterlist.h> |
|---|
| 22 |
#include "internal.h" |
|---|
| 23 |
|
|---|
| 24 |
static void hash_key(struct crypto_tfm *tfm, u8 *key, unsigned int keylen) |
|---|
| 25 |
{ |
|---|
| 26 |
struct scatterlist tmp; |
|---|
| 27 |
|
|---|
| 28 |
tmp.page = virt_to_page(key); |
|---|
| 29 |
tmp.offset = offset_in_page(key); |
|---|
| 30 |
tmp.length = keylen; |
|---|
| 31 |
crypto_digest_digest(tfm, &tmp, 1, key); |
|---|
| 32 |
|
|---|
| 33 |
} |
|---|
| 34 |
|
|---|
| 35 |
int crypto_alloc_hmac_block(struct crypto_tfm *tfm) |
|---|
| 36 |
{ |
|---|
| 37 |
int ret = 0; |
|---|
| 38 |
|
|---|
| 39 |
BUG_ON(!crypto_tfm_alg_blocksize(tfm)); |
|---|
| 40 |
|
|---|
| 41 |
tfm->crt_digest.dit_hmac_block = kmalloc(crypto_tfm_alg_blocksize(tfm), |
|---|
| 42 |
GFP_KERNEL); |
|---|
| 43 |
if (tfm->crt_digest.dit_hmac_block == NULL) |
|---|
| 44 |
ret = -ENOMEM; |
|---|
| 45 |
|
|---|
| 46 |
return ret; |
|---|
| 47 |
|
|---|
| 48 |
} |
|---|
| 49 |
|
|---|
| 50 |
void crypto_free_hmac_block(struct crypto_tfm *tfm) |
|---|
| 51 |
{ |
|---|
| 52 |
if (tfm->crt_digest.dit_hmac_block) |
|---|
| 53 |
kfree(tfm->crt_digest.dit_hmac_block); |
|---|
| 54 |
} |
|---|
| 55 |
|
|---|
| 56 |
void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen) |
|---|
| 57 |
{ |
|---|
| 58 |
unsigned int i; |
|---|
| 59 |
struct scatterlist tmp; |
|---|
| 60 |
char *ipad = tfm->crt_digest.dit_hmac_block; |
|---|
| 61 |
|
|---|
| 62 |
if (*keylen > crypto_tfm_alg_blocksize(tfm)) { |
|---|
| 63 |
hash_key(tfm, key, *keylen); |
|---|
| 64 |
*keylen = crypto_tfm_alg_digestsize(tfm); |
|---|
| 65 |
} |
|---|
| 66 |
|
|---|
| 67 |
memset(ipad, 0, crypto_tfm_alg_blocksize(tfm)); |
|---|
| 68 |
memcpy(ipad, key, *keylen); |
|---|
| 69 |
|
|---|
| 70 |
for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++) |
|---|
| 71 |
ipad[i] ^= 0x36; |
|---|
| 72 |
|
|---|
| 73 |
tmp.page = virt_to_page(ipad); |
|---|
| 74 |
tmp.offset = offset_in_page(ipad); |
|---|
| 75 |
tmp.length = crypto_tfm_alg_blocksize(tfm); |
|---|
| 76 |
|
|---|
| 77 |
crypto_digest_init(tfm); |
|---|
| 78 |
crypto_digest_update(tfm, &tmp, 1); |
|---|
| 79 |
} |
|---|
| 80 |
|
|---|
| 81 |
void crypto_hmac_update(struct crypto_tfm *tfm, |
|---|
| 82 |
struct scatterlist *sg, unsigned int nsg) |
|---|
| 83 |
{ |
|---|
| 84 |
crypto_digest_update(tfm, sg, nsg); |
|---|
| 85 |
} |
|---|
| 86 |
|
|---|
| 87 |
void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key, |
|---|
| 88 |
unsigned int *keylen, u8 *out) |
|---|
| 89 |
{ |
|---|
| 90 |
unsigned int i; |
|---|
| 91 |
struct scatterlist tmp; |
|---|
| 92 |
char *opad = tfm->crt_digest.dit_hmac_block; |
|---|
| 93 |
|
|---|
| 94 |
if (*keylen > crypto_tfm_alg_blocksize(tfm)) { |
|---|
| 95 |
hash_key(tfm, key, *keylen); |
|---|
| 96 |
*keylen = crypto_tfm_alg_digestsize(tfm); |
|---|
| 97 |
} |
|---|
| 98 |
|
|---|
| 99 |
crypto_digest_final(tfm, out); |
|---|
| 100 |
|
|---|
| 101 |
memset(opad, 0, crypto_tfm_alg_blocksize(tfm)); |
|---|
| 102 |
memcpy(opad, key, *keylen); |
|---|
| 103 |
|
|---|
| 104 |
for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++) |
|---|
| 105 |
opad[i] ^= 0x5c; |
|---|
| 106 |
|
|---|
| 107 |
tmp.page = virt_to_page(opad); |
|---|
| 108 |
tmp.offset = offset_in_page(opad); |
|---|
| 109 |
tmp.length = crypto_tfm_alg_blocksize(tfm); |
|---|
| 110 |
|
|---|
| 111 |
crypto_digest_init(tfm); |
|---|
| 112 |
crypto_digest_update(tfm, &tmp, 1); |
|---|
| 113 |
|
|---|
| 114 |
tmp.page = virt_to_page(out); |
|---|
| 115 |
tmp.offset = offset_in_page(out); |
|---|
| 116 |
tmp.length = crypto_tfm_alg_digestsize(tfm); |
|---|
| 117 |
|
|---|
| 118 |
crypto_digest_update(tfm, &tmp, 1); |
|---|
| 119 |
crypto_digest_final(tfm, out); |
|---|
| 120 |
} |
|---|
| 121 |
|
|---|
| 122 |
void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen, |
|---|
| 123 |
struct scatterlist *sg, unsigned int nsg, u8 *out) |
|---|
| 124 |
{ |
|---|
| 125 |
crypto_hmac_init(tfm, key, keylen); |
|---|
| 126 |
crypto_hmac_update(tfm, sg, nsg); |
|---|
| 127 |
crypto_hmac_final(tfm, key, keylen, out); |
|---|
| 128 |
} |
|---|
| 129 |
|
|---|
| 130 |
EXPORT_SYMBOL_GPL(crypto_hmac_init); |
|---|
| 131 |
EXPORT_SYMBOL_GPL(crypto_hmac_update); |
|---|
| 132 |
EXPORT_SYMBOL_GPL(crypto_hmac_final); |
|---|
| 133 |
EXPORT_SYMBOL_GPL(crypto_hmac); |
|---|
| 134 |
|
|---|