aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2006-08-19 08:24:23 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2006-09-20 21:46:17 -0400
commit055bcee3102dc35f019b69df9c2618e9d6dd1c09 (patch)
tree3f7c68abbbb5041d570e4cb8588f3943530bc0b7
parent7226bc877a22244e8003924031435a4bffd52654 (diff)
[CRYPTO] digest: Added user API for new hash type
The existing digest user interface is inadequate for support asynchronous operations. For one it doesn't return a value to indicate success or failure, nor does it take a per-operation descriptor which is essential for the issuing of requests while other requests are still outstanding. This patch is the first in a series of steps to remodel the interface for asynchronous operations. For the ease of transition the new interface will be known as "hash" while the old one will remain as "digest". This patch also changes sg_next to allow chaining. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--crypto/Kconfig4
-rw-r--r--crypto/Makefile3
-rw-r--r--crypto/digest.c129
-rw-r--r--crypto/hash.c61
-rw-r--r--crypto/hmac.c12
-rw-r--r--crypto/scatterwalk.h4
-rw-r--r--include/crypto/algapi.h6
-rw-r--r--include/linux/crypto.h172
8 files changed, 321 insertions, 70 deletions
diff --git a/crypto/Kconfig b/crypto/Kconfig
index be5eb0cb7c30..69c5f992bcd4 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -20,6 +20,10 @@ config CRYPTO_BLKCIPHER
20 tristate 20 tristate
21 select CRYPTO_ALGAPI 21 select CRYPTO_ALGAPI
22 22
23config CRYPTO_HASH
24 tristate
25 select CRYPTO_ALGAPI
26
23config CRYPTO_MANAGER 27config CRYPTO_MANAGER
24 tristate "Cryptographic algorithm manager" 28 tristate "Cryptographic algorithm manager"
25 select CRYPTO_ALGAPI 29 select CRYPTO_ALGAPI
diff --git a/crypto/Makefile b/crypto/Makefile
index 5e1ff4e0b1fc..72366208e291 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -10,6 +10,9 @@ obj-$(CONFIG_CRYPTO_ALGAPI) += crypto_algapi.o
10 10
11obj-$(CONFIG_CRYPTO_BLKCIPHER) += blkcipher.o 11obj-$(CONFIG_CRYPTO_BLKCIPHER) += blkcipher.o
12 12
13crypto_hash-objs := hash.o
14obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o
15
13obj-$(CONFIG_CRYPTO_MANAGER) += cryptomgr.o 16obj-$(CONFIG_CRYPTO_MANAGER) += cryptomgr.o
14obj-$(CONFIG_CRYPTO_HMAC) += hmac.o 17obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
15obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o 18obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o
diff --git a/crypto/digest.c b/crypto/digest.c
index 96244a528844..5873063db840 100644
--- a/crypto/digest.c
+++ b/crypto/digest.c
@@ -11,29 +11,89 @@
11 * any later version. 11 * any later version.
12 * 12 *
13 */ 13 */
14#include <linux/crypto.h> 14
15#include <linux/mm.h> 15#include <linux/mm.h>
16#include <linux/errno.h> 16#include <linux/errno.h>
17#include <linux/highmem.h> 17#include <linux/highmem.h>
18#include <asm/scatterlist.h> 18#include <linux/module.h>
19#include <linux/scatterlist.h>
20
19#include "internal.h" 21#include "internal.h"
22#include "scatterwalk.h"
20 23
21static void init(struct crypto_tfm *tfm) 24void crypto_digest_init(struct crypto_tfm *tfm)
22{ 25{
23 tfm->__crt_alg->cra_digest.dia_init(tfm); 26 struct crypto_hash *hash = crypto_hash_cast(tfm);
27 struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags };
28
29 crypto_hash_init(&desc);
24} 30}
31EXPORT_SYMBOL_GPL(crypto_digest_init);
25 32
26static void update(struct crypto_tfm *tfm, 33void crypto_digest_update(struct crypto_tfm *tfm,
27 struct scatterlist *sg, unsigned int nsg) 34 struct scatterlist *sg, unsigned int nsg)
28{ 35{
36 struct crypto_hash *hash = crypto_hash_cast(tfm);
37 struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags };
38 unsigned int nbytes = 0;
29 unsigned int i; 39 unsigned int i;
40
41 for (i = 0; i < nsg; i++)
42 nbytes += sg[i].length;
43
44 crypto_hash_update(&desc, sg, nbytes);
45}
46EXPORT_SYMBOL_GPL(crypto_digest_update);
47
48void crypto_digest_final(struct crypto_tfm *tfm, u8 *out)
49{
50 struct crypto_hash *hash = crypto_hash_cast(tfm);
51 struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags };
52
53 crypto_hash_final(&desc, out);
54}
55EXPORT_SYMBOL_GPL(crypto_digest_final);
56
57void crypto_digest_digest(struct crypto_tfm *tfm,
58 struct scatterlist *sg, unsigned int nsg, u8 *out)
59{
60 struct crypto_hash *hash = crypto_hash_cast(tfm);
61 struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags };
62 unsigned int nbytes = 0;
63 unsigned int i;
64
65 for (i = 0; i < nsg; i++)
66 nbytes += sg[i].length;
67
68 crypto_hash_digest(&desc, sg, nbytes, out);
69}
70EXPORT_SYMBOL_GPL(crypto_digest_digest);
71
72static int init(struct hash_desc *desc)
73{
74 struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
75
76 tfm->__crt_alg->cra_digest.dia_init(tfm);
77 return 0;
78}
79
80static int update(struct hash_desc *desc,
81 struct scatterlist *sg, unsigned int nbytes)
82{
83 struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
30 unsigned int alignmask = crypto_tfm_alg_alignmask(tfm); 84 unsigned int alignmask = crypto_tfm_alg_alignmask(tfm);
31 85
32 for (i = 0; i < nsg; i++) { 86 if (!nbytes)
87 return 0;
88
89 for (;;) {
90 struct page *pg = sg->page;
91 unsigned int offset = sg->offset;
92 unsigned int l = sg->length;
33 93
34 struct page *pg = sg[i].page; 94 if (unlikely(l > nbytes))
35 unsigned int offset = sg[i].offset; 95 l = nbytes;
36 unsigned int l = sg[i].length; 96 nbytes -= l;
37 97
38 do { 98 do {
39 unsigned int bytes_from_page = min(l, ((unsigned int) 99 unsigned int bytes_from_page = min(l, ((unsigned int)
@@ -55,16 +115,23 @@ static void update(struct crypto_tfm *tfm,
55 tfm->__crt_alg->cra_digest.dia_update(tfm, p, 115 tfm->__crt_alg->cra_digest.dia_update(tfm, p,
56 bytes_from_page); 116 bytes_from_page);
57 crypto_kunmap(src, 0); 117 crypto_kunmap(src, 0);
58 crypto_yield(tfm->crt_flags); 118 crypto_yield(desc->flags);
59 offset = 0; 119 offset = 0;
60 pg++; 120 pg++;
61 l -= bytes_from_page; 121 l -= bytes_from_page;
62 } while (l > 0); 122 } while (l > 0);
123
124 if (!nbytes)
125 break;
126 sg = sg_next(sg);
63 } 127 }
128
129 return 0;
64} 130}
65 131
66static void final(struct crypto_tfm *tfm, u8 *out) 132static int final(struct hash_desc *desc, u8 *out)
67{ 133{
134 struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
68 unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); 135 unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
69 struct digest_alg *digest = &tfm->__crt_alg->cra_digest; 136 struct digest_alg *digest = &tfm->__crt_alg->cra_digest;
70 137
@@ -78,26 +145,30 @@ static void final(struct crypto_tfm *tfm, u8 *out)
78 memcpy(out, dst, digest->dia_digestsize); 145 memcpy(out, dst, digest->dia_digestsize);
79 } else 146 } else
80 digest->dia_final(tfm, out); 147 digest->dia_final(tfm, out);
148
149 return 0;
81} 150}
82 151
83static int nosetkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) 152static int nosetkey(struct crypto_hash *tfm, const u8 *key, unsigned int keylen)
84{ 153{
85 tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK; 154 crypto_hash_clear_flags(tfm, CRYPTO_TFM_RES_MASK);
86 return -ENOSYS; 155 return -ENOSYS;
87} 156}
88 157
89static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) 158static int setkey(struct crypto_hash *hash, const u8 *key, unsigned int keylen)
90{ 159{
91 tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK; 160 struct crypto_tfm *tfm = crypto_hash_tfm(hash);
161
162 crypto_hash_clear_flags(hash, CRYPTO_TFM_RES_MASK);
92 return tfm->__crt_alg->cra_digest.dia_setkey(tfm, key, keylen); 163 return tfm->__crt_alg->cra_digest.dia_setkey(tfm, key, keylen);
93} 164}
94 165
95static void digest(struct crypto_tfm *tfm, 166static int digest(struct hash_desc *desc,
96 struct scatterlist *sg, unsigned int nsg, u8 *out) 167 struct scatterlist *sg, unsigned int nbytes, u8 *out)
97{ 168{
98 init(tfm); 169 init(desc);
99 update(tfm, sg, nsg); 170 update(desc, sg, nbytes);
100 final(tfm, out); 171 return final(desc, out);
101} 172}
102 173
103int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags) 174int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags)
@@ -107,14 +178,18 @@ int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags)
107 178
108int crypto_init_digest_ops(struct crypto_tfm *tfm) 179int crypto_init_digest_ops(struct crypto_tfm *tfm)
109{ 180{
110 struct digest_tfm *ops = &tfm->crt_digest; 181 struct hash_tfm *ops = &tfm->crt_hash;
111 struct digest_alg *dalg = &tfm->__crt_alg->cra_digest; 182 struct digest_alg *dalg = &tfm->__crt_alg->cra_digest;
183
184 if (dalg->dia_digestsize > crypto_tfm_alg_blocksize(tfm))
185 return -EINVAL;
112 186
113 ops->dit_init = init; 187 ops->init = init;
114 ops->dit_update = update; 188 ops->update = update;
115 ops->dit_final = final; 189 ops->final = final;
116 ops->dit_digest = digest; 190 ops->digest = digest;
117 ops->dit_setkey = dalg->dia_setkey ? setkey : nosetkey; 191 ops->setkey = dalg->dia_setkey ? setkey : nosetkey;
192 ops->digestsize = dalg->dia_digestsize;
118 193
119 return crypto_alloc_hmac_block(tfm); 194 return crypto_alloc_hmac_block(tfm);
120} 195}
diff --git a/crypto/hash.c b/crypto/hash.c
new file mode 100644
index 000000000000..cdec23d885fe
--- /dev/null
+++ b/crypto/hash.c
@@ -0,0 +1,61 @@
1/*
2 * Cryptographic Hash operations.
3 *
4 * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 */
11
12#include <linux/errno.h>
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/seq_file.h>
16
17#include "internal.h"
18
19static unsigned int crypto_hash_ctxsize(struct crypto_alg *alg)
20{
21 return alg->cra_ctxsize;
22}
23
24static int crypto_init_hash_ops(struct crypto_tfm *tfm)
25{
26 struct hash_tfm *crt = &tfm->crt_hash;
27 struct hash_alg *alg = &tfm->__crt_alg->cra_hash;
28
29 if (alg->digestsize > crypto_tfm_alg_blocksize(tfm))
30 return -EINVAL;
31
32 crt->init = alg->init;
33 crt->update = alg->update;
34 crt->final = alg->final;
35 crt->digest = alg->digest;
36 crt->setkey = alg->setkey;
37 crt->digestsize = alg->digestsize;
38
39 return 0;
40}
41
42static void crypto_hash_show(struct seq_file *m, struct crypto_alg *alg)
43 __attribute_used__;
44static void crypto_hash_show(struct seq_file *m, struct crypto_alg *alg)
45{
46 seq_printf(m, "type : hash\n");
47 seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
48 seq_printf(m, "digestsize : %u\n", alg->cra_hash.digestsize);
49}
50
51const struct crypto_type crypto_hash_type = {
52 .ctxsize = crypto_hash_ctxsize,
53 .init = crypto_init_hash_ops,
54#ifdef CONFIG_PROC_FS
55 .show = crypto_hash_show,
56#endif
57};
58EXPORT_SYMBOL_GPL(crypto_hash_type);
59
60MODULE_LICENSE("GPL");
61MODULE_DESCRIPTION("Generic cryptographic hash type");
diff --git a/crypto/hmac.c b/crypto/hmac.c
index 46120dee5ada..ecf7b0a95b56 100644
--- a/crypto/hmac.c
+++ b/crypto/hmac.c
@@ -35,9 +35,9 @@ int crypto_alloc_hmac_block(struct crypto_tfm *tfm)
35 35
36 BUG_ON(!crypto_tfm_alg_blocksize(tfm)); 36 BUG_ON(!crypto_tfm_alg_blocksize(tfm));
37 37
38 tfm->crt_digest.dit_hmac_block = kmalloc(crypto_tfm_alg_blocksize(tfm), 38 tfm->crt_hash.hmac_block = kmalloc(crypto_tfm_alg_blocksize(tfm),
39 GFP_KERNEL); 39 GFP_KERNEL);
40 if (tfm->crt_digest.dit_hmac_block == NULL) 40 if (tfm->crt_hash.hmac_block == NULL)
41 ret = -ENOMEM; 41 ret = -ENOMEM;
42 42
43 return ret; 43 return ret;
@@ -46,14 +46,14 @@ int crypto_alloc_hmac_block(struct crypto_tfm *tfm)
46 46
47void crypto_free_hmac_block(struct crypto_tfm *tfm) 47void crypto_free_hmac_block(struct crypto_tfm *tfm)
48{ 48{
49 kfree(tfm->crt_digest.dit_hmac_block); 49 kfree(tfm->crt_hash.hmac_block);
50} 50}
51 51
52void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen) 52void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen)
53{ 53{
54 unsigned int i; 54 unsigned int i;
55 struct scatterlist tmp; 55 struct scatterlist tmp;
56 char *ipad = tfm->crt_digest.dit_hmac_block; 56 char *ipad = tfm->crt_hash.hmac_block;
57 57
58 if (*keylen > crypto_tfm_alg_blocksize(tfm)) { 58 if (*keylen > crypto_tfm_alg_blocksize(tfm)) {
59 hash_key(tfm, key, *keylen); 59 hash_key(tfm, key, *keylen);
@@ -83,7 +83,7 @@ void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key,
83{ 83{
84 unsigned int i; 84 unsigned int i;
85 struct scatterlist tmp; 85 struct scatterlist tmp;
86 char *opad = tfm->crt_digest.dit_hmac_block; 86 char *opad = tfm->crt_hash.hmac_block;
87 87
88 if (*keylen > crypto_tfm_alg_blocksize(tfm)) { 88 if (*keylen > crypto_tfm_alg_blocksize(tfm)) {
89 hash_key(tfm, key, *keylen); 89 hash_key(tfm, key, *keylen);
diff --git a/crypto/scatterwalk.h b/crypto/scatterwalk.h
index ace595a2e119..f1592cc2d0f4 100644
--- a/crypto/scatterwalk.h
+++ b/crypto/scatterwalk.h
@@ -20,11 +20,9 @@
20 20
21#include "internal.h" 21#include "internal.h"
22 22
23/* Define sg_next is an inline routine now in case we want to change
24 scatterlist to a linked list later. */
25static inline struct scatterlist *sg_next(struct scatterlist *sg) 23static inline struct scatterlist *sg_next(struct scatterlist *sg)
26{ 24{
27 return sg + 1; 25 return (++sg)->length ? sg : (void *)sg->page;
28} 26}
29 27
30static inline unsigned long scatterwalk_samebuf(struct scatter_walk *walk_in, 28static inline unsigned long scatterwalk_samebuf(struct scatter_walk *walk_in,
diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
index 444f602724db..5748aecdb414 100644
--- a/include/crypto/algapi.h
+++ b/include/crypto/algapi.h
@@ -82,6 +82,7 @@ struct blkcipher_walk {
82}; 82};
83 83
84extern const struct crypto_type crypto_blkcipher_type; 84extern const struct crypto_type crypto_blkcipher_type;
85extern const struct crypto_type crypto_hash_type;
85 86
86void crypto_mod_put(struct crypto_alg *alg); 87void crypto_mod_put(struct crypto_alg *alg);
87 88
@@ -136,6 +137,11 @@ static inline struct cipher_alg *crypto_cipher_alg(struct crypto_cipher *tfm)
136 return &crypto_cipher_tfm(tfm)->__crt_alg->cra_cipher; 137 return &crypto_cipher_tfm(tfm)->__crt_alg->cra_cipher;
137} 138}
138 139
140static inline void *crypto_hash_ctx_aligned(struct crypto_hash *tfm)
141{
142 return crypto_tfm_ctx_aligned(&tfm->base);
143}
144
139static inline void blkcipher_walk_init(struct blkcipher_walk *walk, 145static inline void blkcipher_walk_init(struct blkcipher_walk *walk,
140 struct scatterlist *dst, 146 struct scatterlist *dst,
141 struct scatterlist *src, 147 struct scatterlist *src,
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 0be666b50463..40c0aab8ad4c 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -31,8 +31,11 @@
31#define CRYPTO_ALG_TYPE_MASK 0x0000000f 31#define CRYPTO_ALG_TYPE_MASK 0x0000000f
32#define CRYPTO_ALG_TYPE_CIPHER 0x00000001 32#define CRYPTO_ALG_TYPE_CIPHER 0x00000001
33#define CRYPTO_ALG_TYPE_DIGEST 0x00000002 33#define CRYPTO_ALG_TYPE_DIGEST 0x00000002
34#define CRYPTO_ALG_TYPE_BLKCIPHER 0x00000003 34#define CRYPTO_ALG_TYPE_HASH 0x00000003
35#define CRYPTO_ALG_TYPE_COMPRESS 0x00000004 35#define CRYPTO_ALG_TYPE_BLKCIPHER 0x00000004
36#define CRYPTO_ALG_TYPE_COMPRESS 0x00000005
37
38#define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e
36 39
37#define CRYPTO_ALG_LARVAL 0x00000010 40#define CRYPTO_ALG_LARVAL 0x00000010
38#define CRYPTO_ALG_DEAD 0x00000020 41#define CRYPTO_ALG_DEAD 0x00000020
@@ -90,6 +93,7 @@
90 93
91struct scatterlist; 94struct scatterlist;
92struct crypto_blkcipher; 95struct crypto_blkcipher;
96struct crypto_hash;
93struct crypto_tfm; 97struct crypto_tfm;
94struct crypto_type; 98struct crypto_type;
95 99
@@ -107,6 +111,11 @@ struct cipher_desc {
107 void *info; 111 void *info;
108}; 112};
109 113
114struct hash_desc {
115 struct crypto_hash *tfm;
116 u32 flags;
117};
118
110/* 119/*
111 * Algorithms: modular crypto algorithm implementations, managed 120 * Algorithms: modular crypto algorithm implementations, managed
112 * via crypto_register_alg() and crypto_unregister_alg(). 121 * via crypto_register_alg() and crypto_unregister_alg().
@@ -158,6 +167,19 @@ struct digest_alg {
158 unsigned int keylen); 167 unsigned int keylen);
159}; 168};
160 169
170struct hash_alg {
171 int (*init)(struct hash_desc *desc);
172 int (*update)(struct hash_desc *desc, struct scatterlist *sg,
173 unsigned int nbytes);
174 int (*final)(struct hash_desc *desc, u8 *out);
175 int (*digest)(struct hash_desc *desc, struct scatterlist *sg,
176 unsigned int nbytes, u8 *out);
177 int (*setkey)(struct crypto_hash *tfm, const u8 *key,
178 unsigned int keylen);
179
180 unsigned int digestsize;
181};
182
161struct compress_alg { 183struct compress_alg {
162 int (*coa_compress)(struct crypto_tfm *tfm, const u8 *src, 184 int (*coa_compress)(struct crypto_tfm *tfm, const u8 *src,
163 unsigned int slen, u8 *dst, unsigned int *dlen); 185 unsigned int slen, u8 *dst, unsigned int *dlen);
@@ -168,6 +190,7 @@ struct compress_alg {
168#define cra_blkcipher cra_u.blkcipher 190#define cra_blkcipher cra_u.blkcipher
169#define cra_cipher cra_u.cipher 191#define cra_cipher cra_u.cipher
170#define cra_digest cra_u.digest 192#define cra_digest cra_u.digest
193#define cra_hash cra_u.hash
171#define cra_compress cra_u.compress 194#define cra_compress cra_u.compress
172 195
173struct crypto_alg { 196struct crypto_alg {
@@ -191,6 +214,7 @@ struct crypto_alg {
191 struct blkcipher_alg blkcipher; 214 struct blkcipher_alg blkcipher;
192 struct cipher_alg cipher; 215 struct cipher_alg cipher;
193 struct digest_alg digest; 216 struct digest_alg digest;
217 struct hash_alg hash;
194 struct compress_alg compress; 218 struct compress_alg compress;
195 } cra_u; 219 } cra_u;
196 220
@@ -262,18 +286,19 @@ struct cipher_tfm {
262 void (*cit_decrypt_one)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); 286 void (*cit_decrypt_one)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
263}; 287};
264 288
265struct digest_tfm { 289struct hash_tfm {
266 void (*dit_init)(struct crypto_tfm *tfm); 290 int (*init)(struct hash_desc *desc);
267 void (*dit_update)(struct crypto_tfm *tfm, 291 int (*update)(struct hash_desc *desc,
268 struct scatterlist *sg, unsigned int nsg); 292 struct scatterlist *sg, unsigned int nsg);
269 void (*dit_final)(struct crypto_tfm *tfm, u8 *out); 293 int (*final)(struct hash_desc *desc, u8 *out);
270 void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg, 294 int (*digest)(struct hash_desc *desc, struct scatterlist *sg,
271 unsigned int nsg, u8 *out); 295 unsigned int nsg, u8 *out);
272 int (*dit_setkey)(struct crypto_tfm *tfm, 296 int (*setkey)(struct crypto_hash *tfm, const u8 *key,
273 const u8 *key, unsigned int keylen); 297 unsigned int keylen);
274#ifdef CONFIG_CRYPTO_HMAC 298#ifdef CONFIG_CRYPTO_HMAC
275 void *dit_hmac_block; 299 void *hmac_block;
276#endif 300#endif
301 unsigned int digestsize;
277}; 302};
278 303
279struct compress_tfm { 304struct compress_tfm {
@@ -287,7 +312,7 @@ struct compress_tfm {
287 312
288#define crt_blkcipher crt_u.blkcipher 313#define crt_blkcipher crt_u.blkcipher
289#define crt_cipher crt_u.cipher 314#define crt_cipher crt_u.cipher
290#define crt_digest crt_u.digest 315#define crt_hash crt_u.hash
291#define crt_compress crt_u.compress 316#define crt_compress crt_u.compress
292 317
293struct crypto_tfm { 318struct crypto_tfm {
@@ -297,7 +322,7 @@ struct crypto_tfm {
297 union { 322 union {
298 struct blkcipher_tfm blkcipher; 323 struct blkcipher_tfm blkcipher;
299 struct cipher_tfm cipher; 324 struct cipher_tfm cipher;
300 struct digest_tfm digest; 325 struct hash_tfm hash;
301 struct compress_tfm compress; 326 struct compress_tfm compress;
302 } crt_u; 327 } crt_u;
303 328
@@ -312,6 +337,10 @@ struct crypto_blkcipher {
312 struct crypto_tfm base; 337 struct crypto_tfm base;
313}; 338};
314 339
340struct crypto_hash {
341 struct crypto_tfm base;
342};
343
315enum { 344enum {
316 CRYPTOA_UNSPEC, 345 CRYPTOA_UNSPEC,
317 CRYPTOA_ALG, 346 CRYPTOA_ALG,
@@ -647,39 +676,114 @@ static inline void crypto_cipher_decrypt_one(struct crypto_cipher *tfm,
647 dst, src); 676 dst, src);
648} 677}
649 678
650static inline void crypto_digest_init(struct crypto_tfm *tfm) 679void crypto_digest_init(struct crypto_tfm *tfm);
680void crypto_digest_update(struct crypto_tfm *tfm,
681 struct scatterlist *sg, unsigned int nsg);
682void crypto_digest_final(struct crypto_tfm *tfm, u8 *out);
683void crypto_digest_digest(struct crypto_tfm *tfm,
684 struct scatterlist *sg, unsigned int nsg, u8 *out);
685
686static inline struct crypto_hash *__crypto_hash_cast(struct crypto_tfm *tfm)
651{ 687{
652 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); 688 return (struct crypto_hash *)tfm;
653 tfm->crt_digest.dit_init(tfm);
654} 689}
655 690
656static inline void crypto_digest_update(struct crypto_tfm *tfm, 691static inline struct crypto_hash *crypto_hash_cast(struct crypto_tfm *tfm)
657 struct scatterlist *sg,
658 unsigned int nsg)
659{ 692{
660 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); 693 BUG_ON((crypto_tfm_alg_type(tfm) ^ CRYPTO_ALG_TYPE_HASH) &
661 tfm->crt_digest.dit_update(tfm, sg, nsg); 694 CRYPTO_ALG_TYPE_HASH_MASK);
695 return __crypto_hash_cast(tfm);
662} 696}
663 697
664static inline void crypto_digest_final(struct crypto_tfm *tfm, u8 *out) 698static inline int crypto_digest_setkey(struct crypto_tfm *tfm,
699 const u8 *key, unsigned int keylen)
665{ 700{
666 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); 701 return tfm->crt_hash.setkey(crypto_hash_cast(tfm), key, keylen);
667 tfm->crt_digest.dit_final(tfm, out);
668} 702}
669 703
670static inline void crypto_digest_digest(struct crypto_tfm *tfm, 704static inline struct crypto_hash *crypto_alloc_hash(const char *alg_name,
671 struct scatterlist *sg, 705 u32 type, u32 mask)
672 unsigned int nsg, u8 *out)
673{ 706{
674 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); 707 type &= ~CRYPTO_ALG_TYPE_MASK;
675 tfm->crt_digest.dit_digest(tfm, sg, nsg, out); 708 type |= CRYPTO_ALG_TYPE_HASH;
709 mask |= CRYPTO_ALG_TYPE_HASH_MASK;
710
711 return __crypto_hash_cast(crypto_alloc_base(alg_name, type, mask));
676} 712}
677 713
678static inline int crypto_digest_setkey(struct crypto_tfm *tfm, 714static inline struct crypto_tfm *crypto_hash_tfm(struct crypto_hash *tfm)
679 const u8 *key, unsigned int keylen)
680{ 715{
681 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); 716 return &tfm->base;
682 return tfm->crt_digest.dit_setkey(tfm, key, keylen); 717}
718
719static inline void crypto_free_hash(struct crypto_hash *tfm)
720{
721 crypto_free_tfm(crypto_hash_tfm(tfm));
722}
723
724static inline struct hash_tfm *crypto_hash_crt(struct crypto_hash *tfm)
725{
726 return &crypto_hash_tfm(tfm)->crt_hash;
727}
728
729static inline unsigned int crypto_hash_blocksize(struct crypto_hash *tfm)
730{
731 return crypto_tfm_alg_blocksize(crypto_hash_tfm(tfm));
732}
733
734static inline unsigned int crypto_hash_alignmask(struct crypto_hash *tfm)
735{
736 return crypto_tfm_alg_alignmask(crypto_hash_tfm(tfm));
737}
738
739static inline unsigned int crypto_hash_digestsize(struct crypto_hash *tfm)
740{
741 return crypto_hash_crt(tfm)->digestsize;
742}
743
744static inline u32 crypto_hash_get_flags(struct crypto_hash *tfm)
745{
746 return crypto_tfm_get_flags(crypto_hash_tfm(tfm));
747}
748
749static inline void crypto_hash_set_flags(struct crypto_hash *tfm, u32 flags)
750{
751 crypto_tfm_set_flags(crypto_hash_tfm(tfm), flags);
752}
753
754static inline void crypto_hash_clear_flags(struct crypto_hash *tfm, u32 flags)
755{
756 crypto_tfm_clear_flags(crypto_hash_tfm(tfm), flags);
757}
758
759static inline int crypto_hash_init(struct hash_desc *desc)
760{
761 return crypto_hash_crt(desc->tfm)->init(desc);
762}
763
764static inline int crypto_hash_update(struct hash_desc *desc,
765 struct scatterlist *sg,
766 unsigned int nbytes)
767{
768 return crypto_hash_crt(desc->tfm)->update(desc, sg, nbytes);
769}
770
771static inline int crypto_hash_final(struct hash_desc *desc, u8 *out)
772{
773 return crypto_hash_crt(desc->tfm)->final(desc, out);
774}
775
776static inline int crypto_hash_digest(struct hash_desc *desc,
777 struct scatterlist *sg,
778 unsigned int nbytes, u8 *out)
779{
780 return crypto_hash_crt(desc->tfm)->digest(desc, sg, nbytes, out);
781}
782
783static inline int crypto_hash_setkey(struct crypto_hash *hash,
784 const u8 *key, unsigned int keylen)
785{
786 return crypto_hash_crt(hash)->setkey(hash, key, keylen);
683} 787}
684 788
685static int crypto_cipher_encrypt(struct crypto_tfm *tfm, 789static int crypto_cipher_encrypt(struct crypto_tfm *tfm,