zcrypt_api.c
来自「linux 内核源代码」· C语言 代码 · 共 1,091 行 · 第 1/2 页
C
1,091 行
switch (cmd) { case ICARSAMODEXPO: { struct ica_rsa_modexpo __user *umex = (void __user *) arg; struct ica_rsa_modexpo mex; if (copy_from_user(&mex, umex, sizeof(mex))) return -EFAULT; do { rc = zcrypt_rsa_modexpo(&mex); } while (rc == -EAGAIN); if (rc) return rc; return put_user(mex.outputdatalength, &umex->outputdatalength); } case ICARSACRT: { struct ica_rsa_modexpo_crt __user *ucrt = (void __user *) arg; struct ica_rsa_modexpo_crt crt; if (copy_from_user(&crt, ucrt, sizeof(crt))) return -EFAULT; do { rc = zcrypt_rsa_crt(&crt); } while (rc == -EAGAIN); if (rc) return rc; return put_user(crt.outputdatalength, &ucrt->outputdatalength); } case ZSECSENDCPRB: { struct ica_xcRB __user *uxcRB = (void __user *) arg; struct ica_xcRB xcRB; if (copy_from_user(&xcRB, uxcRB, sizeof(xcRB))) return -EFAULT; do { rc = zcrypt_send_cprb(&xcRB); } while (rc == -EAGAIN); if (copy_to_user(uxcRB, &xcRB, sizeof(xcRB))) return -EFAULT; return rc; } case Z90STAT_STATUS_MASK: { char status[AP_DEVICES]; zcrypt_status_mask(status); if (copy_to_user((char __user *) arg, status, sizeof(char) * AP_DEVICES)) return -EFAULT; return 0; } case Z90STAT_QDEPTH_MASK: { char qdepth[AP_DEVICES]; zcrypt_qdepth_mask(qdepth); if (copy_to_user((char __user *) arg, qdepth, sizeof(char) * AP_DEVICES)) return -EFAULT; return 0; } case Z90STAT_PERDEV_REQCNT: { int reqcnt[AP_DEVICES]; zcrypt_perdev_reqcnt(reqcnt); if (copy_to_user((int __user *) arg, reqcnt, sizeof(int) * AP_DEVICES)) return -EFAULT; return 0; } case Z90STAT_REQUESTQ_COUNT: return put_user(zcrypt_requestq_count(), (int __user *) arg); case Z90STAT_PENDINGQ_COUNT: return put_user(zcrypt_pendingq_count(), (int __user *) arg); case Z90STAT_TOTALOPEN_COUNT: return put_user(atomic_read(&zcrypt_open_count), (int __user *) arg); case Z90STAT_DOMAIN_INDEX: return put_user(ap_domain_index, (int __user *) arg); /** * Deprecated ioctls. Don't add another device count ioctl, * you can count them yourself in the user space with the * output of the Z90STAT_STATUS_MASK ioctl. */ case ICAZ90STATUS: return zcrypt_ica_status(filp, arg); case Z90STAT_TOTALCOUNT: return put_user(zcrypt_device_count, (int __user *) arg); case Z90STAT_PCICACOUNT: return put_user(zcrypt_count_type(ZCRYPT_PCICA), (int __user *) arg); case Z90STAT_PCICCCOUNT: return put_user(zcrypt_count_type(ZCRYPT_PCICC), (int __user *) arg); case Z90STAT_PCIXCCMCL2COUNT: return put_user(zcrypt_count_type(ZCRYPT_PCIXCC_MCL2), (int __user *) arg); case Z90STAT_PCIXCCMCL3COUNT: return put_user(zcrypt_count_type(ZCRYPT_PCIXCC_MCL3), (int __user *) arg); case Z90STAT_PCIXCCCOUNT: return put_user(zcrypt_count_type(ZCRYPT_PCIXCC_MCL2) + zcrypt_count_type(ZCRYPT_PCIXCC_MCL3), (int __user *) arg); case Z90STAT_CEX2CCOUNT: return put_user(zcrypt_count_type(ZCRYPT_CEX2C), (int __user *) arg); case Z90STAT_CEX2ACOUNT: return put_user(zcrypt_count_type(ZCRYPT_CEX2A), (int __user *) arg); default: /* unknown ioctl number */ return -ENOIOCTLCMD; }}#ifdef CONFIG_COMPAT/** * ioctl32 conversion routines */struct compat_ica_rsa_modexpo { compat_uptr_t inputdata; unsigned int inputdatalength; compat_uptr_t outputdata; unsigned int outputdatalength; compat_uptr_t b_key; compat_uptr_t n_modulus;};static long trans_modexpo32(struct file *filp, unsigned int cmd, unsigned long arg){ struct compat_ica_rsa_modexpo __user *umex32 = compat_ptr(arg); struct compat_ica_rsa_modexpo mex32; struct ica_rsa_modexpo mex64; long rc; if (copy_from_user(&mex32, umex32, sizeof(mex32))) return -EFAULT; mex64.inputdata = compat_ptr(mex32.inputdata); mex64.inputdatalength = mex32.inputdatalength; mex64.outputdata = compat_ptr(mex32.outputdata); mex64.outputdatalength = mex32.outputdatalength; mex64.b_key = compat_ptr(mex32.b_key); mex64.n_modulus = compat_ptr(mex32.n_modulus); do { rc = zcrypt_rsa_modexpo(&mex64); } while (rc == -EAGAIN); if (!rc) rc = put_user(mex64.outputdatalength, &umex32->outputdatalength); return rc;}struct compat_ica_rsa_modexpo_crt { compat_uptr_t inputdata; unsigned int inputdatalength; compat_uptr_t outputdata; unsigned int outputdatalength; compat_uptr_t bp_key; compat_uptr_t bq_key; compat_uptr_t np_prime; compat_uptr_t nq_prime; compat_uptr_t u_mult_inv;};static long trans_modexpo_crt32(struct file *filp, unsigned int cmd, unsigned long arg){ struct compat_ica_rsa_modexpo_crt __user *ucrt32 = compat_ptr(arg); struct compat_ica_rsa_modexpo_crt crt32; struct ica_rsa_modexpo_crt crt64; long rc; if (copy_from_user(&crt32, ucrt32, sizeof(crt32))) return -EFAULT; crt64.inputdata = compat_ptr(crt32.inputdata); crt64.inputdatalength = crt32.inputdatalength; crt64.outputdata= compat_ptr(crt32.outputdata); crt64.outputdatalength = crt32.outputdatalength; crt64.bp_key = compat_ptr(crt32.bp_key); crt64.bq_key = compat_ptr(crt32.bq_key); crt64.np_prime = compat_ptr(crt32.np_prime); crt64.nq_prime = compat_ptr(crt32.nq_prime); crt64.u_mult_inv = compat_ptr(crt32.u_mult_inv); do { rc = zcrypt_rsa_crt(&crt64); } while (rc == -EAGAIN); if (!rc) rc = put_user(crt64.outputdatalength, &ucrt32->outputdatalength); return rc;}struct compat_ica_xcRB { unsigned short agent_ID; unsigned int user_defined; unsigned short request_ID; unsigned int request_control_blk_length; unsigned char padding1[16 - sizeof (compat_uptr_t)]; compat_uptr_t request_control_blk_addr; unsigned int request_data_length; char padding2[16 - sizeof (compat_uptr_t)]; compat_uptr_t request_data_address; unsigned int reply_control_blk_length; char padding3[16 - sizeof (compat_uptr_t)]; compat_uptr_t reply_control_blk_addr; unsigned int reply_data_length; char padding4[16 - sizeof (compat_uptr_t)]; compat_uptr_t reply_data_addr; unsigned short priority_window; unsigned int status;} __attribute__((packed));static long trans_xcRB32(struct file *filp, unsigned int cmd, unsigned long arg){ struct compat_ica_xcRB __user *uxcRB32 = compat_ptr(arg); struct compat_ica_xcRB xcRB32; struct ica_xcRB xcRB64; long rc; if (copy_from_user(&xcRB32, uxcRB32, sizeof(xcRB32))) return -EFAULT; xcRB64.agent_ID = xcRB32.agent_ID; xcRB64.user_defined = xcRB32.user_defined; xcRB64.request_ID = xcRB32.request_ID; xcRB64.request_control_blk_length = xcRB32.request_control_blk_length; xcRB64.request_control_blk_addr = compat_ptr(xcRB32.request_control_blk_addr); xcRB64.request_data_length = xcRB32.request_data_length; xcRB64.request_data_address = compat_ptr(xcRB32.request_data_address); xcRB64.reply_control_blk_length = xcRB32.reply_control_blk_length; xcRB64.reply_control_blk_addr = compat_ptr(xcRB32.reply_control_blk_addr); xcRB64.reply_data_length = xcRB32.reply_data_length; xcRB64.reply_data_addr = compat_ptr(xcRB32.reply_data_addr); xcRB64.priority_window = xcRB32.priority_window; xcRB64.status = xcRB32.status; do { rc = zcrypt_send_cprb(&xcRB64); } while (rc == -EAGAIN); xcRB32.reply_control_blk_length = xcRB64.reply_control_blk_length; xcRB32.reply_data_length = xcRB64.reply_data_length; xcRB32.status = xcRB64.status; if (copy_to_user(uxcRB32, &xcRB32, sizeof(xcRB32))) return -EFAULT; return rc;}static long zcrypt_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){ if (cmd == ICARSAMODEXPO) return trans_modexpo32(filp, cmd, arg); if (cmd == ICARSACRT) return trans_modexpo_crt32(filp, cmd, arg); if (cmd == ZSECSENDCPRB) return trans_xcRB32(filp, cmd, arg); return zcrypt_unlocked_ioctl(filp, cmd, arg);}#endif/** * Misc device file operations. */static const struct file_operations zcrypt_fops = { .owner = THIS_MODULE, .read = zcrypt_read, .write = zcrypt_write, .unlocked_ioctl = zcrypt_unlocked_ioctl,#ifdef CONFIG_COMPAT .compat_ioctl = zcrypt_compat_ioctl,#endif .open = zcrypt_open, .release = zcrypt_release};/** * Misc device. */static struct miscdevice zcrypt_misc_device = { .minor = MISC_DYNAMIC_MINOR, .name = "z90crypt", .fops = &zcrypt_fops,};/** * Deprecated /proc entry support. */static struct proc_dir_entry *zcrypt_entry;static int sprintcl(unsigned char *outaddr, unsigned char *addr, unsigned int len){ int hl, i; hl = 0; for (i = 0; i < len; i++) hl += sprintf(outaddr+hl, "%01x", (unsigned int) addr[i]); hl += sprintf(outaddr+hl, " "); return hl;}static int sprintrw(unsigned char *outaddr, unsigned char *addr, unsigned int len){ int hl, inl, c, cx; hl = sprintf(outaddr, " "); inl = 0; for (c = 0; c < (len / 16); c++) { hl += sprintcl(outaddr+hl, addr+inl, 16); inl += 16; } cx = len%16; if (cx) { hl += sprintcl(outaddr+hl, addr+inl, cx); inl += cx; } hl += sprintf(outaddr+hl, "\n"); return hl;}static int sprinthx(unsigned char *title, unsigned char *outaddr, unsigned char *addr, unsigned int len){ int hl, inl, r, rx; hl = sprintf(outaddr, "\n%s\n", title); inl = 0; for (r = 0; r < (len / 64); r++) { hl += sprintrw(outaddr+hl, addr+inl, 64); inl += 64; } rx = len % 64; if (rx) { hl += sprintrw(outaddr+hl, addr+inl, rx); inl += rx; } hl += sprintf(outaddr+hl, "\n"); return hl;}static int sprinthx4(unsigned char *title, unsigned char *outaddr, unsigned int *array, unsigned int len){ int hl, r; hl = sprintf(outaddr, "\n%s\n", title); for (r = 0; r < len; r++) { if ((r % 8) == 0) hl += sprintf(outaddr+hl, " "); hl += sprintf(outaddr+hl, "%08X ", array[r]); if ((r % 8) == 7) hl += sprintf(outaddr+hl, "\n"); } hl += sprintf(outaddr+hl, "\n"); return hl;}static int zcrypt_status_read(char *resp_buff, char **start, off_t offset, int count, int *eof, void *data){ unsigned char *workarea; int len; len = 0; /* resp_buff is a page. Use the right half for a work area */ workarea = resp_buff + 2000; len += sprintf(resp_buff + len, "\nzcrypt version: %d.%d.%d\n", ZCRYPT_VERSION, ZCRYPT_RELEASE, ZCRYPT_VARIANT); len += sprintf(resp_buff + len, "Cryptographic domain: %d\n", ap_domain_index); len += sprintf(resp_buff + len, "Total device count: %d\n", zcrypt_device_count); len += sprintf(resp_buff + len, "PCICA count: %d\n", zcrypt_count_type(ZCRYPT_PCICA)); len += sprintf(resp_buff + len, "PCICC count: %d\n", zcrypt_count_type(ZCRYPT_PCICC)); len += sprintf(resp_buff + len, "PCIXCC MCL2 count: %d\n", zcrypt_count_type(ZCRYPT_PCIXCC_MCL2)); len += sprintf(resp_buff + len, "PCIXCC MCL3 count: %d\n", zcrypt_count_type(ZCRYPT_PCIXCC_MCL3)); len += sprintf(resp_buff + len, "CEX2C count: %d\n", zcrypt_count_type(ZCRYPT_CEX2C)); len += sprintf(resp_buff + len, "CEX2A count: %d\n", zcrypt_count_type(ZCRYPT_CEX2A)); len += sprintf(resp_buff + len, "requestq count: %d\n", zcrypt_requestq_count()); len += sprintf(resp_buff + len, "pendingq count: %d\n", zcrypt_pendingq_count()); len += sprintf(resp_buff + len, "Total open handles: %d\n\n", atomic_read(&zcrypt_open_count)); zcrypt_status_mask(workarea); len += sprinthx("Online devices: 1=PCICA 2=PCICC 3=PCIXCC(MCL2) " "4=PCIXCC(MCL3) 5=CEX2C 6=CEX2A", resp_buff+len, workarea, AP_DEVICES); zcrypt_qdepth_mask(workarea); len += sprinthx("Waiting work element counts", resp_buff+len, workarea, AP_DEVICES); zcrypt_perdev_reqcnt((int *) workarea); len += sprinthx4("Per-device successfully completed request counts", resp_buff+len,(unsigned int *) workarea, AP_DEVICES); *eof = 1; memset((void *) workarea, 0x00, AP_DEVICES * sizeof(unsigned int)); return len;}static void zcrypt_disable_card(int index){ struct zcrypt_device *zdev; spin_lock_bh(&zcrypt_device_lock); list_for_each_entry(zdev, &zcrypt_device_list, list) if (AP_QID_DEVICE(zdev->ap_dev->qid) == index) { zdev->online = 0; ap_flush_queue(zdev->ap_dev); break; } spin_unlock_bh(&zcrypt_device_lock);}static void zcrypt_enable_card(int index){ struct zcrypt_device *zdev; spin_lock_bh(&zcrypt_device_lock); list_for_each_entry(zdev, &zcrypt_device_list, list) if (AP_QID_DEVICE(zdev->ap_dev->qid) == index) { zdev->online = 1; break; } spin_unlock_bh(&zcrypt_device_lock);}static int zcrypt_status_write(struct file *file, const char __user *buffer, unsigned long count, void *data){ unsigned char *lbuf, *ptr; unsigned long local_count; int j; if (count <= 0) return 0;#define LBUFSIZE 1200UL lbuf = kmalloc(LBUFSIZE, GFP_KERNEL); if (!lbuf) { PRINTK("kmalloc failed!\n"); return 0; } local_count = min(LBUFSIZE - 1, count); if (copy_from_user(lbuf, buffer, local_count) != 0) { kfree(lbuf); return -EFAULT; } lbuf[local_count] = '\0'; ptr = strstr(lbuf, "Online devices"); if (!ptr) { PRINTK("Unable to parse data (missing \"Online devices\")\n"); goto out; } ptr = strstr(ptr, "\n"); if (!ptr) { PRINTK("Unable to parse data (missing newline " "after \"Online devices\")\n"); goto out; } ptr++; if (strstr(ptr, "Waiting work element counts") == NULL) { PRINTK("Unable to parse data (missing " "\"Waiting work element counts\")\n"); goto out; } for (j = 0; j < 64 && *ptr; ptr++) { /** * '0' for no device, '1' for PCICA, '2' for PCICC, * '3' for PCIXCC_MCL2, '4' for PCIXCC_MCL3, * '5' for CEX2C and '6' for CEX2A' */ if (*ptr >= '0' && *ptr <= '6') j++; else if (*ptr == 'd' || *ptr == 'D') zcrypt_disable_card(j++); else if (*ptr == 'e' || *ptr == 'E') zcrypt_enable_card(j++); else if (*ptr != ' ' && *ptr != '\t') break; }out: kfree(lbuf); return count;}/** * The module initialization code. */int __init zcrypt_api_init(void){ int rc; /* Register the request sprayer. */ rc = misc_register(&zcrypt_misc_device); if (rc < 0) { PRINTKW(KERN_ERR "misc_register (minor %d) failed with %d\n", zcrypt_misc_device.minor, rc); goto out; } /* Set up the proc file system */ zcrypt_entry = create_proc_entry("driver/z90crypt", 0644, NULL); if (!zcrypt_entry) { PRINTK("Couldn't create z90crypt proc entry\n"); rc = -ENOMEM; goto out_misc; } zcrypt_entry->data = NULL; zcrypt_entry->read_proc = zcrypt_status_read; zcrypt_entry->write_proc = zcrypt_status_write; return 0;out_misc: misc_deregister(&zcrypt_misc_device);out: return rc;}/** * The module termination code. */void zcrypt_api_exit(void){ remove_proc_entry("driver/z90crypt", NULL); misc_deregister(&zcrypt_misc_device);}#ifndef CONFIG_ZCRYPT_MONOLITHICmodule_init(zcrypt_api_init);module_exit(zcrypt_api_exit);#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?