Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | // SPDX-License-Identifier: GPL-2.0-only /* * CRC vpmsum tester * Copyright 2017 Daniel Axtens, IBM Corporation. */ #include <linux/crc-t10dif.h> #include <linux/crc32.h> #include <crypto/internal/hash.h> #include <linux/init.h> #include <linux/module.h> #include <linux/random.h> #include <linux/string.h> #include <linux/kernel.h> #include <linux/cpufeature.h> #include <asm/switch_to.h> static unsigned long iterations = 10000; #define MAX_CRC_LENGTH 65535 static int __init crc_test_init(void) { u16 crc16 = 0, verify16 = 0; __le32 verify32le = 0; unsigned char *data; u32 verify32 = 0; unsigned long i; __le32 crc32; int ret; struct crypto_shash *crct10dif_tfm; struct crypto_shash *crc32c_tfm; if (!cpu_has_feature(CPU_FTR_ARCH_207S)) return -ENODEV; data = kmalloc(MAX_CRC_LENGTH, GFP_KERNEL); if (!data) return -ENOMEM; crct10dif_tfm = crypto_alloc_shash("crct10dif", 0, 0); if (IS_ERR(crct10dif_tfm)) { pr_err("Error allocating crc-t10dif\n"); goto free_buf; } crc32c_tfm = crypto_alloc_shash("crc32c", 0, 0); if (IS_ERR(crc32c_tfm)) { pr_err("Error allocating crc32c\n"); goto free_16; } do { SHASH_DESC_ON_STACK(crct10dif_shash, crct10dif_tfm); SHASH_DESC_ON_STACK(crc32c_shash, crc32c_tfm); crct10dif_shash->tfm = crct10dif_tfm; ret = crypto_shash_init(crct10dif_shash); if (ret) { pr_err("Error initing crc-t10dif\n"); goto free_32; } crc32c_shash->tfm = crc32c_tfm; ret = crypto_shash_init(crc32c_shash); if (ret) { pr_err("Error initing crc32c\n"); goto free_32; } pr_info("crc-vpmsum_test begins, %lu iterations\n", iterations); for (i=0; i<iterations; i++) { size_t offset = get_random_u32_below(16); size_t len = get_random_u32_below(MAX_CRC_LENGTH); if (len <= offset) continue; get_random_bytes(data, len); len -= offset; crypto_shash_update(crct10dif_shash, data+offset, len); crypto_shash_final(crct10dif_shash, (u8 *)(&crc16)); verify16 = crc_t10dif_generic(verify16, data+offset, len); if (crc16 != verify16) { pr_err("FAILURE in CRC16: got 0x%04x expected 0x%04x (len %lu)\n", crc16, verify16, len); break; } crypto_shash_update(crc32c_shash, data+offset, len); crypto_shash_final(crc32c_shash, (u8 *)(&crc32)); verify32 = le32_to_cpu(verify32le); verify32le = ~cpu_to_le32(__crc32c_le(~verify32, data+offset, len)); if (crc32 != verify32le) { pr_err("FAILURE in CRC32: got 0x%08x expected 0x%08x (len %lu)\n", crc32, verify32, len); break; } cond_resched(); } pr_info("crc-vpmsum_test done, completed %lu iterations\n", i); } while (0); free_32: crypto_free_shash(crc32c_tfm); free_16: crypto_free_shash(crct10dif_tfm); free_buf: kfree(data); return 0; } static void __exit crc_test_exit(void) {} module_init(crc_test_init); module_exit(crc_test_exit); module_param(iterations, long, 0400); MODULE_AUTHOR("Daniel Axtens <dja@axtens.net>"); MODULE_DESCRIPTION("Vector polynomial multiply-sum CRC tester"); MODULE_LICENSE("GPL"); |