summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorKeith Busch <kbusch@kernel.org>2022-03-03 12:13:10 -0800
committerJens Axboe <axboe@kernel.dk>2022-03-07 12:48:35 -0700
commitf3813f4b287e480b1fcd62ca798d8556644b8278 (patch)
tree9f77b5e0c719e20bb7c9dd9faacf1be71b76045d /crypto
parentcbc0a40e17da361a2ada8d669413ccfbd2028f2d (diff)
downloadlinux-f3813f4b287e480b1fcd62ca798d8556644b8278.tar.bz2
crypto: add rocksoft 64b crc guard tag framework
Hardware specific features may be able to calculate a crc64, so provide a framework for drivers to register their implementation. If nothing is registered, fallback to the generic table lookup implementation. The implementation is modeled after the crct10dif equivalent. Signed-off-by: Keith Busch <kbusch@kernel.org> Link: https://lore.kernel.org/r/20220303201312.3255347-7-kbusch@kernel.org Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/Kconfig5
-rw-r--r--crypto/Makefile1
-rw-r--r--crypto/crc64_rocksoft_generic.c89
-rw-r--r--crypto/testmgr.c7
-rw-r--r--crypto/testmgr.h15
5 files changed, 117 insertions, 0 deletions
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 442765219c37..e88e2d00e33d 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -735,6 +735,11 @@ config CRYPTO_CRCT10DIF_VPMSUM
multiply-sum (vpmsum) instructions, introduced in POWER8. Enable on
POWER8 and newer processors for improved performance.
+config CRYPTO_CRC64_ROCKSOFT
+ tristate "Rocksoft Model CRC64 algorithm"
+ depends on CRC64
+ select CRYPTO_HASH
+
config CRYPTO_VPMSUM_TESTER
tristate "Powerpc64 vpmsum hardware acceleration tester"
depends on CRYPTO_CRCT10DIF_VPMSUM && CRYPTO_CRC32C_VPMSUM
diff --git a/crypto/Makefile b/crypto/Makefile
index d76bff8d0ffd..f754c4d17d6b 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -152,6 +152,7 @@ obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
obj-$(CONFIG_CRYPTO_CRC32C) += crc32c_generic.o
obj-$(CONFIG_CRYPTO_CRC32) += crc32_generic.o
obj-$(CONFIG_CRYPTO_CRCT10DIF) += crct10dif_common.o crct10dif_generic.o
+obj-$(CONFIG_CRYPTO_CRC64_ROCKSOFT) += crc64_rocksoft_generic.o
obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
obj-$(CONFIG_CRYPTO_LZO) += lzo.o lzo-rle.o
obj-$(CONFIG_CRYPTO_LZ4) += lz4.o
diff --git a/crypto/crc64_rocksoft_generic.c b/crypto/crc64_rocksoft_generic.c
new file mode 100644
index 000000000000..9e812bb26dba
--- /dev/null
+++ b/crypto/crc64_rocksoft_generic.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/crc64.h>
+#include <linux/module.h>
+#include <crypto/internal/hash.h>
+#include <asm/unaligned.h>
+
+static int chksum_init(struct shash_desc *desc)
+{
+ u64 *crc = shash_desc_ctx(desc);
+
+ *crc = 0;
+
+ return 0;
+}
+
+static int chksum_update(struct shash_desc *desc, const u8 *data,
+ unsigned int length)
+{
+ u64 *crc = shash_desc_ctx(desc);
+
+ *crc = crc64_rocksoft_generic(*crc, data, length);
+
+ return 0;
+}
+
+static int chksum_final(struct shash_desc *desc, u8 *out)
+{
+ u64 *crc = shash_desc_ctx(desc);
+
+ put_unaligned_le64(*crc, out);
+ return 0;
+}
+
+static int __chksum_finup(u64 crc, const u8 *data, unsigned int len, u8 *out)
+{
+ crc = crc64_rocksoft_generic(crc, data, len);
+ put_unaligned_le64(crc, out);
+ return 0;
+}
+
+static int chksum_finup(struct shash_desc *desc, const u8 *data,
+ unsigned int len, u8 *out)
+{
+ u64 *crc = shash_desc_ctx(desc);
+
+ return __chksum_finup(*crc, data, len, out);
+}
+
+static int chksum_digest(struct shash_desc *desc, const u8 *data,
+ unsigned int length, u8 *out)
+{
+ return __chksum_finup(0, data, length, out);
+}
+
+static struct shash_alg alg = {
+ .digestsize = sizeof(u64),
+ .init = chksum_init,
+ .update = chksum_update,
+ .final = chksum_final,
+ .finup = chksum_finup,
+ .digest = chksum_digest,
+ .descsize = sizeof(u64),
+ .base = {
+ .cra_name = CRC64_ROCKSOFT_STRING,
+ .cra_driver_name = "crc64-rocksoft-generic",
+ .cra_priority = 200,
+ .cra_blocksize = 1,
+ .cra_module = THIS_MODULE,
+ }
+};
+
+static int __init crc64_rocksoft_init(void)
+{
+ return crypto_register_shash(&alg);
+}
+
+static void __exit crc64_rocksoft_exit(void)
+{
+ crypto_unregister_shash(&alg);
+}
+
+module_init(crc64_rocksoft_init);
+module_exit(crc64_rocksoft_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Rocksoft model CRC64 calculation.");
+MODULE_ALIAS_CRYPTO("crc64-rocksoft");
+MODULE_ALIAS_CRYPTO("crc64-rocksoft-generic");
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 5831d4bbc64f..2e120eea10b1 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -4527,6 +4527,13 @@ static const struct alg_test_desc alg_test_descs[] = {
.hash = __VECS(crc32c_tv_template)
}
}, {
+ .alg = "crc64-rocksoft",
+ .test = alg_test_hash,
+ .fips_allowed = 1,
+ .suite = {
+ .hash = __VECS(crc64_rocksoft_tv_template)
+ }
+ }, {
.alg = "crct10dif",
.test = alg_test_hash,
.fips_allowed = 1,
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index a253d66ba1c1..f1a22794c404 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -3679,6 +3679,21 @@ static const struct hash_testvec rmd160_tv_template[] = {
}
};
+static const u8 zeroes[4096] = { [0 ... 4095] = 0 };
+static const u8 ones[4096] = { [0 ... 4095] = 0xff };
+
+static const struct hash_testvec crc64_rocksoft_tv_template[] = {
+ {
+ .plaintext = zeroes,
+ .psize = 4096,
+ .digest = (u8 *)(u64[]){ 0x6482d367eb22b64eull },
+ }, {
+ .plaintext = ones,
+ .psize = 4096,
+ .digest = (u8 *)(u64[]){ 0xc0ddba7302eca3acull },
+ }
+};
+
static const struct hash_testvec crct10dif_tv_template[] = {
{
.plaintext = "abc",