aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/crc32c.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2008-07-08 08:54:28 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2008-07-10 08:35:18 -0400
commit5773a3e6e396d5fd9de58372abe6a86b7e258e3e (patch)
tree8c8576fdc279e95d16ed4dfd332b6380285027bf /crypto/crc32c.c
parent20036252fc61c624a49770fb89684ea5cfdfa05e (diff)
crypto: crc32c - Add ahash implementation
This patch reimplements crc32c using the ahash interface. This allows one tfm to be used by an unlimited number of users provided that they all use the same key (which all current crc32c users do). Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/crc32c.c')
-rw-r--r--crypto/crc32c.c128
1 files changed, 121 insertions, 7 deletions
diff --git a/crypto/crc32c.c b/crypto/crc32c.c
index 0dcf64a74e68..a882d9e4e63e 100644
--- a/crypto/crc32c.c
+++ b/crypto/crc32c.c
@@ -5,20 +5,23 @@
5 * 5 *
6 * This module file is a wrapper to invoke the lib/crc32c routines. 6 * This module file is a wrapper to invoke the lib/crc32c routines.
7 * 7 *
8 * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
9 *
8 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free 11 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option) 12 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version. 13 * any later version.
12 * 14 *
13 */ 15 */
16
17#include <crypto/internal/hash.h>
14#include <linux/init.h> 18#include <linux/init.h>
15#include <linux/module.h> 19#include <linux/module.h>
16#include <linux/string.h> 20#include <linux/string.h>
17#include <linux/crypto.h>
18#include <linux/crc32c.h> 21#include <linux/crc32c.h>
19#include <linux/kernel.h> 22#include <linux/kernel.h>
20 23
21#define CHKSUM_BLOCK_SIZE 32 24#define CHKSUM_BLOCK_SIZE 1
22#define CHKSUM_DIGEST_SIZE 4 25#define CHKSUM_DIGEST_SIZE 4
23 26
24struct chksum_ctx { 27struct chksum_ctx {
@@ -71,7 +74,7 @@ static void chksum_final(struct crypto_tfm *tfm, u8 *out)
71 *(__le32 *)out = ~cpu_to_le32(mctx->crc); 74 *(__le32 *)out = ~cpu_to_le32(mctx->crc);
72} 75}
73 76
74static int crc32c_cra_init(struct crypto_tfm *tfm) 77static int crc32c_cra_init_old(struct crypto_tfm *tfm)
75{ 78{
76 struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); 79 struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
77 80
@@ -79,14 +82,14 @@ static int crc32c_cra_init(struct crypto_tfm *tfm)
79 return 0; 82 return 0;
80} 83}
81 84
82static struct crypto_alg alg = { 85static struct crypto_alg old_alg = {
83 .cra_name = "crc32c", 86 .cra_name = "crc32c",
84 .cra_flags = CRYPTO_ALG_TYPE_DIGEST, 87 .cra_flags = CRYPTO_ALG_TYPE_DIGEST,
85 .cra_blocksize = CHKSUM_BLOCK_SIZE, 88 .cra_blocksize = CHKSUM_BLOCK_SIZE,
86 .cra_ctxsize = sizeof(struct chksum_ctx), 89 .cra_ctxsize = sizeof(struct chksum_ctx),
87 .cra_module = THIS_MODULE, 90 .cra_module = THIS_MODULE,
88 .cra_list = LIST_HEAD_INIT(alg.cra_list), 91 .cra_list = LIST_HEAD_INIT(old_alg.cra_list),
89 .cra_init = crc32c_cra_init, 92 .cra_init = crc32c_cra_init_old,
90 .cra_u = { 93 .cra_u = {
91 .digest = { 94 .digest = {
92 .dia_digestsize= CHKSUM_DIGEST_SIZE, 95 .dia_digestsize= CHKSUM_DIGEST_SIZE,
@@ -98,14 +101,125 @@ static struct crypto_alg alg = {
98 } 101 }
99}; 102};
100 103
104/*
105 * Setting the seed allows arbitrary accumulators and flexible XOR policy
106 * If your algorithm starts with ~0, then XOR with ~0 before you set
107 * the seed.
108 */
109static int crc32c_setkey(struct crypto_ahash *hash, const u8 *key,
110 unsigned int keylen)
111{
112 u32 *mctx = crypto_ahash_ctx(hash);
113
114 if (keylen != sizeof(u32)) {
115 crypto_ahash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
116 return -EINVAL;
117 }
118 *mctx = le32_to_cpup((__le32 *)key);
119 return 0;
120}
121
122static int crc32c_init(struct ahash_request *req)
123{
124 u32 *mctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
125 u32 *crcp = ahash_request_ctx(req);
126
127 *crcp = *mctx;
128 return 0;
129}
130
131static int crc32c_update(struct ahash_request *req)
132{
133 struct crypto_hash_walk walk;
134 u32 *crcp = ahash_request_ctx(req);
135 u32 crc = *crcp;
136 int nbytes;
137
138 for (nbytes = crypto_hash_walk_first(req, &walk); nbytes;
139 nbytes = crypto_hash_walk_done(&walk, 0))
140 crc = crc32c(crc, walk.data, nbytes);
141
142 *crcp = crc;
143 return 0;
144}
145
146static int crc32c_final(struct ahash_request *req)
147{
148 u32 *crcp = ahash_request_ctx(req);
149
150 *(__le32 *)req->result = ~cpu_to_le32p(crcp);
151 return 0;
152}
153
154static int crc32c_digest(struct ahash_request *req)
155{
156 struct crypto_hash_walk walk;
157 u32 *mctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
158 u32 crc = *mctx;
159 int nbytes;
160
161 for (nbytes = crypto_hash_walk_first(req, &walk); nbytes;
162 nbytes = crypto_hash_walk_done(&walk, 0))
163 crc = crc32c(crc, walk.data, nbytes);
164
165 *(__le32 *)req->result = ~cpu_to_le32(crc);
166 return 0;
167}
168
169static int crc32c_cra_init(struct crypto_tfm *tfm)
170{
171 u32 *key = crypto_tfm_ctx(tfm);
172
173 *key = ~0;
174
175 tfm->crt_ahash.reqsize = sizeof(u32);
176
177 return 0;
178}
179
180static struct crypto_alg alg = {
181 .cra_name = "crc32c",
182 .cra_driver_name = "crc32c-generic",
183 .cra_priority = 100,
184 .cra_flags = CRYPTO_ALG_TYPE_AHASH,
185 .cra_blocksize = CHKSUM_BLOCK_SIZE,
186 .cra_alignmask = 3,
187 .cra_ctxsize = sizeof(u32),
188 .cra_module = THIS_MODULE,
189 .cra_list = LIST_HEAD_INIT(alg.cra_list),
190 .cra_init = crc32c_cra_init,
191 .cra_type = &crypto_ahash_type,
192 .cra_u = {
193 .ahash = {
194 .digestsize = CHKSUM_DIGEST_SIZE,
195 .setkey = crc32c_setkey,
196 .init = crc32c_init,
197 .update = crc32c_update,
198 .final = crc32c_final,
199 .digest = crc32c_digest,
200 }
201 }
202};
203
101static int __init crc32c_mod_init(void) 204static int __init crc32c_mod_init(void)
102{ 205{
103 return crypto_register_alg(&alg); 206 int err;
207
208 err = crypto_register_alg(&old_alg);
209 if (err)
210 return err;
211
212 err = crypto_register_alg(&alg);
213 if (err)
214 crypto_unregister_alg(&old_alg);
215
216 return err;
104} 217}
105 218
106static void __exit crc32c_mod_fini(void) 219static void __exit crc32c_mod_fini(void)
107{ 220{
108 crypto_unregister_alg(&alg); 221 crypto_unregister_alg(&alg);
222 crypto_unregister_alg(&old_alg);
109} 223}
110 224
111module_init(crc32c_mod_init); 225module_init(crc32c_mod_init);