4 * Copyright IBM Corp. 2001, 2012
5 * Author(s): Robert Burroughs
6 * Eric Rossman (edrossma@us.ibm.com)
8 * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
9 * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com>
10 * Ralph Wuerthner <rwuerthn@de.ibm.com>
11 * MSGTYPE restruct: Holger Dengler <hd@linux.vnet.ibm.com>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #define KMSG_COMPONENT "zcrypt"
29 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
31 #include <linux/module.h>
32 #include <linux/init.h>
33 #include <linux/err.h>
34 #include <linux/delay.h>
35 #include <linux/slab.h>
36 #include <linux/atomic.h>
37 #include <linux/uaccess.h>
40 #include "zcrypt_api.h"
41 #include "zcrypt_error.h"
42 #include "zcrypt_msgtype6.h"
43 #include "zcrypt_cca_key.h"
45 #define PCIXCC_MIN_MOD_SIZE_OLD 64 /* 512 bits */
46 #define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c /* max size type86 v2 reply */
48 #define CEIL4(x) ((((x)+3)/4)*4)
50 struct response_type
{
51 struct completion work
;
54 #define PCIXCC_RESPONSE_TYPE_ICA 0
55 #define PCIXCC_RESPONSE_TYPE_XCRB 1
56 #define PCIXCC_RESPONSE_TYPE_EP11 2
58 MODULE_AUTHOR("IBM Corporation");
59 MODULE_DESCRIPTION("Cryptographic Coprocessor (message type 6), " \
60 "Copyright IBM Corp. 2001, 2012");
61 MODULE_LICENSE("GPL");
65 * Note that all shorts, ints and longs are little-endian.
66 * All pointer fields are 32-bits long, and mean nothing
68 * A request CPRB is followed by a request_parameter_block.
70 * The request (or reply) parameter block is organized thus:
76 unsigned short cprb_len
; /* CPRB length */
77 unsigned char cprb_ver_id
; /* CPRB version id. */
78 unsigned char pad_000
; /* Alignment pad byte. */
79 unsigned char srpi_rtcode
[4]; /* SRPI return code LELONG */
80 unsigned char srpi_verb
; /* SRPI verb type */
81 unsigned char flags
; /* flags */
82 unsigned char func_id
[2]; /* function id */
83 unsigned char checkpoint_flag
; /* */
84 unsigned char resv2
; /* reserved */
85 unsigned short req_parml
; /* request parameter buffer */
86 /* length 16-bit little endian */
87 unsigned char req_parmp
[4]; /* request parameter buffer *
88 * pointer (means nothing: the *
89 * parameter buffer follows *
91 unsigned char req_datal
[4]; /* request data buffer */
93 unsigned char req_datap
[4]; /* request data buffer */
95 unsigned short rpl_parml
; /* reply parameter buffer */
96 /* length 16-bit little endian */
97 unsigned char pad_001
[2]; /* Alignment pad bytes. ULESHORT */
98 unsigned char rpl_parmp
[4]; /* reply parameter buffer *
99 * pointer (means nothing: the *
100 * parameter buffer follows *
102 unsigned char rpl_datal
[4]; /* reply data buffer len ULELONG */
103 unsigned char rpl_datap
[4]; /* reply data buffer */
105 unsigned short ccp_rscode
; /* server reason code ULESHORT */
106 unsigned short ccp_rtcode
; /* server return code ULESHORT */
107 unsigned char repd_parml
[2]; /* replied parameter len ULESHORT*/
108 unsigned char mac_data_len
[2]; /* Mac Data Length ULESHORT */
109 unsigned char repd_datal
[4]; /* replied data length ULELONG */
110 unsigned char req_pc
[2]; /* PC identifier */
111 unsigned char res_origin
[8]; /* resource origin */
112 unsigned char mac_value
[8]; /* Mac Value */
113 unsigned char logon_id
[8]; /* Logon Identifier */
114 unsigned char usage_domain
[2]; /* cdx */
115 unsigned char resv3
[18]; /* reserved for requestor */
116 unsigned short svr_namel
; /* server name length ULESHORT */
117 unsigned char svr_name
[8]; /* server name */
120 struct function_and_rules_block
{
121 unsigned char function_code
[2];
123 unsigned char only_rule
[8];
127 * The following is used to initialize the CPRBX passed to the PCIXCC/CEX2C
128 * card in a type6 message. The 3 fields that must be filled in at execution
129 * time are req_parml, rpl_parml and usage_domain.
130 * Everything about this interface is ascii/big-endian, since the
131 * device does *not* have 'Intel inside'.
133 * The CPRBX is followed immediately by the parm block.
134 * The parm block contains:
135 * - function code ('PD' 0x5044 or 'PK' 0x504B)
136 * - rule block (one of:)
137 * + 0x000A 'PKCS-1.2' (MCL2 'PD')
138 * + 0x000A 'ZERO-PAD' (MCL2 'PK')
139 * + 0x000A 'ZERO-PAD' (MCL3 'PD' or CEX2C 'PD')
140 * + 0x000A 'MRP ' (MCL3 'PK' or CEX2C 'PK')
143 static const struct CPRBX static_cprbx
= {
146 .func_id
= {0x54, 0x32},
149 int speed_idx_cca(int req_type
)
224 int speed_idx_ep11(int req_type
)
256 * Convert a ICAMEX message to a type6 MEX message.
258 * @zq: crypto device pointer
259 * @ap_msg: pointer to AP message
260 * @mex: pointer to user input data
262 * Returns 0 on success or -EFAULT.
264 static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_queue
*zq
,
265 struct ap_message
*ap_msg
,
266 struct ica_rsa_modexpo
*mex
)
268 static struct type6_hdr static_type6_hdrX
= {
270 .offset1
= 0x00000058,
271 .agent_id
= {'C', 'A',},
272 .function_code
= {'P', 'K'},
274 static struct function_and_rules_block static_pke_fnr
= {
275 .function_code
= {'P', 'K'},
277 .only_rule
= {'M', 'R', 'P', ' ', ' ', ' ', ' ', ' '}
280 struct type6_hdr hdr
;
282 struct function_and_rules_block fr
;
283 unsigned short length
;
285 } __packed
* msg
= ap_msg
->message
;
289 msg
->length
= mex
->inputdatalength
+ 2;
290 if (copy_from_user(msg
->text
, mex
->inputdata
, mex
->inputdatalength
))
293 /* Set up key which is located after the variable length text. */
294 size
= zcrypt_type6_mex_key_en(mex
, msg
->text
+mex
->inputdatalength
);
297 size
+= sizeof(*msg
) + mex
->inputdatalength
;
299 /* message header, cprbx and f&r */
300 msg
->hdr
= static_type6_hdrX
;
301 msg
->hdr
.ToCardLen1
= size
- sizeof(msg
->hdr
);
302 msg
->hdr
.FromCardLen1
= PCIXCC_MAX_ICA_RESPONSE_SIZE
- sizeof(msg
->hdr
);
304 msg
->cprbx
= static_cprbx
;
305 msg
->cprbx
.domain
= AP_QID_QUEUE(zq
->queue
->qid
);
306 msg
->cprbx
.rpl_msgbl
= msg
->hdr
.FromCardLen1
;
308 msg
->fr
= static_pke_fnr
;
310 msg
->cprbx
.req_parml
= size
- sizeof(msg
->hdr
) - sizeof(msg
->cprbx
);
312 ap_msg
->length
= size
;
317 * Convert a ICACRT message to a type6 CRT message.
319 * @zq: crypto device pointer
320 * @ap_msg: pointer to AP message
321 * @crt: pointer to user input data
323 * Returns 0 on success or -EFAULT.
325 static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_queue
*zq
,
326 struct ap_message
*ap_msg
,
327 struct ica_rsa_modexpo_crt
*crt
)
329 static struct type6_hdr static_type6_hdrX
= {
331 .offset1
= 0x00000058,
332 .agent_id
= {'C', 'A',},
333 .function_code
= {'P', 'D'},
335 static struct function_and_rules_block static_pkd_fnr
= {
336 .function_code
= {'P', 'D'},
338 .only_rule
= {'Z', 'E', 'R', 'O', '-', 'P', 'A', 'D'}
342 struct type6_hdr hdr
;
344 struct function_and_rules_block fr
;
345 unsigned short length
;
347 } __packed
* msg
= ap_msg
->message
;
351 msg
->length
= crt
->inputdatalength
+ 2;
352 if (copy_from_user(msg
->text
, crt
->inputdata
, crt
->inputdatalength
))
355 /* Set up key which is located after the variable length text. */
356 size
= zcrypt_type6_crt_key(crt
, msg
->text
+ crt
->inputdatalength
);
359 size
+= sizeof(*msg
) + crt
->inputdatalength
; /* total size of msg */
361 /* message header, cprbx and f&r */
362 msg
->hdr
= static_type6_hdrX
;
363 msg
->hdr
.ToCardLen1
= size
- sizeof(msg
->hdr
);
364 msg
->hdr
.FromCardLen1
= PCIXCC_MAX_ICA_RESPONSE_SIZE
- sizeof(msg
->hdr
);
366 msg
->cprbx
= static_cprbx
;
367 msg
->cprbx
.domain
= AP_QID_QUEUE(zq
->queue
->qid
);
368 msg
->cprbx
.req_parml
= msg
->cprbx
.rpl_msgbl
=
369 size
- sizeof(msg
->hdr
) - sizeof(msg
->cprbx
);
371 msg
->fr
= static_pkd_fnr
;
373 ap_msg
->length
= size
;
378 * Convert a XCRB message to a type6 CPRB message.
380 * @zq: crypto device pointer
381 * @ap_msg: pointer to AP message
382 * @xcRB: pointer to user input data
384 * Returns 0 on success or -EFAULT, -EINVAL.
386 struct type86_fmt2_msg
{
387 struct type86_hdr hdr
;
388 struct type86_fmt2_ext fmt2
;
391 static int XCRB_msg_to_type6CPRB_msgX(struct ap_message
*ap_msg
,
392 struct ica_xcRB
*xcRB
,
394 unsigned short **dom
)
396 static struct type6_hdr static_type6_hdrX
= {
398 .offset1
= 0x00000058,
401 struct type6_hdr hdr
;
403 } __packed
* msg
= ap_msg
->message
;
405 int rcblen
= CEIL4(xcRB
->request_control_blk_length
);
406 int replylen
, req_sumlen
, resp_sumlen
;
407 char *req_data
= ap_msg
->message
+ sizeof(struct type6_hdr
) + rcblen
;
410 if (CEIL4(xcRB
->request_control_blk_length
) <
411 xcRB
->request_control_blk_length
)
412 return -EINVAL
; /* overflow after alignment*/
415 ap_msg
->length
= sizeof(struct type6_hdr
) +
416 CEIL4(xcRB
->request_control_blk_length
) +
417 xcRB
->request_data_length
;
418 if (ap_msg
->length
> MSGTYPE06_MAX_MSG_SIZE
)
422 sum must be greater (or equal) than the largest operand */
423 req_sumlen
= CEIL4(xcRB
->request_control_blk_length
) +
424 xcRB
->request_data_length
;
425 if ((CEIL4(xcRB
->request_control_blk_length
) <=
426 xcRB
->request_data_length
) ?
427 (req_sumlen
< xcRB
->request_data_length
) :
428 (req_sumlen
< CEIL4(xcRB
->request_control_blk_length
))) {
432 if (CEIL4(xcRB
->reply_control_blk_length
) <
433 xcRB
->reply_control_blk_length
)
434 return -EINVAL
; /* overflow after alignment*/
436 replylen
= sizeof(struct type86_fmt2_msg
) +
437 CEIL4(xcRB
->reply_control_blk_length
) +
438 xcRB
->reply_data_length
;
439 if (replylen
> MSGTYPE06_MAX_MSG_SIZE
)
443 sum must be greater (or equal) than the largest operand */
444 resp_sumlen
= CEIL4(xcRB
->reply_control_blk_length
) +
445 xcRB
->reply_data_length
;
446 if ((CEIL4(xcRB
->reply_control_blk_length
) <= xcRB
->reply_data_length
) ?
447 (resp_sumlen
< xcRB
->reply_data_length
) :
448 (resp_sumlen
< CEIL4(xcRB
->reply_control_blk_length
))) {
452 /* prepare type6 header */
453 msg
->hdr
= static_type6_hdrX
;
454 memcpy(msg
->hdr
.agent_id
, &(xcRB
->agent_ID
), sizeof(xcRB
->agent_ID
));
455 msg
->hdr
.ToCardLen1
= xcRB
->request_control_blk_length
;
456 if (xcRB
->request_data_length
) {
457 msg
->hdr
.offset2
= msg
->hdr
.offset1
+ rcblen
;
458 msg
->hdr
.ToCardLen2
= xcRB
->request_data_length
;
460 msg
->hdr
.FromCardLen1
= xcRB
->reply_control_blk_length
;
461 msg
->hdr
.FromCardLen2
= xcRB
->reply_data_length
;
464 if (copy_from_user(&(msg
->cprbx
), xcRB
->request_control_blk_addr
,
465 xcRB
->request_control_blk_length
))
467 if (msg
->cprbx
.cprb_len
+ sizeof(msg
->hdr
.function_code
) >
468 xcRB
->request_control_blk_length
)
470 function_code
= ((unsigned char *)&msg
->cprbx
) + msg
->cprbx
.cprb_len
;
471 memcpy(msg
->hdr
.function_code
, function_code
,
472 sizeof(msg
->hdr
.function_code
));
474 *fcode
= (msg
->hdr
.function_code
[0] << 8) | msg
->hdr
.function_code
[1];
475 *dom
= (unsigned short *)&msg
->cprbx
.domain
;
477 if (memcmp(function_code
, "US", 2) == 0
478 || memcmp(function_code
, "AU", 2) == 0)
483 /* copy data block */
484 if (xcRB
->request_data_length
&&
485 copy_from_user(req_data
, xcRB
->request_data_address
,
486 xcRB
->request_data_length
))
492 static int xcrb_msg_to_type6_ep11cprb_msgx(struct ap_message
*ap_msg
,
493 struct ep11_urb
*xcRB
,
497 static struct type6_hdr static_type6_ep11_hdr
= {
499 .rqid
= {0x00, 0x01},
500 .function_code
= {0x00, 0x00},
501 .agent_id
[0] = 0x58, /* {'X'} */
502 .agent_id
[1] = 0x43, /* {'C'} */
503 .offset1
= 0x00000058,
507 struct type6_hdr hdr
;
508 struct ep11_cprb cprbx
;
509 unsigned char pld_tag
; /* fixed value 0x30 */
510 unsigned char pld_lenfmt
; /* payload length format */
511 } __packed
* msg
= ap_msg
->message
;
514 unsigned char func_tag
; /* fixed value 0x4 */
515 unsigned char func_len
; /* fixed value 0x4 */
516 unsigned int func_val
; /* function ID */
517 unsigned char dom_tag
; /* fixed value 0x4 */
518 unsigned char dom_len
; /* fixed value 0x4 */
519 unsigned int dom_val
; /* domain id */
520 } __packed
* payload_hdr
= NULL
;
522 if (CEIL4(xcRB
->req_len
) < xcRB
->req_len
)
523 return -EINVAL
; /* overflow after alignment*/
526 ap_msg
->length
= sizeof(struct type6_hdr
) + xcRB
->req_len
;
527 if (CEIL4(xcRB
->req_len
) > MSGTYPE06_MAX_MSG_SIZE
-
528 (sizeof(struct type6_hdr
)))
531 if (CEIL4(xcRB
->resp_len
) < xcRB
->resp_len
)
532 return -EINVAL
; /* overflow after alignment*/
534 if (CEIL4(xcRB
->resp_len
) > MSGTYPE06_MAX_MSG_SIZE
-
535 (sizeof(struct type86_fmt2_msg
)))
538 /* prepare type6 header */
539 msg
->hdr
= static_type6_ep11_hdr
;
540 msg
->hdr
.ToCardLen1
= xcRB
->req_len
;
541 msg
->hdr
.FromCardLen1
= xcRB
->resp_len
;
543 /* Import CPRB data from the ioctl input parameter */
544 if (copy_from_user(&(msg
->cprbx
.cprb_len
),
545 (char __force __user
*)xcRB
->req
, xcRB
->req_len
)) {
549 if ((msg
->pld_lenfmt
& 0x80) == 0x80) { /*ext.len.fmt 2 or 3*/
550 switch (msg
->pld_lenfmt
& 0x03) {
561 lfmt
= 1; /* length format #1 */
563 payload_hdr
= (struct pld_hdr
*)((&(msg
->pld_lenfmt
))+lfmt
);
564 *fcode
= payload_hdr
->func_val
& 0xFFFF;
570 * Copy results from a type 86 ICA reply message back to user space.
572 * @zq: crypto device pointer
573 * @reply: reply AP message.
574 * @data: pointer to user output data
575 * @length: size of user output data
577 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
579 struct type86x_reply
{
580 struct type86_hdr hdr
;
581 struct type86_fmt2_ext fmt2
;
583 unsigned char pad
[4]; /* 4 byte function code/rules block ? */
584 unsigned short length
;
588 struct type86_ep11_reply
{
589 struct type86_hdr hdr
;
590 struct type86_fmt2_ext fmt2
;
591 struct ep11_cprb cprbx
;
594 static int convert_type86_ica(struct zcrypt_queue
*zq
,
595 struct ap_message
*reply
,
596 char __user
*outputdata
,
597 unsigned int outputdatalength
)
599 static unsigned char static_pad
[] = {
601 0x1B, 0x7B, 0x5D, 0xB5, 0x75, 0x01, 0x3D, 0xFD,
602 0x8D, 0xD1, 0xC7, 0x03, 0x2D, 0x09, 0x23, 0x57,
603 0x89, 0x49, 0xB9, 0x3F, 0xBB, 0x99, 0x41, 0x5B,
604 0x75, 0x21, 0x7B, 0x9D, 0x3B, 0x6B, 0x51, 0x39,
605 0xBB, 0x0D, 0x35, 0xB9, 0x89, 0x0F, 0x93, 0xA5,
606 0x0B, 0x47, 0xF1, 0xD3, 0xBB, 0xCB, 0xF1, 0x9D,
607 0x23, 0x73, 0x71, 0xFF, 0xF3, 0xF5, 0x45, 0xFB,
608 0x61, 0x29, 0x23, 0xFD, 0xF1, 0x29, 0x3F, 0x7F,
609 0x17, 0xB7, 0x1B, 0xA9, 0x19, 0xBD, 0x57, 0xA9,
610 0xD7, 0x95, 0xA3, 0xCB, 0xED, 0x1D, 0xDB, 0x45,
611 0x7D, 0x11, 0xD1, 0x51, 0x1B, 0xED, 0x71, 0xE9,
612 0xB1, 0xD1, 0xAB, 0xAB, 0x21, 0x2B, 0x1B, 0x9F,
613 0x3B, 0x9F, 0xF7, 0xF7, 0xBD, 0x63, 0xEB, 0xAD,
614 0xDF, 0xB3, 0x6F, 0x5B, 0xDB, 0x8D, 0xA9, 0x5D,
615 0xE3, 0x7D, 0x77, 0x49, 0x47, 0xF5, 0xA7, 0xFD,
616 0xAB, 0x2F, 0x27, 0x35, 0x77, 0xD3, 0x49, 0xC9,
617 0x09, 0xEB, 0xB1, 0xF9, 0xBF, 0x4B, 0xCB, 0x2B,
618 0xEB, 0xEB, 0x05, 0xFF, 0x7D, 0xC7, 0x91, 0x8B,
619 0x09, 0x83, 0xB9, 0xB9, 0x69, 0x33, 0x39, 0x6B,
620 0x79, 0x75, 0x19, 0xBF, 0xBB, 0x07, 0x1D, 0xBD,
621 0x29, 0xBF, 0x39, 0x95, 0x93, 0x1D, 0x35, 0xC7,
622 0xC9, 0x4D, 0xE5, 0x97, 0x0B, 0x43, 0x9B, 0xF1,
623 0x16, 0x93, 0x03, 0x1F, 0xA5, 0xFB, 0xDB, 0xF3,
624 0x27, 0x4F, 0x27, 0x61, 0x05, 0x1F, 0xB9, 0x23,
625 0x2F, 0xC3, 0x81, 0xA9, 0x23, 0x71, 0x55, 0x55,
626 0xEB, 0xED, 0x41, 0xE5, 0xF3, 0x11, 0xF1, 0x43,
627 0x69, 0x03, 0xBD, 0x0B, 0x37, 0x0F, 0x51, 0x8F,
628 0x0B, 0xB5, 0x89, 0x5B, 0x67, 0xA9, 0xD9, 0x4F,
629 0x01, 0xF9, 0x21, 0x77, 0x37, 0x73, 0x79, 0xC5,
630 0x7F, 0x51, 0xC1, 0xCF, 0x97, 0xA1, 0x75, 0xAD,
631 0x35, 0x9D, 0xD3, 0xD3, 0xA7, 0x9D, 0x5D, 0x41,
632 0x6F, 0x65, 0x1B, 0xCF, 0xA9, 0x87, 0x91, 0x09
634 struct type86x_reply
*msg
= reply
->message
;
635 unsigned short service_rc
, service_rs
;
636 unsigned int reply_len
, pad_len
;
639 service_rc
= msg
->cprbx
.ccp_rtcode
;
640 if (unlikely(service_rc
!= 0)) {
641 service_rs
= msg
->cprbx
.ccp_rscode
;
642 if ((service_rc
== 8 && service_rs
== 66) ||
643 (service_rc
== 8 && service_rs
== 65) ||
644 (service_rc
== 8 && service_rs
== 72) ||
645 (service_rc
== 8 && service_rs
== 770) ||
646 (service_rc
== 12 && service_rs
== 769)) {
647 ZCRYPT_DBF(DBF_DEBUG
,
648 "device=%02x.%04x rc/rs=%d/%d => rc=EINVAL\n",
649 AP_QID_CARD(zq
->queue
->qid
),
650 AP_QID_QUEUE(zq
->queue
->qid
),
651 (int) service_rc
, (int) service_rs
);
654 if (service_rc
== 8 && service_rs
== 783) {
655 zq
->zcard
->min_mod_size
=
656 PCIXCC_MIN_MOD_SIZE_OLD
;
657 ZCRYPT_DBF(DBF_DEBUG
,
658 "device=%02x.%04x rc/rs=%d/%d => rc=EAGAIN\n",
659 AP_QID_CARD(zq
->queue
->qid
),
660 AP_QID_QUEUE(zq
->queue
->qid
),
661 (int) service_rc
, (int) service_rs
);
665 pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
666 AP_QID_CARD(zq
->queue
->qid
),
667 AP_QID_QUEUE(zq
->queue
->qid
));
669 "device=%02x.%04x rc/rs=%d/%d => online=0 rc=EAGAIN\n",
670 AP_QID_CARD(zq
->queue
->qid
),
671 AP_QID_QUEUE(zq
->queue
->qid
),
672 (int) service_rc
, (int) service_rs
);
673 return -EAGAIN
; /* repeat the request on a different device. */
676 reply_len
= msg
->length
- 2;
677 if (reply_len
> outputdatalength
)
680 * For all encipher requests, the length of the ciphertext (reply_len)
681 * will always equal the modulus length. For MEX decipher requests
682 * the output needs to get padded. Minimum pad size is 10.
684 * Currently, the cases where padding will be added is for:
685 * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support
686 * ZERO-PAD and CRT is only supported for PKD requests)
689 pad_len
= outputdatalength
- reply_len
;
693 /* 'restore' padding left in the PCICC/PCIXCC card. */
694 if (copy_to_user(outputdata
, static_pad
, pad_len
- 1))
696 if (put_user(0, outputdata
+ pad_len
- 1))
699 /* Copy the crypto response to user space. */
700 if (copy_to_user(outputdata
+ pad_len
, data
, reply_len
))
706 * Copy results from a type 86 XCRB reply message back to user space.
708 * @zq: crypto device pointer
709 * @reply: reply AP message.
710 * @xcRB: pointer to XCRB
712 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
714 static int convert_type86_xcrb(struct zcrypt_queue
*zq
,
715 struct ap_message
*reply
,
716 struct ica_xcRB
*xcRB
)
718 struct type86_fmt2_msg
*msg
= reply
->message
;
719 char *data
= reply
->message
;
721 /* Copy CPRB to user */
722 if (copy_to_user(xcRB
->reply_control_blk_addr
,
723 data
+ msg
->fmt2
.offset1
, msg
->fmt2
.count1
))
725 xcRB
->reply_control_blk_length
= msg
->fmt2
.count1
;
727 /* Copy data buffer to user */
728 if (msg
->fmt2
.count2
)
729 if (copy_to_user(xcRB
->reply_data_addr
,
730 data
+ msg
->fmt2
.offset2
, msg
->fmt2
.count2
))
732 xcRB
->reply_data_length
= msg
->fmt2
.count2
;
737 * Copy results from a type 86 EP11 XCRB reply message back to user space.
739 * @zq: crypto device pointer
740 * @reply: reply AP message.
741 * @xcRB: pointer to EP11 user request block
743 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
745 static int convert_type86_ep11_xcrb(struct zcrypt_queue
*zq
,
746 struct ap_message
*reply
,
747 struct ep11_urb
*xcRB
)
749 struct type86_fmt2_msg
*msg
= reply
->message
;
750 char *data
= reply
->message
;
752 if (xcRB
->resp_len
< msg
->fmt2
.count1
)
755 /* Copy response CPRB to user */
756 if (copy_to_user((char __force __user
*)xcRB
->resp
,
757 data
+ msg
->fmt2
.offset1
, msg
->fmt2
.count1
))
759 xcRB
->resp_len
= msg
->fmt2
.count1
;
763 static int convert_type86_rng(struct zcrypt_queue
*zq
,
764 struct ap_message
*reply
,
768 struct type86_hdr hdr
;
769 struct type86_fmt2_ext fmt2
;
771 } __packed
* msg
= reply
->message
;
772 char *data
= reply
->message
;
774 if (msg
->cprbx
.ccp_rtcode
!= 0 || msg
->cprbx
.ccp_rscode
!= 0)
776 memcpy(buffer
, data
+ msg
->fmt2
.offset2
, msg
->fmt2
.count2
);
777 return msg
->fmt2
.count2
;
780 static int convert_response_ica(struct zcrypt_queue
*zq
,
781 struct ap_message
*reply
,
782 char __user
*outputdata
,
783 unsigned int outputdatalength
)
785 struct type86x_reply
*msg
= reply
->message
;
787 switch (msg
->hdr
.type
) {
788 case TYPE82_RSP_CODE
:
789 case TYPE88_RSP_CODE
:
790 return convert_error(zq
, reply
);
791 case TYPE86_RSP_CODE
:
792 if (msg
->cprbx
.ccp_rtcode
&&
793 (msg
->cprbx
.ccp_rscode
== 0x14f) &&
794 (outputdatalength
> 256)) {
795 if (zq
->zcard
->max_exp_bit_length
<= 17) {
796 zq
->zcard
->max_exp_bit_length
= 17;
801 if (msg
->hdr
.reply_code
)
802 return convert_error(zq
, reply
);
803 if (msg
->cprbx
.cprb_ver_id
== 0x02)
804 return convert_type86_ica(zq
, reply
,
805 outputdata
, outputdatalength
);
806 /* Fall through, no break, incorrect cprb version is an unknown
808 default: /* Unknown response type, this should NEVER EVER happen */
810 pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
811 AP_QID_CARD(zq
->queue
->qid
),
812 AP_QID_QUEUE(zq
->queue
->qid
));
814 "device=%02x.%04x rtype=0x%02x => online=0 rc=EAGAIN\n",
815 AP_QID_CARD(zq
->queue
->qid
),
816 AP_QID_QUEUE(zq
->queue
->qid
),
817 (int) msg
->hdr
.type
);
818 return -EAGAIN
; /* repeat the request on a different device. */
822 static int convert_response_xcrb(struct zcrypt_queue
*zq
,
823 struct ap_message
*reply
,
824 struct ica_xcRB
*xcRB
)
826 struct type86x_reply
*msg
= reply
->message
;
828 switch (msg
->hdr
.type
) {
829 case TYPE82_RSP_CODE
:
830 case TYPE88_RSP_CODE
:
831 xcRB
->status
= 0x0008044DL
; /* HDD_InvalidParm */
832 return convert_error(zq
, reply
);
833 case TYPE86_RSP_CODE
:
834 if (msg
->hdr
.reply_code
) {
835 memcpy(&(xcRB
->status
), msg
->fmt2
.apfs
, sizeof(u32
));
836 return convert_error(zq
, reply
);
838 if (msg
->cprbx
.cprb_ver_id
== 0x02)
839 return convert_type86_xcrb(zq
, reply
, xcRB
);
840 /* Fall through, no break, incorrect cprb version is an unknown
842 default: /* Unknown response type, this should NEVER EVER happen */
843 xcRB
->status
= 0x0008044DL
; /* HDD_InvalidParm */
845 pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
846 AP_QID_CARD(zq
->queue
->qid
),
847 AP_QID_QUEUE(zq
->queue
->qid
));
849 "device=%02x.%04x rtype=0x%02x => online=0 rc=EAGAIN\n",
850 AP_QID_CARD(zq
->queue
->qid
),
851 AP_QID_QUEUE(zq
->queue
->qid
),
852 (int) msg
->hdr
.type
);
853 return -EAGAIN
; /* repeat the request on a different device. */
857 static int convert_response_ep11_xcrb(struct zcrypt_queue
*zq
,
858 struct ap_message
*reply
, struct ep11_urb
*xcRB
)
860 struct type86_ep11_reply
*msg
= reply
->message
;
862 switch (msg
->hdr
.type
) {
863 case TYPE82_RSP_CODE
:
864 case TYPE87_RSP_CODE
:
865 return convert_error(zq
, reply
);
866 case TYPE86_RSP_CODE
:
867 if (msg
->hdr
.reply_code
)
868 return convert_error(zq
, reply
);
869 if (msg
->cprbx
.cprb_ver_id
== 0x04)
870 return convert_type86_ep11_xcrb(zq
, reply
, xcRB
);
871 /* Fall through, no break, incorrect cprb version is an unknown resp.*/
872 default: /* Unknown response type, this should NEVER EVER happen */
874 pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
875 AP_QID_CARD(zq
->queue
->qid
),
876 AP_QID_QUEUE(zq
->queue
->qid
));
878 "device=%02x.%04x rtype=0x%02x => online=0 rc=EAGAIN\n",
879 AP_QID_CARD(zq
->queue
->qid
),
880 AP_QID_QUEUE(zq
->queue
->qid
),
881 (int) msg
->hdr
.type
);
882 return -EAGAIN
; /* repeat the request on a different device. */
886 static int convert_response_rng(struct zcrypt_queue
*zq
,
887 struct ap_message
*reply
,
890 struct type86x_reply
*msg
= reply
->message
;
892 switch (msg
->hdr
.type
) {
893 case TYPE82_RSP_CODE
:
894 case TYPE88_RSP_CODE
:
896 case TYPE86_RSP_CODE
:
897 if (msg
->hdr
.reply_code
)
899 if (msg
->cprbx
.cprb_ver_id
== 0x02)
900 return convert_type86_rng(zq
, reply
, data
);
901 /* Fall through, no break, incorrect cprb version is an unknown
903 default: /* Unknown response type, this should NEVER EVER happen */
905 pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
906 AP_QID_CARD(zq
->queue
->qid
),
907 AP_QID_QUEUE(zq
->queue
->qid
));
909 "device=%02x.%04x rtype=0x%02x => online=0 rc=EAGAIN\n",
910 AP_QID_CARD(zq
->queue
->qid
),
911 AP_QID_QUEUE(zq
->queue
->qid
),
912 (int) msg
->hdr
.type
);
913 return -EAGAIN
; /* repeat the request on a different device. */
918 * This function is called from the AP bus code after a crypto request
919 * "msg" has finished with the reply message "reply".
920 * It is called from tasklet context.
921 * @aq: pointer to the AP queue
922 * @msg: pointer to the AP message
923 * @reply: pointer to the AP reply message
925 static void zcrypt_msgtype6_receive(struct ap_queue
*aq
,
926 struct ap_message
*msg
,
927 struct ap_message
*reply
)
929 static struct error_hdr error_reply
= {
930 .type
= TYPE82_RSP_CODE
,
931 .reply_code
= REP82_ERROR_MACHINE_FAILURE
,
933 struct response_type
*resp_type
=
934 (struct response_type
*) msg
->private;
935 struct type86x_reply
*t86r
;
938 /* Copy the reply message to the request message buffer. */
940 goto out
; /* ap_msg->rc indicates the error */
941 t86r
= reply
->message
;
942 if (t86r
->hdr
.type
== TYPE86_RSP_CODE
&&
943 t86r
->cprbx
.cprb_ver_id
== 0x02) {
944 switch (resp_type
->type
) {
945 case PCIXCC_RESPONSE_TYPE_ICA
:
946 length
= sizeof(struct type86x_reply
)
948 length
= min(PCIXCC_MAX_ICA_RESPONSE_SIZE
, length
);
949 memcpy(msg
->message
, reply
->message
, length
);
951 case PCIXCC_RESPONSE_TYPE_XCRB
:
952 length
= t86r
->fmt2
.offset2
+ t86r
->fmt2
.count2
;
953 length
= min(MSGTYPE06_MAX_MSG_SIZE
, length
);
954 memcpy(msg
->message
, reply
->message
, length
);
957 memcpy(msg
->message
, &error_reply
,
958 sizeof(error_reply
));
961 memcpy(msg
->message
, reply
->message
, sizeof(error_reply
));
963 complete(&(resp_type
->work
));
967 * This function is called from the AP bus code after a crypto request
968 * "msg" has finished with the reply message "reply".
969 * It is called from tasklet context.
970 * @aq: pointer to the AP queue
971 * @msg: pointer to the AP message
972 * @reply: pointer to the AP reply message
974 static void zcrypt_msgtype6_receive_ep11(struct ap_queue
*aq
,
975 struct ap_message
*msg
,
976 struct ap_message
*reply
)
978 static struct error_hdr error_reply
= {
979 .type
= TYPE82_RSP_CODE
,
980 .reply_code
= REP82_ERROR_MACHINE_FAILURE
,
982 struct response_type
*resp_type
=
983 (struct response_type
*)msg
->private;
984 struct type86_ep11_reply
*t86r
;
987 /* Copy the reply message to the request message buffer. */
989 goto out
; /* ap_msg->rc indicates the error */
990 t86r
= reply
->message
;
991 if (t86r
->hdr
.type
== TYPE86_RSP_CODE
&&
992 t86r
->cprbx
.cprb_ver_id
== 0x04) {
993 switch (resp_type
->type
) {
994 case PCIXCC_RESPONSE_TYPE_EP11
:
995 length
= t86r
->fmt2
.offset1
+ t86r
->fmt2
.count1
;
996 length
= min(MSGTYPE06_MAX_MSG_SIZE
, length
);
997 memcpy(msg
->message
, reply
->message
, length
);
1000 memcpy(msg
->message
, &error_reply
, sizeof(error_reply
));
1003 memcpy(msg
->message
, reply
->message
, sizeof(error_reply
));
1006 complete(&(resp_type
->work
));
1009 static atomic_t zcrypt_step
= ATOMIC_INIT(0);
1012 * The request distributor calls this function if it picked the PCIXCC/CEX2C
1013 * device to handle a modexpo request.
1014 * @zq: pointer to zcrypt_queue structure that identifies the
1015 * PCIXCC/CEX2C device to the request distributor
1016 * @mex: pointer to the modexpo request buffer
1018 static long zcrypt_msgtype6_modexpo(struct zcrypt_queue
*zq
,
1019 struct ica_rsa_modexpo
*mex
)
1021 struct ap_message ap_msg
;
1022 struct response_type resp_type
= {
1023 .type
= PCIXCC_RESPONSE_TYPE_ICA
,
1027 ap_init_message(&ap_msg
);
1028 ap_msg
.message
= (void *) get_zeroed_page(GFP_KERNEL
);
1029 if (!ap_msg
.message
)
1031 ap_msg
.receive
= zcrypt_msgtype6_receive
;
1032 ap_msg
.psmid
= (((unsigned long long) current
->pid
) << 32) +
1033 atomic_inc_return(&zcrypt_step
);
1034 ap_msg
.private = &resp_type
;
1035 rc
= ICAMEX_msg_to_type6MEX_msgX(zq
, &ap_msg
, mex
);
1038 init_completion(&resp_type
.work
);
1039 ap_queue_message(zq
->queue
, &ap_msg
);
1040 rc
= wait_for_completion_interruptible(&resp_type
.work
);
1044 rc
= convert_response_ica(zq
, &ap_msg
,
1046 mex
->outputdatalength
);
1048 /* Signal pending. */
1049 ap_cancel_message(zq
->queue
, &ap_msg
);
1051 free_page((unsigned long) ap_msg
.message
);
1056 * The request distributor calls this function if it picked the PCIXCC/CEX2C
1057 * device to handle a modexpo_crt request.
1058 * @zq: pointer to zcrypt_queue structure that identifies the
1059 * PCIXCC/CEX2C device to the request distributor
1060 * @crt: pointer to the modexpoc_crt request buffer
1062 static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_queue
*zq
,
1063 struct ica_rsa_modexpo_crt
*crt
)
1065 struct ap_message ap_msg
;
1066 struct response_type resp_type
= {
1067 .type
= PCIXCC_RESPONSE_TYPE_ICA
,
1071 ap_init_message(&ap_msg
);
1072 ap_msg
.message
= (void *) get_zeroed_page(GFP_KERNEL
);
1073 if (!ap_msg
.message
)
1075 ap_msg
.receive
= zcrypt_msgtype6_receive
;
1076 ap_msg
.psmid
= (((unsigned long long) current
->pid
) << 32) +
1077 atomic_inc_return(&zcrypt_step
);
1078 ap_msg
.private = &resp_type
;
1079 rc
= ICACRT_msg_to_type6CRT_msgX(zq
, &ap_msg
, crt
);
1082 init_completion(&resp_type
.work
);
1083 ap_queue_message(zq
->queue
, &ap_msg
);
1084 rc
= wait_for_completion_interruptible(&resp_type
.work
);
1088 rc
= convert_response_ica(zq
, &ap_msg
,
1090 crt
->outputdatalength
);
1092 /* Signal pending. */
1093 ap_cancel_message(zq
->queue
, &ap_msg
);
1096 free_page((unsigned long) ap_msg
.message
);
1100 unsigned int get_cprb_fc(struct ica_xcRB
*xcRB
,
1101 struct ap_message
*ap_msg
,
1102 unsigned int *func_code
, unsigned short **dom
)
1104 struct response_type resp_type
= {
1105 .type
= PCIXCC_RESPONSE_TYPE_XCRB
,
1109 ap_init_message(ap_msg
);
1110 ap_msg
->message
= kmalloc(MSGTYPE06_MAX_MSG_SIZE
, GFP_KERNEL
);
1111 if (!ap_msg
->message
)
1113 ap_msg
->receive
= zcrypt_msgtype6_receive
;
1114 ap_msg
->psmid
= (((unsigned long long) current
->pid
) << 32) +
1115 atomic_inc_return(&zcrypt_step
);
1116 ap_msg
->private = kmalloc(sizeof(resp_type
), GFP_KERNEL
);
1117 if (!ap_msg
->private) {
1118 kzfree(ap_msg
->message
);
1121 memcpy(ap_msg
->private, &resp_type
, sizeof(resp_type
));
1122 rc
= XCRB_msg_to_type6CPRB_msgX(ap_msg
, xcRB
, func_code
, dom
);
1124 kzfree(ap_msg
->message
);
1125 kzfree(ap_msg
->private);
1131 * The request distributor calls this function if it picked the PCIXCC/CEX2C
1132 * device to handle a send_cprb request.
1133 * @zq: pointer to zcrypt_queue structure that identifies the
1134 * PCIXCC/CEX2C device to the request distributor
1135 * @xcRB: pointer to the send_cprb request buffer
1137 static long zcrypt_msgtype6_send_cprb(struct zcrypt_queue
*zq
,
1138 struct ica_xcRB
*xcRB
,
1139 struct ap_message
*ap_msg
)
1142 struct response_type
*rtype
= (struct response_type
*)(ap_msg
->private);
1144 init_completion(&rtype
->work
);
1145 ap_queue_message(zq
->queue
, ap_msg
);
1146 rc
= wait_for_completion_interruptible(&rtype
->work
);
1150 rc
= convert_response_xcrb(zq
, ap_msg
, xcRB
);
1152 /* Signal pending. */
1153 ap_cancel_message(zq
->queue
, ap_msg
);
1155 kzfree(ap_msg
->message
);
1156 kzfree(ap_msg
->private);
1160 unsigned int get_ep11cprb_fc(struct ep11_urb
*xcrb
,
1161 struct ap_message
*ap_msg
,
1162 unsigned int *func_code
)
1164 struct response_type resp_type
= {
1165 .type
= PCIXCC_RESPONSE_TYPE_EP11
,
1169 ap_init_message(ap_msg
);
1170 ap_msg
->message
= kmalloc(MSGTYPE06_MAX_MSG_SIZE
, GFP_KERNEL
);
1171 if (!ap_msg
->message
)
1173 ap_msg
->receive
= zcrypt_msgtype6_receive_ep11
;
1174 ap_msg
->psmid
= (((unsigned long long) current
->pid
) << 32) +
1175 atomic_inc_return(&zcrypt_step
);
1176 ap_msg
->private = kmalloc(sizeof(resp_type
), GFP_KERNEL
);
1177 if (!ap_msg
->private) {
1178 kzfree(ap_msg
->message
);
1181 memcpy(ap_msg
->private, &resp_type
, sizeof(resp_type
));
1182 rc
= xcrb_msg_to_type6_ep11cprb_msgx(ap_msg
, xcrb
, func_code
);
1184 kzfree(ap_msg
->message
);
1185 kzfree(ap_msg
->private);
1191 * The request distributor calls this function if it picked the CEX4P
1192 * device to handle a send_ep11_cprb request.
1193 * @zq: pointer to zcrypt_queue structure that identifies the
1194 * CEX4P device to the request distributor
1195 * @xcRB: pointer to the ep11 user request block
1197 static long zcrypt_msgtype6_send_ep11_cprb(struct zcrypt_queue
*zq
,
1198 struct ep11_urb
*xcrb
,
1199 struct ap_message
*ap_msg
)
1203 struct response_type
*rtype
= (struct response_type
*)(ap_msg
->private);
1205 struct type6_hdr hdr
;
1206 struct ep11_cprb cprbx
;
1207 unsigned char pld_tag
; /* fixed value 0x30 */
1208 unsigned char pld_lenfmt
; /* payload length format */
1209 } __packed
* msg
= ap_msg
->message
;
1211 unsigned char func_tag
; /* fixed value 0x4 */
1212 unsigned char func_len
; /* fixed value 0x4 */
1213 unsigned int func_val
; /* function ID */
1214 unsigned char dom_tag
; /* fixed value 0x4 */
1215 unsigned char dom_len
; /* fixed value 0x4 */
1216 unsigned int dom_val
; /* domain id */
1217 } __packed
* payload_hdr
= NULL
;
1221 * The target domain field within the cprb body/payload block will be
1222 * replaced by the usage domain for non-management commands only.
1223 * Therefore we check the first bit of the 'flags' parameter for
1224 * management command indication.
1225 * 0 - non management command
1226 * 1 - management command
1228 if (!((msg
->cprbx
.flags
& 0x80) == 0x80)) {
1229 msg
->cprbx
.target_id
= (unsigned int)
1230 AP_QID_QUEUE(zq
->queue
->qid
);
1232 if ((msg
->pld_lenfmt
& 0x80) == 0x80) { /*ext.len.fmt 2 or 3*/
1233 switch (msg
->pld_lenfmt
& 0x03) {
1244 lfmt
= 1; /* length format #1 */
1246 payload_hdr
= (struct pld_hdr
*)((&(msg
->pld_lenfmt
))+lfmt
);
1247 payload_hdr
->dom_val
= (unsigned int)
1248 AP_QID_QUEUE(zq
->queue
->qid
);
1251 init_completion(&rtype
->work
);
1252 ap_queue_message(zq
->queue
, ap_msg
);
1253 rc
= wait_for_completion_interruptible(&rtype
->work
);
1257 rc
= convert_response_ep11_xcrb(zq
, ap_msg
, xcrb
);
1259 /* Signal pending. */
1260 ap_cancel_message(zq
->queue
, ap_msg
);
1262 kzfree(ap_msg
->message
);
1263 kzfree(ap_msg
->private);
1267 unsigned int get_rng_fc(struct ap_message
*ap_msg
, int *func_code
,
1268 unsigned int *domain
)
1270 struct response_type resp_type
= {
1271 .type
= PCIXCC_RESPONSE_TYPE_XCRB
,
1274 ap_init_message(ap_msg
);
1275 ap_msg
->message
= kmalloc(MSGTYPE06_MAX_MSG_SIZE
, GFP_KERNEL
);
1276 if (!ap_msg
->message
)
1278 ap_msg
->receive
= zcrypt_msgtype6_receive
;
1279 ap_msg
->psmid
= (((unsigned long long) current
->pid
) << 32) +
1280 atomic_inc_return(&zcrypt_step
);
1281 ap_msg
->private = kmalloc(sizeof(resp_type
), GFP_KERNEL
);
1282 if (!ap_msg
->private) {
1283 kzfree(ap_msg
->message
);
1286 memcpy(ap_msg
->private, &resp_type
, sizeof(resp_type
));
1288 rng_type6CPRB_msgX(ap_msg
, ZCRYPT_RNG_BUFFER_SIZE
, domain
);
1295 * The request distributor calls this function if it picked the PCIXCC/CEX2C
1296 * device to generate random data.
1297 * @zq: pointer to zcrypt_queue structure that identifies the
1298 * PCIXCC/CEX2C device to the request distributor
1299 * @buffer: pointer to a memory page to return random data
1301 static long zcrypt_msgtype6_rng(struct zcrypt_queue
*zq
,
1302 char *buffer
, struct ap_message
*ap_msg
)
1305 struct type6_hdr hdr
;
1307 char function_code
[2];
1308 short int rule_length
;
1310 short int verb_length
;
1311 short int key_length
;
1312 } __packed
* msg
= ap_msg
->message
;
1313 struct response_type
*rtype
= (struct response_type
*)(ap_msg
->private);
1316 msg
->cprbx
.domain
= AP_QID_QUEUE(zq
->queue
->qid
);
1318 init_completion(&rtype
->work
);
1319 ap_queue_message(zq
->queue
, ap_msg
);
1320 rc
= wait_for_completion_interruptible(&rtype
->work
);
1324 rc
= convert_response_rng(zq
, ap_msg
, buffer
);
1326 /* Signal pending. */
1327 ap_cancel_message(zq
->queue
, ap_msg
);
1329 kzfree(ap_msg
->message
);
1330 kzfree(ap_msg
->private);
1335 * The crypto operations for a PCIXCC/CEX2C card.
1337 static struct zcrypt_ops zcrypt_msgtype6_norng_ops
= {
1338 .owner
= THIS_MODULE
,
1339 .name
= MSGTYPE06_NAME
,
1340 .variant
= MSGTYPE06_VARIANT_NORNG
,
1341 .rsa_modexpo
= zcrypt_msgtype6_modexpo
,
1342 .rsa_modexpo_crt
= zcrypt_msgtype6_modexpo_crt
,
1343 .send_cprb
= zcrypt_msgtype6_send_cprb
,
1346 static struct zcrypt_ops zcrypt_msgtype6_ops
= {
1347 .owner
= THIS_MODULE
,
1348 .name
= MSGTYPE06_NAME
,
1349 .variant
= MSGTYPE06_VARIANT_DEFAULT
,
1350 .rsa_modexpo
= zcrypt_msgtype6_modexpo
,
1351 .rsa_modexpo_crt
= zcrypt_msgtype6_modexpo_crt
,
1352 .send_cprb
= zcrypt_msgtype6_send_cprb
,
1353 .rng
= zcrypt_msgtype6_rng
,
1356 static struct zcrypt_ops zcrypt_msgtype6_ep11_ops
= {
1357 .owner
= THIS_MODULE
,
1358 .name
= MSGTYPE06_NAME
,
1359 .variant
= MSGTYPE06_VARIANT_EP11
,
1360 .rsa_modexpo
= NULL
,
1361 .rsa_modexpo_crt
= NULL
,
1362 .send_ep11_cprb
= zcrypt_msgtype6_send_ep11_cprb
,
1365 void __init
zcrypt_msgtype6_init(void)
1367 zcrypt_msgtype_register(&zcrypt_msgtype6_norng_ops
);
1368 zcrypt_msgtype_register(&zcrypt_msgtype6_ops
);
1369 zcrypt_msgtype_register(&zcrypt_msgtype6_ep11_ops
);
1372 void __exit
zcrypt_msgtype6_exit(void)
1374 zcrypt_msgtype_unregister(&zcrypt_msgtype6_norng_ops
);
1375 zcrypt_msgtype_unregister(&zcrypt_msgtype6_ops
);
1376 zcrypt_msgtype_unregister(&zcrypt_msgtype6_ep11_ops
);