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
*
* 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 .
*
*/
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>
# include <crypto/algapi.h>
# include <crypto/des.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 ;
2014-01-22 13:01:33 +01:00
static DEFINE_SPINLOCK ( 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 ) ;
2010-05-21 22:04:46 +10:00
u32 tmp [ DES_EXPKEY_WORDS ] ;
2005-04-16 15:20:36 -07:00
2010-05-21 22:04:46 +10:00
/* check for weak keys */
2016-08-18 12:59:46 +02:00
if ( ! des_ekey ( tmp , key ) & &
( tfm - > crt_flags & CRYPTO_TFM_REQ_WEAK_KEY ) ) {
tfm - > crt_flags | = CRYPTO_TFM_RES_WEAK_KEY ;
2010-05-21 22:04:46 +10:00
return - EINVAL ;
}
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
}
2006-05-16 22:09:29 +10:00
static void 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
}
2006-05-16 22:09:29 +10:00
static void 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 ,
. cia_encrypt = des_encrypt ,
2006-01-14 13:20:53 -08:00
. cia_decrypt = des_decrypt ,
2006-01-14 13:20:53 -08:00
}
}
2005-04-16 15:20:36 -07:00
} ;
2006-08-21 21:39:24 +10:00
static int ecb_desall_crypt ( struct blkcipher_desc * desc , long func ,
2011-04-19 21:29:15 +02:00
u8 * key , struct blkcipher_walk * walk )
2006-08-21 21:39:24 +10:00
{
int ret = blkcipher_walk_virt ( desc , walk ) ;
unsigned int nbytes ;
while ( ( nbytes = walk - > nbytes ) ) {
/* only use complete blocks */
unsigned int n = nbytes & ~ ( DES_BLOCK_SIZE - 1 ) ;
u8 * out = walk - > dst . virt . addr ;
u8 * in = walk - > src . virt . addr ;
2016-08-15 10:41:52 +02:00
cpacf_km ( func , key , out , in , n ) ;
2006-08-21 21:39:24 +10:00
nbytes & = DES_BLOCK_SIZE - 1 ;
ret = blkcipher_walk_done ( desc , walk , nbytes ) ;
}
return ret ;
}
static int cbc_desall_crypt ( struct blkcipher_desc * desc , long func ,
2014-01-22 13:00:04 +01:00
struct blkcipher_walk * walk )
2006-08-21 21:39:24 +10:00
{
2014-01-22 13:00:04 +01:00
struct s390_des_ctx * ctx = crypto_blkcipher_ctx ( desc - > tfm ) ;
2006-08-21 21:39:24 +10:00
int ret = blkcipher_walk_virt ( desc , walk ) ;
unsigned int nbytes = walk - > nbytes ;
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
if ( ! nbytes )
goto out ;
2014-01-22 13:00:04 +01:00
memcpy ( param . iv , walk - > iv , DES_BLOCK_SIZE ) ;
memcpy ( param . key , ctx - > key , DES3_KEY_SIZE ) ;
2006-08-21 21:39:24 +10:00
do {
/* only use complete blocks */
unsigned int n = nbytes & ~ ( DES_BLOCK_SIZE - 1 ) ;
u8 * out = walk - > dst . virt . addr ;
u8 * in = walk - > src . virt . addr ;
2016-08-15 10:41:52 +02:00
cpacf_kmc ( func , & param , out , in , n ) ;
2006-08-21 21:39:24 +10:00
nbytes & = DES_BLOCK_SIZE - 1 ;
ret = blkcipher_walk_done ( desc , walk , nbytes ) ;
} while ( ( nbytes = walk - > nbytes ) ) ;
2014-01-22 13:00:04 +01:00
memcpy ( walk - > iv , param . iv , DES_BLOCK_SIZE ) ;
2006-08-21 21:39:24 +10:00
out :
return ret ;
}
static int ecb_des_encrypt ( struct blkcipher_desc * desc ,
struct scatterlist * dst , struct scatterlist * src ,
unsigned int nbytes )
{
2011-04-19 21:29:15 +02:00
struct s390_des_ctx * ctx = crypto_blkcipher_ctx ( desc - > tfm ) ;
2006-08-21 21:39:24 +10:00
struct blkcipher_walk walk ;
blkcipher_walk_init ( & walk , dst , src , nbytes ) ;
2016-08-15 09:19:16 +02:00
return ecb_desall_crypt ( desc , CPACF_KM_DEA , ctx - > key , & walk ) ;
2006-08-21 21:39:24 +10:00
}
static int ecb_des_decrypt ( struct blkcipher_desc * desc ,
struct scatterlist * dst , struct scatterlist * src ,
unsigned int nbytes )
{
2011-04-19 21:29:15 +02:00
struct s390_des_ctx * ctx = crypto_blkcipher_ctx ( desc - > tfm ) ;
2006-08-21 21:39:24 +10:00
struct blkcipher_walk walk ;
blkcipher_walk_init ( & walk , dst , src , nbytes ) ;
2016-08-15 09:19:16 +02:00
return ecb_desall_crypt ( desc , CPACF_KM_DEA | CPACF_DECRYPT ,
ctx - > key , & walk ) ;
2006-08-21 21:39:24 +10:00
}
static struct crypto_alg ecb_des_alg = {
. cra_name = " ecb(des) " ,
. cra_driver_name = " ecb-des-s390 " ,
2016-03-17 15:22:12 +01:00
. cra_priority = 400 , /* combo: des + ecb */
2006-08-21 21:39:24 +10:00
. cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER ,
. cra_blocksize = DES_BLOCK_SIZE ,
2011-04-19 21:29:15 +02:00
. cra_ctxsize = sizeof ( struct s390_des_ctx ) ,
2006-08-21 21:39:24 +10:00
. cra_type = & crypto_blkcipher_type ,
. cra_module = THIS_MODULE ,
. cra_u = {
. blkcipher = {
. min_keysize = DES_KEY_SIZE ,
. max_keysize = DES_KEY_SIZE ,
. setkey = des_setkey ,
. encrypt = ecb_des_encrypt ,
. decrypt = ecb_des_decrypt ,
}
}
} ;
static int cbc_des_encrypt ( struct blkcipher_desc * desc ,
struct scatterlist * dst , struct scatterlist * src ,
unsigned int nbytes )
{
struct blkcipher_walk walk ;
blkcipher_walk_init ( & walk , dst , src , nbytes ) ;
2016-08-15 09:19:16 +02:00
return cbc_desall_crypt ( desc , CPACF_KMC_DEA , & walk ) ;
2006-08-21 21:39:24 +10:00
}
static int cbc_des_decrypt ( struct blkcipher_desc * desc ,
struct scatterlist * dst , struct scatterlist * src ,
unsigned int nbytes )
{
struct blkcipher_walk walk ;
blkcipher_walk_init ( & walk , dst , src , nbytes ) ;
2016-08-15 09:19:16 +02:00
return cbc_desall_crypt ( desc , CPACF_KMC_DEA | CPACF_DECRYPT , & walk ) ;
2006-08-21 21:39:24 +10:00
}
static struct crypto_alg cbc_des_alg = {
. cra_name = " cbc(des) " ,
. cra_driver_name = " cbc-des-s390 " ,
2016-03-17 15:22:12 +01:00
. cra_priority = 400 , /* combo: des + cbc */
2006-08-21 21:39:24 +10:00
. cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER ,
. cra_blocksize = DES_BLOCK_SIZE ,
2011-04-19 21:29:15 +02:00
. cra_ctxsize = sizeof ( struct s390_des_ctx ) ,
2006-08-21 21:39:24 +10:00
. cra_type = & crypto_blkcipher_type ,
. cra_module = THIS_MODULE ,
. cra_u = {
. blkcipher = {
. min_keysize = DES_KEY_SIZE ,
. max_keysize = DES_KEY_SIZE ,
. ivsize = DES_BLOCK_SIZE ,
. setkey = des_setkey ,
. encrypt = cbc_des_encrypt ,
. decrypt = cbc_des_decrypt ,
}
}
} ;
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 .
*
*/
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 ) ;
2005-04-16 15:20:36 -07:00
2013-12-11 11:28:59 +01:00
if ( ! ( crypto_memneq ( key , & key [ DES_KEY_SIZE ] , DES_KEY_SIZE ) & &
crypto_memneq ( & key [ DES_KEY_SIZE ] , & key [ DES_KEY_SIZE * 2 ] ,
DES_KEY_SIZE ) ) & &
2016-08-18 12:59:46 +02:00
( tfm - > crt_flags & CRYPTO_TFM_REQ_WEAK_KEY ) ) {
tfm - > crt_flags | = CRYPTO_TFM_RES_WEAK_KEY ;
2005-04-16 15:20:36 -07:00
return - EINVAL ;
}
2011-04-19 21:29:15 +02:00
memcpy ( ctx - > key , key , key_len ) ;
2005-04-16 15:20:36 -07:00
return 0 ;
}
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
} ;
2011-04-19 21:29:15 +02:00
static int ecb_des3_encrypt ( struct blkcipher_desc * desc ,
struct scatterlist * dst , struct scatterlist * src ,
unsigned int nbytes )
2006-08-21 21:39:24 +10:00
{
2011-04-19 21:29:15 +02:00
struct s390_des_ctx * ctx = crypto_blkcipher_ctx ( desc - > tfm ) ;
2006-08-21 21:39:24 +10:00
struct blkcipher_walk walk ;
blkcipher_walk_init ( & walk , dst , src , nbytes ) ;
2016-08-15 09:19:16 +02:00
return ecb_desall_crypt ( desc , CPACF_KM_TDEA_192 , ctx - > key , & walk ) ;
2006-08-21 21:39:24 +10:00
}
2011-04-19 21:29:15 +02:00
static int ecb_des3_decrypt ( struct blkcipher_desc * desc ,
struct scatterlist * dst , struct scatterlist * src ,
unsigned int nbytes )
2006-08-21 21:39:24 +10:00
{
2011-04-19 21:29:15 +02:00
struct s390_des_ctx * ctx = crypto_blkcipher_ctx ( desc - > tfm ) ;
2006-08-21 21:39:24 +10:00
struct blkcipher_walk walk ;
blkcipher_walk_init ( & walk , dst , src , nbytes ) ;
2016-08-15 09:19:16 +02:00
return ecb_desall_crypt ( desc , CPACF_KM_TDEA_192 | CPACF_DECRYPT ,
ctx - > key , & walk ) ;
2006-08-21 21:39:24 +10:00
}
2011-04-19 21:29:15 +02:00
static struct crypto_alg ecb_des3_alg = {
2006-08-21 21:39:24 +10:00
. cra_name = " ecb(des3_ede) " ,
. cra_driver_name = " ecb-des3_ede-s390 " ,
2016-03-17 15:22:12 +01:00
. cra_priority = 400 , /* combo: des3 + ecb */
2006-08-21 21:39:24 +10:00
. cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER ,
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 ) ,
2006-08-21 21:39:24 +10:00
. cra_type = & crypto_blkcipher_type ,
. cra_module = THIS_MODULE ,
. cra_u = {
. blkcipher = {
2011-04-19 21:29:15 +02:00
. min_keysize = DES3_KEY_SIZE ,
. max_keysize = DES3_KEY_SIZE ,
. setkey = des3_setkey ,
. encrypt = ecb_des3_encrypt ,
. decrypt = ecb_des3_decrypt ,
2006-08-21 21:39:24 +10:00
}
}
} ;
2011-04-19 21:29:15 +02:00
static int cbc_des3_encrypt ( struct blkcipher_desc * desc ,
struct scatterlist * dst , struct scatterlist * src ,
unsigned int nbytes )
2006-08-21 21:39:24 +10:00
{
struct blkcipher_walk walk ;
blkcipher_walk_init ( & walk , dst , src , nbytes ) ;
2016-08-15 09:19:16 +02:00
return cbc_desall_crypt ( desc , CPACF_KMC_TDEA_192 , & walk ) ;
2006-08-21 21:39:24 +10:00
}
2011-04-19 21:29:15 +02:00
static int cbc_des3_decrypt ( struct blkcipher_desc * desc ,
struct scatterlist * dst , struct scatterlist * src ,
unsigned int nbytes )
2006-08-21 21:39:24 +10:00
{
struct blkcipher_walk walk ;
blkcipher_walk_init ( & walk , dst , src , nbytes ) ;
2016-08-15 09:19:16 +02:00
return cbc_desall_crypt ( desc , CPACF_KMC_TDEA_192 | CPACF_DECRYPT ,
& walk ) ;
2006-08-21 21:39:24 +10:00
}
2011-04-19 21:29:15 +02:00
static struct crypto_alg cbc_des3_alg = {
2006-08-21 21:39:24 +10:00
. cra_name = " cbc(des3_ede) " ,
. cra_driver_name = " cbc-des3_ede-s390 " ,
2016-03-17 15:22:12 +01:00
. cra_priority = 400 , /* combo: des3 + cbc */
2006-08-21 21:39:24 +10:00
. cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER ,
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 ) ,
2006-08-21 21:39:24 +10:00
. cra_type = & crypto_blkcipher_type ,
. cra_module = THIS_MODULE ,
. cra_u = {
. blkcipher = {
2011-04-19 21:29:15 +02:00
. min_keysize = DES3_KEY_SIZE ,
. max_keysize = DES3_KEY_SIZE ,
2010-05-21 22:04:46 +10:00
. ivsize = DES_BLOCK_SIZE ,
2011-04-19 21:29:15 +02:00
. setkey = des3_setkey ,
. encrypt = cbc_des3_encrypt ,
. decrypt = cbc_des3_decrypt ,
2006-08-21 21:39:24 +10:00
}
}
} ;
2014-01-22 13:01:33 +01:00
static unsigned int __ctrblk_init ( u8 * ctrptr , unsigned int nbytes )
{
unsigned int i , n ;
/* align to block size, max. PAGE_SIZE */
n = ( nbytes > PAGE_SIZE ) ? PAGE_SIZE : nbytes & ~ ( DES_BLOCK_SIZE - 1 ) ;
for ( i = DES_BLOCK_SIZE ; i < n ; i + = DES_BLOCK_SIZE ) {
memcpy ( ctrptr + i , ctrptr + i - DES_BLOCK_SIZE , DES_BLOCK_SIZE ) ;
crypto_inc ( ctrptr + i , DES_BLOCK_SIZE ) ;
}
return n ;
}
2011-05-04 15:09:44 +10:00
static int ctr_desall_crypt ( struct blkcipher_desc * desc , long func ,
2014-01-22 13:01:33 +01:00
struct s390_des_ctx * ctx ,
struct blkcipher_walk * walk )
2011-05-04 15:09:44 +10:00
{
int ret = blkcipher_walk_virt_block ( desc , walk , DES_BLOCK_SIZE ) ;
2014-01-22 13:01:33 +01:00
unsigned int n , nbytes ;
u8 buf [ DES_BLOCK_SIZE ] , ctrbuf [ DES_BLOCK_SIZE ] ;
u8 * out , * in , * ctrptr = ctrbuf ;
if ( ! walk - > nbytes )
return ret ;
2011-05-04 15:09:44 +10:00
2014-01-22 13:01:33 +01:00
if ( spin_trylock ( & ctrblk_lock ) )
ctrptr = ctrblk ;
memcpy ( ctrptr , walk - > iv , DES_BLOCK_SIZE ) ;
2011-05-04 15:09:44 +10:00
while ( ( nbytes = walk - > nbytes ) > = DES_BLOCK_SIZE ) {
out = walk - > dst . virt . addr ;
in = walk - > src . virt . addr ;
while ( nbytes > = DES_BLOCK_SIZE ) {
2014-01-22 13:01:33 +01:00
if ( ctrptr = = ctrblk )
n = __ctrblk_init ( ctrptr , nbytes ) ;
else
n = DES_BLOCK_SIZE ;
2016-08-15 10:41:52 +02:00
cpacf_kmctr ( func , ctx - > key , out , in , n , ctrptr ) ;
2011-05-04 15:09:44 +10:00
if ( n > DES_BLOCK_SIZE )
2014-01-22 13:01:33 +01:00
memcpy ( ctrptr , ctrptr + n - DES_BLOCK_SIZE ,
2011-05-04 15:09:44 +10:00
DES_BLOCK_SIZE ) ;
2014-01-22 13:01:33 +01:00
crypto_inc ( ctrptr , DES_BLOCK_SIZE ) ;
2011-05-04 15:09:44 +10:00
out + = n ;
in + = n ;
nbytes - = n ;
}
ret = blkcipher_walk_done ( desc , walk , nbytes ) ;
}
2014-01-22 13:01:33 +01:00
if ( ctrptr = = ctrblk ) {
if ( nbytes )
memcpy ( ctrbuf , ctrptr , DES_BLOCK_SIZE ) ;
else
memcpy ( walk - > iv , ctrptr , DES_BLOCK_SIZE ) ;
spin_unlock ( & ctrblk_lock ) ;
2014-05-07 16:51:29 +02:00
} else {
if ( ! nbytes )
memcpy ( walk - > iv , ctrptr , DES_BLOCK_SIZE ) ;
2014-01-22 13:01:33 +01:00
}
2011-05-04 15:09:44 +10:00
/* final block may be < DES_BLOCK_SIZE, copy only nbytes */
if ( nbytes ) {
out = walk - > dst . virt . addr ;
in = walk - > src . virt . addr ;
2016-08-15 10:41:52 +02:00
cpacf_kmctr ( func , ctx - > key , buf , in , DES_BLOCK_SIZE , ctrbuf ) ;
2011-05-04 15:09:44 +10:00
memcpy ( out , buf , nbytes ) ;
2014-01-22 13:01:33 +01:00
crypto_inc ( ctrbuf , DES_BLOCK_SIZE ) ;
2011-05-04 15:09:44 +10:00
ret = blkcipher_walk_done ( desc , walk , 0 ) ;
2014-01-22 13:01:33 +01:00
memcpy ( walk - > iv , ctrbuf , DES_BLOCK_SIZE ) ;
2011-05-04 15:09:44 +10:00
}
return ret ;
}
static int ctr_des_encrypt ( struct blkcipher_desc * desc ,
struct scatterlist * dst , struct scatterlist * src ,
unsigned int nbytes )
{
struct s390_des_ctx * ctx = crypto_blkcipher_ctx ( desc - > tfm ) ;
struct blkcipher_walk walk ;
blkcipher_walk_init ( & walk , dst , src , nbytes ) ;
2016-08-15 09:19:16 +02:00
return ctr_desall_crypt ( desc , CPACF_KMCTR_DEA , ctx , & walk ) ;
2011-05-04 15:09:44 +10:00
}
static int ctr_des_decrypt ( struct blkcipher_desc * desc ,
struct scatterlist * dst , struct scatterlist * src ,
unsigned int nbytes )
{
struct s390_des_ctx * ctx = crypto_blkcipher_ctx ( desc - > tfm ) ;
struct blkcipher_walk walk ;
blkcipher_walk_init ( & walk , dst , src , nbytes ) ;
2016-08-15 09:19:16 +02:00
return ctr_desall_crypt ( desc , CPACF_KMCTR_DEA | CPACF_DECRYPT ,
ctx , & walk ) ;
2011-05-04 15:09:44 +10:00
}
static struct crypto_alg ctr_des_alg = {
. cra_name = " ctr(des) " ,
. cra_driver_name = " ctr-des-s390 " ,
2016-03-17 15:22:12 +01:00
. cra_priority = 400 , /* combo: des + ctr */
2011-05-04 15:09:44 +10:00
. cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER ,
. cra_blocksize = 1 ,
. cra_ctxsize = sizeof ( struct s390_des_ctx ) ,
. cra_type = & crypto_blkcipher_type ,
. cra_module = THIS_MODULE ,
. cra_u = {
. blkcipher = {
. min_keysize = DES_KEY_SIZE ,
. max_keysize = DES_KEY_SIZE ,
. ivsize = DES_BLOCK_SIZE ,
. setkey = des_setkey ,
. encrypt = ctr_des_encrypt ,
. decrypt = ctr_des_decrypt ,
}
}
} ;
static int ctr_des3_encrypt ( struct blkcipher_desc * desc ,
struct scatterlist * dst , struct scatterlist * src ,
unsigned int nbytes )
{
struct s390_des_ctx * ctx = crypto_blkcipher_ctx ( desc - > tfm ) ;
struct blkcipher_walk walk ;
blkcipher_walk_init ( & walk , dst , src , nbytes ) ;
2016-08-15 09:19:16 +02:00
return ctr_desall_crypt ( desc , CPACF_KMCTR_TDEA_192 , ctx , & walk ) ;
2011-05-04 15:09:44 +10:00
}
static int ctr_des3_decrypt ( struct blkcipher_desc * desc ,
struct scatterlist * dst , struct scatterlist * src ,
unsigned int nbytes )
{
struct s390_des_ctx * ctx = crypto_blkcipher_ctx ( desc - > tfm ) ;
struct blkcipher_walk walk ;
blkcipher_walk_init ( & walk , dst , src , nbytes ) ;
2016-08-15 09:19:16 +02:00
return ctr_desall_crypt ( desc , CPACF_KMCTR_TDEA_192 | CPACF_DECRYPT ,
ctx , & walk ) ;
2011-05-04 15:09:44 +10:00
}
static struct crypto_alg ctr_des3_alg = {
. cra_name = " ctr(des3_ede) " ,
. cra_driver_name = " ctr-des3_ede-s390 " ,
2016-03-17 15:22:12 +01:00
. cra_priority = 400 , /* combo: des3 + ede */
2011-05-04 15:09:44 +10:00
. cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER ,
. cra_blocksize = 1 ,
. cra_ctxsize = sizeof ( struct s390_des_ctx ) ,
. cra_type = & crypto_blkcipher_type ,
. cra_module = THIS_MODULE ,
. cra_u = {
. blkcipher = {
. min_keysize = DES3_KEY_SIZE ,
. max_keysize = DES3_KEY_SIZE ,
. ivsize = DES_BLOCK_SIZE ,
. setkey = des3_setkey ,
. encrypt = ctr_des3_encrypt ,
. decrypt = ctr_des3_decrypt ,
}
}
} ;
2016-08-18 12:34:34 +02:00
static struct crypto_alg * des_s390_algs_ptr [ 8 ] ;
static int des_s390_algs_num ;
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 ;
}
static void des_s390_exit ( void )
{
while ( des_s390_algs_num - - )
crypto_unregister_alg ( des_s390_algs_ptr [ des_s390_algs_num ] ) ;
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 ;
ret = des_s390_register_alg ( & ecb_des_alg ) ;
if ( ret )
goto out_err ;
}
if ( cpacf_test_func ( & kmc_functions , CPACF_KMC_DEA ) ) {
ret = des_s390_register_alg ( & cbc_des_alg ) ;
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 ;
ret = des_s390_register_alg ( & ecb_des3_alg ) ;
if ( ret )
goto out_err ;
}
if ( cpacf_test_func ( & kmc_functions , CPACF_KMC_TDEA_192 ) ) {
ret = des_s390_register_alg ( & cbc_des3_alg ) ;
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 ) ) {
2016-08-18 12:34:34 +02:00
ret = des_s390_register_alg ( & ctr_des_alg ) ;
if ( ret )
goto out_err ;
2016-08-18 12:59:46 +02:00
}
if ( cpacf_test_func ( & kmctr_functions , CPACF_KMCTR_TDEA_192 ) ) {
2016-08-18 12:34:34 +02:00
ret = des_s390_register_alg ( & ctr_des3_alg ) ;
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 " ) ;