2014-03-20 15:35:40 +01:00
/*
* sha2 - ce - glue . c - SHA - 224 / SHA - 256 using ARMv8 Crypto Extensions
*
* Copyright ( C ) 2014 Linaro Ltd < ard . biesheuvel @ linaro . org >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <asm/neon.h>
# include <asm/unaligned.h>
# include <crypto/internal/hash.h>
# include <crypto/sha.h>
2015-04-09 12:55:45 +02:00
# include <crypto/sha256_base.h>
2014-03-20 15:35:40 +01:00
# include <linux/cpufeature.h>
# include <linux/crypto.h>
# include <linux/module.h>
MODULE_DESCRIPTION ( " SHA-224/SHA-256 secure hash using ARMv8 Crypto Extensions " ) ;
MODULE_AUTHOR ( " Ard Biesheuvel <ard.biesheuvel@linaro.org> " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
2015-04-09 12:55:45 +02:00
struct sha256_ce_state {
struct sha256_state sst ;
u32 finalize ;
} ;
2014-03-20 15:35:40 +01:00
2015-04-09 12:55:45 +02:00
asmlinkage void sha2_ce_transform ( struct sha256_ce_state * sst , u8 const * src ,
int blocks ) ;
2014-03-20 15:35:40 +01:00
2017-04-26 17:11:32 +01:00
const u32 sha256_ce_offsetof_count = offsetof ( struct sha256_ce_state ,
sst . count ) ;
const u32 sha256_ce_offsetof_finalize = offsetof ( struct sha256_ce_state ,
finalize ) ;
2015-04-09 12:55:45 +02:00
static int sha256_ce_update ( struct shash_desc * desc , const u8 * data ,
unsigned int len )
2014-03-20 15:35:40 +01:00
{
2015-04-09 12:55:45 +02:00
struct sha256_ce_state * sctx = shash_desc_ctx ( desc ) ;
2014-03-20 15:35:40 +01:00
2015-04-09 12:55:45 +02:00
sctx - > finalize = 0 ;
kernel_neon_begin_partial ( 28 ) ;
sha256_base_do_update ( desc , data , len ,
( sha256_block_fn * ) sha2_ce_transform ) ;
kernel_neon_end ( ) ;
2014-03-20 15:35:40 +01:00
return 0 ;
}
2015-04-09 12:55:45 +02:00
static int sha256_ce_finup ( struct shash_desc * desc , const u8 * data ,
unsigned int len , u8 * out )
2014-03-20 15:35:40 +01:00
{
2015-04-09 12:55:45 +02:00
struct sha256_ce_state * sctx = shash_desc_ctx ( desc ) ;
bool finalize = ! sctx - > sst . count & & ! ( len % SHA256_BLOCK_SIZE ) ;
2014-03-20 15:35:40 +01:00
/*
2015-04-09 12:55:45 +02:00
* Allow the asm code to perform the finalization if there is no
* partial data and the input is a round multiple of the block size .
2014-03-20 15:35:40 +01:00
*/
2015-04-09 12:55:45 +02:00
sctx - > finalize = finalize ;
2014-03-20 15:35:40 +01:00
kernel_neon_begin_partial ( 28 ) ;
2015-04-09 12:55:45 +02:00
sha256_base_do_update ( desc , data , len ,
( sha256_block_fn * ) sha2_ce_transform ) ;
if ( ! finalize )
sha256_base_do_finalize ( desc ,
( sha256_block_fn * ) sha2_ce_transform ) ;
2014-03-20 15:35:40 +01:00
kernel_neon_end ( ) ;
2015-04-09 12:55:45 +02:00
return sha256_base_finish ( desc , out ) ;
2014-03-20 15:35:40 +01:00
}
2015-04-09 12:55:45 +02:00
static int sha256_ce_final ( struct shash_desc * desc , u8 * out )
2014-03-20 15:35:40 +01:00
{
2015-05-06 15:54:32 +02:00
struct sha256_ce_state * sctx = shash_desc_ctx ( desc ) ;
sctx - > finalize = 0 ;
2015-04-09 12:55:45 +02:00
kernel_neon_begin_partial ( 28 ) ;
sha256_base_do_finalize ( desc , ( sha256_block_fn * ) sha2_ce_transform ) ;
kernel_neon_end ( ) ;
return sha256_base_finish ( desc , out ) ;
2014-03-20 15:35:40 +01:00
}
static struct shash_alg algs [ ] = { {
2015-04-09 12:55:45 +02:00
. init = sha224_base_init ,
. update = sha256_ce_update ,
. final = sha256_ce_final ,
. finup = sha256_ce_finup ,
. descsize = sizeof ( struct sha256_ce_state ) ,
2014-03-20 15:35:40 +01:00
. digestsize = SHA224_DIGEST_SIZE ,
. base = {
. cra_name = " sha224 " ,
. cra_driver_name = " sha224-ce " ,
. cra_priority = 200 ,
. cra_flags = CRYPTO_ALG_TYPE_SHASH ,
. cra_blocksize = SHA256_BLOCK_SIZE ,
. cra_module = THIS_MODULE ,
}
} , {
2015-04-09 12:55:45 +02:00
. init = sha256_base_init ,
. update = sha256_ce_update ,
. final = sha256_ce_final ,
. finup = sha256_ce_finup ,
. descsize = sizeof ( struct sha256_ce_state ) ,
2014-03-20 15:35:40 +01:00
. digestsize = SHA256_DIGEST_SIZE ,
. base = {
. cra_name = " sha256 " ,
. cra_driver_name = " sha256-ce " ,
. cra_priority = 200 ,
. cra_flags = CRYPTO_ALG_TYPE_SHASH ,
. cra_blocksize = SHA256_BLOCK_SIZE ,
. cra_module = THIS_MODULE ,
}
} } ;
static int __init sha2_ce_mod_init ( void )
{
return crypto_register_shashes ( algs , ARRAY_SIZE ( algs ) ) ;
}
static void __exit sha2_ce_mod_fini ( void )
{
crypto_unregister_shashes ( algs , ARRAY_SIZE ( algs ) ) ;
}
module_cpu_feature_match ( SHA2 , sha2_ce_mod_init ) ;
module_exit ( sha2_ce_mod_fini ) ;