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 28*0f4128dcSHerbert Xu extern const u32 sha1_ce_offsetof_count; 29*0f4128dcSHerbert Xu extern const u32 sha1_ce_offsetof_finalize; 30*0f4128dcSHerbert Xu 3107eb54d3SArd Biesheuvel asmlinkage void sha1_ce_transform(struct sha1_ce_state *sst, u8 const *src, 3207eb54d3SArd Biesheuvel int blocks); 3307eb54d3SArd Biesheuvel 346320a15eSSami Tolvanen static void __sha1_ce_transform(struct sha1_state *sst, u8 const *src, 356320a15eSSami Tolvanen int blocks) 366320a15eSSami Tolvanen { 376320a15eSSami Tolvanen sha1_ce_transform(container_of(sst, struct sha1_ce_state, sst), src, 386320a15eSSami Tolvanen blocks); 396320a15eSSami Tolvanen } 406320a15eSSami Tolvanen 41f4857f4cSArd Biesheuvel const u32 sha1_ce_offsetof_count = offsetof(struct sha1_ce_state, sst.count); 42f4857f4cSArd Biesheuvel const u32 sha1_ce_offsetof_finalize = offsetof(struct sha1_ce_state, finalize); 43f4857f4cSArd Biesheuvel 4407eb54d3SArd Biesheuvel static int sha1_ce_update(struct shash_desc *desc, const u8 *data, 452c98833aSArd Biesheuvel unsigned int len) 462c98833aSArd Biesheuvel { 4707eb54d3SArd Biesheuvel struct sha1_ce_state *sctx = shash_desc_ctx(desc); 482c98833aSArd Biesheuvel 49e52b7023SEric Biggers if (!crypto_simd_usable()) 500771f323SArd Biesheuvel return crypto_sha1_update(desc, data, len); 510771f323SArd Biesheuvel 5207eb54d3SArd Biesheuvel sctx->finalize = 0; 530771f323SArd Biesheuvel kernel_neon_begin(); 546320a15eSSami Tolvanen sha1_base_do_update(desc, data, len, __sha1_ce_transform); 552c98833aSArd Biesheuvel kernel_neon_end(); 562c98833aSArd Biesheuvel 572c98833aSArd Biesheuvel return 0; 582c98833aSArd Biesheuvel } 592c98833aSArd Biesheuvel 6007eb54d3SArd Biesheuvel static int sha1_ce_finup(struct shash_desc *desc, const u8 *data, 612c98833aSArd Biesheuvel unsigned int len, u8 *out) 622c98833aSArd Biesheuvel { 6307eb54d3SArd Biesheuvel struct sha1_ce_state *sctx = shash_desc_ctx(desc); 641d4aaf16SElena Petrova bool finalize = !sctx->sst.count && !(len % SHA1_BLOCK_SIZE) && len; 652c98833aSArd Biesheuvel 66e52b7023SEric Biggers if (!crypto_simd_usable()) 670771f323SArd Biesheuvel return crypto_sha1_finup(desc, data, len, out); 680771f323SArd Biesheuvel 692c98833aSArd Biesheuvel /* 7007eb54d3SArd Biesheuvel * Allow the asm code to perform the finalization if there is no 7107eb54d3SArd Biesheuvel * partial data and the input is a round multiple of the block size. 722c98833aSArd Biesheuvel */ 7307eb54d3SArd Biesheuvel sctx->finalize = finalize; 742c98833aSArd Biesheuvel 750771f323SArd Biesheuvel kernel_neon_begin(); 766320a15eSSami Tolvanen sha1_base_do_update(desc, data, len, __sha1_ce_transform); 7707eb54d3SArd Biesheuvel if (!finalize) 786320a15eSSami Tolvanen sha1_base_do_finalize(desc, __sha1_ce_transform); 792c98833aSArd Biesheuvel kernel_neon_end(); 8007eb54d3SArd Biesheuvel return sha1_base_finish(desc, out); 812c98833aSArd Biesheuvel } 822c98833aSArd Biesheuvel 8307eb54d3SArd Biesheuvel static int sha1_ce_final(struct shash_desc *desc, u8 *out) 842c98833aSArd Biesheuvel { 85bf7883ebSArd Biesheuvel struct sha1_ce_state *sctx = shash_desc_ctx(desc); 86bf7883ebSArd Biesheuvel 87e52b7023SEric Biggers if (!crypto_simd_usable()) 880771f323SArd Biesheuvel return crypto_sha1_finup(desc, NULL, 0, out); 890771f323SArd Biesheuvel 90bf7883ebSArd Biesheuvel sctx->finalize = 0; 910771f323SArd Biesheuvel kernel_neon_begin(); 926320a15eSSami Tolvanen sha1_base_do_finalize(desc, __sha1_ce_transform); 9307eb54d3SArd Biesheuvel kernel_neon_end(); 9407eb54d3SArd Biesheuvel return sha1_base_finish(desc, out); 952c98833aSArd Biesheuvel } 962c98833aSArd Biesheuvel 97d282eeebSCorentin Labbe static int sha1_ce_export(struct shash_desc *desc, void *out) 98d282eeebSCorentin Labbe { 99d282eeebSCorentin Labbe struct sha1_ce_state *sctx = shash_desc_ctx(desc); 100d282eeebSCorentin Labbe 101d282eeebSCorentin Labbe memcpy(out, &sctx->sst, sizeof(struct sha1_state)); 102d282eeebSCorentin Labbe return 0; 103d282eeebSCorentin Labbe } 104d282eeebSCorentin Labbe 105d282eeebSCorentin Labbe static int sha1_ce_import(struct shash_desc *desc, const void *in) 106d282eeebSCorentin Labbe { 107d282eeebSCorentin Labbe struct sha1_ce_state *sctx = shash_desc_ctx(desc); 108d282eeebSCorentin Labbe 109d282eeebSCorentin Labbe memcpy(&sctx->sst, in, sizeof(struct sha1_state)); 110d282eeebSCorentin Labbe sctx->finalize = 0; 111d282eeebSCorentin Labbe return 0; 112d282eeebSCorentin Labbe } 113d282eeebSCorentin Labbe 1142c98833aSArd Biesheuvel static struct shash_alg alg = { 11507eb54d3SArd Biesheuvel .init = sha1_base_init, 11607eb54d3SArd Biesheuvel .update = sha1_ce_update, 11707eb54d3SArd Biesheuvel .final = sha1_ce_final, 11807eb54d3SArd Biesheuvel .finup = sha1_ce_finup, 119d282eeebSCorentin Labbe .import = sha1_ce_import, 120d282eeebSCorentin Labbe .export = sha1_ce_export, 12107eb54d3SArd Biesheuvel .descsize = sizeof(struct sha1_ce_state), 122d282eeebSCorentin Labbe .statesize = sizeof(struct sha1_state), 1232c98833aSArd Biesheuvel .digestsize = SHA1_DIGEST_SIZE, 1242c98833aSArd Biesheuvel .base = { 1252c98833aSArd Biesheuvel .cra_name = "sha1", 1262c98833aSArd Biesheuvel .cra_driver_name = "sha1-ce", 1272c98833aSArd Biesheuvel .cra_priority = 200, 1282c98833aSArd Biesheuvel .cra_blocksize = SHA1_BLOCK_SIZE, 1292c98833aSArd Biesheuvel .cra_module = THIS_MODULE, 1302c98833aSArd Biesheuvel } 1312c98833aSArd Biesheuvel }; 1322c98833aSArd Biesheuvel 1332c98833aSArd Biesheuvel static int __init sha1_ce_mod_init(void) 1342c98833aSArd Biesheuvel { 1352c98833aSArd Biesheuvel return crypto_register_shash(&alg); 1362c98833aSArd Biesheuvel } 1372c98833aSArd Biesheuvel 1382c98833aSArd Biesheuvel static void __exit sha1_ce_mod_fini(void) 1392c98833aSArd Biesheuvel { 1402c98833aSArd Biesheuvel crypto_unregister_shash(&alg); 1412c98833aSArd Biesheuvel } 1422c98833aSArd Biesheuvel 1432c98833aSArd Biesheuvel module_cpu_feature_match(SHA1, sha1_ce_mod_init); 1442c98833aSArd Biesheuvel module_exit(sha1_ce_mod_fini); 145