2016-06-17 08:00:35 +03:00
/*
* Cryptographic API .
*
* SHA - 3 , as specified in
* http : //nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
*
* SHA - 3 code by Jeff Garzik < jeff @ garzik . org >
2018-01-19 15:04:34 +03:00
* Ard Biesheuvel < ard . biesheuvel @ linaro . org >
2016-06-17 08:00:35 +03:00
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation ; either version 2 of the License , or ( at your option ) •
* any later version .
*
*/
# include <crypto/internal/hash.h>
# include <linux/init.h>
# include <linux/module.h>
# include <linux/types.h>
# include <crypto/sha3.h>
2018-01-19 15:04:33 +03:00
# include <asm/unaligned.h>
2016-06-17 08:00:35 +03:00
# define KECCAK_ROUNDS 24
static const u64 keccakf_rndc [ 24 ] = {
2016-08-03 20:37:03 +03:00
0x0000000000000001ULL , 0x0000000000008082ULL , 0x800000000000808aULL ,
0x8000000080008000ULL , 0x000000000000808bULL , 0x0000000080000001ULL ,
0x8000000080008081ULL , 0x8000000000008009ULL , 0x000000000000008aULL ,
0x0000000000000088ULL , 0x0000000080008009ULL , 0x000000008000000aULL ,
0x000000008000808bULL , 0x800000000000008bULL , 0x8000000000008089ULL ,
0x8000000000008003ULL , 0x8000000000008002ULL , 0x8000000000000080ULL ,
0x000000000000800aULL , 0x800000008000000aULL , 0x8000000080008081ULL ,
0x8000000000008080ULL , 0x0000000080000001ULL , 0x8000000080008008ULL
2016-06-17 08:00:35 +03:00
} ;
/* update the state with given number of rounds */
2018-01-19 15:04:34 +03:00
static void __attribute__ ( ( __optimize__ ( " O3 " ) ) ) keccakf ( u64 st [ 25 ] )
2016-06-17 08:00:35 +03:00
{
2018-01-19 15:04:34 +03:00
u64 t [ 5 ] , tt , bc [ 5 ] ;
int round ;
2016-06-17 08:00:35 +03:00
for ( round = 0 ; round < KECCAK_ROUNDS ; round + + ) {
/* Theta */
2018-01-19 15:04:34 +03:00
bc [ 0 ] = st [ 0 ] ^ st [ 5 ] ^ st [ 10 ] ^ st [ 15 ] ^ st [ 20 ] ;
bc [ 1 ] = st [ 1 ] ^ st [ 6 ] ^ st [ 11 ] ^ st [ 16 ] ^ st [ 21 ] ;
bc [ 2 ] = st [ 2 ] ^ st [ 7 ] ^ st [ 12 ] ^ st [ 17 ] ^ st [ 22 ] ;
bc [ 3 ] = st [ 3 ] ^ st [ 8 ] ^ st [ 13 ] ^ st [ 18 ] ^ st [ 23 ] ;
bc [ 4 ] = st [ 4 ] ^ st [ 9 ] ^ st [ 14 ] ^ st [ 19 ] ^ st [ 24 ] ;
t [ 0 ] = bc [ 4 ] ^ rol64 ( bc [ 1 ] , 1 ) ;
t [ 1 ] = bc [ 0 ] ^ rol64 ( bc [ 2 ] , 1 ) ;
t [ 2 ] = bc [ 1 ] ^ rol64 ( bc [ 3 ] , 1 ) ;
t [ 3 ] = bc [ 2 ] ^ rol64 ( bc [ 4 ] , 1 ) ;
t [ 4 ] = bc [ 3 ] ^ rol64 ( bc [ 0 ] , 1 ) ;
2016-06-17 08:00:35 +03:00
2018-01-19 15:04:34 +03:00
st [ 0 ] ^ = t [ 0 ] ;
2016-06-17 08:00:35 +03:00
/* Rho Pi */
2018-01-19 15:04:34 +03:00
tt = st [ 1 ] ;
st [ 1 ] = rol64 ( st [ 6 ] ^ t [ 1 ] , 44 ) ;
st [ 6 ] = rol64 ( st [ 9 ] ^ t [ 4 ] , 20 ) ;
st [ 9 ] = rol64 ( st [ 22 ] ^ t [ 2 ] , 61 ) ;
st [ 22 ] = rol64 ( st [ 14 ] ^ t [ 4 ] , 39 ) ;
st [ 14 ] = rol64 ( st [ 20 ] ^ t [ 0 ] , 18 ) ;
st [ 20 ] = rol64 ( st [ 2 ] ^ t [ 2 ] , 62 ) ;
st [ 2 ] = rol64 ( st [ 12 ] ^ t [ 2 ] , 43 ) ;
st [ 12 ] = rol64 ( st [ 13 ] ^ t [ 3 ] , 25 ) ;
st [ 13 ] = rol64 ( st [ 19 ] ^ t [ 4 ] , 8 ) ;
st [ 19 ] = rol64 ( st [ 23 ] ^ t [ 3 ] , 56 ) ;
st [ 23 ] = rol64 ( st [ 15 ] ^ t [ 0 ] , 41 ) ;
st [ 15 ] = rol64 ( st [ 4 ] ^ t [ 4 ] , 27 ) ;
st [ 4 ] = rol64 ( st [ 24 ] ^ t [ 4 ] , 14 ) ;
st [ 24 ] = rol64 ( st [ 21 ] ^ t [ 1 ] , 2 ) ;
st [ 21 ] = rol64 ( st [ 8 ] ^ t [ 3 ] , 55 ) ;
st [ 8 ] = rol64 ( st [ 16 ] ^ t [ 1 ] , 45 ) ;
st [ 16 ] = rol64 ( st [ 5 ] ^ t [ 0 ] , 36 ) ;
st [ 5 ] = rol64 ( st [ 3 ] ^ t [ 3 ] , 28 ) ;
st [ 3 ] = rol64 ( st [ 18 ] ^ t [ 3 ] , 21 ) ;
st [ 18 ] = rol64 ( st [ 17 ] ^ t [ 2 ] , 15 ) ;
st [ 17 ] = rol64 ( st [ 11 ] ^ t [ 1 ] , 10 ) ;
st [ 11 ] = rol64 ( st [ 7 ] ^ t [ 2 ] , 6 ) ;
st [ 7 ] = rol64 ( st [ 10 ] ^ t [ 0 ] , 3 ) ;
st [ 10 ] = rol64 ( tt ^ t [ 1 ] , 1 ) ;
2016-06-17 08:00:35 +03:00
/* Chi */
2018-01-19 15:04:34 +03:00
bc [ 0 ] = ~ st [ 1 ] & st [ 2 ] ;
bc [ 1 ] = ~ st [ 2 ] & st [ 3 ] ;
bc [ 2 ] = ~ st [ 3 ] & st [ 4 ] ;
bc [ 3 ] = ~ st [ 4 ] & st [ 0 ] ;
bc [ 4 ] = ~ st [ 0 ] & st [ 1 ] ;
st [ 0 ] ^ = bc [ 0 ] ;
st [ 1 ] ^ = bc [ 1 ] ;
st [ 2 ] ^ = bc [ 2 ] ;
st [ 3 ] ^ = bc [ 3 ] ;
st [ 4 ] ^ = bc [ 4 ] ;
bc [ 0 ] = ~ st [ 6 ] & st [ 7 ] ;
bc [ 1 ] = ~ st [ 7 ] & st [ 8 ] ;
bc [ 2 ] = ~ st [ 8 ] & st [ 9 ] ;
bc [ 3 ] = ~ st [ 9 ] & st [ 5 ] ;
bc [ 4 ] = ~ st [ 5 ] & st [ 6 ] ;
st [ 5 ] ^ = bc [ 0 ] ;
st [ 6 ] ^ = bc [ 1 ] ;
st [ 7 ] ^ = bc [ 2 ] ;
st [ 8 ] ^ = bc [ 3 ] ;
st [ 9 ] ^ = bc [ 4 ] ;
bc [ 0 ] = ~ st [ 11 ] & st [ 12 ] ;
bc [ 1 ] = ~ st [ 12 ] & st [ 13 ] ;
bc [ 2 ] = ~ st [ 13 ] & st [ 14 ] ;
bc [ 3 ] = ~ st [ 14 ] & st [ 10 ] ;
bc [ 4 ] = ~ st [ 10 ] & st [ 11 ] ;
st [ 10 ] ^ = bc [ 0 ] ;
st [ 11 ] ^ = bc [ 1 ] ;
st [ 12 ] ^ = bc [ 2 ] ;
st [ 13 ] ^ = bc [ 3 ] ;
st [ 14 ] ^ = bc [ 4 ] ;
bc [ 0 ] = ~ st [ 16 ] & st [ 17 ] ;
bc [ 1 ] = ~ st [ 17 ] & st [ 18 ] ;
bc [ 2 ] = ~ st [ 18 ] & st [ 19 ] ;
bc [ 3 ] = ~ st [ 19 ] & st [ 15 ] ;
bc [ 4 ] = ~ st [ 15 ] & st [ 16 ] ;
st [ 15 ] ^ = bc [ 0 ] ;
st [ 16 ] ^ = bc [ 1 ] ;
st [ 17 ] ^ = bc [ 2 ] ;
st [ 18 ] ^ = bc [ 3 ] ;
st [ 19 ] ^ = bc [ 4 ] ;
bc [ 0 ] = ~ st [ 21 ] & st [ 22 ] ;
bc [ 1 ] = ~ st [ 22 ] & st [ 23 ] ;
bc [ 2 ] = ~ st [ 23 ] & st [ 24 ] ;
bc [ 3 ] = ~ st [ 24 ] & st [ 20 ] ;
bc [ 4 ] = ~ st [ 20 ] & st [ 21 ] ;
st [ 20 ] ^ = bc [ 0 ] ;
st [ 21 ] ^ = bc [ 1 ] ;
st [ 22 ] ^ = bc [ 2 ] ;
st [ 23 ] ^ = bc [ 3 ] ;
st [ 24 ] ^ = bc [ 4 ] ;
2016-06-17 08:00:35 +03:00
/* Iota */
st [ 0 ] ^ = keccakf_rndc [ round ] ;
}
}
2018-01-19 15:04:35 +03:00
static int sha3_init ( struct shash_desc * desc )
2016-06-17 08:00:35 +03:00
{
struct sha3_state * sctx = shash_desc_ctx ( desc ) ;
2018-01-19 15:04:35 +03:00
unsigned int digest_size = crypto_shash_digestsize ( desc - > tfm ) ;
2016-06-17 08:00:35 +03:00
2018-01-19 15:04:35 +03:00
sctx - > rsiz = 200 - 2 * digest_size ;
sctx - > rsizw = sctx - > rsiz / 8 ;
sctx - > partial = 0 ;
2016-06-17 08:00:35 +03:00
2018-01-19 15:04:35 +03:00
memset ( sctx - > st , 0 , sizeof ( sctx - > st ) ) ;
2016-06-17 08:00:35 +03:00
return 0 ;
}
static int sha3_update ( struct shash_desc * desc , const u8 * data ,
unsigned int len )
{
struct sha3_state * sctx = shash_desc_ctx ( desc ) ;
unsigned int done ;
const u8 * src ;
done = 0 ;
src = data ;
if ( ( sctx - > partial + len ) > ( sctx - > rsiz - 1 ) ) {
if ( sctx - > partial ) {
done = - sctx - > partial ;
memcpy ( sctx - > buf + sctx - > partial , data ,
done + sctx - > rsiz ) ;
src = sctx - > buf ;
}
do {
unsigned int i ;
for ( i = 0 ; i < sctx - > rsizw ; i + + )
2018-01-19 15:04:33 +03:00
sctx - > st [ i ] ^ = get_unaligned_le64 ( src + 8 * i ) ;
2016-06-17 08:00:35 +03:00
keccakf ( sctx - > st ) ;
done + = sctx - > rsiz ;
src = data + done ;
} while ( done + ( sctx - > rsiz - 1 ) < len ) ;
sctx - > partial = 0 ;
}
memcpy ( sctx - > buf + sctx - > partial , src , len - done ) ;
sctx - > partial + = ( len - done ) ;
return 0 ;
}
static int sha3_final ( struct shash_desc * desc , u8 * out )
{
struct sha3_state * sctx = shash_desc_ctx ( desc ) ;
unsigned int i , inlen = sctx - > partial ;
2018-01-19 15:04:35 +03:00
unsigned int digest_size = crypto_shash_digestsize ( desc - > tfm ) ;
__le64 * digest = ( __le64 * ) out ;
2016-06-17 08:00:35 +03:00
sctx - > buf [ inlen + + ] = 0x06 ;
memset ( sctx - > buf + inlen , 0 , sctx - > rsiz - inlen ) ;
sctx - > buf [ sctx - > rsiz - 1 ] | = 0x80 ;
for ( i = 0 ; i < sctx - > rsizw ; i + + )
2018-01-19 15:04:33 +03:00
sctx - > st [ i ] ^ = get_unaligned_le64 ( sctx - > buf + 8 * i ) ;
2016-06-17 08:00:35 +03:00
keccakf ( sctx - > st ) ;
2018-01-19 15:04:35 +03:00
for ( i = 0 ; i < digest_size / 8 ; i + + )
put_unaligned_le64 ( sctx - > st [ i ] , digest + + ) ;
2016-06-17 08:00:35 +03:00
2018-01-19 15:04:35 +03:00
if ( digest_size & 4 )
put_unaligned_le32 ( sctx - > st [ i ] , ( __le32 * ) digest ) ;
2016-06-17 08:00:35 +03:00
memset ( sctx , 0 , sizeof ( * sctx ) ) ;
return 0 ;
}
2018-01-19 15:04:35 +03:00
static struct shash_alg algs [ ] = { {
. digestsize = SHA3_224_DIGEST_SIZE ,
. init = sha3_init ,
. update = sha3_update ,
. final = sha3_final ,
. descsize = sizeof ( struct sha3_state ) ,
. base . cra_name = " sha3-224 " ,
. base . cra_driver_name = " sha3-224-generic " ,
. base . cra_flags = CRYPTO_ALG_TYPE_SHASH ,
. base . cra_blocksize = SHA3_224_BLOCK_SIZE ,
. base . cra_module = THIS_MODULE ,
} , {
. digestsize = SHA3_256_DIGEST_SIZE ,
. init = sha3_init ,
. update = sha3_update ,
. final = sha3_final ,
. descsize = sizeof ( struct sha3_state ) ,
. base . cra_name = " sha3-256 " ,
. base . cra_driver_name = " sha3-256-generic " ,
. base . cra_flags = CRYPTO_ALG_TYPE_SHASH ,
. base . cra_blocksize = SHA3_256_BLOCK_SIZE ,
. base . cra_module = THIS_MODULE ,
} , {
. digestsize = SHA3_384_DIGEST_SIZE ,
. init = sha3_init ,
. update = sha3_update ,
. final = sha3_final ,
. descsize = sizeof ( struct sha3_state ) ,
. base . cra_name = " sha3-384 " ,
. base . cra_driver_name = " sha3-384-generic " ,
. base . cra_flags = CRYPTO_ALG_TYPE_SHASH ,
. base . cra_blocksize = SHA3_384_BLOCK_SIZE ,
. base . cra_module = THIS_MODULE ,
} , {
. digestsize = SHA3_512_DIGEST_SIZE ,
. init = sha3_init ,
. update = sha3_update ,
. final = sha3_final ,
. descsize = sizeof ( struct sha3_state ) ,
. base . cra_name = " sha3-512 " ,
. base . cra_driver_name = " sha3-512-generic " ,
. base . cra_flags = CRYPTO_ALG_TYPE_SHASH ,
. base . cra_blocksize = SHA3_512_BLOCK_SIZE ,
. base . cra_module = THIS_MODULE ,
} } ;
2016-06-17 08:00:35 +03:00
static int __init sha3_generic_mod_init ( void )
{
2018-01-19 15:04:35 +03:00
return crypto_register_shashes ( algs , ARRAY_SIZE ( algs ) ) ;
2016-06-17 08:00:35 +03:00
}
static void __exit sha3_generic_mod_fini ( void )
{
2018-01-19 15:04:35 +03:00
crypto_unregister_shashes ( algs , ARRAY_SIZE ( algs ) ) ;
2016-06-17 08:00:35 +03:00
}
module_init ( sha3_generic_mod_init ) ;
module_exit ( sha3_generic_mod_fini ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_DESCRIPTION ( " SHA-3 Secure Hash Algorithm " ) ;
MODULE_ALIAS_CRYPTO ( " sha3-224 " ) ;
MODULE_ALIAS_CRYPTO ( " sha3-224-generic " ) ;
MODULE_ALIAS_CRYPTO ( " sha3-256 " ) ;
MODULE_ALIAS_CRYPTO ( " sha3-256-generic " ) ;
MODULE_ALIAS_CRYPTO ( " sha3-384 " ) ;
MODULE_ALIAS_CRYPTO ( " sha3-384-generic " ) ;
MODULE_ALIAS_CRYPTO ( " sha3-512 " ) ;
MODULE_ALIAS_CRYPTO ( " sha3-512-generic " ) ;