2005-04-17 02:20:36 +04:00
/*
* Cryptographic API .
*
2006-01-06 11:19:17 +03:00
* Support for s390 cryptographic instructions .
2005-04-17 02:20:36 +04:00
*
2007-02-05 23:18:14 +03:00
* Copyright IBM Corp . 2003 , 2007
* Author ( s ) : Thomas Spatzier
* Jan Glauber ( jan . glauber @ de . ibm . com )
2005-04-17 02:20:36 +04: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-01-06 11:19:17 +03:00
# ifndef _CRYPTO_ARCH_S390_CRYPT_S390_H
# define _CRYPTO_ARCH_S390_CRYPT_S390_H
2005-04-17 02:20:36 +04:00
# include <asm/errno.h>
2006-01-06 11:19:17 +03:00
# define CRYPT_S390_OP_MASK 0xFF00
# define CRYPT_S390_FUNC_MASK 0x00FF
2005-04-17 02:20:36 +04:00
2006-08-21 15:18:50 +04:00
# define CRYPT_S390_PRIORITY 300
2006-08-21 15:39:24 +04:00
# define CRYPT_S390_COMPOSITE_PRIORITY 400
2006-08-21 15:18:50 +04:00
2007-07-10 13:24:08 +04:00
/* s390 cryptographic operations */
2006-01-06 11:19:17 +03:00
enum crypt_s390_operations {
CRYPT_S390_KM = 0x0100 ,
CRYPT_S390_KMC = 0x0200 ,
CRYPT_S390_KIMD = 0x0300 ,
CRYPT_S390_KLMD = 0x0400 ,
CRYPT_S390_KMAC = 0x0500
2005-04-17 02:20:36 +04:00
} ;
2007-02-05 23:18:14 +03:00
/*
* function codes for KM ( CIPHER MESSAGE ) instruction
2006-01-06 11:19:17 +03:00
* 0x80 is the decipher modifier bit
*/
enum crypt_s390_km_func {
2006-01-06 11:19:18 +03:00
KM_QUERY = CRYPT_S390_KM | 0x0 ,
KM_DEA_ENCRYPT = CRYPT_S390_KM | 0x1 ,
KM_DEA_DECRYPT = CRYPT_S390_KM | 0x1 | 0x80 ,
KM_TDEA_128_ENCRYPT = CRYPT_S390_KM | 0x2 ,
KM_TDEA_128_DECRYPT = CRYPT_S390_KM | 0x2 | 0x80 ,
KM_TDEA_192_ENCRYPT = CRYPT_S390_KM | 0x3 ,
KM_TDEA_192_DECRYPT = CRYPT_S390_KM | 0x3 | 0x80 ,
KM_AES_128_ENCRYPT = CRYPT_S390_KM | 0x12 ,
KM_AES_128_DECRYPT = CRYPT_S390_KM | 0x12 | 0x80 ,
KM_AES_192_ENCRYPT = CRYPT_S390_KM | 0x13 ,
KM_AES_192_DECRYPT = CRYPT_S390_KM | 0x13 | 0x80 ,
KM_AES_256_ENCRYPT = CRYPT_S390_KM | 0x14 ,
KM_AES_256_DECRYPT = CRYPT_S390_KM | 0x14 | 0x80 ,
2005-04-17 02:20:36 +04:00
} ;
2007-02-05 23:18:14 +03:00
/*
* function codes for KMC ( CIPHER MESSAGE WITH CHAINING )
2006-01-06 11:19:17 +03:00
* instruction
*/
enum crypt_s390_kmc_func {
2006-01-06 11:19:18 +03:00
KMC_QUERY = CRYPT_S390_KMC | 0x0 ,
KMC_DEA_ENCRYPT = CRYPT_S390_KMC | 0x1 ,
KMC_DEA_DECRYPT = CRYPT_S390_KMC | 0x1 | 0x80 ,
KMC_TDEA_128_ENCRYPT = CRYPT_S390_KMC | 0x2 ,
KMC_TDEA_128_DECRYPT = CRYPT_S390_KMC | 0x2 | 0x80 ,
KMC_TDEA_192_ENCRYPT = CRYPT_S390_KMC | 0x3 ,
KMC_TDEA_192_DECRYPT = CRYPT_S390_KMC | 0x3 | 0x80 ,
KMC_AES_128_ENCRYPT = CRYPT_S390_KMC | 0x12 ,
KMC_AES_128_DECRYPT = CRYPT_S390_KMC | 0x12 | 0x80 ,
KMC_AES_192_ENCRYPT = CRYPT_S390_KMC | 0x13 ,
KMC_AES_192_DECRYPT = CRYPT_S390_KMC | 0x13 | 0x80 ,
KMC_AES_256_ENCRYPT = CRYPT_S390_KMC | 0x14 ,
KMC_AES_256_DECRYPT = CRYPT_S390_KMC | 0x14 | 0x80 ,
2007-02-05 23:18:22 +03:00
KMC_PRNG = CRYPT_S390_KMC | 0x43 ,
2005-04-17 02:20:36 +04:00
} ;
2007-02-05 23:18:14 +03:00
/*
* function codes for KIMD ( COMPUTE INTERMEDIATE MESSAGE DIGEST )
2006-01-06 11:19:17 +03:00
* instruction
*/
enum crypt_s390_kimd_func {
KIMD_QUERY = CRYPT_S390_KIMD | 0 ,
KIMD_SHA_1 = CRYPT_S390_KIMD | 1 ,
2006-01-06 11:19:18 +03:00
KIMD_SHA_256 = CRYPT_S390_KIMD | 2 ,
2008-03-06 14:52:00 +03:00
KIMD_SHA_512 = CRYPT_S390_KIMD | 3 ,
2005-04-17 02:20:36 +04:00
} ;
2007-02-05 23:18:14 +03:00
/*
* function codes for KLMD ( COMPUTE LAST MESSAGE DIGEST )
2006-01-06 11:19:17 +03:00
* instruction
*/
enum crypt_s390_klmd_func {
KLMD_QUERY = CRYPT_S390_KLMD | 0 ,
KLMD_SHA_1 = CRYPT_S390_KLMD | 1 ,
2006-01-06 11:19:18 +03:00
KLMD_SHA_256 = CRYPT_S390_KLMD | 2 ,
2008-03-06 14:52:00 +03:00
KLMD_SHA_512 = CRYPT_S390_KLMD | 3 ,
2005-04-17 02:20:36 +04:00
} ;
2007-02-05 23:18:14 +03:00
/*
* function codes for KMAC ( COMPUTE MESSAGE AUTHENTICATION CODE )
2006-01-06 11:19:17 +03:00
* instruction
*/
enum crypt_s390_kmac_func {
KMAC_QUERY = CRYPT_S390_KMAC | 0 ,
KMAC_DEA = CRYPT_S390_KMAC | 1 ,
KMAC_TDEA_128 = CRYPT_S390_KMAC | 2 ,
KMAC_TDEA_192 = CRYPT_S390_KMAC | 3
2005-04-17 02:20:36 +04:00
} ;
2007-02-05 23:18:14 +03:00
/**
* crypt_s390_km :
* @ func : the function code passed to KM ; see crypt_s390_km_func
* @ param : address of parameter block ; see POP for details on each func
* @ dest : address of destination memory area
* @ src : address of source memory area
* @ src_len : length of src operand in bytes
*
2006-01-06 11:19:17 +03:00
* Executes the KM ( CIPHER MESSAGE ) operation of the CPU .
2007-02-05 23:18:14 +03:00
*
* Returns - 1 for failure , 0 for the query func , number of processed
* bytes for encryption / decryption funcs
2005-04-17 02:20:36 +04:00
*/
2007-02-05 23:18:14 +03:00
static inline int crypt_s390_km ( long func , void * param ,
u8 * dest , const u8 * src , long src_len )
2005-04-17 02:20:36 +04:00
{
2006-01-06 11:19:17 +03:00
register long __func asm ( " 0 " ) = func & CRYPT_S390_FUNC_MASK ;
2007-02-05 23:18:14 +03:00
register void * __param asm ( " 1 " ) = param ;
register const u8 * __src asm ( " 2 " ) = src ;
2005-04-17 02:20:36 +04:00
register long __src_len asm ( " 3 " ) = src_len ;
2007-02-05 23:18:14 +03:00
register u8 * __dest asm ( " 4 " ) = dest ;
2005-04-17 02:20:36 +04:00
int ret ;
2006-09-28 18:56:43 +04:00
asm volatile (
" 0: .insn rre,0xb92e0000,%3,%1 \n " /* KM opcode */
2006-01-06 11:19:17 +03:00
" 1: brc 1,0b \n " /* handle partial completion */
2007-02-05 23:18:14 +03:00
" la %0,0 \n "
" 2: \n "
EX_TABLE ( 0 b , 2 b ) EX_TABLE ( 1 b , 2 b )
2006-09-28 18:56:43 +04:00
: " =d " ( ret ) , " +a " ( __src ) , " +d " ( __src_len ) , " +a " ( __dest )
2007-02-05 23:18:14 +03:00
: " d " ( __func ) , " a " ( __param ) , " 0 " ( - 1 ) : " cc " , " memory " ) ;
2006-09-28 18:56:43 +04:00
if ( ret < 0 )
return ret ;
return ( func & CRYPT_S390_FUNC_MASK ) ? src_len - __src_len : __src_len ;
2005-04-17 02:20:36 +04:00
}
2007-02-05 23:18:14 +03:00
/**
* crypt_s390_kmc :
* @ func : the function code passed to KM ; see crypt_s390_kmc_func
* @ param : address of parameter block ; see POP for details on each func
* @ dest : address of destination memory area
* @ src : address of source memory area
* @ src_len : length of src operand in bytes
*
2006-01-06 11:19:17 +03:00
* Executes the KMC ( CIPHER MESSAGE WITH CHAINING ) operation of the CPU .
2007-02-05 23:18:14 +03:00
*
* Returns - 1 for failure , 0 for the query func , number of processed
* bytes for encryption / decryption funcs
2005-04-17 02:20:36 +04:00
*/
2007-02-05 23:18:14 +03:00
static inline int crypt_s390_kmc ( long func , void * param ,
u8 * dest , const u8 * src , long src_len )
2005-04-17 02:20:36 +04:00
{
2006-01-06 11:19:17 +03:00
register long __func asm ( " 0 " ) = func & CRYPT_S390_FUNC_MASK ;
2007-02-05 23:18:14 +03:00
register void * __param asm ( " 1 " ) = param ;
register const u8 * __src asm ( " 2 " ) = src ;
2005-04-17 02:20:36 +04:00
register long __src_len asm ( " 3 " ) = src_len ;
2007-02-05 23:18:14 +03:00
register u8 * __dest asm ( " 4 " ) = dest ;
2005-04-17 02:20:36 +04:00
int ret ;
2006-09-28 18:56:43 +04:00
asm volatile (
" 0: .insn rre,0xb92f0000,%3,%1 \n " /* KMC opcode */
2006-01-06 11:19:17 +03:00
" 1: brc 1,0b \n " /* handle partial completion */
2007-02-05 23:18:14 +03:00
" la %0,0 \n "
" 2: \n "
EX_TABLE ( 0 b , 2 b ) EX_TABLE ( 1 b , 2 b )
2006-09-28 18:56:43 +04:00
: " =d " ( ret ) , " +a " ( __src ) , " +d " ( __src_len ) , " +a " ( __dest )
2007-02-05 23:18:14 +03:00
: " d " ( __func ) , " a " ( __param ) , " 0 " ( - 1 ) : " cc " , " memory " ) ;
2006-09-28 18:56:43 +04:00
if ( ret < 0 )
return ret ;
return ( func & CRYPT_S390_FUNC_MASK ) ? src_len - __src_len : __src_len ;
2005-04-17 02:20:36 +04:00
}
2007-02-05 23:18:14 +03:00
/**
* crypt_s390_kimd :
* @ func : the function code passed to KM ; see crypt_s390_kimd_func
* @ param : address of parameter block ; see POP for details on each func
* @ src : address of source memory area
* @ src_len : length of src operand in bytes
*
2005-04-17 02:20:36 +04:00
* Executes the KIMD ( COMPUTE INTERMEDIATE MESSAGE DIGEST ) operation
2006-01-06 11:19:17 +03:00
* of the CPU .
2007-02-05 23:18:14 +03:00
*
* Returns - 1 for failure , 0 for the query func , number of processed
* bytes for digest funcs
2005-04-17 02:20:36 +04:00
*/
2007-02-05 23:18:14 +03:00
static inline int crypt_s390_kimd ( long func , void * param ,
const u8 * src , long src_len )
2005-04-17 02:20:36 +04:00
{
2006-01-06 11:19:17 +03:00
register long __func asm ( " 0 " ) = func & CRYPT_S390_FUNC_MASK ;
2007-02-05 23:18:14 +03:00
register void * __param asm ( " 1 " ) = param ;
register const u8 * __src asm ( " 2 " ) = src ;
2005-04-17 02:20:36 +04:00
register long __src_len asm ( " 3 " ) = src_len ;
int ret ;
2006-09-28 18:56:43 +04:00
asm volatile (
" 0: .insn rre,0xb93e0000,%1,%1 \n " /* KIMD opcode */
" 1: brc 1,0b \n " /* handle partial completion */
2007-02-05 23:18:14 +03:00
" la %0,0 \n "
" 2: \n "
EX_TABLE ( 0 b , 2 b ) EX_TABLE ( 1 b , 2 b )
2006-09-28 18:56:43 +04:00
: " =d " ( ret ) , " +a " ( __src ) , " +d " ( __src_len )
2007-02-05 23:18:14 +03:00
: " d " ( __func ) , " a " ( __param ) , " 0 " ( - 1 ) : " cc " , " memory " ) ;
2006-09-28 18:56:43 +04:00
if ( ret < 0 )
return ret ;
return ( func & CRYPT_S390_FUNC_MASK ) ? src_len - __src_len : __src_len ;
2005-04-17 02:20:36 +04:00
}
2007-02-05 23:18:14 +03:00
/**
* crypt_s390_klmd :
* @ func : the function code passed to KM ; see crypt_s390_klmd_func
* @ param : address of parameter block ; see POP for details on each func
* @ src : address of source memory area
* @ src_len : length of src operand in bytes
*
2006-01-06 11:19:17 +03:00
* Executes the KLMD ( COMPUTE LAST MESSAGE DIGEST ) operation of the CPU .
2007-02-05 23:18:14 +03:00
*
* Returns - 1 for failure , 0 for the query func , number of processed
* bytes for digest funcs
2005-04-17 02:20:36 +04:00
*/
2007-02-05 23:18:14 +03:00
static inline int crypt_s390_klmd ( long func , void * param ,
const u8 * src , long src_len )
2005-04-17 02:20:36 +04:00
{
2006-01-06 11:19:17 +03:00
register long __func asm ( " 0 " ) = func & CRYPT_S390_FUNC_MASK ;
2007-02-05 23:18:14 +03:00
register void * __param asm ( " 1 " ) = param ;
register const u8 * __src asm ( " 2 " ) = src ;
2005-04-17 02:20:36 +04:00
register long __src_len asm ( " 3 " ) = src_len ;
int ret ;
2006-09-28 18:56:43 +04:00
asm volatile (
" 0: .insn rre,0xb93f0000,%1,%1 \n " /* KLMD opcode */
" 1: brc 1,0b \n " /* handle partial completion */
2007-02-05 23:18:14 +03:00
" la %0,0 \n "
" 2: \n "
EX_TABLE ( 0 b , 2 b ) EX_TABLE ( 1 b , 2 b )
2006-09-28 18:56:43 +04:00
: " =d " ( ret ) , " +a " ( __src ) , " +d " ( __src_len )
2007-02-05 23:18:14 +03:00
: " d " ( __func ) , " a " ( __param ) , " 0 " ( - 1 ) : " cc " , " memory " ) ;
2006-09-28 18:56:43 +04:00
if ( ret < 0 )
return ret ;
return ( func & CRYPT_S390_FUNC_MASK ) ? src_len - __src_len : __src_len ;
2005-04-17 02:20:36 +04:00
}
2007-02-05 23:18:14 +03:00
/**
* crypt_s390_kmac :
* @ func : the function code passed to KM ; see crypt_s390_klmd_func
* @ param : address of parameter block ; see POP for details on each func
* @ src : address of source memory area
* @ src_len : length of src operand in bytes
*
2005-04-17 02:20:36 +04:00
* Executes the KMAC ( COMPUTE MESSAGE AUTHENTICATION CODE ) operation
2006-01-06 11:19:17 +03:00
* of the CPU .
2007-02-05 23:18:14 +03:00
*
* Returns - 1 for failure , 0 for the query func , number of processed
* bytes for digest funcs
2005-04-17 02:20:36 +04:00
*/
2007-02-05 23:18:14 +03:00
static inline int crypt_s390_kmac ( long func , void * param ,
const u8 * src , long src_len )
2005-04-17 02:20:36 +04:00
{
2006-01-06 11:19:17 +03:00
register long __func asm ( " 0 " ) = func & CRYPT_S390_FUNC_MASK ;
2007-02-05 23:18:14 +03:00
register void * __param asm ( " 1 " ) = param ;
register const u8 * __src asm ( " 2 " ) = src ;
2005-04-17 02:20:36 +04:00
register long __src_len asm ( " 3 " ) = src_len ;
int ret ;
2006-09-28 18:56:43 +04:00
asm volatile (
" 0: .insn rre,0xb91e0000,%1,%1 \n " /* KLAC opcode */
" 1: brc 1,0b \n " /* handle partial completion */
2007-02-05 23:18:14 +03:00
" la %0,0 \n "
" 2: \n "
EX_TABLE ( 0 b , 2 b ) EX_TABLE ( 1 b , 2 b )
2006-09-28 18:56:43 +04:00
: " =d " ( ret ) , " +a " ( __src ) , " +d " ( __src_len )
2007-02-05 23:18:14 +03:00
: " d " ( __func ) , " a " ( __param ) , " 0 " ( - 1 ) : " cc " , " memory " ) ;
2006-09-28 18:56:43 +04:00
if ( ret < 0 )
return ret ;
return ( func & CRYPT_S390_FUNC_MASK ) ? src_len - __src_len : __src_len ;
2005-04-17 02:20:36 +04:00
}
/**
2007-02-05 23:18:14 +03:00
* crypt_s390_func_available :
* @ func : the function code of the specific function ; 0 if op in general
*
2006-01-06 11:19:17 +03:00
* Tests if a specific crypto function is implemented on the machine .
2007-02-05 23:18:14 +03:00
*
* Returns 1 if func available ; 0 if func or op in general not available
2005-04-17 02:20:36 +04:00
*/
2007-02-05 23:18:14 +03:00
static inline int crypt_s390_func_available ( int func )
2005-04-17 02:20:36 +04:00
{
2007-02-05 23:18:14 +03:00
unsigned char status [ 16 ] ;
2005-04-17 02:20:36 +04:00
int ret ;
2008-07-12 11:42:11 +04:00
/* check if CPACF facility (bit 17) is available */
if ( ! ( stfl ( ) & 1ULL < < ( 31 - 17 ) ) )
return 0 ;
2007-02-05 23:18:14 +03:00
switch ( func & CRYPT_S390_OP_MASK ) {
case CRYPT_S390_KM :
ret = crypt_s390_km ( KM_QUERY , & status , NULL , NULL , 0 ) ;
break ;
case CRYPT_S390_KMC :
ret = crypt_s390_kmc ( KMC_QUERY , & status , NULL , NULL , 0 ) ;
break ;
case CRYPT_S390_KIMD :
ret = crypt_s390_kimd ( KIMD_QUERY , & status , NULL , 0 ) ;
break ;
case CRYPT_S390_KLMD :
ret = crypt_s390_klmd ( KLMD_QUERY , & status , NULL , 0 ) ;
break ;
case CRYPT_S390_KMAC :
ret = crypt_s390_kmac ( KMAC_QUERY , & status , NULL , 0 ) ;
break ;
default :
return 0 ;
2005-04-17 02:20:36 +04:00
}
2007-02-05 23:18:14 +03:00
if ( ret < 0 )
return 0 ;
func & = CRYPT_S390_FUNC_MASK ;
func & = 0x7f ; /* mask modifier bit */
return ( status [ func > > 3 ] & ( 0x80 > > ( func & 7 ) ) ) ! = 0 ;
2005-04-17 02:20:36 +04:00
}
2007-02-05 23:18:14 +03:00
# endif /* _CRYPTO_ARCH_S390_CRYPT_S390_H */