2017-11-24 15:00:34 +01:00
// SPDX-License-Identifier: GPL-2.0+
2005-04-16 15:20:36 -07:00
/*
* Cryptographic API .
*
2006-01-06 00:19:17 -08:00
* s390 implementation of the DES Cipher Algorithm .
2005-04-16 15:20:36 -07:00
*
2012-07-20 11:15:04 +02:00
* Copyright IBM Corp . 2003 , 2011
2007-02-05 21:18:14 +01:00
* Author ( s ) : Thomas Spatzier
* Jan Glauber ( jan . glauber @ de . ibm . com )
2005-04-16 15:20:36 -07:00
*/
2006-08-21 21:39:24 +10:00
2005-04-16 15:20:36 -07:00
# include <linux/init.h>
# include <linux/module.h>
2015-02-19 17:34:07 +01:00
# include <linux/cpufeature.h>
2010-05-21 22:04:46 +10:00
# include <linux/crypto.h>
2016-12-15 14:54:30 +01:00
# include <linux/fips.h>
2019-05-27 15:24:20 +02:00
# include <linux/mutex.h>
2010-05-21 22:04:46 +10:00
# include <crypto/algapi.h>
2019-08-15 12:00:44 +03:00
# include <crypto/internal/des.h>
2019-10-12 13:18:09 -07:00
# include <crypto/internal/skcipher.h>
2016-03-17 15:22:12 +01:00
# include <asm/cpacf.h>
2005-04-16 15:20:36 -07:00
2011-04-19 21:29:15 +02:00
# define DES3_KEY_SIZE (3 * DES_KEY_SIZE)
2005-04-16 15:20:36 -07:00
2011-05-04 15:09:44 +10:00
static u8 * ctrblk ;
2019-05-27 15:24:20 +02:00
static DEFINE_MUTEX ( ctrblk_lock ) ;
2011-05-04 15:09:44 +10:00
2016-08-18 12:59:46 +02:00
static cpacf_mask_t km_functions , kmc_functions , kmctr_functions ;
2011-04-19 21:29:15 +02:00
struct s390_des_ctx {
2005-04-16 15:20:36 -07:00
u8 iv [ DES_BLOCK_SIZE ] ;
2011-04-19 21:29:15 +02:00
u8 key [ DES3_KEY_SIZE ] ;
2005-04-16 15:20:36 -07:00
} ;
2006-05-16 22:09:29 +10:00
static int des_setkey ( struct crypto_tfm * tfm , const u8 * key ,
2011-04-19 21:29:15 +02:00
unsigned int key_len )
2005-04-16 15:20:36 -07:00
{
2011-04-19 21:29:15 +02:00
struct s390_des_ctx * ctx = crypto_tfm_ctx ( tfm ) ;
2019-08-15 12:00:44 +03:00
int err ;
2005-04-16 15:20:36 -07:00
2019-08-15 12:00:44 +03:00
err = crypto_des_verify_key ( tfm , key ) ;
if ( err )
return err ;
2010-05-21 22:04:46 +10:00
2011-04-19 21:29:15 +02:00
memcpy ( ctx - > key , key , key_len ) ;
2010-05-21 22:04:46 +10:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
2019-10-12 13:18:09 -07:00
static int des_setkey_skcipher ( struct crypto_skcipher * tfm , const u8 * key ,
unsigned int key_len )
{
return des_setkey ( crypto_skcipher_tfm ( tfm ) , key , key_len ) ;
}
2019-08-15 12:00:44 +03:00
static void s390_des_encrypt ( struct crypto_tfm * tfm , u8 * out , const u8 * in )
2005-04-16 15:20:36 -07:00
{
2011-04-19 21:29:15 +02:00
struct s390_des_ctx * ctx = crypto_tfm_ctx ( tfm ) ;
2005-04-16 15:20:36 -07:00
2016-08-15 09:19:16 +02:00
cpacf_km ( CPACF_KM_DEA , ctx - > key , out , in , DES_BLOCK_SIZE ) ;
2005-04-16 15:20:36 -07:00
}
2019-08-15 12:00:44 +03:00
static void s390_des_decrypt ( struct crypto_tfm * tfm , u8 * out , const u8 * in )
2005-04-16 15:20:36 -07:00
{
2011-04-19 21:29:15 +02:00
struct s390_des_ctx * ctx = crypto_tfm_ctx ( tfm ) ;
2005-04-16 15:20:36 -07:00
2016-08-15 09:19:16 +02:00
cpacf_km ( CPACF_KM_DEA | CPACF_DECRYPT ,
ctx - > key , out , in , DES_BLOCK_SIZE ) ;
2006-01-14 13:20:53 -08:00
}
2005-04-16 15:20:36 -07:00
static struct crypto_alg des_alg = {
. cra_name = " des " ,
2006-08-21 21:18:50 +10:00
. cra_driver_name = " des-s390 " ,
2016-03-17 15:22:12 +01:00
. cra_priority = 300 ,
2005-04-16 15:20:36 -07:00
. cra_flags = CRYPTO_ALG_TYPE_CIPHER ,
. cra_blocksize = DES_BLOCK_SIZE ,
2011-04-19 21:29:15 +02:00
. cra_ctxsize = sizeof ( struct s390_des_ctx ) ,
2005-04-16 15:20:36 -07:00
. cra_module = THIS_MODULE ,
2006-01-14 13:20:53 -08:00
. cra_u = {
. cipher = {
. cia_min_keysize = DES_KEY_SIZE ,
. cia_max_keysize = DES_KEY_SIZE ,
. cia_setkey = des_setkey ,
2019-08-15 12:00:44 +03:00
. cia_encrypt = s390_des_encrypt ,
. cia_decrypt = s390_des_decrypt ,
2006-01-14 13:20:53 -08:00
}
}
2005-04-16 15:20:36 -07:00
} ;
2019-10-12 13:18:09 -07:00
static int ecb_desall_crypt ( struct skcipher_request * req , unsigned long fc )
2006-08-21 21:39:24 +10:00
{
2019-10-12 13:18:09 -07:00
struct crypto_skcipher * tfm = crypto_skcipher_reqtfm ( req ) ;
struct s390_des_ctx * ctx = crypto_skcipher_ctx ( tfm ) ;
struct skcipher_walk walk ;
2016-08-15 15:17:52 +02:00
unsigned int nbytes , n ;
int ret ;
2006-08-21 21:39:24 +10:00
2019-10-12 13:18:09 -07:00
ret = skcipher_walk_virt ( & walk , req , false ) ;
while ( ( nbytes = walk . nbytes ) ! = 0 ) {
2006-08-21 21:39:24 +10:00
/* only use complete blocks */
2016-08-15 15:17:52 +02:00
n = nbytes & ~ ( DES_BLOCK_SIZE - 1 ) ;
2019-10-12 13:18:09 -07:00
cpacf_km ( fc , ctx - > key , walk . dst . virt . addr ,
walk . src . virt . addr , n ) ;
ret = skcipher_walk_done ( & walk , nbytes - n ) ;
2006-08-21 21:39:24 +10:00
}
return ret ;
}
2019-10-12 13:18:09 -07:00
static int cbc_desall_crypt ( struct skcipher_request * req , unsigned long fc )
2006-08-21 21:39:24 +10:00
{
2019-10-12 13:18:09 -07:00
struct crypto_skcipher * tfm = crypto_skcipher_reqtfm ( req ) ;
struct s390_des_ctx * ctx = crypto_skcipher_ctx ( tfm ) ;
struct skcipher_walk walk ;
2016-08-15 15:17:52 +02:00
unsigned int nbytes , n ;
int ret ;
2014-01-22 13:00:04 +01:00
struct {
u8 iv [ DES_BLOCK_SIZE ] ;
u8 key [ DES3_KEY_SIZE ] ;
} param ;
2006-08-21 21:39:24 +10:00
2019-10-12 13:18:09 -07:00
ret = skcipher_walk_virt ( & walk , req , false ) ;
if ( ret )
return ret ;
memcpy ( param . iv , walk . iv , DES_BLOCK_SIZE ) ;
2014-01-22 13:00:04 +01:00
memcpy ( param . key , ctx - > key , DES3_KEY_SIZE ) ;
2019-10-12 13:18:09 -07:00
while ( ( nbytes = walk . nbytes ) ! = 0 ) {
2006-08-21 21:39:24 +10:00
/* only use complete blocks */
2016-08-15 15:17:52 +02:00
n = nbytes & ~ ( DES_BLOCK_SIZE - 1 ) ;
2019-10-12 13:18:09 -07:00
cpacf_kmc ( fc , & param , walk . dst . virt . addr ,
walk . src . virt . addr , n ) ;
memcpy ( walk . iv , param . iv , DES_BLOCK_SIZE ) ;
ret = skcipher_walk_done ( & walk , nbytes - n ) ;
2016-08-15 15:17:52 +02:00
}
2006-08-21 21:39:24 +10:00
return ret ;
}
2019-10-12 13:18:09 -07:00
static int ecb_des_encrypt ( struct skcipher_request * req )
2006-08-21 21:39:24 +10:00
{
2019-10-12 13:18:09 -07:00
return ecb_desall_crypt ( req , CPACF_KM_DEA ) ;
2006-08-21 21:39:24 +10:00
}
2019-10-12 13:18:09 -07:00
static int ecb_des_decrypt ( struct skcipher_request * req )
2006-08-21 21:39:24 +10:00
{
2019-10-12 13:18:09 -07:00
return ecb_desall_crypt ( req , CPACF_KM_DEA | CPACF_DECRYPT ) ;
2006-08-21 21:39:24 +10:00
}
2019-10-12 13:18:09 -07:00
static struct skcipher_alg ecb_des_alg = {
. base . cra_name = " ecb(des) " ,
. base . cra_driver_name = " ecb-des-s390 " ,
. base . cra_priority = 400 , /* combo: des + ecb */
. base . cra_blocksize = DES_BLOCK_SIZE ,
. base . cra_ctxsize = sizeof ( struct s390_des_ctx ) ,
. base . cra_module = THIS_MODULE ,
. min_keysize = DES_KEY_SIZE ,
. max_keysize = DES_KEY_SIZE ,
. setkey = des_setkey_skcipher ,
. encrypt = ecb_des_encrypt ,
. decrypt = ecb_des_decrypt ,
2006-08-21 21:39:24 +10:00
} ;
2019-10-12 13:18:09 -07:00
static int cbc_des_encrypt ( struct skcipher_request * req )
2006-08-21 21:39:24 +10:00
{
2019-10-12 13:18:09 -07:00
return cbc_desall_crypt ( req , CPACF_KMC_DEA ) ;
2006-08-21 21:39:24 +10:00
}
2019-10-12 13:18:09 -07:00
static int cbc_des_decrypt ( struct skcipher_request * req )
2006-08-21 21:39:24 +10:00
{
2019-10-12 13:18:09 -07:00
return cbc_desall_crypt ( req , CPACF_KMC_DEA | CPACF_DECRYPT ) ;
2006-08-21 21:39:24 +10:00
}
2019-10-12 13:18:09 -07:00
static struct skcipher_alg cbc_des_alg = {
. base . cra_name = " cbc(des) " ,
. base . cra_driver_name = " cbc-des-s390 " ,
. base . cra_priority = 400 , /* combo: des + cbc */
. base . cra_blocksize = DES_BLOCK_SIZE ,
. base . cra_ctxsize = sizeof ( struct s390_des_ctx ) ,
. base . cra_module = THIS_MODULE ,
. min_keysize = DES_KEY_SIZE ,
. max_keysize = DES_KEY_SIZE ,
. ivsize = DES_BLOCK_SIZE ,
. setkey = des_setkey_skcipher ,
. encrypt = cbc_des_encrypt ,
. decrypt = cbc_des_decrypt ,
2006-08-21 21:39:24 +10:00
} ;
2005-04-16 15:20:36 -07:00
/*
* RFC2451 :
*
* For DES - EDE3 , there is no known need to reject weak or
* complementation keys . Any weakness is obviated by the use of
* multiple keys .
*
* However , if the first two or last two independent 64 - bit keys are
* equal ( k1 = = k2 or k2 = = k3 ) , then the DES3 operation is simply the
* same as DES . Implementers MUST reject keys that exhibit this
* property .
*
2016-12-15 14:54:30 +01:00
* In fips mode additinally check for all 3 keys are unique .
*
2005-04-16 15:20:36 -07:00
*/
2011-04-19 21:29:15 +02:00
static int des3_setkey ( struct crypto_tfm * tfm , const u8 * key ,
unsigned int key_len )
2005-04-16 15:20:36 -07:00
{
2011-04-19 21:29:15 +02:00
struct s390_des_ctx * ctx = crypto_tfm_ctx ( tfm ) ;
2019-04-11 16:50:57 +08:00
int err ;
2005-04-16 15:20:36 -07:00
2019-08-15 12:00:44 +03:00
err = crypto_des3_ede_verify_key ( tfm , key ) ;
if ( err )
2019-04-11 16:50:57 +08:00
return err ;
2016-12-15 14:54:30 +01:00
2011-04-19 21:29:15 +02:00
memcpy ( ctx - > key , key , key_len ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
2019-10-12 13:18:09 -07:00
static int des3_setkey_skcipher ( struct crypto_skcipher * tfm , const u8 * key ,
unsigned int key_len )
{
return des3_setkey ( crypto_skcipher_tfm ( tfm ) , key , key_len ) ;
}
2011-04-19 21:29:15 +02:00
static void des3_encrypt ( struct crypto_tfm * tfm , u8 * dst , const u8 * src )
2005-04-16 15:20:36 -07:00
{
2011-04-19 21:29:15 +02:00
struct s390_des_ctx * ctx = crypto_tfm_ctx ( tfm ) ;
2005-04-16 15:20:36 -07:00
2016-08-15 09:19:16 +02:00
cpacf_km ( CPACF_KM_TDEA_192 , ctx - > key , dst , src , DES_BLOCK_SIZE ) ;
2005-04-16 15:20:36 -07:00
}
2011-04-19 21:29:15 +02:00
static void des3_decrypt ( struct crypto_tfm * tfm , u8 * dst , const u8 * src )
2005-04-16 15:20:36 -07:00
{
2011-04-19 21:29:15 +02:00
struct s390_des_ctx * ctx = crypto_tfm_ctx ( tfm ) ;
2005-04-16 15:20:36 -07:00
2016-08-15 09:19:16 +02:00
cpacf_km ( CPACF_KM_TDEA_192 | CPACF_DECRYPT ,
ctx - > key , dst , src , DES_BLOCK_SIZE ) ;
2005-04-16 15:20:36 -07:00
}
2011-04-19 21:29:15 +02:00
static struct crypto_alg des3_alg = {
2005-04-16 15:20:36 -07:00
. cra_name = " des3_ede " ,
2006-08-21 21:18:50 +10:00
. cra_driver_name = " des3_ede-s390 " ,
2016-03-17 15:22:12 +01:00
. cra_priority = 300 ,
2005-04-16 15:20:36 -07:00
. cra_flags = CRYPTO_ALG_TYPE_CIPHER ,
2010-05-21 22:04:46 +10:00
. cra_blocksize = DES_BLOCK_SIZE ,
2011-04-19 21:29:15 +02:00
. cra_ctxsize = sizeof ( struct s390_des_ctx ) ,
2005-04-16 15:20:36 -07:00
. cra_module = THIS_MODULE ,
2006-01-14 13:20:53 -08:00
. cra_u = {
. cipher = {
2011-04-19 21:29:15 +02:00
. cia_min_keysize = DES3_KEY_SIZE ,
. cia_max_keysize = DES3_KEY_SIZE ,
. cia_setkey = des3_setkey ,
. cia_encrypt = des3_encrypt ,
. cia_decrypt = des3_decrypt ,
2006-01-14 13:20:53 -08:00
}
}
2005-04-16 15:20:36 -07:00
} ;
2019-10-12 13:18:09 -07:00
static int ecb_des3_encrypt ( struct skcipher_request * req )
2006-08-21 21:39:24 +10:00
{
2019-10-12 13:18:09 -07:00
return ecb_desall_crypt ( req , CPACF_KM_TDEA_192 ) ;
2006-08-21 21:39:24 +10:00
}
2019-10-12 13:18:09 -07:00
static int ecb_des3_decrypt ( struct skcipher_request * req )
2006-08-21 21:39:24 +10:00
{
2019-10-12 13:18:09 -07:00
return ecb_desall_crypt ( req , CPACF_KM_TDEA_192 | CPACF_DECRYPT ) ;
2006-08-21 21:39:24 +10:00
}
2019-10-12 13:18:09 -07:00
static struct skcipher_alg ecb_des3_alg = {
. base . cra_name = " ecb(des3_ede) " ,
. base . cra_driver_name = " ecb-des3_ede-s390 " ,
. base . cra_priority = 400 , /* combo: des3 + ecb */
. base . cra_blocksize = DES_BLOCK_SIZE ,
. base . cra_ctxsize = sizeof ( struct s390_des_ctx ) ,
. base . cra_module = THIS_MODULE ,
. min_keysize = DES3_KEY_SIZE ,
. max_keysize = DES3_KEY_SIZE ,
. setkey = des3_setkey_skcipher ,
. encrypt = ecb_des3_encrypt ,
. decrypt = ecb_des3_decrypt ,
2006-08-21 21:39:24 +10:00
} ;
2019-10-12 13:18:09 -07:00
static int cbc_des3_encrypt ( struct skcipher_request * req )
2006-08-21 21:39:24 +10:00
{
2019-10-12 13:18:09 -07:00
return cbc_desall_crypt ( req , CPACF_KMC_TDEA_192 ) ;
2006-08-21 21:39:24 +10:00
}
2019-10-12 13:18:09 -07:00
static int cbc_des3_decrypt ( struct skcipher_request * req )
2006-08-21 21:39:24 +10:00
{
2019-10-12 13:18:09 -07:00
return cbc_desall_crypt ( req , CPACF_KMC_TDEA_192 | CPACF_DECRYPT ) ;
2006-08-21 21:39:24 +10:00
}
2019-10-12 13:18:09 -07:00
static struct skcipher_alg cbc_des3_alg = {
. base . cra_name = " cbc(des3_ede) " ,
. base . cra_driver_name = " cbc-des3_ede-s390 " ,
. base . cra_priority = 400 , /* combo: des3 + cbc */
. base . cra_blocksize = DES_BLOCK_SIZE ,
. base . cra_ctxsize = sizeof ( struct s390_des_ctx ) ,
. base . cra_module = THIS_MODULE ,
. min_keysize = DES3_KEY_SIZE ,
. max_keysize = DES3_KEY_SIZE ,
. ivsize = DES_BLOCK_SIZE ,
. setkey = des3_setkey_skcipher ,
. encrypt = cbc_des3_encrypt ,
. decrypt = cbc_des3_decrypt ,
2006-08-21 21:39:24 +10:00
} ;
2016-08-15 15:17:52 +02:00
static unsigned int __ctrblk_init ( u8 * ctrptr , u8 * iv , unsigned int nbytes )
2014-01-22 13:01:33 +01:00
{
unsigned int i , n ;
/* align to block size, max. PAGE_SIZE */
n = ( nbytes > PAGE_SIZE ) ? PAGE_SIZE : nbytes & ~ ( DES_BLOCK_SIZE - 1 ) ;
2016-08-15 15:17:52 +02:00
memcpy ( ctrptr , iv , DES_BLOCK_SIZE ) ;
for ( i = ( n / DES_BLOCK_SIZE ) - 1 ; i > 0 ; i - - ) {
memcpy ( ctrptr + DES_BLOCK_SIZE , ctrptr , DES_BLOCK_SIZE ) ;
crypto_inc ( ctrptr + DES_BLOCK_SIZE , DES_BLOCK_SIZE ) ;
ctrptr + = DES_BLOCK_SIZE ;
2014-01-22 13:01:33 +01:00
}
return n ;
}
2019-10-12 13:18:09 -07:00
static int ctr_desall_crypt ( struct skcipher_request * req , unsigned long fc )
2011-05-04 15:09:44 +10:00
{
2019-10-12 13:18:09 -07:00
struct crypto_skcipher * tfm = crypto_skcipher_reqtfm ( req ) ;
struct s390_des_ctx * ctx = crypto_skcipher_ctx ( tfm ) ;
2016-08-15 15:17:52 +02:00
u8 buf [ DES_BLOCK_SIZE ] , * ctrptr ;
2019-10-12 13:18:09 -07:00
struct skcipher_walk walk ;
2014-01-22 13:01:33 +01:00
unsigned int n , nbytes ;
2016-08-15 15:17:52 +02:00
int ret , locked ;
2011-05-04 15:09:44 +10:00
2019-05-27 15:24:20 +02:00
locked = mutex_trylock ( & ctrblk_lock ) ;
2014-01-22 13:01:33 +01:00
2019-10-12 13:18:09 -07:00
ret = skcipher_walk_virt ( & walk , req , false ) ;
while ( ( nbytes = walk . nbytes ) > = DES_BLOCK_SIZE ) {
2016-08-15 15:17:52 +02:00
n = DES_BLOCK_SIZE ;
if ( nbytes > = 2 * DES_BLOCK_SIZE & & locked )
2019-10-12 13:18:09 -07:00
n = __ctrblk_init ( ctrblk , walk . iv , nbytes ) ;
ctrptr = ( n > DES_BLOCK_SIZE ) ? ctrblk : walk . iv ;
cpacf_kmctr ( fc , ctx - > key , walk . dst . virt . addr ,
walk . src . virt . addr , n , ctrptr ) ;
2016-08-15 15:17:52 +02:00
if ( ctrptr = = ctrblk )
2019-10-12 13:18:09 -07:00
memcpy ( walk . iv , ctrptr + n - DES_BLOCK_SIZE ,
2016-08-15 15:17:52 +02:00
DES_BLOCK_SIZE ) ;
2019-10-12 13:18:09 -07:00
crypto_inc ( walk . iv , DES_BLOCK_SIZE ) ;
ret = skcipher_walk_done ( & walk , nbytes - n ) ;
2011-05-04 15:09:44 +10:00
}
2016-08-15 15:17:52 +02:00
if ( locked )
2019-05-27 15:24:20 +02:00
mutex_unlock ( & ctrblk_lock ) ;
2011-05-04 15:09:44 +10:00
/* final block may be < DES_BLOCK_SIZE, copy only nbytes */
if ( nbytes ) {
2019-10-12 13:18:09 -07:00
cpacf_kmctr ( fc , ctx - > key , buf , walk . src . virt . addr ,
DES_BLOCK_SIZE , walk . iv ) ;
memcpy ( walk . dst . virt . addr , buf , nbytes ) ;
crypto_inc ( walk . iv , DES_BLOCK_SIZE ) ;
ret = skcipher_walk_done ( & walk , 0 ) ;
2011-05-04 15:09:44 +10:00
}
return ret ;
}
2019-10-12 13:18:09 -07:00
static int ctr_des_crypt ( struct skcipher_request * req )
2011-05-04 15:09:44 +10:00
{
2019-10-12 13:18:09 -07:00
return ctr_desall_crypt ( req , CPACF_KMCTR_DEA ) ;
2011-05-04 15:09:44 +10:00
}
2019-10-12 13:18:09 -07:00
static struct skcipher_alg ctr_des_alg = {
. base . cra_name = " ctr(des) " ,
. base . cra_driver_name = " ctr-des-s390 " ,
. base . cra_priority = 400 , /* combo: des + ctr */
. base . cra_blocksize = 1 ,
. base . cra_ctxsize = sizeof ( struct s390_des_ctx ) ,
. base . cra_module = THIS_MODULE ,
. min_keysize = DES_KEY_SIZE ,
. max_keysize = DES_KEY_SIZE ,
. ivsize = DES_BLOCK_SIZE ,
. setkey = des_setkey_skcipher ,
. encrypt = ctr_des_crypt ,
. decrypt = ctr_des_crypt ,
. chunksize = DES_BLOCK_SIZE ,
2011-05-04 15:09:44 +10:00
} ;
2019-10-12 13:18:09 -07:00
static int ctr_des3_crypt ( struct skcipher_request * req )
2011-05-04 15:09:44 +10:00
{
2019-10-12 13:18:09 -07:00
return ctr_desall_crypt ( req , CPACF_KMCTR_TDEA_192 ) ;
2011-05-04 15:09:44 +10:00
}
2019-10-12 13:18:09 -07:00
static struct skcipher_alg ctr_des3_alg = {
. base . cra_name = " ctr(des3_ede) " ,
. base . cra_driver_name = " ctr-des3_ede-s390 " ,
. base . cra_priority = 400 , /* combo: des3 + ede */
. base . cra_blocksize = 1 ,
. base . cra_ctxsize = sizeof ( struct s390_des_ctx ) ,
. base . cra_module = THIS_MODULE ,
. min_keysize = DES3_KEY_SIZE ,
. max_keysize = DES3_KEY_SIZE ,
. ivsize = DES_BLOCK_SIZE ,
. setkey = des3_setkey_skcipher ,
. encrypt = ctr_des3_crypt ,
. decrypt = ctr_des3_crypt ,
. chunksize = DES_BLOCK_SIZE ,
2011-05-04 15:09:44 +10:00
} ;
2019-10-12 13:18:09 -07:00
static struct crypto_alg * des_s390_algs_ptr [ 2 ] ;
2016-08-18 12:34:34 +02:00
static int des_s390_algs_num ;
2019-10-12 13:18:09 -07:00
static struct skcipher_alg * des_s390_skciphers_ptr [ 6 ] ;
static int des_s390_skciphers_num ;
2016-08-18 12:34:34 +02:00
static int des_s390_register_alg ( struct crypto_alg * alg )
{
int ret ;
ret = crypto_register_alg ( alg ) ;
if ( ! ret )
des_s390_algs_ptr [ des_s390_algs_num + + ] = alg ;
return ret ;
}
2019-10-12 13:18:09 -07:00
static int des_s390_register_skcipher ( struct skcipher_alg * alg )
{
int ret ;
ret = crypto_register_skcipher ( alg ) ;
if ( ! ret )
des_s390_skciphers_ptr [ des_s390_skciphers_num + + ] = alg ;
return ret ;
}
2016-08-18 12:34:34 +02:00
static void des_s390_exit ( void )
{
while ( des_s390_algs_num - - )
crypto_unregister_alg ( des_s390_algs_ptr [ des_s390_algs_num ] ) ;
2019-10-12 13:18:09 -07:00
while ( des_s390_skciphers_num - - )
crypto_unregister_skcipher ( des_s390_skciphers_ptr [ des_s390_skciphers_num ] ) ;
2016-08-18 12:34:34 +02:00
if ( ctrblk )
free_page ( ( unsigned long ) ctrblk ) ;
}
2011-04-19 21:29:15 +02:00
static int __init des_s390_init ( void )
2005-04-16 15:20:36 -07:00
{
2010-05-21 22:04:08 +10:00
int ret ;
2005-04-16 15:20:36 -07:00
2016-08-18 12:59:46 +02:00
/* Query available functions for KM, KMC and KMCTR */
cpacf_query ( CPACF_KM , & km_functions ) ;
cpacf_query ( CPACF_KMC , & kmc_functions ) ;
cpacf_query ( CPACF_KMCTR , & kmctr_functions ) ;
if ( cpacf_test_func ( & km_functions , CPACF_KM_DEA ) ) {
ret = des_s390_register_alg ( & des_alg ) ;
if ( ret )
goto out_err ;
2019-10-12 13:18:09 -07:00
ret = des_s390_register_skcipher ( & ecb_des_alg ) ;
2016-08-18 12:59:46 +02:00
if ( ret )
goto out_err ;
}
if ( cpacf_test_func ( & kmc_functions , CPACF_KMC_DEA ) ) {
2019-10-12 13:18:09 -07:00
ret = des_s390_register_skcipher ( & cbc_des_alg ) ;
2016-08-18 12:59:46 +02:00
if ( ret )
goto out_err ;
}
if ( cpacf_test_func ( & km_functions , CPACF_KM_TDEA_192 ) ) {
ret = des_s390_register_alg ( & des3_alg ) ;
if ( ret )
goto out_err ;
2019-10-12 13:18:09 -07:00
ret = des_s390_register_skcipher ( & ecb_des3_alg ) ;
2016-08-18 12:59:46 +02:00
if ( ret )
goto out_err ;
}
if ( cpacf_test_func ( & kmc_functions , CPACF_KMC_TDEA_192 ) ) {
2019-10-12 13:18:09 -07:00
ret = des_s390_register_skcipher ( & cbc_des3_alg ) ;
2016-08-18 12:59:46 +02:00
if ( ret )
goto out_err ;
}
if ( cpacf_test_func ( & kmctr_functions , CPACF_KMCTR_DEA ) | |
cpacf_test_func ( & kmctr_functions , CPACF_KMCTR_TDEA_192 ) ) {
2011-05-04 15:09:44 +10:00
ctrblk = ( u8 * ) __get_free_page ( GFP_KERNEL ) ;
if ( ! ctrblk ) {
ret = - ENOMEM ;
2016-08-18 12:34:34 +02:00
goto out_err ;
2011-05-04 15:09:44 +10:00
}
2016-08-18 12:59:46 +02:00
}
if ( cpacf_test_func ( & kmctr_functions , CPACF_KMCTR_DEA ) ) {
2019-10-12 13:18:09 -07:00
ret = des_s390_register_skcipher ( & ctr_des_alg ) ;
2016-08-18 12:34:34 +02:00
if ( ret )
goto out_err ;
2016-08-18 12:59:46 +02:00
}
if ( cpacf_test_func ( & kmctr_functions , CPACF_KMCTR_TDEA_192 ) ) {
2019-10-12 13:18:09 -07:00
ret = des_s390_register_skcipher ( & ctr_des3_alg ) ;
2016-08-18 12:34:34 +02:00
if ( ret )
goto out_err ;
2011-05-04 15:09:44 +10:00
}
2005-04-16 15:20:36 -07:00
2016-08-18 12:34:34 +02:00
return 0 ;
out_err :
des_s390_exit ( ) ;
return ret ;
2005-04-16 15:20:36 -07:00
}
2015-02-19 17:34:07 +01:00
module_cpu_feature_match ( MSA , des_s390_init ) ;
2010-05-21 22:04:46 +10:00
module_exit ( des_s390_exit ) ;
2005-04-16 15:20:36 -07:00
2014-11-20 17:05:53 -08:00
MODULE_ALIAS_CRYPTO ( " des " ) ;
MODULE_ALIAS_CRYPTO ( " des3_ede " ) ;
2005-04-16 15:20:36 -07:00
MODULE_LICENSE ( " GPL " ) ;
MODULE_DESCRIPTION ( " DES & Triple DES EDE Cipher Algorithms " ) ;