^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * sha1-ce-glue.c - SHA-1 secure hash using ARMv8 Crypto Extensions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2014 - 2017 Linaro Ltd <ard.biesheuvel@linaro.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <asm/neon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <asm/simd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <crypto/internal/hash.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <crypto/internal/simd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <crypto/sha.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <crypto/sha1_base.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/cpufeature.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/crypto.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) MODULE_ALIAS_CRYPTO("sha1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct sha1_ce_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct sha1_state sst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) u32 finalize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) extern const u32 sha1_ce_offsetof_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) extern const u32 sha1_ce_offsetof_finalize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) asmlinkage int sha1_ce_transform(struct sha1_ce_state *sst, u8 const *src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) int blocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static void __sha1_ce_transform(struct sha1_state *sst, u8 const *src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int blocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) while (blocks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) int rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) kernel_neon_begin();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) rem = sha1_ce_transform(container_of(sst, struct sha1_ce_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) sst), src, blocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) kernel_neon_end();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) src += (blocks - rem) * SHA1_BLOCK_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) blocks = rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) const u32 sha1_ce_offsetof_count = offsetof(struct sha1_ce_state, sst.count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) const u32 sha1_ce_offsetof_finalize = offsetof(struct sha1_ce_state, finalize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static int sha1_ce_update(struct shash_desc *desc, const u8 *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct sha1_ce_state *sctx = shash_desc_ctx(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (!crypto_simd_usable())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return crypto_sha1_update(desc, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) sctx->finalize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) sha1_base_do_update(desc, data, len, __sha1_ce_transform);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static int sha1_ce_finup(struct shash_desc *desc, const u8 *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) unsigned int len, u8 *out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct sha1_ce_state *sctx = shash_desc_ctx(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) bool finalize = !sctx->sst.count && !(len % SHA1_BLOCK_SIZE) && len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (!crypto_simd_usable())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return crypto_sha1_finup(desc, data, len, out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * Allow the asm code to perform the finalization if there is no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * partial data and the input is a round multiple of the block size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) sctx->finalize = finalize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) sha1_base_do_update(desc, data, len, __sha1_ce_transform);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (!finalize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) sha1_base_do_finalize(desc, __sha1_ce_transform);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return sha1_base_finish(desc, out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static int sha1_ce_final(struct shash_desc *desc, u8 *out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct sha1_ce_state *sctx = shash_desc_ctx(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (!crypto_simd_usable())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return crypto_sha1_finup(desc, NULL, 0, out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) sctx->finalize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) sha1_base_do_finalize(desc, __sha1_ce_transform);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return sha1_base_finish(desc, out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static int sha1_ce_export(struct shash_desc *desc, void *out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct sha1_ce_state *sctx = shash_desc_ctx(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) memcpy(out, &sctx->sst, sizeof(struct sha1_state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static int sha1_ce_import(struct shash_desc *desc, const void *in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct sha1_ce_state *sctx = shash_desc_ctx(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) memcpy(&sctx->sst, in, sizeof(struct sha1_state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) sctx->finalize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static struct shash_alg alg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .init = sha1_base_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .update = sha1_ce_update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .final = sha1_ce_final,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .finup = sha1_ce_finup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .import = sha1_ce_import,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .export = sha1_ce_export,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .descsize = sizeof(struct sha1_ce_state),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .statesize = sizeof(struct sha1_state),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .digestsize = SHA1_DIGEST_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .base = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .cra_name = "sha1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .cra_driver_name = "sha1-ce",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .cra_priority = 200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .cra_blocksize = SHA1_BLOCK_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) .cra_module = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static int __init sha1_ce_mod_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return crypto_register_shash(&alg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static void __exit sha1_ce_mod_fini(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) crypto_unregister_shash(&alg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) module_cpu_feature_match(SHA1, sha1_ce_mod_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) module_exit(sha1_ce_mod_fini);