1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 22c98833aSArd Biesheuvel /* 32c98833aSArd Biesheuvel * sha1-ce-glue.c - SHA-1 secure hash using ARMv8 Crypto Extensions 42c98833aSArd Biesheuvel * 50771f323SArd Biesheuvel * Copyright (C) 2014 - 2017 Linaro Ltd <ard.biesheuvel@linaro.org> 62c98833aSArd Biesheuvel */ 72c98833aSArd Biesheuvel 82c98833aSArd Biesheuvel #include <asm/neon.h> 90771f323SArd Biesheuvel #include <asm/simd.h> 102c98833aSArd Biesheuvel #include <asm/unaligned.h> 112c98833aSArd Biesheuvel #include <crypto/internal/hash.h> 12e52b7023SEric Biggers #include <crypto/internal/simd.h> 132c98833aSArd Biesheuvel #include <crypto/sha.h> 1407eb54d3SArd Biesheuvel #include <crypto/sha1_base.h> 152c98833aSArd Biesheuvel #include <linux/cpufeature.h> 162c98833aSArd Biesheuvel #include <linux/crypto.h> 172c98833aSArd Biesheuvel #include <linux/module.h> 182c98833aSArd Biesheuvel 192c98833aSArd Biesheuvel MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions"); 202c98833aSArd Biesheuvel MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>"); 212c98833aSArd Biesheuvel MODULE_LICENSE("GPL v2"); 222c98833aSArd Biesheuvel 2307eb54d3SArd Biesheuvel struct sha1_ce_state { 2407eb54d3SArd Biesheuvel struct sha1_state sst; 2507eb54d3SArd Biesheuvel u32 finalize; 262c98833aSArd Biesheuvel }; 272c98833aSArd Biesheuvel 2807eb54d3SArd Biesheuvel asmlinkage void sha1_ce_transform(struct sha1_ce_state *sst, u8 const *src, 2907eb54d3SArd Biesheuvel int blocks); 3007eb54d3SArd Biesheuvel 316320a15eSSami Tolvanen static void __sha1_ce_transform(struct sha1_state *sst, u8 const *src, 326320a15eSSami Tolvanen int blocks) 336320a15eSSami Tolvanen { 346320a15eSSami Tolvanen sha1_ce_transform(container_of(sst, struct sha1_ce_state, sst), src, 356320a15eSSami Tolvanen blocks); 366320a15eSSami Tolvanen } 376320a15eSSami Tolvanen 38f4857f4cSArd Biesheuvel const u32 sha1_ce_offsetof_count = offsetof(struct sha1_ce_state, sst.count); 39f4857f4cSArd Biesheuvel const u32 sha1_ce_offsetof_finalize = offsetof(struct sha1_ce_state, finalize); 40f4857f4cSArd Biesheuvel 4107eb54d3SArd Biesheuvel static int sha1_ce_update(struct shash_desc *desc, const u8 *data, 422c98833aSArd Biesheuvel unsigned int len) 432c98833aSArd Biesheuvel { 4407eb54d3SArd Biesheuvel struct sha1_ce_state *sctx = shash_desc_ctx(desc); 452c98833aSArd Biesheuvel 46e52b7023SEric Biggers if (!crypto_simd_usable()) 470771f323SArd Biesheuvel return crypto_sha1_update(desc, data, len); 480771f323SArd Biesheuvel 4907eb54d3SArd Biesheuvel sctx->finalize = 0; 500771f323SArd Biesheuvel kernel_neon_begin(); 516320a15eSSami Tolvanen sha1_base_do_update(desc, data, len, __sha1_ce_transform); 522c98833aSArd Biesheuvel kernel_neon_end(); 532c98833aSArd Biesheuvel 542c98833aSArd Biesheuvel return 0; 552c98833aSArd Biesheuvel } 562c98833aSArd Biesheuvel 5707eb54d3SArd Biesheuvel static int sha1_ce_finup(struct shash_desc *desc, const u8 *data, 582c98833aSArd Biesheuvel unsigned int len, u8 *out) 592c98833aSArd Biesheuvel { 6007eb54d3SArd Biesheuvel struct sha1_ce_state *sctx = shash_desc_ctx(desc); 611d4aaf16SElena Petrova bool finalize = !sctx->sst.count && !(len % SHA1_BLOCK_SIZE) && len; 622c98833aSArd Biesheuvel 63e52b7023SEric Biggers if (!crypto_simd_usable()) 640771f323SArd Biesheuvel return crypto_sha1_finup(desc, data, len, out); 650771f323SArd Biesheuvel 662c98833aSArd Biesheuvel /* 6707eb54d3SArd Biesheuvel * Allow the asm code to perform the finalization if there is no 6807eb54d3SArd Biesheuvel * partial data and the input is a round multiple of the block size. 692c98833aSArd Biesheuvel */ 7007eb54d3SArd Biesheuvel sctx->finalize = finalize; 712c98833aSArd Biesheuvel 720771f323SArd Biesheuvel kernel_neon_begin(); 736320a15eSSami Tolvanen sha1_base_do_update(desc, data, len, __sha1_ce_transform); 7407eb54d3SArd Biesheuvel if (!finalize) 756320a15eSSami Tolvanen sha1_base_do_finalize(desc, __sha1_ce_transform); 762c98833aSArd Biesheuvel kernel_neon_end(); 7707eb54d3SArd Biesheuvel return sha1_base_finish(desc, out); 782c98833aSArd Biesheuvel } 792c98833aSArd Biesheuvel 8007eb54d3SArd Biesheuvel static int sha1_ce_final(struct shash_desc *desc, u8 *out) 812c98833aSArd Biesheuvel { 82bf7883ebSArd Biesheuvel struct sha1_ce_state *sctx = shash_desc_ctx(desc); 83bf7883ebSArd Biesheuvel 84e52b7023SEric Biggers if (!crypto_simd_usable()) 850771f323SArd Biesheuvel return crypto_sha1_finup(desc, NULL, 0, out); 860771f323SArd Biesheuvel 87bf7883ebSArd Biesheuvel sctx->finalize = 0; 880771f323SArd Biesheuvel kernel_neon_begin(); 896320a15eSSami Tolvanen sha1_base_do_finalize(desc, __sha1_ce_transform); 9007eb54d3SArd Biesheuvel kernel_neon_end(); 9107eb54d3SArd Biesheuvel return sha1_base_finish(desc, out); 922c98833aSArd Biesheuvel } 932c98833aSArd Biesheuvel 94*d282eeebSCorentin Labbe static int sha1_ce_export(struct shash_desc *desc, void *out) 95*d282eeebSCorentin Labbe { 96*d282eeebSCorentin Labbe struct sha1_ce_state *sctx = shash_desc_ctx(desc); 97*d282eeebSCorentin Labbe 98*d282eeebSCorentin Labbe memcpy(out, &sctx->sst, sizeof(struct sha1_state)); 99*d282eeebSCorentin Labbe return 0; 100*d282eeebSCorentin Labbe } 101*d282eeebSCorentin Labbe 102*d282eeebSCorentin Labbe static int sha1_ce_import(struct shash_desc *desc, const void *in) 103*d282eeebSCorentin Labbe { 104*d282eeebSCorentin Labbe struct sha1_ce_state *sctx = shash_desc_ctx(desc); 105*d282eeebSCorentin Labbe 106*d282eeebSCorentin Labbe memcpy(&sctx->sst, in, sizeof(struct sha1_state)); 107*d282eeebSCorentin Labbe sctx->finalize = 0; 108*d282eeebSCorentin Labbe return 0; 109*d282eeebSCorentin Labbe } 110*d282eeebSCorentin Labbe 1112c98833aSArd Biesheuvel static struct shash_alg alg = { 11207eb54d3SArd Biesheuvel .init = sha1_base_init, 11307eb54d3SArd Biesheuvel .update = sha1_ce_update, 11407eb54d3SArd Biesheuvel .final = sha1_ce_final, 11507eb54d3SArd Biesheuvel .finup = sha1_ce_finup, 116*d282eeebSCorentin Labbe .import = sha1_ce_import, 117*d282eeebSCorentin Labbe .export = sha1_ce_export, 11807eb54d3SArd Biesheuvel .descsize = sizeof(struct sha1_ce_state), 119*d282eeebSCorentin Labbe .statesize = sizeof(struct sha1_state), 1202c98833aSArd Biesheuvel .digestsize = SHA1_DIGEST_SIZE, 1212c98833aSArd Biesheuvel .base = { 1222c98833aSArd Biesheuvel .cra_name = "sha1", 1232c98833aSArd Biesheuvel .cra_driver_name = "sha1-ce", 1242c98833aSArd Biesheuvel .cra_priority = 200, 1252c98833aSArd Biesheuvel .cra_blocksize = SHA1_BLOCK_SIZE, 1262c98833aSArd Biesheuvel .cra_module = THIS_MODULE, 1272c98833aSArd Biesheuvel } 1282c98833aSArd Biesheuvel }; 1292c98833aSArd Biesheuvel 1302c98833aSArd Biesheuvel static int __init sha1_ce_mod_init(void) 1312c98833aSArd Biesheuvel { 1322c98833aSArd Biesheuvel return crypto_register_shash(&alg); 1332c98833aSArd Biesheuvel } 1342c98833aSArd Biesheuvel 1352c98833aSArd Biesheuvel static void __exit sha1_ce_mod_fini(void) 1362c98833aSArd Biesheuvel { 1372c98833aSArd Biesheuvel crypto_unregister_shash(&alg); 1382c98833aSArd Biesheuvel } 1392c98833aSArd Biesheuvel 1402c98833aSArd Biesheuvel module_cpu_feature_match(SHA1, sha1_ce_mod_init); 1412c98833aSArd Biesheuvel module_exit(sha1_ce_mod_fini); 142