Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Cryptographic API. | |
3 | * | |
4 | * CRC32C chksum | |
5 | * | |
6 | * This module file is a wrapper to invoke the lib/crc32c routines. | |
7 | * | |
5773a3e6 HX |
8 | * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au> |
9 | * | |
1da177e4 LT |
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) | |
13 | * any later version. | |
14 | * | |
15 | */ | |
5773a3e6 HX |
16 | |
17 | #include <crypto/internal/hash.h> | |
1da177e4 LT |
18 | #include <linux/init.h> |
19 | #include <linux/module.h> | |
20 | #include <linux/string.h> | |
1da177e4 | 21 | #include <linux/crc32c.h> |
25cdbcd9 | 22 | #include <linux/kernel.h> |
1da177e4 | 23 | |
5773a3e6 | 24 | #define CHKSUM_BLOCK_SIZE 1 |
1da177e4 LT |
25 | #define CHKSUM_DIGEST_SIZE 4 |
26 | ||
27 | struct chksum_ctx { | |
25cdbcd9 | 28 | u32 key; |
1da177e4 LT |
29 | }; |
30 | ||
faccc4bb HX |
31 | struct chksum_desc_ctx { |
32 | u32 crc; | |
33 | }; | |
34 | ||
1da177e4 LT |
35 | /* |
36 | * Steps through buffer one byte at at time, calculates reflected | |
37 | * crc using table. | |
38 | */ | |
39 | ||
faccc4bb | 40 | static int chksum_init(struct shash_desc *desc) |
1da177e4 | 41 | { |
faccc4bb HX |
42 | struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm); |
43 | struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); | |
44 | ||
45 | ctx->crc = mctx->key; | |
1da177e4 | 46 | |
faccc4bb | 47 | return 0; |
1da177e4 LT |
48 | } |
49 | ||
50 | /* | |
51 | * Setting the seed allows arbitrary accumulators and flexible XOR policy | |
52 | * If your algorithm starts with ~0, then XOR with ~0 before you set | |
53 | * the seed. | |
54 | */ | |
faccc4bb | 55 | static int chksum_setkey(struct crypto_shash *tfm, const u8 *key, |
560c06ae | 56 | unsigned int keylen) |
1da177e4 | 57 | { |
faccc4bb | 58 | struct chksum_ctx *mctx = crypto_shash_ctx(tfm); |
1da177e4 | 59 | |
faccc4bb HX |
60 | if (keylen != sizeof(mctx->key)) { |
61 | crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); | |
1da177e4 LT |
62 | return -EINVAL; |
63 | } | |
25cdbcd9 | 64 | mctx->key = le32_to_cpu(*(__le32 *)key); |
1da177e4 LT |
65 | return 0; |
66 | } | |
67 | ||
faccc4bb HX |
68 | static int chksum_update(struct shash_desc *desc, const u8 *data, |
69 | unsigned int length) | |
1da177e4 | 70 | { |
faccc4bb | 71 | struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); |
1da177e4 | 72 | |
faccc4bb | 73 | ctx->crc = crc32c(ctx->crc, data, length); |
25cdbcd9 | 74 | return 0; |
1da177e4 LT |
75 | } |
76 | ||
faccc4bb | 77 | static int chksum_final(struct shash_desc *desc, u8 *out) |
5773a3e6 | 78 | { |
faccc4bb | 79 | struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); |
5773a3e6 | 80 | |
faccc4bb | 81 | *(__le32 *)out = ~cpu_to_le32p(&ctx->crc); |
5773a3e6 HX |
82 | return 0; |
83 | } | |
84 | ||
faccc4bb | 85 | static int __chksum_finup(u32 *crcp, const u8 *data, unsigned int len, u8 *out) |
5773a3e6 | 86 | { |
faccc4bb | 87 | *(__le32 *)out = ~cpu_to_le32(crc32c(*crcp, data, len)); |
5773a3e6 HX |
88 | return 0; |
89 | } | |
90 | ||
faccc4bb HX |
91 | static int chksum_finup(struct shash_desc *desc, const u8 *data, |
92 | unsigned int len, u8 *out) | |
5773a3e6 | 93 | { |
faccc4bb | 94 | struct chksum_desc_ctx *ctx = shash_desc_ctx(desc); |
5773a3e6 | 95 | |
faccc4bb | 96 | return __chksum_finup(&ctx->crc, data, len, out); |
5773a3e6 HX |
97 | } |
98 | ||
faccc4bb HX |
99 | static int chksum_digest(struct shash_desc *desc, const u8 *data, |
100 | unsigned int length, u8 *out) | |
5773a3e6 | 101 | { |
faccc4bb | 102 | struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm); |
5773a3e6 | 103 | |
faccc4bb | 104 | return __chksum_finup(&mctx->key, data, length, out); |
5773a3e6 HX |
105 | } |
106 | ||
107 | static int crc32c_cra_init(struct crypto_tfm *tfm) | |
108 | { | |
faccc4bb | 109 | struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); |
5773a3e6 | 110 | |
faccc4bb | 111 | mctx->key = ~0; |
5773a3e6 HX |
112 | return 0; |
113 | } | |
114 | ||
faccc4bb HX |
115 | static struct shash_alg alg = { |
116 | .digestsize = CHKSUM_DIGEST_SIZE, | |
117 | .setkey = chksum_setkey, | |
118 | .init = chksum_init, | |
119 | .update = chksum_update, | |
120 | .final = chksum_final, | |
121 | .finup = chksum_finup, | |
122 | .digest = chksum_digest, | |
123 | .descsize = sizeof(struct chksum_desc_ctx), | |
124 | .base = { | |
125 | .cra_name = "crc32c", | |
126 | .cra_driver_name = "crc32c-generic", | |
127 | .cra_priority = 100, | |
128 | .cra_blocksize = CHKSUM_BLOCK_SIZE, | |
129 | .cra_alignmask = 3, | |
130 | .cra_ctxsize = sizeof(struct chksum_ctx), | |
131 | .cra_module = THIS_MODULE, | |
132 | .cra_init = crc32c_cra_init, | |
5773a3e6 HX |
133 | } |
134 | }; | |
135 | ||
3af5b90b | 136 | static int __init crc32c_mod_init(void) |
1da177e4 | 137 | { |
faccc4bb | 138 | return crypto_register_shash(&alg); |
1da177e4 LT |
139 | } |
140 | ||
3af5b90b | 141 | static void __exit crc32c_mod_fini(void) |
1da177e4 | 142 | { |
faccc4bb | 143 | crypto_unregister_shash(&alg); |
1da177e4 LT |
144 | } |
145 | ||
3af5b90b KB |
146 | module_init(crc32c_mod_init); |
147 | module_exit(crc32c_mod_fini); | |
1da177e4 LT |
148 | |
149 | MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>"); | |
150 | MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c"); | |
151 | MODULE_LICENSE("GPL"); |