Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  *  Copyright IBM Corp. 2001, 2012
0004  *  Author(s): Robert Burroughs
0005  *         Eric Rossman (edrossma@us.ibm.com)
0006  *
0007  *  Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
0008  *  Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com>
0009  *                Ralph Wuerthner <rwuerthn@de.ibm.com>
0010  *  MSGTYPE restruct:         Holger Dengler <hd@linux.vnet.ibm.com>
0011  */
0012 
0013 #define KMSG_COMPONENT "zcrypt"
0014 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
0015 
0016 #include <linux/module.h>
0017 #include <linux/slab.h>
0018 #include <linux/init.h>
0019 #include <linux/err.h>
0020 #include <linux/atomic.h>
0021 #include <linux/uaccess.h>
0022 
0023 #include "ap_bus.h"
0024 #include "zcrypt_api.h"
0025 #include "zcrypt_error.h"
0026 #include "zcrypt_msgtype50.h"
0027 
0028 /* >= CEX3A: 4096 bits */
0029 #define CEX3A_MAX_MOD_SIZE 512
0030 
0031 /* CEX2A: max outputdatalength + type80_hdr */
0032 #define CEX2A_MAX_RESPONSE_SIZE 0x110
0033 
0034 /* >= CEX3A: 512 bit modulus, (max outputdatalength) + type80_hdr */
0035 #define CEX3A_MAX_RESPONSE_SIZE 0x210
0036 
0037 MODULE_AUTHOR("IBM Corporation");
0038 MODULE_DESCRIPTION("Cryptographic Accelerator (message type 50), " \
0039            "Copyright IBM Corp. 2001, 2012");
0040 MODULE_LICENSE("GPL");
0041 
0042 /*
0043  * The type 50 message family is associated with a CEXxA cards.
0044  *
0045  * The four members of the family are described below.
0046  *
0047  * Note that all unsigned char arrays are right-justified and left-padded
0048  * with zeroes.
0049  *
0050  * Note that all reserved fields must be zeroes.
0051  */
0052 struct type50_hdr {
0053     unsigned char   reserved1;
0054     unsigned char   msg_type_code;  /* 0x50 */
0055     unsigned short  msg_len;
0056     unsigned char   reserved2;
0057     unsigned char   ignored;
0058     unsigned short  reserved3;
0059 } __packed;
0060 
0061 #define TYPE50_TYPE_CODE    0x50
0062 
0063 #define TYPE50_MEB1_FMT     0x0001
0064 #define TYPE50_MEB2_FMT     0x0002
0065 #define TYPE50_MEB3_FMT     0x0003
0066 #define TYPE50_CRB1_FMT     0x0011
0067 #define TYPE50_CRB2_FMT     0x0012
0068 #define TYPE50_CRB3_FMT     0x0013
0069 
0070 /* Mod-Exp, with a small modulus */
0071 struct type50_meb1_msg {
0072     struct type50_hdr header;
0073     unsigned short  keyblock_type;  /* 0x0001 */
0074     unsigned char   reserved[6];
0075     unsigned char   exponent[128];
0076     unsigned char   modulus[128];
0077     unsigned char   message[128];
0078 } __packed;
0079 
0080 /* Mod-Exp, with a large modulus */
0081 struct type50_meb2_msg {
0082     struct type50_hdr header;
0083     unsigned short  keyblock_type;  /* 0x0002 */
0084     unsigned char   reserved[6];
0085     unsigned char   exponent[256];
0086     unsigned char   modulus[256];
0087     unsigned char   message[256];
0088 } __packed;
0089 
0090 /* Mod-Exp, with a larger modulus */
0091 struct type50_meb3_msg {
0092     struct type50_hdr header;
0093     unsigned short  keyblock_type;  /* 0x0003 */
0094     unsigned char   reserved[6];
0095     unsigned char   exponent[512];
0096     unsigned char   modulus[512];
0097     unsigned char   message[512];
0098 } __packed;
0099 
0100 /* CRT, with a small modulus */
0101 struct type50_crb1_msg {
0102     struct type50_hdr header;
0103     unsigned short  keyblock_type;  /* 0x0011 */
0104     unsigned char   reserved[6];
0105     unsigned char   p[64];
0106     unsigned char   q[64];
0107     unsigned char   dp[64];
0108     unsigned char   dq[64];
0109     unsigned char   u[64];
0110     unsigned char   message[128];
0111 } __packed;
0112 
0113 /* CRT, with a large modulus */
0114 struct type50_crb2_msg {
0115     struct type50_hdr header;
0116     unsigned short  keyblock_type;  /* 0x0012 */
0117     unsigned char   reserved[6];
0118     unsigned char   p[128];
0119     unsigned char   q[128];
0120     unsigned char   dp[128];
0121     unsigned char   dq[128];
0122     unsigned char   u[128];
0123     unsigned char   message[256];
0124 } __packed;
0125 
0126 /* CRT, with a larger modulus */
0127 struct type50_crb3_msg {
0128     struct type50_hdr header;
0129     unsigned short  keyblock_type;  /* 0x0013 */
0130     unsigned char   reserved[6];
0131     unsigned char   p[256];
0132     unsigned char   q[256];
0133     unsigned char   dp[256];
0134     unsigned char   dq[256];
0135     unsigned char   u[256];
0136     unsigned char   message[512];
0137 } __packed;
0138 
0139 /*
0140  * The type 80 response family is associated with a CEXxA cards.
0141  *
0142  * Note that all unsigned char arrays are right-justified and left-padded
0143  * with zeroes.
0144  *
0145  * Note that all reserved fields must be zeroes.
0146  */
0147 
0148 #define TYPE80_RSP_CODE 0x80
0149 
0150 struct type80_hdr {
0151     unsigned char   reserved1;
0152     unsigned char   type;       /* 0x80 */
0153     unsigned short  len;
0154     unsigned char   code;       /* 0x00 */
0155     unsigned char   reserved2[3];
0156     unsigned char   reserved3[8];
0157 } __packed;
0158 
0159 int get_rsa_modex_fc(struct ica_rsa_modexpo *mex, int *fcode)
0160 {
0161     if (!mex->inputdatalength)
0162         return -EINVAL;
0163 
0164     if (mex->inputdatalength <= 128)    /* 1024 bit */
0165         *fcode = MEX_1K;
0166     else if (mex->inputdatalength <= 256)   /* 2048 bit */
0167         *fcode = MEX_2K;
0168     else                    /* 4096 bit */
0169         *fcode = MEX_4K;
0170 
0171     return 0;
0172 }
0173 
0174 int get_rsa_crt_fc(struct ica_rsa_modexpo_crt *crt, int *fcode)
0175 {
0176     if (!crt->inputdatalength)
0177         return -EINVAL;
0178 
0179     if (crt->inputdatalength <= 128)    /* 1024 bit */
0180         *fcode = CRT_1K;
0181     else if (crt->inputdatalength <= 256)   /* 2048 bit */
0182         *fcode = CRT_2K;
0183     else                    /* 4096 bit */
0184         *fcode = CRT_4K;
0185 
0186     return 0;
0187 }
0188 
0189 /*
0190  * Convert a ICAMEX message to a type50 MEX message.
0191  *
0192  * @zq: crypto queue pointer
0193  * @ap_msg: crypto request pointer
0194  * @mex: pointer to user input data
0195  *
0196  * Returns 0 on success or -EFAULT.
0197  */
0198 static int ICAMEX_msg_to_type50MEX_msg(struct zcrypt_queue *zq,
0199                        struct ap_message *ap_msg,
0200                        struct ica_rsa_modexpo *mex)
0201 {
0202     unsigned char *mod, *exp, *inp;
0203     int mod_len;
0204 
0205     mod_len = mex->inputdatalength;
0206 
0207     if (mod_len <= 128) {
0208         struct type50_meb1_msg *meb1 = ap_msg->msg;
0209 
0210         memset(meb1, 0, sizeof(*meb1));
0211         ap_msg->len = sizeof(*meb1);
0212         meb1->header.msg_type_code = TYPE50_TYPE_CODE;
0213         meb1->header.msg_len = sizeof(*meb1);
0214         meb1->keyblock_type = TYPE50_MEB1_FMT;
0215         mod = meb1->modulus + sizeof(meb1->modulus) - mod_len;
0216         exp = meb1->exponent + sizeof(meb1->exponent) - mod_len;
0217         inp = meb1->message + sizeof(meb1->message) - mod_len;
0218     } else if (mod_len <= 256) {
0219         struct type50_meb2_msg *meb2 = ap_msg->msg;
0220 
0221         memset(meb2, 0, sizeof(*meb2));
0222         ap_msg->len = sizeof(*meb2);
0223         meb2->header.msg_type_code = TYPE50_TYPE_CODE;
0224         meb2->header.msg_len = sizeof(*meb2);
0225         meb2->keyblock_type = TYPE50_MEB2_FMT;
0226         mod = meb2->modulus + sizeof(meb2->modulus) - mod_len;
0227         exp = meb2->exponent + sizeof(meb2->exponent) - mod_len;
0228         inp = meb2->message + sizeof(meb2->message) - mod_len;
0229     } else if (mod_len <= 512) {
0230         struct type50_meb3_msg *meb3 = ap_msg->msg;
0231 
0232         memset(meb3, 0, sizeof(*meb3));
0233         ap_msg->len = sizeof(*meb3);
0234         meb3->header.msg_type_code = TYPE50_TYPE_CODE;
0235         meb3->header.msg_len = sizeof(*meb3);
0236         meb3->keyblock_type = TYPE50_MEB3_FMT;
0237         mod = meb3->modulus + sizeof(meb3->modulus) - mod_len;
0238         exp = meb3->exponent + sizeof(meb3->exponent) - mod_len;
0239         inp = meb3->message + sizeof(meb3->message) - mod_len;
0240     } else {
0241         return -EINVAL;
0242     }
0243 
0244     if (copy_from_user(mod, mex->n_modulus, mod_len) ||
0245         copy_from_user(exp, mex->b_key, mod_len) ||
0246         copy_from_user(inp, mex->inputdata, mod_len))
0247         return -EFAULT;
0248 
0249 #ifdef CONFIG_ZCRYPT_DEBUG
0250     if (ap_msg->fi.flags & AP_FI_FLAG_TOGGLE_SPECIAL)
0251         ap_msg->flags ^= AP_MSG_FLAG_SPECIAL;
0252 #endif
0253 
0254     return 0;
0255 }
0256 
0257 /*
0258  * Convert a ICACRT message to a type50 CRT message.
0259  *
0260  * @zq: crypto queue pointer
0261  * @ap_msg: crypto request pointer
0262  * @crt: pointer to user input data
0263  *
0264  * Returns 0 on success or -EFAULT.
0265  */
0266 static int ICACRT_msg_to_type50CRT_msg(struct zcrypt_queue *zq,
0267                        struct ap_message *ap_msg,
0268                        struct ica_rsa_modexpo_crt *crt)
0269 {
0270     int mod_len, short_len;
0271     unsigned char *p, *q, *dp, *dq, *u, *inp;
0272 
0273     mod_len = crt->inputdatalength;
0274     short_len = (mod_len + 1) / 2;
0275 
0276     /*
0277      * CEX2A and CEX3A w/o FW update can handle requests up to
0278      * 256 byte modulus (2k keys).
0279      * CEX3A with FW update and newer CEXxA cards are able to handle
0280      * 512 byte modulus (4k keys).
0281      */
0282     if (mod_len <= 128) {       /* up to 1024 bit key size */
0283         struct type50_crb1_msg *crb1 = ap_msg->msg;
0284 
0285         memset(crb1, 0, sizeof(*crb1));
0286         ap_msg->len = sizeof(*crb1);
0287         crb1->header.msg_type_code = TYPE50_TYPE_CODE;
0288         crb1->header.msg_len = sizeof(*crb1);
0289         crb1->keyblock_type = TYPE50_CRB1_FMT;
0290         p = crb1->p + sizeof(crb1->p) - short_len;
0291         q = crb1->q + sizeof(crb1->q) - short_len;
0292         dp = crb1->dp + sizeof(crb1->dp) - short_len;
0293         dq = crb1->dq + sizeof(crb1->dq) - short_len;
0294         u = crb1->u + sizeof(crb1->u) - short_len;
0295         inp = crb1->message + sizeof(crb1->message) - mod_len;
0296     } else if (mod_len <= 256) {    /* up to 2048 bit key size */
0297         struct type50_crb2_msg *crb2 = ap_msg->msg;
0298 
0299         memset(crb2, 0, sizeof(*crb2));
0300         ap_msg->len = sizeof(*crb2);
0301         crb2->header.msg_type_code = TYPE50_TYPE_CODE;
0302         crb2->header.msg_len = sizeof(*crb2);
0303         crb2->keyblock_type = TYPE50_CRB2_FMT;
0304         p = crb2->p + sizeof(crb2->p) - short_len;
0305         q = crb2->q + sizeof(crb2->q) - short_len;
0306         dp = crb2->dp + sizeof(crb2->dp) - short_len;
0307         dq = crb2->dq + sizeof(crb2->dq) - short_len;
0308         u = crb2->u + sizeof(crb2->u) - short_len;
0309         inp = crb2->message + sizeof(crb2->message) - mod_len;
0310     } else if ((mod_len <= 512) &&  /* up to 4096 bit key size */
0311            (zq->zcard->max_mod_size == CEX3A_MAX_MOD_SIZE)) {
0312         struct type50_crb3_msg *crb3 = ap_msg->msg;
0313 
0314         memset(crb3, 0, sizeof(*crb3));
0315         ap_msg->len = sizeof(*crb3);
0316         crb3->header.msg_type_code = TYPE50_TYPE_CODE;
0317         crb3->header.msg_len = sizeof(*crb3);
0318         crb3->keyblock_type = TYPE50_CRB3_FMT;
0319         p = crb3->p + sizeof(crb3->p) - short_len;
0320         q = crb3->q + sizeof(crb3->q) - short_len;
0321         dp = crb3->dp + sizeof(crb3->dp) - short_len;
0322         dq = crb3->dq + sizeof(crb3->dq) - short_len;
0323         u = crb3->u + sizeof(crb3->u) - short_len;
0324         inp = crb3->message + sizeof(crb3->message) - mod_len;
0325     } else {
0326         return -EINVAL;
0327     }
0328 
0329     /*
0330      * correct the offset of p, bp and mult_inv according zcrypt.h
0331      * block size right aligned (skip the first byte)
0332      */
0333     if (copy_from_user(p, crt->np_prime + MSGTYPE_ADJUSTMENT, short_len) ||
0334         copy_from_user(q, crt->nq_prime, short_len) ||
0335         copy_from_user(dp, crt->bp_key + MSGTYPE_ADJUSTMENT, short_len) ||
0336         copy_from_user(dq, crt->bq_key, short_len) ||
0337         copy_from_user(u, crt->u_mult_inv + MSGTYPE_ADJUSTMENT, short_len) ||
0338         copy_from_user(inp, crt->inputdata, mod_len))
0339         return -EFAULT;
0340 
0341 #ifdef CONFIG_ZCRYPT_DEBUG
0342     if (ap_msg->fi.flags & AP_FI_FLAG_TOGGLE_SPECIAL)
0343         ap_msg->flags ^= AP_MSG_FLAG_SPECIAL;
0344 #endif
0345 
0346     return 0;
0347 }
0348 
0349 /*
0350  * Copy results from a type 80 reply message back to user space.
0351  *
0352  * @zq: crypto device pointer
0353  * @reply: reply AP message.
0354  * @data: pointer to user output data
0355  * @length: size of user output data
0356  *
0357  * Returns 0 on success or -EFAULT.
0358  */
0359 static int convert_type80(struct zcrypt_queue *zq,
0360               struct ap_message *reply,
0361               char __user *outputdata,
0362               unsigned int outputdatalength)
0363 {
0364     struct type80_hdr *t80h = reply->msg;
0365     unsigned char *data;
0366 
0367     if (t80h->len < sizeof(*t80h) + outputdatalength) {
0368         /* The result is too short, the CEXxA card may not do that.. */
0369         zq->online = 0;
0370         pr_err("Crypto dev=%02x.%04x code=0x%02x => online=0 rc=EAGAIN\n",
0371                AP_QID_CARD(zq->queue->qid),
0372                AP_QID_QUEUE(zq->queue->qid), t80h->code);
0373         ZCRYPT_DBF_ERR("%s dev=%02x.%04x code=0x%02x => online=0 rc=EAGAIN\n",
0374                    __func__, AP_QID_CARD(zq->queue->qid),
0375                    AP_QID_QUEUE(zq->queue->qid), t80h->code);
0376         ap_send_online_uevent(&zq->queue->ap_dev, zq->online);
0377         return -EAGAIN;
0378     }
0379     if (zq->zcard->user_space_type == ZCRYPT_CEX2A)
0380         BUG_ON(t80h->len > CEX2A_MAX_RESPONSE_SIZE);
0381     else
0382         BUG_ON(t80h->len > CEX3A_MAX_RESPONSE_SIZE);
0383     data = reply->msg + t80h->len - outputdatalength;
0384     if (copy_to_user(outputdata, data, outputdatalength))
0385         return -EFAULT;
0386     return 0;
0387 }
0388 
0389 static int convert_response_cex2a(struct zcrypt_queue *zq,
0390                   struct ap_message *reply,
0391                   char __user *outputdata,
0392                   unsigned int outputdatalength)
0393 {
0394     /* Response type byte is the second byte in the response. */
0395     unsigned char rtype = ((unsigned char *)reply->msg)[1];
0396 
0397     switch (rtype) {
0398     case TYPE82_RSP_CODE:
0399     case TYPE88_RSP_CODE:
0400         return convert_error(zq, reply);
0401     case TYPE80_RSP_CODE:
0402         return convert_type80(zq, reply,
0403                       outputdata, outputdatalength);
0404     default: /* Unknown response type, this should NEVER EVER happen */
0405         zq->online = 0;
0406         pr_err("Crypto dev=%02x.%04x unknown response type 0x%02x => online=0 rc=EAGAIN\n",
0407                AP_QID_CARD(zq->queue->qid),
0408                AP_QID_QUEUE(zq->queue->qid),
0409                (int)rtype);
0410         ZCRYPT_DBF_ERR(
0411             "%s dev=%02x.%04x unknown response type 0x%02x => online=0 rc=EAGAIN\n",
0412             __func__, AP_QID_CARD(zq->queue->qid),
0413             AP_QID_QUEUE(zq->queue->qid), (int)rtype);
0414         ap_send_online_uevent(&zq->queue->ap_dev, zq->online);
0415         return -EAGAIN;
0416     }
0417 }
0418 
0419 /*
0420  * This function is called from the AP bus code after a crypto request
0421  * "msg" has finished with the reply message "reply".
0422  * It is called from tasklet context.
0423  * @aq: pointer to the AP device
0424  * @msg: pointer to the AP message
0425  * @reply: pointer to the AP reply message
0426  */
0427 static void zcrypt_cex2a_receive(struct ap_queue *aq,
0428                  struct ap_message *msg,
0429                  struct ap_message *reply)
0430 {
0431     static struct error_hdr error_reply = {
0432         .type = TYPE82_RSP_CODE,
0433         .reply_code = REP82_ERROR_MACHINE_FAILURE,
0434     };
0435     struct type80_hdr *t80h;
0436     int len;
0437 
0438     /* Copy the reply message to the request message buffer. */
0439     if (!reply)
0440         goto out;   /* ap_msg->rc indicates the error */
0441     t80h = reply->msg;
0442     if (t80h->type == TYPE80_RSP_CODE) {
0443         len = t80h->len;
0444         if (len > reply->bufsize || len > msg->bufsize) {
0445             msg->rc = -EMSGSIZE;
0446         } else {
0447             memcpy(msg->msg, reply->msg, len);
0448             msg->len = len;
0449         }
0450     } else {
0451         memcpy(msg->msg, reply->msg, sizeof(error_reply));
0452     }
0453 out:
0454     complete((struct completion *)msg->private);
0455 }
0456 
0457 static atomic_t zcrypt_step = ATOMIC_INIT(0);
0458 
0459 /*
0460  * The request distributor calls this function if it picked the CEXxA
0461  * device to handle a modexpo request.
0462  * @zq: pointer to zcrypt_queue structure that identifies the
0463  *  CEXxA device to the request distributor
0464  * @mex: pointer to the modexpo request buffer
0465  */
0466 static long zcrypt_cex2a_modexpo(struct zcrypt_queue *zq,
0467                  struct ica_rsa_modexpo *mex,
0468                  struct ap_message *ap_msg)
0469 {
0470     struct completion work;
0471     int rc;
0472 
0473     ap_msg->bufsize = (zq->zcard->user_space_type == ZCRYPT_CEX2A) ?
0474         MSGTYPE50_CRB2_MAX_MSG_SIZE : MSGTYPE50_CRB3_MAX_MSG_SIZE;
0475     ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
0476     if (!ap_msg->msg)
0477         return -ENOMEM;
0478     ap_msg->receive = zcrypt_cex2a_receive;
0479     ap_msg->psmid = (((unsigned long long)current->pid) << 32) +
0480         atomic_inc_return(&zcrypt_step);
0481     ap_msg->private = &work;
0482     rc = ICAMEX_msg_to_type50MEX_msg(zq, ap_msg, mex);
0483     if (rc)
0484         goto out;
0485     init_completion(&work);
0486     rc = ap_queue_message(zq->queue, ap_msg);
0487     if (rc)
0488         goto out;
0489     rc = wait_for_completion_interruptible(&work);
0490     if (rc == 0) {
0491         rc = ap_msg->rc;
0492         if (rc == 0)
0493             rc = convert_response_cex2a(zq, ap_msg,
0494                             mex->outputdata,
0495                             mex->outputdatalength);
0496     } else {
0497         /* Signal pending. */
0498         ap_cancel_message(zq->queue, ap_msg);
0499     }
0500 
0501 out:
0502     ap_msg->private = NULL;
0503     if (rc)
0504         ZCRYPT_DBF_DBG("%s send me cprb at dev=%02x.%04x rc=%d\n",
0505                    __func__, AP_QID_CARD(zq->queue->qid),
0506                    AP_QID_QUEUE(zq->queue->qid), rc);
0507     return rc;
0508 }
0509 
0510 /*
0511  * The request distributor calls this function if it picked the CEXxA
0512  * device to handle a modexpo_crt request.
0513  * @zq: pointer to zcrypt_queue structure that identifies the
0514  *  CEXxA device to the request distributor
0515  * @crt: pointer to the modexpoc_crt request buffer
0516  */
0517 static long zcrypt_cex2a_modexpo_crt(struct zcrypt_queue *zq,
0518                      struct ica_rsa_modexpo_crt *crt,
0519                      struct ap_message *ap_msg)
0520 {
0521     struct completion work;
0522     int rc;
0523 
0524     ap_msg->bufsize = (zq->zcard->user_space_type == ZCRYPT_CEX2A) ?
0525         MSGTYPE50_CRB2_MAX_MSG_SIZE : MSGTYPE50_CRB3_MAX_MSG_SIZE;
0526     ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
0527     if (!ap_msg->msg)
0528         return -ENOMEM;
0529     ap_msg->receive = zcrypt_cex2a_receive;
0530     ap_msg->psmid = (((unsigned long long)current->pid) << 32) +
0531         atomic_inc_return(&zcrypt_step);
0532     ap_msg->private = &work;
0533     rc = ICACRT_msg_to_type50CRT_msg(zq, ap_msg, crt);
0534     if (rc)
0535         goto out;
0536     init_completion(&work);
0537     rc = ap_queue_message(zq->queue, ap_msg);
0538     if (rc)
0539         goto out;
0540     rc = wait_for_completion_interruptible(&work);
0541     if (rc == 0) {
0542         rc = ap_msg->rc;
0543         if (rc == 0)
0544             rc = convert_response_cex2a(zq, ap_msg,
0545                             crt->outputdata,
0546                             crt->outputdatalength);
0547     } else {
0548         /* Signal pending. */
0549         ap_cancel_message(zq->queue, ap_msg);
0550     }
0551 
0552 out:
0553     ap_msg->private = NULL;
0554     if (rc)
0555         ZCRYPT_DBF_DBG("%s send crt cprb at dev=%02x.%04x rc=%d\n",
0556                    __func__, AP_QID_CARD(zq->queue->qid),
0557                    AP_QID_QUEUE(zq->queue->qid), rc);
0558     return rc;
0559 }
0560 
0561 /*
0562  * The crypto operations for message type 50.
0563  */
0564 static struct zcrypt_ops zcrypt_msgtype50_ops = {
0565     .rsa_modexpo = zcrypt_cex2a_modexpo,
0566     .rsa_modexpo_crt = zcrypt_cex2a_modexpo_crt,
0567     .owner = THIS_MODULE,
0568     .name = MSGTYPE50_NAME,
0569     .variant = MSGTYPE50_VARIANT_DEFAULT,
0570 };
0571 
0572 void __init zcrypt_msgtype50_init(void)
0573 {
0574     zcrypt_msgtype_register(&zcrypt_msgtype50_ops);
0575 }
0576 
0577 void __exit zcrypt_msgtype50_exit(void)
0578 {
0579     zcrypt_msgtype_unregister(&zcrypt_msgtype50_ops);
0580 }