1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <linux/crypto.h>
15#include <linux/mm.h>
16#include <linux/errno.h>
17#include <linux/highmem.h>
18#include <asm/scatterlist.h>
19#include "internal.h"
20
21static void init(struct crypto_tfm *tfm)
22{
23 tfm->__crt_alg->cra_digest.dia_init(crypto_tfm_ctx(tfm));
24}
25
26static void update(struct crypto_tfm *tfm,
27 struct scatterlist *sg, unsigned int nsg)
28{
29 unsigned int i;
30
31 for (i = 0; i < nsg; i++) {
32
33 struct page *pg = sg[i].page;
34 unsigned int offset = sg[i].offset;
35 unsigned int l = sg[i].length;
36
37 do {
38 unsigned int bytes_from_page = min(l, ((unsigned int)
39 (PAGE_SIZE)) -
40 offset);
41 char *p = crypto_kmap(pg, 0) + offset;
42
43 tfm->__crt_alg->cra_digest.dia_update
44 (crypto_tfm_ctx(tfm), p,
45 bytes_from_page);
46 crypto_kunmap(p, 0);
47 crypto_yield(tfm);
48 offset = 0;
49 pg++;
50 l -= bytes_from_page;
51 } while (l > 0);
52 }
53}
54
55static void update_kernel(struct crypto_tfm *tfm,
56 const void *data, size_t count)
57{
58 tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm), data, count);
59 crypto_yield(tfm);
60}
61
62static void final(struct crypto_tfm *tfm, u8 *out)
63{
64 tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out);
65}
66
67static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
68{
69 u32 flags;
70 if (tfm->__crt_alg->cra_digest.dia_setkey == NULL)
71 return -ENOSYS;
72 return tfm->__crt_alg->cra_digest.dia_setkey(crypto_tfm_ctx(tfm),
73 key, keylen, &flags);
74}
75
76static void digest(struct crypto_tfm *tfm,
77 struct scatterlist *sg, unsigned int nsg, u8 *out)
78{
79 unsigned int i;
80
81 tfm->crt_digest.dit_init(tfm);
82
83 for (i = 0; i < nsg; i++) {
84 char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset;
85 tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm),
86 p, sg[i].length);
87 crypto_kunmap(p, 0);
88 crypto_yield(tfm);
89 }
90 crypto_digest_final(tfm, out);
91}
92
93int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags)
94{
95 return flags ? -EINVAL : 0;
96}
97
98int crypto_init_digest_ops(struct crypto_tfm *tfm)
99{
100 struct digest_tfm *ops = &tfm->crt_digest;
101
102 ops->dit_init = init;
103 ops->dit_update = update;
104 ops->dit_update_kernel = update_kernel;
105 ops->dit_final = final;
106 ops->dit_digest = digest;
107 ops->dit_setkey = setkey;
108
109 return crypto_alloc_hmac_block(tfm);
110}
111
112void crypto_exit_digest_ops(struct crypto_tfm *tfm)
113{
114 crypto_free_hmac_block(tfm);
115}
116