17384eb72SHarald Freudenberger // SPDX-License-Identifier: GPL-2.0+ 27384eb72SHarald Freudenberger /* 37384eb72SHarald Freudenberger * Copyright IBM Corp. 2019 47384eb72SHarald Freudenberger * Author(s): Harald Freudenberger <freude@linux.ibm.com> 57384eb72SHarald Freudenberger * 67384eb72SHarald Freudenberger * Collection of EP11 misc functions used by zcrypt and pkey 77384eb72SHarald Freudenberger */ 87384eb72SHarald Freudenberger 97384eb72SHarald Freudenberger #define KMSG_COMPONENT "zcrypt" 107384eb72SHarald Freudenberger #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 117384eb72SHarald Freudenberger 127384eb72SHarald Freudenberger #include <linux/init.h> 137384eb72SHarald Freudenberger #include <linux/module.h> 147384eb72SHarald Freudenberger #include <linux/slab.h> 157384eb72SHarald Freudenberger #include <linux/random.h> 167384eb72SHarald Freudenberger #include <asm/zcrypt.h> 177384eb72SHarald Freudenberger #include <asm/pkey.h> 18fa6999e3SHarald Freudenberger #include <crypto/aes.h> 197384eb72SHarald Freudenberger 207384eb72SHarald Freudenberger #include "ap_bus.h" 217384eb72SHarald Freudenberger #include "zcrypt_api.h" 227384eb72SHarald Freudenberger #include "zcrypt_debug.h" 237384eb72SHarald Freudenberger #include "zcrypt_msgtype6.h" 247384eb72SHarald Freudenberger #include "zcrypt_ep11misc.h" 2555d0a513SHarald Freudenberger #include "zcrypt_ccamisc.h" 267384eb72SHarald Freudenberger 27386cb81eSHolger Dengler #define EP11_PINBLOB_V1_BYTES 56 28386cb81eSHolger Dengler 2955d0a513SHarald Freudenberger /* default iv used here */ 3055d0a513SHarald Freudenberger static const u8 def_iv[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 3155d0a513SHarald Freudenberger 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; 3255d0a513SHarald Freudenberger 337384eb72SHarald Freudenberger /* ep11 card info cache */ 347384eb72SHarald Freudenberger struct card_list_entry { 357384eb72SHarald Freudenberger struct list_head list; 367384eb72SHarald Freudenberger u16 cardnr; 377384eb72SHarald Freudenberger struct ep11_card_info info; 387384eb72SHarald Freudenberger }; 397384eb72SHarald Freudenberger static LIST_HEAD(card_list); 407384eb72SHarald Freudenberger static DEFINE_SPINLOCK(card_list_lock); 417384eb72SHarald Freudenberger 427384eb72SHarald Freudenberger static int card_cache_fetch(u16 cardnr, struct ep11_card_info *ci) 437384eb72SHarald Freudenberger { 447384eb72SHarald Freudenberger int rc = -ENOENT; 457384eb72SHarald Freudenberger struct card_list_entry *ptr; 467384eb72SHarald Freudenberger 477384eb72SHarald Freudenberger spin_lock_bh(&card_list_lock); 487384eb72SHarald Freudenberger list_for_each_entry(ptr, &card_list, list) { 497384eb72SHarald Freudenberger if (ptr->cardnr == cardnr) { 507384eb72SHarald Freudenberger memcpy(ci, &ptr->info, sizeof(*ci)); 517384eb72SHarald Freudenberger rc = 0; 527384eb72SHarald Freudenberger break; 537384eb72SHarald Freudenberger } 547384eb72SHarald Freudenberger } 557384eb72SHarald Freudenberger spin_unlock_bh(&card_list_lock); 567384eb72SHarald Freudenberger 577384eb72SHarald Freudenberger return rc; 587384eb72SHarald Freudenberger } 597384eb72SHarald Freudenberger 607384eb72SHarald Freudenberger static void card_cache_update(u16 cardnr, const struct ep11_card_info *ci) 617384eb72SHarald Freudenberger { 627384eb72SHarald Freudenberger int found = 0; 637384eb72SHarald Freudenberger struct card_list_entry *ptr; 647384eb72SHarald Freudenberger 657384eb72SHarald Freudenberger spin_lock_bh(&card_list_lock); 667384eb72SHarald Freudenberger list_for_each_entry(ptr, &card_list, list) { 677384eb72SHarald Freudenberger if (ptr->cardnr == cardnr) { 687384eb72SHarald Freudenberger memcpy(&ptr->info, ci, sizeof(*ci)); 697384eb72SHarald Freudenberger found = 1; 707384eb72SHarald Freudenberger break; 717384eb72SHarald Freudenberger } 727384eb72SHarald Freudenberger } 737384eb72SHarald Freudenberger if (!found) { 747384eb72SHarald Freudenberger ptr = kmalloc(sizeof(*ptr), GFP_ATOMIC); 757384eb72SHarald Freudenberger if (!ptr) { 767384eb72SHarald Freudenberger spin_unlock_bh(&card_list_lock); 777384eb72SHarald Freudenberger return; 787384eb72SHarald Freudenberger } 797384eb72SHarald Freudenberger ptr->cardnr = cardnr; 807384eb72SHarald Freudenberger memcpy(&ptr->info, ci, sizeof(*ci)); 817384eb72SHarald Freudenberger list_add(&ptr->list, &card_list); 827384eb72SHarald Freudenberger } 837384eb72SHarald Freudenberger spin_unlock_bh(&card_list_lock); 847384eb72SHarald Freudenberger } 857384eb72SHarald Freudenberger 867384eb72SHarald Freudenberger static void card_cache_scrub(u16 cardnr) 877384eb72SHarald Freudenberger { 887384eb72SHarald Freudenberger struct card_list_entry *ptr; 897384eb72SHarald Freudenberger 907384eb72SHarald Freudenberger spin_lock_bh(&card_list_lock); 917384eb72SHarald Freudenberger list_for_each_entry(ptr, &card_list, list) { 927384eb72SHarald Freudenberger if (ptr->cardnr == cardnr) { 937384eb72SHarald Freudenberger list_del(&ptr->list); 947384eb72SHarald Freudenberger kfree(ptr); 957384eb72SHarald Freudenberger break; 967384eb72SHarald Freudenberger } 977384eb72SHarald Freudenberger } 987384eb72SHarald Freudenberger spin_unlock_bh(&card_list_lock); 997384eb72SHarald Freudenberger } 1007384eb72SHarald Freudenberger 1017384eb72SHarald Freudenberger static void __exit card_cache_free(void) 1027384eb72SHarald Freudenberger { 1037384eb72SHarald Freudenberger struct card_list_entry *ptr, *pnext; 1047384eb72SHarald Freudenberger 1057384eb72SHarald Freudenberger spin_lock_bh(&card_list_lock); 1067384eb72SHarald Freudenberger list_for_each_entry_safe(ptr, pnext, &card_list, list) { 1077384eb72SHarald Freudenberger list_del(&ptr->list); 1087384eb72SHarald Freudenberger kfree(ptr); 1097384eb72SHarald Freudenberger } 1107384eb72SHarald Freudenberger spin_unlock_bh(&card_list_lock); 1117384eb72SHarald Freudenberger } 1127384eb72SHarald Freudenberger 113fb249ce7SHolger Dengler static int ep11_kb_split(const u8 *kb, size_t kblen, u32 kbver, 114fb249ce7SHolger Dengler struct ep11kblob_header **kbhdr, size_t *kbhdrsize, 115fb249ce7SHolger Dengler u8 **kbpl, size_t *kbplsize) 116fb249ce7SHolger Dengler { 117fb249ce7SHolger Dengler struct ep11kblob_header *hdr = NULL; 118fb249ce7SHolger Dengler size_t hdrsize, plsize = 0; 119fb249ce7SHolger Dengler int rc = -EINVAL; 120fb249ce7SHolger Dengler u8 *pl = NULL; 121fb249ce7SHolger Dengler 122fb249ce7SHolger Dengler if (kblen < sizeof(struct ep11kblob_header)) 123fb249ce7SHolger Dengler goto out; 124fb249ce7SHolger Dengler hdr = (struct ep11kblob_header *)kb; 125fb249ce7SHolger Dengler 126fb249ce7SHolger Dengler switch (kbver) { 127fb249ce7SHolger Dengler case TOKVER_EP11_AES: 128fb249ce7SHolger Dengler /* header overlays the payload */ 129fb249ce7SHolger Dengler hdrsize = 0; 130fb249ce7SHolger Dengler break; 131fb249ce7SHolger Dengler case TOKVER_EP11_ECC_WITH_HEADER: 132fb249ce7SHolger Dengler case TOKVER_EP11_AES_WITH_HEADER: 133fb249ce7SHolger Dengler /* payload starts after the header */ 134fb249ce7SHolger Dengler hdrsize = sizeof(struct ep11kblob_header); 135fb249ce7SHolger Dengler break; 136fb249ce7SHolger Dengler default: 137fb249ce7SHolger Dengler goto out; 138fb249ce7SHolger Dengler } 139fb249ce7SHolger Dengler 140fb249ce7SHolger Dengler plsize = kblen - hdrsize; 141fb249ce7SHolger Dengler pl = (u8 *)kb + hdrsize; 142fb249ce7SHolger Dengler 143fb249ce7SHolger Dengler if (kbhdr) 144fb249ce7SHolger Dengler *kbhdr = hdr; 145fb249ce7SHolger Dengler if (kbhdrsize) 146fb249ce7SHolger Dengler *kbhdrsize = hdrsize; 147fb249ce7SHolger Dengler if (kbpl) 148fb249ce7SHolger Dengler *kbpl = pl; 149fb249ce7SHolger Dengler if (kbplsize) 150fb249ce7SHolger Dengler *kbplsize = plsize; 151fb249ce7SHolger Dengler 152fb249ce7SHolger Dengler rc = 0; 153fb249ce7SHolger Dengler out: 154fb249ce7SHolger Dengler return rc; 155fb249ce7SHolger Dengler } 156fb249ce7SHolger Dengler 157d1fdfb0bSHolger Dengler static int ep11_kb_decode(const u8 *kb, size_t kblen, 158d1fdfb0bSHolger Dengler struct ep11kblob_header **kbhdr, size_t *kbhdrsize, 159d1fdfb0bSHolger Dengler struct ep11keyblob **kbpl, size_t *kbplsize) 160d1fdfb0bSHolger Dengler { 161d1fdfb0bSHolger Dengler struct ep11kblob_header *tmph, *hdr = NULL; 162d1fdfb0bSHolger Dengler size_t hdrsize = 0, plsize = 0; 163d1fdfb0bSHolger Dengler struct ep11keyblob *pl = NULL; 164d1fdfb0bSHolger Dengler int rc = -EINVAL; 165d1fdfb0bSHolger Dengler u8 *tmpp; 166d1fdfb0bSHolger Dengler 167d1fdfb0bSHolger Dengler if (kblen < sizeof(struct ep11kblob_header)) 168d1fdfb0bSHolger Dengler goto out; 169d1fdfb0bSHolger Dengler tmph = (struct ep11kblob_header *)kb; 170d1fdfb0bSHolger Dengler 171d1fdfb0bSHolger Dengler if (tmph->type != TOKTYPE_NON_CCA && 172d1fdfb0bSHolger Dengler tmph->len > kblen) 173d1fdfb0bSHolger Dengler goto out; 174d1fdfb0bSHolger Dengler 175d1fdfb0bSHolger Dengler if (ep11_kb_split(kb, kblen, tmph->version, 176d1fdfb0bSHolger Dengler &hdr, &hdrsize, &tmpp, &plsize)) 177d1fdfb0bSHolger Dengler goto out; 178d1fdfb0bSHolger Dengler 179d1fdfb0bSHolger Dengler if (plsize < sizeof(struct ep11keyblob)) 180d1fdfb0bSHolger Dengler goto out; 181d1fdfb0bSHolger Dengler 182d1fdfb0bSHolger Dengler if (!is_ep11_keyblob(tmpp)) 183d1fdfb0bSHolger Dengler goto out; 184d1fdfb0bSHolger Dengler 185d1fdfb0bSHolger Dengler pl = (struct ep11keyblob *)tmpp; 186d1fdfb0bSHolger Dengler plsize = hdr->len - hdrsize; 187d1fdfb0bSHolger Dengler 188d1fdfb0bSHolger Dengler if (kbhdr) 189d1fdfb0bSHolger Dengler *kbhdr = hdr; 190d1fdfb0bSHolger Dengler if (kbhdrsize) 191d1fdfb0bSHolger Dengler *kbhdrsize = hdrsize; 192d1fdfb0bSHolger Dengler if (kbpl) 193d1fdfb0bSHolger Dengler *kbpl = pl; 194d1fdfb0bSHolger Dengler if (kbplsize) 195d1fdfb0bSHolger Dengler *kbplsize = plsize; 196d1fdfb0bSHolger Dengler 197d1fdfb0bSHolger Dengler rc = 0; 198d1fdfb0bSHolger Dengler out: 199d1fdfb0bSHolger Dengler return rc; 200d1fdfb0bSHolger Dengler } 201d1fdfb0bSHolger Dengler 202d1fdfb0bSHolger Dengler /* 203d1fdfb0bSHolger Dengler * For valid ep11 keyblobs, returns a reference to the wrappingkey verification 204d1fdfb0bSHolger Dengler * pattern. Otherwise NULL. 205d1fdfb0bSHolger Dengler */ 206d1fdfb0bSHolger Dengler const u8 *ep11_kb_wkvp(const u8 *keyblob, size_t keybloblen) 207d1fdfb0bSHolger Dengler { 208d1fdfb0bSHolger Dengler struct ep11keyblob *kb; 209d1fdfb0bSHolger Dengler 210d1fdfb0bSHolger Dengler if (ep11_kb_decode(keyblob, keybloblen, NULL, NULL, &kb, NULL)) 211d1fdfb0bSHolger Dengler return NULL; 212d1fdfb0bSHolger Dengler return kb->wkvp; 213d1fdfb0bSHolger Dengler } 214d1fdfb0bSHolger Dengler EXPORT_SYMBOL(ep11_kb_wkvp); 215d1fdfb0bSHolger Dengler 2167384eb72SHarald Freudenberger /* 217fa6999e3SHarald Freudenberger * Simple check if the key blob is a valid EP11 AES key blob with header. 21855d0a513SHarald Freudenberger */ 219fa6999e3SHarald Freudenberger int ep11_check_aes_key_with_hdr(debug_info_t *dbg, int dbflvl, 220fa6999e3SHarald Freudenberger const u8 *key, size_t keylen, int checkcpacfexp) 221fa6999e3SHarald Freudenberger { 222fa6999e3SHarald Freudenberger struct ep11kblob_header *hdr = (struct ep11kblob_header *)key; 223fa6999e3SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)(key + sizeof(*hdr)); 224fa6999e3SHarald Freudenberger 225fa6999e3SHarald Freudenberger #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__) 226fa6999e3SHarald Freudenberger 227fa6999e3SHarald Freudenberger if (keylen < sizeof(*hdr) + sizeof(*kb)) { 228fa6999e3SHarald Freudenberger DBF("%s key check failed, keylen %zu < %zu\n", 229fa6999e3SHarald Freudenberger __func__, keylen, sizeof(*hdr) + sizeof(*kb)); 230fa6999e3SHarald Freudenberger return -EINVAL; 231fa6999e3SHarald Freudenberger } 232fa6999e3SHarald Freudenberger 233fa6999e3SHarald Freudenberger if (hdr->type != TOKTYPE_NON_CCA) { 234fa6999e3SHarald Freudenberger if (dbg) 235fa6999e3SHarald Freudenberger DBF("%s key check failed, type 0x%02x != 0x%02x\n", 236fa6999e3SHarald Freudenberger __func__, (int)hdr->type, TOKTYPE_NON_CCA); 237fa6999e3SHarald Freudenberger return -EINVAL; 238fa6999e3SHarald Freudenberger } 239fa6999e3SHarald Freudenberger if (hdr->hver != 0x00) { 240fa6999e3SHarald Freudenberger if (dbg) 241fa6999e3SHarald Freudenberger DBF("%s key check failed, header version 0x%02x != 0x00\n", 242fa6999e3SHarald Freudenberger __func__, (int)hdr->hver); 243fa6999e3SHarald Freudenberger return -EINVAL; 244fa6999e3SHarald Freudenberger } 245fa6999e3SHarald Freudenberger if (hdr->version != TOKVER_EP11_AES_WITH_HEADER) { 246fa6999e3SHarald Freudenberger if (dbg) 247fa6999e3SHarald Freudenberger DBF("%s key check failed, version 0x%02x != 0x%02x\n", 248fa6999e3SHarald Freudenberger __func__, (int)hdr->version, TOKVER_EP11_AES_WITH_HEADER); 249fa6999e3SHarald Freudenberger return -EINVAL; 250fa6999e3SHarald Freudenberger } 251fa6999e3SHarald Freudenberger if (hdr->len > keylen) { 252fa6999e3SHarald Freudenberger if (dbg) 253fa6999e3SHarald Freudenberger DBF("%s key check failed, header len %d keylen %zu mismatch\n", 254fa6999e3SHarald Freudenberger __func__, (int)hdr->len, keylen); 255fa6999e3SHarald Freudenberger return -EINVAL; 256fa6999e3SHarald Freudenberger } 257fa6999e3SHarald Freudenberger if (hdr->len < sizeof(*hdr) + sizeof(*kb)) { 258fa6999e3SHarald Freudenberger if (dbg) 259fa6999e3SHarald Freudenberger DBF("%s key check failed, header len %d < %zu\n", 260fa6999e3SHarald Freudenberger __func__, (int)hdr->len, sizeof(*hdr) + sizeof(*kb)); 261fa6999e3SHarald Freudenberger return -EINVAL; 262fa6999e3SHarald Freudenberger } 263fa6999e3SHarald Freudenberger 264fa6999e3SHarald Freudenberger if (kb->version != EP11_STRUCT_MAGIC) { 265fa6999e3SHarald Freudenberger if (dbg) 266fa6999e3SHarald Freudenberger DBF("%s key check failed, blob magic 0x%04x != 0x%04x\n", 267fa6999e3SHarald Freudenberger __func__, (int)kb->version, EP11_STRUCT_MAGIC); 268fa6999e3SHarald Freudenberger return -EINVAL; 269fa6999e3SHarald Freudenberger } 270fa6999e3SHarald Freudenberger if (checkcpacfexp && !(kb->attr & EP11_BLOB_PKEY_EXTRACTABLE)) { 271fa6999e3SHarald Freudenberger if (dbg) 272fa6999e3SHarald Freudenberger DBF("%s key check failed, PKEY_EXTRACTABLE is off\n", 273fa6999e3SHarald Freudenberger __func__); 274fa6999e3SHarald Freudenberger return -EINVAL; 275fa6999e3SHarald Freudenberger } 276fa6999e3SHarald Freudenberger 277fa6999e3SHarald Freudenberger #undef DBF 278fa6999e3SHarald Freudenberger 279fa6999e3SHarald Freudenberger return 0; 280fa6999e3SHarald Freudenberger } 281fa6999e3SHarald Freudenberger EXPORT_SYMBOL(ep11_check_aes_key_with_hdr); 282fa6999e3SHarald Freudenberger 283fa6999e3SHarald Freudenberger /* 284fa6999e3SHarald Freudenberger * Simple check if the key blob is a valid EP11 ECC key blob with header. 285fa6999e3SHarald Freudenberger */ 286fa6999e3SHarald Freudenberger int ep11_check_ecc_key_with_hdr(debug_info_t *dbg, int dbflvl, 287fa6999e3SHarald Freudenberger const u8 *key, size_t keylen, int checkcpacfexp) 288fa6999e3SHarald Freudenberger { 289fa6999e3SHarald Freudenberger struct ep11kblob_header *hdr = (struct ep11kblob_header *)key; 290fa6999e3SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)(key + sizeof(*hdr)); 291fa6999e3SHarald Freudenberger 292fa6999e3SHarald Freudenberger #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__) 293fa6999e3SHarald Freudenberger 294fa6999e3SHarald Freudenberger if (keylen < sizeof(*hdr) + sizeof(*kb)) { 295fa6999e3SHarald Freudenberger DBF("%s key check failed, keylen %zu < %zu\n", 296fa6999e3SHarald Freudenberger __func__, keylen, sizeof(*hdr) + sizeof(*kb)); 297fa6999e3SHarald Freudenberger return -EINVAL; 298fa6999e3SHarald Freudenberger } 299fa6999e3SHarald Freudenberger 300fa6999e3SHarald Freudenberger if (hdr->type != TOKTYPE_NON_CCA) { 301fa6999e3SHarald Freudenberger if (dbg) 302fa6999e3SHarald Freudenberger DBF("%s key check failed, type 0x%02x != 0x%02x\n", 303fa6999e3SHarald Freudenberger __func__, (int)hdr->type, TOKTYPE_NON_CCA); 304fa6999e3SHarald Freudenberger return -EINVAL; 305fa6999e3SHarald Freudenberger } 306fa6999e3SHarald Freudenberger if (hdr->hver != 0x00) { 307fa6999e3SHarald Freudenberger if (dbg) 308fa6999e3SHarald Freudenberger DBF("%s key check failed, header version 0x%02x != 0x00\n", 309fa6999e3SHarald Freudenberger __func__, (int)hdr->hver); 310fa6999e3SHarald Freudenberger return -EINVAL; 311fa6999e3SHarald Freudenberger } 312fa6999e3SHarald Freudenberger if (hdr->version != TOKVER_EP11_ECC_WITH_HEADER) { 313fa6999e3SHarald Freudenberger if (dbg) 314fa6999e3SHarald Freudenberger DBF("%s key check failed, version 0x%02x != 0x%02x\n", 315fa6999e3SHarald Freudenberger __func__, (int)hdr->version, TOKVER_EP11_ECC_WITH_HEADER); 316fa6999e3SHarald Freudenberger return -EINVAL; 317fa6999e3SHarald Freudenberger } 318fa6999e3SHarald Freudenberger if (hdr->len > keylen) { 319fa6999e3SHarald Freudenberger if (dbg) 320fa6999e3SHarald Freudenberger DBF("%s key check failed, header len %d keylen %zu mismatch\n", 321fa6999e3SHarald Freudenberger __func__, (int)hdr->len, keylen); 322fa6999e3SHarald Freudenberger return -EINVAL; 323fa6999e3SHarald Freudenberger } 324fa6999e3SHarald Freudenberger if (hdr->len < sizeof(*hdr) + sizeof(*kb)) { 325fa6999e3SHarald Freudenberger if (dbg) 326fa6999e3SHarald Freudenberger DBF("%s key check failed, header len %d < %zu\n", 327fa6999e3SHarald Freudenberger __func__, (int)hdr->len, sizeof(*hdr) + sizeof(*kb)); 328fa6999e3SHarald Freudenberger return -EINVAL; 329fa6999e3SHarald Freudenberger } 330fa6999e3SHarald Freudenberger 331fa6999e3SHarald Freudenberger if (kb->version != EP11_STRUCT_MAGIC) { 332fa6999e3SHarald Freudenberger if (dbg) 333fa6999e3SHarald Freudenberger DBF("%s key check failed, blob magic 0x%04x != 0x%04x\n", 334fa6999e3SHarald Freudenberger __func__, (int)kb->version, EP11_STRUCT_MAGIC); 335fa6999e3SHarald Freudenberger return -EINVAL; 336fa6999e3SHarald Freudenberger } 337fa6999e3SHarald Freudenberger if (checkcpacfexp && !(kb->attr & EP11_BLOB_PKEY_EXTRACTABLE)) { 338fa6999e3SHarald Freudenberger if (dbg) 339fa6999e3SHarald Freudenberger DBF("%s key check failed, PKEY_EXTRACTABLE is off\n", 340fa6999e3SHarald Freudenberger __func__); 341fa6999e3SHarald Freudenberger return -EINVAL; 342fa6999e3SHarald Freudenberger } 343fa6999e3SHarald Freudenberger 344fa6999e3SHarald Freudenberger #undef DBF 345fa6999e3SHarald Freudenberger 346fa6999e3SHarald Freudenberger return 0; 347fa6999e3SHarald Freudenberger } 348fa6999e3SHarald Freudenberger EXPORT_SYMBOL(ep11_check_ecc_key_with_hdr); 349fa6999e3SHarald Freudenberger 350fa6999e3SHarald Freudenberger /* 351fa6999e3SHarald Freudenberger * Simple check if the key blob is a valid EP11 AES key blob with 352fa6999e3SHarald Freudenberger * the header in the session field (old style EP11 AES key). 353fa6999e3SHarald Freudenberger */ 354fa6999e3SHarald Freudenberger int ep11_check_aes_key(debug_info_t *dbg, int dbflvl, 355fa6999e3SHarald Freudenberger const u8 *key, size_t keylen, int checkcpacfexp) 35655d0a513SHarald Freudenberger { 35755d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 35855d0a513SHarald Freudenberger 35955d0a513SHarald Freudenberger #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__) 36055d0a513SHarald Freudenberger 361fa6999e3SHarald Freudenberger if (keylen < sizeof(*kb)) { 362fa6999e3SHarald Freudenberger DBF("%s key check failed, keylen %zu < %zu\n", 363fa6999e3SHarald Freudenberger __func__, keylen, sizeof(*kb)); 364fa6999e3SHarald Freudenberger return -EINVAL; 365fa6999e3SHarald Freudenberger } 366fa6999e3SHarald Freudenberger 36755d0a513SHarald Freudenberger if (kb->head.type != TOKTYPE_NON_CCA) { 36855d0a513SHarald Freudenberger if (dbg) 36955d0a513SHarald Freudenberger DBF("%s key check failed, type 0x%02x != 0x%02x\n", 37055d0a513SHarald Freudenberger __func__, (int)kb->head.type, TOKTYPE_NON_CCA); 37155d0a513SHarald Freudenberger return -EINVAL; 37255d0a513SHarald Freudenberger } 37355d0a513SHarald Freudenberger if (kb->head.version != TOKVER_EP11_AES) { 37455d0a513SHarald Freudenberger if (dbg) 37555d0a513SHarald Freudenberger DBF("%s key check failed, version 0x%02x != 0x%02x\n", 37655d0a513SHarald Freudenberger __func__, (int)kb->head.version, TOKVER_EP11_AES); 37755d0a513SHarald Freudenberger return -EINVAL; 37855d0a513SHarald Freudenberger } 379fa6999e3SHarald Freudenberger if (kb->head.len > keylen) { 380fa6999e3SHarald Freudenberger if (dbg) 381fa6999e3SHarald Freudenberger DBF("%s key check failed, header len %d keylen %zu mismatch\n", 382fa6999e3SHarald Freudenberger __func__, (int)kb->head.len, keylen); 383fa6999e3SHarald Freudenberger return -EINVAL; 384fa6999e3SHarald Freudenberger } 385fa6999e3SHarald Freudenberger if (kb->head.len < sizeof(*kb)) { 386fa6999e3SHarald Freudenberger if (dbg) 387fa6999e3SHarald Freudenberger DBF("%s key check failed, header len %d < %zu\n", 388fa6999e3SHarald Freudenberger __func__, (int)kb->head.len, sizeof(*kb)); 389fa6999e3SHarald Freudenberger return -EINVAL; 390fa6999e3SHarald Freudenberger } 391fa6999e3SHarald Freudenberger 39255d0a513SHarald Freudenberger if (kb->version != EP11_STRUCT_MAGIC) { 39355d0a513SHarald Freudenberger if (dbg) 394fa6999e3SHarald Freudenberger DBF("%s key check failed, blob magic 0x%04x != 0x%04x\n", 39555d0a513SHarald Freudenberger __func__, (int)kb->version, EP11_STRUCT_MAGIC); 39655d0a513SHarald Freudenberger return -EINVAL; 39755d0a513SHarald Freudenberger } 398fa6999e3SHarald Freudenberger if (checkcpacfexp && !(kb->attr & EP11_BLOB_PKEY_EXTRACTABLE)) { 39955d0a513SHarald Freudenberger if (dbg) 400fa6999e3SHarald Freudenberger DBF("%s key check failed, PKEY_EXTRACTABLE is off\n", 40155d0a513SHarald Freudenberger __func__); 40255d0a513SHarald Freudenberger return -EINVAL; 40355d0a513SHarald Freudenberger } 404fa6999e3SHarald Freudenberger 40555d0a513SHarald Freudenberger #undef DBF 40655d0a513SHarald Freudenberger 40755d0a513SHarald Freudenberger return 0; 40855d0a513SHarald Freudenberger } 409fa6999e3SHarald Freudenberger EXPORT_SYMBOL(ep11_check_aes_key); 41055d0a513SHarald Freudenberger 41155d0a513SHarald Freudenberger /* 4127384eb72SHarald Freudenberger * Allocate and prepare ep11 cprb plus additional payload. 4137384eb72SHarald Freudenberger */ 41455d0a513SHarald Freudenberger static inline struct ep11_cprb *alloc_cprb(size_t payload_len) 4157384eb72SHarald Freudenberger { 4167384eb72SHarald Freudenberger size_t len = sizeof(struct ep11_cprb) + payload_len; 4177384eb72SHarald Freudenberger struct ep11_cprb *cprb; 4187384eb72SHarald Freudenberger 41979d6c502SZou Wei cprb = kzalloc(len, GFP_KERNEL); 4207384eb72SHarald Freudenberger if (!cprb) 4217384eb72SHarald Freudenberger return NULL; 4227384eb72SHarald Freudenberger 4237384eb72SHarald Freudenberger cprb->cprb_len = sizeof(struct ep11_cprb); 4247384eb72SHarald Freudenberger cprb->cprb_ver_id = 0x04; 4257384eb72SHarald Freudenberger memcpy(cprb->func_id, "T4", 2); 4267384eb72SHarald Freudenberger cprb->ret_code = 0xFFFFFFFF; 4277384eb72SHarald Freudenberger cprb->payload_len = payload_len; 4287384eb72SHarald Freudenberger 4297384eb72SHarald Freudenberger return cprb; 4307384eb72SHarald Freudenberger } 4317384eb72SHarald Freudenberger 4327384eb72SHarald Freudenberger /* 43355d0a513SHarald Freudenberger * Some helper functions related to ASN1 encoding. 43455d0a513SHarald Freudenberger * Limited to length info <= 2 byte. 4357384eb72SHarald Freudenberger */ 43655d0a513SHarald Freudenberger 43755d0a513SHarald Freudenberger #define ASN1TAGLEN(x) (2 + (x) + ((x) > 127 ? 1 : 0) + ((x) > 255 ? 1 : 0)) 43855d0a513SHarald Freudenberger 43955d0a513SHarald Freudenberger static int asn1tag_write(u8 *ptr, u8 tag, const u8 *pvalue, u16 valuelen) 4407384eb72SHarald Freudenberger { 44155d0a513SHarald Freudenberger ptr[0] = tag; 44255d0a513SHarald Freudenberger if (valuelen > 255) { 44355d0a513SHarald Freudenberger ptr[1] = 0x82; 44455d0a513SHarald Freudenberger *((u16 *)(ptr + 2)) = valuelen; 44555d0a513SHarald Freudenberger memcpy(ptr + 4, pvalue, valuelen); 44655d0a513SHarald Freudenberger return 4 + valuelen; 44755d0a513SHarald Freudenberger } 44855d0a513SHarald Freudenberger if (valuelen > 127) { 44955d0a513SHarald Freudenberger ptr[1] = 0x81; 45055d0a513SHarald Freudenberger ptr[2] = (u8)valuelen; 45155d0a513SHarald Freudenberger memcpy(ptr + 3, pvalue, valuelen); 45255d0a513SHarald Freudenberger return 3 + valuelen; 45355d0a513SHarald Freudenberger } 45455d0a513SHarald Freudenberger ptr[1] = (u8)valuelen; 45555d0a513SHarald Freudenberger memcpy(ptr + 2, pvalue, valuelen); 45655d0a513SHarald Freudenberger return 2 + valuelen; 45755d0a513SHarald Freudenberger } 45855d0a513SHarald Freudenberger 45955d0a513SHarald Freudenberger /* EP11 payload > 127 bytes starts with this struct */ 46055d0a513SHarald Freudenberger struct pl_head { 4617384eb72SHarald Freudenberger u8 tag; 4627384eb72SHarald Freudenberger u8 lenfmt; 4637384eb72SHarald Freudenberger u16 len; 4647384eb72SHarald Freudenberger u8 func_tag; 4657384eb72SHarald Freudenberger u8 func_len; 4667384eb72SHarald Freudenberger u32 func; 4677384eb72SHarald Freudenberger u8 dom_tag; 4687384eb72SHarald Freudenberger u8 dom_len; 4697384eb72SHarald Freudenberger u32 dom; 47055d0a513SHarald Freudenberger } __packed; 47155d0a513SHarald Freudenberger 47255d0a513SHarald Freudenberger /* prep ep11 payload head helper function */ 47355d0a513SHarald Freudenberger static inline void prep_head(struct pl_head *h, 47455d0a513SHarald Freudenberger size_t pl_size, int api, int func) 47555d0a513SHarald Freudenberger { 47655d0a513SHarald Freudenberger h->tag = 0x30; 47755d0a513SHarald Freudenberger h->lenfmt = 0x82; 47855d0a513SHarald Freudenberger h->len = pl_size - 4; 47955d0a513SHarald Freudenberger h->func_tag = 0x04; 48055d0a513SHarald Freudenberger h->func_len = sizeof(u32); 48155d0a513SHarald Freudenberger h->func = (api << 16) + func; 48255d0a513SHarald Freudenberger h->dom_tag = 0x04; 48355d0a513SHarald Freudenberger h->dom_len = sizeof(u32); 48455d0a513SHarald Freudenberger } 48555d0a513SHarald Freudenberger 48655d0a513SHarald Freudenberger /* prep urb helper function */ 48755d0a513SHarald Freudenberger static inline void prep_urb(struct ep11_urb *u, 48855d0a513SHarald Freudenberger struct ep11_target_dev *t, int nt, 48955d0a513SHarald Freudenberger struct ep11_cprb *req, size_t req_len, 49055d0a513SHarald Freudenberger struct ep11_cprb *rep, size_t rep_len) 49155d0a513SHarald Freudenberger { 49255d0a513SHarald Freudenberger u->targets = (u8 __user *)t; 49355d0a513SHarald Freudenberger u->targets_num = nt; 49455d0a513SHarald Freudenberger u->req = (u8 __user *)req; 49555d0a513SHarald Freudenberger u->req_len = req_len; 49655d0a513SHarald Freudenberger u->resp = (u8 __user *)rep; 49755d0a513SHarald Freudenberger u->resp_len = rep_len; 49855d0a513SHarald Freudenberger } 49955d0a513SHarald Freudenberger 50055d0a513SHarald Freudenberger /* Check ep11 reply payload, return 0 or suggested errno value. */ 50155d0a513SHarald Freudenberger static int check_reply_pl(const u8 *pl, const char *func) 50255d0a513SHarald Freudenberger { 50355d0a513SHarald Freudenberger int len; 50455d0a513SHarald Freudenberger u32 ret; 50555d0a513SHarald Freudenberger 50655d0a513SHarald Freudenberger /* start tag */ 50755d0a513SHarald Freudenberger if (*pl++ != 0x30) { 50888e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s reply start tag mismatch\n", func); 50955d0a513SHarald Freudenberger return -EIO; 51055d0a513SHarald Freudenberger } 51155d0a513SHarald Freudenberger 51255d0a513SHarald Freudenberger /* payload length format */ 51355d0a513SHarald Freudenberger if (*pl < 127) { 51455d0a513SHarald Freudenberger len = *pl; 51555d0a513SHarald Freudenberger pl++; 51655d0a513SHarald Freudenberger } else if (*pl == 0x81) { 51755d0a513SHarald Freudenberger pl++; 51855d0a513SHarald Freudenberger len = *pl; 51955d0a513SHarald Freudenberger pl++; 52055d0a513SHarald Freudenberger } else if (*pl == 0x82) { 52155d0a513SHarald Freudenberger pl++; 52255d0a513SHarald Freudenberger len = *((u16 *)pl); 52355d0a513SHarald Freudenberger pl += 2; 52455d0a513SHarald Freudenberger } else { 52588e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s reply start tag lenfmt mismatch 0x%02hhx\n", 52655d0a513SHarald Freudenberger func, *pl); 52755d0a513SHarald Freudenberger return -EIO; 52855d0a513SHarald Freudenberger } 52955d0a513SHarald Freudenberger 53055d0a513SHarald Freudenberger /* len should cover at least 3 fields with 32 bit value each */ 53155d0a513SHarald Freudenberger if (len < 3 * 6) { 53288e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s reply length %d too small\n", func, len); 53355d0a513SHarald Freudenberger return -EIO; 53455d0a513SHarald Freudenberger } 53555d0a513SHarald Freudenberger 53655d0a513SHarald Freudenberger /* function tag, length and value */ 53755d0a513SHarald Freudenberger if (pl[0] != 0x04 || pl[1] != 0x04) { 53888e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s function tag or length mismatch\n", func); 53955d0a513SHarald Freudenberger return -EIO; 54055d0a513SHarald Freudenberger } 54155d0a513SHarald Freudenberger pl += 6; 54255d0a513SHarald Freudenberger 54355d0a513SHarald Freudenberger /* dom tag, length and value */ 54455d0a513SHarald Freudenberger if (pl[0] != 0x04 || pl[1] != 0x04) { 54588e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s dom tag or length mismatch\n", func); 54655d0a513SHarald Freudenberger return -EIO; 54755d0a513SHarald Freudenberger } 54855d0a513SHarald Freudenberger pl += 6; 54955d0a513SHarald Freudenberger 55055d0a513SHarald Freudenberger /* return value tag, length and value */ 55155d0a513SHarald Freudenberger if (pl[0] != 0x04 || pl[1] != 0x04) { 55288e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s return value tag or length mismatch\n", 55388e4c0daSHarald Freudenberger func); 55455d0a513SHarald Freudenberger return -EIO; 55555d0a513SHarald Freudenberger } 55655d0a513SHarald Freudenberger pl += 2; 55755d0a513SHarald Freudenberger ret = *((u32 *)pl); 55855d0a513SHarald Freudenberger if (ret != 0) { 559a4499998SHarald Freudenberger ZCRYPT_DBF_ERR("%s return value 0x%08x != 0\n", func, ret); 56055d0a513SHarald Freudenberger return -EIO; 56155d0a513SHarald Freudenberger } 56255d0a513SHarald Freudenberger 56355d0a513SHarald Freudenberger return 0; 56455d0a513SHarald Freudenberger } 56555d0a513SHarald Freudenberger 566c0e983b6SHarald Freudenberger /* Check ep11 reply cprb, return 0 or suggested errno value. */ 567c0e983b6SHarald Freudenberger static int check_reply_cprb(const struct ep11_cprb *rep, const char *func) 568c0e983b6SHarald Freudenberger { 569c0e983b6SHarald Freudenberger /* check ep11 reply return code field */ 570c0e983b6SHarald Freudenberger if (rep->ret_code) { 571c0e983b6SHarald Freudenberger ZCRYPT_DBF_ERR("%s ep11 reply ret_code=0x%08x\n", __func__, 572c0e983b6SHarald Freudenberger rep->ret_code); 573c0e983b6SHarald Freudenberger if (rep->ret_code == 0x000c0003) 574c0e983b6SHarald Freudenberger return -EBUSY; 575c0e983b6SHarald Freudenberger else 576c0e983b6SHarald Freudenberger return -EIO; 577c0e983b6SHarald Freudenberger } 578c0e983b6SHarald Freudenberger 579c0e983b6SHarald Freudenberger return 0; 580c0e983b6SHarald Freudenberger } 581c0e983b6SHarald Freudenberger 58255d0a513SHarald Freudenberger /* 58355d0a513SHarald Freudenberger * Helper function which does an ep11 query with given query type. 58455d0a513SHarald Freudenberger */ 58555d0a513SHarald Freudenberger static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type, 58655d0a513SHarald Freudenberger size_t buflen, u8 *buf) 58755d0a513SHarald Freudenberger { 58855d0a513SHarald Freudenberger struct ep11_info_req_pl { 58955d0a513SHarald Freudenberger struct pl_head head; 59055d0a513SHarald Freudenberger u8 query_type_tag; 59155d0a513SHarald Freudenberger u8 query_type_len; 59255d0a513SHarald Freudenberger u32 query_type; 59355d0a513SHarald Freudenberger u8 query_subtype_tag; 59455d0a513SHarald Freudenberger u8 query_subtype_len; 59555d0a513SHarald Freudenberger u32 query_subtype; 59655d0a513SHarald Freudenberger } __packed * req_pl; 59755d0a513SHarald Freudenberger struct ep11_info_rep_pl { 59855d0a513SHarald Freudenberger struct pl_head head; 5997384eb72SHarald Freudenberger u8 rc_tag; 6007384eb72SHarald Freudenberger u8 rc_len; 6017384eb72SHarald Freudenberger u32 rc; 6027384eb72SHarald Freudenberger u8 data_tag; 6037384eb72SHarald Freudenberger u8 data_lenfmt; 6047384eb72SHarald Freudenberger u16 data_len; 6057384eb72SHarald Freudenberger } __packed * rep_pl; 6067384eb72SHarald Freudenberger struct ep11_cprb *req = NULL, *rep = NULL; 6077384eb72SHarald Freudenberger struct ep11_target_dev target; 6087384eb72SHarald Freudenberger struct ep11_urb *urb = NULL; 609386cb81eSHolger Dengler int api = EP11_API_V1, rc = -ENOMEM; 6107384eb72SHarald Freudenberger 6117384eb72SHarald Freudenberger /* request cprb and payload */ 61255d0a513SHarald Freudenberger req = alloc_cprb(sizeof(struct ep11_info_req_pl)); 6137384eb72SHarald Freudenberger if (!req) 6147384eb72SHarald Freudenberger goto out; 6157384eb72SHarald Freudenberger req_pl = (struct ep11_info_req_pl *)(((u8 *)req) + sizeof(*req)); 61655d0a513SHarald Freudenberger prep_head(&req_pl->head, sizeof(*req_pl), api, 38); /* get xcp info */ 6177384eb72SHarald Freudenberger req_pl->query_type_tag = 0x04; 6187384eb72SHarald Freudenberger req_pl->query_type_len = sizeof(u32); 6197384eb72SHarald Freudenberger req_pl->query_type = query_type; 6207384eb72SHarald Freudenberger req_pl->query_subtype_tag = 0x04; 6217384eb72SHarald Freudenberger req_pl->query_subtype_len = sizeof(u32); 6227384eb72SHarald Freudenberger 6237384eb72SHarald Freudenberger /* reply cprb and payload */ 62455d0a513SHarald Freudenberger rep = alloc_cprb(sizeof(struct ep11_info_rep_pl) + buflen); 6257384eb72SHarald Freudenberger if (!rep) 6267384eb72SHarald Freudenberger goto out; 6277384eb72SHarald Freudenberger rep_pl = (struct ep11_info_rep_pl *)(((u8 *)rep) + sizeof(*rep)); 6287384eb72SHarald Freudenberger 6297384eb72SHarald Freudenberger /* urb and target */ 6302004b57cSHarald Freudenberger urb = kmalloc(sizeof(*urb), GFP_KERNEL); 6317384eb72SHarald Freudenberger if (!urb) 6327384eb72SHarald Freudenberger goto out; 6337384eb72SHarald Freudenberger target.ap_id = cardnr; 6347384eb72SHarald Freudenberger target.dom_id = domain; 63555d0a513SHarald Freudenberger prep_urb(urb, &target, 1, 63655d0a513SHarald Freudenberger req, sizeof(*req) + sizeof(*req_pl), 63755d0a513SHarald Freudenberger rep, sizeof(*rep) + sizeof(*rep_pl) + buflen); 6387384eb72SHarald Freudenberger 63952f72febSHarald Freudenberger rc = zcrypt_send_ep11_cprb(urb); 6407384eb72SHarald Freudenberger if (rc) { 64188e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n", 6427384eb72SHarald Freudenberger __func__, (int)cardnr, (int)domain, rc); 6437384eb72SHarald Freudenberger goto out; 6447384eb72SHarald Freudenberger } 6457384eb72SHarald Freudenberger 646c0e983b6SHarald Freudenberger /* check ep11 reply cprb */ 647c0e983b6SHarald Freudenberger rc = check_reply_cprb(rep, __func__); 648c0e983b6SHarald Freudenberger if (rc) 649c0e983b6SHarald Freudenberger goto out; 650c0e983b6SHarald Freudenberger 651c0e983b6SHarald Freudenberger /* check payload */ 65255d0a513SHarald Freudenberger rc = check_reply_pl((u8 *)rep_pl, __func__); 65355d0a513SHarald Freudenberger if (rc) 6547384eb72SHarald Freudenberger goto out; 65555d0a513SHarald Freudenberger if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) { 65688e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s unknown reply data format\n", __func__); 65755d0a513SHarald Freudenberger rc = -EIO; 6587384eb72SHarald Freudenberger goto out; 6597384eb72SHarald Freudenberger } 6607384eb72SHarald Freudenberger if (rep_pl->data_len > buflen) { 66188e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s mismatch between reply data len and buffer len\n", 6627384eb72SHarald Freudenberger __func__); 66355d0a513SHarald Freudenberger rc = -ENOSPC; 6647384eb72SHarald Freudenberger goto out; 6657384eb72SHarald Freudenberger } 6667384eb72SHarald Freudenberger 66755d0a513SHarald Freudenberger memcpy(buf, ((u8 *)rep_pl) + sizeof(*rep_pl), rep_pl->data_len); 6687384eb72SHarald Freudenberger 6697384eb72SHarald Freudenberger out: 6707384eb72SHarald Freudenberger kfree(req); 6717384eb72SHarald Freudenberger kfree(rep); 6727384eb72SHarald Freudenberger kfree(urb); 6737384eb72SHarald Freudenberger return rc; 6747384eb72SHarald Freudenberger } 6757384eb72SHarald Freudenberger 6767384eb72SHarald Freudenberger /* 6777384eb72SHarald Freudenberger * Provide information about an EP11 card. 6787384eb72SHarald Freudenberger */ 6797384eb72SHarald Freudenberger int ep11_get_card_info(u16 card, struct ep11_card_info *info, int verify) 6807384eb72SHarald Freudenberger { 6817384eb72SHarald Freudenberger int rc; 6827384eb72SHarald Freudenberger struct ep11_module_query_info { 6837384eb72SHarald Freudenberger u32 API_ord_nr; 6847384eb72SHarald Freudenberger u32 firmware_id; 6857384eb72SHarald Freudenberger u8 FW_major_vers; 6867384eb72SHarald Freudenberger u8 FW_minor_vers; 6877384eb72SHarald Freudenberger u8 CSP_major_vers; 6887384eb72SHarald Freudenberger u8 CSP_minor_vers; 6897384eb72SHarald Freudenberger u8 fwid[32]; 6907384eb72SHarald Freudenberger u8 xcp_config_hash[32]; 6917384eb72SHarald Freudenberger u8 CSP_config_hash[32]; 6927384eb72SHarald Freudenberger u8 serial[16]; 6937384eb72SHarald Freudenberger u8 module_date_time[16]; 6947384eb72SHarald Freudenberger u64 op_mode; 6957384eb72SHarald Freudenberger u32 PKCS11_flags; 6967384eb72SHarald Freudenberger u32 ext_flags; 6977384eb72SHarald Freudenberger u32 domains; 6987384eb72SHarald Freudenberger u32 sym_state_bytes; 6997384eb72SHarald Freudenberger u32 digest_state_bytes; 7007384eb72SHarald Freudenberger u32 pin_blob_bytes; 7017384eb72SHarald Freudenberger u32 SPKI_bytes; 7027384eb72SHarald Freudenberger u32 priv_key_blob_bytes; 7037384eb72SHarald Freudenberger u32 sym_blob_bytes; 7047384eb72SHarald Freudenberger u32 max_payload_bytes; 7057384eb72SHarald Freudenberger u32 CP_profile_bytes; 7067384eb72SHarald Freudenberger u32 max_CP_index; 7077384eb72SHarald Freudenberger } __packed * pmqi = NULL; 7087384eb72SHarald Freudenberger 7097384eb72SHarald Freudenberger rc = card_cache_fetch(card, info); 7107384eb72SHarald Freudenberger if (rc || verify) { 7117384eb72SHarald Freudenberger pmqi = kmalloc(sizeof(*pmqi), GFP_KERNEL); 7127384eb72SHarald Freudenberger if (!pmqi) 7137384eb72SHarald Freudenberger return -ENOMEM; 7147384eb72SHarald Freudenberger rc = ep11_query_info(card, AUTOSEL_DOM, 7157384eb72SHarald Freudenberger 0x01 /* module info query */, 7167384eb72SHarald Freudenberger sizeof(*pmqi), (u8 *)pmqi); 7177384eb72SHarald Freudenberger if (rc) { 7187384eb72SHarald Freudenberger if (rc == -ENODEV) 7197384eb72SHarald Freudenberger card_cache_scrub(card); 7207384eb72SHarald Freudenberger goto out; 7217384eb72SHarald Freudenberger } 7227384eb72SHarald Freudenberger memset(info, 0, sizeof(*info)); 7237384eb72SHarald Freudenberger info->API_ord_nr = pmqi->API_ord_nr; 7247384eb72SHarald Freudenberger info->FW_version = 7257384eb72SHarald Freudenberger (pmqi->FW_major_vers << 8) + pmqi->FW_minor_vers; 7267384eb72SHarald Freudenberger memcpy(info->serial, pmqi->serial, sizeof(info->serial)); 7277384eb72SHarald Freudenberger info->op_mode = pmqi->op_mode; 7287384eb72SHarald Freudenberger card_cache_update(card, info); 7297384eb72SHarald Freudenberger } 7307384eb72SHarald Freudenberger 7317384eb72SHarald Freudenberger out: 7327384eb72SHarald Freudenberger kfree(pmqi); 7337384eb72SHarald Freudenberger return rc; 7347384eb72SHarald Freudenberger } 7357384eb72SHarald Freudenberger EXPORT_SYMBOL(ep11_get_card_info); 7367384eb72SHarald Freudenberger 7377384eb72SHarald Freudenberger /* 7387384eb72SHarald Freudenberger * Provide information about a domain within an EP11 card. 7397384eb72SHarald Freudenberger */ 7407384eb72SHarald Freudenberger int ep11_get_domain_info(u16 card, u16 domain, struct ep11_domain_info *info) 7417384eb72SHarald Freudenberger { 7427384eb72SHarald Freudenberger int rc; 7437384eb72SHarald Freudenberger struct ep11_domain_query_info { 7447384eb72SHarald Freudenberger u32 dom_index; 7457384eb72SHarald Freudenberger u8 cur_WK_VP[32]; 7467384eb72SHarald Freudenberger u8 new_WK_VP[32]; 7477384eb72SHarald Freudenberger u32 dom_flags; 7487384eb72SHarald Freudenberger u64 op_mode; 7497384eb72SHarald Freudenberger } __packed * p_dom_info; 7507384eb72SHarald Freudenberger 7517384eb72SHarald Freudenberger p_dom_info = kmalloc(sizeof(*p_dom_info), GFP_KERNEL); 7527384eb72SHarald Freudenberger if (!p_dom_info) 7537384eb72SHarald Freudenberger return -ENOMEM; 7547384eb72SHarald Freudenberger 7557384eb72SHarald Freudenberger rc = ep11_query_info(card, domain, 0x03 /* domain info query */, 7567384eb72SHarald Freudenberger sizeof(*p_dom_info), (u8 *)p_dom_info); 7577384eb72SHarald Freudenberger if (rc) 7587384eb72SHarald Freudenberger goto out; 7597384eb72SHarald Freudenberger 7607384eb72SHarald Freudenberger memset(info, 0, sizeof(*info)); 7617384eb72SHarald Freudenberger info->cur_wk_state = '0'; 7627384eb72SHarald Freudenberger info->new_wk_state = '0'; 7637384eb72SHarald Freudenberger if (p_dom_info->dom_flags & 0x10 /* left imprint mode */) { 7647384eb72SHarald Freudenberger if (p_dom_info->dom_flags & 0x02 /* cur wk valid */) { 7657384eb72SHarald Freudenberger info->cur_wk_state = '1'; 7667384eb72SHarald Freudenberger memcpy(info->cur_wkvp, p_dom_info->cur_WK_VP, 32); 7677384eb72SHarald Freudenberger } 7682004b57cSHarald Freudenberger if (p_dom_info->dom_flags & 0x04 || /* new wk present */ 7692004b57cSHarald Freudenberger p_dom_info->dom_flags & 0x08 /* new wk committed */) { 7707384eb72SHarald Freudenberger info->new_wk_state = 7717384eb72SHarald Freudenberger p_dom_info->dom_flags & 0x08 ? '2' : '1'; 7727384eb72SHarald Freudenberger memcpy(info->new_wkvp, p_dom_info->new_WK_VP, 32); 7737384eb72SHarald Freudenberger } 7747384eb72SHarald Freudenberger } 7757384eb72SHarald Freudenberger info->op_mode = p_dom_info->op_mode; 7767384eb72SHarald Freudenberger 7777384eb72SHarald Freudenberger out: 7787384eb72SHarald Freudenberger kfree(p_dom_info); 7797384eb72SHarald Freudenberger return rc; 7807384eb72SHarald Freudenberger } 7817384eb72SHarald Freudenberger EXPORT_SYMBOL(ep11_get_domain_info); 7827384eb72SHarald Freudenberger 78355d0a513SHarald Freudenberger /* 78455d0a513SHarald Freudenberger * Default EP11 AES key generate attributes, used when no keygenflags given: 78555d0a513SHarald Freudenberger * XCP_BLOB_ENCRYPT | XCP_BLOB_DECRYPT | XCP_BLOB_PROTKEY_EXTRACTABLE 78655d0a513SHarald Freudenberger */ 78755d0a513SHarald Freudenberger #define KEY_ATTR_DEFAULTS 0x00200c00 78855d0a513SHarald Freudenberger 789fb249ce7SHolger Dengler static int _ep11_genaeskey(u16 card, u16 domain, 790fb249ce7SHolger Dengler u32 keybitsize, u32 keygenflags, 79155d0a513SHarald Freudenberger u8 *keybuf, size_t *keybufsize) 79255d0a513SHarald Freudenberger { 79355d0a513SHarald Freudenberger struct keygen_req_pl { 79455d0a513SHarald Freudenberger struct pl_head head; 79555d0a513SHarald Freudenberger u8 var_tag; 79655d0a513SHarald Freudenberger u8 var_len; 79755d0a513SHarald Freudenberger u32 var; 79855d0a513SHarald Freudenberger u8 keybytes_tag; 79955d0a513SHarald Freudenberger u8 keybytes_len; 80055d0a513SHarald Freudenberger u32 keybytes; 80155d0a513SHarald Freudenberger u8 mech_tag; 80255d0a513SHarald Freudenberger u8 mech_len; 80355d0a513SHarald Freudenberger u32 mech; 80455d0a513SHarald Freudenberger u8 attr_tag; 80555d0a513SHarald Freudenberger u8 attr_len; 80655d0a513SHarald Freudenberger u32 attr_header; 80755d0a513SHarald Freudenberger u32 attr_bool_mask; 80855d0a513SHarald Freudenberger u32 attr_bool_bits; 80955d0a513SHarald Freudenberger u32 attr_val_len_type; 81055d0a513SHarald Freudenberger u32 attr_val_len_value; 811386cb81eSHolger Dengler /* followed by empty pin tag or empty pinblob tag */ 81255d0a513SHarald Freudenberger } __packed * req_pl; 81355d0a513SHarald Freudenberger struct keygen_rep_pl { 81455d0a513SHarald Freudenberger struct pl_head head; 81555d0a513SHarald Freudenberger u8 rc_tag; 81655d0a513SHarald Freudenberger u8 rc_len; 81755d0a513SHarald Freudenberger u32 rc; 81855d0a513SHarald Freudenberger u8 data_tag; 81955d0a513SHarald Freudenberger u8 data_lenfmt; 82055d0a513SHarald Freudenberger u16 data_len; 82155d0a513SHarald Freudenberger u8 data[512]; 82255d0a513SHarald Freudenberger } __packed * rep_pl; 82355d0a513SHarald Freudenberger struct ep11_cprb *req = NULL, *rep = NULL; 824386cb81eSHolger Dengler size_t req_pl_size, pinblob_size = 0; 82555d0a513SHarald Freudenberger struct ep11_target_dev target; 82655d0a513SHarald Freudenberger struct ep11_urb *urb = NULL; 82755d0a513SHarald Freudenberger int api, rc = -ENOMEM; 828386cb81eSHolger Dengler u8 *p; 82955d0a513SHarald Freudenberger 83055d0a513SHarald Freudenberger switch (keybitsize) { 83155d0a513SHarald Freudenberger case 128: 83255d0a513SHarald Freudenberger case 192: 83355d0a513SHarald Freudenberger case 256: 83455d0a513SHarald Freudenberger break; 83555d0a513SHarald Freudenberger default: 83688e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s unknown/unsupported keybitsize %d\n", 83755d0a513SHarald Freudenberger __func__, keybitsize); 83855d0a513SHarald Freudenberger rc = -EINVAL; 83955d0a513SHarald Freudenberger goto out; 84055d0a513SHarald Freudenberger } 84155d0a513SHarald Freudenberger 84255d0a513SHarald Freudenberger /* request cprb and payload */ 843386cb81eSHolger Dengler api = (!keygenflags || keygenflags & 0x00200000) ? 844386cb81eSHolger Dengler EP11_API_V4 : EP11_API_V1; 845386cb81eSHolger Dengler if (ap_is_se_guest()) { 846386cb81eSHolger Dengler /* 847386cb81eSHolger Dengler * genkey within SE environment requires API ordinal 6 848386cb81eSHolger Dengler * with empty pinblob 849386cb81eSHolger Dengler */ 850386cb81eSHolger Dengler api = EP11_API_V6; 851386cb81eSHolger Dengler pinblob_size = EP11_PINBLOB_V1_BYTES; 852386cb81eSHolger Dengler } 853386cb81eSHolger Dengler req_pl_size = sizeof(struct keygen_req_pl) + ASN1TAGLEN(pinblob_size); 854386cb81eSHolger Dengler req = alloc_cprb(req_pl_size); 85555d0a513SHarald Freudenberger if (!req) 85655d0a513SHarald Freudenberger goto out; 85755d0a513SHarald Freudenberger req_pl = (struct keygen_req_pl *)(((u8 *)req) + sizeof(*req)); 858386cb81eSHolger Dengler prep_head(&req_pl->head, req_pl_size, api, 21); /* GenerateKey */ 85955d0a513SHarald Freudenberger req_pl->var_tag = 0x04; 86055d0a513SHarald Freudenberger req_pl->var_len = sizeof(u32); 86155d0a513SHarald Freudenberger req_pl->keybytes_tag = 0x04; 86255d0a513SHarald Freudenberger req_pl->keybytes_len = sizeof(u32); 86355d0a513SHarald Freudenberger req_pl->keybytes = keybitsize / 8; 86455d0a513SHarald Freudenberger req_pl->mech_tag = 0x04; 86555d0a513SHarald Freudenberger req_pl->mech_len = sizeof(u32); 86655d0a513SHarald Freudenberger req_pl->mech = 0x00001080; /* CKM_AES_KEY_GEN */ 86755d0a513SHarald Freudenberger req_pl->attr_tag = 0x04; 86855d0a513SHarald Freudenberger req_pl->attr_len = 5 * sizeof(u32); 86955d0a513SHarald Freudenberger req_pl->attr_header = 0x10010000; 87055d0a513SHarald Freudenberger req_pl->attr_bool_mask = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS; 87155d0a513SHarald Freudenberger req_pl->attr_bool_bits = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS; 87255d0a513SHarald Freudenberger req_pl->attr_val_len_type = 0x00000161; /* CKA_VALUE_LEN */ 87355d0a513SHarald Freudenberger req_pl->attr_val_len_value = keybitsize / 8; 874386cb81eSHolger Dengler p = ((u8 *)req_pl) + sizeof(*req_pl); 875386cb81eSHolger Dengler /* pin tag */ 876386cb81eSHolger Dengler *p++ = 0x04; 877386cb81eSHolger Dengler *p++ = pinblob_size; 87855d0a513SHarald Freudenberger 87955d0a513SHarald Freudenberger /* reply cprb and payload */ 88055d0a513SHarald Freudenberger rep = alloc_cprb(sizeof(struct keygen_rep_pl)); 88155d0a513SHarald Freudenberger if (!rep) 88255d0a513SHarald Freudenberger goto out; 88355d0a513SHarald Freudenberger rep_pl = (struct keygen_rep_pl *)(((u8 *)rep) + sizeof(*rep)); 88455d0a513SHarald Freudenberger 88555d0a513SHarald Freudenberger /* urb and target */ 8862004b57cSHarald Freudenberger urb = kmalloc(sizeof(*urb), GFP_KERNEL); 88755d0a513SHarald Freudenberger if (!urb) 88855d0a513SHarald Freudenberger goto out; 88955d0a513SHarald Freudenberger target.ap_id = card; 89055d0a513SHarald Freudenberger target.dom_id = domain; 89155d0a513SHarald Freudenberger prep_urb(urb, &target, 1, 892386cb81eSHolger Dengler req, sizeof(*req) + req_pl_size, 89355d0a513SHarald Freudenberger rep, sizeof(*rep) + sizeof(*rep_pl)); 89455d0a513SHarald Freudenberger 89552f72febSHarald Freudenberger rc = zcrypt_send_ep11_cprb(urb); 89655d0a513SHarald Freudenberger if (rc) { 89788e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n", 89855d0a513SHarald Freudenberger __func__, (int)card, (int)domain, rc); 89955d0a513SHarald Freudenberger goto out; 90055d0a513SHarald Freudenberger } 90155d0a513SHarald Freudenberger 902c0e983b6SHarald Freudenberger /* check ep11 reply cprb */ 903c0e983b6SHarald Freudenberger rc = check_reply_cprb(rep, __func__); 904c0e983b6SHarald Freudenberger if (rc) 905c0e983b6SHarald Freudenberger goto out; 906c0e983b6SHarald Freudenberger 907c0e983b6SHarald Freudenberger /* check payload */ 90855d0a513SHarald Freudenberger rc = check_reply_pl((u8 *)rep_pl, __func__); 90955d0a513SHarald Freudenberger if (rc) 91055d0a513SHarald Freudenberger goto out; 91155d0a513SHarald Freudenberger if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) { 91288e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s unknown reply data format\n", __func__); 91355d0a513SHarald Freudenberger rc = -EIO; 91455d0a513SHarald Freudenberger goto out; 91555d0a513SHarald Freudenberger } 91655d0a513SHarald Freudenberger if (rep_pl->data_len > *keybufsize) { 91788e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s mismatch reply data len / key buffer len\n", 91855d0a513SHarald Freudenberger __func__); 91955d0a513SHarald Freudenberger rc = -ENOSPC; 92055d0a513SHarald Freudenberger goto out; 92155d0a513SHarald Freudenberger } 92255d0a513SHarald Freudenberger 923fb249ce7SHolger Dengler /* copy key blob */ 92455d0a513SHarald Freudenberger memcpy(keybuf, rep_pl->data, rep_pl->data_len); 92555d0a513SHarald Freudenberger *keybufsize = rep_pl->data_len; 92655d0a513SHarald Freudenberger 92755d0a513SHarald Freudenberger out: 92855d0a513SHarald Freudenberger kfree(req); 92955d0a513SHarald Freudenberger kfree(rep); 93055d0a513SHarald Freudenberger kfree(urb); 93155d0a513SHarald Freudenberger return rc; 93255d0a513SHarald Freudenberger } 933fb249ce7SHolger Dengler 934fb249ce7SHolger Dengler int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags, 935fb249ce7SHolger Dengler u8 *keybuf, size_t *keybufsize, u32 keybufver) 936fb249ce7SHolger Dengler { 937fb249ce7SHolger Dengler struct ep11kblob_header *hdr; 938fb249ce7SHolger Dengler size_t hdr_size, pl_size; 939fb249ce7SHolger Dengler u8 *pl; 940fb249ce7SHolger Dengler int rc; 941fb249ce7SHolger Dengler 942fb249ce7SHolger Dengler switch (keybufver) { 943fb249ce7SHolger Dengler case TOKVER_EP11_AES: 944fb249ce7SHolger Dengler case TOKVER_EP11_AES_WITH_HEADER: 945fb249ce7SHolger Dengler break; 946fb249ce7SHolger Dengler default: 947fb249ce7SHolger Dengler return -EINVAL; 948fb249ce7SHolger Dengler } 949fb249ce7SHolger Dengler 950fb249ce7SHolger Dengler rc = ep11_kb_split(keybuf, *keybufsize, keybufver, 951fb249ce7SHolger Dengler &hdr, &hdr_size, &pl, &pl_size); 952fb249ce7SHolger Dengler if (rc) 953fb249ce7SHolger Dengler return rc; 954fb249ce7SHolger Dengler 955fb249ce7SHolger Dengler rc = _ep11_genaeskey(card, domain, keybitsize, keygenflags, 956fb249ce7SHolger Dengler pl, &pl_size); 957fb249ce7SHolger Dengler if (rc) 958fb249ce7SHolger Dengler return rc; 959fb249ce7SHolger Dengler 960fb249ce7SHolger Dengler *keybufsize = hdr_size + pl_size; 961fb249ce7SHolger Dengler 962fb249ce7SHolger Dengler /* update header information */ 963fb249ce7SHolger Dengler hdr->type = TOKTYPE_NON_CCA; 964fb249ce7SHolger Dengler hdr->len = *keybufsize; 965fb249ce7SHolger Dengler hdr->version = keybufver; 966fb249ce7SHolger Dengler hdr->bitlen = keybitsize; 967fb249ce7SHolger Dengler 968fb249ce7SHolger Dengler return 0; 969fb249ce7SHolger Dengler } 97055d0a513SHarald Freudenberger EXPORT_SYMBOL(ep11_genaeskey); 97155d0a513SHarald Freudenberger 97255d0a513SHarald Freudenberger static int ep11_cryptsingle(u16 card, u16 domain, 97355d0a513SHarald Freudenberger u16 mode, u32 mech, const u8 *iv, 97455d0a513SHarald Freudenberger const u8 *key, size_t keysize, 97555d0a513SHarald Freudenberger const u8 *inbuf, size_t inbufsize, 97655d0a513SHarald Freudenberger u8 *outbuf, size_t *outbufsize) 97755d0a513SHarald Freudenberger { 97855d0a513SHarald Freudenberger struct crypt_req_pl { 97955d0a513SHarald Freudenberger struct pl_head head; 98055d0a513SHarald Freudenberger u8 var_tag; 98155d0a513SHarald Freudenberger u8 var_len; 98255d0a513SHarald Freudenberger u32 var; 98355d0a513SHarald Freudenberger u8 mech_tag; 98455d0a513SHarald Freudenberger u8 mech_len; 98555d0a513SHarald Freudenberger u32 mech; 98655d0a513SHarald Freudenberger /* 98755d0a513SHarald Freudenberger * maybe followed by iv data 98855d0a513SHarald Freudenberger * followed by key tag + key blob 98955d0a513SHarald Freudenberger * followed by plaintext tag + plaintext 99055d0a513SHarald Freudenberger */ 99155d0a513SHarald Freudenberger } __packed * req_pl; 99255d0a513SHarald Freudenberger struct crypt_rep_pl { 99355d0a513SHarald Freudenberger struct pl_head head; 99455d0a513SHarald Freudenberger u8 rc_tag; 99555d0a513SHarald Freudenberger u8 rc_len; 99655d0a513SHarald Freudenberger u32 rc; 99755d0a513SHarald Freudenberger u8 data_tag; 99855d0a513SHarald Freudenberger u8 data_lenfmt; 99955d0a513SHarald Freudenberger /* data follows */ 100055d0a513SHarald Freudenberger } __packed * rep_pl; 100155d0a513SHarald Freudenberger struct ep11_cprb *req = NULL, *rep = NULL; 100255d0a513SHarald Freudenberger struct ep11_target_dev target; 100355d0a513SHarald Freudenberger struct ep11_urb *urb = NULL; 100455d0a513SHarald Freudenberger size_t req_pl_size, rep_pl_size; 1005386cb81eSHolger Dengler int n, api = EP11_API_V1, rc = -ENOMEM; 100655d0a513SHarald Freudenberger u8 *p; 100755d0a513SHarald Freudenberger 100855d0a513SHarald Freudenberger /* the simple asn1 coding used has length limits */ 100955d0a513SHarald Freudenberger if (keysize > 0xFFFF || inbufsize > 0xFFFF) 101055d0a513SHarald Freudenberger return -EINVAL; 101155d0a513SHarald Freudenberger 101255d0a513SHarald Freudenberger /* request cprb and payload */ 101355d0a513SHarald Freudenberger req_pl_size = sizeof(struct crypt_req_pl) + (iv ? 16 : 0) 101455d0a513SHarald Freudenberger + ASN1TAGLEN(keysize) + ASN1TAGLEN(inbufsize); 101555d0a513SHarald Freudenberger req = alloc_cprb(req_pl_size); 101655d0a513SHarald Freudenberger if (!req) 101755d0a513SHarald Freudenberger goto out; 101855d0a513SHarald Freudenberger req_pl = (struct crypt_req_pl *)(((u8 *)req) + sizeof(*req)); 101955d0a513SHarald Freudenberger prep_head(&req_pl->head, req_pl_size, api, (mode ? 20 : 19)); 102055d0a513SHarald Freudenberger req_pl->var_tag = 0x04; 102155d0a513SHarald Freudenberger req_pl->var_len = sizeof(u32); 102255d0a513SHarald Freudenberger /* mech is mech + mech params (iv here) */ 102355d0a513SHarald Freudenberger req_pl->mech_tag = 0x04; 102455d0a513SHarald Freudenberger req_pl->mech_len = sizeof(u32) + (iv ? 16 : 0); 102555d0a513SHarald Freudenberger req_pl->mech = (mech ? mech : 0x00001085); /* CKM_AES_CBC_PAD */ 102655d0a513SHarald Freudenberger p = ((u8 *)req_pl) + sizeof(*req_pl); 102755d0a513SHarald Freudenberger if (iv) { 102855d0a513SHarald Freudenberger memcpy(p, iv, 16); 102955d0a513SHarald Freudenberger p += 16; 103055d0a513SHarald Freudenberger } 103155d0a513SHarald Freudenberger /* key and input data */ 103255d0a513SHarald Freudenberger p += asn1tag_write(p, 0x04, key, keysize); 103355d0a513SHarald Freudenberger p += asn1tag_write(p, 0x04, inbuf, inbufsize); 103455d0a513SHarald Freudenberger 103555d0a513SHarald Freudenberger /* reply cprb and payload, assume out data size <= in data size + 32 */ 103655d0a513SHarald Freudenberger rep_pl_size = sizeof(struct crypt_rep_pl) + ASN1TAGLEN(inbufsize + 32); 103755d0a513SHarald Freudenberger rep = alloc_cprb(rep_pl_size); 103855d0a513SHarald Freudenberger if (!rep) 103955d0a513SHarald Freudenberger goto out; 104055d0a513SHarald Freudenberger rep_pl = (struct crypt_rep_pl *)(((u8 *)rep) + sizeof(*rep)); 104155d0a513SHarald Freudenberger 104255d0a513SHarald Freudenberger /* urb and target */ 10432004b57cSHarald Freudenberger urb = kmalloc(sizeof(*urb), GFP_KERNEL); 104455d0a513SHarald Freudenberger if (!urb) 104555d0a513SHarald Freudenberger goto out; 104655d0a513SHarald Freudenberger target.ap_id = card; 104755d0a513SHarald Freudenberger target.dom_id = domain; 104855d0a513SHarald Freudenberger prep_urb(urb, &target, 1, 104955d0a513SHarald Freudenberger req, sizeof(*req) + req_pl_size, 105055d0a513SHarald Freudenberger rep, sizeof(*rep) + rep_pl_size); 105155d0a513SHarald Freudenberger 105252f72febSHarald Freudenberger rc = zcrypt_send_ep11_cprb(urb); 105355d0a513SHarald Freudenberger if (rc) { 105488e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n", 105555d0a513SHarald Freudenberger __func__, (int)card, (int)domain, rc); 105655d0a513SHarald Freudenberger goto out; 105755d0a513SHarald Freudenberger } 105855d0a513SHarald Freudenberger 1059c0e983b6SHarald Freudenberger /* check ep11 reply cprb */ 1060c0e983b6SHarald Freudenberger rc = check_reply_cprb(rep, __func__); 1061c0e983b6SHarald Freudenberger if (rc) 1062c0e983b6SHarald Freudenberger goto out; 1063c0e983b6SHarald Freudenberger 1064c0e983b6SHarald Freudenberger /* check payload */ 106555d0a513SHarald Freudenberger rc = check_reply_pl((u8 *)rep_pl, __func__); 106655d0a513SHarald Freudenberger if (rc) 106755d0a513SHarald Freudenberger goto out; 106855d0a513SHarald Freudenberger if (rep_pl->data_tag != 0x04) { 106988e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s unknown reply data format\n", __func__); 107055d0a513SHarald Freudenberger rc = -EIO; 107155d0a513SHarald Freudenberger goto out; 107255d0a513SHarald Freudenberger } 107355d0a513SHarald Freudenberger p = ((u8 *)rep_pl) + sizeof(*rep_pl); 10742004b57cSHarald Freudenberger if (rep_pl->data_lenfmt <= 127) { 107555d0a513SHarald Freudenberger n = rep_pl->data_lenfmt; 10762004b57cSHarald Freudenberger } else if (rep_pl->data_lenfmt == 0x81) { 107755d0a513SHarald Freudenberger n = *p++; 10782004b57cSHarald Freudenberger } else if (rep_pl->data_lenfmt == 0x82) { 107955d0a513SHarald Freudenberger n = *((u16 *)p); 108055d0a513SHarald Freudenberger p += 2; 108155d0a513SHarald Freudenberger } else { 108288e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s unknown reply data length format 0x%02hhx\n", 108355d0a513SHarald Freudenberger __func__, rep_pl->data_lenfmt); 108455d0a513SHarald Freudenberger rc = -EIO; 108555d0a513SHarald Freudenberger goto out; 108655d0a513SHarald Freudenberger } 108755d0a513SHarald Freudenberger if (n > *outbufsize) { 108888e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s mismatch reply data len %d / output buffer %zu\n", 108955d0a513SHarald Freudenberger __func__, n, *outbufsize); 109055d0a513SHarald Freudenberger rc = -ENOSPC; 109155d0a513SHarald Freudenberger goto out; 109255d0a513SHarald Freudenberger } 109355d0a513SHarald Freudenberger 109455d0a513SHarald Freudenberger memcpy(outbuf, p, n); 109555d0a513SHarald Freudenberger *outbufsize = n; 109655d0a513SHarald Freudenberger 109755d0a513SHarald Freudenberger out: 109855d0a513SHarald Freudenberger kfree(req); 109955d0a513SHarald Freudenberger kfree(rep); 110055d0a513SHarald Freudenberger kfree(urb); 110155d0a513SHarald Freudenberger return rc; 110255d0a513SHarald Freudenberger } 110355d0a513SHarald Freudenberger 1104da2863f1SHolger Dengler static int _ep11_unwrapkey(u16 card, u16 domain, 110555d0a513SHarald Freudenberger const u8 *kek, size_t keksize, 110655d0a513SHarald Freudenberger const u8 *enckey, size_t enckeysize, 110755d0a513SHarald Freudenberger u32 mech, const u8 *iv, 110855d0a513SHarald Freudenberger u32 keybitsize, u32 keygenflags, 110955d0a513SHarald Freudenberger u8 *keybuf, size_t *keybufsize) 111055d0a513SHarald Freudenberger { 111155d0a513SHarald Freudenberger struct uw_req_pl { 111255d0a513SHarald Freudenberger struct pl_head head; 111355d0a513SHarald Freudenberger u8 attr_tag; 111455d0a513SHarald Freudenberger u8 attr_len; 111555d0a513SHarald Freudenberger u32 attr_header; 111655d0a513SHarald Freudenberger u32 attr_bool_mask; 111755d0a513SHarald Freudenberger u32 attr_bool_bits; 111855d0a513SHarald Freudenberger u32 attr_key_type; 111955d0a513SHarald Freudenberger u32 attr_key_type_value; 112055d0a513SHarald Freudenberger u32 attr_val_len; 112155d0a513SHarald Freudenberger u32 attr_val_len_value; 112255d0a513SHarald Freudenberger u8 mech_tag; 112355d0a513SHarald Freudenberger u8 mech_len; 112455d0a513SHarald Freudenberger u32 mech; 112555d0a513SHarald Freudenberger /* 112655d0a513SHarald Freudenberger * maybe followed by iv data 112755d0a513SHarald Freudenberger * followed by kek tag + kek blob 112855d0a513SHarald Freudenberger * followed by empty mac tag 1129386cb81eSHolger Dengler * followed by empty pin tag or empty pinblob tag 113055d0a513SHarald Freudenberger * followed by encryted key tag + bytes 113155d0a513SHarald Freudenberger */ 113255d0a513SHarald Freudenberger } __packed * req_pl; 113355d0a513SHarald Freudenberger struct uw_rep_pl { 113455d0a513SHarald Freudenberger struct pl_head head; 113555d0a513SHarald Freudenberger u8 rc_tag; 113655d0a513SHarald Freudenberger u8 rc_len; 113755d0a513SHarald Freudenberger u32 rc; 113855d0a513SHarald Freudenberger u8 data_tag; 113955d0a513SHarald Freudenberger u8 data_lenfmt; 114055d0a513SHarald Freudenberger u16 data_len; 114155d0a513SHarald Freudenberger u8 data[512]; 114255d0a513SHarald Freudenberger } __packed * rep_pl; 114355d0a513SHarald Freudenberger struct ep11_cprb *req = NULL, *rep = NULL; 1144386cb81eSHolger Dengler size_t req_pl_size, pinblob_size = 0; 114555d0a513SHarald Freudenberger struct ep11_target_dev target; 114655d0a513SHarald Freudenberger struct ep11_urb *urb = NULL; 114755d0a513SHarald Freudenberger int api, rc = -ENOMEM; 114855d0a513SHarald Freudenberger u8 *p; 114955d0a513SHarald Freudenberger 115055d0a513SHarald Freudenberger /* request cprb and payload */ 1151386cb81eSHolger Dengler api = (!keygenflags || keygenflags & 0x00200000) ? 1152386cb81eSHolger Dengler EP11_API_V4 : EP11_API_V1; 1153386cb81eSHolger Dengler if (ap_is_se_guest()) { 1154386cb81eSHolger Dengler /* 1155386cb81eSHolger Dengler * unwrap within SE environment requires API ordinal 6 1156386cb81eSHolger Dengler * with empty pinblob 1157386cb81eSHolger Dengler */ 1158386cb81eSHolger Dengler api = EP11_API_V6; 1159386cb81eSHolger Dengler pinblob_size = EP11_PINBLOB_V1_BYTES; 1160386cb81eSHolger Dengler } 116155d0a513SHarald Freudenberger req_pl_size = sizeof(struct uw_req_pl) + (iv ? 16 : 0) 1162386cb81eSHolger Dengler + ASN1TAGLEN(keksize) + ASN1TAGLEN(0) 1163386cb81eSHolger Dengler + ASN1TAGLEN(pinblob_size) + ASN1TAGLEN(enckeysize); 116455d0a513SHarald Freudenberger req = alloc_cprb(req_pl_size); 116555d0a513SHarald Freudenberger if (!req) 116655d0a513SHarald Freudenberger goto out; 116755d0a513SHarald Freudenberger req_pl = (struct uw_req_pl *)(((u8 *)req) + sizeof(*req)); 116855d0a513SHarald Freudenberger prep_head(&req_pl->head, req_pl_size, api, 34); /* UnwrapKey */ 116955d0a513SHarald Freudenberger req_pl->attr_tag = 0x04; 117055d0a513SHarald Freudenberger req_pl->attr_len = 7 * sizeof(u32); 117155d0a513SHarald Freudenberger req_pl->attr_header = 0x10020000; 117255d0a513SHarald Freudenberger req_pl->attr_bool_mask = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS; 117355d0a513SHarald Freudenberger req_pl->attr_bool_bits = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS; 117455d0a513SHarald Freudenberger req_pl->attr_key_type = 0x00000100; /* CKA_KEY_TYPE */ 117555d0a513SHarald Freudenberger req_pl->attr_key_type_value = 0x0000001f; /* CKK_AES */ 117655d0a513SHarald Freudenberger req_pl->attr_val_len = 0x00000161; /* CKA_VALUE_LEN */ 117755d0a513SHarald Freudenberger req_pl->attr_val_len_value = keybitsize / 8; 117855d0a513SHarald Freudenberger /* mech is mech + mech params (iv here) */ 117955d0a513SHarald Freudenberger req_pl->mech_tag = 0x04; 118055d0a513SHarald Freudenberger req_pl->mech_len = sizeof(u32) + (iv ? 16 : 0); 118155d0a513SHarald Freudenberger req_pl->mech = (mech ? mech : 0x00001085); /* CKM_AES_CBC_PAD */ 118255d0a513SHarald Freudenberger p = ((u8 *)req_pl) + sizeof(*req_pl); 118355d0a513SHarald Freudenberger if (iv) { 118455d0a513SHarald Freudenberger memcpy(p, iv, 16); 118555d0a513SHarald Freudenberger p += 16; 118655d0a513SHarald Freudenberger } 118755d0a513SHarald Freudenberger /* kek */ 118855d0a513SHarald Freudenberger p += asn1tag_write(p, 0x04, kek, keksize); 118955d0a513SHarald Freudenberger /* empty mac key tag */ 119055d0a513SHarald Freudenberger *p++ = 0x04; 119155d0a513SHarald Freudenberger *p++ = 0; 1192386cb81eSHolger Dengler /* pin tag */ 119355d0a513SHarald Freudenberger *p++ = 0x04; 1194386cb81eSHolger Dengler *p++ = pinblob_size; 1195386cb81eSHolger Dengler p += pinblob_size; 119605ccaca0SGeert Uytterhoeven /* encrypted key value tag and bytes */ 119755d0a513SHarald Freudenberger p += asn1tag_write(p, 0x04, enckey, enckeysize); 119855d0a513SHarald Freudenberger 119955d0a513SHarald Freudenberger /* reply cprb and payload */ 120055d0a513SHarald Freudenberger rep = alloc_cprb(sizeof(struct uw_rep_pl)); 120155d0a513SHarald Freudenberger if (!rep) 120255d0a513SHarald Freudenberger goto out; 120355d0a513SHarald Freudenberger rep_pl = (struct uw_rep_pl *)(((u8 *)rep) + sizeof(*rep)); 120455d0a513SHarald Freudenberger 120555d0a513SHarald Freudenberger /* urb and target */ 12062004b57cSHarald Freudenberger urb = kmalloc(sizeof(*urb), GFP_KERNEL); 120755d0a513SHarald Freudenberger if (!urb) 120855d0a513SHarald Freudenberger goto out; 120955d0a513SHarald Freudenberger target.ap_id = card; 121055d0a513SHarald Freudenberger target.dom_id = domain; 121155d0a513SHarald Freudenberger prep_urb(urb, &target, 1, 121255d0a513SHarald Freudenberger req, sizeof(*req) + req_pl_size, 121355d0a513SHarald Freudenberger rep, sizeof(*rep) + sizeof(*rep_pl)); 121455d0a513SHarald Freudenberger 121552f72febSHarald Freudenberger rc = zcrypt_send_ep11_cprb(urb); 121655d0a513SHarald Freudenberger if (rc) { 121788e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n", 121855d0a513SHarald Freudenberger __func__, (int)card, (int)domain, rc); 121955d0a513SHarald Freudenberger goto out; 122055d0a513SHarald Freudenberger } 122155d0a513SHarald Freudenberger 1222c0e983b6SHarald Freudenberger /* check ep11 reply cprb */ 1223c0e983b6SHarald Freudenberger rc = check_reply_cprb(rep, __func__); 1224c0e983b6SHarald Freudenberger if (rc) 1225c0e983b6SHarald Freudenberger goto out; 1226c0e983b6SHarald Freudenberger 1227c0e983b6SHarald Freudenberger /* check payload */ 122855d0a513SHarald Freudenberger rc = check_reply_pl((u8 *)rep_pl, __func__); 122955d0a513SHarald Freudenberger if (rc) 123055d0a513SHarald Freudenberger goto out; 123155d0a513SHarald Freudenberger if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) { 123288e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s unknown reply data format\n", __func__); 123355d0a513SHarald Freudenberger rc = -EIO; 123455d0a513SHarald Freudenberger goto out; 123555d0a513SHarald Freudenberger } 123655d0a513SHarald Freudenberger if (rep_pl->data_len > *keybufsize) { 123788e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s mismatch reply data len / key buffer len\n", 123855d0a513SHarald Freudenberger __func__); 123955d0a513SHarald Freudenberger rc = -ENOSPC; 124055d0a513SHarald Freudenberger goto out; 124155d0a513SHarald Freudenberger } 124255d0a513SHarald Freudenberger 1243da2863f1SHolger Dengler /* copy key blob */ 124455d0a513SHarald Freudenberger memcpy(keybuf, rep_pl->data, rep_pl->data_len); 124555d0a513SHarald Freudenberger *keybufsize = rep_pl->data_len; 124655d0a513SHarald Freudenberger 124755d0a513SHarald Freudenberger out: 124855d0a513SHarald Freudenberger kfree(req); 124955d0a513SHarald Freudenberger kfree(rep); 125055d0a513SHarald Freudenberger kfree(urb); 125155d0a513SHarald Freudenberger return rc; 125255d0a513SHarald Freudenberger } 125355d0a513SHarald Freudenberger 1254da2863f1SHolger Dengler static int ep11_unwrapkey(u16 card, u16 domain, 1255da2863f1SHolger Dengler const u8 *kek, size_t keksize, 1256da2863f1SHolger Dengler const u8 *enckey, size_t enckeysize, 1257da2863f1SHolger Dengler u32 mech, const u8 *iv, 1258da2863f1SHolger Dengler u32 keybitsize, u32 keygenflags, 1259da2863f1SHolger Dengler u8 *keybuf, size_t *keybufsize, 1260da2863f1SHolger Dengler u8 keybufver) 1261da2863f1SHolger Dengler { 1262da2863f1SHolger Dengler struct ep11kblob_header *hdr; 1263da2863f1SHolger Dengler size_t hdr_size, pl_size; 1264da2863f1SHolger Dengler u8 *pl; 1265da2863f1SHolger Dengler int rc; 1266da2863f1SHolger Dengler 1267da2863f1SHolger Dengler rc = ep11_kb_split(keybuf, *keybufsize, keybufver, 1268da2863f1SHolger Dengler &hdr, &hdr_size, &pl, &pl_size); 1269da2863f1SHolger Dengler if (rc) 1270da2863f1SHolger Dengler return rc; 1271da2863f1SHolger Dengler 1272da2863f1SHolger Dengler rc = _ep11_unwrapkey(card, domain, kek, keksize, enckey, enckeysize, 1273da2863f1SHolger Dengler mech, iv, keybitsize, keygenflags, 1274da2863f1SHolger Dengler pl, &pl_size); 1275da2863f1SHolger Dengler if (rc) 1276da2863f1SHolger Dengler return rc; 1277da2863f1SHolger Dengler 1278da2863f1SHolger Dengler *keybufsize = hdr_size + pl_size; 1279da2863f1SHolger Dengler 1280da2863f1SHolger Dengler /* update header information */ 1281da2863f1SHolger Dengler hdr = (struct ep11kblob_header *)keybuf; 1282da2863f1SHolger Dengler hdr->type = TOKTYPE_NON_CCA; 1283da2863f1SHolger Dengler hdr->len = *keybufsize; 1284da2863f1SHolger Dengler hdr->version = keybufver; 1285da2863f1SHolger Dengler hdr->bitlen = keybitsize; 1286da2863f1SHolger Dengler 1287da2863f1SHolger Dengler return 0; 1288da2863f1SHolger Dengler } 1289da2863f1SHolger Dengler 1290d1fdfb0bSHolger Dengler static int _ep11_wrapkey(u16 card, u16 domain, 129155d0a513SHarald Freudenberger const u8 *key, size_t keysize, 129255d0a513SHarald Freudenberger u32 mech, const u8 *iv, 129355d0a513SHarald Freudenberger u8 *databuf, size_t *datasize) 129455d0a513SHarald Freudenberger { 129555d0a513SHarald Freudenberger struct wk_req_pl { 129655d0a513SHarald Freudenberger struct pl_head head; 129755d0a513SHarald Freudenberger u8 var_tag; 129855d0a513SHarald Freudenberger u8 var_len; 129955d0a513SHarald Freudenberger u32 var; 130055d0a513SHarald Freudenberger u8 mech_tag; 130155d0a513SHarald Freudenberger u8 mech_len; 130255d0a513SHarald Freudenberger u32 mech; 130355d0a513SHarald Freudenberger /* 130455d0a513SHarald Freudenberger * followed by iv data 130555d0a513SHarald Freudenberger * followed by key tag + key blob 130655d0a513SHarald Freudenberger * followed by dummy kek param 130755d0a513SHarald Freudenberger * followed by dummy mac param 130855d0a513SHarald Freudenberger */ 130955d0a513SHarald Freudenberger } __packed * req_pl; 131055d0a513SHarald Freudenberger struct wk_rep_pl { 131155d0a513SHarald Freudenberger struct pl_head head; 131255d0a513SHarald Freudenberger u8 rc_tag; 131355d0a513SHarald Freudenberger u8 rc_len; 131455d0a513SHarald Freudenberger u32 rc; 131555d0a513SHarald Freudenberger u8 data_tag; 131655d0a513SHarald Freudenberger u8 data_lenfmt; 131755d0a513SHarald Freudenberger u16 data_len; 1318fa6999e3SHarald Freudenberger u8 data[1024]; 131955d0a513SHarald Freudenberger } __packed * rep_pl; 132055d0a513SHarald Freudenberger struct ep11_cprb *req = NULL, *rep = NULL; 132155d0a513SHarald Freudenberger struct ep11_target_dev target; 132255d0a513SHarald Freudenberger struct ep11_urb *urb = NULL; 132355d0a513SHarald Freudenberger size_t req_pl_size; 132455d0a513SHarald Freudenberger int api, rc = -ENOMEM; 132555d0a513SHarald Freudenberger u8 *p; 132655d0a513SHarald Freudenberger 132755d0a513SHarald Freudenberger /* request cprb and payload */ 132855d0a513SHarald Freudenberger req_pl_size = sizeof(struct wk_req_pl) + (iv ? 16 : 0) 132955d0a513SHarald Freudenberger + ASN1TAGLEN(keysize) + 4; 133055d0a513SHarald Freudenberger req = alloc_cprb(req_pl_size); 133155d0a513SHarald Freudenberger if (!req) 133255d0a513SHarald Freudenberger goto out; 133355d0a513SHarald Freudenberger if (!mech || mech == 0x80060001) 133455d0a513SHarald Freudenberger req->flags |= 0x20; /* CPACF_WRAP needs special bit */ 133555d0a513SHarald Freudenberger req_pl = (struct wk_req_pl *)(((u8 *)req) + sizeof(*req)); 1336386cb81eSHolger Dengler api = (!mech || mech == 0x80060001) ? /* CKM_IBM_CPACF_WRAP */ 1337386cb81eSHolger Dengler EP11_API_V4 : EP11_API_V1; 133855d0a513SHarald Freudenberger prep_head(&req_pl->head, req_pl_size, api, 33); /* WrapKey */ 133955d0a513SHarald Freudenberger req_pl->var_tag = 0x04; 134055d0a513SHarald Freudenberger req_pl->var_len = sizeof(u32); 134155d0a513SHarald Freudenberger /* mech is mech + mech params (iv here) */ 134255d0a513SHarald Freudenberger req_pl->mech_tag = 0x04; 134355d0a513SHarald Freudenberger req_pl->mech_len = sizeof(u32) + (iv ? 16 : 0); 134455d0a513SHarald Freudenberger req_pl->mech = (mech ? mech : 0x80060001); /* CKM_IBM_CPACF_WRAP */ 134555d0a513SHarald Freudenberger p = ((u8 *)req_pl) + sizeof(*req_pl); 134655d0a513SHarald Freudenberger if (iv) { 134755d0a513SHarald Freudenberger memcpy(p, iv, 16); 134855d0a513SHarald Freudenberger p += 16; 134955d0a513SHarald Freudenberger } 135055d0a513SHarald Freudenberger /* key blob */ 135155d0a513SHarald Freudenberger p += asn1tag_write(p, 0x04, key, keysize); 135255d0a513SHarald Freudenberger /* empty kek tag */ 135355d0a513SHarald Freudenberger *p++ = 0x04; 135455d0a513SHarald Freudenberger *p++ = 0; 135555d0a513SHarald Freudenberger /* empty mac tag */ 135655d0a513SHarald Freudenberger *p++ = 0x04; 135755d0a513SHarald Freudenberger *p++ = 0; 135855d0a513SHarald Freudenberger 135955d0a513SHarald Freudenberger /* reply cprb and payload */ 136055d0a513SHarald Freudenberger rep = alloc_cprb(sizeof(struct wk_rep_pl)); 136155d0a513SHarald Freudenberger if (!rep) 136255d0a513SHarald Freudenberger goto out; 136355d0a513SHarald Freudenberger rep_pl = (struct wk_rep_pl *)(((u8 *)rep) + sizeof(*rep)); 136455d0a513SHarald Freudenberger 136555d0a513SHarald Freudenberger /* urb and target */ 13662004b57cSHarald Freudenberger urb = kmalloc(sizeof(*urb), GFP_KERNEL); 136755d0a513SHarald Freudenberger if (!urb) 136855d0a513SHarald Freudenberger goto out; 136955d0a513SHarald Freudenberger target.ap_id = card; 137055d0a513SHarald Freudenberger target.dom_id = domain; 137155d0a513SHarald Freudenberger prep_urb(urb, &target, 1, 137255d0a513SHarald Freudenberger req, sizeof(*req) + req_pl_size, 137355d0a513SHarald Freudenberger rep, sizeof(*rep) + sizeof(*rep_pl)); 137455d0a513SHarald Freudenberger 137552f72febSHarald Freudenberger rc = zcrypt_send_ep11_cprb(urb); 137655d0a513SHarald Freudenberger if (rc) { 137788e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n", 137855d0a513SHarald Freudenberger __func__, (int)card, (int)domain, rc); 137955d0a513SHarald Freudenberger goto out; 138055d0a513SHarald Freudenberger } 138155d0a513SHarald Freudenberger 1382c0e983b6SHarald Freudenberger /* check ep11 reply cprb */ 1383c0e983b6SHarald Freudenberger rc = check_reply_cprb(rep, __func__); 1384c0e983b6SHarald Freudenberger if (rc) 1385c0e983b6SHarald Freudenberger goto out; 1386c0e983b6SHarald Freudenberger 1387c0e983b6SHarald Freudenberger /* check payload */ 138855d0a513SHarald Freudenberger rc = check_reply_pl((u8 *)rep_pl, __func__); 138955d0a513SHarald Freudenberger if (rc) 139055d0a513SHarald Freudenberger goto out; 139155d0a513SHarald Freudenberger if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) { 139288e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s unknown reply data format\n", __func__); 139355d0a513SHarald Freudenberger rc = -EIO; 139455d0a513SHarald Freudenberger goto out; 139555d0a513SHarald Freudenberger } 139655d0a513SHarald Freudenberger if (rep_pl->data_len > *datasize) { 139788e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s mismatch reply data len / data buffer len\n", 139855d0a513SHarald Freudenberger __func__); 139955d0a513SHarald Freudenberger rc = -ENOSPC; 140055d0a513SHarald Freudenberger goto out; 140155d0a513SHarald Freudenberger } 140255d0a513SHarald Freudenberger 140355d0a513SHarald Freudenberger /* copy the data from the cprb to the data buffer */ 140455d0a513SHarald Freudenberger memcpy(databuf, rep_pl->data, rep_pl->data_len); 140555d0a513SHarald Freudenberger *datasize = rep_pl->data_len; 140655d0a513SHarald Freudenberger 140755d0a513SHarald Freudenberger out: 140855d0a513SHarald Freudenberger kfree(req); 140955d0a513SHarald Freudenberger kfree(rep); 141055d0a513SHarald Freudenberger kfree(urb); 141155d0a513SHarald Freudenberger return rc; 141255d0a513SHarald Freudenberger } 141355d0a513SHarald Freudenberger 141455d0a513SHarald Freudenberger int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags, 1415da2863f1SHolger Dengler const u8 *clrkey, u8 *keybuf, size_t *keybufsize, 1416da2863f1SHolger Dengler u32 keytype) 141755d0a513SHarald Freudenberger { 141855d0a513SHarald Freudenberger int rc; 141955d0a513SHarald Freudenberger u8 encbuf[64], *kek = NULL; 142055d0a513SHarald Freudenberger size_t clrkeylen, keklen, encbuflen = sizeof(encbuf); 142155d0a513SHarald Freudenberger 14222004b57cSHarald Freudenberger if (keybitsize == 128 || keybitsize == 192 || keybitsize == 256) { 142355d0a513SHarald Freudenberger clrkeylen = keybitsize / 8; 14242004b57cSHarald Freudenberger } else { 142588e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s unknown/unsupported keybitsize %d\n", 142655d0a513SHarald Freudenberger __func__, keybitsize); 142755d0a513SHarald Freudenberger return -EINVAL; 142855d0a513SHarald Freudenberger } 142955d0a513SHarald Freudenberger 143055d0a513SHarald Freudenberger /* allocate memory for the temp kek */ 143155d0a513SHarald Freudenberger keklen = MAXEP11AESKEYBLOBSIZE; 143255d0a513SHarald Freudenberger kek = kmalloc(keklen, GFP_ATOMIC); 143355d0a513SHarald Freudenberger if (!kek) { 143455d0a513SHarald Freudenberger rc = -ENOMEM; 143555d0a513SHarald Freudenberger goto out; 143655d0a513SHarald Freudenberger } 143755d0a513SHarald Freudenberger 143855d0a513SHarald Freudenberger /* Step 1: generate AES 256 bit random kek key */ 1439fb249ce7SHolger Dengler rc = _ep11_genaeskey(card, domain, 256, 144005ccaca0SGeert Uytterhoeven 0x00006c00, /* EN/DECRYPT, WRAP/UNWRAP */ 144155d0a513SHarald Freudenberger kek, &keklen); 144255d0a513SHarald Freudenberger if (rc) { 144388e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s generate kek key failed, rc=%d\n", 144455d0a513SHarald Freudenberger __func__, rc); 144555d0a513SHarald Freudenberger goto out; 144655d0a513SHarald Freudenberger } 144755d0a513SHarald Freudenberger 144855d0a513SHarald Freudenberger /* Step 2: encrypt clear key value with the kek key */ 144955d0a513SHarald Freudenberger rc = ep11_cryptsingle(card, domain, 0, 0, def_iv, kek, keklen, 145055d0a513SHarald Freudenberger clrkey, clrkeylen, encbuf, &encbuflen); 145155d0a513SHarald Freudenberger if (rc) { 145288e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s encrypting key value with kek key failed, rc=%d\n", 145355d0a513SHarald Freudenberger __func__, rc); 145455d0a513SHarald Freudenberger goto out; 145555d0a513SHarald Freudenberger } 145655d0a513SHarald Freudenberger 145755d0a513SHarald Freudenberger /* Step 3: import the encrypted key value as a new key */ 145855d0a513SHarald Freudenberger rc = ep11_unwrapkey(card, domain, kek, keklen, 145955d0a513SHarald Freudenberger encbuf, encbuflen, 0, def_iv, 1460da2863f1SHolger Dengler keybitsize, 0, keybuf, keybufsize, keytype); 146155d0a513SHarald Freudenberger if (rc) { 146288e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s importing key value as new key failed,, rc=%d\n", 146355d0a513SHarald Freudenberger __func__, rc); 146455d0a513SHarald Freudenberger goto out; 146555d0a513SHarald Freudenberger } 146655d0a513SHarald Freudenberger 146755d0a513SHarald Freudenberger out: 146855d0a513SHarald Freudenberger kfree(kek); 146955d0a513SHarald Freudenberger return rc; 147055d0a513SHarald Freudenberger } 147155d0a513SHarald Freudenberger EXPORT_SYMBOL(ep11_clr2keyblob); 147255d0a513SHarald Freudenberger 1473d1fdfb0bSHolger Dengler int ep11_kblob2protkey(u16 card, u16 dom, 1474d1fdfb0bSHolger Dengler const u8 *keyblob, size_t keybloblen, 147555d0a513SHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 147655d0a513SHarald Freudenberger { 1477d1fdfb0bSHolger Dengler struct ep11kblob_header *hdr; 1478d1fdfb0bSHolger Dengler struct ep11keyblob *key; 1479fa6999e3SHarald Freudenberger size_t wkbuflen, keylen; 148055d0a513SHarald Freudenberger struct wk_info { 148155d0a513SHarald Freudenberger u16 version; 148255d0a513SHarald Freudenberger u8 res1[16]; 148355d0a513SHarald Freudenberger u32 pkeytype; 148455d0a513SHarald Freudenberger u32 pkeybitsize; 148555d0a513SHarald Freudenberger u64 pkeysize; 148655d0a513SHarald Freudenberger u8 res2[8]; 14873b42877cSHarald Freudenberger u8 pkey[]; 148855d0a513SHarald Freudenberger } __packed * wki; 1489d1fdfb0bSHolger Dengler u8 *wkbuf = NULL; 1490d1fdfb0bSHolger Dengler int rc = -EIO; 1491fa6999e3SHarald Freudenberger 1492d1fdfb0bSHolger Dengler if (ep11_kb_decode((u8 *)keyblob, keybloblen, &hdr, NULL, &key, &keylen)) 1493fa6999e3SHarald Freudenberger return -EINVAL; 1494d1fdfb0bSHolger Dengler 1495d1fdfb0bSHolger Dengler if (hdr->version == TOKVER_EP11_AES) { 1496d1fdfb0bSHolger Dengler /* wipe overlayed header */ 1497d1fdfb0bSHolger Dengler memset(hdr, 0, sizeof(*hdr)); 14982004b57cSHarald Freudenberger } 1499d1fdfb0bSHolger Dengler /* !!! hdr is no longer a valid header !!! */ 150055d0a513SHarald Freudenberger 150155d0a513SHarald Freudenberger /* alloc temp working buffer */ 1502fa6999e3SHarald Freudenberger wkbuflen = (keylen + AES_BLOCK_SIZE) & (~(AES_BLOCK_SIZE - 1)); 150355d0a513SHarald Freudenberger wkbuf = kmalloc(wkbuflen, GFP_ATOMIC); 150455d0a513SHarald Freudenberger if (!wkbuf) 150555d0a513SHarald Freudenberger return -ENOMEM; 150655d0a513SHarald Freudenberger 150755d0a513SHarald Freudenberger /* ep11 secure key -> protected key + info */ 1508d1fdfb0bSHolger Dengler rc = _ep11_wrapkey(card, dom, (u8 *)key, keylen, 150955d0a513SHarald Freudenberger 0, def_iv, wkbuf, &wkbuflen); 151055d0a513SHarald Freudenberger if (rc) { 151188e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s rewrapping ep11 key to pkey failed, rc=%d\n", 151255d0a513SHarald Freudenberger __func__, rc); 151355d0a513SHarald Freudenberger goto out; 151455d0a513SHarald Freudenberger } 151555d0a513SHarald Freudenberger wki = (struct wk_info *)wkbuf; 151655d0a513SHarald Freudenberger 151755d0a513SHarald Freudenberger /* check struct version and pkey type */ 1518fa6999e3SHarald Freudenberger if (wki->version != 1 || wki->pkeytype < 1 || wki->pkeytype > 5) { 151988e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s wk info version %d or pkeytype %d mismatch.\n", 152055d0a513SHarald Freudenberger __func__, (int)wki->version, (int)wki->pkeytype); 152155d0a513SHarald Freudenberger rc = -EIO; 152255d0a513SHarald Freudenberger goto out; 152355d0a513SHarald Freudenberger } 152455d0a513SHarald Freudenberger 1525fa6999e3SHarald Freudenberger /* check protected key type field */ 1526fa6999e3SHarald Freudenberger switch (wki->pkeytype) { 1527fa6999e3SHarald Freudenberger case 1: /* AES */ 152855d0a513SHarald Freudenberger switch (wki->pkeysize) { 152955d0a513SHarald Freudenberger case 16 + 32: 153055d0a513SHarald Freudenberger /* AES 128 protected key */ 153155d0a513SHarald Freudenberger if (protkeytype) 153255d0a513SHarald Freudenberger *protkeytype = PKEY_KEYTYPE_AES_128; 153355d0a513SHarald Freudenberger break; 153455d0a513SHarald Freudenberger case 24 + 32: 153555d0a513SHarald Freudenberger /* AES 192 protected key */ 153655d0a513SHarald Freudenberger if (protkeytype) 153755d0a513SHarald Freudenberger *protkeytype = PKEY_KEYTYPE_AES_192; 153855d0a513SHarald Freudenberger break; 153955d0a513SHarald Freudenberger case 32 + 32: 154055d0a513SHarald Freudenberger /* AES 256 protected key */ 154155d0a513SHarald Freudenberger if (protkeytype) 154255d0a513SHarald Freudenberger *protkeytype = PKEY_KEYTYPE_AES_256; 154355d0a513SHarald Freudenberger break; 154455d0a513SHarald Freudenberger default: 154588e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s unknown/unsupported AES pkeysize %d\n", 154655d0a513SHarald Freudenberger __func__, (int)wki->pkeysize); 154755d0a513SHarald Freudenberger rc = -EIO; 154855d0a513SHarald Freudenberger goto out; 154955d0a513SHarald Freudenberger } 1550fa6999e3SHarald Freudenberger break; 1551fa6999e3SHarald Freudenberger case 3: /* EC-P */ 1552fa6999e3SHarald Freudenberger case 4: /* EC-ED */ 1553fa6999e3SHarald Freudenberger case 5: /* EC-BP */ 1554fa6999e3SHarald Freudenberger if (protkeytype) 1555fa6999e3SHarald Freudenberger *protkeytype = PKEY_KEYTYPE_ECC; 1556fa6999e3SHarald Freudenberger break; 1557fa6999e3SHarald Freudenberger case 2: /* TDES */ 1558fa6999e3SHarald Freudenberger default: 155988e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s unknown/unsupported key type %d\n", 1560fa6999e3SHarald Freudenberger __func__, (int)wki->pkeytype); 1561fa6999e3SHarald Freudenberger rc = -EIO; 1562fa6999e3SHarald Freudenberger goto out; 1563fa6999e3SHarald Freudenberger } 1564fa6999e3SHarald Freudenberger 1565cada938aSHeiko Carstens /* copy the translated protected key */ 1566fa6999e3SHarald Freudenberger if (wki->pkeysize > *protkeylen) { 156788e4c0daSHarald Freudenberger ZCRYPT_DBF_ERR("%s wk info pkeysize %llu > protkeysize %u\n", 1568fa6999e3SHarald Freudenberger __func__, wki->pkeysize, *protkeylen); 1569fa6999e3SHarald Freudenberger rc = -EINVAL; 1570fa6999e3SHarald Freudenberger goto out; 1571fa6999e3SHarald Freudenberger } 157255d0a513SHarald Freudenberger memcpy(protkey, wki->pkey, wki->pkeysize); 1573fa6999e3SHarald Freudenberger *protkeylen = wki->pkeysize; 157455d0a513SHarald Freudenberger 157555d0a513SHarald Freudenberger out: 157655d0a513SHarald Freudenberger kfree(wkbuf); 157755d0a513SHarald Freudenberger return rc; 157855d0a513SHarald Freudenberger } 1579fa6999e3SHarald Freudenberger EXPORT_SYMBOL(ep11_kblob2protkey); 158055d0a513SHarald Freudenberger 158155d0a513SHarald Freudenberger int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain, 158255d0a513SHarald Freudenberger int minhwtype, int minapi, const u8 *wkvp) 158355d0a513SHarald Freudenberger { 158455d0a513SHarald Freudenberger struct zcrypt_device_status_ext *device_status; 158555d0a513SHarald Freudenberger u32 *_apqns = NULL, _nr_apqns = 0; 158655d0a513SHarald Freudenberger int i, card, dom, rc = -ENOMEM; 158755d0a513SHarald Freudenberger struct ep11_domain_info edi; 158855d0a513SHarald Freudenberger struct ep11_card_info eci; 158955d0a513SHarald Freudenberger 159055d0a513SHarald Freudenberger /* fetch status of all crypto cards */ 1591*c1248638SHeiko Carstens device_status = kvcalloc(MAX_ZDEV_ENTRIES_EXT, 159255d0a513SHarald Freudenberger sizeof(struct zcrypt_device_status_ext), 159355d0a513SHarald Freudenberger GFP_KERNEL); 159455d0a513SHarald Freudenberger if (!device_status) 159555d0a513SHarald Freudenberger return -ENOMEM; 159655d0a513SHarald Freudenberger zcrypt_device_status_mask_ext(device_status); 159755d0a513SHarald Freudenberger 159855d0a513SHarald Freudenberger /* allocate 1k space for up to 256 apqns */ 159955d0a513SHarald Freudenberger _apqns = kmalloc_array(256, sizeof(u32), GFP_KERNEL); 160055d0a513SHarald Freudenberger if (!_apqns) { 160134515df2SHarald Freudenberger kvfree(device_status); 160255d0a513SHarald Freudenberger return -ENOMEM; 160355d0a513SHarald Freudenberger } 160455d0a513SHarald Freudenberger 160555d0a513SHarald Freudenberger /* walk through all the crypto apqnss */ 160655d0a513SHarald Freudenberger for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) { 160755d0a513SHarald Freudenberger card = AP_QID_CARD(device_status[i].qid); 160855d0a513SHarald Freudenberger dom = AP_QID_QUEUE(device_status[i].qid); 160955d0a513SHarald Freudenberger /* check online state */ 161055d0a513SHarald Freudenberger if (!device_status[i].online) 161155d0a513SHarald Freudenberger continue; 161255d0a513SHarald Freudenberger /* check for ep11 functions */ 161355d0a513SHarald Freudenberger if (!(device_status[i].functions & 0x01)) 161455d0a513SHarald Freudenberger continue; 161555d0a513SHarald Freudenberger /* check cardnr */ 161655d0a513SHarald Freudenberger if (cardnr != 0xFFFF && card != cardnr) 161755d0a513SHarald Freudenberger continue; 161855d0a513SHarald Freudenberger /* check domain */ 161955d0a513SHarald Freudenberger if (domain != 0xFFFF && dom != domain) 162055d0a513SHarald Freudenberger continue; 162155d0a513SHarald Freudenberger /* check min hardware type */ 162255d0a513SHarald Freudenberger if (minhwtype && device_status[i].hwtype < minhwtype) 162355d0a513SHarald Freudenberger continue; 162455d0a513SHarald Freudenberger /* check min api version if given */ 162555d0a513SHarald Freudenberger if (minapi > 0) { 162655d0a513SHarald Freudenberger if (ep11_get_card_info(card, &eci, 0)) 162755d0a513SHarald Freudenberger continue; 162855d0a513SHarald Freudenberger if (minapi > eci.API_ord_nr) 162955d0a513SHarald Freudenberger continue; 163055d0a513SHarald Freudenberger } 163155d0a513SHarald Freudenberger /* check wkvp if given */ 163255d0a513SHarald Freudenberger if (wkvp) { 163355d0a513SHarald Freudenberger if (ep11_get_domain_info(card, dom, &edi)) 163455d0a513SHarald Freudenberger continue; 163555d0a513SHarald Freudenberger if (edi.cur_wk_state != '1') 163655d0a513SHarald Freudenberger continue; 163755d0a513SHarald Freudenberger if (memcmp(wkvp, edi.cur_wkvp, 16)) 163855d0a513SHarald Freudenberger continue; 163955d0a513SHarald Freudenberger } 164055d0a513SHarald Freudenberger /* apqn passed all filtering criterons, add to the array */ 164155d0a513SHarald Freudenberger if (_nr_apqns < 256) 164255d0a513SHarald Freudenberger _apqns[_nr_apqns++] = (((u16)card) << 16) | ((u16)dom); 164355d0a513SHarald Freudenberger } 164455d0a513SHarald Freudenberger 164555d0a513SHarald Freudenberger /* nothing found ? */ 164655d0a513SHarald Freudenberger if (!_nr_apqns) { 164755d0a513SHarald Freudenberger kfree(_apqns); 164855d0a513SHarald Freudenberger rc = -ENODEV; 164955d0a513SHarald Freudenberger } else { 165055d0a513SHarald Freudenberger /* no re-allocation, simple return the _apqns array */ 165155d0a513SHarald Freudenberger *apqns = _apqns; 165255d0a513SHarald Freudenberger *nr_apqns = _nr_apqns; 165355d0a513SHarald Freudenberger rc = 0; 165455d0a513SHarald Freudenberger } 165555d0a513SHarald Freudenberger 165634515df2SHarald Freudenberger kvfree(device_status); 165755d0a513SHarald Freudenberger return rc; 165855d0a513SHarald Freudenberger } 165955d0a513SHarald Freudenberger EXPORT_SYMBOL(ep11_findcard2); 166055d0a513SHarald Freudenberger 16617384eb72SHarald Freudenberger void __exit zcrypt_ep11misc_exit(void) 16627384eb72SHarald Freudenberger { 16637384eb72SHarald Freudenberger card_cache_free(); 16647384eb72SHarald Freudenberger } 1665