2022-07-04 12:42:48 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Cryptographic API .
*
* ARIA Cipher Algorithm .
*
* Documentation of ARIA can be found in RFC 5794.
* Copyright ( c ) 2022 Taehee Yoo < ap420073 @ gmail . com >
*
* Information for ARIA
* http : //210.104.33.10/ARIA/index-e.html (English)
* http : //seed.kisa.or.kr/ (Korean)
*
* Public domain version is distributed above .
*/
# include <crypto/aria.h>
2022-09-16 15:57:34 +03:00
static const u32 key_rc [ 20 ] = {
0x517cc1b7 , 0x27220a94 , 0xfe13abe8 , 0xfa9a6ee0 ,
0x6db14acc , 0x9e21c820 , 0xff28b1d5 , 0xef5de2b0 ,
0xdb92371d , 0x2126e970 , 0x03249775 , 0x04e8c90e ,
0x517cc1b7 , 0x27220a94 , 0xfe13abe8 , 0xfa9a6ee0 ,
0x6db14acc , 0x9e21c820 , 0xff28b1d5 , 0xef5de2b0
} ;
2022-07-04 12:42:48 +03:00
static void aria_set_encrypt_key ( struct aria_ctx * ctx , const u8 * in_key ,
unsigned int key_len )
{
const __be32 * key = ( const __be32 * ) in_key ;
u32 w0 [ 4 ] , w1 [ 4 ] , w2 [ 4 ] , w3 [ 4 ] ;
u32 reg0 , reg1 , reg2 , reg3 ;
const u32 * ck ;
int rkidx = 0 ;
2022-09-16 15:57:34 +03:00
ck = & key_rc [ ( key_len - 16 ) / 2 ] ;
2022-07-04 12:42:48 +03:00
w0 [ 0 ] = be32_to_cpu ( key [ 0 ] ) ;
w0 [ 1 ] = be32_to_cpu ( key [ 1 ] ) ;
w0 [ 2 ] = be32_to_cpu ( key [ 2 ] ) ;
w0 [ 3 ] = be32_to_cpu ( key [ 3 ] ) ;
reg0 = w0 [ 0 ] ^ ck [ 0 ] ;
reg1 = w0 [ 1 ] ^ ck [ 1 ] ;
reg2 = w0 [ 2 ] ^ ck [ 2 ] ;
reg3 = w0 [ 3 ] ^ ck [ 3 ] ;
aria_subst_diff_odd ( & reg0 , & reg1 , & reg2 , & reg3 ) ;
if ( key_len > 16 ) {
w1 [ 0 ] = be32_to_cpu ( key [ 4 ] ) ;
w1 [ 1 ] = be32_to_cpu ( key [ 5 ] ) ;
if ( key_len > 24 ) {
w1 [ 2 ] = be32_to_cpu ( key [ 6 ] ) ;
w1 [ 3 ] = be32_to_cpu ( key [ 7 ] ) ;
} else {
w1 [ 2 ] = 0 ;
w1 [ 3 ] = 0 ;
}
} else {
w1 [ 0 ] = 0 ;
w1 [ 1 ] = 0 ;
w1 [ 2 ] = 0 ;
w1 [ 3 ] = 0 ;
}
w1 [ 0 ] ^ = reg0 ;
w1 [ 1 ] ^ = reg1 ;
w1 [ 2 ] ^ = reg2 ;
w1 [ 3 ] ^ = reg3 ;
reg0 = w1 [ 0 ] ;
reg1 = w1 [ 1 ] ;
reg2 = w1 [ 2 ] ;
reg3 = w1 [ 3 ] ;
reg0 ^ = ck [ 4 ] ;
reg1 ^ = ck [ 5 ] ;
reg2 ^ = ck [ 6 ] ;
reg3 ^ = ck [ 7 ] ;
aria_subst_diff_even ( & reg0 , & reg1 , & reg2 , & reg3 ) ;
reg0 ^ = w0 [ 0 ] ;
reg1 ^ = w0 [ 1 ] ;
reg2 ^ = w0 [ 2 ] ;
reg3 ^ = w0 [ 3 ] ;
w2 [ 0 ] = reg0 ;
w2 [ 1 ] = reg1 ;
w2 [ 2 ] = reg2 ;
w2 [ 3 ] = reg3 ;
reg0 ^ = ck [ 8 ] ;
reg1 ^ = ck [ 9 ] ;
reg2 ^ = ck [ 10 ] ;
reg3 ^ = ck [ 11 ] ;
aria_subst_diff_odd ( & reg0 , & reg1 , & reg2 , & reg3 ) ;
w3 [ 0 ] = reg0 ^ w1 [ 0 ] ;
w3 [ 1 ] = reg1 ^ w1 [ 1 ] ;
w3 [ 2 ] = reg2 ^ w1 [ 2 ] ;
w3 [ 3 ] = reg3 ^ w1 [ 3 ] ;
aria_gsrk ( ctx - > enc_key [ rkidx ] , w0 , w1 , 19 ) ;
rkidx + + ;
aria_gsrk ( ctx - > enc_key [ rkidx ] , w1 , w2 , 19 ) ;
rkidx + + ;
aria_gsrk ( ctx - > enc_key [ rkidx ] , w2 , w3 , 19 ) ;
rkidx + + ;
aria_gsrk ( ctx - > enc_key [ rkidx ] , w3 , w0 , 19 ) ;
rkidx + + ;
aria_gsrk ( ctx - > enc_key [ rkidx ] , w0 , w1 , 31 ) ;
rkidx + + ;
aria_gsrk ( ctx - > enc_key [ rkidx ] , w1 , w2 , 31 ) ;
rkidx + + ;
aria_gsrk ( ctx - > enc_key [ rkidx ] , w2 , w3 , 31 ) ;
rkidx + + ;
aria_gsrk ( ctx - > enc_key [ rkidx ] , w3 , w0 , 31 ) ;
rkidx + + ;
aria_gsrk ( ctx - > enc_key [ rkidx ] , w0 , w1 , 67 ) ;
rkidx + + ;
aria_gsrk ( ctx - > enc_key [ rkidx ] , w1 , w2 , 67 ) ;
rkidx + + ;
aria_gsrk ( ctx - > enc_key [ rkidx ] , w2 , w3 , 67 ) ;
rkidx + + ;
aria_gsrk ( ctx - > enc_key [ rkidx ] , w3 , w0 , 67 ) ;
rkidx + + ;
aria_gsrk ( ctx - > enc_key [ rkidx ] , w0 , w1 , 97 ) ;
if ( key_len > 16 ) {
rkidx + + ;
aria_gsrk ( ctx - > enc_key [ rkidx ] , w1 , w2 , 97 ) ;
rkidx + + ;
aria_gsrk ( ctx - > enc_key [ rkidx ] , w2 , w3 , 97 ) ;
if ( key_len > 24 ) {
rkidx + + ;
aria_gsrk ( ctx - > enc_key [ rkidx ] , w3 , w0 , 97 ) ;
rkidx + + ;
aria_gsrk ( ctx - > enc_key [ rkidx ] , w0 , w1 , 109 ) ;
}
}
}
static void aria_set_decrypt_key ( struct aria_ctx * ctx )
{
int i ;
for ( i = 0 ; i < 4 ; i + + ) {
ctx - > dec_key [ 0 ] [ i ] = ctx - > enc_key [ ctx - > rounds ] [ i ] ;
ctx - > dec_key [ ctx - > rounds ] [ i ] = ctx - > enc_key [ 0 ] [ i ] ;
}
for ( i = 1 ; i < ctx - > rounds ; i + + ) {
ctx - > dec_key [ i ] [ 0 ] = aria_m ( ctx - > enc_key [ ctx - > rounds - i ] [ 0 ] ) ;
ctx - > dec_key [ i ] [ 1 ] = aria_m ( ctx - > enc_key [ ctx - > rounds - i ] [ 1 ] ) ;
ctx - > dec_key [ i ] [ 2 ] = aria_m ( ctx - > enc_key [ ctx - > rounds - i ] [ 2 ] ) ;
ctx - > dec_key [ i ] [ 3 ] = aria_m ( ctx - > enc_key [ ctx - > rounds - i ] [ 3 ] ) ;
aria_diff_word ( & ctx - > dec_key [ i ] [ 0 ] , & ctx - > dec_key [ i ] [ 1 ] ,
& ctx - > dec_key [ i ] [ 2 ] , & ctx - > dec_key [ i ] [ 3 ] ) ;
aria_diff_byte ( & ctx - > dec_key [ i ] [ 1 ] ,
& ctx - > dec_key [ i ] [ 2 ] , & ctx - > dec_key [ i ] [ 3 ] ) ;
aria_diff_word ( & ctx - > dec_key [ i ] [ 0 ] , & ctx - > dec_key [ i ] [ 1 ] ,
& ctx - > dec_key [ i ] [ 2 ] , & ctx - > dec_key [ i ] [ 3 ] ) ;
}
}
2022-09-16 15:57:34 +03:00
int aria_set_key ( struct crypto_tfm * tfm , const u8 * in_key , unsigned int key_len )
2022-07-04 12:42:48 +03:00
{
struct aria_ctx * ctx = crypto_tfm_ctx ( tfm ) ;
if ( key_len ! = 16 & & key_len ! = 24 & & key_len ! = 32 )
return - EINVAL ;
2023-01-01 12:12:50 +03:00
BUILD_BUG_ON ( sizeof ( ctx - > enc_key ) ! = 272 ) ;
BUILD_BUG_ON ( sizeof ( ctx - > dec_key ) ! = 272 ) ;
BUILD_BUG_ON ( sizeof ( int ) ! = sizeof ( ctx - > rounds ) ) ;
2022-07-04 12:42:48 +03:00
ctx - > key_length = key_len ;
ctx - > rounds = ( key_len + 32 ) / 4 ;
aria_set_encrypt_key ( ctx , in_key , key_len ) ;
aria_set_decrypt_key ( ctx ) ;
return 0 ;
}
2022-09-16 15:57:34 +03:00
EXPORT_SYMBOL_GPL ( aria_set_key ) ;
2022-07-04 12:42:48 +03:00
static void __aria_crypt ( struct aria_ctx * ctx , u8 * out , const u8 * in ,
u32 key [ ] [ ARIA_RD_KEY_WORDS ] )
{
const __be32 * src = ( const __be32 * ) in ;
__be32 * dst = ( __be32 * ) out ;
u32 reg0 , reg1 , reg2 , reg3 ;
int rounds , rkidx = 0 ;
rounds = ctx - > rounds ;
reg0 = be32_to_cpu ( src [ 0 ] ) ;
reg1 = be32_to_cpu ( src [ 1 ] ) ;
reg2 = be32_to_cpu ( src [ 2 ] ) ;
reg3 = be32_to_cpu ( src [ 3 ] ) ;
aria_add_round_key ( key [ rkidx ] , & reg0 , & reg1 , & reg2 , & reg3 ) ;
rkidx + + ;
aria_subst_diff_odd ( & reg0 , & reg1 , & reg2 , & reg3 ) ;
aria_add_round_key ( key [ rkidx ] , & reg0 , & reg1 , & reg2 , & reg3 ) ;
rkidx + + ;
while ( ( rounds - = 2 ) > 0 ) {
aria_subst_diff_even ( & reg0 , & reg1 , & reg2 , & reg3 ) ;
aria_add_round_key ( key [ rkidx ] , & reg0 , & reg1 , & reg2 , & reg3 ) ;
rkidx + + ;
aria_subst_diff_odd ( & reg0 , & reg1 , & reg2 , & reg3 ) ;
aria_add_round_key ( key [ rkidx ] , & reg0 , & reg1 , & reg2 , & reg3 ) ;
rkidx + + ;
}
reg0 = key [ rkidx ] [ 0 ] ^ make_u32 ( ( u8 ) ( x1 [ get_u8 ( reg0 , 0 ) ] ) ,
( u8 ) ( x2 [ get_u8 ( reg0 , 1 ) ] > > 8 ) ,
( u8 ) ( s1 [ get_u8 ( reg0 , 2 ) ] ) ,
( u8 ) ( s2 [ get_u8 ( reg0 , 3 ) ] ) ) ;
reg1 = key [ rkidx ] [ 1 ] ^ make_u32 ( ( u8 ) ( x1 [ get_u8 ( reg1 , 0 ) ] ) ,
( u8 ) ( x2 [ get_u8 ( reg1 , 1 ) ] > > 8 ) ,
( u8 ) ( s1 [ get_u8 ( reg1 , 2 ) ] ) ,
( u8 ) ( s2 [ get_u8 ( reg1 , 3 ) ] ) ) ;
reg2 = key [ rkidx ] [ 2 ] ^ make_u32 ( ( u8 ) ( x1 [ get_u8 ( reg2 , 0 ) ] ) ,
( u8 ) ( x2 [ get_u8 ( reg2 , 1 ) ] > > 8 ) ,
( u8 ) ( s1 [ get_u8 ( reg2 , 2 ) ] ) ,
( u8 ) ( s2 [ get_u8 ( reg2 , 3 ) ] ) ) ;
reg3 = key [ rkidx ] [ 3 ] ^ make_u32 ( ( u8 ) ( x1 [ get_u8 ( reg3 , 0 ) ] ) ,
( u8 ) ( x2 [ get_u8 ( reg3 , 1 ) ] > > 8 ) ,
( u8 ) ( s1 [ get_u8 ( reg3 , 2 ) ] ) ,
( u8 ) ( s2 [ get_u8 ( reg3 , 3 ) ] ) ) ;
dst [ 0 ] = cpu_to_be32 ( reg0 ) ;
dst [ 1 ] = cpu_to_be32 ( reg1 ) ;
dst [ 2 ] = cpu_to_be32 ( reg2 ) ;
dst [ 3 ] = cpu_to_be32 ( reg3 ) ;
}
2022-09-16 15:57:34 +03:00
void aria_encrypt ( void * _ctx , u8 * out , const u8 * in )
{
struct aria_ctx * ctx = ( struct aria_ctx * ) _ctx ;
__aria_crypt ( ctx , out , in , ctx - > enc_key ) ;
}
EXPORT_SYMBOL_GPL ( aria_encrypt ) ;
void aria_decrypt ( void * _ctx , u8 * out , const u8 * in )
{
struct aria_ctx * ctx = ( struct aria_ctx * ) _ctx ;
__aria_crypt ( ctx , out , in , ctx - > dec_key ) ;
}
EXPORT_SYMBOL_GPL ( aria_decrypt ) ;
static void __aria_encrypt ( struct crypto_tfm * tfm , u8 * out , const u8 * in )
2022-07-04 12:42:48 +03:00
{
struct aria_ctx * ctx = crypto_tfm_ctx ( tfm ) ;
__aria_crypt ( ctx , out , in , ctx - > enc_key ) ;
}
2022-09-16 15:57:34 +03:00
static void __aria_decrypt ( struct crypto_tfm * tfm , u8 * out , const u8 * in )
2022-07-04 12:42:48 +03:00
{
struct aria_ctx * ctx = crypto_tfm_ctx ( tfm ) ;
__aria_crypt ( ctx , out , in , ctx - > dec_key ) ;
}
static struct crypto_alg aria_alg = {
. cra_name = " aria " ,
. cra_driver_name = " aria-generic " ,
. cra_priority = 100 ,
. cra_flags = CRYPTO_ALG_TYPE_CIPHER ,
. cra_blocksize = ARIA_BLOCK_SIZE ,
. cra_ctxsize = sizeof ( struct aria_ctx ) ,
. cra_alignmask = 3 ,
. cra_module = THIS_MODULE ,
. cra_u = {
. cipher = {
. cia_min_keysize = ARIA_MIN_KEY_SIZE ,
. cia_max_keysize = ARIA_MAX_KEY_SIZE ,
. cia_setkey = aria_set_key ,
2022-09-16 15:57:34 +03:00
. cia_encrypt = __aria_encrypt ,
. cia_decrypt = __aria_decrypt
2022-07-04 12:42:48 +03:00
}
}
} ;
static int __init aria_init ( void )
{
return crypto_register_alg ( & aria_alg ) ;
}
static void __exit aria_fini ( void )
{
crypto_unregister_alg ( & aria_alg ) ;
}
subsys_initcall ( aria_init ) ;
module_exit ( aria_fini ) ;
MODULE_DESCRIPTION ( " ARIA Cipher Algorithm " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " Taehee Yoo <ap420073@gmail.com> " ) ;
MODULE_ALIAS_CRYPTO ( " aria " ) ;
2022-09-16 15:57:34 +03:00
MODULE_ALIAS_CRYPTO ( " aria-generic " ) ;