0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include <asm/unaligned.h>
0034 #include <crypto/internal/hash.h>
0035 #include <linux/init.h>
0036 #include <linux/module.h>
0037 #include <linux/string.h>
0038 #include <linux/kernel.h>
0039 #include <linux/crc32.h>
0040
0041 #define CHKSUM_BLOCK_SIZE 1
0042 #define CHKSUM_DIGEST_SIZE 4
0043
0044 struct chksum_ctx {
0045 u32 key;
0046 };
0047
0048 struct chksum_desc_ctx {
0049 u32 crc;
0050 };
0051
0052
0053
0054
0055
0056
0057 static int chksum_init(struct shash_desc *desc)
0058 {
0059 struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm);
0060 struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
0061
0062 ctx->crc = mctx->key;
0063
0064 return 0;
0065 }
0066
0067
0068
0069
0070
0071
0072 static int chksum_setkey(struct crypto_shash *tfm, const u8 *key,
0073 unsigned int keylen)
0074 {
0075 struct chksum_ctx *mctx = crypto_shash_ctx(tfm);
0076
0077 if (keylen != sizeof(mctx->key))
0078 return -EINVAL;
0079 mctx->key = get_unaligned_le32(key);
0080 return 0;
0081 }
0082
0083 static int chksum_update(struct shash_desc *desc, const u8 *data,
0084 unsigned int length)
0085 {
0086 struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
0087
0088 ctx->crc = __crc32c_le(ctx->crc, data, length);
0089 return 0;
0090 }
0091
0092 static int chksum_final(struct shash_desc *desc, u8 *out)
0093 {
0094 struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
0095
0096 put_unaligned_le32(~ctx->crc, out);
0097 return 0;
0098 }
0099
0100 static int __chksum_finup(u32 *crcp, const u8 *data, unsigned int len, u8 *out)
0101 {
0102 put_unaligned_le32(~__crc32c_le(*crcp, data, len), out);
0103 return 0;
0104 }
0105
0106 static int chksum_finup(struct shash_desc *desc, const u8 *data,
0107 unsigned int len, u8 *out)
0108 {
0109 struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
0110
0111 return __chksum_finup(&ctx->crc, data, len, out);
0112 }
0113
0114 static int chksum_digest(struct shash_desc *desc, const u8 *data,
0115 unsigned int length, u8 *out)
0116 {
0117 struct chksum_ctx *mctx = crypto_shash_ctx(desc->tfm);
0118
0119 return __chksum_finup(&mctx->key, data, length, out);
0120 }
0121
0122 static int crc32c_cra_init(struct crypto_tfm *tfm)
0123 {
0124 struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
0125
0126 mctx->key = ~0;
0127 return 0;
0128 }
0129
0130 static struct shash_alg alg = {
0131 .digestsize = CHKSUM_DIGEST_SIZE,
0132 .setkey = chksum_setkey,
0133 .init = chksum_init,
0134 .update = chksum_update,
0135 .final = chksum_final,
0136 .finup = chksum_finup,
0137 .digest = chksum_digest,
0138 .descsize = sizeof(struct chksum_desc_ctx),
0139 .base = {
0140 .cra_name = "crc32c",
0141 .cra_driver_name = "crc32c-generic",
0142 .cra_priority = 100,
0143 .cra_flags = CRYPTO_ALG_OPTIONAL_KEY,
0144 .cra_blocksize = CHKSUM_BLOCK_SIZE,
0145 .cra_ctxsize = sizeof(struct chksum_ctx),
0146 .cra_module = THIS_MODULE,
0147 .cra_init = crc32c_cra_init,
0148 }
0149 };
0150
0151 static int __init crc32c_mod_init(void)
0152 {
0153 return crypto_register_shash(&alg);
0154 }
0155
0156 static void __exit crc32c_mod_fini(void)
0157 {
0158 crypto_unregister_shash(&alg);
0159 }
0160
0161 subsys_initcall(crc32c_mod_init);
0162 module_exit(crc32c_mod_fini);
0163
0164 MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>");
0165 MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
0166 MODULE_LICENSE("GPL");
0167 MODULE_ALIAS_CRYPTO("crc32c");
0168 MODULE_ALIAS_CRYPTO("crc32c-generic");