1a7c58ac0SHerbert Xu /* GPL HEADER START 2a7c58ac0SHerbert Xu * 3a7c58ac0SHerbert Xu * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4a7c58ac0SHerbert Xu * 5a7c58ac0SHerbert Xu * This program is free software; you can redistribute it and/or modify 6a7c58ac0SHerbert Xu * it under the terms of the GNU General Public License version 2 only, 7a7c58ac0SHerbert Xu * as published by the Free Software Foundation. 8a7c58ac0SHerbert Xu * 9a7c58ac0SHerbert Xu * This program is distributed in the hope that it will be useful, but 10a7c58ac0SHerbert Xu * WITHOUT ANY WARRANTY; without even the implied warranty of 11a7c58ac0SHerbert Xu * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12a7c58ac0SHerbert Xu * General Public License version 2 for more details (a copy is included 13a7c58ac0SHerbert Xu * in the LICENSE file that accompanied this code). 14a7c58ac0SHerbert Xu * 15a7c58ac0SHerbert Xu * You should have received a copy of the GNU General Public License 16a7c58ac0SHerbert Xu * version 2 along with this program; If not, see http://www.gnu.org/licenses 17a7c58ac0SHerbert Xu * 18a7c58ac0SHerbert Xu * Please visit http://www.xyratex.com/contact if you need additional 19a7c58ac0SHerbert Xu * information or have any questions. 20a7c58ac0SHerbert Xu * 21a7c58ac0SHerbert Xu * GPL HEADER END 22a7c58ac0SHerbert Xu */ 23a7c58ac0SHerbert Xu 24a7c58ac0SHerbert Xu /* 25a7c58ac0SHerbert Xu * Copyright 2012 Xyratex Technology Limited 26a7c58ac0SHerbert Xu */ 27a7c58ac0SHerbert Xu 28a7c58ac0SHerbert Xu /* 29a7c58ac0SHerbert Xu * This is crypto api shash wrappers to crc32_le. 30a7c58ac0SHerbert Xu */ 31a7c58ac0SHerbert Xu 32fffe7d92SEric Biggers #include <asm/unaligned.h> 33a7c58ac0SHerbert Xu #include <linux/crc32.h> 34a7c58ac0SHerbert Xu #include <crypto/internal/hash.h> 35a7c58ac0SHerbert Xu #include <linux/init.h> 36a7c58ac0SHerbert Xu #include <linux/module.h> 37a7c58ac0SHerbert Xu #include <linux/string.h> 38a7c58ac0SHerbert Xu #include <linux/kernel.h> 39a7c58ac0SHerbert Xu 40a7c58ac0SHerbert Xu #define CHKSUM_BLOCK_SIZE 1 41a7c58ac0SHerbert Xu #define CHKSUM_DIGEST_SIZE 4 42a7c58ac0SHerbert Xu 43a7c58ac0SHerbert Xu /** No default init with ~0 */ 44a7c58ac0SHerbert Xu static int crc32_cra_init(struct crypto_tfm *tfm) 45a7c58ac0SHerbert Xu { 46a7c58ac0SHerbert Xu u32 *key = crypto_tfm_ctx(tfm); 47a7c58ac0SHerbert Xu 48a7c58ac0SHerbert Xu *key = 0; 49a7c58ac0SHerbert Xu 50a7c58ac0SHerbert Xu return 0; 51a7c58ac0SHerbert Xu } 52a7c58ac0SHerbert Xu 53a7c58ac0SHerbert Xu /* 54a7c58ac0SHerbert Xu * Setting the seed allows arbitrary accumulators and flexible XOR policy 55a7c58ac0SHerbert Xu * If your algorithm starts with ~0, then XOR with ~0 before you set 56a7c58ac0SHerbert Xu * the seed. 57a7c58ac0SHerbert Xu */ 58a7c58ac0SHerbert Xu static int crc32_setkey(struct crypto_shash *hash, const u8 *key, 59a7c58ac0SHerbert Xu unsigned int keylen) 60a7c58ac0SHerbert Xu { 61a7c58ac0SHerbert Xu u32 *mctx = crypto_shash_ctx(hash); 62a7c58ac0SHerbert Xu 63a7c58ac0SHerbert Xu if (keylen != sizeof(u32)) { 64a7c58ac0SHerbert Xu crypto_shash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN); 65a7c58ac0SHerbert Xu return -EINVAL; 66a7c58ac0SHerbert Xu } 67fffe7d92SEric Biggers *mctx = get_unaligned_le32(key); 68a7c58ac0SHerbert Xu return 0; 69a7c58ac0SHerbert Xu } 70a7c58ac0SHerbert Xu 71a7c58ac0SHerbert Xu static int crc32_init(struct shash_desc *desc) 72a7c58ac0SHerbert Xu { 73a7c58ac0SHerbert Xu u32 *mctx = crypto_shash_ctx(desc->tfm); 74a7c58ac0SHerbert Xu u32 *crcp = shash_desc_ctx(desc); 75a7c58ac0SHerbert Xu 76a7c58ac0SHerbert Xu *crcp = *mctx; 77a7c58ac0SHerbert Xu 78a7c58ac0SHerbert Xu return 0; 79a7c58ac0SHerbert Xu } 80a7c58ac0SHerbert Xu 81a7c58ac0SHerbert Xu static int crc32_update(struct shash_desc *desc, const u8 *data, 82a7c58ac0SHerbert Xu unsigned int len) 83a7c58ac0SHerbert Xu { 84a7c58ac0SHerbert Xu u32 *crcp = shash_desc_ctx(desc); 85a7c58ac0SHerbert Xu 866943546cSEric Biggers *crcp = crc32_le(*crcp, data, len); 87a7c58ac0SHerbert Xu return 0; 88a7c58ac0SHerbert Xu } 89a7c58ac0SHerbert Xu 90a7c58ac0SHerbert Xu /* No final XOR 0xFFFFFFFF, like crc32_le */ 91a7c58ac0SHerbert Xu static int __crc32_finup(u32 *crcp, const u8 *data, unsigned int len, 92a7c58ac0SHerbert Xu u8 *out) 93a7c58ac0SHerbert Xu { 946943546cSEric Biggers put_unaligned_le32(crc32_le(*crcp, data, len), out); 95a7c58ac0SHerbert Xu return 0; 96a7c58ac0SHerbert Xu } 97a7c58ac0SHerbert Xu 98a7c58ac0SHerbert Xu static int crc32_finup(struct shash_desc *desc, const u8 *data, 99a7c58ac0SHerbert Xu unsigned int len, u8 *out) 100a7c58ac0SHerbert Xu { 101a7c58ac0SHerbert Xu return __crc32_finup(shash_desc_ctx(desc), data, len, out); 102a7c58ac0SHerbert Xu } 103a7c58ac0SHerbert Xu 104a7c58ac0SHerbert Xu static int crc32_final(struct shash_desc *desc, u8 *out) 105a7c58ac0SHerbert Xu { 106a7c58ac0SHerbert Xu u32 *crcp = shash_desc_ctx(desc); 107a7c58ac0SHerbert Xu 108fffe7d92SEric Biggers put_unaligned_le32(*crcp, out); 109a7c58ac0SHerbert Xu return 0; 110a7c58ac0SHerbert Xu } 111a7c58ac0SHerbert Xu 112a7c58ac0SHerbert Xu static int crc32_digest(struct shash_desc *desc, const u8 *data, 113a7c58ac0SHerbert Xu unsigned int len, u8 *out) 114a7c58ac0SHerbert Xu { 115a7c58ac0SHerbert Xu return __crc32_finup(crypto_shash_ctx(desc->tfm), data, len, 116a7c58ac0SHerbert Xu out); 117a7c58ac0SHerbert Xu } 118a7c58ac0SHerbert Xu static struct shash_alg alg = { 119a7c58ac0SHerbert Xu .setkey = crc32_setkey, 120a7c58ac0SHerbert Xu .init = crc32_init, 121a7c58ac0SHerbert Xu .update = crc32_update, 122a7c58ac0SHerbert Xu .final = crc32_final, 123a7c58ac0SHerbert Xu .finup = crc32_finup, 124a7c58ac0SHerbert Xu .digest = crc32_digest, 125a7c58ac0SHerbert Xu .descsize = sizeof(u32), 126a7c58ac0SHerbert Xu .digestsize = CHKSUM_DIGEST_SIZE, 127a7c58ac0SHerbert Xu .base = { 128a7c58ac0SHerbert Xu .cra_name = "crc32", 129a7c58ac0SHerbert Xu .cra_driver_name = "crc32-generic", 130a7c58ac0SHerbert Xu .cra_priority = 100, 131a208fa8fSEric Biggers .cra_flags = CRYPTO_ALG_OPTIONAL_KEY, 132a7c58ac0SHerbert Xu .cra_blocksize = CHKSUM_BLOCK_SIZE, 133a7c58ac0SHerbert Xu .cra_ctxsize = sizeof(u32), 134a7c58ac0SHerbert Xu .cra_module = THIS_MODULE, 135a7c58ac0SHerbert Xu .cra_init = crc32_cra_init, 136a7c58ac0SHerbert Xu } 137a7c58ac0SHerbert Xu }; 138a7c58ac0SHerbert Xu 139a7c58ac0SHerbert Xu static int __init crc32_mod_init(void) 140a7c58ac0SHerbert Xu { 141a7c58ac0SHerbert Xu return crypto_register_shash(&alg); 142a7c58ac0SHerbert Xu } 143a7c58ac0SHerbert Xu 144a7c58ac0SHerbert Xu static void __exit crc32_mod_fini(void) 145a7c58ac0SHerbert Xu { 146a7c58ac0SHerbert Xu crypto_unregister_shash(&alg); 147a7c58ac0SHerbert Xu } 148a7c58ac0SHerbert Xu 149a7c58ac0SHerbert Xu module_init(crc32_mod_init); 150a7c58ac0SHerbert Xu module_exit(crc32_mod_fini); 151a7c58ac0SHerbert Xu 152a7c58ac0SHerbert Xu MODULE_AUTHOR("Alexander Boyko <alexander_boyko@xyratex.com>"); 153a7c58ac0SHerbert Xu MODULE_DESCRIPTION("CRC32 calculations wrapper for lib/crc32"); 154a7c58ac0SHerbert Xu MODULE_LICENSE("GPL"); 155a7c58ac0SHerbert Xu MODULE_ALIAS_CRYPTO("crc32"); 156a7c58ac0SHerbert Xu MODULE_ALIAS_CRYPTO("crc32-generic"); 157