1*15d5910eSArd Biesheuvel /* SPDX-License-Identifier: GPL-2.0 */ 2*15d5910eSArd Biesheuvel /* 3*15d5910eSArd Biesheuvel * sha3-ce-glue.c - core SHA-3 transform using v8.2 Crypto Extensions 4*15d5910eSArd Biesheuvel * 5*15d5910eSArd Biesheuvel * Copyright (C) 2018 Linaro Ltd <ard.biesheuvel@linaro.org> 6*15d5910eSArd Biesheuvel * 7*15d5910eSArd Biesheuvel * This program is free software; you can redistribute it and/or modify 8*15d5910eSArd Biesheuvel * it under the terms of the GNU General Public License version 2 as 9*15d5910eSArd Biesheuvel * published by the Free Software Foundation. 10*15d5910eSArd Biesheuvel */ 11*15d5910eSArd Biesheuvel 12*15d5910eSArd Biesheuvel #include <asm/hwcap.h> 13*15d5910eSArd Biesheuvel #include <asm/neon.h> 14*15d5910eSArd Biesheuvel #include <asm/simd.h> 15*15d5910eSArd Biesheuvel #include <asm/unaligned.h> 16*15d5910eSArd Biesheuvel #include <crypto/internal/hash.h> 17*15d5910eSArd Biesheuvel #include <crypto/sha3.h> 18*15d5910eSArd Biesheuvel #include <linux/cpufeature.h> 19*15d5910eSArd Biesheuvel #include <linux/crypto.h> 20*15d5910eSArd Biesheuvel #include <linux/module.h> 21*15d5910eSArd Biesheuvel 22*15d5910eSArd Biesheuvel MODULE_DESCRIPTION("SHA3 secure hash using ARMv8 Crypto Extensions"); 23*15d5910eSArd Biesheuvel MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>"); 24*15d5910eSArd Biesheuvel MODULE_LICENSE("GPL v2"); 25*15d5910eSArd Biesheuvel 26*15d5910eSArd Biesheuvel asmlinkage void sha3_ce_transform(u64 *st, const u8 *data, int blocks, 27*15d5910eSArd Biesheuvel int md_len); 28*15d5910eSArd Biesheuvel 29*15d5910eSArd Biesheuvel static int sha3_update(struct shash_desc *desc, const u8 *data, 30*15d5910eSArd Biesheuvel unsigned int len) 31*15d5910eSArd Biesheuvel { 32*15d5910eSArd Biesheuvel struct sha3_state *sctx = shash_desc_ctx(desc); 33*15d5910eSArd Biesheuvel unsigned int digest_size = crypto_shash_digestsize(desc->tfm); 34*15d5910eSArd Biesheuvel 35*15d5910eSArd Biesheuvel if (!may_use_simd()) 36*15d5910eSArd Biesheuvel return crypto_sha3_update(desc, data, len); 37*15d5910eSArd Biesheuvel 38*15d5910eSArd Biesheuvel if ((sctx->partial + len) >= sctx->rsiz) { 39*15d5910eSArd Biesheuvel int blocks; 40*15d5910eSArd Biesheuvel 41*15d5910eSArd Biesheuvel if (sctx->partial) { 42*15d5910eSArd Biesheuvel int p = sctx->rsiz - sctx->partial; 43*15d5910eSArd Biesheuvel 44*15d5910eSArd Biesheuvel memcpy(sctx->buf + sctx->partial, data, p); 45*15d5910eSArd Biesheuvel kernel_neon_begin(); 46*15d5910eSArd Biesheuvel sha3_ce_transform(sctx->st, sctx->buf, 1, digest_size); 47*15d5910eSArd Biesheuvel kernel_neon_end(); 48*15d5910eSArd Biesheuvel 49*15d5910eSArd Biesheuvel data += p; 50*15d5910eSArd Biesheuvel len -= p; 51*15d5910eSArd Biesheuvel sctx->partial = 0; 52*15d5910eSArd Biesheuvel } 53*15d5910eSArd Biesheuvel 54*15d5910eSArd Biesheuvel blocks = len / sctx->rsiz; 55*15d5910eSArd Biesheuvel len %= sctx->rsiz; 56*15d5910eSArd Biesheuvel 57*15d5910eSArd Biesheuvel if (blocks) { 58*15d5910eSArd Biesheuvel kernel_neon_begin(); 59*15d5910eSArd Biesheuvel sha3_ce_transform(sctx->st, data, blocks, digest_size); 60*15d5910eSArd Biesheuvel kernel_neon_end(); 61*15d5910eSArd Biesheuvel data += blocks * sctx->rsiz; 62*15d5910eSArd Biesheuvel } 63*15d5910eSArd Biesheuvel } 64*15d5910eSArd Biesheuvel 65*15d5910eSArd Biesheuvel if (len) { 66*15d5910eSArd Biesheuvel memcpy(sctx->buf + sctx->partial, data, len); 67*15d5910eSArd Biesheuvel sctx->partial += len; 68*15d5910eSArd Biesheuvel } 69*15d5910eSArd Biesheuvel return 0; 70*15d5910eSArd Biesheuvel } 71*15d5910eSArd Biesheuvel 72*15d5910eSArd Biesheuvel static int sha3_final(struct shash_desc *desc, u8 *out) 73*15d5910eSArd Biesheuvel { 74*15d5910eSArd Biesheuvel struct sha3_state *sctx = shash_desc_ctx(desc); 75*15d5910eSArd Biesheuvel unsigned int digest_size = crypto_shash_digestsize(desc->tfm); 76*15d5910eSArd Biesheuvel __le64 *digest = (__le64 *)out; 77*15d5910eSArd Biesheuvel int i; 78*15d5910eSArd Biesheuvel 79*15d5910eSArd Biesheuvel if (!may_use_simd()) 80*15d5910eSArd Biesheuvel return crypto_sha3_final(desc, out); 81*15d5910eSArd Biesheuvel 82*15d5910eSArd Biesheuvel sctx->buf[sctx->partial++] = 0x06; 83*15d5910eSArd Biesheuvel memset(sctx->buf + sctx->partial, 0, sctx->rsiz - sctx->partial); 84*15d5910eSArd Biesheuvel sctx->buf[sctx->rsiz - 1] |= 0x80; 85*15d5910eSArd Biesheuvel 86*15d5910eSArd Biesheuvel kernel_neon_begin(); 87*15d5910eSArd Biesheuvel sha3_ce_transform(sctx->st, sctx->buf, 1, digest_size); 88*15d5910eSArd Biesheuvel kernel_neon_end(); 89*15d5910eSArd Biesheuvel 90*15d5910eSArd Biesheuvel for (i = 0; i < digest_size / 8; i++) 91*15d5910eSArd Biesheuvel put_unaligned_le64(sctx->st[i], digest++); 92*15d5910eSArd Biesheuvel 93*15d5910eSArd Biesheuvel if (digest_size & 4) 94*15d5910eSArd Biesheuvel put_unaligned_le32(sctx->st[i], (__le32 *)digest); 95*15d5910eSArd Biesheuvel 96*15d5910eSArd Biesheuvel *sctx = (struct sha3_state){}; 97*15d5910eSArd Biesheuvel return 0; 98*15d5910eSArd Biesheuvel } 99*15d5910eSArd Biesheuvel 100*15d5910eSArd Biesheuvel static struct shash_alg algs[] = { { 101*15d5910eSArd Biesheuvel .digestsize = SHA3_224_DIGEST_SIZE, 102*15d5910eSArd Biesheuvel .init = crypto_sha3_init, 103*15d5910eSArd Biesheuvel .update = sha3_update, 104*15d5910eSArd Biesheuvel .final = sha3_final, 105*15d5910eSArd Biesheuvel .descsize = sizeof(struct sha3_state), 106*15d5910eSArd Biesheuvel .base.cra_name = "sha3-224", 107*15d5910eSArd Biesheuvel .base.cra_driver_name = "sha3-224-ce", 108*15d5910eSArd Biesheuvel .base.cra_flags = CRYPTO_ALG_TYPE_SHASH, 109*15d5910eSArd Biesheuvel .base.cra_blocksize = SHA3_224_BLOCK_SIZE, 110*15d5910eSArd Biesheuvel .base.cra_module = THIS_MODULE, 111*15d5910eSArd Biesheuvel .base.cra_priority = 200, 112*15d5910eSArd Biesheuvel }, { 113*15d5910eSArd Biesheuvel .digestsize = SHA3_256_DIGEST_SIZE, 114*15d5910eSArd Biesheuvel .init = crypto_sha3_init, 115*15d5910eSArd Biesheuvel .update = sha3_update, 116*15d5910eSArd Biesheuvel .final = sha3_final, 117*15d5910eSArd Biesheuvel .descsize = sizeof(struct sha3_state), 118*15d5910eSArd Biesheuvel .base.cra_name = "sha3-256", 119*15d5910eSArd Biesheuvel .base.cra_driver_name = "sha3-256-ce", 120*15d5910eSArd Biesheuvel .base.cra_flags = CRYPTO_ALG_TYPE_SHASH, 121*15d5910eSArd Biesheuvel .base.cra_blocksize = SHA3_256_BLOCK_SIZE, 122*15d5910eSArd Biesheuvel .base.cra_module = THIS_MODULE, 123*15d5910eSArd Biesheuvel .base.cra_priority = 200, 124*15d5910eSArd Biesheuvel }, { 125*15d5910eSArd Biesheuvel .digestsize = SHA3_384_DIGEST_SIZE, 126*15d5910eSArd Biesheuvel .init = crypto_sha3_init, 127*15d5910eSArd Biesheuvel .update = sha3_update, 128*15d5910eSArd Biesheuvel .final = sha3_final, 129*15d5910eSArd Biesheuvel .descsize = sizeof(struct sha3_state), 130*15d5910eSArd Biesheuvel .base.cra_name = "sha3-384", 131*15d5910eSArd Biesheuvel .base.cra_driver_name = "sha3-384-ce", 132*15d5910eSArd Biesheuvel .base.cra_flags = CRYPTO_ALG_TYPE_SHASH, 133*15d5910eSArd Biesheuvel .base.cra_blocksize = SHA3_384_BLOCK_SIZE, 134*15d5910eSArd Biesheuvel .base.cra_module = THIS_MODULE, 135*15d5910eSArd Biesheuvel .base.cra_priority = 200, 136*15d5910eSArd Biesheuvel }, { 137*15d5910eSArd Biesheuvel .digestsize = SHA3_512_DIGEST_SIZE, 138*15d5910eSArd Biesheuvel .init = crypto_sha3_init, 139*15d5910eSArd Biesheuvel .update = sha3_update, 140*15d5910eSArd Biesheuvel .final = sha3_final, 141*15d5910eSArd Biesheuvel .descsize = sizeof(struct sha3_state), 142*15d5910eSArd Biesheuvel .base.cra_name = "sha3-512", 143*15d5910eSArd Biesheuvel .base.cra_driver_name = "sha3-512-ce", 144*15d5910eSArd Biesheuvel .base.cra_flags = CRYPTO_ALG_TYPE_SHASH, 145*15d5910eSArd Biesheuvel .base.cra_blocksize = SHA3_512_BLOCK_SIZE, 146*15d5910eSArd Biesheuvel .base.cra_module = THIS_MODULE, 147*15d5910eSArd Biesheuvel .base.cra_priority = 200, 148*15d5910eSArd Biesheuvel } }; 149*15d5910eSArd Biesheuvel 150*15d5910eSArd Biesheuvel static int __init sha3_neon_mod_init(void) 151*15d5910eSArd Biesheuvel { 152*15d5910eSArd Biesheuvel return crypto_register_shashes(algs, ARRAY_SIZE(algs)); 153*15d5910eSArd Biesheuvel } 154*15d5910eSArd Biesheuvel 155*15d5910eSArd Biesheuvel static void __exit sha3_neon_mod_fini(void) 156*15d5910eSArd Biesheuvel { 157*15d5910eSArd Biesheuvel crypto_unregister_shashes(algs, ARRAY_SIZE(algs)); 158*15d5910eSArd Biesheuvel } 159*15d5910eSArd Biesheuvel 160*15d5910eSArd Biesheuvel module_cpu_feature_match(SHA3, sha3_neon_mod_init); 161*15d5910eSArd Biesheuvel module_exit(sha3_neon_mod_fini); 162