2019-05-27 09:55:01 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2010-02-16 15:24:30 +03:00
/*
2005-04-17 02:20:36 +04:00
* Cryptographic API .
*
* Blowfish Cipher Algorithm , by Bruce Schneier .
* http : //www.counterpane.com/blowfish.html
*
* Adapted from Kerneli implementation .
*
* Copyright ( c ) Herbert Valerio Riedel < hvr @ hvrlab . org >
* Copyright ( c ) Kyle McMartin < kyle @ debian . org >
* Copyright ( c ) 2002 James Morris < jmorris @ intercode . com . au >
*/
# include <linux/init.h>
# include <linux/module.h>
# include <linux/mm.h>
2021-02-01 21:02:32 +03:00
# include <asm/unaligned.h>
2005-04-17 02:20:36 +04:00
# include <linux/crypto.h>
2005-10-30 13:25:15 +03:00
# include <linux/types.h>
2011-09-02 02:45:07 +04:00
# include <crypto/blowfish.h>
2005-04-17 02:20:36 +04:00
2010-02-16 15:24:30 +03:00
/*
2005-04-17 02:20:36 +04:00
* Round loop unrolling macros , S is a pointer to a S - Box array
* organized in 4 unsigned longs at a row .
*/
# define GET32_3(x) (((x) & 0xff))
# define GET32_2(x) (((x) >> (8)) & (0xff))
# define GET32_1(x) (((x) >> (16)) & (0xff))
# define GET32_0(x) (((x) >> (24)) & (0xff))
# define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \
2011-09-02 02:45:12 +04:00
S [ 512 + GET32_2 ( x ) ] ) + S [ 768 + GET32_3 ( x ) ] )
2005-04-17 02:20:36 +04:00
2011-09-02 02:45:12 +04:00
# define ROUND(a, b, n) ({ b ^= P[n]; a ^= bf_F(b); })
2005-04-17 02:20:36 +04:00
2011-09-02 02:45:07 +04:00
static void bf_encrypt ( struct crypto_tfm * tfm , u8 * dst , const u8 * src )
2005-04-17 02:20:36 +04:00
{
2011-09-02 02:45:07 +04:00
struct bf_ctx * ctx = crypto_tfm_ctx ( tfm ) ;
const u32 * P = ctx - > p ;
const u32 * S = ctx - > s ;
2021-02-01 21:02:32 +03:00
u32 yl = get_unaligned_be32 ( src ) ;
u32 yr = get_unaligned_be32 ( src + 4 ) ;
2005-04-17 02:20:36 +04:00
ROUND ( yr , yl , 0 ) ;
ROUND ( yl , yr , 1 ) ;
ROUND ( yr , yl , 2 ) ;
ROUND ( yl , yr , 3 ) ;
ROUND ( yr , yl , 4 ) ;
ROUND ( yl , yr , 5 ) ;
ROUND ( yr , yl , 6 ) ;
ROUND ( yl , yr , 7 ) ;
ROUND ( yr , yl , 8 ) ;
ROUND ( yl , yr , 9 ) ;
ROUND ( yr , yl , 10 ) ;
ROUND ( yl , yr , 11 ) ;
ROUND ( yr , yl , 12 ) ;
ROUND ( yl , yr , 13 ) ;
ROUND ( yr , yl , 14 ) ;
ROUND ( yl , yr , 15 ) ;
yl ^ = P [ 16 ] ;
yr ^ = P [ 17 ] ;
2021-02-01 21:02:32 +03:00
put_unaligned_be32 ( yr , dst ) ;
put_unaligned_be32 ( yl , dst + 4 ) ;
2005-04-17 02:20:36 +04:00
}
2006-05-16 16:09:29 +04:00
static void bf_decrypt ( struct crypto_tfm * tfm , u8 * dst , const u8 * src )
2005-04-17 02:20:36 +04:00
{
2006-05-16 16:09:29 +04:00
struct bf_ctx * ctx = crypto_tfm_ctx ( tfm ) ;
const u32 * P = ctx - > p ;
const u32 * S = ctx - > s ;
2021-02-01 21:02:32 +03:00
u32 yl = get_unaligned_be32 ( src ) ;
u32 yr = get_unaligned_be32 ( src + 4 ) ;
2005-04-17 02:20:36 +04:00
ROUND ( yr , yl , 17 ) ;
ROUND ( yl , yr , 16 ) ;
ROUND ( yr , yl , 15 ) ;
ROUND ( yl , yr , 14 ) ;
ROUND ( yr , yl , 13 ) ;
ROUND ( yl , yr , 12 ) ;
ROUND ( yr , yl , 11 ) ;
ROUND ( yl , yr , 10 ) ;
ROUND ( yr , yl , 9 ) ;
ROUND ( yl , yr , 8 ) ;
ROUND ( yr , yl , 7 ) ;
ROUND ( yl , yr , 6 ) ;
ROUND ( yr , yl , 5 ) ;
ROUND ( yl , yr , 4 ) ;
ROUND ( yr , yl , 3 ) ;
ROUND ( yl , yr , 2 ) ;
yl ^ = P [ 1 ] ;
yr ^ = P [ 0 ] ;
2021-02-01 21:02:32 +03:00
put_unaligned_be32 ( yr , dst ) ;
put_unaligned_be32 ( yl , dst + 4 ) ;
2005-04-17 02:20:36 +04:00
}
static struct crypto_alg alg = {
. cra_name = " blowfish " ,
2011-09-02 02:45:12 +04:00
. cra_driver_name = " blowfish-generic " ,
. cra_priority = 100 ,
2005-04-17 02:20:36 +04:00
. cra_flags = CRYPTO_ALG_TYPE_CIPHER ,
. cra_blocksize = BF_BLOCK_SIZE ,
. cra_ctxsize = sizeof ( struct bf_ctx ) ,
. cra_module = THIS_MODULE ,
. cra_u = { . cipher = {
. cia_min_keysize = BF_MIN_KEY_SIZE ,
. cia_max_keysize = BF_MAX_KEY_SIZE ,
2011-09-02 02:45:07 +04:00
. cia_setkey = blowfish_setkey ,
2011-09-02 02:45:12 +04:00
. cia_encrypt = bf_encrypt ,
. cia_decrypt = bf_decrypt } }
2005-04-17 02:20:36 +04:00
} ;
2008-04-05 17:00:57 +04:00
static int __init blowfish_mod_init ( void )
2005-04-17 02:20:36 +04:00
{
return crypto_register_alg ( & alg ) ;
}
2008-04-05 17:00:57 +04:00
static void __exit blowfish_mod_fini ( void )
2005-04-17 02:20:36 +04:00
{
crypto_unregister_alg ( & alg ) ;
}
2019-04-12 07:57:42 +03:00
subsys_initcall ( blowfish_mod_init ) ;
2008-04-05 17:00:57 +04:00
module_exit ( blowfish_mod_fini ) ;
2005-04-17 02:20:36 +04:00
MODULE_LICENSE ( " GPL " ) ;
MODULE_DESCRIPTION ( " Blowfish Cipher Algorithm " ) ;
2014-11-21 04:05:53 +03:00
MODULE_ALIAS_CRYPTO ( " blowfish " ) ;
2015-01-11 20:17:42 +03:00
MODULE_ALIAS_CRYPTO ( " blowfish-generic " ) ;