2019-05-27 09:55:05 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2011-11-09 18:26:25 +04:00
/*
* Glue Code for SSE2 assembler versions of Serpent Cipher
*
* Copyright ( c ) 2011 Jussi Kivilinna < jussi . kivilinna @ mbnet . fi >
*
* Glue code based on aesni - intel_glue . c by :
* Copyright ( C ) 2008 , Intel Corp .
* Author : Huang Ying < ying . huang @ intel . com >
*
* CBC & ECB parts based on code ( crypto / cbc . c , ecb . c ) by :
* Copyright ( c ) 2006 Herbert Xu < herbert @ gondor . apana . org . au >
*/
# include <linux/module.h>
# include <linux/types.h>
# include <linux/crypto.h>
# include <linux/err.h>
# include <crypto/algapi.h>
# include <crypto/b128ops.h>
2018-02-20 10:48:03 +03:00
# include <crypto/internal/simd.h>
# include <crypto/serpent.h>
2021-01-05 19:48:04 +03:00
2021-01-05 19:48:09 +03:00
# include "serpent-sse2.h"
2021-01-05 19:48:04 +03:00
# include "ecb_cbc_helpers.h"
2011-11-09 18:26:25 +04:00
2018-02-20 10:48:03 +03:00
static int serpent_setkey_skcipher ( struct crypto_skcipher * tfm ,
const u8 * key , unsigned int keylen )
{
return __serpent_setkey ( crypto_skcipher_ctx ( tfm ) , key , keylen ) ;
}
2021-01-05 19:48:04 +03:00
static void serpent_decrypt_cbc_xway ( const void * ctx , u8 * dst , const u8 * src )
2012-06-18 15:07:14 +04:00
{
2021-01-05 19:48:04 +03:00
u8 buf [ SERPENT_PARALLEL_BLOCKS - 1 ] [ SERPENT_BLOCK_SIZE ] ;
const u8 * s = src ;
2012-06-18 15:07:14 +04:00
2021-01-05 19:48:04 +03:00
if ( dst = = src )
s = memcpy ( buf , src , sizeof ( buf ) ) ;
serpent_dec_blk_xway ( ctx , dst , src ) ;
crypto_xor ( dst + SERPENT_BLOCK_SIZE , s , sizeof ( buf ) ) ;
2012-06-18 15:07:14 +04:00
}
2018-02-20 10:48:03 +03:00
static int ecb_encrypt ( struct skcipher_request * req )
2012-06-18 15:07:14 +04:00
{
2021-01-05 19:48:04 +03:00
ECB_WALK_START ( req , SERPENT_BLOCK_SIZE , SERPENT_PARALLEL_BLOCKS ) ;
ECB_BLOCK ( SERPENT_PARALLEL_BLOCKS , serpent_enc_blk_xway ) ;
ECB_BLOCK ( 1 , __serpent_encrypt ) ;
ECB_WALK_END ( ) ;
2012-06-18 15:07:14 +04:00
}
2018-02-20 10:48:03 +03:00
static int ecb_decrypt ( struct skcipher_request * req )
2012-06-18 15:07:14 +04:00
{
2021-01-05 19:48:04 +03:00
ECB_WALK_START ( req , SERPENT_BLOCK_SIZE , SERPENT_PARALLEL_BLOCKS ) ;
ECB_BLOCK ( SERPENT_PARALLEL_BLOCKS , serpent_dec_blk_xway ) ;
ECB_BLOCK ( 1 , __serpent_decrypt ) ;
ECB_WALK_END ( ) ;
2012-06-18 15:07:14 +04:00
}
2018-02-20 10:48:03 +03:00
static int cbc_encrypt ( struct skcipher_request * req )
2012-06-18 15:07:14 +04:00
{
2021-01-05 19:48:04 +03:00
CBC_WALK_START ( req , SERPENT_BLOCK_SIZE , - 1 ) ;
CBC_ENC_BLOCK ( __serpent_encrypt ) ;
CBC_WALK_END ( ) ;
2012-06-18 15:07:14 +04:00
}
2018-02-20 10:48:03 +03:00
static int cbc_decrypt ( struct skcipher_request * req )
2012-06-18 15:07:14 +04:00
{
2021-01-05 19:48:04 +03:00
CBC_WALK_START ( req , SERPENT_BLOCK_SIZE , SERPENT_PARALLEL_BLOCKS ) ;
CBC_DEC_BLOCK ( SERPENT_PARALLEL_BLOCKS , serpent_decrypt_cbc_xway ) ;
CBC_DEC_BLOCK ( 1 , __serpent_decrypt ) ;
CBC_WALK_END ( ) ;
2012-06-18 15:07:14 +04:00
}
2018-02-20 10:48:03 +03:00
static struct skcipher_alg serpent_algs [ ] = {
{
. base . cra_name = " __ecb(serpent) " ,
. base . cra_driver_name = " __ecb-serpent-sse2 " ,
. base . cra_priority = 400 ,
. base . cra_flags = CRYPTO_ALG_INTERNAL ,
. base . cra_blocksize = SERPENT_BLOCK_SIZE ,
. base . cra_ctxsize = sizeof ( struct serpent_ctx ) ,
. base . cra_module = THIS_MODULE ,
. min_keysize = SERPENT_MIN_KEY_SIZE ,
. max_keysize = SERPENT_MAX_KEY_SIZE ,
. setkey = serpent_setkey_skcipher ,
. encrypt = ecb_encrypt ,
. decrypt = ecb_decrypt ,
} , {
. base . cra_name = " __cbc(serpent) " ,
. base . cra_driver_name = " __cbc-serpent-sse2 " ,
. base . cra_priority = 400 ,
. base . cra_flags = CRYPTO_ALG_INTERNAL ,
. base . cra_blocksize = SERPENT_BLOCK_SIZE ,
. base . cra_ctxsize = sizeof ( struct serpent_ctx ) ,
. base . cra_module = THIS_MODULE ,
. min_keysize = SERPENT_MIN_KEY_SIZE ,
. max_keysize = SERPENT_MAX_KEY_SIZE ,
. ivsize = SERPENT_BLOCK_SIZE ,
. setkey = serpent_setkey_skcipher ,
. encrypt = cbc_encrypt ,
. decrypt = cbc_decrypt ,
2011-11-09 18:26:25 +04:00
} ,
2018-02-20 10:48:03 +03:00
} ;
static struct simd_skcipher_alg * serpent_simd_algs [ ARRAY_SIZE ( serpent_algs ) ] ;
2011-11-09 18:26:41 +04:00
2011-11-09 18:26:25 +04:00
static int __init serpent_sse2_init ( void )
{
2016-03-29 18:42:00 +03:00
if ( ! boot_cpu_has ( X86_FEATURE_XMM2 ) ) {
2011-11-09 18:26:25 +04:00
printk ( KERN_INFO " SSE2 instructions are not detected. \n " ) ;
return - ENODEV ;
}
2018-02-20 10:48:03 +03:00
return simd_register_skciphers_compat ( serpent_algs ,
ARRAY_SIZE ( serpent_algs ) ,
serpent_simd_algs ) ;
2011-11-09 18:26:25 +04:00
}
static void __exit serpent_sse2_exit ( void )
{
2018-02-20 10:48:03 +03:00
simd_unregister_skciphers ( serpent_algs , ARRAY_SIZE ( serpent_algs ) ,
serpent_simd_algs ) ;
2011-11-09 18:26:25 +04:00
}
module_init ( serpent_sse2_init ) ;
module_exit ( serpent_sse2_exit ) ;
MODULE_DESCRIPTION ( " Serpent Cipher Algorithm, SSE2 optimized " ) ;
MODULE_LICENSE ( " GPL " ) ;
2014-11-21 04:05:53 +03:00
MODULE_ALIAS_CRYPTO ( " serpent " ) ;