6 * This module file is a wrapper to invoke the lib/crc32c routines.
8 * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the Free
12 * Software Foundation; either version 2 of the License, or (at your option)
17 #include <crypto/internal/hash.h>
18 #include <linux/init.h>
19 #include <linux/module.h>
20 #include <linux/string.h>
21 #include <linux/crc32c.h>
22 #include <linux/kernel.h>
24 #define CHKSUM_BLOCK_SIZE 1
25 #define CHKSUM_DIGEST_SIZE 4
33 * Steps through buffer one byte at at time, calculates reflected
37 static void chksum_init(struct crypto_tfm
*tfm
)
39 struct chksum_ctx
*mctx
= crypto_tfm_ctx(tfm
);
41 mctx
->crc
= mctx
->key
;
45 * Setting the seed allows arbitrary accumulators and flexible XOR policy
46 * If your algorithm starts with ~0, then XOR with ~0 before you set
49 static int chksum_setkey(struct crypto_tfm
*tfm
, const u8
*key
,
52 struct chksum_ctx
*mctx
= crypto_tfm_ctx(tfm
);
54 if (keylen
!= sizeof(mctx
->crc
)) {
55 tfm
->crt_flags
|= CRYPTO_TFM_RES_BAD_KEY_LEN
;
58 mctx
->key
= le32_to_cpu(*(__le32
*)key
);
62 static void chksum_update(struct crypto_tfm
*tfm
, const u8
*data
,
65 struct chksum_ctx
*mctx
= crypto_tfm_ctx(tfm
);
67 mctx
->crc
= crc32c(mctx
->crc
, data
, length
);
70 static void chksum_final(struct crypto_tfm
*tfm
, u8
*out
)
72 struct chksum_ctx
*mctx
= crypto_tfm_ctx(tfm
);
74 *(__le32
*)out
= ~cpu_to_le32(mctx
->crc
);
77 static int crc32c_cra_init_old(struct crypto_tfm
*tfm
)
79 struct chksum_ctx
*mctx
= crypto_tfm_ctx(tfm
);
85 static struct crypto_alg old_alg
= {
87 .cra_flags
= CRYPTO_ALG_TYPE_DIGEST
,
88 .cra_blocksize
= CHKSUM_BLOCK_SIZE
,
89 .cra_ctxsize
= sizeof(struct chksum_ctx
),
90 .cra_module
= THIS_MODULE
,
91 .cra_list
= LIST_HEAD_INIT(old_alg
.cra_list
),
92 .cra_init
= crc32c_cra_init_old
,
95 .dia_digestsize
= CHKSUM_DIGEST_SIZE
,
96 .dia_setkey
= chksum_setkey
,
97 .dia_init
= chksum_init
,
98 .dia_update
= chksum_update
,
99 .dia_final
= chksum_final
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
109 static int crc32c_setkey(struct crypto_ahash
*hash
, const u8
*key
,
112 u32
*mctx
= crypto_ahash_ctx(hash
);
114 if (keylen
!= sizeof(u32
)) {
115 crypto_ahash_set_flags(hash
, CRYPTO_TFM_RES_BAD_KEY_LEN
);
118 *mctx
= le32_to_cpup((__le32
*)key
);
122 static int crc32c_init(struct ahash_request
*req
)
124 u32
*mctx
= crypto_ahash_ctx(crypto_ahash_reqtfm(req
));
125 u32
*crcp
= ahash_request_ctx(req
);
131 static int crc32c_update(struct ahash_request
*req
)
133 struct crypto_hash_walk walk
;
134 u32
*crcp
= ahash_request_ctx(req
);
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
);
146 static int crc32c_final(struct ahash_request
*req
)
148 u32
*crcp
= ahash_request_ctx(req
);
150 *(__le32
*)req
->result
= ~cpu_to_le32p(crcp
);
154 static int crc32c_digest(struct ahash_request
*req
)
156 struct crypto_hash_walk walk
;
157 u32
*mctx
= crypto_ahash_ctx(crypto_ahash_reqtfm(req
));
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
);
165 *(__le32
*)req
->result
= ~cpu_to_le32(crc
);
169 static int crc32c_cra_init(struct crypto_tfm
*tfm
)
171 u32
*key
= crypto_tfm_ctx(tfm
);
175 tfm
->crt_ahash
.reqsize
= sizeof(u32
);
180 static struct crypto_alg alg
= {
181 .cra_name
= "crc32c",
182 .cra_driver_name
= "crc32c-generic",
184 .cra_flags
= CRYPTO_ALG_TYPE_AHASH
,
185 .cra_blocksize
= CHKSUM_BLOCK_SIZE
,
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
,
194 .digestsize
= CHKSUM_DIGEST_SIZE
,
195 .setkey
= crc32c_setkey
,
197 .update
= crc32c_update
,
198 .final
= crc32c_final
,
199 .digest
= crc32c_digest
,
204 static int __init
crc32c_mod_init(void)
208 err
= crypto_register_alg(&old_alg
);
212 err
= crypto_register_alg(&alg
);
214 crypto_unregister_alg(&old_alg
);
219 static void __exit
crc32c_mod_fini(void)
221 crypto_unregister_alg(&alg
);
222 crypto_unregister_alg(&old_alg
);
225 module_init(crc32c_mod_init
);
226 module_exit(crc32c_mod_fini
);
228 MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>");
229 MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
230 MODULE_LICENSE("GPL");