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 277384eb72SHarald Freudenberger #define DEBUG_DBG(...) ZCRYPT_DBF(DBF_DEBUG, ##__VA_ARGS__) 287384eb72SHarald Freudenberger #define DEBUG_INFO(...) ZCRYPT_DBF(DBF_INFO, ##__VA_ARGS__) 297384eb72SHarald Freudenberger #define DEBUG_WARN(...) ZCRYPT_DBF(DBF_WARN, ##__VA_ARGS__) 307384eb72SHarald Freudenberger #define DEBUG_ERR(...) ZCRYPT_DBF(DBF_ERR, ##__VA_ARGS__) 317384eb72SHarald Freudenberger 32*386cb81eSHolger Dengler #define EP11_PINBLOB_V1_BYTES 56 33*386cb81eSHolger Dengler 3455d0a513SHarald Freudenberger /* default iv used here */ 3555d0a513SHarald Freudenberger static const u8 def_iv[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 3655d0a513SHarald Freudenberger 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; 3755d0a513SHarald Freudenberger 387384eb72SHarald Freudenberger /* ep11 card info cache */ 397384eb72SHarald Freudenberger struct card_list_entry { 407384eb72SHarald Freudenberger struct list_head list; 417384eb72SHarald Freudenberger u16 cardnr; 427384eb72SHarald Freudenberger struct ep11_card_info info; 437384eb72SHarald Freudenberger }; 447384eb72SHarald Freudenberger static LIST_HEAD(card_list); 457384eb72SHarald Freudenberger static DEFINE_SPINLOCK(card_list_lock); 467384eb72SHarald Freudenberger 477384eb72SHarald Freudenberger static int card_cache_fetch(u16 cardnr, struct ep11_card_info *ci) 487384eb72SHarald Freudenberger { 497384eb72SHarald Freudenberger int rc = -ENOENT; 507384eb72SHarald Freudenberger struct card_list_entry *ptr; 517384eb72SHarald Freudenberger 527384eb72SHarald Freudenberger spin_lock_bh(&card_list_lock); 537384eb72SHarald Freudenberger list_for_each_entry(ptr, &card_list, list) { 547384eb72SHarald Freudenberger if (ptr->cardnr == cardnr) { 557384eb72SHarald Freudenberger memcpy(ci, &ptr->info, sizeof(*ci)); 567384eb72SHarald Freudenberger rc = 0; 577384eb72SHarald Freudenberger break; 587384eb72SHarald Freudenberger } 597384eb72SHarald Freudenberger } 607384eb72SHarald Freudenberger spin_unlock_bh(&card_list_lock); 617384eb72SHarald Freudenberger 627384eb72SHarald Freudenberger return rc; 637384eb72SHarald Freudenberger } 647384eb72SHarald Freudenberger 657384eb72SHarald Freudenberger static void card_cache_update(u16 cardnr, const struct ep11_card_info *ci) 667384eb72SHarald Freudenberger { 677384eb72SHarald Freudenberger int found = 0; 687384eb72SHarald Freudenberger struct card_list_entry *ptr; 697384eb72SHarald Freudenberger 707384eb72SHarald Freudenberger spin_lock_bh(&card_list_lock); 717384eb72SHarald Freudenberger list_for_each_entry(ptr, &card_list, list) { 727384eb72SHarald Freudenberger if (ptr->cardnr == cardnr) { 737384eb72SHarald Freudenberger memcpy(&ptr->info, ci, sizeof(*ci)); 747384eb72SHarald Freudenberger found = 1; 757384eb72SHarald Freudenberger break; 767384eb72SHarald Freudenberger } 777384eb72SHarald Freudenberger } 787384eb72SHarald Freudenberger if (!found) { 797384eb72SHarald Freudenberger ptr = kmalloc(sizeof(*ptr), GFP_ATOMIC); 807384eb72SHarald Freudenberger if (!ptr) { 817384eb72SHarald Freudenberger spin_unlock_bh(&card_list_lock); 827384eb72SHarald Freudenberger return; 837384eb72SHarald Freudenberger } 847384eb72SHarald Freudenberger ptr->cardnr = cardnr; 857384eb72SHarald Freudenberger memcpy(&ptr->info, ci, sizeof(*ci)); 867384eb72SHarald Freudenberger list_add(&ptr->list, &card_list); 877384eb72SHarald Freudenberger } 887384eb72SHarald Freudenberger spin_unlock_bh(&card_list_lock); 897384eb72SHarald Freudenberger } 907384eb72SHarald Freudenberger 917384eb72SHarald Freudenberger static void card_cache_scrub(u16 cardnr) 927384eb72SHarald Freudenberger { 937384eb72SHarald Freudenberger struct card_list_entry *ptr; 947384eb72SHarald Freudenberger 957384eb72SHarald Freudenberger spin_lock_bh(&card_list_lock); 967384eb72SHarald Freudenberger list_for_each_entry(ptr, &card_list, list) { 977384eb72SHarald Freudenberger if (ptr->cardnr == cardnr) { 987384eb72SHarald Freudenberger list_del(&ptr->list); 997384eb72SHarald Freudenberger kfree(ptr); 1007384eb72SHarald Freudenberger break; 1017384eb72SHarald Freudenberger } 1027384eb72SHarald Freudenberger } 1037384eb72SHarald Freudenberger spin_unlock_bh(&card_list_lock); 1047384eb72SHarald Freudenberger } 1057384eb72SHarald Freudenberger 1067384eb72SHarald Freudenberger static void __exit card_cache_free(void) 1077384eb72SHarald Freudenberger { 1087384eb72SHarald Freudenberger struct card_list_entry *ptr, *pnext; 1097384eb72SHarald Freudenberger 1107384eb72SHarald Freudenberger spin_lock_bh(&card_list_lock); 1117384eb72SHarald Freudenberger list_for_each_entry_safe(ptr, pnext, &card_list, list) { 1127384eb72SHarald Freudenberger list_del(&ptr->list); 1137384eb72SHarald Freudenberger kfree(ptr); 1147384eb72SHarald Freudenberger } 1157384eb72SHarald Freudenberger spin_unlock_bh(&card_list_lock); 1167384eb72SHarald Freudenberger } 1177384eb72SHarald Freudenberger 118fb249ce7SHolger Dengler static int ep11_kb_split(const u8 *kb, size_t kblen, u32 kbver, 119fb249ce7SHolger Dengler struct ep11kblob_header **kbhdr, size_t *kbhdrsize, 120fb249ce7SHolger Dengler u8 **kbpl, size_t *kbplsize) 121fb249ce7SHolger Dengler { 122fb249ce7SHolger Dengler struct ep11kblob_header *hdr = NULL; 123fb249ce7SHolger Dengler size_t hdrsize, plsize = 0; 124fb249ce7SHolger Dengler int rc = -EINVAL; 125fb249ce7SHolger Dengler u8 *pl = NULL; 126fb249ce7SHolger Dengler 127fb249ce7SHolger Dengler if (kblen < sizeof(struct ep11kblob_header)) 128fb249ce7SHolger Dengler goto out; 129fb249ce7SHolger Dengler hdr = (struct ep11kblob_header *)kb; 130fb249ce7SHolger Dengler 131fb249ce7SHolger Dengler switch (kbver) { 132fb249ce7SHolger Dengler case TOKVER_EP11_AES: 133fb249ce7SHolger Dengler /* header overlays the payload */ 134fb249ce7SHolger Dengler hdrsize = 0; 135fb249ce7SHolger Dengler break; 136fb249ce7SHolger Dengler case TOKVER_EP11_ECC_WITH_HEADER: 137fb249ce7SHolger Dengler case TOKVER_EP11_AES_WITH_HEADER: 138fb249ce7SHolger Dengler /* payload starts after the header */ 139fb249ce7SHolger Dengler hdrsize = sizeof(struct ep11kblob_header); 140fb249ce7SHolger Dengler break; 141fb249ce7SHolger Dengler default: 142fb249ce7SHolger Dengler goto out; 143fb249ce7SHolger Dengler } 144fb249ce7SHolger Dengler 145fb249ce7SHolger Dengler plsize = kblen - hdrsize; 146fb249ce7SHolger Dengler pl = (u8 *)kb + hdrsize; 147fb249ce7SHolger Dengler 148fb249ce7SHolger Dengler if (kbhdr) 149fb249ce7SHolger Dengler *kbhdr = hdr; 150fb249ce7SHolger Dengler if (kbhdrsize) 151fb249ce7SHolger Dengler *kbhdrsize = hdrsize; 152fb249ce7SHolger Dengler if (kbpl) 153fb249ce7SHolger Dengler *kbpl = pl; 154fb249ce7SHolger Dengler if (kbplsize) 155fb249ce7SHolger Dengler *kbplsize = plsize; 156fb249ce7SHolger Dengler 157fb249ce7SHolger Dengler rc = 0; 158fb249ce7SHolger Dengler out: 159fb249ce7SHolger Dengler return rc; 160fb249ce7SHolger Dengler } 161fb249ce7SHolger Dengler 162d1fdfb0bSHolger Dengler static int ep11_kb_decode(const u8 *kb, size_t kblen, 163d1fdfb0bSHolger Dengler struct ep11kblob_header **kbhdr, size_t *kbhdrsize, 164d1fdfb0bSHolger Dengler struct ep11keyblob **kbpl, size_t *kbplsize) 165d1fdfb0bSHolger Dengler { 166d1fdfb0bSHolger Dengler struct ep11kblob_header *tmph, *hdr = NULL; 167d1fdfb0bSHolger Dengler size_t hdrsize = 0, plsize = 0; 168d1fdfb0bSHolger Dengler struct ep11keyblob *pl = NULL; 169d1fdfb0bSHolger Dengler int rc = -EINVAL; 170d1fdfb0bSHolger Dengler u8 *tmpp; 171d1fdfb0bSHolger Dengler 172d1fdfb0bSHolger Dengler if (kblen < sizeof(struct ep11kblob_header)) 173d1fdfb0bSHolger Dengler goto out; 174d1fdfb0bSHolger Dengler tmph = (struct ep11kblob_header *)kb; 175d1fdfb0bSHolger Dengler 176d1fdfb0bSHolger Dengler if (tmph->type != TOKTYPE_NON_CCA && 177d1fdfb0bSHolger Dengler tmph->len > kblen) 178d1fdfb0bSHolger Dengler goto out; 179d1fdfb0bSHolger Dengler 180d1fdfb0bSHolger Dengler if (ep11_kb_split(kb, kblen, tmph->version, 181d1fdfb0bSHolger Dengler &hdr, &hdrsize, &tmpp, &plsize)) 182d1fdfb0bSHolger Dengler goto out; 183d1fdfb0bSHolger Dengler 184d1fdfb0bSHolger Dengler if (plsize < sizeof(struct ep11keyblob)) 185d1fdfb0bSHolger Dengler goto out; 186d1fdfb0bSHolger Dengler 187d1fdfb0bSHolger Dengler if (!is_ep11_keyblob(tmpp)) 188d1fdfb0bSHolger Dengler goto out; 189d1fdfb0bSHolger Dengler 190d1fdfb0bSHolger Dengler pl = (struct ep11keyblob *)tmpp; 191d1fdfb0bSHolger Dengler plsize = hdr->len - hdrsize; 192d1fdfb0bSHolger Dengler 193d1fdfb0bSHolger Dengler if (kbhdr) 194d1fdfb0bSHolger Dengler *kbhdr = hdr; 195d1fdfb0bSHolger Dengler if (kbhdrsize) 196d1fdfb0bSHolger Dengler *kbhdrsize = hdrsize; 197d1fdfb0bSHolger Dengler if (kbpl) 198d1fdfb0bSHolger Dengler *kbpl = pl; 199d1fdfb0bSHolger Dengler if (kbplsize) 200d1fdfb0bSHolger Dengler *kbplsize = plsize; 201d1fdfb0bSHolger Dengler 202d1fdfb0bSHolger Dengler rc = 0; 203d1fdfb0bSHolger Dengler out: 204d1fdfb0bSHolger Dengler return rc; 205d1fdfb0bSHolger Dengler } 206d1fdfb0bSHolger Dengler 207d1fdfb0bSHolger Dengler /* 208d1fdfb0bSHolger Dengler * For valid ep11 keyblobs, returns a reference to the wrappingkey verification 209d1fdfb0bSHolger Dengler * pattern. Otherwise NULL. 210d1fdfb0bSHolger Dengler */ 211d1fdfb0bSHolger Dengler const u8 *ep11_kb_wkvp(const u8 *keyblob, size_t keybloblen) 212d1fdfb0bSHolger Dengler { 213d1fdfb0bSHolger Dengler struct ep11keyblob *kb; 214d1fdfb0bSHolger Dengler 215d1fdfb0bSHolger Dengler if (ep11_kb_decode(keyblob, keybloblen, NULL, NULL, &kb, NULL)) 216d1fdfb0bSHolger Dengler return NULL; 217d1fdfb0bSHolger Dengler return kb->wkvp; 218d1fdfb0bSHolger Dengler } 219d1fdfb0bSHolger Dengler EXPORT_SYMBOL(ep11_kb_wkvp); 220d1fdfb0bSHolger Dengler 2217384eb72SHarald Freudenberger /* 222fa6999e3SHarald Freudenberger * Simple check if the key blob is a valid EP11 AES key blob with header. 22355d0a513SHarald Freudenberger */ 224fa6999e3SHarald Freudenberger int ep11_check_aes_key_with_hdr(debug_info_t *dbg, int dbflvl, 225fa6999e3SHarald Freudenberger const u8 *key, size_t keylen, int checkcpacfexp) 226fa6999e3SHarald Freudenberger { 227fa6999e3SHarald Freudenberger struct ep11kblob_header *hdr = (struct ep11kblob_header *)key; 228fa6999e3SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)(key + sizeof(*hdr)); 229fa6999e3SHarald Freudenberger 230fa6999e3SHarald Freudenberger #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__) 231fa6999e3SHarald Freudenberger 232fa6999e3SHarald Freudenberger if (keylen < sizeof(*hdr) + sizeof(*kb)) { 233fa6999e3SHarald Freudenberger DBF("%s key check failed, keylen %zu < %zu\n", 234fa6999e3SHarald Freudenberger __func__, keylen, sizeof(*hdr) + sizeof(*kb)); 235fa6999e3SHarald Freudenberger return -EINVAL; 236fa6999e3SHarald Freudenberger } 237fa6999e3SHarald Freudenberger 238fa6999e3SHarald Freudenberger if (hdr->type != TOKTYPE_NON_CCA) { 239fa6999e3SHarald Freudenberger if (dbg) 240fa6999e3SHarald Freudenberger DBF("%s key check failed, type 0x%02x != 0x%02x\n", 241fa6999e3SHarald Freudenberger __func__, (int)hdr->type, TOKTYPE_NON_CCA); 242fa6999e3SHarald Freudenberger return -EINVAL; 243fa6999e3SHarald Freudenberger } 244fa6999e3SHarald Freudenberger if (hdr->hver != 0x00) { 245fa6999e3SHarald Freudenberger if (dbg) 246fa6999e3SHarald Freudenberger DBF("%s key check failed, header version 0x%02x != 0x00\n", 247fa6999e3SHarald Freudenberger __func__, (int)hdr->hver); 248fa6999e3SHarald Freudenberger return -EINVAL; 249fa6999e3SHarald Freudenberger } 250fa6999e3SHarald Freudenberger if (hdr->version != TOKVER_EP11_AES_WITH_HEADER) { 251fa6999e3SHarald Freudenberger if (dbg) 252fa6999e3SHarald Freudenberger DBF("%s key check failed, version 0x%02x != 0x%02x\n", 253fa6999e3SHarald Freudenberger __func__, (int)hdr->version, TOKVER_EP11_AES_WITH_HEADER); 254fa6999e3SHarald Freudenberger return -EINVAL; 255fa6999e3SHarald Freudenberger } 256fa6999e3SHarald Freudenberger if (hdr->len > keylen) { 257fa6999e3SHarald Freudenberger if (dbg) 258fa6999e3SHarald Freudenberger DBF("%s key check failed, header len %d keylen %zu mismatch\n", 259fa6999e3SHarald Freudenberger __func__, (int)hdr->len, keylen); 260fa6999e3SHarald Freudenberger return -EINVAL; 261fa6999e3SHarald Freudenberger } 262fa6999e3SHarald Freudenberger if (hdr->len < sizeof(*hdr) + sizeof(*kb)) { 263fa6999e3SHarald Freudenberger if (dbg) 264fa6999e3SHarald Freudenberger DBF("%s key check failed, header len %d < %zu\n", 265fa6999e3SHarald Freudenberger __func__, (int)hdr->len, sizeof(*hdr) + sizeof(*kb)); 266fa6999e3SHarald Freudenberger return -EINVAL; 267fa6999e3SHarald Freudenberger } 268fa6999e3SHarald Freudenberger 269fa6999e3SHarald Freudenberger if (kb->version != EP11_STRUCT_MAGIC) { 270fa6999e3SHarald Freudenberger if (dbg) 271fa6999e3SHarald Freudenberger DBF("%s key check failed, blob magic 0x%04x != 0x%04x\n", 272fa6999e3SHarald Freudenberger __func__, (int)kb->version, EP11_STRUCT_MAGIC); 273fa6999e3SHarald Freudenberger return -EINVAL; 274fa6999e3SHarald Freudenberger } 275fa6999e3SHarald Freudenberger if (checkcpacfexp && !(kb->attr & EP11_BLOB_PKEY_EXTRACTABLE)) { 276fa6999e3SHarald Freudenberger if (dbg) 277fa6999e3SHarald Freudenberger DBF("%s key check failed, PKEY_EXTRACTABLE is off\n", 278fa6999e3SHarald Freudenberger __func__); 279fa6999e3SHarald Freudenberger return -EINVAL; 280fa6999e3SHarald Freudenberger } 281fa6999e3SHarald Freudenberger 282fa6999e3SHarald Freudenberger #undef DBF 283fa6999e3SHarald Freudenberger 284fa6999e3SHarald Freudenberger return 0; 285fa6999e3SHarald Freudenberger } 286fa6999e3SHarald Freudenberger EXPORT_SYMBOL(ep11_check_aes_key_with_hdr); 287fa6999e3SHarald Freudenberger 288fa6999e3SHarald Freudenberger /* 289fa6999e3SHarald Freudenberger * Simple check if the key blob is a valid EP11 ECC key blob with header. 290fa6999e3SHarald Freudenberger */ 291fa6999e3SHarald Freudenberger int ep11_check_ecc_key_with_hdr(debug_info_t *dbg, int dbflvl, 292fa6999e3SHarald Freudenberger const u8 *key, size_t keylen, int checkcpacfexp) 293fa6999e3SHarald Freudenberger { 294fa6999e3SHarald Freudenberger struct ep11kblob_header *hdr = (struct ep11kblob_header *)key; 295fa6999e3SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)(key + sizeof(*hdr)); 296fa6999e3SHarald Freudenberger 297fa6999e3SHarald Freudenberger #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__) 298fa6999e3SHarald Freudenberger 299fa6999e3SHarald Freudenberger if (keylen < sizeof(*hdr) + sizeof(*kb)) { 300fa6999e3SHarald Freudenberger DBF("%s key check failed, keylen %zu < %zu\n", 301fa6999e3SHarald Freudenberger __func__, keylen, sizeof(*hdr) + sizeof(*kb)); 302fa6999e3SHarald Freudenberger return -EINVAL; 303fa6999e3SHarald Freudenberger } 304fa6999e3SHarald Freudenberger 305fa6999e3SHarald Freudenberger if (hdr->type != TOKTYPE_NON_CCA) { 306fa6999e3SHarald Freudenberger if (dbg) 307fa6999e3SHarald Freudenberger DBF("%s key check failed, type 0x%02x != 0x%02x\n", 308fa6999e3SHarald Freudenberger __func__, (int)hdr->type, TOKTYPE_NON_CCA); 309fa6999e3SHarald Freudenberger return -EINVAL; 310fa6999e3SHarald Freudenberger } 311fa6999e3SHarald Freudenberger if (hdr->hver != 0x00) { 312fa6999e3SHarald Freudenberger if (dbg) 313fa6999e3SHarald Freudenberger DBF("%s key check failed, header version 0x%02x != 0x00\n", 314fa6999e3SHarald Freudenberger __func__, (int)hdr->hver); 315fa6999e3SHarald Freudenberger return -EINVAL; 316fa6999e3SHarald Freudenberger } 317fa6999e3SHarald Freudenberger if (hdr->version != TOKVER_EP11_ECC_WITH_HEADER) { 318fa6999e3SHarald Freudenberger if (dbg) 319fa6999e3SHarald Freudenberger DBF("%s key check failed, version 0x%02x != 0x%02x\n", 320fa6999e3SHarald Freudenberger __func__, (int)hdr->version, TOKVER_EP11_ECC_WITH_HEADER); 321fa6999e3SHarald Freudenberger return -EINVAL; 322fa6999e3SHarald Freudenberger } 323fa6999e3SHarald Freudenberger if (hdr->len > keylen) { 324fa6999e3SHarald Freudenberger if (dbg) 325fa6999e3SHarald Freudenberger DBF("%s key check failed, header len %d keylen %zu mismatch\n", 326fa6999e3SHarald Freudenberger __func__, (int)hdr->len, keylen); 327fa6999e3SHarald Freudenberger return -EINVAL; 328fa6999e3SHarald Freudenberger } 329fa6999e3SHarald Freudenberger if (hdr->len < sizeof(*hdr) + sizeof(*kb)) { 330fa6999e3SHarald Freudenberger if (dbg) 331fa6999e3SHarald Freudenberger DBF("%s key check failed, header len %d < %zu\n", 332fa6999e3SHarald Freudenberger __func__, (int)hdr->len, sizeof(*hdr) + sizeof(*kb)); 333fa6999e3SHarald Freudenberger return -EINVAL; 334fa6999e3SHarald Freudenberger } 335fa6999e3SHarald Freudenberger 336fa6999e3SHarald Freudenberger if (kb->version != EP11_STRUCT_MAGIC) { 337fa6999e3SHarald Freudenberger if (dbg) 338fa6999e3SHarald Freudenberger DBF("%s key check failed, blob magic 0x%04x != 0x%04x\n", 339fa6999e3SHarald Freudenberger __func__, (int)kb->version, EP11_STRUCT_MAGIC); 340fa6999e3SHarald Freudenberger return -EINVAL; 341fa6999e3SHarald Freudenberger } 342fa6999e3SHarald Freudenberger if (checkcpacfexp && !(kb->attr & EP11_BLOB_PKEY_EXTRACTABLE)) { 343fa6999e3SHarald Freudenberger if (dbg) 344fa6999e3SHarald Freudenberger DBF("%s key check failed, PKEY_EXTRACTABLE is off\n", 345fa6999e3SHarald Freudenberger __func__); 346fa6999e3SHarald Freudenberger return -EINVAL; 347fa6999e3SHarald Freudenberger } 348fa6999e3SHarald Freudenberger 349fa6999e3SHarald Freudenberger #undef DBF 350fa6999e3SHarald Freudenberger 351fa6999e3SHarald Freudenberger return 0; 352fa6999e3SHarald Freudenberger } 353fa6999e3SHarald Freudenberger EXPORT_SYMBOL(ep11_check_ecc_key_with_hdr); 354fa6999e3SHarald Freudenberger 355fa6999e3SHarald Freudenberger /* 356fa6999e3SHarald Freudenberger * Simple check if the key blob is a valid EP11 AES key blob with 357fa6999e3SHarald Freudenberger * the header in the session field (old style EP11 AES key). 358fa6999e3SHarald Freudenberger */ 359fa6999e3SHarald Freudenberger int ep11_check_aes_key(debug_info_t *dbg, int dbflvl, 360fa6999e3SHarald Freudenberger const u8 *key, size_t keylen, int checkcpacfexp) 36155d0a513SHarald Freudenberger { 36255d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 36355d0a513SHarald Freudenberger 36455d0a513SHarald Freudenberger #define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__) 36555d0a513SHarald Freudenberger 366fa6999e3SHarald Freudenberger if (keylen < sizeof(*kb)) { 367fa6999e3SHarald Freudenberger DBF("%s key check failed, keylen %zu < %zu\n", 368fa6999e3SHarald Freudenberger __func__, keylen, sizeof(*kb)); 369fa6999e3SHarald Freudenberger return -EINVAL; 370fa6999e3SHarald Freudenberger } 371fa6999e3SHarald Freudenberger 37255d0a513SHarald Freudenberger if (kb->head.type != TOKTYPE_NON_CCA) { 37355d0a513SHarald Freudenberger if (dbg) 37455d0a513SHarald Freudenberger DBF("%s key check failed, type 0x%02x != 0x%02x\n", 37555d0a513SHarald Freudenberger __func__, (int)kb->head.type, TOKTYPE_NON_CCA); 37655d0a513SHarald Freudenberger return -EINVAL; 37755d0a513SHarald Freudenberger } 37855d0a513SHarald Freudenberger if (kb->head.version != TOKVER_EP11_AES) { 37955d0a513SHarald Freudenberger if (dbg) 38055d0a513SHarald Freudenberger DBF("%s key check failed, version 0x%02x != 0x%02x\n", 38155d0a513SHarald Freudenberger __func__, (int)kb->head.version, TOKVER_EP11_AES); 38255d0a513SHarald Freudenberger return -EINVAL; 38355d0a513SHarald Freudenberger } 384fa6999e3SHarald Freudenberger if (kb->head.len > keylen) { 385fa6999e3SHarald Freudenberger if (dbg) 386fa6999e3SHarald Freudenberger DBF("%s key check failed, header len %d keylen %zu mismatch\n", 387fa6999e3SHarald Freudenberger __func__, (int)kb->head.len, keylen); 388fa6999e3SHarald Freudenberger return -EINVAL; 389fa6999e3SHarald Freudenberger } 390fa6999e3SHarald Freudenberger if (kb->head.len < sizeof(*kb)) { 391fa6999e3SHarald Freudenberger if (dbg) 392fa6999e3SHarald Freudenberger DBF("%s key check failed, header len %d < %zu\n", 393fa6999e3SHarald Freudenberger __func__, (int)kb->head.len, sizeof(*kb)); 394fa6999e3SHarald Freudenberger return -EINVAL; 395fa6999e3SHarald Freudenberger } 396fa6999e3SHarald Freudenberger 39755d0a513SHarald Freudenberger if (kb->version != EP11_STRUCT_MAGIC) { 39855d0a513SHarald Freudenberger if (dbg) 399fa6999e3SHarald Freudenberger DBF("%s key check failed, blob magic 0x%04x != 0x%04x\n", 40055d0a513SHarald Freudenberger __func__, (int)kb->version, EP11_STRUCT_MAGIC); 40155d0a513SHarald Freudenberger return -EINVAL; 40255d0a513SHarald Freudenberger } 403fa6999e3SHarald Freudenberger if (checkcpacfexp && !(kb->attr & EP11_BLOB_PKEY_EXTRACTABLE)) { 40455d0a513SHarald Freudenberger if (dbg) 405fa6999e3SHarald Freudenberger DBF("%s key check failed, PKEY_EXTRACTABLE is off\n", 40655d0a513SHarald Freudenberger __func__); 40755d0a513SHarald Freudenberger return -EINVAL; 40855d0a513SHarald Freudenberger } 409fa6999e3SHarald Freudenberger 41055d0a513SHarald Freudenberger #undef DBF 41155d0a513SHarald Freudenberger 41255d0a513SHarald Freudenberger return 0; 41355d0a513SHarald Freudenberger } 414fa6999e3SHarald Freudenberger EXPORT_SYMBOL(ep11_check_aes_key); 41555d0a513SHarald Freudenberger 41655d0a513SHarald Freudenberger /* 4177384eb72SHarald Freudenberger * Allocate and prepare ep11 cprb plus additional payload. 4187384eb72SHarald Freudenberger */ 41955d0a513SHarald Freudenberger static inline struct ep11_cprb *alloc_cprb(size_t payload_len) 4207384eb72SHarald Freudenberger { 4217384eb72SHarald Freudenberger size_t len = sizeof(struct ep11_cprb) + payload_len; 4227384eb72SHarald Freudenberger struct ep11_cprb *cprb; 4237384eb72SHarald Freudenberger 42479d6c502SZou Wei cprb = kzalloc(len, GFP_KERNEL); 4257384eb72SHarald Freudenberger if (!cprb) 4267384eb72SHarald Freudenberger return NULL; 4277384eb72SHarald Freudenberger 4287384eb72SHarald Freudenberger cprb->cprb_len = sizeof(struct ep11_cprb); 4297384eb72SHarald Freudenberger cprb->cprb_ver_id = 0x04; 4307384eb72SHarald Freudenberger memcpy(cprb->func_id, "T4", 2); 4317384eb72SHarald Freudenberger cprb->ret_code = 0xFFFFFFFF; 4327384eb72SHarald Freudenberger cprb->payload_len = payload_len; 4337384eb72SHarald Freudenberger 4347384eb72SHarald Freudenberger return cprb; 4357384eb72SHarald Freudenberger } 4367384eb72SHarald Freudenberger 4377384eb72SHarald Freudenberger /* 43855d0a513SHarald Freudenberger * Some helper functions related to ASN1 encoding. 43955d0a513SHarald Freudenberger * Limited to length info <= 2 byte. 4407384eb72SHarald Freudenberger */ 44155d0a513SHarald Freudenberger 44255d0a513SHarald Freudenberger #define ASN1TAGLEN(x) (2 + (x) + ((x) > 127 ? 1 : 0) + ((x) > 255 ? 1 : 0)) 44355d0a513SHarald Freudenberger 44455d0a513SHarald Freudenberger static int asn1tag_write(u8 *ptr, u8 tag, const u8 *pvalue, u16 valuelen) 4457384eb72SHarald Freudenberger { 44655d0a513SHarald Freudenberger ptr[0] = tag; 44755d0a513SHarald Freudenberger if (valuelen > 255) { 44855d0a513SHarald Freudenberger ptr[1] = 0x82; 44955d0a513SHarald Freudenberger *((u16 *)(ptr + 2)) = valuelen; 45055d0a513SHarald Freudenberger memcpy(ptr + 4, pvalue, valuelen); 45155d0a513SHarald Freudenberger return 4 + valuelen; 45255d0a513SHarald Freudenberger } 45355d0a513SHarald Freudenberger if (valuelen > 127) { 45455d0a513SHarald Freudenberger ptr[1] = 0x81; 45555d0a513SHarald Freudenberger ptr[2] = (u8)valuelen; 45655d0a513SHarald Freudenberger memcpy(ptr + 3, pvalue, valuelen); 45755d0a513SHarald Freudenberger return 3 + valuelen; 45855d0a513SHarald Freudenberger } 45955d0a513SHarald Freudenberger ptr[1] = (u8)valuelen; 46055d0a513SHarald Freudenberger memcpy(ptr + 2, pvalue, valuelen); 46155d0a513SHarald Freudenberger return 2 + valuelen; 46255d0a513SHarald Freudenberger } 46355d0a513SHarald Freudenberger 46455d0a513SHarald Freudenberger /* EP11 payload > 127 bytes starts with this struct */ 46555d0a513SHarald Freudenberger struct pl_head { 4667384eb72SHarald Freudenberger u8 tag; 4677384eb72SHarald Freudenberger u8 lenfmt; 4687384eb72SHarald Freudenberger u16 len; 4697384eb72SHarald Freudenberger u8 func_tag; 4707384eb72SHarald Freudenberger u8 func_len; 4717384eb72SHarald Freudenberger u32 func; 4727384eb72SHarald Freudenberger u8 dom_tag; 4737384eb72SHarald Freudenberger u8 dom_len; 4747384eb72SHarald Freudenberger u32 dom; 47555d0a513SHarald Freudenberger } __packed; 47655d0a513SHarald Freudenberger 47755d0a513SHarald Freudenberger /* prep ep11 payload head helper function */ 47855d0a513SHarald Freudenberger static inline void prep_head(struct pl_head *h, 47955d0a513SHarald Freudenberger size_t pl_size, int api, int func) 48055d0a513SHarald Freudenberger { 48155d0a513SHarald Freudenberger h->tag = 0x30; 48255d0a513SHarald Freudenberger h->lenfmt = 0x82; 48355d0a513SHarald Freudenberger h->len = pl_size - 4; 48455d0a513SHarald Freudenberger h->func_tag = 0x04; 48555d0a513SHarald Freudenberger h->func_len = sizeof(u32); 48655d0a513SHarald Freudenberger h->func = (api << 16) + func; 48755d0a513SHarald Freudenberger h->dom_tag = 0x04; 48855d0a513SHarald Freudenberger h->dom_len = sizeof(u32); 48955d0a513SHarald Freudenberger } 49055d0a513SHarald Freudenberger 49155d0a513SHarald Freudenberger /* prep urb helper function */ 49255d0a513SHarald Freudenberger static inline void prep_urb(struct ep11_urb *u, 49355d0a513SHarald Freudenberger struct ep11_target_dev *t, int nt, 49455d0a513SHarald Freudenberger struct ep11_cprb *req, size_t req_len, 49555d0a513SHarald Freudenberger struct ep11_cprb *rep, size_t rep_len) 49655d0a513SHarald Freudenberger { 49755d0a513SHarald Freudenberger u->targets = (u8 __user *)t; 49855d0a513SHarald Freudenberger u->targets_num = nt; 49955d0a513SHarald Freudenberger u->req = (u8 __user *)req; 50055d0a513SHarald Freudenberger u->req_len = req_len; 50155d0a513SHarald Freudenberger u->resp = (u8 __user *)rep; 50255d0a513SHarald Freudenberger u->resp_len = rep_len; 50355d0a513SHarald Freudenberger } 50455d0a513SHarald Freudenberger 50555d0a513SHarald Freudenberger /* Check ep11 reply payload, return 0 or suggested errno value. */ 50655d0a513SHarald Freudenberger static int check_reply_pl(const u8 *pl, const char *func) 50755d0a513SHarald Freudenberger { 50855d0a513SHarald Freudenberger int len; 50955d0a513SHarald Freudenberger u32 ret; 51055d0a513SHarald Freudenberger 51155d0a513SHarald Freudenberger /* start tag */ 51255d0a513SHarald Freudenberger if (*pl++ != 0x30) { 51355d0a513SHarald Freudenberger DEBUG_ERR("%s reply start tag mismatch\n", func); 51455d0a513SHarald Freudenberger return -EIO; 51555d0a513SHarald Freudenberger } 51655d0a513SHarald Freudenberger 51755d0a513SHarald Freudenberger /* payload length format */ 51855d0a513SHarald Freudenberger if (*pl < 127) { 51955d0a513SHarald Freudenberger len = *pl; 52055d0a513SHarald Freudenberger pl++; 52155d0a513SHarald Freudenberger } else if (*pl == 0x81) { 52255d0a513SHarald Freudenberger pl++; 52355d0a513SHarald Freudenberger len = *pl; 52455d0a513SHarald Freudenberger pl++; 52555d0a513SHarald Freudenberger } else if (*pl == 0x82) { 52655d0a513SHarald Freudenberger pl++; 52755d0a513SHarald Freudenberger len = *((u16 *)pl); 52855d0a513SHarald Freudenberger pl += 2; 52955d0a513SHarald Freudenberger } else { 53055d0a513SHarald Freudenberger DEBUG_ERR("%s reply start tag lenfmt mismatch 0x%02hhx\n", 53155d0a513SHarald Freudenberger func, *pl); 53255d0a513SHarald Freudenberger return -EIO; 53355d0a513SHarald Freudenberger } 53455d0a513SHarald Freudenberger 53555d0a513SHarald Freudenberger /* len should cover at least 3 fields with 32 bit value each */ 53655d0a513SHarald Freudenberger if (len < 3 * 6) { 53755d0a513SHarald Freudenberger DEBUG_ERR("%s reply length %d too small\n", func, len); 53855d0a513SHarald Freudenberger return -EIO; 53955d0a513SHarald Freudenberger } 54055d0a513SHarald Freudenberger 54155d0a513SHarald Freudenberger /* function tag, length and value */ 54255d0a513SHarald Freudenberger if (pl[0] != 0x04 || pl[1] != 0x04) { 54355d0a513SHarald Freudenberger DEBUG_ERR("%s function tag or length mismatch\n", func); 54455d0a513SHarald Freudenberger return -EIO; 54555d0a513SHarald Freudenberger } 54655d0a513SHarald Freudenberger pl += 6; 54755d0a513SHarald Freudenberger 54855d0a513SHarald Freudenberger /* dom tag, length and value */ 54955d0a513SHarald Freudenberger if (pl[0] != 0x04 || pl[1] != 0x04) { 55055d0a513SHarald Freudenberger DEBUG_ERR("%s dom tag or length mismatch\n", func); 55155d0a513SHarald Freudenberger return -EIO; 55255d0a513SHarald Freudenberger } 55355d0a513SHarald Freudenberger pl += 6; 55455d0a513SHarald Freudenberger 55555d0a513SHarald Freudenberger /* return value tag, length and value */ 55655d0a513SHarald Freudenberger if (pl[0] != 0x04 || pl[1] != 0x04) { 55755d0a513SHarald Freudenberger DEBUG_ERR("%s return value tag or length mismatch\n", func); 55855d0a513SHarald Freudenberger return -EIO; 55955d0a513SHarald Freudenberger } 56055d0a513SHarald Freudenberger pl += 2; 56155d0a513SHarald Freudenberger ret = *((u32 *)pl); 56255d0a513SHarald Freudenberger if (ret != 0) { 56355d0a513SHarald Freudenberger DEBUG_ERR("%s return value 0x%04x != 0\n", func, ret); 56455d0a513SHarald Freudenberger return -EIO; 56555d0a513SHarald Freudenberger } 56655d0a513SHarald Freudenberger 56755d0a513SHarald Freudenberger return 0; 56855d0a513SHarald Freudenberger } 56955d0a513SHarald Freudenberger 57055d0a513SHarald Freudenberger /* 57155d0a513SHarald Freudenberger * Helper function which does an ep11 query with given query type. 57255d0a513SHarald Freudenberger */ 57355d0a513SHarald Freudenberger static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type, 57455d0a513SHarald Freudenberger size_t buflen, u8 *buf) 57555d0a513SHarald Freudenberger { 57655d0a513SHarald Freudenberger struct ep11_info_req_pl { 57755d0a513SHarald Freudenberger struct pl_head head; 57855d0a513SHarald Freudenberger u8 query_type_tag; 57955d0a513SHarald Freudenberger u8 query_type_len; 58055d0a513SHarald Freudenberger u32 query_type; 58155d0a513SHarald Freudenberger u8 query_subtype_tag; 58255d0a513SHarald Freudenberger u8 query_subtype_len; 58355d0a513SHarald Freudenberger u32 query_subtype; 58455d0a513SHarald Freudenberger } __packed * req_pl; 58555d0a513SHarald Freudenberger struct ep11_info_rep_pl { 58655d0a513SHarald Freudenberger struct pl_head head; 5877384eb72SHarald Freudenberger u8 rc_tag; 5887384eb72SHarald Freudenberger u8 rc_len; 5897384eb72SHarald Freudenberger u32 rc; 5907384eb72SHarald Freudenberger u8 data_tag; 5917384eb72SHarald Freudenberger u8 data_lenfmt; 5927384eb72SHarald Freudenberger u16 data_len; 5937384eb72SHarald Freudenberger } __packed * rep_pl; 5947384eb72SHarald Freudenberger struct ep11_cprb *req = NULL, *rep = NULL; 5957384eb72SHarald Freudenberger struct ep11_target_dev target; 5967384eb72SHarald Freudenberger struct ep11_urb *urb = NULL; 597*386cb81eSHolger Dengler int api = EP11_API_V1, rc = -ENOMEM; 5987384eb72SHarald Freudenberger 5997384eb72SHarald Freudenberger /* request cprb and payload */ 60055d0a513SHarald Freudenberger req = alloc_cprb(sizeof(struct ep11_info_req_pl)); 6017384eb72SHarald Freudenberger if (!req) 6027384eb72SHarald Freudenberger goto out; 6037384eb72SHarald Freudenberger req_pl = (struct ep11_info_req_pl *)(((u8 *)req) + sizeof(*req)); 60455d0a513SHarald Freudenberger prep_head(&req_pl->head, sizeof(*req_pl), api, 38); /* get xcp info */ 6057384eb72SHarald Freudenberger req_pl->query_type_tag = 0x04; 6067384eb72SHarald Freudenberger req_pl->query_type_len = sizeof(u32); 6077384eb72SHarald Freudenberger req_pl->query_type = query_type; 6087384eb72SHarald Freudenberger req_pl->query_subtype_tag = 0x04; 6097384eb72SHarald Freudenberger req_pl->query_subtype_len = sizeof(u32); 6107384eb72SHarald Freudenberger 6117384eb72SHarald Freudenberger /* reply cprb and payload */ 61255d0a513SHarald Freudenberger rep = alloc_cprb(sizeof(struct ep11_info_rep_pl) + buflen); 6137384eb72SHarald Freudenberger if (!rep) 6147384eb72SHarald Freudenberger goto out; 6157384eb72SHarald Freudenberger rep_pl = (struct ep11_info_rep_pl *)(((u8 *)rep) + sizeof(*rep)); 6167384eb72SHarald Freudenberger 6177384eb72SHarald Freudenberger /* urb and target */ 6182004b57cSHarald Freudenberger urb = kmalloc(sizeof(*urb), GFP_KERNEL); 6197384eb72SHarald Freudenberger if (!urb) 6207384eb72SHarald Freudenberger goto out; 6217384eb72SHarald Freudenberger target.ap_id = cardnr; 6227384eb72SHarald Freudenberger target.dom_id = domain; 62355d0a513SHarald Freudenberger prep_urb(urb, &target, 1, 62455d0a513SHarald Freudenberger req, sizeof(*req) + sizeof(*req_pl), 62555d0a513SHarald Freudenberger rep, sizeof(*rep) + sizeof(*rep_pl) + buflen); 6267384eb72SHarald Freudenberger 62752f72febSHarald Freudenberger rc = zcrypt_send_ep11_cprb(urb); 6287384eb72SHarald Freudenberger if (rc) { 6297384eb72SHarald Freudenberger DEBUG_ERR( 6307384eb72SHarald Freudenberger "%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n", 6317384eb72SHarald Freudenberger __func__, (int)cardnr, (int)domain, rc); 6327384eb72SHarald Freudenberger goto out; 6337384eb72SHarald Freudenberger } 6347384eb72SHarald Freudenberger 63555d0a513SHarald Freudenberger rc = check_reply_pl((u8 *)rep_pl, __func__); 63655d0a513SHarald Freudenberger if (rc) 6377384eb72SHarald Freudenberger goto out; 63855d0a513SHarald Freudenberger if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) { 6397384eb72SHarald Freudenberger DEBUG_ERR("%s unknown reply data format\n", __func__); 64055d0a513SHarald Freudenberger rc = -EIO; 6417384eb72SHarald Freudenberger goto out; 6427384eb72SHarald Freudenberger } 6437384eb72SHarald Freudenberger if (rep_pl->data_len > buflen) { 6447384eb72SHarald Freudenberger DEBUG_ERR("%s mismatch between reply data len and buffer len\n", 6457384eb72SHarald Freudenberger __func__); 64655d0a513SHarald Freudenberger rc = -ENOSPC; 6477384eb72SHarald Freudenberger goto out; 6487384eb72SHarald Freudenberger } 6497384eb72SHarald Freudenberger 65055d0a513SHarald Freudenberger memcpy(buf, ((u8 *)rep_pl) + sizeof(*rep_pl), rep_pl->data_len); 6517384eb72SHarald Freudenberger 6527384eb72SHarald Freudenberger out: 6537384eb72SHarald Freudenberger kfree(req); 6547384eb72SHarald Freudenberger kfree(rep); 6557384eb72SHarald Freudenberger kfree(urb); 6567384eb72SHarald Freudenberger return rc; 6577384eb72SHarald Freudenberger } 6587384eb72SHarald Freudenberger 6597384eb72SHarald Freudenberger /* 6607384eb72SHarald Freudenberger * Provide information about an EP11 card. 6617384eb72SHarald Freudenberger */ 6627384eb72SHarald Freudenberger int ep11_get_card_info(u16 card, struct ep11_card_info *info, int verify) 6637384eb72SHarald Freudenberger { 6647384eb72SHarald Freudenberger int rc; 6657384eb72SHarald Freudenberger struct ep11_module_query_info { 6667384eb72SHarald Freudenberger u32 API_ord_nr; 6677384eb72SHarald Freudenberger u32 firmware_id; 6687384eb72SHarald Freudenberger u8 FW_major_vers; 6697384eb72SHarald Freudenberger u8 FW_minor_vers; 6707384eb72SHarald Freudenberger u8 CSP_major_vers; 6717384eb72SHarald Freudenberger u8 CSP_minor_vers; 6727384eb72SHarald Freudenberger u8 fwid[32]; 6737384eb72SHarald Freudenberger u8 xcp_config_hash[32]; 6747384eb72SHarald Freudenberger u8 CSP_config_hash[32]; 6757384eb72SHarald Freudenberger u8 serial[16]; 6767384eb72SHarald Freudenberger u8 module_date_time[16]; 6777384eb72SHarald Freudenberger u64 op_mode; 6787384eb72SHarald Freudenberger u32 PKCS11_flags; 6797384eb72SHarald Freudenberger u32 ext_flags; 6807384eb72SHarald Freudenberger u32 domains; 6817384eb72SHarald Freudenberger u32 sym_state_bytes; 6827384eb72SHarald Freudenberger u32 digest_state_bytes; 6837384eb72SHarald Freudenberger u32 pin_blob_bytes; 6847384eb72SHarald Freudenberger u32 SPKI_bytes; 6857384eb72SHarald Freudenberger u32 priv_key_blob_bytes; 6867384eb72SHarald Freudenberger u32 sym_blob_bytes; 6877384eb72SHarald Freudenberger u32 max_payload_bytes; 6887384eb72SHarald Freudenberger u32 CP_profile_bytes; 6897384eb72SHarald Freudenberger u32 max_CP_index; 6907384eb72SHarald Freudenberger } __packed * pmqi = NULL; 6917384eb72SHarald Freudenberger 6927384eb72SHarald Freudenberger rc = card_cache_fetch(card, info); 6937384eb72SHarald Freudenberger if (rc || verify) { 6947384eb72SHarald Freudenberger pmqi = kmalloc(sizeof(*pmqi), GFP_KERNEL); 6957384eb72SHarald Freudenberger if (!pmqi) 6967384eb72SHarald Freudenberger return -ENOMEM; 6977384eb72SHarald Freudenberger rc = ep11_query_info(card, AUTOSEL_DOM, 6987384eb72SHarald Freudenberger 0x01 /* module info query */, 6997384eb72SHarald Freudenberger sizeof(*pmqi), (u8 *)pmqi); 7007384eb72SHarald Freudenberger if (rc) { 7017384eb72SHarald Freudenberger if (rc == -ENODEV) 7027384eb72SHarald Freudenberger card_cache_scrub(card); 7037384eb72SHarald Freudenberger goto out; 7047384eb72SHarald Freudenberger } 7057384eb72SHarald Freudenberger memset(info, 0, sizeof(*info)); 7067384eb72SHarald Freudenberger info->API_ord_nr = pmqi->API_ord_nr; 7077384eb72SHarald Freudenberger info->FW_version = 7087384eb72SHarald Freudenberger (pmqi->FW_major_vers << 8) + pmqi->FW_minor_vers; 7097384eb72SHarald Freudenberger memcpy(info->serial, pmqi->serial, sizeof(info->serial)); 7107384eb72SHarald Freudenberger info->op_mode = pmqi->op_mode; 7117384eb72SHarald Freudenberger card_cache_update(card, info); 7127384eb72SHarald Freudenberger } 7137384eb72SHarald Freudenberger 7147384eb72SHarald Freudenberger out: 7157384eb72SHarald Freudenberger kfree(pmqi); 7167384eb72SHarald Freudenberger return rc; 7177384eb72SHarald Freudenberger } 7187384eb72SHarald Freudenberger EXPORT_SYMBOL(ep11_get_card_info); 7197384eb72SHarald Freudenberger 7207384eb72SHarald Freudenberger /* 7217384eb72SHarald Freudenberger * Provide information about a domain within an EP11 card. 7227384eb72SHarald Freudenberger */ 7237384eb72SHarald Freudenberger int ep11_get_domain_info(u16 card, u16 domain, struct ep11_domain_info *info) 7247384eb72SHarald Freudenberger { 7257384eb72SHarald Freudenberger int rc; 7267384eb72SHarald Freudenberger struct ep11_domain_query_info { 7277384eb72SHarald Freudenberger u32 dom_index; 7287384eb72SHarald Freudenberger u8 cur_WK_VP[32]; 7297384eb72SHarald Freudenberger u8 new_WK_VP[32]; 7307384eb72SHarald Freudenberger u32 dom_flags; 7317384eb72SHarald Freudenberger u64 op_mode; 7327384eb72SHarald Freudenberger } __packed * p_dom_info; 7337384eb72SHarald Freudenberger 7347384eb72SHarald Freudenberger p_dom_info = kmalloc(sizeof(*p_dom_info), GFP_KERNEL); 7357384eb72SHarald Freudenberger if (!p_dom_info) 7367384eb72SHarald Freudenberger return -ENOMEM; 7377384eb72SHarald Freudenberger 7387384eb72SHarald Freudenberger rc = ep11_query_info(card, domain, 0x03 /* domain info query */, 7397384eb72SHarald Freudenberger sizeof(*p_dom_info), (u8 *)p_dom_info); 7407384eb72SHarald Freudenberger if (rc) 7417384eb72SHarald Freudenberger goto out; 7427384eb72SHarald Freudenberger 7437384eb72SHarald Freudenberger memset(info, 0, sizeof(*info)); 7447384eb72SHarald Freudenberger info->cur_wk_state = '0'; 7457384eb72SHarald Freudenberger info->new_wk_state = '0'; 7467384eb72SHarald Freudenberger if (p_dom_info->dom_flags & 0x10 /* left imprint mode */) { 7477384eb72SHarald Freudenberger if (p_dom_info->dom_flags & 0x02 /* cur wk valid */) { 7487384eb72SHarald Freudenberger info->cur_wk_state = '1'; 7497384eb72SHarald Freudenberger memcpy(info->cur_wkvp, p_dom_info->cur_WK_VP, 32); 7507384eb72SHarald Freudenberger } 7512004b57cSHarald Freudenberger if (p_dom_info->dom_flags & 0x04 || /* new wk present */ 7522004b57cSHarald Freudenberger p_dom_info->dom_flags & 0x08 /* new wk committed */) { 7537384eb72SHarald Freudenberger info->new_wk_state = 7547384eb72SHarald Freudenberger p_dom_info->dom_flags & 0x08 ? '2' : '1'; 7557384eb72SHarald Freudenberger memcpy(info->new_wkvp, p_dom_info->new_WK_VP, 32); 7567384eb72SHarald Freudenberger } 7577384eb72SHarald Freudenberger } 7587384eb72SHarald Freudenberger info->op_mode = p_dom_info->op_mode; 7597384eb72SHarald Freudenberger 7607384eb72SHarald Freudenberger out: 7617384eb72SHarald Freudenberger kfree(p_dom_info); 7627384eb72SHarald Freudenberger return rc; 7637384eb72SHarald Freudenberger } 7647384eb72SHarald Freudenberger EXPORT_SYMBOL(ep11_get_domain_info); 7657384eb72SHarald Freudenberger 76655d0a513SHarald Freudenberger /* 76755d0a513SHarald Freudenberger * Default EP11 AES key generate attributes, used when no keygenflags given: 76855d0a513SHarald Freudenberger * XCP_BLOB_ENCRYPT | XCP_BLOB_DECRYPT | XCP_BLOB_PROTKEY_EXTRACTABLE 76955d0a513SHarald Freudenberger */ 77055d0a513SHarald Freudenberger #define KEY_ATTR_DEFAULTS 0x00200c00 77155d0a513SHarald Freudenberger 772fb249ce7SHolger Dengler static int _ep11_genaeskey(u16 card, u16 domain, 773fb249ce7SHolger Dengler u32 keybitsize, u32 keygenflags, 77455d0a513SHarald Freudenberger u8 *keybuf, size_t *keybufsize) 77555d0a513SHarald Freudenberger { 77655d0a513SHarald Freudenberger struct keygen_req_pl { 77755d0a513SHarald Freudenberger struct pl_head head; 77855d0a513SHarald Freudenberger u8 var_tag; 77955d0a513SHarald Freudenberger u8 var_len; 78055d0a513SHarald Freudenberger u32 var; 78155d0a513SHarald Freudenberger u8 keybytes_tag; 78255d0a513SHarald Freudenberger u8 keybytes_len; 78355d0a513SHarald Freudenberger u32 keybytes; 78455d0a513SHarald Freudenberger u8 mech_tag; 78555d0a513SHarald Freudenberger u8 mech_len; 78655d0a513SHarald Freudenberger u32 mech; 78755d0a513SHarald Freudenberger u8 attr_tag; 78855d0a513SHarald Freudenberger u8 attr_len; 78955d0a513SHarald Freudenberger u32 attr_header; 79055d0a513SHarald Freudenberger u32 attr_bool_mask; 79155d0a513SHarald Freudenberger u32 attr_bool_bits; 79255d0a513SHarald Freudenberger u32 attr_val_len_type; 79355d0a513SHarald Freudenberger u32 attr_val_len_value; 794*386cb81eSHolger Dengler /* followed by empty pin tag or empty pinblob tag */ 79555d0a513SHarald Freudenberger } __packed * req_pl; 79655d0a513SHarald Freudenberger struct keygen_rep_pl { 79755d0a513SHarald Freudenberger struct pl_head head; 79855d0a513SHarald Freudenberger u8 rc_tag; 79955d0a513SHarald Freudenberger u8 rc_len; 80055d0a513SHarald Freudenberger u32 rc; 80155d0a513SHarald Freudenberger u8 data_tag; 80255d0a513SHarald Freudenberger u8 data_lenfmt; 80355d0a513SHarald Freudenberger u16 data_len; 80455d0a513SHarald Freudenberger u8 data[512]; 80555d0a513SHarald Freudenberger } __packed * rep_pl; 80655d0a513SHarald Freudenberger struct ep11_cprb *req = NULL, *rep = NULL; 807*386cb81eSHolger Dengler size_t req_pl_size, pinblob_size = 0; 80855d0a513SHarald Freudenberger struct ep11_target_dev target; 80955d0a513SHarald Freudenberger struct ep11_urb *urb = NULL; 81055d0a513SHarald Freudenberger int api, rc = -ENOMEM; 811*386cb81eSHolger Dengler u8 *p; 81255d0a513SHarald Freudenberger 81355d0a513SHarald Freudenberger switch (keybitsize) { 81455d0a513SHarald Freudenberger case 128: 81555d0a513SHarald Freudenberger case 192: 81655d0a513SHarald Freudenberger case 256: 81755d0a513SHarald Freudenberger break; 81855d0a513SHarald Freudenberger default: 81955d0a513SHarald Freudenberger DEBUG_ERR( 82055d0a513SHarald Freudenberger "%s unknown/unsupported keybitsize %d\n", 82155d0a513SHarald Freudenberger __func__, keybitsize); 82255d0a513SHarald Freudenberger rc = -EINVAL; 82355d0a513SHarald Freudenberger goto out; 82455d0a513SHarald Freudenberger } 82555d0a513SHarald Freudenberger 82655d0a513SHarald Freudenberger /* request cprb and payload */ 827*386cb81eSHolger Dengler api = (!keygenflags || keygenflags & 0x00200000) ? 828*386cb81eSHolger Dengler EP11_API_V4 : EP11_API_V1; 829*386cb81eSHolger Dengler if (ap_is_se_guest()) { 830*386cb81eSHolger Dengler /* 831*386cb81eSHolger Dengler * genkey within SE environment requires API ordinal 6 832*386cb81eSHolger Dengler * with empty pinblob 833*386cb81eSHolger Dengler */ 834*386cb81eSHolger Dengler api = EP11_API_V6; 835*386cb81eSHolger Dengler pinblob_size = EP11_PINBLOB_V1_BYTES; 836*386cb81eSHolger Dengler } 837*386cb81eSHolger Dengler req_pl_size = sizeof(struct keygen_req_pl) + ASN1TAGLEN(pinblob_size); 838*386cb81eSHolger Dengler req = alloc_cprb(req_pl_size); 83955d0a513SHarald Freudenberger if (!req) 84055d0a513SHarald Freudenberger goto out; 84155d0a513SHarald Freudenberger req_pl = (struct keygen_req_pl *)(((u8 *)req) + sizeof(*req)); 842*386cb81eSHolger Dengler prep_head(&req_pl->head, req_pl_size, api, 21); /* GenerateKey */ 84355d0a513SHarald Freudenberger req_pl->var_tag = 0x04; 84455d0a513SHarald Freudenberger req_pl->var_len = sizeof(u32); 84555d0a513SHarald Freudenberger req_pl->keybytes_tag = 0x04; 84655d0a513SHarald Freudenberger req_pl->keybytes_len = sizeof(u32); 84755d0a513SHarald Freudenberger req_pl->keybytes = keybitsize / 8; 84855d0a513SHarald Freudenberger req_pl->mech_tag = 0x04; 84955d0a513SHarald Freudenberger req_pl->mech_len = sizeof(u32); 85055d0a513SHarald Freudenberger req_pl->mech = 0x00001080; /* CKM_AES_KEY_GEN */ 85155d0a513SHarald Freudenberger req_pl->attr_tag = 0x04; 85255d0a513SHarald Freudenberger req_pl->attr_len = 5 * sizeof(u32); 85355d0a513SHarald Freudenberger req_pl->attr_header = 0x10010000; 85455d0a513SHarald Freudenberger req_pl->attr_bool_mask = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS; 85555d0a513SHarald Freudenberger req_pl->attr_bool_bits = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS; 85655d0a513SHarald Freudenberger req_pl->attr_val_len_type = 0x00000161; /* CKA_VALUE_LEN */ 85755d0a513SHarald Freudenberger req_pl->attr_val_len_value = keybitsize / 8; 858*386cb81eSHolger Dengler p = ((u8 *)req_pl) + sizeof(*req_pl); 859*386cb81eSHolger Dengler /* pin tag */ 860*386cb81eSHolger Dengler *p++ = 0x04; 861*386cb81eSHolger Dengler *p++ = pinblob_size; 86255d0a513SHarald Freudenberger 86355d0a513SHarald Freudenberger /* reply cprb and payload */ 86455d0a513SHarald Freudenberger rep = alloc_cprb(sizeof(struct keygen_rep_pl)); 86555d0a513SHarald Freudenberger if (!rep) 86655d0a513SHarald Freudenberger goto out; 86755d0a513SHarald Freudenberger rep_pl = (struct keygen_rep_pl *)(((u8 *)rep) + sizeof(*rep)); 86855d0a513SHarald Freudenberger 86955d0a513SHarald Freudenberger /* urb and target */ 8702004b57cSHarald Freudenberger urb = kmalloc(sizeof(*urb), GFP_KERNEL); 87155d0a513SHarald Freudenberger if (!urb) 87255d0a513SHarald Freudenberger goto out; 87355d0a513SHarald Freudenberger target.ap_id = card; 87455d0a513SHarald Freudenberger target.dom_id = domain; 87555d0a513SHarald Freudenberger prep_urb(urb, &target, 1, 876*386cb81eSHolger Dengler req, sizeof(*req) + req_pl_size, 87755d0a513SHarald Freudenberger rep, sizeof(*rep) + sizeof(*rep_pl)); 87855d0a513SHarald Freudenberger 87952f72febSHarald Freudenberger rc = zcrypt_send_ep11_cprb(urb); 88055d0a513SHarald Freudenberger if (rc) { 88155d0a513SHarald Freudenberger DEBUG_ERR( 88255d0a513SHarald Freudenberger "%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n", 88355d0a513SHarald Freudenberger __func__, (int)card, (int)domain, rc); 88455d0a513SHarald Freudenberger goto out; 88555d0a513SHarald Freudenberger } 88655d0a513SHarald Freudenberger 88755d0a513SHarald Freudenberger rc = check_reply_pl((u8 *)rep_pl, __func__); 88855d0a513SHarald Freudenberger if (rc) 88955d0a513SHarald Freudenberger goto out; 89055d0a513SHarald Freudenberger if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) { 89155d0a513SHarald Freudenberger DEBUG_ERR("%s unknown reply data format\n", __func__); 89255d0a513SHarald Freudenberger rc = -EIO; 89355d0a513SHarald Freudenberger goto out; 89455d0a513SHarald Freudenberger } 89555d0a513SHarald Freudenberger if (rep_pl->data_len > *keybufsize) { 89655d0a513SHarald Freudenberger DEBUG_ERR("%s mismatch reply data len / key buffer len\n", 89755d0a513SHarald Freudenberger __func__); 89855d0a513SHarald Freudenberger rc = -ENOSPC; 89955d0a513SHarald Freudenberger goto out; 90055d0a513SHarald Freudenberger } 90155d0a513SHarald Freudenberger 902fb249ce7SHolger Dengler /* copy key blob */ 90355d0a513SHarald Freudenberger memcpy(keybuf, rep_pl->data, rep_pl->data_len); 90455d0a513SHarald Freudenberger *keybufsize = rep_pl->data_len; 90555d0a513SHarald Freudenberger 90655d0a513SHarald Freudenberger out: 90755d0a513SHarald Freudenberger kfree(req); 90855d0a513SHarald Freudenberger kfree(rep); 90955d0a513SHarald Freudenberger kfree(urb); 91055d0a513SHarald Freudenberger return rc; 91155d0a513SHarald Freudenberger } 912fb249ce7SHolger Dengler 913fb249ce7SHolger Dengler int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags, 914fb249ce7SHolger Dengler u8 *keybuf, size_t *keybufsize, u32 keybufver) 915fb249ce7SHolger Dengler { 916fb249ce7SHolger Dengler struct ep11kblob_header *hdr; 917fb249ce7SHolger Dengler size_t hdr_size, pl_size; 918fb249ce7SHolger Dengler u8 *pl; 919fb249ce7SHolger Dengler int rc; 920fb249ce7SHolger Dengler 921fb249ce7SHolger Dengler switch (keybufver) { 922fb249ce7SHolger Dengler case TOKVER_EP11_AES: 923fb249ce7SHolger Dengler case TOKVER_EP11_AES_WITH_HEADER: 924fb249ce7SHolger Dengler break; 925fb249ce7SHolger Dengler default: 926fb249ce7SHolger Dengler return -EINVAL; 927fb249ce7SHolger Dengler } 928fb249ce7SHolger Dengler 929fb249ce7SHolger Dengler rc = ep11_kb_split(keybuf, *keybufsize, keybufver, 930fb249ce7SHolger Dengler &hdr, &hdr_size, &pl, &pl_size); 931fb249ce7SHolger Dengler if (rc) 932fb249ce7SHolger Dengler return rc; 933fb249ce7SHolger Dengler 934fb249ce7SHolger Dengler rc = _ep11_genaeskey(card, domain, keybitsize, keygenflags, 935fb249ce7SHolger Dengler pl, &pl_size); 936fb249ce7SHolger Dengler if (rc) 937fb249ce7SHolger Dengler return rc; 938fb249ce7SHolger Dengler 939fb249ce7SHolger Dengler *keybufsize = hdr_size + pl_size; 940fb249ce7SHolger Dengler 941fb249ce7SHolger Dengler /* update header information */ 942fb249ce7SHolger Dengler hdr->type = TOKTYPE_NON_CCA; 943fb249ce7SHolger Dengler hdr->len = *keybufsize; 944fb249ce7SHolger Dengler hdr->version = keybufver; 945fb249ce7SHolger Dengler hdr->bitlen = keybitsize; 946fb249ce7SHolger Dengler 947fb249ce7SHolger Dengler return 0; 948fb249ce7SHolger Dengler } 94955d0a513SHarald Freudenberger EXPORT_SYMBOL(ep11_genaeskey); 95055d0a513SHarald Freudenberger 95155d0a513SHarald Freudenberger static int ep11_cryptsingle(u16 card, u16 domain, 95255d0a513SHarald Freudenberger u16 mode, u32 mech, const u8 *iv, 95355d0a513SHarald Freudenberger const u8 *key, size_t keysize, 95455d0a513SHarald Freudenberger const u8 *inbuf, size_t inbufsize, 95555d0a513SHarald Freudenberger u8 *outbuf, size_t *outbufsize) 95655d0a513SHarald Freudenberger { 95755d0a513SHarald Freudenberger struct crypt_req_pl { 95855d0a513SHarald Freudenberger struct pl_head head; 95955d0a513SHarald Freudenberger u8 var_tag; 96055d0a513SHarald Freudenberger u8 var_len; 96155d0a513SHarald Freudenberger u32 var; 96255d0a513SHarald Freudenberger u8 mech_tag; 96355d0a513SHarald Freudenberger u8 mech_len; 96455d0a513SHarald Freudenberger u32 mech; 96555d0a513SHarald Freudenberger /* 96655d0a513SHarald Freudenberger * maybe followed by iv data 96755d0a513SHarald Freudenberger * followed by key tag + key blob 96855d0a513SHarald Freudenberger * followed by plaintext tag + plaintext 96955d0a513SHarald Freudenberger */ 97055d0a513SHarald Freudenberger } __packed * req_pl; 97155d0a513SHarald Freudenberger struct crypt_rep_pl { 97255d0a513SHarald Freudenberger struct pl_head head; 97355d0a513SHarald Freudenberger u8 rc_tag; 97455d0a513SHarald Freudenberger u8 rc_len; 97555d0a513SHarald Freudenberger u32 rc; 97655d0a513SHarald Freudenberger u8 data_tag; 97755d0a513SHarald Freudenberger u8 data_lenfmt; 97855d0a513SHarald Freudenberger /* data follows */ 97955d0a513SHarald Freudenberger } __packed * rep_pl; 98055d0a513SHarald Freudenberger struct ep11_cprb *req = NULL, *rep = NULL; 98155d0a513SHarald Freudenberger struct ep11_target_dev target; 98255d0a513SHarald Freudenberger struct ep11_urb *urb = NULL; 98355d0a513SHarald Freudenberger size_t req_pl_size, rep_pl_size; 984*386cb81eSHolger Dengler int n, api = EP11_API_V1, rc = -ENOMEM; 98555d0a513SHarald Freudenberger u8 *p; 98655d0a513SHarald Freudenberger 98755d0a513SHarald Freudenberger /* the simple asn1 coding used has length limits */ 98855d0a513SHarald Freudenberger if (keysize > 0xFFFF || inbufsize > 0xFFFF) 98955d0a513SHarald Freudenberger return -EINVAL; 99055d0a513SHarald Freudenberger 99155d0a513SHarald Freudenberger /* request cprb and payload */ 99255d0a513SHarald Freudenberger req_pl_size = sizeof(struct crypt_req_pl) + (iv ? 16 : 0) 99355d0a513SHarald Freudenberger + ASN1TAGLEN(keysize) + ASN1TAGLEN(inbufsize); 99455d0a513SHarald Freudenberger req = alloc_cprb(req_pl_size); 99555d0a513SHarald Freudenberger if (!req) 99655d0a513SHarald Freudenberger goto out; 99755d0a513SHarald Freudenberger req_pl = (struct crypt_req_pl *)(((u8 *)req) + sizeof(*req)); 99855d0a513SHarald Freudenberger prep_head(&req_pl->head, req_pl_size, api, (mode ? 20 : 19)); 99955d0a513SHarald Freudenberger req_pl->var_tag = 0x04; 100055d0a513SHarald Freudenberger req_pl->var_len = sizeof(u32); 100155d0a513SHarald Freudenberger /* mech is mech + mech params (iv here) */ 100255d0a513SHarald Freudenberger req_pl->mech_tag = 0x04; 100355d0a513SHarald Freudenberger req_pl->mech_len = sizeof(u32) + (iv ? 16 : 0); 100455d0a513SHarald Freudenberger req_pl->mech = (mech ? mech : 0x00001085); /* CKM_AES_CBC_PAD */ 100555d0a513SHarald Freudenberger p = ((u8 *)req_pl) + sizeof(*req_pl); 100655d0a513SHarald Freudenberger if (iv) { 100755d0a513SHarald Freudenberger memcpy(p, iv, 16); 100855d0a513SHarald Freudenberger p += 16; 100955d0a513SHarald Freudenberger } 101055d0a513SHarald Freudenberger /* key and input data */ 101155d0a513SHarald Freudenberger p += asn1tag_write(p, 0x04, key, keysize); 101255d0a513SHarald Freudenberger p += asn1tag_write(p, 0x04, inbuf, inbufsize); 101355d0a513SHarald Freudenberger 101455d0a513SHarald Freudenberger /* reply cprb and payload, assume out data size <= in data size + 32 */ 101555d0a513SHarald Freudenberger rep_pl_size = sizeof(struct crypt_rep_pl) + ASN1TAGLEN(inbufsize + 32); 101655d0a513SHarald Freudenberger rep = alloc_cprb(rep_pl_size); 101755d0a513SHarald Freudenberger if (!rep) 101855d0a513SHarald Freudenberger goto out; 101955d0a513SHarald Freudenberger rep_pl = (struct crypt_rep_pl *)(((u8 *)rep) + sizeof(*rep)); 102055d0a513SHarald Freudenberger 102155d0a513SHarald Freudenberger /* urb and target */ 10222004b57cSHarald Freudenberger urb = kmalloc(sizeof(*urb), GFP_KERNEL); 102355d0a513SHarald Freudenberger if (!urb) 102455d0a513SHarald Freudenberger goto out; 102555d0a513SHarald Freudenberger target.ap_id = card; 102655d0a513SHarald Freudenberger target.dom_id = domain; 102755d0a513SHarald Freudenberger prep_urb(urb, &target, 1, 102855d0a513SHarald Freudenberger req, sizeof(*req) + req_pl_size, 102955d0a513SHarald Freudenberger rep, sizeof(*rep) + rep_pl_size); 103055d0a513SHarald Freudenberger 103152f72febSHarald Freudenberger rc = zcrypt_send_ep11_cprb(urb); 103255d0a513SHarald Freudenberger if (rc) { 103355d0a513SHarald Freudenberger DEBUG_ERR( 103455d0a513SHarald Freudenberger "%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n", 103555d0a513SHarald Freudenberger __func__, (int)card, (int)domain, rc); 103655d0a513SHarald Freudenberger goto out; 103755d0a513SHarald Freudenberger } 103855d0a513SHarald Freudenberger 103955d0a513SHarald Freudenberger rc = check_reply_pl((u8 *)rep_pl, __func__); 104055d0a513SHarald Freudenberger if (rc) 104155d0a513SHarald Freudenberger goto out; 104255d0a513SHarald Freudenberger if (rep_pl->data_tag != 0x04) { 104355d0a513SHarald Freudenberger DEBUG_ERR("%s unknown reply data format\n", __func__); 104455d0a513SHarald Freudenberger rc = -EIO; 104555d0a513SHarald Freudenberger goto out; 104655d0a513SHarald Freudenberger } 104755d0a513SHarald Freudenberger p = ((u8 *)rep_pl) + sizeof(*rep_pl); 10482004b57cSHarald Freudenberger if (rep_pl->data_lenfmt <= 127) { 104955d0a513SHarald Freudenberger n = rep_pl->data_lenfmt; 10502004b57cSHarald Freudenberger } else if (rep_pl->data_lenfmt == 0x81) { 105155d0a513SHarald Freudenberger n = *p++; 10522004b57cSHarald Freudenberger } else if (rep_pl->data_lenfmt == 0x82) { 105355d0a513SHarald Freudenberger n = *((u16 *)p); 105455d0a513SHarald Freudenberger p += 2; 105555d0a513SHarald Freudenberger } else { 105655d0a513SHarald Freudenberger DEBUG_ERR("%s unknown reply data length format 0x%02hhx\n", 105755d0a513SHarald Freudenberger __func__, rep_pl->data_lenfmt); 105855d0a513SHarald Freudenberger rc = -EIO; 105955d0a513SHarald Freudenberger goto out; 106055d0a513SHarald Freudenberger } 106155d0a513SHarald Freudenberger if (n > *outbufsize) { 106255d0a513SHarald Freudenberger DEBUG_ERR("%s mismatch reply data len %d / output buffer %zu\n", 106355d0a513SHarald Freudenberger __func__, n, *outbufsize); 106455d0a513SHarald Freudenberger rc = -ENOSPC; 106555d0a513SHarald Freudenberger goto out; 106655d0a513SHarald Freudenberger } 106755d0a513SHarald Freudenberger 106855d0a513SHarald Freudenberger memcpy(outbuf, p, n); 106955d0a513SHarald Freudenberger *outbufsize = n; 107055d0a513SHarald Freudenberger 107155d0a513SHarald Freudenberger out: 107255d0a513SHarald Freudenberger kfree(req); 107355d0a513SHarald Freudenberger kfree(rep); 107455d0a513SHarald Freudenberger kfree(urb); 107555d0a513SHarald Freudenberger return rc; 107655d0a513SHarald Freudenberger } 107755d0a513SHarald Freudenberger 1078da2863f1SHolger Dengler static int _ep11_unwrapkey(u16 card, u16 domain, 107955d0a513SHarald Freudenberger const u8 *kek, size_t keksize, 108055d0a513SHarald Freudenberger const u8 *enckey, size_t enckeysize, 108155d0a513SHarald Freudenberger u32 mech, const u8 *iv, 108255d0a513SHarald Freudenberger u32 keybitsize, u32 keygenflags, 108355d0a513SHarald Freudenberger u8 *keybuf, size_t *keybufsize) 108455d0a513SHarald Freudenberger { 108555d0a513SHarald Freudenberger struct uw_req_pl { 108655d0a513SHarald Freudenberger struct pl_head head; 108755d0a513SHarald Freudenberger u8 attr_tag; 108855d0a513SHarald Freudenberger u8 attr_len; 108955d0a513SHarald Freudenberger u32 attr_header; 109055d0a513SHarald Freudenberger u32 attr_bool_mask; 109155d0a513SHarald Freudenberger u32 attr_bool_bits; 109255d0a513SHarald Freudenberger u32 attr_key_type; 109355d0a513SHarald Freudenberger u32 attr_key_type_value; 109455d0a513SHarald Freudenberger u32 attr_val_len; 109555d0a513SHarald Freudenberger u32 attr_val_len_value; 109655d0a513SHarald Freudenberger u8 mech_tag; 109755d0a513SHarald Freudenberger u8 mech_len; 109855d0a513SHarald Freudenberger u32 mech; 109955d0a513SHarald Freudenberger /* 110055d0a513SHarald Freudenberger * maybe followed by iv data 110155d0a513SHarald Freudenberger * followed by kek tag + kek blob 110255d0a513SHarald Freudenberger * followed by empty mac tag 1103*386cb81eSHolger Dengler * followed by empty pin tag or empty pinblob tag 110455d0a513SHarald Freudenberger * followed by encryted key tag + bytes 110555d0a513SHarald Freudenberger */ 110655d0a513SHarald Freudenberger } __packed * req_pl; 110755d0a513SHarald Freudenberger struct uw_rep_pl { 110855d0a513SHarald Freudenberger struct pl_head head; 110955d0a513SHarald Freudenberger u8 rc_tag; 111055d0a513SHarald Freudenberger u8 rc_len; 111155d0a513SHarald Freudenberger u32 rc; 111255d0a513SHarald Freudenberger u8 data_tag; 111355d0a513SHarald Freudenberger u8 data_lenfmt; 111455d0a513SHarald Freudenberger u16 data_len; 111555d0a513SHarald Freudenberger u8 data[512]; 111655d0a513SHarald Freudenberger } __packed * rep_pl; 111755d0a513SHarald Freudenberger struct ep11_cprb *req = NULL, *rep = NULL; 1118*386cb81eSHolger Dengler size_t req_pl_size, pinblob_size = 0; 111955d0a513SHarald Freudenberger struct ep11_target_dev target; 112055d0a513SHarald Freudenberger struct ep11_urb *urb = NULL; 112155d0a513SHarald Freudenberger int api, rc = -ENOMEM; 112255d0a513SHarald Freudenberger u8 *p; 112355d0a513SHarald Freudenberger 112455d0a513SHarald Freudenberger /* request cprb and payload */ 1125*386cb81eSHolger Dengler api = (!keygenflags || keygenflags & 0x00200000) ? 1126*386cb81eSHolger Dengler EP11_API_V4 : EP11_API_V1; 1127*386cb81eSHolger Dengler if (ap_is_se_guest()) { 1128*386cb81eSHolger Dengler /* 1129*386cb81eSHolger Dengler * unwrap within SE environment requires API ordinal 6 1130*386cb81eSHolger Dengler * with empty pinblob 1131*386cb81eSHolger Dengler */ 1132*386cb81eSHolger Dengler api = EP11_API_V6; 1133*386cb81eSHolger Dengler pinblob_size = EP11_PINBLOB_V1_BYTES; 1134*386cb81eSHolger Dengler } 113555d0a513SHarald Freudenberger req_pl_size = sizeof(struct uw_req_pl) + (iv ? 16 : 0) 1136*386cb81eSHolger Dengler + ASN1TAGLEN(keksize) + ASN1TAGLEN(0) 1137*386cb81eSHolger Dengler + ASN1TAGLEN(pinblob_size) + ASN1TAGLEN(enckeysize); 113855d0a513SHarald Freudenberger req = alloc_cprb(req_pl_size); 113955d0a513SHarald Freudenberger if (!req) 114055d0a513SHarald Freudenberger goto out; 114155d0a513SHarald Freudenberger req_pl = (struct uw_req_pl *)(((u8 *)req) + sizeof(*req)); 114255d0a513SHarald Freudenberger prep_head(&req_pl->head, req_pl_size, api, 34); /* UnwrapKey */ 114355d0a513SHarald Freudenberger req_pl->attr_tag = 0x04; 114455d0a513SHarald Freudenberger req_pl->attr_len = 7 * sizeof(u32); 114555d0a513SHarald Freudenberger req_pl->attr_header = 0x10020000; 114655d0a513SHarald Freudenberger req_pl->attr_bool_mask = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS; 114755d0a513SHarald Freudenberger req_pl->attr_bool_bits = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS; 114855d0a513SHarald Freudenberger req_pl->attr_key_type = 0x00000100; /* CKA_KEY_TYPE */ 114955d0a513SHarald Freudenberger req_pl->attr_key_type_value = 0x0000001f; /* CKK_AES */ 115055d0a513SHarald Freudenberger req_pl->attr_val_len = 0x00000161; /* CKA_VALUE_LEN */ 115155d0a513SHarald Freudenberger req_pl->attr_val_len_value = keybitsize / 8; 115255d0a513SHarald Freudenberger /* mech is mech + mech params (iv here) */ 115355d0a513SHarald Freudenberger req_pl->mech_tag = 0x04; 115455d0a513SHarald Freudenberger req_pl->mech_len = sizeof(u32) + (iv ? 16 : 0); 115555d0a513SHarald Freudenberger req_pl->mech = (mech ? mech : 0x00001085); /* CKM_AES_CBC_PAD */ 115655d0a513SHarald Freudenberger p = ((u8 *)req_pl) + sizeof(*req_pl); 115755d0a513SHarald Freudenberger if (iv) { 115855d0a513SHarald Freudenberger memcpy(p, iv, 16); 115955d0a513SHarald Freudenberger p += 16; 116055d0a513SHarald Freudenberger } 116155d0a513SHarald Freudenberger /* kek */ 116255d0a513SHarald Freudenberger p += asn1tag_write(p, 0x04, kek, keksize); 116355d0a513SHarald Freudenberger /* empty mac key tag */ 116455d0a513SHarald Freudenberger *p++ = 0x04; 116555d0a513SHarald Freudenberger *p++ = 0; 1166*386cb81eSHolger Dengler /* pin tag */ 116755d0a513SHarald Freudenberger *p++ = 0x04; 1168*386cb81eSHolger Dengler *p++ = pinblob_size; 1169*386cb81eSHolger Dengler p += pinblob_size; 117005ccaca0SGeert Uytterhoeven /* encrypted key value tag and bytes */ 117155d0a513SHarald Freudenberger p += asn1tag_write(p, 0x04, enckey, enckeysize); 117255d0a513SHarald Freudenberger 117355d0a513SHarald Freudenberger /* reply cprb and payload */ 117455d0a513SHarald Freudenberger rep = alloc_cprb(sizeof(struct uw_rep_pl)); 117555d0a513SHarald Freudenberger if (!rep) 117655d0a513SHarald Freudenberger goto out; 117755d0a513SHarald Freudenberger rep_pl = (struct uw_rep_pl *)(((u8 *)rep) + sizeof(*rep)); 117855d0a513SHarald Freudenberger 117955d0a513SHarald Freudenberger /* urb and target */ 11802004b57cSHarald Freudenberger urb = kmalloc(sizeof(*urb), GFP_KERNEL); 118155d0a513SHarald Freudenberger if (!urb) 118255d0a513SHarald Freudenberger goto out; 118355d0a513SHarald Freudenberger target.ap_id = card; 118455d0a513SHarald Freudenberger target.dom_id = domain; 118555d0a513SHarald Freudenberger prep_urb(urb, &target, 1, 118655d0a513SHarald Freudenberger req, sizeof(*req) + req_pl_size, 118755d0a513SHarald Freudenberger rep, sizeof(*rep) + sizeof(*rep_pl)); 118855d0a513SHarald Freudenberger 118952f72febSHarald Freudenberger rc = zcrypt_send_ep11_cprb(urb); 119055d0a513SHarald Freudenberger if (rc) { 119155d0a513SHarald Freudenberger DEBUG_ERR( 119255d0a513SHarald Freudenberger "%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n", 119355d0a513SHarald Freudenberger __func__, (int)card, (int)domain, rc); 119455d0a513SHarald Freudenberger goto out; 119555d0a513SHarald Freudenberger } 119655d0a513SHarald Freudenberger 119755d0a513SHarald Freudenberger rc = check_reply_pl((u8 *)rep_pl, __func__); 119855d0a513SHarald Freudenberger if (rc) 119955d0a513SHarald Freudenberger goto out; 120055d0a513SHarald Freudenberger if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) { 120155d0a513SHarald Freudenberger DEBUG_ERR("%s unknown reply data format\n", __func__); 120255d0a513SHarald Freudenberger rc = -EIO; 120355d0a513SHarald Freudenberger goto out; 120455d0a513SHarald Freudenberger } 120555d0a513SHarald Freudenberger if (rep_pl->data_len > *keybufsize) { 120655d0a513SHarald Freudenberger DEBUG_ERR("%s mismatch reply data len / key buffer len\n", 120755d0a513SHarald Freudenberger __func__); 120855d0a513SHarald Freudenberger rc = -ENOSPC; 120955d0a513SHarald Freudenberger goto out; 121055d0a513SHarald Freudenberger } 121155d0a513SHarald Freudenberger 1212da2863f1SHolger Dengler /* copy key blob */ 121355d0a513SHarald Freudenberger memcpy(keybuf, rep_pl->data, rep_pl->data_len); 121455d0a513SHarald Freudenberger *keybufsize = rep_pl->data_len; 121555d0a513SHarald Freudenberger 121655d0a513SHarald Freudenberger out: 121755d0a513SHarald Freudenberger kfree(req); 121855d0a513SHarald Freudenberger kfree(rep); 121955d0a513SHarald Freudenberger kfree(urb); 122055d0a513SHarald Freudenberger return rc; 122155d0a513SHarald Freudenberger } 122255d0a513SHarald Freudenberger 1223da2863f1SHolger Dengler static int ep11_unwrapkey(u16 card, u16 domain, 1224da2863f1SHolger Dengler const u8 *kek, size_t keksize, 1225da2863f1SHolger Dengler const u8 *enckey, size_t enckeysize, 1226da2863f1SHolger Dengler u32 mech, const u8 *iv, 1227da2863f1SHolger Dengler u32 keybitsize, u32 keygenflags, 1228da2863f1SHolger Dengler u8 *keybuf, size_t *keybufsize, 1229da2863f1SHolger Dengler u8 keybufver) 1230da2863f1SHolger Dengler { 1231da2863f1SHolger Dengler struct ep11kblob_header *hdr; 1232da2863f1SHolger Dengler size_t hdr_size, pl_size; 1233da2863f1SHolger Dengler u8 *pl; 1234da2863f1SHolger Dengler int rc; 1235da2863f1SHolger Dengler 1236da2863f1SHolger Dengler rc = ep11_kb_split(keybuf, *keybufsize, keybufver, 1237da2863f1SHolger Dengler &hdr, &hdr_size, &pl, &pl_size); 1238da2863f1SHolger Dengler if (rc) 1239da2863f1SHolger Dengler return rc; 1240da2863f1SHolger Dengler 1241da2863f1SHolger Dengler rc = _ep11_unwrapkey(card, domain, kek, keksize, enckey, enckeysize, 1242da2863f1SHolger Dengler mech, iv, keybitsize, keygenflags, 1243da2863f1SHolger Dengler pl, &pl_size); 1244da2863f1SHolger Dengler if (rc) 1245da2863f1SHolger Dengler return rc; 1246da2863f1SHolger Dengler 1247da2863f1SHolger Dengler *keybufsize = hdr_size + pl_size; 1248da2863f1SHolger Dengler 1249da2863f1SHolger Dengler /* update header information */ 1250da2863f1SHolger Dengler hdr = (struct ep11kblob_header *)keybuf; 1251da2863f1SHolger Dengler hdr->type = TOKTYPE_NON_CCA; 1252da2863f1SHolger Dengler hdr->len = *keybufsize; 1253da2863f1SHolger Dengler hdr->version = keybufver; 1254da2863f1SHolger Dengler hdr->bitlen = keybitsize; 1255da2863f1SHolger Dengler 1256da2863f1SHolger Dengler return 0; 1257da2863f1SHolger Dengler } 1258da2863f1SHolger Dengler 1259d1fdfb0bSHolger Dengler static int _ep11_wrapkey(u16 card, u16 domain, 126055d0a513SHarald Freudenberger const u8 *key, size_t keysize, 126155d0a513SHarald Freudenberger u32 mech, const u8 *iv, 126255d0a513SHarald Freudenberger u8 *databuf, size_t *datasize) 126355d0a513SHarald Freudenberger { 126455d0a513SHarald Freudenberger struct wk_req_pl { 126555d0a513SHarald Freudenberger struct pl_head head; 126655d0a513SHarald Freudenberger u8 var_tag; 126755d0a513SHarald Freudenberger u8 var_len; 126855d0a513SHarald Freudenberger u32 var; 126955d0a513SHarald Freudenberger u8 mech_tag; 127055d0a513SHarald Freudenberger u8 mech_len; 127155d0a513SHarald Freudenberger u32 mech; 127255d0a513SHarald Freudenberger /* 127355d0a513SHarald Freudenberger * followed by iv data 127455d0a513SHarald Freudenberger * followed by key tag + key blob 127555d0a513SHarald Freudenberger * followed by dummy kek param 127655d0a513SHarald Freudenberger * followed by dummy mac param 127755d0a513SHarald Freudenberger */ 127855d0a513SHarald Freudenberger } __packed * req_pl; 127955d0a513SHarald Freudenberger struct wk_rep_pl { 128055d0a513SHarald Freudenberger struct pl_head head; 128155d0a513SHarald Freudenberger u8 rc_tag; 128255d0a513SHarald Freudenberger u8 rc_len; 128355d0a513SHarald Freudenberger u32 rc; 128455d0a513SHarald Freudenberger u8 data_tag; 128555d0a513SHarald Freudenberger u8 data_lenfmt; 128655d0a513SHarald Freudenberger u16 data_len; 1287fa6999e3SHarald Freudenberger u8 data[1024]; 128855d0a513SHarald Freudenberger } __packed * rep_pl; 128955d0a513SHarald Freudenberger struct ep11_cprb *req = NULL, *rep = NULL; 129055d0a513SHarald Freudenberger struct ep11_target_dev target; 129155d0a513SHarald Freudenberger struct ep11_urb *urb = NULL; 129255d0a513SHarald Freudenberger size_t req_pl_size; 129355d0a513SHarald Freudenberger int api, rc = -ENOMEM; 129455d0a513SHarald Freudenberger u8 *p; 129555d0a513SHarald Freudenberger 129655d0a513SHarald Freudenberger /* request cprb and payload */ 129755d0a513SHarald Freudenberger req_pl_size = sizeof(struct wk_req_pl) + (iv ? 16 : 0) 129855d0a513SHarald Freudenberger + ASN1TAGLEN(keysize) + 4; 129955d0a513SHarald Freudenberger req = alloc_cprb(req_pl_size); 130055d0a513SHarald Freudenberger if (!req) 130155d0a513SHarald Freudenberger goto out; 130255d0a513SHarald Freudenberger if (!mech || mech == 0x80060001) 130355d0a513SHarald Freudenberger req->flags |= 0x20; /* CPACF_WRAP needs special bit */ 130455d0a513SHarald Freudenberger req_pl = (struct wk_req_pl *)(((u8 *)req) + sizeof(*req)); 1305*386cb81eSHolger Dengler api = (!mech || mech == 0x80060001) ? /* CKM_IBM_CPACF_WRAP */ 1306*386cb81eSHolger Dengler EP11_API_V4 : EP11_API_V1; 130755d0a513SHarald Freudenberger prep_head(&req_pl->head, req_pl_size, api, 33); /* WrapKey */ 130855d0a513SHarald Freudenberger req_pl->var_tag = 0x04; 130955d0a513SHarald Freudenberger req_pl->var_len = sizeof(u32); 131055d0a513SHarald Freudenberger /* mech is mech + mech params (iv here) */ 131155d0a513SHarald Freudenberger req_pl->mech_tag = 0x04; 131255d0a513SHarald Freudenberger req_pl->mech_len = sizeof(u32) + (iv ? 16 : 0); 131355d0a513SHarald Freudenberger req_pl->mech = (mech ? mech : 0x80060001); /* CKM_IBM_CPACF_WRAP */ 131455d0a513SHarald Freudenberger p = ((u8 *)req_pl) + sizeof(*req_pl); 131555d0a513SHarald Freudenberger if (iv) { 131655d0a513SHarald Freudenberger memcpy(p, iv, 16); 131755d0a513SHarald Freudenberger p += 16; 131855d0a513SHarald Freudenberger } 131955d0a513SHarald Freudenberger /* key blob */ 132055d0a513SHarald Freudenberger p += asn1tag_write(p, 0x04, key, keysize); 132155d0a513SHarald Freudenberger /* empty kek tag */ 132255d0a513SHarald Freudenberger *p++ = 0x04; 132355d0a513SHarald Freudenberger *p++ = 0; 132455d0a513SHarald Freudenberger /* empty mac tag */ 132555d0a513SHarald Freudenberger *p++ = 0x04; 132655d0a513SHarald Freudenberger *p++ = 0; 132755d0a513SHarald Freudenberger 132855d0a513SHarald Freudenberger /* reply cprb and payload */ 132955d0a513SHarald Freudenberger rep = alloc_cprb(sizeof(struct wk_rep_pl)); 133055d0a513SHarald Freudenberger if (!rep) 133155d0a513SHarald Freudenberger goto out; 133255d0a513SHarald Freudenberger rep_pl = (struct wk_rep_pl *)(((u8 *)rep) + sizeof(*rep)); 133355d0a513SHarald Freudenberger 133455d0a513SHarald Freudenberger /* urb and target */ 13352004b57cSHarald Freudenberger urb = kmalloc(sizeof(*urb), GFP_KERNEL); 133655d0a513SHarald Freudenberger if (!urb) 133755d0a513SHarald Freudenberger goto out; 133855d0a513SHarald Freudenberger target.ap_id = card; 133955d0a513SHarald Freudenberger target.dom_id = domain; 134055d0a513SHarald Freudenberger prep_urb(urb, &target, 1, 134155d0a513SHarald Freudenberger req, sizeof(*req) + req_pl_size, 134255d0a513SHarald Freudenberger rep, sizeof(*rep) + sizeof(*rep_pl)); 134355d0a513SHarald Freudenberger 134452f72febSHarald Freudenberger rc = zcrypt_send_ep11_cprb(urb); 134555d0a513SHarald Freudenberger if (rc) { 134655d0a513SHarald Freudenberger DEBUG_ERR( 134755d0a513SHarald Freudenberger "%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n", 134855d0a513SHarald Freudenberger __func__, (int)card, (int)domain, rc); 134955d0a513SHarald Freudenberger goto out; 135055d0a513SHarald Freudenberger } 135155d0a513SHarald Freudenberger 135255d0a513SHarald Freudenberger rc = check_reply_pl((u8 *)rep_pl, __func__); 135355d0a513SHarald Freudenberger if (rc) 135455d0a513SHarald Freudenberger goto out; 135555d0a513SHarald Freudenberger if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) { 135655d0a513SHarald Freudenberger DEBUG_ERR("%s unknown reply data format\n", __func__); 135755d0a513SHarald Freudenberger rc = -EIO; 135855d0a513SHarald Freudenberger goto out; 135955d0a513SHarald Freudenberger } 136055d0a513SHarald Freudenberger if (rep_pl->data_len > *datasize) { 136155d0a513SHarald Freudenberger DEBUG_ERR("%s mismatch reply data len / data buffer len\n", 136255d0a513SHarald Freudenberger __func__); 136355d0a513SHarald Freudenberger rc = -ENOSPC; 136455d0a513SHarald Freudenberger goto out; 136555d0a513SHarald Freudenberger } 136655d0a513SHarald Freudenberger 136755d0a513SHarald Freudenberger /* copy the data from the cprb to the data buffer */ 136855d0a513SHarald Freudenberger memcpy(databuf, rep_pl->data, rep_pl->data_len); 136955d0a513SHarald Freudenberger *datasize = rep_pl->data_len; 137055d0a513SHarald Freudenberger 137155d0a513SHarald Freudenberger out: 137255d0a513SHarald Freudenberger kfree(req); 137355d0a513SHarald Freudenberger kfree(rep); 137455d0a513SHarald Freudenberger kfree(urb); 137555d0a513SHarald Freudenberger return rc; 137655d0a513SHarald Freudenberger } 137755d0a513SHarald Freudenberger 137855d0a513SHarald Freudenberger int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags, 1379da2863f1SHolger Dengler const u8 *clrkey, u8 *keybuf, size_t *keybufsize, 1380da2863f1SHolger Dengler u32 keytype) 138155d0a513SHarald Freudenberger { 138255d0a513SHarald Freudenberger int rc; 138355d0a513SHarald Freudenberger u8 encbuf[64], *kek = NULL; 138455d0a513SHarald Freudenberger size_t clrkeylen, keklen, encbuflen = sizeof(encbuf); 138555d0a513SHarald Freudenberger 13862004b57cSHarald Freudenberger if (keybitsize == 128 || keybitsize == 192 || keybitsize == 256) { 138755d0a513SHarald Freudenberger clrkeylen = keybitsize / 8; 13882004b57cSHarald Freudenberger } else { 138955d0a513SHarald Freudenberger DEBUG_ERR( 139055d0a513SHarald Freudenberger "%s unknown/unsupported keybitsize %d\n", 139155d0a513SHarald Freudenberger __func__, keybitsize); 139255d0a513SHarald Freudenberger return -EINVAL; 139355d0a513SHarald Freudenberger } 139455d0a513SHarald Freudenberger 139555d0a513SHarald Freudenberger /* allocate memory for the temp kek */ 139655d0a513SHarald Freudenberger keklen = MAXEP11AESKEYBLOBSIZE; 139755d0a513SHarald Freudenberger kek = kmalloc(keklen, GFP_ATOMIC); 139855d0a513SHarald Freudenberger if (!kek) { 139955d0a513SHarald Freudenberger rc = -ENOMEM; 140055d0a513SHarald Freudenberger goto out; 140155d0a513SHarald Freudenberger } 140255d0a513SHarald Freudenberger 140355d0a513SHarald Freudenberger /* Step 1: generate AES 256 bit random kek key */ 1404fb249ce7SHolger Dengler rc = _ep11_genaeskey(card, domain, 256, 140505ccaca0SGeert Uytterhoeven 0x00006c00, /* EN/DECRYPT, WRAP/UNWRAP */ 140655d0a513SHarald Freudenberger kek, &keklen); 140755d0a513SHarald Freudenberger if (rc) { 140855d0a513SHarald Freudenberger DEBUG_ERR( 140955d0a513SHarald Freudenberger "%s generate kek key failed, rc=%d\n", 141055d0a513SHarald Freudenberger __func__, rc); 141155d0a513SHarald Freudenberger goto out; 141255d0a513SHarald Freudenberger } 141355d0a513SHarald Freudenberger 141455d0a513SHarald Freudenberger /* Step 2: encrypt clear key value with the kek key */ 141555d0a513SHarald Freudenberger rc = ep11_cryptsingle(card, domain, 0, 0, def_iv, kek, keklen, 141655d0a513SHarald Freudenberger clrkey, clrkeylen, encbuf, &encbuflen); 141755d0a513SHarald Freudenberger if (rc) { 141855d0a513SHarald Freudenberger DEBUG_ERR( 141955d0a513SHarald Freudenberger "%s encrypting key value with kek key failed, rc=%d\n", 142055d0a513SHarald Freudenberger __func__, rc); 142155d0a513SHarald Freudenberger goto out; 142255d0a513SHarald Freudenberger } 142355d0a513SHarald Freudenberger 142455d0a513SHarald Freudenberger /* Step 3: import the encrypted key value as a new key */ 142555d0a513SHarald Freudenberger rc = ep11_unwrapkey(card, domain, kek, keklen, 142655d0a513SHarald Freudenberger encbuf, encbuflen, 0, def_iv, 1427da2863f1SHolger Dengler keybitsize, 0, keybuf, keybufsize, keytype); 142855d0a513SHarald Freudenberger if (rc) { 142955d0a513SHarald Freudenberger DEBUG_ERR( 143055d0a513SHarald Freudenberger "%s importing key value as new key failed,, rc=%d\n", 143155d0a513SHarald Freudenberger __func__, rc); 143255d0a513SHarald Freudenberger goto out; 143355d0a513SHarald Freudenberger } 143455d0a513SHarald Freudenberger 143555d0a513SHarald Freudenberger out: 143655d0a513SHarald Freudenberger kfree(kek); 143755d0a513SHarald Freudenberger return rc; 143855d0a513SHarald Freudenberger } 143955d0a513SHarald Freudenberger EXPORT_SYMBOL(ep11_clr2keyblob); 144055d0a513SHarald Freudenberger 1441d1fdfb0bSHolger Dengler int ep11_kblob2protkey(u16 card, u16 dom, 1442d1fdfb0bSHolger Dengler const u8 *keyblob, size_t keybloblen, 144355d0a513SHarald Freudenberger u8 *protkey, u32 *protkeylen, u32 *protkeytype) 144455d0a513SHarald Freudenberger { 1445d1fdfb0bSHolger Dengler struct ep11kblob_header *hdr; 1446d1fdfb0bSHolger Dengler struct ep11keyblob *key; 1447fa6999e3SHarald Freudenberger size_t wkbuflen, keylen; 144855d0a513SHarald Freudenberger struct wk_info { 144955d0a513SHarald Freudenberger u16 version; 145055d0a513SHarald Freudenberger u8 res1[16]; 145155d0a513SHarald Freudenberger u32 pkeytype; 145255d0a513SHarald Freudenberger u32 pkeybitsize; 145355d0a513SHarald Freudenberger u64 pkeysize; 145455d0a513SHarald Freudenberger u8 res2[8]; 14553b42877cSHarald Freudenberger u8 pkey[]; 145655d0a513SHarald Freudenberger } __packed * wki; 1457d1fdfb0bSHolger Dengler u8 *wkbuf = NULL; 1458d1fdfb0bSHolger Dengler int rc = -EIO; 1459fa6999e3SHarald Freudenberger 1460d1fdfb0bSHolger Dengler if (ep11_kb_decode((u8 *)keyblob, keybloblen, &hdr, NULL, &key, &keylen)) 1461fa6999e3SHarald Freudenberger return -EINVAL; 1462d1fdfb0bSHolger Dengler 1463d1fdfb0bSHolger Dengler if (hdr->version == TOKVER_EP11_AES) { 1464d1fdfb0bSHolger Dengler /* wipe overlayed header */ 1465d1fdfb0bSHolger Dengler memset(hdr, 0, sizeof(*hdr)); 14662004b57cSHarald Freudenberger } 1467d1fdfb0bSHolger Dengler /* !!! hdr is no longer a valid header !!! */ 146855d0a513SHarald Freudenberger 146955d0a513SHarald Freudenberger /* alloc temp working buffer */ 1470fa6999e3SHarald Freudenberger wkbuflen = (keylen + AES_BLOCK_SIZE) & (~(AES_BLOCK_SIZE - 1)); 147155d0a513SHarald Freudenberger wkbuf = kmalloc(wkbuflen, GFP_ATOMIC); 147255d0a513SHarald Freudenberger if (!wkbuf) 147355d0a513SHarald Freudenberger return -ENOMEM; 147455d0a513SHarald Freudenberger 147555d0a513SHarald Freudenberger /* ep11 secure key -> protected key + info */ 1476d1fdfb0bSHolger Dengler rc = _ep11_wrapkey(card, dom, (u8 *)key, keylen, 147755d0a513SHarald Freudenberger 0, def_iv, wkbuf, &wkbuflen); 147855d0a513SHarald Freudenberger if (rc) { 147955d0a513SHarald Freudenberger DEBUG_ERR( 148055d0a513SHarald Freudenberger "%s rewrapping ep11 key to pkey failed, rc=%d\n", 148155d0a513SHarald Freudenberger __func__, rc); 148255d0a513SHarald Freudenberger goto out; 148355d0a513SHarald Freudenberger } 148455d0a513SHarald Freudenberger wki = (struct wk_info *)wkbuf; 148555d0a513SHarald Freudenberger 148655d0a513SHarald Freudenberger /* check struct version and pkey type */ 1487fa6999e3SHarald Freudenberger if (wki->version != 1 || wki->pkeytype < 1 || wki->pkeytype > 5) { 148855d0a513SHarald Freudenberger DEBUG_ERR("%s wk info version %d or pkeytype %d mismatch.\n", 148955d0a513SHarald Freudenberger __func__, (int)wki->version, (int)wki->pkeytype); 149055d0a513SHarald Freudenberger rc = -EIO; 149155d0a513SHarald Freudenberger goto out; 149255d0a513SHarald Freudenberger } 149355d0a513SHarald Freudenberger 1494fa6999e3SHarald Freudenberger /* check protected key type field */ 1495fa6999e3SHarald Freudenberger switch (wki->pkeytype) { 1496fa6999e3SHarald Freudenberger case 1: /* AES */ 149755d0a513SHarald Freudenberger switch (wki->pkeysize) { 149855d0a513SHarald Freudenberger case 16 + 32: 149955d0a513SHarald Freudenberger /* AES 128 protected key */ 150055d0a513SHarald Freudenberger if (protkeytype) 150155d0a513SHarald Freudenberger *protkeytype = PKEY_KEYTYPE_AES_128; 150255d0a513SHarald Freudenberger break; 150355d0a513SHarald Freudenberger case 24 + 32: 150455d0a513SHarald Freudenberger /* AES 192 protected key */ 150555d0a513SHarald Freudenberger if (protkeytype) 150655d0a513SHarald Freudenberger *protkeytype = PKEY_KEYTYPE_AES_192; 150755d0a513SHarald Freudenberger break; 150855d0a513SHarald Freudenberger case 32 + 32: 150955d0a513SHarald Freudenberger /* AES 256 protected key */ 151055d0a513SHarald Freudenberger if (protkeytype) 151155d0a513SHarald Freudenberger *protkeytype = PKEY_KEYTYPE_AES_256; 151255d0a513SHarald Freudenberger break; 151355d0a513SHarald Freudenberger default: 1514fa6999e3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported AES pkeysize %d\n", 151555d0a513SHarald Freudenberger __func__, (int)wki->pkeysize); 151655d0a513SHarald Freudenberger rc = -EIO; 151755d0a513SHarald Freudenberger goto out; 151855d0a513SHarald Freudenberger } 1519fa6999e3SHarald Freudenberger break; 1520fa6999e3SHarald Freudenberger case 3: /* EC-P */ 1521fa6999e3SHarald Freudenberger case 4: /* EC-ED */ 1522fa6999e3SHarald Freudenberger case 5: /* EC-BP */ 1523fa6999e3SHarald Freudenberger if (protkeytype) 1524fa6999e3SHarald Freudenberger *protkeytype = PKEY_KEYTYPE_ECC; 1525fa6999e3SHarald Freudenberger break; 1526fa6999e3SHarald Freudenberger case 2: /* TDES */ 1527fa6999e3SHarald Freudenberger default: 1528fa6999e3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported key type %d\n", 1529fa6999e3SHarald Freudenberger __func__, (int)wki->pkeytype); 1530fa6999e3SHarald Freudenberger rc = -EIO; 1531fa6999e3SHarald Freudenberger goto out; 1532fa6999e3SHarald Freudenberger } 1533fa6999e3SHarald Freudenberger 1534cada938aSHeiko Carstens /* copy the translated protected key */ 1535fa6999e3SHarald Freudenberger if (wki->pkeysize > *protkeylen) { 1536fa6999e3SHarald Freudenberger DEBUG_ERR("%s wk info pkeysize %llu > protkeysize %u\n", 1537fa6999e3SHarald Freudenberger __func__, wki->pkeysize, *protkeylen); 1538fa6999e3SHarald Freudenberger rc = -EINVAL; 1539fa6999e3SHarald Freudenberger goto out; 1540fa6999e3SHarald Freudenberger } 154155d0a513SHarald Freudenberger memcpy(protkey, wki->pkey, wki->pkeysize); 1542fa6999e3SHarald Freudenberger *protkeylen = wki->pkeysize; 154355d0a513SHarald Freudenberger 154455d0a513SHarald Freudenberger out: 154555d0a513SHarald Freudenberger kfree(wkbuf); 154655d0a513SHarald Freudenberger return rc; 154755d0a513SHarald Freudenberger } 1548fa6999e3SHarald Freudenberger EXPORT_SYMBOL(ep11_kblob2protkey); 154955d0a513SHarald Freudenberger 155055d0a513SHarald Freudenberger int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain, 155155d0a513SHarald Freudenberger int minhwtype, int minapi, const u8 *wkvp) 155255d0a513SHarald Freudenberger { 155355d0a513SHarald Freudenberger struct zcrypt_device_status_ext *device_status; 155455d0a513SHarald Freudenberger u32 *_apqns = NULL, _nr_apqns = 0; 155555d0a513SHarald Freudenberger int i, card, dom, rc = -ENOMEM; 155655d0a513SHarald Freudenberger struct ep11_domain_info edi; 155755d0a513SHarald Freudenberger struct ep11_card_info eci; 155855d0a513SHarald Freudenberger 155955d0a513SHarald Freudenberger /* fetch status of all crypto cards */ 156034515df2SHarald Freudenberger device_status = kvmalloc_array(MAX_ZDEV_ENTRIES_EXT, 156155d0a513SHarald Freudenberger sizeof(struct zcrypt_device_status_ext), 156255d0a513SHarald Freudenberger GFP_KERNEL); 156355d0a513SHarald Freudenberger if (!device_status) 156455d0a513SHarald Freudenberger return -ENOMEM; 156555d0a513SHarald Freudenberger zcrypt_device_status_mask_ext(device_status); 156655d0a513SHarald Freudenberger 156755d0a513SHarald Freudenberger /* allocate 1k space for up to 256 apqns */ 156855d0a513SHarald Freudenberger _apqns = kmalloc_array(256, sizeof(u32), GFP_KERNEL); 156955d0a513SHarald Freudenberger if (!_apqns) { 157034515df2SHarald Freudenberger kvfree(device_status); 157155d0a513SHarald Freudenberger return -ENOMEM; 157255d0a513SHarald Freudenberger } 157355d0a513SHarald Freudenberger 157455d0a513SHarald Freudenberger /* walk through all the crypto apqnss */ 157555d0a513SHarald Freudenberger for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) { 157655d0a513SHarald Freudenberger card = AP_QID_CARD(device_status[i].qid); 157755d0a513SHarald Freudenberger dom = AP_QID_QUEUE(device_status[i].qid); 157855d0a513SHarald Freudenberger /* check online state */ 157955d0a513SHarald Freudenberger if (!device_status[i].online) 158055d0a513SHarald Freudenberger continue; 158155d0a513SHarald Freudenberger /* check for ep11 functions */ 158255d0a513SHarald Freudenberger if (!(device_status[i].functions & 0x01)) 158355d0a513SHarald Freudenberger continue; 158455d0a513SHarald Freudenberger /* check cardnr */ 158555d0a513SHarald Freudenberger if (cardnr != 0xFFFF && card != cardnr) 158655d0a513SHarald Freudenberger continue; 158755d0a513SHarald Freudenberger /* check domain */ 158855d0a513SHarald Freudenberger if (domain != 0xFFFF && dom != domain) 158955d0a513SHarald Freudenberger continue; 159055d0a513SHarald Freudenberger /* check min hardware type */ 159155d0a513SHarald Freudenberger if (minhwtype && device_status[i].hwtype < minhwtype) 159255d0a513SHarald Freudenberger continue; 159355d0a513SHarald Freudenberger /* check min api version if given */ 159455d0a513SHarald Freudenberger if (minapi > 0) { 159555d0a513SHarald Freudenberger if (ep11_get_card_info(card, &eci, 0)) 159655d0a513SHarald Freudenberger continue; 159755d0a513SHarald Freudenberger if (minapi > eci.API_ord_nr) 159855d0a513SHarald Freudenberger continue; 159955d0a513SHarald Freudenberger } 160055d0a513SHarald Freudenberger /* check wkvp if given */ 160155d0a513SHarald Freudenberger if (wkvp) { 160255d0a513SHarald Freudenberger if (ep11_get_domain_info(card, dom, &edi)) 160355d0a513SHarald Freudenberger continue; 160455d0a513SHarald Freudenberger if (edi.cur_wk_state != '1') 160555d0a513SHarald Freudenberger continue; 160655d0a513SHarald Freudenberger if (memcmp(wkvp, edi.cur_wkvp, 16)) 160755d0a513SHarald Freudenberger continue; 160855d0a513SHarald Freudenberger } 160955d0a513SHarald Freudenberger /* apqn passed all filtering criterons, add to the array */ 161055d0a513SHarald Freudenberger if (_nr_apqns < 256) 161155d0a513SHarald Freudenberger _apqns[_nr_apqns++] = (((u16)card) << 16) | ((u16)dom); 161255d0a513SHarald Freudenberger } 161355d0a513SHarald Freudenberger 161455d0a513SHarald Freudenberger /* nothing found ? */ 161555d0a513SHarald Freudenberger if (!_nr_apqns) { 161655d0a513SHarald Freudenberger kfree(_apqns); 161755d0a513SHarald Freudenberger rc = -ENODEV; 161855d0a513SHarald Freudenberger } else { 161955d0a513SHarald Freudenberger /* no re-allocation, simple return the _apqns array */ 162055d0a513SHarald Freudenberger *apqns = _apqns; 162155d0a513SHarald Freudenberger *nr_apqns = _nr_apqns; 162255d0a513SHarald Freudenberger rc = 0; 162355d0a513SHarald Freudenberger } 162455d0a513SHarald Freudenberger 162534515df2SHarald Freudenberger kvfree(device_status); 162655d0a513SHarald Freudenberger return rc; 162755d0a513SHarald Freudenberger } 162855d0a513SHarald Freudenberger EXPORT_SYMBOL(ep11_findcard2); 162955d0a513SHarald Freudenberger 16307384eb72SHarald Freudenberger void __exit zcrypt_ep11misc_exit(void) 16317384eb72SHarald Freudenberger { 16327384eb72SHarald Freudenberger card_cache_free(); 16337384eb72SHarald Freudenberger } 1634