1*2c98833aSArd Biesheuvel /* 2*2c98833aSArd Biesheuvel * sha1-ce-glue.c - SHA-1 secure hash using ARMv8 Crypto Extensions 3*2c98833aSArd Biesheuvel * 4*2c98833aSArd Biesheuvel * Copyright (C) 2014 Linaro Ltd <ard.biesheuvel@linaro.org> 5*2c98833aSArd Biesheuvel * 6*2c98833aSArd Biesheuvel * This program is free software; you can redistribute it and/or modify 7*2c98833aSArd Biesheuvel * it under the terms of the GNU General Public License version 2 as 8*2c98833aSArd Biesheuvel * published by the Free Software Foundation. 9*2c98833aSArd Biesheuvel */ 10*2c98833aSArd Biesheuvel 11*2c98833aSArd Biesheuvel #include <asm/neon.h> 12*2c98833aSArd Biesheuvel #include <asm/unaligned.h> 13*2c98833aSArd Biesheuvel #include <crypto/internal/hash.h> 14*2c98833aSArd Biesheuvel #include <crypto/sha.h> 15*2c98833aSArd Biesheuvel #include <linux/cpufeature.h> 16*2c98833aSArd Biesheuvel #include <linux/crypto.h> 17*2c98833aSArd Biesheuvel #include <linux/module.h> 18*2c98833aSArd Biesheuvel 19*2c98833aSArd Biesheuvel MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions"); 20*2c98833aSArd Biesheuvel MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>"); 21*2c98833aSArd Biesheuvel MODULE_LICENSE("GPL v2"); 22*2c98833aSArd Biesheuvel 23*2c98833aSArd Biesheuvel asmlinkage void sha1_ce_transform(int blocks, u8 const *src, u32 *state, 24*2c98833aSArd Biesheuvel u8 *head, long bytes); 25*2c98833aSArd Biesheuvel 26*2c98833aSArd Biesheuvel static int sha1_init(struct shash_desc *desc) 27*2c98833aSArd Biesheuvel { 28*2c98833aSArd Biesheuvel struct sha1_state *sctx = shash_desc_ctx(desc); 29*2c98833aSArd Biesheuvel 30*2c98833aSArd Biesheuvel *sctx = (struct sha1_state){ 31*2c98833aSArd Biesheuvel .state = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 }, 32*2c98833aSArd Biesheuvel }; 33*2c98833aSArd Biesheuvel return 0; 34*2c98833aSArd Biesheuvel } 35*2c98833aSArd Biesheuvel 36*2c98833aSArd Biesheuvel static int sha1_update(struct shash_desc *desc, const u8 *data, 37*2c98833aSArd Biesheuvel unsigned int len) 38*2c98833aSArd Biesheuvel { 39*2c98833aSArd Biesheuvel struct sha1_state *sctx = shash_desc_ctx(desc); 40*2c98833aSArd Biesheuvel unsigned int partial = sctx->count % SHA1_BLOCK_SIZE; 41*2c98833aSArd Biesheuvel 42*2c98833aSArd Biesheuvel sctx->count += len; 43*2c98833aSArd Biesheuvel 44*2c98833aSArd Biesheuvel if ((partial + len) >= SHA1_BLOCK_SIZE) { 45*2c98833aSArd Biesheuvel int blocks; 46*2c98833aSArd Biesheuvel 47*2c98833aSArd Biesheuvel if (partial) { 48*2c98833aSArd Biesheuvel int p = SHA1_BLOCK_SIZE - partial; 49*2c98833aSArd Biesheuvel 50*2c98833aSArd Biesheuvel memcpy(sctx->buffer + partial, data, p); 51*2c98833aSArd Biesheuvel data += p; 52*2c98833aSArd Biesheuvel len -= p; 53*2c98833aSArd Biesheuvel } 54*2c98833aSArd Biesheuvel 55*2c98833aSArd Biesheuvel blocks = len / SHA1_BLOCK_SIZE; 56*2c98833aSArd Biesheuvel len %= SHA1_BLOCK_SIZE; 57*2c98833aSArd Biesheuvel 58*2c98833aSArd Biesheuvel kernel_neon_begin_partial(16); 59*2c98833aSArd Biesheuvel sha1_ce_transform(blocks, data, sctx->state, 60*2c98833aSArd Biesheuvel partial ? sctx->buffer : NULL, 0); 61*2c98833aSArd Biesheuvel kernel_neon_end(); 62*2c98833aSArd Biesheuvel 63*2c98833aSArd Biesheuvel data += blocks * SHA1_BLOCK_SIZE; 64*2c98833aSArd Biesheuvel partial = 0; 65*2c98833aSArd Biesheuvel } 66*2c98833aSArd Biesheuvel if (len) 67*2c98833aSArd Biesheuvel memcpy(sctx->buffer + partial, data, len); 68*2c98833aSArd Biesheuvel return 0; 69*2c98833aSArd Biesheuvel } 70*2c98833aSArd Biesheuvel 71*2c98833aSArd Biesheuvel static int sha1_final(struct shash_desc *desc, u8 *out) 72*2c98833aSArd Biesheuvel { 73*2c98833aSArd Biesheuvel static const u8 padding[SHA1_BLOCK_SIZE] = { 0x80, }; 74*2c98833aSArd Biesheuvel 75*2c98833aSArd Biesheuvel struct sha1_state *sctx = shash_desc_ctx(desc); 76*2c98833aSArd Biesheuvel __be64 bits = cpu_to_be64(sctx->count << 3); 77*2c98833aSArd Biesheuvel __be32 *dst = (__be32 *)out; 78*2c98833aSArd Biesheuvel int i; 79*2c98833aSArd Biesheuvel 80*2c98833aSArd Biesheuvel u32 padlen = SHA1_BLOCK_SIZE 81*2c98833aSArd Biesheuvel - ((sctx->count + sizeof(bits)) % SHA1_BLOCK_SIZE); 82*2c98833aSArd Biesheuvel 83*2c98833aSArd Biesheuvel sha1_update(desc, padding, padlen); 84*2c98833aSArd Biesheuvel sha1_update(desc, (const u8 *)&bits, sizeof(bits)); 85*2c98833aSArd Biesheuvel 86*2c98833aSArd Biesheuvel for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++) 87*2c98833aSArd Biesheuvel put_unaligned_be32(sctx->state[i], dst++); 88*2c98833aSArd Biesheuvel 89*2c98833aSArd Biesheuvel *sctx = (struct sha1_state){}; 90*2c98833aSArd Biesheuvel return 0; 91*2c98833aSArd Biesheuvel } 92*2c98833aSArd Biesheuvel 93*2c98833aSArd Biesheuvel static int sha1_finup(struct shash_desc *desc, const u8 *data, 94*2c98833aSArd Biesheuvel unsigned int len, u8 *out) 95*2c98833aSArd Biesheuvel { 96*2c98833aSArd Biesheuvel struct sha1_state *sctx = shash_desc_ctx(desc); 97*2c98833aSArd Biesheuvel __be32 *dst = (__be32 *)out; 98*2c98833aSArd Biesheuvel int blocks; 99*2c98833aSArd Biesheuvel int i; 100*2c98833aSArd Biesheuvel 101*2c98833aSArd Biesheuvel if (sctx->count || !len || (len % SHA1_BLOCK_SIZE)) { 102*2c98833aSArd Biesheuvel sha1_update(desc, data, len); 103*2c98833aSArd Biesheuvel return sha1_final(desc, out); 104*2c98833aSArd Biesheuvel } 105*2c98833aSArd Biesheuvel 106*2c98833aSArd Biesheuvel /* 107*2c98833aSArd Biesheuvel * Use a fast path if the input is a multiple of 64 bytes. In 108*2c98833aSArd Biesheuvel * this case, there is no need to copy data around, and we can 109*2c98833aSArd Biesheuvel * perform the entire digest calculation in a single invocation 110*2c98833aSArd Biesheuvel * of sha1_ce_transform() 111*2c98833aSArd Biesheuvel */ 112*2c98833aSArd Biesheuvel blocks = len / SHA1_BLOCK_SIZE; 113*2c98833aSArd Biesheuvel 114*2c98833aSArd Biesheuvel kernel_neon_begin_partial(16); 115*2c98833aSArd Biesheuvel sha1_ce_transform(blocks, data, sctx->state, NULL, len); 116*2c98833aSArd Biesheuvel kernel_neon_end(); 117*2c98833aSArd Biesheuvel 118*2c98833aSArd Biesheuvel for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++) 119*2c98833aSArd Biesheuvel put_unaligned_be32(sctx->state[i], dst++); 120*2c98833aSArd Biesheuvel 121*2c98833aSArd Biesheuvel *sctx = (struct sha1_state){}; 122*2c98833aSArd Biesheuvel return 0; 123*2c98833aSArd Biesheuvel } 124*2c98833aSArd Biesheuvel 125*2c98833aSArd Biesheuvel static int sha1_export(struct shash_desc *desc, void *out) 126*2c98833aSArd Biesheuvel { 127*2c98833aSArd Biesheuvel struct sha1_state *sctx = shash_desc_ctx(desc); 128*2c98833aSArd Biesheuvel struct sha1_state *dst = out; 129*2c98833aSArd Biesheuvel 130*2c98833aSArd Biesheuvel *dst = *sctx; 131*2c98833aSArd Biesheuvel return 0; 132*2c98833aSArd Biesheuvel } 133*2c98833aSArd Biesheuvel 134*2c98833aSArd Biesheuvel static int sha1_import(struct shash_desc *desc, const void *in) 135*2c98833aSArd Biesheuvel { 136*2c98833aSArd Biesheuvel struct sha1_state *sctx = shash_desc_ctx(desc); 137*2c98833aSArd Biesheuvel struct sha1_state const *src = in; 138*2c98833aSArd Biesheuvel 139*2c98833aSArd Biesheuvel *sctx = *src; 140*2c98833aSArd Biesheuvel return 0; 141*2c98833aSArd Biesheuvel } 142*2c98833aSArd Biesheuvel 143*2c98833aSArd Biesheuvel static struct shash_alg alg = { 144*2c98833aSArd Biesheuvel .init = sha1_init, 145*2c98833aSArd Biesheuvel .update = sha1_update, 146*2c98833aSArd Biesheuvel .final = sha1_final, 147*2c98833aSArd Biesheuvel .finup = sha1_finup, 148*2c98833aSArd Biesheuvel .export = sha1_export, 149*2c98833aSArd Biesheuvel .import = sha1_import, 150*2c98833aSArd Biesheuvel .descsize = sizeof(struct sha1_state), 151*2c98833aSArd Biesheuvel .digestsize = SHA1_DIGEST_SIZE, 152*2c98833aSArd Biesheuvel .statesize = sizeof(struct sha1_state), 153*2c98833aSArd Biesheuvel .base = { 154*2c98833aSArd Biesheuvel .cra_name = "sha1", 155*2c98833aSArd Biesheuvel .cra_driver_name = "sha1-ce", 156*2c98833aSArd Biesheuvel .cra_priority = 200, 157*2c98833aSArd Biesheuvel .cra_flags = CRYPTO_ALG_TYPE_SHASH, 158*2c98833aSArd Biesheuvel .cra_blocksize = SHA1_BLOCK_SIZE, 159*2c98833aSArd Biesheuvel .cra_module = THIS_MODULE, 160*2c98833aSArd Biesheuvel } 161*2c98833aSArd Biesheuvel }; 162*2c98833aSArd Biesheuvel 163*2c98833aSArd Biesheuvel static int __init sha1_ce_mod_init(void) 164*2c98833aSArd Biesheuvel { 165*2c98833aSArd Biesheuvel return crypto_register_shash(&alg); 166*2c98833aSArd Biesheuvel } 167*2c98833aSArd Biesheuvel 168*2c98833aSArd Biesheuvel static void __exit sha1_ce_mod_fini(void) 169*2c98833aSArd Biesheuvel { 170*2c98833aSArd Biesheuvel crypto_unregister_shash(&alg); 171*2c98833aSArd Biesheuvel } 172*2c98833aSArd Biesheuvel 173*2c98833aSArd Biesheuvel module_cpu_feature_match(SHA1, sha1_ce_mod_init); 174*2c98833aSArd Biesheuvel module_exit(sha1_ce_mod_fini); 175