Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/zcrypt: add new low level ep11 functions support file

This patch introduces two new files which provide some
low level functions to interact with EP11 crypto cards:

ep11_get_card_info() sends an EP11 query module info CPRB to the
addressed card, processes the returning reply and exposes some of
the information returned in the new ep11_card_info struct.

ep11_get_domain_info() sends an EP11 query domain info CPRB to the
addressed card/queue, processes the returning reply and exposes some
of the information returned in the new ep11_domain_info struct.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>

authored by

Harald Freudenberger and committed by
Vasily Gorbik
7384eb72 a7367997

+428 -1
+2 -1
drivers/s390/crypto/Makefile
··· 7 7 obj-$(subst m,y,$(CONFIG_ZCRYPT)) += ap.o 8 8 # zcrypt_api.o and zcrypt_msgtype*.o depend on ap.o 9 9 zcrypt-objs := zcrypt_api.o zcrypt_card.o zcrypt_queue.o 10 - zcrypt-objs += zcrypt_msgtype6.o zcrypt_msgtype50.o zcrypt_ccamisc.o 10 + zcrypt-objs += zcrypt_msgtype6.o zcrypt_msgtype50.o 11 + zcrypt-objs += zcrypt_ccamisc.o zcrypt_ep11misc.o 11 12 obj-$(CONFIG_ZCRYPT) += zcrypt.o 12 13 # adapter drivers depend on ap.o and zcrypt.o 13 14 obj-$(CONFIG_ZCRYPT) += zcrypt_cex2c.o zcrypt_cex2a.o zcrypt_cex4.o
+2
drivers/s390/crypto/zcrypt_api.c
··· 36 36 #include "zcrypt_msgtype6.h" 37 37 #include "zcrypt_msgtype50.h" 38 38 #include "zcrypt_ccamisc.h" 39 + #include "zcrypt_ep11misc.h" 39 40 40 41 /* 41 42 * Module description. ··· 1895 1894 zcrypt_msgtype6_exit(); 1896 1895 zcrypt_msgtype50_exit(); 1897 1896 zcrypt_ccamisc_exit(); 1897 + zcrypt_ep11misc_exit(); 1898 1898 zcrypt_debug_exit(); 1899 1899 } 1900 1900
+380
drivers/s390/crypto/zcrypt_ep11misc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright IBM Corp. 2019 4 + * Author(s): Harald Freudenberger <freude@linux.ibm.com> 5 + * 6 + * Collection of EP11 misc functions used by zcrypt and pkey 7 + */ 8 + 9 + #define KMSG_COMPONENT "zcrypt" 10 + #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 11 + 12 + #include <linux/init.h> 13 + #include <linux/module.h> 14 + #include <linux/slab.h> 15 + #include <linux/random.h> 16 + #include <asm/zcrypt.h> 17 + #include <asm/pkey.h> 18 + 19 + #include "ap_bus.h" 20 + #include "zcrypt_api.h" 21 + #include "zcrypt_debug.h" 22 + #include "zcrypt_msgtype6.h" 23 + #include "zcrypt_ep11misc.h" 24 + 25 + #define DEBUG_DBG(...) ZCRYPT_DBF(DBF_DEBUG, ##__VA_ARGS__) 26 + #define DEBUG_INFO(...) ZCRYPT_DBF(DBF_INFO, ##__VA_ARGS__) 27 + #define DEBUG_WARN(...) ZCRYPT_DBF(DBF_WARN, ##__VA_ARGS__) 28 + #define DEBUG_ERR(...) ZCRYPT_DBF(DBF_ERR, ##__VA_ARGS__) 29 + 30 + /* ep11 card info cache */ 31 + struct card_list_entry { 32 + struct list_head list; 33 + u16 cardnr; 34 + struct ep11_card_info info; 35 + }; 36 + static LIST_HEAD(card_list); 37 + static DEFINE_SPINLOCK(card_list_lock); 38 + 39 + static int card_cache_fetch(u16 cardnr, struct ep11_card_info *ci) 40 + { 41 + int rc = -ENOENT; 42 + struct card_list_entry *ptr; 43 + 44 + spin_lock_bh(&card_list_lock); 45 + list_for_each_entry(ptr, &card_list, list) { 46 + if (ptr->cardnr == cardnr) { 47 + memcpy(ci, &ptr->info, sizeof(*ci)); 48 + rc = 0; 49 + break; 50 + } 51 + } 52 + spin_unlock_bh(&card_list_lock); 53 + 54 + return rc; 55 + } 56 + 57 + static void card_cache_update(u16 cardnr, const struct ep11_card_info *ci) 58 + { 59 + int found = 0; 60 + struct card_list_entry *ptr; 61 + 62 + spin_lock_bh(&card_list_lock); 63 + list_for_each_entry(ptr, &card_list, list) { 64 + if (ptr->cardnr == cardnr) { 65 + memcpy(&ptr->info, ci, sizeof(*ci)); 66 + found = 1; 67 + break; 68 + } 69 + } 70 + if (!found) { 71 + ptr = kmalloc(sizeof(*ptr), GFP_ATOMIC); 72 + if (!ptr) { 73 + spin_unlock_bh(&card_list_lock); 74 + return; 75 + } 76 + ptr->cardnr = cardnr; 77 + memcpy(&ptr->info, ci, sizeof(*ci)); 78 + list_add(&ptr->list, &card_list); 79 + } 80 + spin_unlock_bh(&card_list_lock); 81 + } 82 + 83 + static void card_cache_scrub(u16 cardnr) 84 + { 85 + struct card_list_entry *ptr; 86 + 87 + spin_lock_bh(&card_list_lock); 88 + list_for_each_entry(ptr, &card_list, list) { 89 + if (ptr->cardnr == cardnr) { 90 + list_del(&ptr->list); 91 + kfree(ptr); 92 + break; 93 + } 94 + } 95 + spin_unlock_bh(&card_list_lock); 96 + } 97 + 98 + static void __exit card_cache_free(void) 99 + { 100 + struct card_list_entry *ptr, *pnext; 101 + 102 + spin_lock_bh(&card_list_lock); 103 + list_for_each_entry_safe(ptr, pnext, &card_list, list) { 104 + list_del(&ptr->list); 105 + kfree(ptr); 106 + } 107 + spin_unlock_bh(&card_list_lock); 108 + } 109 + 110 + /* 111 + * Helper function which calls zcrypt_send_ep11_cprb with 112 + * memory management segment adjusted to kernel space 113 + * so that the copy_from_user called within this 114 + * function do in fact copy from kernel space. 115 + */ 116 + static inline int _zcrypt_send_ep11_cprb(struct ep11_urb *urb) 117 + { 118 + int rc; 119 + mm_segment_t old_fs = get_fs(); 120 + 121 + set_fs(KERNEL_DS); 122 + rc = zcrypt_send_ep11_cprb(urb); 123 + set_fs(old_fs); 124 + 125 + return rc; 126 + } 127 + 128 + /* 129 + * Allocate and prepare ep11 cprb plus additional payload. 130 + */ 131 + static struct ep11_cprb *alloc_ep11_cprb(size_t payload_len) 132 + { 133 + size_t len = sizeof(struct ep11_cprb) + payload_len; 134 + struct ep11_cprb *cprb; 135 + 136 + cprb = kmalloc(len, GFP_KERNEL); 137 + if (!cprb) 138 + return NULL; 139 + 140 + memset(cprb, 0, len); 141 + cprb->cprb_len = sizeof(struct ep11_cprb); 142 + cprb->cprb_ver_id = 0x04; 143 + memcpy(cprb->func_id, "T4", 2); 144 + cprb->ret_code = 0xFFFFFFFF; 145 + cprb->payload_len = payload_len; 146 + 147 + return cprb; 148 + } 149 + 150 + /* 151 + * Helper function which does an ep11 query with given query type. 152 + */ 153 + static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type, 154 + size_t buflen, u8 *buf) 155 + { 156 + struct ep11_info_req_pl { 157 + u8 tag; 158 + u8 lenfmt; 159 + u8 func_tag; 160 + u8 func_len; 161 + u32 func; 162 + u8 dom_tag; 163 + u8 dom_len; 164 + u32 dom; 165 + u8 query_type_tag; 166 + u8 query_type_len; 167 + u32 query_type; 168 + u8 query_subtype_tag; 169 + u8 query_subtype_len; 170 + u32 query_subtype; 171 + } __packed * req_pl; 172 + struct ep11_info_rep_pl { 173 + u8 tag; 174 + u8 lenfmt; 175 + u16 len; 176 + u8 func_tag; 177 + u8 func_len; 178 + u32 func; 179 + u8 dom_tag; 180 + u8 dom_len; 181 + u32 dom; 182 + u8 rc_tag; 183 + u8 rc_len; 184 + u32 rc; 185 + u8 data_tag; 186 + u8 data_lenfmt; 187 + u16 data_len; 188 + } __packed * rep_pl; 189 + struct ep11_cprb *req = NULL, *rep = NULL; 190 + struct ep11_target_dev target; 191 + struct ep11_urb *urb = NULL; 192 + int rc = -ENOMEM; 193 + 194 + /* request cprb and payload */ 195 + req = alloc_ep11_cprb(sizeof(struct ep11_info_req_pl)); 196 + if (!req) 197 + goto out; 198 + req_pl = (struct ep11_info_req_pl *) (((u8 *) req) + sizeof(*req)); 199 + req_pl->tag = 0x30; 200 + req_pl->lenfmt = sizeof(*req_pl) - 2 * sizeof(u8); 201 + req_pl->func_tag = 0x04; 202 + req_pl->func_len = sizeof(u32); 203 + req_pl->func = 0x00010026; 204 + req_pl->dom_tag = 0x04; 205 + req_pl->dom_len = sizeof(u32); 206 + req_pl->query_type_tag = 0x04; 207 + req_pl->query_type_len = sizeof(u32); 208 + req_pl->query_type = query_type; 209 + req_pl->query_subtype_tag = 0x04; 210 + req_pl->query_subtype_len = sizeof(u32); 211 + 212 + /* reply cprb and payload */ 213 + rep = alloc_ep11_cprb(sizeof(struct ep11_info_rep_pl) + buflen); 214 + if (!rep) 215 + goto out; 216 + rep_pl = (struct ep11_info_rep_pl *) (((u8 *) rep) + sizeof(*rep)); 217 + 218 + /* urb and target */ 219 + urb = kmalloc(sizeof(struct ep11_urb), GFP_KERNEL); 220 + if (!urb) 221 + goto out; 222 + target.ap_id = cardnr; 223 + target.dom_id = domain; 224 + urb->targets_num = 1; 225 + urb->targets = (u8 __user *) &target; 226 + urb->req_len = sizeof(*req) + sizeof(*req_pl); 227 + urb->req = (u8 __user *) req; 228 + urb->resp_len = sizeof(*rep) + sizeof(*rep_pl) + buflen; 229 + urb->resp = (u8 __user *) rep; 230 + 231 + rc = _zcrypt_send_ep11_cprb(urb); 232 + if (rc) { 233 + DEBUG_ERR( 234 + "%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n", 235 + __func__, (int) cardnr, (int) domain, rc); 236 + goto out; 237 + } 238 + 239 + rc = -EIO; 240 + if (rep_pl->tag != 0x30 || rep_pl->func_tag != 0x04 || 241 + rep_pl->dom_tag != 0x04 || rep_pl->rc_tag != 0x04) { 242 + DEBUG_ERR("%s reply tag mismatch\n", __func__); 243 + goto out; 244 + } 245 + if (rep_pl->rc != 0) { 246 + DEBUG_ERR("%s reply cprb payload rc=0x%04x\n", 247 + __func__, rep_pl->rc); 248 + goto out; 249 + } 250 + if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != (0x80 + 2)) { 251 + DEBUG_ERR("%s unknown reply data format\n", __func__); 252 + goto out; 253 + } 254 + if (rep_pl->data_len > buflen) { 255 + DEBUG_ERR("%s mismatch between reply data len and buffer len\n", 256 + __func__); 257 + goto out; 258 + } 259 + 260 + rc = 0; 261 + memcpy(buf, ((u8 *) rep_pl) + sizeof(*req_pl), rep_pl->data_len); 262 + 263 + out: 264 + kfree(req); 265 + kfree(rep); 266 + kfree(urb); 267 + return rc; 268 + } 269 + 270 + /* 271 + * Provide information about an EP11 card. 272 + */ 273 + int ep11_get_card_info(u16 card, struct ep11_card_info *info, int verify) 274 + { 275 + int rc; 276 + struct ep11_module_query_info { 277 + u32 API_ord_nr; 278 + u32 firmware_id; 279 + u8 FW_major_vers; 280 + u8 FW_minor_vers; 281 + u8 CSP_major_vers; 282 + u8 CSP_minor_vers; 283 + u8 fwid[32]; 284 + u8 xcp_config_hash[32]; 285 + u8 CSP_config_hash[32]; 286 + u8 serial[16]; 287 + u8 module_date_time[16]; 288 + u64 op_mode; 289 + u32 PKCS11_flags; 290 + u32 ext_flags; 291 + u32 domains; 292 + u32 sym_state_bytes; 293 + u32 digest_state_bytes; 294 + u32 pin_blob_bytes; 295 + u32 SPKI_bytes; 296 + u32 priv_key_blob_bytes; 297 + u32 sym_blob_bytes; 298 + u32 max_payload_bytes; 299 + u32 CP_profile_bytes; 300 + u32 max_CP_index; 301 + } __packed * pmqi = NULL; 302 + 303 + rc = card_cache_fetch(card, info); 304 + if (rc || verify) { 305 + pmqi = kmalloc(sizeof(*pmqi), GFP_KERNEL); 306 + if (!pmqi) 307 + return -ENOMEM; 308 + rc = ep11_query_info(card, AUTOSEL_DOM, 309 + 0x01 /* module info query */, 310 + sizeof(*pmqi), (u8 *) pmqi); 311 + if (rc) { 312 + if (rc == -ENODEV) 313 + card_cache_scrub(card); 314 + goto out; 315 + } 316 + memset(info, 0, sizeof(*info)); 317 + info->API_ord_nr = pmqi->API_ord_nr; 318 + info->FW_version = 319 + (pmqi->FW_major_vers << 8) + pmqi->FW_minor_vers; 320 + memcpy(info->serial, pmqi->serial, sizeof(info->serial)); 321 + info->op_mode = pmqi->op_mode; 322 + card_cache_update(card, info); 323 + } 324 + 325 + out: 326 + kfree(pmqi); 327 + return rc; 328 + } 329 + EXPORT_SYMBOL(ep11_get_card_info); 330 + 331 + /* 332 + * Provide information about a domain within an EP11 card. 333 + */ 334 + int ep11_get_domain_info(u16 card, u16 domain, struct ep11_domain_info *info) 335 + { 336 + int rc; 337 + struct ep11_domain_query_info { 338 + u32 dom_index; 339 + u8 cur_WK_VP[32]; 340 + u8 new_WK_VP[32]; 341 + u32 dom_flags; 342 + u64 op_mode; 343 + } __packed * p_dom_info; 344 + 345 + p_dom_info = kmalloc(sizeof(*p_dom_info), GFP_KERNEL); 346 + if (!p_dom_info) 347 + return -ENOMEM; 348 + 349 + rc = ep11_query_info(card, domain, 0x03 /* domain info query */, 350 + sizeof(*p_dom_info), (u8 *) p_dom_info); 351 + if (rc) 352 + goto out; 353 + 354 + memset(info, 0, sizeof(*info)); 355 + info->cur_wk_state = '0'; 356 + info->new_wk_state = '0'; 357 + if (p_dom_info->dom_flags & 0x10 /* left imprint mode */) { 358 + if (p_dom_info->dom_flags & 0x02 /* cur wk valid */) { 359 + info->cur_wk_state = '1'; 360 + memcpy(info->cur_wkvp, p_dom_info->cur_WK_VP, 32); 361 + } 362 + if (p_dom_info->dom_flags & 0x04 /* new wk present */ 363 + || p_dom_info->dom_flags & 0x08 /* new wk committed */) { 364 + info->new_wk_state = 365 + p_dom_info->dom_flags & 0x08 ? '2' : '1'; 366 + memcpy(info->new_wkvp, p_dom_info->new_WK_VP, 32); 367 + } 368 + } 369 + info->op_mode = p_dom_info->op_mode; 370 + 371 + out: 372 + kfree(p_dom_info); 373 + return rc; 374 + } 375 + EXPORT_SYMBOL(ep11_get_domain_info); 376 + 377 + void __exit zcrypt_ep11misc_exit(void) 378 + { 379 + card_cache_free(); 380 + }
+44
drivers/s390/crypto/zcrypt_ep11misc.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + /* 3 + * Copyright IBM Corp. 2019 4 + * Author(s): Harald Freudenberger <freude@linux.ibm.com> 5 + * 6 + * Collection of EP11 misc functions used by zcrypt and pkey 7 + */ 8 + 9 + #ifndef _ZCRYPT_EP11MISC_H_ 10 + #define _ZCRYPT_EP11MISC_H_ 11 + 12 + #include <asm/zcrypt.h> 13 + #include <asm/pkey.h> 14 + 15 + /* EP11 card info struct */ 16 + struct ep11_card_info { 17 + u32 API_ord_nr; /* API ordinal number */ 18 + u16 FW_version; /* Firmware major and minor version */ 19 + char serial[16]; /* serial number string (16 ascii, no 0x00 !) */ 20 + u64 op_mode; /* card operational mode(s) */ 21 + }; 22 + 23 + /* EP11 domain info struct */ 24 + struct ep11_domain_info { 25 + char cur_wk_state; /* '0' invalid, '1' valid */ 26 + char new_wk_state; /* '0' empty, '1' uncommitted, '2' committed */ 27 + u8 cur_wkvp[32]; /* current wrapping key verification pattern */ 28 + u8 new_wkvp[32]; /* new wrapping key verification pattern */ 29 + u64 op_mode; /* domain operational mode(s) */ 30 + }; 31 + 32 + /* 33 + * Provide information about an EP11 card. 34 + */ 35 + int ep11_get_card_info(u16 card, struct ep11_card_info *info, int verify); 36 + 37 + /* 38 + * Provide information about a domain within an EP11 card. 39 + */ 40 + int ep11_get_domain_info(u16 card, u16 domain, struct ep11_domain_info *info); 41 + 42 + void zcrypt_ep11misc_exit(void); 43 + 44 + #endif /* _ZCRYPT_EP11MISC_H_ */