s390: zcrypt PCICC, PCIXCC coprocessor card ap bus drivers.
Subsystems (2)
PATCH 4/6 s390: zcrypt PCICC, PCIXCC coprocessor card ap bus drivers.
From: Martin Schwidefsky <[email protected]>
From: Ralph Wuerthner <[email protected]>
[patch 4/6] s390: zcrypt PCICC, PCIXCC coprocessor card ap bus drivers.
Signed-off-by Martin Schwidefsky <[email protected]>
---
drivers/s390/crypto/zcrypt_cca_key.h | 350 ++++++++++++++++ drivers/s390/crypto/zcrypt_pcicc.c | 651 +++++++++++++++++++++++++++++++ drivers/s390/crypto/zcrypt_pcicc.h | 176 ++++++++ drivers/s390/crypto/zcrypt_pcixcc.c | 735 +++++++++++++++++++++++++++++++++++ drivers/s390/crypto/zcrypt_pcixcc.h | 79 +++ 5 files changed, 1991 insertions(+)
drivers/s390/crypto/zcrypt_cca_key.h +350 -0
@@ -0,0 +1,350 @@ +/* +* linux/drivers/s390/crypto/zcrypt_cca_key.h +* +* zcrypt 2.0.0 +* +* Copyright (C) 2001, 2006 IBM Corporation +* Author(s): Robert Burroughs +* Eric Rossman ([email protected]) +* +* Hotplug & misc device support: Jochen Roehrig ([email protected]) +* Major cleanup & driver split: Martin Schwidefsky <[email protected]> +* +* 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, or (at your option) +* any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _ZCRYPT_CCA_KEY_H_ +#define _ZCRYPT_CCA_KEY_H_ + +struct T6_keyBlock_hdr { +unsigned short blen; +unsigned short ulen; +unsigned short flags; +}; + +/** +* mapping for the cca private ME key token. +* Three parts of interest here: the header, the private section and +* the public section. +* +* mapping for the cca key token header +*/ +struct cca_token_hdr { +unsigned char token_identifier; +unsigned char version; +unsigned short token_length; +unsigned char reserved[4 ]; +} __attribute__((packed)); + +#define CCA_TKN_HDR_ID_EXT 0x1E + +/** +* mapping for the cca private ME section +*/ +struct cca_private_ext_ME_sec { +unsigned char section_identifier; +unsigned char version; +unsigned short section_length; +unsigned char private_key_hash[20 ]; +unsigned char reserved1[4 ]; +unsigned char key_format; +unsigned char reserved2; +unsigned char key_name_hash[20 ]; +unsigned char key_use_flags[4 ]; +unsigned char reserved3[6 ]; +unsigned char reserved4[24 ]; +unsigned char confounder[24 ]; +unsigned char exponent[128 ]; +unsigned char modulus[128 ]; +} __attribute__((packed)); + +#define CCA_PVT_USAGE_ALL 0x80 + +/** +* mapping for the cca public section +* In a private key, the modulus doesn't appear in the public +* section. So, an arbitrary public exponent of 0x010001 will be +* used, for a section length of 0x0F always. +*/ +struct cca_public_sec { +unsigned char section_identifier; +unsigned char version; +unsigned short section_length; +unsigned char reserved[2 ]; +unsigned short exponent_len; +unsigned short modulus_bit_len; +unsigned short modulus_byte_len;/* In a private key, this is 0 */ +} __attribute__((packed)); + +/** +* mapping for the cca private CRT key 'token' +* The first three parts (the only parts considered in this release) +* are: the header, the private section and the public section. +* The header and public section are the same as for the +* struct cca_private_ext_ME +* +* Following the structure are the quantities p, q, dp, dq, u, pad, +* and modulus, in that order, where pad_len is the modulo 8 +* complement of the residue modulo 8 of the sum of +* (p_len + q_len + dp_len + dq_len + u_len). +*/ +struct cca_pvt_ext_CRT_sec { +unsigned char section_identifier; +unsigned char version; +unsigned short section_length; +unsigned char private_key_hash[20 ]; +unsigned char reserved1[4 ]; +unsigned char key_format; +unsigned char reserved2; +unsigned char key_name_hash[20 ]; +unsigned char key_use_flags[4 ]; +unsigned short p_len; +unsigned short q_len; +unsigned short dp_len; +unsigned short dq_len; +unsigned short u_len; +unsigned short mod_len; +unsigned char reserved3[4 ]; +unsigned short pad_len; +unsigned char reserved4[52 ]; +unsigned char confounder[8 ]; +} __attribute__((packed)); + +#define CCA_PVT_EXT_CRT_SEC_ID_PVT 0x08 +#define CCA_PVT_EXT_CRT_SEC_FMT_CL 0x40 + +/** +* Set up private key fields of a type6 MEX message. +* Note that all numerics in the key token are big-endian, +* while the entries in the key block header are little-endian. +* +* @mex: pointer to user input data +* @p: pointer to memory area for the key +* +* Returns the size of the key area or -EFAULT +*/ +static inline int zcrypt_type6_mex_key_de (struct ica_rsa_modexpo *mex, +void *p,int big_endian) +{ +static struct cca_token_hdr static_pvt_me_hdr = { + .token_identifier =0x1E , + .token_length =0x0183 , + }; +static struct cca_private_ext_ME_sec static_pvt_me_sec = { + .section_identifier =0x02 , + .section_length =0x016C , + .key_use_flags = {0x80 ,0x00 ,0x00 ,0x00 }, + }; +static struct cca_public_sec static_pub_me_sec = { + .section_identifier =0x04 , + .section_length =0x000F , + .exponent_len =0x0003 , + }; +static char pk_exponent[3 ] = {0x01 ,0x00 ,0x01 }; +struct { +struct T6_keyBlock_hdr t6_hdr; +struct cca_token_hdr pvtMeHdr; +struct cca_private_ext_ME_sec pvtMeSec; +struct cca_public_sec pubMeSec; +char exponent[3 ]; + } __attribute__((packed)) *key = p; +unsigned char *temp; + +memset (key,0 ,sizeof (*key)); + +if (big_endian) { + key->t6_hdr.blen =cpu_to_be16 (0x189 ); + key->t6_hdr.ulen =cpu_to_be16 (0x189 -2 ); + }else { + key->t6_hdr.blen =cpu_to_le16 (0x189 ); + key->t6_hdr.ulen =cpu_to_le16 (0x189 -2 ); + } + key->pvtMeHdr = static_pvt_me_hdr; + key->pvtMeSec = static_pvt_me_sec; + key->pubMeSec = static_pub_me_sec; +/** +* In a private key, the modulus doesn't appear in the public +* section. So, an arbitrary public exponent of 0x010001 will be +* used. +*/ +memcpy (key->exponent, pk_exponent,3 ); + +/* key parameter block */ + temp = key->pvtMeSec.exponent + +sizeof (key->pvtMeSec.exponent) - mex->inputdatalength; +if (copy_from_user (temp, mex->b_key, mex->inputdatalength)) +return -EFAULT ; + +/* modulus */ + temp = key->pvtMeSec.modulus + +sizeof (key->pvtMeSec.modulus) - mex->inputdatalength; +if (copy_from_user (temp, mex->n_modulus, mex->inputdatalength)) +return -EFAULT ; + key->pubMeSec.modulus_bit_len =8 * mex->inputdatalength; +return sizeof (*key); +} + +/** +* Set up private key fields of a type6 MEX message. The _pad variant +* strips leading zeroes from the b_key. +* Note that all numerics in the key token are big-endian, +* while the entries in the key block header are little-endian. +* +* @mex: pointer to user input data +* @p: pointer to memory area for the key +* +* Returns the size of the key area or -EFAULT +*/ +static inline int zcrypt_type6_mex_key_en (struct ica_rsa_modexpo *mex, +void *p,int big_endian) +{ +static struct cca_token_hdr static_pub_hdr = { + .token_identifier =0x1E , + }; +static struct cca_public_sec static_pub_sec = { + .section_identifier =0x04 , + }; +struct { +struct T6_keyBlock_hdr t6_hdr; +struct cca_token_hdr pubHdr; +struct cca_public_sec pubSec; +char exponent[0 ]; + } __attribute__((packed)) *key = p; +unsigned char *temp; +int i; + +memset (key,0 ,sizeof (*key)); + + key->pubHdr = static_pub_hdr; + key->pubSec = static_pub_sec; + +/* key parameter block */ + temp = key->exponent; +if (copy_from_user (temp, mex->b_key, mex->inputdatalength)) +return -EFAULT ; +/* Strip leading zeroes from b_key. */ +for (i =0 ; i < mex->inputdatalength; i++) +if (temp[i]) +break ; +if (i >= mex->inputdatalength) +return -EINVAL ; +memmove (temp, temp + i, mex->inputdatalength - i); + temp += mex->inputdatalength - i; +/* modulus */ +if (copy_from_user (temp, mex->n_modulus, mex->inputdatalength)) +return -EFAULT ; + + key->pubSec.modulus_bit_len =8 * mex->inputdatalength; + key->pubSec.modulus_byte_len = mex->inputdatalength; + key->pubSec.exponent_len = mex->inputdatalength - i; + key->pubSec.section_length =sizeof (key->pubSec) + +2 *mex->inputdatalength - i; + key->pubHdr.token_length = + key->pubSec.section_length +sizeof (key->pubHdr); +if (big_endian) { + key->t6_hdr.ulen =cpu_to_be16 (key->pubHdr.token_length +4 ); + key->t6_hdr.blen =cpu_to_be16 (key->pubHdr.token_length +6 ); + }else { + key->t6_hdr.ulen =cpu_to_le16 (key->pubHdr.token_length +4 ); + key->t6_hdr.blen =cpu_to_le16 (key->pubHdr.token_length +6 ); + } +return sizeof (*key) +2 *mex->inputdatalength - i; +} + +/** +* Set up private key fields of a type6 CRT message. +* Note that all numerics in the key token are big-endian, +* while the entries in the key block header are little-endian. +* +* @mex: pointer to user input data +* @p: pointer to memory area for the key +* +* Returns the size of the key area or -EFAULT +*/ +static inline int zcrypt_type6_crt_key (struct ica_rsa_modexpo_crt *crt, +void *p,int big_endian) +{ +static struct cca_public_sec static_cca_pub_sec = { + .section_identifier =4 , + .section_length =0x000f , + .exponent_len =0x0003 , + }; +static char pk_exponent[3 ] = {0x01 ,0x00 ,0x01 }; +struct { +struct T6_keyBlock_hdr t6_hdr; +struct cca_token_hdr token; +struct cca_pvt_ext_CRT_sec pvt; +char key_parts[0 ]; + } __attribute__((packed)) *key = p; +struct cca_public_sec *pub; +int short_len, long_len, pad_len, key_len, size; + +memset (key,0 ,sizeof (*key)); + + short_len = crt->inputdatalength /2 ; + long_len = short_len +8 ; + pad_len = -(3 *long_len +2 *short_len) &7 ; + key_len =3 *long_len +2 *short_len + pad_len + crt->inputdatalength; + size =sizeof (*key) + key_len +sizeof (*pub) +3 ; + +/* parameter block.key block */ +if (big_endian) { + key->t6_hdr.blen =cpu_to_be16 (size); + key->t6_hdr.ulen =cpu_to_be16 (size -2 ); + }else { + key->t6_hdr.blen =cpu_to_le16 (size); + key->t6_hdr.ulen =cpu_to_le16 (size -2 ); + } + +/* key token header */ + key->token.token_identifier =CCA_TKN_HDR_ID_EXT ; + key->token.token_length = size -6 ; + +/* private section */ + key->pvt.section_identifier =CCA_PVT_EXT_CRT_SEC_ID_PVT ; + key->pvt.section_length =sizeof (key->pvt) + key_len; + key->pvt.key_format =CCA_PVT_EXT_CRT_SEC_FMT_CL ; + key->pvt.key_use_flags[0 ] =CCA_PVT_USAGE_ALL ; + key->pvt.p_len = key->pvt.dp_len = key->pvt.u_len = long_len; + key->pvt.q_len = key->pvt.dq_len = short_len; + key->pvt.mod_len = crt->inputdatalength; + key->pvt.pad_len = pad_len; + +/* key parts */ +if (copy_from_user (key->key_parts, crt->np_prime, long_len) || +copy_from_user (key->key_parts + long_len, + crt->nq_prime, short_len) || +copy_from_user (key->key_parts + long_len + short_len, + crt->bp_key, long_len) || +copy_from_user (key->key_parts +2 *long_len + short_len, + crt->bq_key, short_len) || +copy_from_user (key->key_parts +2 *long_len +2 *short_len, + crt->u_mult_inv, long_len)) +return -EFAULT ; +memset (key->key_parts +3 *long_len +2 *short_len + pad_len, +0xff , crt->inputdatalength); + pub = (struct cca_public_sec *)(key->key_parts + key_len); + *pub = static_cca_pub_sec; + pub->modulus_bit_len =8 * crt->inputdatalength; +/** +* In a private key, the modulus doesn't appear in the public +* section. So, an arbitrary public exponent of 0x010001 will be +* used. +*/ +memcpy ((char *) (pub +1 ), pk_exponent,3 ); +return size; +} + +#endif /* _ZCRYPT_CCA_KEY_H_ */
drivers/s390/crypto/zcrypt_pcicc.c +651 -0
651 lines not on this page · raw message
drivers/s390/crypto/zcrypt_pcicc.h +176 -0
176 lines not on this page · raw message
drivers/s390/crypto/zcrypt_pcixcc.c +735 -0
735 lines not on this page · raw message
drivers/s390/crypto/zcrypt_pcixcc.h +79 -0
79 lines not on this page · raw message