2017-11-24 15:00:34 +01:00
// SPDX-License-Identifier: GPL-2.0+
2008-03-06 19:50:20 +08:00
/*
* Cryptographic API .
*
* s390 generic implementation of the SHA Secure Hash Algorithms .
*
* Copyright IBM Corp . 2007
* Author ( s ) : Jan Glauber ( jang @ de . ibm . com )
*/
2009-01-18 20:33:33 +11:00
# include <crypto/internal/hash.h>
2011-07-30 09:25:15 +02:00
# include <linux/module.h>
2016-03-17 15:22:12 +01:00
# include <asm/cpacf.h>
2008-03-06 19:50:20 +08:00
# include "sha.h"
2009-01-18 20:33:33 +11:00
int s390_sha_update ( struct shash_desc * desc , const u8 * data , unsigned int len )
2008-03-06 19:50:20 +08:00
{
2009-01-18 20:33:33 +11:00
struct s390_sha_ctx * ctx = shash_desc_ctx ( desc ) ;
unsigned int bsize = crypto_shash_blocksize ( desc - > tfm ) ;
2016-08-15 10:41:52 +02:00
unsigned int index , n ;
2008-03-06 19:50:20 +08:00
/* how much is already in the buffer? */
2019-08-14 14:56:54 +02:00
index = ctx - > count % bsize ;
2008-03-06 19:50:20 +08:00
ctx - > count + = len ;
if ( ( index + len ) < bsize )
goto store ;
/* process one stored block */
if ( index ) {
memcpy ( ctx - > buf + index , data , bsize - index ) ;
2016-08-15 10:41:52 +02:00
cpacf_kimd ( ctx - > func , ctx - > state , ctx - > buf , bsize ) ;
2008-03-06 19:50:20 +08:00
data + = bsize - index ;
len - = bsize - index ;
2011-02-07 20:26:06 +11:00
index = 0 ;
2008-03-06 19:50:20 +08:00
}
/* process as many blocks as possible */
if ( len > = bsize ) {
2019-08-14 14:56:54 +02:00
n = ( len / bsize ) * bsize ;
2016-08-15 10:41:52 +02:00
cpacf_kimd ( ctx - > func , ctx - > state , data , n ) ;
data + = n ;
len - = n ;
2008-03-06 19:50:20 +08:00
}
store :
if ( len )
memcpy ( ctx - > buf + index , data , len ) ;
2009-01-18 20:33:33 +11:00
return 0 ;
2008-03-06 19:50:20 +08:00
}
EXPORT_SYMBOL_GPL ( s390_sha_update ) ;
2019-08-14 14:56:54 +02:00
static int s390_crypto_shash_parmsize ( int func )
{
switch ( func ) {
case CPACF_KLMD_SHA_1 :
return 20 ;
case CPACF_KLMD_SHA_256 :
return 32 ;
case CPACF_KLMD_SHA_512 :
return 64 ;
case CPACF_KLMD_SHA3_224 :
case CPACF_KLMD_SHA3_256 :
case CPACF_KLMD_SHA3_384 :
case CPACF_KLMD_SHA3_512 :
return 200 ;
default :
return - EINVAL ;
}
}
2009-01-18 20:33:33 +11:00
int s390_sha_final ( struct shash_desc * desc , u8 * out )
2008-03-06 19:50:20 +08:00
{
2009-01-18 20:33:33 +11:00
struct s390_sha_ctx * ctx = shash_desc_ctx ( desc ) ;
unsigned int bsize = crypto_shash_blocksize ( desc - > tfm ) ;
2008-03-06 19:50:20 +08:00
u64 bits ;
2019-08-14 14:56:54 +02:00
unsigned int n , mbl_offset ;
2008-03-06 19:52:00 +08:00
2019-08-14 14:56:54 +02:00
n = ctx - > count % bsize ;
2008-03-06 19:50:20 +08:00
bits = ctx - > count * 8 ;
2019-08-14 14:56:54 +02:00
mbl_offset = s390_crypto_shash_parmsize ( ctx - > func ) / sizeof ( u32 ) ;
if ( mbl_offset < 0 )
return - EINVAL ;
/* set total msg bit length (mbl) in CPACF parmblock */
switch ( ctx - > func ) {
case CPACF_KLMD_SHA_1 :
case CPACF_KLMD_SHA_256 :
memcpy ( ctx - > state + mbl_offset , & bits , sizeof ( bits ) ) ;
break ;
case CPACF_KLMD_SHA_512 :
/*
* the SHA512 parmblock has a 128 - bit mbl field , clear
* high - order u64 field , copy bits to low - order u64 field
*/
memset ( ctx - > state + mbl_offset , 0x00 , sizeof ( bits ) ) ;
mbl_offset + = sizeof ( u64 ) / sizeof ( u32 ) ;
memcpy ( ctx - > state + mbl_offset , & bits , sizeof ( bits ) ) ;
break ;
case CPACF_KLMD_SHA3_224 :
case CPACF_KLMD_SHA3_256 :
case CPACF_KLMD_SHA3_384 :
case CPACF_KLMD_SHA3_512 :
break ;
default :
return - EINVAL ;
}
cpacf_klmd ( ctx - > func , ctx - > state , ctx - > buf , n ) ;
2008-03-06 19:50:20 +08:00
/* copy digest to out */
2009-01-18 20:33:33 +11:00
memcpy ( out , ctx - > state , crypto_shash_digestsize ( desc - > tfm ) ) ;
2008-03-06 19:50:20 +08:00
/* wipe context */
memset ( ctx , 0 , sizeof * ctx ) ;
2009-01-18 20:33:33 +11:00
return 0 ;
2008-03-06 19:50:20 +08:00
}
EXPORT_SYMBOL_GPL ( s390_sha_final ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_DESCRIPTION ( " s390 SHA cipher common functions " ) ;