/* * linux/drivers/s390/crypto/zcrypt_pcixcc.c * * zcrypt 2.1.0 * * Copyright (C) 2001, 2006 IBM Corporation * Author(s): Robert Burroughs * Eric Rossman (edrossma@us.ibm.com) * * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> * Ralph Wuerthner <rwuerthn@de.ibm.com> * * 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. */#include <linux/module.h>#include <linux/init.h>#include <linux/err.h>#include <linux/delay.h>#include <linux/slab.h>#include <linux/atomic.h>#include <asm/uaccess.h>#include"ap_bus.h"#include"zcrypt_api.h"#include"zcrypt_error.h"#include"zcrypt_pcicc.h"#include"zcrypt_pcixcc.h"#include"zcrypt_cca_key.h"#define PCIXCC_MIN_MOD_SIZE 16/* 128 bits */#define PCIXCC_MIN_MOD_SIZE_OLD 64/* 512 bits */#define PCIXCC_MAX_MOD_SIZE 256/* 2048 bits */#define CEX3C_MIN_MOD_SIZE PCIXCC_MIN_MOD_SIZE#define CEX3C_MAX_MOD_SIZE 512/* 4096 bits */#define PCIXCC_MCL2_SPEED_RATING 7870#define PCIXCC_MCL3_SPEED_RATING 7870#define CEX2C_SPEED_RATING 7000#define CEX3C_SPEED_RATING 6500#define PCIXCC_MAX_ICA_MESSAGE_SIZE 0x77c/* max size type6 v2 crt message */#define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c/* max size type86 v2 reply */#define PCIXCC_MAX_XCRB_MESSAGE_SIZE (12*1024)#define PCIXCC_CLEANUP_TIME (15*HZ)#define CEIL4(x) ((((x)+3)/4)*4)struct response_type {struct completion work;int type;};#define PCIXCC_RESPONSE_TYPE_ICA 0#define PCIXCC_RESPONSE_TYPE_XCRB 1static struct ap_device_id zcrypt_pcixcc_ids[] = {{AP_DEVICE(AP_DEVICE_TYPE_PCIXCC) },{AP_DEVICE(AP_DEVICE_TYPE_CEX2C) },{AP_DEVICE(AP_DEVICE_TYPE_CEX3C) },{/* end of list */},};MODULE_DEVICE_TABLE(ap, zcrypt_pcixcc_ids);MODULE_AUTHOR("IBM Corporation");MODULE_DESCRIPTION("PCIXCC Cryptographic Coprocessor device driver, ""Copyright 2001, 2006 IBM Corporation");MODULE_LICENSE("GPL");static intzcrypt_pcixcc_probe(struct ap_device *ap_dev);static voidzcrypt_pcixcc_remove(struct ap_device *ap_dev);static voidzcrypt_pcixcc_receive(struct ap_device *,struct ap_message *,struct ap_message *);static struct ap_driver zcrypt_pcixcc_driver = {.probe = zcrypt_pcixcc_probe,.remove = zcrypt_pcixcc_remove,.ids = zcrypt_pcixcc_ids,.request_timeout = PCIXCC_CLEANUP_TIME,};/** * The following is used to initialize the CPRBX passed to the PCIXCC/CEX2C * card in a type6 message. The 3 fields that must be filled in at execution * time are req_parml, rpl_parml and usage_domain. * Everything about this interface is ascii/big-endian, since the * device does *not* have 'Intel inside'. * * The CPRBX is followed immediately by the parm block. * The parm block contains: * - function code ('PD' 0x5044 or 'PK' 0x504B) * - rule block (one of:) * + 0x000A 'PKCS-1.2' (MCL2 'PD') * + 0x000A 'ZERO-PAD' (MCL2 'PK') * + 0x000A 'ZERO-PAD' (MCL3 'PD' or CEX2C 'PD') * + 0x000A 'MRP ' (MCL3 'PK' or CEX2C 'PK') * - VUD block */static struct CPRBX static_cprbx = {.cprb_len =0x00DC,.cprb_ver_id =0x02,.func_id = {0x54,0x32},};/** * Convert a ICAMEX message to a type6 MEX message. * * @zdev: crypto device pointer * @ap_msg: pointer to AP message * @mex: pointer to user input data * * Returns 0 on success or -EFAULT. */static intICAMEX_msg_to_type6MEX_msgX(struct zcrypt_device *zdev,struct ap_message *ap_msg,struct ica_rsa_modexpo *mex){static struct type6_hdr static_type6_hdrX = {.type =0x06,.offset1 =0x00000058,.agent_id = {'C','A',},.function_code = {'P','K'},};static struct function_and_rules_block static_pke_fnr = {.function_code = {'P','K'},.ulen =10,.only_rule = {'M','R','P',' ',' ',' ',' ',' '}};static struct function_and_rules_block static_pke_fnr_MCL2 = {.function_code = {'P','K'},.ulen =10,.only_rule = {'Z','E','R','O','-','P','A','D'}};struct{struct type6_hdr hdr;struct CPRBX cprbx;struct function_and_rules_block fr;unsigned short length;char text[0];}__attribute__((packed)) *msg = ap_msg->message;int size;/* VUD.ciphertext */
msg->length = mex->inputdatalength +2;if(copy_from_user(msg->text, mex->inputdata, mex->inputdatalength))return-EFAULT;/* Set up key which is located after the variable length text. */
size =zcrypt_type6_mex_key_en(mex, msg->text+mex->inputdatalength,1);if(size <0)return size;
size +=sizeof(*msg) + mex->inputdatalength;/* message header, cprbx and f&r */
msg->hdr = static_type6_hdrX;
msg->hdr.ToCardLen1 = size -sizeof(msg->hdr);
msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE -sizeof(msg->hdr);
msg->cprbx = static_cprbx;
msg->cprbx.domain =AP_QID_QUEUE(zdev->ap_dev->qid);
msg->cprbx.rpl_msgbl = msg->hdr.FromCardLen1;
msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
static_pke_fnr_MCL2 : static_pke_fnr;
msg->cprbx.req_parml = size -sizeof(msg->hdr) -sizeof(msg->cprbx);
ap_msg->length = size;return0;}/** * Convert a ICACRT message to a type6 CRT message. * * @zdev: crypto device pointer * @ap_msg: pointer to AP message * @crt: pointer to user input data * * Returns 0 on success or -EFAULT. */static intICACRT_msg_to_type6CRT_msgX(struct zcrypt_device *zdev,struct ap_message *ap_msg,struct ica_rsa_modexpo_crt *crt){static struct type6_hdr static_type6_hdrX = {.type =0x06,.offset1 =0x00000058,.agent_id = {'C','A',},.function_code = {'P','D'},};static struct function_and_rules_block static_pkd_fnr = {.function_code = {'P','D'},.ulen =10,.only_rule = {'Z','E','R','O','-','P','A','D'}};static struct function_and_rules_block static_pkd_fnr_MCL2 = {.function_code = {'P','D'},.ulen =10,.only_rule = {'P','K','C','S','-','1','.','2'}};struct{struct