2015-03-10 09:47:45 +01:00
/*
* sha1 - ce - glue . c - SHA - 1 secure hash using ARMv8 Crypto Extensions
*
* Copyright ( C ) 2015 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 <crypto/internal/hash.h>
# include <crypto/sha.h>
2015-04-09 12:55:41 +02:00
# include <crypto/sha1_base.h>
2017-05-21 10:23:38 +00:00
# include <linux/cpufeature.h>
2015-03-10 09:47:45 +01:00
# include <linux/crypto.h>
# include <linux/module.h>
# include <asm/hwcap.h>
# include <asm/neon.h>
# include <asm/simd.h>
2015-04-09 12:55:39 +02:00
# include "sha1.h"
2015-03-10 09:47:45 +01:00
MODULE_DESCRIPTION ( " SHA1 secure hash using ARMv8 Crypto Extensions " ) ;
MODULE_AUTHOR ( " Ard Biesheuvel <ard.biesheuvel@linaro.org> " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
2015-04-09 12:55:41 +02:00
asmlinkage void sha1_ce_transform ( struct sha1_state * sst , u8 const * src ,
int blocks ) ;
2015-03-10 09:47:45 +01:00
2015-04-09 12:55:41 +02:00
static int sha1_ce_update ( struct shash_desc * desc , const u8 * data ,
unsigned int len )
2015-03-10 09:47:45 +01:00
{
struct sha1_state * sctx = shash_desc_ctx ( desc ) ;
2015-04-09 12:55:41 +02:00
if ( ! may_use_simd ( ) | |
( sctx - > count % SHA1_BLOCK_SIZE ) + len < SHA1_BLOCK_SIZE )
2015-03-10 09:47:45 +01:00
return sha1_update_arm ( desc , data , len ) ;
2015-04-09 12:55:41 +02:00
kernel_neon_begin ( ) ;
sha1_base_do_update ( desc , data , len , sha1_ce_transform ) ;
kernel_neon_end ( ) ;
2015-03-10 09:47:45 +01:00
return 0 ;
}
2015-04-09 12:55:41 +02:00
static int sha1_ce_finup ( struct shash_desc * desc , const u8 * data ,
unsigned int len , u8 * out )
2015-03-10 09:47:45 +01:00
{
2015-04-09 12:55:41 +02:00
if ( ! may_use_simd ( ) )
return sha1_finup_arm ( desc , data , len , out ) ;
2015-03-10 09:47:45 +01:00
2015-04-09 12:55:41 +02:00
kernel_neon_begin ( ) ;
if ( len )
sha1_base_do_update ( desc , data , len , sha1_ce_transform ) ;
sha1_base_do_finalize ( desc , sha1_ce_transform ) ;
kernel_neon_end ( ) ;
2015-03-10 09:47:45 +01:00
2015-04-09 12:55:41 +02:00
return sha1_base_finish ( desc , out ) ;
2015-03-10 09:47:45 +01:00
}
2015-04-09 12:55:41 +02:00
static int sha1_ce_final ( struct shash_desc * desc , u8 * out )
2015-03-10 09:47:45 +01:00
{
2015-04-09 12:55:41 +02:00
return sha1_ce_finup ( desc , NULL , 0 , out ) ;
2015-03-10 09:47:45 +01:00
}
static struct shash_alg alg = {
2015-04-09 12:55:41 +02:00
. init = sha1_base_init ,
. update = sha1_ce_update ,
. final = sha1_ce_final ,
. finup = sha1_ce_finup ,
2015-03-10 09:47:45 +01:00
. descsize = sizeof ( struct sha1_state ) ,
. digestsize = SHA1_DIGEST_SIZE ,
. base = {
. cra_name = " sha1 " ,
. cra_driver_name = " sha1-ce " ,
. cra_priority = 200 ,
. cra_blocksize = SHA1_BLOCK_SIZE ,
. cra_module = THIS_MODULE ,
}
} ;
static int __init sha1_ce_mod_init ( void )
{
return crypto_register_shash ( & alg ) ;
}
static void __exit sha1_ce_mod_fini ( void )
{
crypto_unregister_shash ( & alg ) ;
}
2017-05-21 10:23:38 +00:00
module_cpu_feature_match ( SHA1 , sha1_ce_mod_init ) ;
2015-03-10 09:47:45 +01:00
module_exit ( sha1_ce_mod_fini ) ;