18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * pkey device driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright IBM Corp. 2017,2019 68c2ecf20Sopenharmony_ci * Author(s): Harald Freudenberger 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#define KMSG_COMPONENT "pkey" 108c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/fs.h> 138c2ecf20Sopenharmony_ci#include <linux/init.h> 148c2ecf20Sopenharmony_ci#include <linux/miscdevice.h> 158c2ecf20Sopenharmony_ci#include <linux/module.h> 168c2ecf20Sopenharmony_ci#include <linux/slab.h> 178c2ecf20Sopenharmony_ci#include <linux/kallsyms.h> 188c2ecf20Sopenharmony_ci#include <linux/debugfs.h> 198c2ecf20Sopenharmony_ci#include <linux/random.h> 208c2ecf20Sopenharmony_ci#include <linux/cpufeature.h> 218c2ecf20Sopenharmony_ci#include <asm/zcrypt.h> 228c2ecf20Sopenharmony_ci#include <asm/cpacf.h> 238c2ecf20Sopenharmony_ci#include <asm/pkey.h> 248c2ecf20Sopenharmony_ci#include <crypto/aes.h> 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#include "zcrypt_api.h" 278c2ecf20Sopenharmony_ci#include "zcrypt_ccamisc.h" 288c2ecf20Sopenharmony_ci#include "zcrypt_ep11misc.h" 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 318c2ecf20Sopenharmony_ciMODULE_AUTHOR("IBM Corporation"); 328c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("s390 protected key interface"); 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define KEYBLOBBUFSIZE 8192 /* key buffer size used for internal processing */ 358c2ecf20Sopenharmony_ci#define PROTKEYBLOBBUFSIZE 256 /* protected key buffer size used internal */ 368c2ecf20Sopenharmony_ci#define MAXAPQNSINLIST 64 /* max 64 apqns within a apqn list */ 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* 398c2ecf20Sopenharmony_ci * debug feature data and functions 408c2ecf20Sopenharmony_ci */ 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic debug_info_t *debug_info; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#define DEBUG_DBG(...) debug_sprintf_event(debug_info, 6, ##__VA_ARGS__) 458c2ecf20Sopenharmony_ci#define DEBUG_INFO(...) debug_sprintf_event(debug_info, 5, ##__VA_ARGS__) 468c2ecf20Sopenharmony_ci#define DEBUG_WARN(...) debug_sprintf_event(debug_info, 4, ##__VA_ARGS__) 478c2ecf20Sopenharmony_ci#define DEBUG_ERR(...) debug_sprintf_event(debug_info, 3, ##__VA_ARGS__) 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic void __init pkey_debug_init(void) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci /* 5 arguments per dbf entry (including the format string ptr) */ 528c2ecf20Sopenharmony_ci debug_info = debug_register("pkey", 1, 1, 5 * sizeof(long)); 538c2ecf20Sopenharmony_ci debug_register_view(debug_info, &debug_sprintf_view); 548c2ecf20Sopenharmony_ci debug_set_level(debug_info, 3); 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic void __exit pkey_debug_exit(void) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci debug_unregister(debug_info); 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci/* inside view of a protected key token (only type 0x00 version 0x01) */ 638c2ecf20Sopenharmony_cistruct protaeskeytoken { 648c2ecf20Sopenharmony_ci u8 type; /* 0x00 for PAES specific key tokens */ 658c2ecf20Sopenharmony_ci u8 res0[3]; 668c2ecf20Sopenharmony_ci u8 version; /* should be 0x01 for protected AES key token */ 678c2ecf20Sopenharmony_ci u8 res1[3]; 688c2ecf20Sopenharmony_ci u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ 698c2ecf20Sopenharmony_ci u32 len; /* bytes actually stored in protkey[] */ 708c2ecf20Sopenharmony_ci u8 protkey[MAXPROTKEYSIZE]; /* the protected key blob */ 718c2ecf20Sopenharmony_ci} __packed; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci/* inside view of a clear key token (type 0x00 version 0x02) */ 748c2ecf20Sopenharmony_cistruct clearaeskeytoken { 758c2ecf20Sopenharmony_ci u8 type; /* 0x00 for PAES specific key tokens */ 768c2ecf20Sopenharmony_ci u8 res0[3]; 778c2ecf20Sopenharmony_ci u8 version; /* 0x02 for clear AES key token */ 788c2ecf20Sopenharmony_ci u8 res1[3]; 798c2ecf20Sopenharmony_ci u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ 808c2ecf20Sopenharmony_ci u32 len; /* bytes actually stored in clearkey[] */ 818c2ecf20Sopenharmony_ci u8 clearkey[]; /* clear key value */ 828c2ecf20Sopenharmony_ci} __packed; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci/* 858c2ecf20Sopenharmony_ci * Create a protected key from a clear key value. 868c2ecf20Sopenharmony_ci */ 878c2ecf20Sopenharmony_cistatic int pkey_clr2protkey(u32 keytype, 888c2ecf20Sopenharmony_ci const struct pkey_clrkey *clrkey, 898c2ecf20Sopenharmony_ci struct pkey_protkey *protkey) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci /* mask of available pckmo subfunctions */ 928c2ecf20Sopenharmony_ci static cpacf_mask_t pckmo_functions; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci long fc; 958c2ecf20Sopenharmony_ci int keysize; 968c2ecf20Sopenharmony_ci u8 paramblock[64]; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci switch (keytype) { 998c2ecf20Sopenharmony_ci case PKEY_KEYTYPE_AES_128: 1008c2ecf20Sopenharmony_ci keysize = 16; 1018c2ecf20Sopenharmony_ci fc = CPACF_PCKMO_ENC_AES_128_KEY; 1028c2ecf20Sopenharmony_ci break; 1038c2ecf20Sopenharmony_ci case PKEY_KEYTYPE_AES_192: 1048c2ecf20Sopenharmony_ci keysize = 24; 1058c2ecf20Sopenharmony_ci fc = CPACF_PCKMO_ENC_AES_192_KEY; 1068c2ecf20Sopenharmony_ci break; 1078c2ecf20Sopenharmony_ci case PKEY_KEYTYPE_AES_256: 1088c2ecf20Sopenharmony_ci keysize = 32; 1098c2ecf20Sopenharmony_ci fc = CPACF_PCKMO_ENC_AES_256_KEY; 1108c2ecf20Sopenharmony_ci break; 1118c2ecf20Sopenharmony_ci default: 1128c2ecf20Sopenharmony_ci DEBUG_ERR("%s unknown/unsupported keytype %d\n", 1138c2ecf20Sopenharmony_ci __func__, keytype); 1148c2ecf20Sopenharmony_ci return -EINVAL; 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci /* Did we already check for PCKMO ? */ 1188c2ecf20Sopenharmony_ci if (!pckmo_functions.bytes[0]) { 1198c2ecf20Sopenharmony_ci /* no, so check now */ 1208c2ecf20Sopenharmony_ci if (!cpacf_query(CPACF_PCKMO, &pckmo_functions)) 1218c2ecf20Sopenharmony_ci return -ENODEV; 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci /* check for the pckmo subfunction we need now */ 1248c2ecf20Sopenharmony_ci if (!cpacf_test_func(&pckmo_functions, fc)) { 1258c2ecf20Sopenharmony_ci DEBUG_ERR("%s pckmo functions not available\n", __func__); 1268c2ecf20Sopenharmony_ci return -ENODEV; 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci /* prepare param block */ 1308c2ecf20Sopenharmony_ci memset(paramblock, 0, sizeof(paramblock)); 1318c2ecf20Sopenharmony_ci memcpy(paramblock, clrkey->clrkey, keysize); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci /* call the pckmo instruction */ 1348c2ecf20Sopenharmony_ci cpacf_pckmo(fc, paramblock); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci /* copy created protected key */ 1378c2ecf20Sopenharmony_ci protkey->type = keytype; 1388c2ecf20Sopenharmony_ci protkey->len = keysize + 32; 1398c2ecf20Sopenharmony_ci memcpy(protkey->protkey, paramblock, keysize + 32); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci return 0; 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci/* 1458c2ecf20Sopenharmony_ci * Find card and transform secure key into protected key. 1468c2ecf20Sopenharmony_ci */ 1478c2ecf20Sopenharmony_cistatic int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci int rc, verify; 1508c2ecf20Sopenharmony_ci u16 cardnr, domain; 1518c2ecf20Sopenharmony_ci struct keytoken_header *hdr = (struct keytoken_header *)key; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci /* 1548c2ecf20Sopenharmony_ci * The cca_xxx2protkey call may fail when a card has been 1558c2ecf20Sopenharmony_ci * addressed where the master key was changed after last fetch 1568c2ecf20Sopenharmony_ci * of the mkvp into the cache. Try 3 times: First witout verify 1578c2ecf20Sopenharmony_ci * then with verify and last round with verify and old master 1588c2ecf20Sopenharmony_ci * key verification pattern match not ignored. 1598c2ecf20Sopenharmony_ci */ 1608c2ecf20Sopenharmony_ci for (verify = 0; verify < 3; verify++) { 1618c2ecf20Sopenharmony_ci rc = cca_findcard(key, &cardnr, &domain, verify); 1628c2ecf20Sopenharmony_ci if (rc < 0) 1638c2ecf20Sopenharmony_ci continue; 1648c2ecf20Sopenharmony_ci if (rc > 0 && verify < 2) 1658c2ecf20Sopenharmony_ci continue; 1668c2ecf20Sopenharmony_ci switch (hdr->version) { 1678c2ecf20Sopenharmony_ci case TOKVER_CCA_AES: 1688c2ecf20Sopenharmony_ci rc = cca_sec2protkey(cardnr, domain, 1698c2ecf20Sopenharmony_ci key, pkey->protkey, 1708c2ecf20Sopenharmony_ci &pkey->len, &pkey->type); 1718c2ecf20Sopenharmony_ci break; 1728c2ecf20Sopenharmony_ci case TOKVER_CCA_VLSC: 1738c2ecf20Sopenharmony_ci rc = cca_cipher2protkey(cardnr, domain, 1748c2ecf20Sopenharmony_ci key, pkey->protkey, 1758c2ecf20Sopenharmony_ci &pkey->len, &pkey->type); 1768c2ecf20Sopenharmony_ci break; 1778c2ecf20Sopenharmony_ci default: 1788c2ecf20Sopenharmony_ci return -EINVAL; 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci if (rc == 0) 1818c2ecf20Sopenharmony_ci break; 1828c2ecf20Sopenharmony_ci } 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci if (rc) 1858c2ecf20Sopenharmony_ci DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci return rc; 1888c2ecf20Sopenharmony_ci} 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci/* 1918c2ecf20Sopenharmony_ci * Construct EP11 key with given clear key value. 1928c2ecf20Sopenharmony_ci */ 1938c2ecf20Sopenharmony_cistatic int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen, 1948c2ecf20Sopenharmony_ci u8 *keybuf, size_t *keybuflen) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci int i, rc; 1978c2ecf20Sopenharmony_ci u16 card, dom; 1988c2ecf20Sopenharmony_ci u32 nr_apqns, *apqns = NULL; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci /* build a list of apqns suitable for ep11 keys with cpacf support */ 2018c2ecf20Sopenharmony_ci rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 2028c2ecf20Sopenharmony_ci ZCRYPT_CEX7, EP11_API_V, NULL); 2038c2ecf20Sopenharmony_ci if (rc) 2048c2ecf20Sopenharmony_ci goto out; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci /* go through the list of apqns and try to bild an ep11 key */ 2078c2ecf20Sopenharmony_ci for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { 2088c2ecf20Sopenharmony_ci card = apqns[i] >> 16; 2098c2ecf20Sopenharmony_ci dom = apqns[i] & 0xFFFF; 2108c2ecf20Sopenharmony_ci rc = ep11_clr2keyblob(card, dom, clrkeylen * 8, 2118c2ecf20Sopenharmony_ci 0, clrkey, keybuf, keybuflen); 2128c2ecf20Sopenharmony_ci if (rc == 0) 2138c2ecf20Sopenharmony_ci break; 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ciout: 2178c2ecf20Sopenharmony_ci kfree(apqns); 2188c2ecf20Sopenharmony_ci if (rc) 2198c2ecf20Sopenharmony_ci DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 2208c2ecf20Sopenharmony_ci return rc; 2218c2ecf20Sopenharmony_ci} 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci/* 2248c2ecf20Sopenharmony_ci * Find card and transform EP11 secure key into protected key. 2258c2ecf20Sopenharmony_ci */ 2268c2ecf20Sopenharmony_cistatic int pkey_ep11key2pkey(const u8 *key, struct pkey_protkey *pkey) 2278c2ecf20Sopenharmony_ci{ 2288c2ecf20Sopenharmony_ci int i, rc; 2298c2ecf20Sopenharmony_ci u16 card, dom; 2308c2ecf20Sopenharmony_ci u32 nr_apqns, *apqns = NULL; 2318c2ecf20Sopenharmony_ci struct ep11keyblob *kb = (struct ep11keyblob *) key; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci /* build a list of apqns suitable for this key */ 2348c2ecf20Sopenharmony_ci rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 2358c2ecf20Sopenharmony_ci ZCRYPT_CEX7, EP11_API_V, kb->wkvp); 2368c2ecf20Sopenharmony_ci if (rc) 2378c2ecf20Sopenharmony_ci goto out; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci /* go through the list of apqns and try to derive an pkey */ 2408c2ecf20Sopenharmony_ci for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { 2418c2ecf20Sopenharmony_ci card = apqns[i] >> 16; 2428c2ecf20Sopenharmony_ci dom = apqns[i] & 0xFFFF; 2438c2ecf20Sopenharmony_ci pkey->len = sizeof(pkey->protkey); 2448c2ecf20Sopenharmony_ci rc = ep11_kblob2protkey(card, dom, key, kb->head.len, 2458c2ecf20Sopenharmony_ci pkey->protkey, &pkey->len, &pkey->type); 2468c2ecf20Sopenharmony_ci if (rc == 0) 2478c2ecf20Sopenharmony_ci break; 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ciout: 2518c2ecf20Sopenharmony_ci kfree(apqns); 2528c2ecf20Sopenharmony_ci if (rc) 2538c2ecf20Sopenharmony_ci DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 2548c2ecf20Sopenharmony_ci return rc; 2558c2ecf20Sopenharmony_ci} 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci/* 2588c2ecf20Sopenharmony_ci * Verify key and give back some info about the key. 2598c2ecf20Sopenharmony_ci */ 2608c2ecf20Sopenharmony_cistatic int pkey_verifykey(const struct pkey_seckey *seckey, 2618c2ecf20Sopenharmony_ci u16 *pcardnr, u16 *pdomain, 2628c2ecf20Sopenharmony_ci u16 *pkeysize, u32 *pattributes) 2638c2ecf20Sopenharmony_ci{ 2648c2ecf20Sopenharmony_ci struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; 2658c2ecf20Sopenharmony_ci u16 cardnr, domain; 2668c2ecf20Sopenharmony_ci int rc; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci /* check the secure key for valid AES secure key */ 2698c2ecf20Sopenharmony_ci rc = cca_check_secaeskeytoken(debug_info, 3, (u8 *) seckey, 0); 2708c2ecf20Sopenharmony_ci if (rc) 2718c2ecf20Sopenharmony_ci goto out; 2728c2ecf20Sopenharmony_ci if (pattributes) 2738c2ecf20Sopenharmony_ci *pattributes = PKEY_VERIFY_ATTR_AES; 2748c2ecf20Sopenharmony_ci if (pkeysize) 2758c2ecf20Sopenharmony_ci *pkeysize = t->bitsize; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci /* try to find a card which can handle this key */ 2788c2ecf20Sopenharmony_ci rc = cca_findcard(seckey->seckey, &cardnr, &domain, 1); 2798c2ecf20Sopenharmony_ci if (rc < 0) 2808c2ecf20Sopenharmony_ci goto out; 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci if (rc > 0) { 2838c2ecf20Sopenharmony_ci /* key mkvp matches to old master key mkvp */ 2848c2ecf20Sopenharmony_ci DEBUG_DBG("%s secure key has old mkvp\n", __func__); 2858c2ecf20Sopenharmony_ci if (pattributes) 2868c2ecf20Sopenharmony_ci *pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP; 2878c2ecf20Sopenharmony_ci rc = 0; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci if (pcardnr) 2918c2ecf20Sopenharmony_ci *pcardnr = cardnr; 2928c2ecf20Sopenharmony_ci if (pdomain) 2938c2ecf20Sopenharmony_ci *pdomain = domain; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ciout: 2968c2ecf20Sopenharmony_ci DEBUG_DBG("%s rc=%d\n", __func__, rc); 2978c2ecf20Sopenharmony_ci return rc; 2988c2ecf20Sopenharmony_ci} 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci/* 3018c2ecf20Sopenharmony_ci * Generate a random protected key 3028c2ecf20Sopenharmony_ci */ 3038c2ecf20Sopenharmony_cistatic int pkey_genprotkey(u32 keytype, struct pkey_protkey *protkey) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci struct pkey_clrkey clrkey; 3068c2ecf20Sopenharmony_ci int keysize; 3078c2ecf20Sopenharmony_ci int rc; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci switch (keytype) { 3108c2ecf20Sopenharmony_ci case PKEY_KEYTYPE_AES_128: 3118c2ecf20Sopenharmony_ci keysize = 16; 3128c2ecf20Sopenharmony_ci break; 3138c2ecf20Sopenharmony_ci case PKEY_KEYTYPE_AES_192: 3148c2ecf20Sopenharmony_ci keysize = 24; 3158c2ecf20Sopenharmony_ci break; 3168c2ecf20Sopenharmony_ci case PKEY_KEYTYPE_AES_256: 3178c2ecf20Sopenharmony_ci keysize = 32; 3188c2ecf20Sopenharmony_ci break; 3198c2ecf20Sopenharmony_ci default: 3208c2ecf20Sopenharmony_ci DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 3218c2ecf20Sopenharmony_ci keytype); 3228c2ecf20Sopenharmony_ci return -EINVAL; 3238c2ecf20Sopenharmony_ci } 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci /* generate a dummy random clear key */ 3268c2ecf20Sopenharmony_ci get_random_bytes(clrkey.clrkey, keysize); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci /* convert it to a dummy protected key */ 3298c2ecf20Sopenharmony_ci rc = pkey_clr2protkey(keytype, &clrkey, protkey); 3308c2ecf20Sopenharmony_ci if (rc) 3318c2ecf20Sopenharmony_ci return rc; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci /* replace the key part of the protected key with random bytes */ 3348c2ecf20Sopenharmony_ci get_random_bytes(protkey->protkey, keysize); 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci return 0; 3378c2ecf20Sopenharmony_ci} 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci/* 3408c2ecf20Sopenharmony_ci * Verify if a protected key is still valid 3418c2ecf20Sopenharmony_ci */ 3428c2ecf20Sopenharmony_cistatic int pkey_verifyprotkey(const struct pkey_protkey *protkey) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci unsigned long fc; 3458c2ecf20Sopenharmony_ci struct { 3468c2ecf20Sopenharmony_ci u8 iv[AES_BLOCK_SIZE]; 3478c2ecf20Sopenharmony_ci u8 key[MAXPROTKEYSIZE]; 3488c2ecf20Sopenharmony_ci } param; 3498c2ecf20Sopenharmony_ci u8 null_msg[AES_BLOCK_SIZE]; 3508c2ecf20Sopenharmony_ci u8 dest_buf[AES_BLOCK_SIZE]; 3518c2ecf20Sopenharmony_ci unsigned int k; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci switch (protkey->type) { 3548c2ecf20Sopenharmony_ci case PKEY_KEYTYPE_AES_128: 3558c2ecf20Sopenharmony_ci fc = CPACF_KMC_PAES_128; 3568c2ecf20Sopenharmony_ci break; 3578c2ecf20Sopenharmony_ci case PKEY_KEYTYPE_AES_192: 3588c2ecf20Sopenharmony_ci fc = CPACF_KMC_PAES_192; 3598c2ecf20Sopenharmony_ci break; 3608c2ecf20Sopenharmony_ci case PKEY_KEYTYPE_AES_256: 3618c2ecf20Sopenharmony_ci fc = CPACF_KMC_PAES_256; 3628c2ecf20Sopenharmony_ci break; 3638c2ecf20Sopenharmony_ci default: 3648c2ecf20Sopenharmony_ci DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 3658c2ecf20Sopenharmony_ci protkey->type); 3668c2ecf20Sopenharmony_ci return -EINVAL; 3678c2ecf20Sopenharmony_ci } 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci memset(null_msg, 0, sizeof(null_msg)); 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci memset(param.iv, 0, sizeof(param.iv)); 3728c2ecf20Sopenharmony_ci memcpy(param.key, protkey->protkey, sizeof(param.key)); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci k = cpacf_kmc(fc | CPACF_ENCRYPT, ¶m, null_msg, dest_buf, 3758c2ecf20Sopenharmony_ci sizeof(null_msg)); 3768c2ecf20Sopenharmony_ci if (k != sizeof(null_msg)) { 3778c2ecf20Sopenharmony_ci DEBUG_ERR("%s protected key is not valid\n", __func__); 3788c2ecf20Sopenharmony_ci return -EKEYREJECTED; 3798c2ecf20Sopenharmony_ci } 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci return 0; 3828c2ecf20Sopenharmony_ci} 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci/* 3858c2ecf20Sopenharmony_ci * Transform a non-CCA key token into a protected key 3868c2ecf20Sopenharmony_ci */ 3878c2ecf20Sopenharmony_cistatic int pkey_nonccatok2pkey(const u8 *key, u32 keylen, 3888c2ecf20Sopenharmony_ci struct pkey_protkey *protkey) 3898c2ecf20Sopenharmony_ci{ 3908c2ecf20Sopenharmony_ci int rc = -EINVAL; 3918c2ecf20Sopenharmony_ci u8 *tmpbuf = NULL; 3928c2ecf20Sopenharmony_ci struct keytoken_header *hdr = (struct keytoken_header *)key; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci switch (hdr->version) { 3958c2ecf20Sopenharmony_ci case TOKVER_PROTECTED_KEY: { 3968c2ecf20Sopenharmony_ci struct protaeskeytoken *t; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci if (keylen != sizeof(struct protaeskeytoken)) 3998c2ecf20Sopenharmony_ci goto out; 4008c2ecf20Sopenharmony_ci t = (struct protaeskeytoken *)key; 4018c2ecf20Sopenharmony_ci protkey->len = t->len; 4028c2ecf20Sopenharmony_ci protkey->type = t->keytype; 4038c2ecf20Sopenharmony_ci memcpy(protkey->protkey, t->protkey, 4048c2ecf20Sopenharmony_ci sizeof(protkey->protkey)); 4058c2ecf20Sopenharmony_ci rc = pkey_verifyprotkey(protkey); 4068c2ecf20Sopenharmony_ci break; 4078c2ecf20Sopenharmony_ci } 4088c2ecf20Sopenharmony_ci case TOKVER_CLEAR_KEY: { 4098c2ecf20Sopenharmony_ci struct clearaeskeytoken *t; 4108c2ecf20Sopenharmony_ci struct pkey_clrkey ckey; 4118c2ecf20Sopenharmony_ci union u_tmpbuf { 4128c2ecf20Sopenharmony_ci u8 skey[SECKEYBLOBSIZE]; 4138c2ecf20Sopenharmony_ci u8 ep11key[MAXEP11AESKEYBLOBSIZE]; 4148c2ecf20Sopenharmony_ci }; 4158c2ecf20Sopenharmony_ci size_t tmpbuflen = sizeof(union u_tmpbuf); 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci if (keylen < sizeof(struct clearaeskeytoken)) 4188c2ecf20Sopenharmony_ci goto out; 4198c2ecf20Sopenharmony_ci t = (struct clearaeskeytoken *)key; 4208c2ecf20Sopenharmony_ci if (keylen != sizeof(*t) + t->len) 4218c2ecf20Sopenharmony_ci goto out; 4228c2ecf20Sopenharmony_ci if ((t->keytype == PKEY_KEYTYPE_AES_128 && t->len == 16) 4238c2ecf20Sopenharmony_ci || (t->keytype == PKEY_KEYTYPE_AES_192 && t->len == 24) 4248c2ecf20Sopenharmony_ci || (t->keytype == PKEY_KEYTYPE_AES_256 && t->len == 32)) 4258c2ecf20Sopenharmony_ci memcpy(ckey.clrkey, t->clearkey, t->len); 4268c2ecf20Sopenharmony_ci else 4278c2ecf20Sopenharmony_ci goto out; 4288c2ecf20Sopenharmony_ci /* alloc temp key buffer space */ 4298c2ecf20Sopenharmony_ci tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC); 4308c2ecf20Sopenharmony_ci if (!tmpbuf) { 4318c2ecf20Sopenharmony_ci rc = -ENOMEM; 4328c2ecf20Sopenharmony_ci goto out; 4338c2ecf20Sopenharmony_ci } 4348c2ecf20Sopenharmony_ci /* try direct way with the PCKMO instruction */ 4358c2ecf20Sopenharmony_ci rc = pkey_clr2protkey(t->keytype, &ckey, protkey); 4368c2ecf20Sopenharmony_ci if (rc == 0) 4378c2ecf20Sopenharmony_ci break; 4388c2ecf20Sopenharmony_ci /* PCKMO failed, so try the CCA secure key way */ 4398c2ecf20Sopenharmony_ci rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, 4408c2ecf20Sopenharmony_ci ckey.clrkey, tmpbuf); 4418c2ecf20Sopenharmony_ci if (rc == 0) 4428c2ecf20Sopenharmony_ci rc = pkey_skey2pkey(tmpbuf, protkey); 4438c2ecf20Sopenharmony_ci if (rc == 0) 4448c2ecf20Sopenharmony_ci break; 4458c2ecf20Sopenharmony_ci /* if the CCA way also failed, let's try via EP11 */ 4468c2ecf20Sopenharmony_ci rc = pkey_clr2ep11key(ckey.clrkey, t->len, 4478c2ecf20Sopenharmony_ci tmpbuf, &tmpbuflen); 4488c2ecf20Sopenharmony_ci if (rc == 0) 4498c2ecf20Sopenharmony_ci rc = pkey_ep11key2pkey(tmpbuf, protkey); 4508c2ecf20Sopenharmony_ci /* now we should really have an protected key */ 4518c2ecf20Sopenharmony_ci DEBUG_ERR("%s unable to build protected key from clear", 4528c2ecf20Sopenharmony_ci __func__); 4538c2ecf20Sopenharmony_ci break; 4548c2ecf20Sopenharmony_ci } 4558c2ecf20Sopenharmony_ci case TOKVER_EP11_AES: { 4568c2ecf20Sopenharmony_ci /* check ep11 key for exportable as protected key */ 4578c2ecf20Sopenharmony_ci rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); 4588c2ecf20Sopenharmony_ci if (rc) 4598c2ecf20Sopenharmony_ci goto out; 4608c2ecf20Sopenharmony_ci rc = pkey_ep11key2pkey(key, protkey); 4618c2ecf20Sopenharmony_ci break; 4628c2ecf20Sopenharmony_ci } 4638c2ecf20Sopenharmony_ci case TOKVER_EP11_AES_WITH_HEADER: 4648c2ecf20Sopenharmony_ci /* check ep11 key with header for exportable as protected key */ 4658c2ecf20Sopenharmony_ci rc = ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1); 4668c2ecf20Sopenharmony_ci if (rc) 4678c2ecf20Sopenharmony_ci goto out; 4688c2ecf20Sopenharmony_ci rc = pkey_ep11key2pkey(key + sizeof(struct ep11kblob_header), 4698c2ecf20Sopenharmony_ci protkey); 4708c2ecf20Sopenharmony_ci break; 4718c2ecf20Sopenharmony_ci default: 4728c2ecf20Sopenharmony_ci DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n", 4738c2ecf20Sopenharmony_ci __func__, hdr->version); 4748c2ecf20Sopenharmony_ci rc = -EINVAL; 4758c2ecf20Sopenharmony_ci } 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ciout: 4788c2ecf20Sopenharmony_ci kfree(tmpbuf); 4798c2ecf20Sopenharmony_ci return rc; 4808c2ecf20Sopenharmony_ci} 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci/* 4838c2ecf20Sopenharmony_ci * Transform a CCA internal key token into a protected key 4848c2ecf20Sopenharmony_ci */ 4858c2ecf20Sopenharmony_cistatic int pkey_ccainttok2pkey(const u8 *key, u32 keylen, 4868c2ecf20Sopenharmony_ci struct pkey_protkey *protkey) 4878c2ecf20Sopenharmony_ci{ 4888c2ecf20Sopenharmony_ci struct keytoken_header *hdr = (struct keytoken_header *)key; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci switch (hdr->version) { 4918c2ecf20Sopenharmony_ci case TOKVER_CCA_AES: 4928c2ecf20Sopenharmony_ci if (keylen != sizeof(struct secaeskeytoken)) 4938c2ecf20Sopenharmony_ci return -EINVAL; 4948c2ecf20Sopenharmony_ci break; 4958c2ecf20Sopenharmony_ci case TOKVER_CCA_VLSC: 4968c2ecf20Sopenharmony_ci if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 4978c2ecf20Sopenharmony_ci return -EINVAL; 4988c2ecf20Sopenharmony_ci break; 4998c2ecf20Sopenharmony_ci default: 5008c2ecf20Sopenharmony_ci DEBUG_ERR("%s unknown/unsupported CCA internal token version %d\n", 5018c2ecf20Sopenharmony_ci __func__, hdr->version); 5028c2ecf20Sopenharmony_ci return -EINVAL; 5038c2ecf20Sopenharmony_ci } 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci return pkey_skey2pkey(key, protkey); 5068c2ecf20Sopenharmony_ci} 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci/* 5098c2ecf20Sopenharmony_ci * Transform a key blob (of any type) into a protected key 5108c2ecf20Sopenharmony_ci */ 5118c2ecf20Sopenharmony_ciint pkey_keyblob2pkey(const u8 *key, u32 keylen, 5128c2ecf20Sopenharmony_ci struct pkey_protkey *protkey) 5138c2ecf20Sopenharmony_ci{ 5148c2ecf20Sopenharmony_ci int rc; 5158c2ecf20Sopenharmony_ci struct keytoken_header *hdr = (struct keytoken_header *)key; 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci if (keylen < sizeof(struct keytoken_header)) { 5188c2ecf20Sopenharmony_ci DEBUG_ERR("%s invalid keylen %d\n", __func__, keylen); 5198c2ecf20Sopenharmony_ci return -EINVAL; 5208c2ecf20Sopenharmony_ci } 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci switch (hdr->type) { 5238c2ecf20Sopenharmony_ci case TOKTYPE_NON_CCA: 5248c2ecf20Sopenharmony_ci rc = pkey_nonccatok2pkey(key, keylen, protkey); 5258c2ecf20Sopenharmony_ci break; 5268c2ecf20Sopenharmony_ci case TOKTYPE_CCA_INTERNAL: 5278c2ecf20Sopenharmony_ci rc = pkey_ccainttok2pkey(key, keylen, protkey); 5288c2ecf20Sopenharmony_ci break; 5298c2ecf20Sopenharmony_ci default: 5308c2ecf20Sopenharmony_ci DEBUG_ERR("%s unknown/unsupported blob type %d\n", 5318c2ecf20Sopenharmony_ci __func__, hdr->type); 5328c2ecf20Sopenharmony_ci return -EINVAL; 5338c2ecf20Sopenharmony_ci } 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci DEBUG_DBG("%s rc=%d\n", __func__, rc); 5368c2ecf20Sopenharmony_ci return rc; 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci} 5398c2ecf20Sopenharmony_ciEXPORT_SYMBOL(pkey_keyblob2pkey); 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_cistatic int pkey_genseckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 5428c2ecf20Sopenharmony_ci enum pkey_key_type ktype, enum pkey_key_size ksize, 5438c2ecf20Sopenharmony_ci u32 kflags, u8 *keybuf, size_t *keybufsize) 5448c2ecf20Sopenharmony_ci{ 5458c2ecf20Sopenharmony_ci int i, card, dom, rc; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci /* check for at least one apqn given */ 5488c2ecf20Sopenharmony_ci if (!apqns || !nr_apqns) 5498c2ecf20Sopenharmony_ci return -EINVAL; 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci /* check key type and size */ 5528c2ecf20Sopenharmony_ci switch (ktype) { 5538c2ecf20Sopenharmony_ci case PKEY_TYPE_CCA_DATA: 5548c2ecf20Sopenharmony_ci case PKEY_TYPE_CCA_CIPHER: 5558c2ecf20Sopenharmony_ci if (*keybufsize < SECKEYBLOBSIZE) 5568c2ecf20Sopenharmony_ci return -EINVAL; 5578c2ecf20Sopenharmony_ci break; 5588c2ecf20Sopenharmony_ci case PKEY_TYPE_EP11: 5598c2ecf20Sopenharmony_ci if (*keybufsize < MINEP11AESKEYBLOBSIZE) 5608c2ecf20Sopenharmony_ci return -EINVAL; 5618c2ecf20Sopenharmony_ci break; 5628c2ecf20Sopenharmony_ci default: 5638c2ecf20Sopenharmony_ci return -EINVAL; 5648c2ecf20Sopenharmony_ci } 5658c2ecf20Sopenharmony_ci switch (ksize) { 5668c2ecf20Sopenharmony_ci case PKEY_SIZE_AES_128: 5678c2ecf20Sopenharmony_ci case PKEY_SIZE_AES_192: 5688c2ecf20Sopenharmony_ci case PKEY_SIZE_AES_256: 5698c2ecf20Sopenharmony_ci break; 5708c2ecf20Sopenharmony_ci default: 5718c2ecf20Sopenharmony_ci return -EINVAL; 5728c2ecf20Sopenharmony_ci } 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci /* simple try all apqns from the list */ 5758c2ecf20Sopenharmony_ci for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 5768c2ecf20Sopenharmony_ci card = apqns[i].card; 5778c2ecf20Sopenharmony_ci dom = apqns[i].domain; 5788c2ecf20Sopenharmony_ci if (ktype == PKEY_TYPE_EP11) { 5798c2ecf20Sopenharmony_ci rc = ep11_genaeskey(card, dom, ksize, kflags, 5808c2ecf20Sopenharmony_ci keybuf, keybufsize); 5818c2ecf20Sopenharmony_ci } else if (ktype == PKEY_TYPE_CCA_DATA) { 5828c2ecf20Sopenharmony_ci rc = cca_genseckey(card, dom, ksize, keybuf); 5838c2ecf20Sopenharmony_ci *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 5848c2ecf20Sopenharmony_ci } else /* TOKVER_CCA_VLSC */ 5858c2ecf20Sopenharmony_ci rc = cca_gencipherkey(card, dom, ksize, kflags, 5868c2ecf20Sopenharmony_ci keybuf, keybufsize); 5878c2ecf20Sopenharmony_ci if (rc == 0) 5888c2ecf20Sopenharmony_ci break; 5898c2ecf20Sopenharmony_ci } 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci return rc; 5928c2ecf20Sopenharmony_ci} 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_cistatic int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 5958c2ecf20Sopenharmony_ci enum pkey_key_type ktype, enum pkey_key_size ksize, 5968c2ecf20Sopenharmony_ci u32 kflags, const u8 *clrkey, 5978c2ecf20Sopenharmony_ci u8 *keybuf, size_t *keybufsize) 5988c2ecf20Sopenharmony_ci{ 5998c2ecf20Sopenharmony_ci int i, card, dom, rc; 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci /* check for at least one apqn given */ 6028c2ecf20Sopenharmony_ci if (!apqns || !nr_apqns) 6038c2ecf20Sopenharmony_ci return -EINVAL; 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci /* check key type and size */ 6068c2ecf20Sopenharmony_ci switch (ktype) { 6078c2ecf20Sopenharmony_ci case PKEY_TYPE_CCA_DATA: 6088c2ecf20Sopenharmony_ci case PKEY_TYPE_CCA_CIPHER: 6098c2ecf20Sopenharmony_ci if (*keybufsize < SECKEYBLOBSIZE) 6108c2ecf20Sopenharmony_ci return -EINVAL; 6118c2ecf20Sopenharmony_ci break; 6128c2ecf20Sopenharmony_ci case PKEY_TYPE_EP11: 6138c2ecf20Sopenharmony_ci if (*keybufsize < MINEP11AESKEYBLOBSIZE) 6148c2ecf20Sopenharmony_ci return -EINVAL; 6158c2ecf20Sopenharmony_ci break; 6168c2ecf20Sopenharmony_ci default: 6178c2ecf20Sopenharmony_ci return -EINVAL; 6188c2ecf20Sopenharmony_ci } 6198c2ecf20Sopenharmony_ci switch (ksize) { 6208c2ecf20Sopenharmony_ci case PKEY_SIZE_AES_128: 6218c2ecf20Sopenharmony_ci case PKEY_SIZE_AES_192: 6228c2ecf20Sopenharmony_ci case PKEY_SIZE_AES_256: 6238c2ecf20Sopenharmony_ci break; 6248c2ecf20Sopenharmony_ci default: 6258c2ecf20Sopenharmony_ci return -EINVAL; 6268c2ecf20Sopenharmony_ci } 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci /* simple try all apqns from the list */ 6298c2ecf20Sopenharmony_ci for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 6308c2ecf20Sopenharmony_ci card = apqns[i].card; 6318c2ecf20Sopenharmony_ci dom = apqns[i].domain; 6328c2ecf20Sopenharmony_ci if (ktype == PKEY_TYPE_EP11) { 6338c2ecf20Sopenharmony_ci rc = ep11_clr2keyblob(card, dom, ksize, kflags, 6348c2ecf20Sopenharmony_ci clrkey, keybuf, keybufsize); 6358c2ecf20Sopenharmony_ci } else if (ktype == PKEY_TYPE_CCA_DATA) { 6368c2ecf20Sopenharmony_ci rc = cca_clr2seckey(card, dom, ksize, 6378c2ecf20Sopenharmony_ci clrkey, keybuf); 6388c2ecf20Sopenharmony_ci *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 6398c2ecf20Sopenharmony_ci } else /* TOKVER_CCA_VLSC */ 6408c2ecf20Sopenharmony_ci rc = cca_clr2cipherkey(card, dom, ksize, kflags, 6418c2ecf20Sopenharmony_ci clrkey, keybuf, keybufsize); 6428c2ecf20Sopenharmony_ci if (rc == 0) 6438c2ecf20Sopenharmony_ci break; 6448c2ecf20Sopenharmony_ci } 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci return rc; 6478c2ecf20Sopenharmony_ci} 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_cistatic int pkey_verifykey2(const u8 *key, size_t keylen, 6508c2ecf20Sopenharmony_ci u16 *cardnr, u16 *domain, 6518c2ecf20Sopenharmony_ci enum pkey_key_type *ktype, 6528c2ecf20Sopenharmony_ci enum pkey_key_size *ksize, u32 *flags) 6538c2ecf20Sopenharmony_ci{ 6548c2ecf20Sopenharmony_ci int rc; 6558c2ecf20Sopenharmony_ci u32 _nr_apqns, *_apqns = NULL; 6568c2ecf20Sopenharmony_ci struct keytoken_header *hdr = (struct keytoken_header *)key; 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci if (keylen < sizeof(struct keytoken_header)) 6598c2ecf20Sopenharmony_ci return -EINVAL; 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci if (hdr->type == TOKTYPE_CCA_INTERNAL 6628c2ecf20Sopenharmony_ci && hdr->version == TOKVER_CCA_AES) { 6638c2ecf20Sopenharmony_ci struct secaeskeytoken *t = (struct secaeskeytoken *)key; 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci rc = cca_check_secaeskeytoken(debug_info, 3, key, 0); 6668c2ecf20Sopenharmony_ci if (rc) 6678c2ecf20Sopenharmony_ci goto out; 6688c2ecf20Sopenharmony_ci if (ktype) 6698c2ecf20Sopenharmony_ci *ktype = PKEY_TYPE_CCA_DATA; 6708c2ecf20Sopenharmony_ci if (ksize) 6718c2ecf20Sopenharmony_ci *ksize = (enum pkey_key_size) t->bitsize; 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 6748c2ecf20Sopenharmony_ci ZCRYPT_CEX3C, AES_MK_SET, t->mkvp, 0, 1); 6758c2ecf20Sopenharmony_ci if (rc == 0 && flags) 6768c2ecf20Sopenharmony_ci *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 6778c2ecf20Sopenharmony_ci if (rc == -ENODEV) { 6788c2ecf20Sopenharmony_ci rc = cca_findcard2(&_apqns, &_nr_apqns, 6798c2ecf20Sopenharmony_ci *cardnr, *domain, 6808c2ecf20Sopenharmony_ci ZCRYPT_CEX3C, AES_MK_SET, 6818c2ecf20Sopenharmony_ci 0, t->mkvp, 1); 6828c2ecf20Sopenharmony_ci if (rc == 0 && flags) 6838c2ecf20Sopenharmony_ci *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 6848c2ecf20Sopenharmony_ci } 6858c2ecf20Sopenharmony_ci if (rc) 6868c2ecf20Sopenharmony_ci goto out; 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci *cardnr = ((struct pkey_apqn *)_apqns)->card; 6898c2ecf20Sopenharmony_ci *domain = ((struct pkey_apqn *)_apqns)->domain; 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci } else if (hdr->type == TOKTYPE_CCA_INTERNAL 6928c2ecf20Sopenharmony_ci && hdr->version == TOKVER_CCA_VLSC) { 6938c2ecf20Sopenharmony_ci struct cipherkeytoken *t = (struct cipherkeytoken *)key; 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci rc = cca_check_secaescipherkey(debug_info, 3, key, 0, 1); 6968c2ecf20Sopenharmony_ci if (rc) 6978c2ecf20Sopenharmony_ci goto out; 6988c2ecf20Sopenharmony_ci if (ktype) 6998c2ecf20Sopenharmony_ci *ktype = PKEY_TYPE_CCA_CIPHER; 7008c2ecf20Sopenharmony_ci if (ksize) { 7018c2ecf20Sopenharmony_ci *ksize = PKEY_SIZE_UNKNOWN; 7028c2ecf20Sopenharmony_ci if (!t->plfver && t->wpllen == 512) 7038c2ecf20Sopenharmony_ci *ksize = PKEY_SIZE_AES_128; 7048c2ecf20Sopenharmony_ci else if (!t->plfver && t->wpllen == 576) 7058c2ecf20Sopenharmony_ci *ksize = PKEY_SIZE_AES_192; 7068c2ecf20Sopenharmony_ci else if (!t->plfver && t->wpllen == 640) 7078c2ecf20Sopenharmony_ci *ksize = PKEY_SIZE_AES_256; 7088c2ecf20Sopenharmony_ci } 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 7118c2ecf20Sopenharmony_ci ZCRYPT_CEX6, AES_MK_SET, t->mkvp0, 0, 1); 7128c2ecf20Sopenharmony_ci if (rc == 0 && flags) 7138c2ecf20Sopenharmony_ci *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 7148c2ecf20Sopenharmony_ci if (rc == -ENODEV) { 7158c2ecf20Sopenharmony_ci rc = cca_findcard2(&_apqns, &_nr_apqns, 7168c2ecf20Sopenharmony_ci *cardnr, *domain, 7178c2ecf20Sopenharmony_ci ZCRYPT_CEX6, AES_MK_SET, 7188c2ecf20Sopenharmony_ci 0, t->mkvp0, 1); 7198c2ecf20Sopenharmony_ci if (rc == 0 && flags) 7208c2ecf20Sopenharmony_ci *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 7218c2ecf20Sopenharmony_ci } 7228c2ecf20Sopenharmony_ci if (rc) 7238c2ecf20Sopenharmony_ci goto out; 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci *cardnr = ((struct pkey_apqn *)_apqns)->card; 7268c2ecf20Sopenharmony_ci *domain = ((struct pkey_apqn *)_apqns)->domain; 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci } else if (hdr->type == TOKTYPE_NON_CCA 7298c2ecf20Sopenharmony_ci && hdr->version == TOKVER_EP11_AES) { 7308c2ecf20Sopenharmony_ci struct ep11keyblob *kb = (struct ep11keyblob *)key; 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); 7338c2ecf20Sopenharmony_ci if (rc) 7348c2ecf20Sopenharmony_ci goto out; 7358c2ecf20Sopenharmony_ci if (ktype) 7368c2ecf20Sopenharmony_ci *ktype = PKEY_TYPE_EP11; 7378c2ecf20Sopenharmony_ci if (ksize) 7388c2ecf20Sopenharmony_ci *ksize = kb->head.bitlen; 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 7418c2ecf20Sopenharmony_ci ZCRYPT_CEX7, EP11_API_V, kb->wkvp); 7428c2ecf20Sopenharmony_ci if (rc) 7438c2ecf20Sopenharmony_ci goto out; 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci if (flags) 7468c2ecf20Sopenharmony_ci *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci *cardnr = ((struct pkey_apqn *)_apqns)->card; 7498c2ecf20Sopenharmony_ci *domain = ((struct pkey_apqn *)_apqns)->domain; 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci } else 7528c2ecf20Sopenharmony_ci rc = -EINVAL; 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ciout: 7558c2ecf20Sopenharmony_ci kfree(_apqns); 7568c2ecf20Sopenharmony_ci return rc; 7578c2ecf20Sopenharmony_ci} 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_cistatic int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, 7608c2ecf20Sopenharmony_ci const u8 *key, size_t keylen, 7618c2ecf20Sopenharmony_ci struct pkey_protkey *pkey) 7628c2ecf20Sopenharmony_ci{ 7638c2ecf20Sopenharmony_ci int i, card, dom, rc; 7648c2ecf20Sopenharmony_ci struct keytoken_header *hdr = (struct keytoken_header *)key; 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci /* check for at least one apqn given */ 7678c2ecf20Sopenharmony_ci if (!apqns || !nr_apqns) 7688c2ecf20Sopenharmony_ci return -EINVAL; 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci if (keylen < sizeof(struct keytoken_header)) 7718c2ecf20Sopenharmony_ci return -EINVAL; 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci if (hdr->type == TOKTYPE_CCA_INTERNAL) { 7748c2ecf20Sopenharmony_ci if (hdr->version == TOKVER_CCA_AES) { 7758c2ecf20Sopenharmony_ci if (keylen != sizeof(struct secaeskeytoken)) 7768c2ecf20Sopenharmony_ci return -EINVAL; 7778c2ecf20Sopenharmony_ci if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) 7788c2ecf20Sopenharmony_ci return -EINVAL; 7798c2ecf20Sopenharmony_ci } else if (hdr->version == TOKVER_CCA_VLSC) { 7808c2ecf20Sopenharmony_ci if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 7818c2ecf20Sopenharmony_ci return -EINVAL; 7828c2ecf20Sopenharmony_ci if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) 7838c2ecf20Sopenharmony_ci return -EINVAL; 7848c2ecf20Sopenharmony_ci } else { 7858c2ecf20Sopenharmony_ci DEBUG_ERR("%s unknown CCA internal token version %d\n", 7868c2ecf20Sopenharmony_ci __func__, hdr->version); 7878c2ecf20Sopenharmony_ci return -EINVAL; 7888c2ecf20Sopenharmony_ci } 7898c2ecf20Sopenharmony_ci } else if (hdr->type == TOKTYPE_NON_CCA) { 7908c2ecf20Sopenharmony_ci if (hdr->version == TOKVER_EP11_AES) { 7918c2ecf20Sopenharmony_ci if (keylen < sizeof(struct ep11keyblob)) 7928c2ecf20Sopenharmony_ci return -EINVAL; 7938c2ecf20Sopenharmony_ci if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) 7948c2ecf20Sopenharmony_ci return -EINVAL; 7958c2ecf20Sopenharmony_ci } else { 7968c2ecf20Sopenharmony_ci return pkey_nonccatok2pkey(key, keylen, pkey); 7978c2ecf20Sopenharmony_ci } 7988c2ecf20Sopenharmony_ci } else { 7998c2ecf20Sopenharmony_ci DEBUG_ERR("%s unknown/unsupported blob type %d\n", 8008c2ecf20Sopenharmony_ci __func__, hdr->type); 8018c2ecf20Sopenharmony_ci return -EINVAL; 8028c2ecf20Sopenharmony_ci } 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci /* simple try all apqns from the list */ 8058c2ecf20Sopenharmony_ci for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 8068c2ecf20Sopenharmony_ci card = apqns[i].card; 8078c2ecf20Sopenharmony_ci dom = apqns[i].domain; 8088c2ecf20Sopenharmony_ci if (hdr->type == TOKTYPE_CCA_INTERNAL 8098c2ecf20Sopenharmony_ci && hdr->version == TOKVER_CCA_AES) 8108c2ecf20Sopenharmony_ci rc = cca_sec2protkey(card, dom, key, pkey->protkey, 8118c2ecf20Sopenharmony_ci &pkey->len, &pkey->type); 8128c2ecf20Sopenharmony_ci else if (hdr->type == TOKTYPE_CCA_INTERNAL 8138c2ecf20Sopenharmony_ci && hdr->version == TOKVER_CCA_VLSC) 8148c2ecf20Sopenharmony_ci rc = cca_cipher2protkey(card, dom, key, pkey->protkey, 8158c2ecf20Sopenharmony_ci &pkey->len, &pkey->type); 8168c2ecf20Sopenharmony_ci else { /* EP11 AES secure key blob */ 8178c2ecf20Sopenharmony_ci struct ep11keyblob *kb = (struct ep11keyblob *) key; 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci pkey->len = sizeof(pkey->protkey); 8208c2ecf20Sopenharmony_ci rc = ep11_kblob2protkey(card, dom, key, kb->head.len, 8218c2ecf20Sopenharmony_ci pkey->protkey, &pkey->len, 8228c2ecf20Sopenharmony_ci &pkey->type); 8238c2ecf20Sopenharmony_ci } 8248c2ecf20Sopenharmony_ci if (rc == 0) 8258c2ecf20Sopenharmony_ci break; 8268c2ecf20Sopenharmony_ci } 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci return rc; 8298c2ecf20Sopenharmony_ci} 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_cistatic int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, 8328c2ecf20Sopenharmony_ci struct pkey_apqn *apqns, size_t *nr_apqns) 8338c2ecf20Sopenharmony_ci{ 8348c2ecf20Sopenharmony_ci int rc; 8358c2ecf20Sopenharmony_ci u32 _nr_apqns, *_apqns = NULL; 8368c2ecf20Sopenharmony_ci struct keytoken_header *hdr = (struct keytoken_header *)key; 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci if (keylen < sizeof(struct keytoken_header) || flags == 0) 8398c2ecf20Sopenharmony_ci return -EINVAL; 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci if (hdr->type == TOKTYPE_NON_CCA 8428c2ecf20Sopenharmony_ci && (hdr->version == TOKVER_EP11_AES_WITH_HEADER 8438c2ecf20Sopenharmony_ci || hdr->version == TOKVER_EP11_ECC_WITH_HEADER) 8448c2ecf20Sopenharmony_ci && is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 8458c2ecf20Sopenharmony_ci int minhwtype = 0, api = 0; 8468c2ecf20Sopenharmony_ci struct ep11keyblob *kb = (struct ep11keyblob *) 8478c2ecf20Sopenharmony_ci (key + sizeof(struct ep11kblob_header)); 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) 8508c2ecf20Sopenharmony_ci return -EINVAL; 8518c2ecf20Sopenharmony_ci if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { 8528c2ecf20Sopenharmony_ci minhwtype = ZCRYPT_CEX7; 8538c2ecf20Sopenharmony_ci api = EP11_API_V; 8548c2ecf20Sopenharmony_ci } 8558c2ecf20Sopenharmony_ci rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 8568c2ecf20Sopenharmony_ci minhwtype, api, kb->wkvp); 8578c2ecf20Sopenharmony_ci if (rc) 8588c2ecf20Sopenharmony_ci goto out; 8598c2ecf20Sopenharmony_ci } else if (hdr->type == TOKTYPE_NON_CCA 8608c2ecf20Sopenharmony_ci && hdr->version == TOKVER_EP11_AES 8618c2ecf20Sopenharmony_ci && is_ep11_keyblob(key)) { 8628c2ecf20Sopenharmony_ci int minhwtype = 0, api = 0; 8638c2ecf20Sopenharmony_ci struct ep11keyblob *kb = (struct ep11keyblob *) key; 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) 8668c2ecf20Sopenharmony_ci return -EINVAL; 8678c2ecf20Sopenharmony_ci if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { 8688c2ecf20Sopenharmony_ci minhwtype = ZCRYPT_CEX7; 8698c2ecf20Sopenharmony_ci api = EP11_API_V; 8708c2ecf20Sopenharmony_ci } 8718c2ecf20Sopenharmony_ci rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 8728c2ecf20Sopenharmony_ci minhwtype, api, kb->wkvp); 8738c2ecf20Sopenharmony_ci if (rc) 8748c2ecf20Sopenharmony_ci goto out; 8758c2ecf20Sopenharmony_ci } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { 8768c2ecf20Sopenharmony_ci int minhwtype = ZCRYPT_CEX3C; 8778c2ecf20Sopenharmony_ci u64 cur_mkvp = 0, old_mkvp = 0; 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci if (hdr->version == TOKVER_CCA_AES) { 8808c2ecf20Sopenharmony_ci struct secaeskeytoken *t = (struct secaeskeytoken *)key; 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 8838c2ecf20Sopenharmony_ci cur_mkvp = t->mkvp; 8848c2ecf20Sopenharmony_ci if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 8858c2ecf20Sopenharmony_ci old_mkvp = t->mkvp; 8868c2ecf20Sopenharmony_ci } else if (hdr->version == TOKVER_CCA_VLSC) { 8878c2ecf20Sopenharmony_ci struct cipherkeytoken *t = (struct cipherkeytoken *)key; 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci minhwtype = ZCRYPT_CEX6; 8908c2ecf20Sopenharmony_ci if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 8918c2ecf20Sopenharmony_ci cur_mkvp = t->mkvp0; 8928c2ecf20Sopenharmony_ci if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 8938c2ecf20Sopenharmony_ci old_mkvp = t->mkvp0; 8948c2ecf20Sopenharmony_ci } else { 8958c2ecf20Sopenharmony_ci /* unknown cca internal token type */ 8968c2ecf20Sopenharmony_ci return -EINVAL; 8978c2ecf20Sopenharmony_ci } 8988c2ecf20Sopenharmony_ci rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 8998c2ecf20Sopenharmony_ci minhwtype, AES_MK_SET, 9008c2ecf20Sopenharmony_ci cur_mkvp, old_mkvp, 1); 9018c2ecf20Sopenharmony_ci if (rc) 9028c2ecf20Sopenharmony_ci goto out; 9038c2ecf20Sopenharmony_ci } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { 9048c2ecf20Sopenharmony_ci u64 cur_mkvp = 0, old_mkvp = 0; 9058c2ecf20Sopenharmony_ci struct eccprivkeytoken *t = (struct eccprivkeytoken *)key; 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci if (t->secid == 0x20) { 9088c2ecf20Sopenharmony_ci if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 9098c2ecf20Sopenharmony_ci cur_mkvp = t->mkvp; 9108c2ecf20Sopenharmony_ci if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 9118c2ecf20Sopenharmony_ci old_mkvp = t->mkvp; 9128c2ecf20Sopenharmony_ci } else { 9138c2ecf20Sopenharmony_ci /* unknown cca internal 2 token type */ 9148c2ecf20Sopenharmony_ci return -EINVAL; 9158c2ecf20Sopenharmony_ci } 9168c2ecf20Sopenharmony_ci rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 9178c2ecf20Sopenharmony_ci ZCRYPT_CEX7, APKA_MK_SET, 9188c2ecf20Sopenharmony_ci cur_mkvp, old_mkvp, 1); 9198c2ecf20Sopenharmony_ci if (rc) 9208c2ecf20Sopenharmony_ci goto out; 9218c2ecf20Sopenharmony_ci } else 9228c2ecf20Sopenharmony_ci return -EINVAL; 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci if (apqns) { 9258c2ecf20Sopenharmony_ci if (*nr_apqns < _nr_apqns) 9268c2ecf20Sopenharmony_ci rc = -ENOSPC; 9278c2ecf20Sopenharmony_ci else 9288c2ecf20Sopenharmony_ci memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 9298c2ecf20Sopenharmony_ci } 9308c2ecf20Sopenharmony_ci *nr_apqns = _nr_apqns; 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ciout: 9338c2ecf20Sopenharmony_ci kfree(_apqns); 9348c2ecf20Sopenharmony_ci return rc; 9358c2ecf20Sopenharmony_ci} 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_cistatic int pkey_apqns4keytype(enum pkey_key_type ktype, 9388c2ecf20Sopenharmony_ci u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, 9398c2ecf20Sopenharmony_ci struct pkey_apqn *apqns, size_t *nr_apqns) 9408c2ecf20Sopenharmony_ci{ 9418c2ecf20Sopenharmony_ci int rc; 9428c2ecf20Sopenharmony_ci u32 _nr_apqns, *_apqns = NULL; 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_ci if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) { 9458c2ecf20Sopenharmony_ci u64 cur_mkvp = 0, old_mkvp = 0; 9468c2ecf20Sopenharmony_ci int minhwtype = ZCRYPT_CEX3C; 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_ci if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 9498c2ecf20Sopenharmony_ci cur_mkvp = *((u64 *) cur_mkvp); 9508c2ecf20Sopenharmony_ci if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 9518c2ecf20Sopenharmony_ci old_mkvp = *((u64 *) alt_mkvp); 9528c2ecf20Sopenharmony_ci if (ktype == PKEY_TYPE_CCA_CIPHER) 9538c2ecf20Sopenharmony_ci minhwtype = ZCRYPT_CEX6; 9548c2ecf20Sopenharmony_ci rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 9558c2ecf20Sopenharmony_ci minhwtype, AES_MK_SET, 9568c2ecf20Sopenharmony_ci cur_mkvp, old_mkvp, 1); 9578c2ecf20Sopenharmony_ci if (rc) 9588c2ecf20Sopenharmony_ci goto out; 9598c2ecf20Sopenharmony_ci } else if (ktype == PKEY_TYPE_CCA_ECC) { 9608c2ecf20Sopenharmony_ci u64 cur_mkvp = 0, old_mkvp = 0; 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_ci if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 9638c2ecf20Sopenharmony_ci cur_mkvp = *((u64 *) cur_mkvp); 9648c2ecf20Sopenharmony_ci if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 9658c2ecf20Sopenharmony_ci old_mkvp = *((u64 *) alt_mkvp); 9668c2ecf20Sopenharmony_ci rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 9678c2ecf20Sopenharmony_ci ZCRYPT_CEX7, APKA_MK_SET, 9688c2ecf20Sopenharmony_ci cur_mkvp, old_mkvp, 1); 9698c2ecf20Sopenharmony_ci if (rc) 9708c2ecf20Sopenharmony_ci goto out; 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci } else if (ktype == PKEY_TYPE_EP11 || 9738c2ecf20Sopenharmony_ci ktype == PKEY_TYPE_EP11_AES || 9748c2ecf20Sopenharmony_ci ktype == PKEY_TYPE_EP11_ECC) { 9758c2ecf20Sopenharmony_ci u8 *wkvp = NULL; 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 9788c2ecf20Sopenharmony_ci wkvp = cur_mkvp; 9798c2ecf20Sopenharmony_ci rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 9808c2ecf20Sopenharmony_ci ZCRYPT_CEX7, EP11_API_V, wkvp); 9818c2ecf20Sopenharmony_ci if (rc) 9828c2ecf20Sopenharmony_ci goto out; 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci } else 9858c2ecf20Sopenharmony_ci return -EINVAL; 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci if (apqns) { 9888c2ecf20Sopenharmony_ci if (*nr_apqns < _nr_apqns) 9898c2ecf20Sopenharmony_ci rc = -ENOSPC; 9908c2ecf20Sopenharmony_ci else 9918c2ecf20Sopenharmony_ci memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 9928c2ecf20Sopenharmony_ci } 9938c2ecf20Sopenharmony_ci *nr_apqns = _nr_apqns; 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ciout: 9968c2ecf20Sopenharmony_ci kfree(_apqns); 9978c2ecf20Sopenharmony_ci return rc; 9988c2ecf20Sopenharmony_ci} 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_cistatic int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns, 10018c2ecf20Sopenharmony_ci const u8 *key, size_t keylen, u32 *protkeytype, 10028c2ecf20Sopenharmony_ci u8 *protkey, u32 *protkeylen) 10038c2ecf20Sopenharmony_ci{ 10048c2ecf20Sopenharmony_ci int i, card, dom, rc; 10058c2ecf20Sopenharmony_ci struct keytoken_header *hdr = (struct keytoken_header *)key; 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci /* check for at least one apqn given */ 10088c2ecf20Sopenharmony_ci if (!apqns || !nr_apqns) 10098c2ecf20Sopenharmony_ci return -EINVAL; 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_ci if (keylen < sizeof(struct keytoken_header)) 10128c2ecf20Sopenharmony_ci return -EINVAL; 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci if (hdr->type == TOKTYPE_NON_CCA 10158c2ecf20Sopenharmony_ci && hdr->version == TOKVER_EP11_AES_WITH_HEADER 10168c2ecf20Sopenharmony_ci && is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 10178c2ecf20Sopenharmony_ci /* EP11 AES key blob with header */ 10188c2ecf20Sopenharmony_ci if (ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1)) 10198c2ecf20Sopenharmony_ci return -EINVAL; 10208c2ecf20Sopenharmony_ci } else if (hdr->type == TOKTYPE_NON_CCA 10218c2ecf20Sopenharmony_ci && hdr->version == TOKVER_EP11_ECC_WITH_HEADER 10228c2ecf20Sopenharmony_ci && is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 10238c2ecf20Sopenharmony_ci /* EP11 ECC key blob with header */ 10248c2ecf20Sopenharmony_ci if (ep11_check_ecc_key_with_hdr(debug_info, 3, key, keylen, 1)) 10258c2ecf20Sopenharmony_ci return -EINVAL; 10268c2ecf20Sopenharmony_ci } else if (hdr->type == TOKTYPE_NON_CCA 10278c2ecf20Sopenharmony_ci && hdr->version == TOKVER_EP11_AES 10288c2ecf20Sopenharmony_ci && is_ep11_keyblob(key)) { 10298c2ecf20Sopenharmony_ci /* EP11 AES key blob with header in session field */ 10308c2ecf20Sopenharmony_ci if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) 10318c2ecf20Sopenharmony_ci return -EINVAL; 10328c2ecf20Sopenharmony_ci } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { 10338c2ecf20Sopenharmony_ci if (hdr->version == TOKVER_CCA_AES) { 10348c2ecf20Sopenharmony_ci /* CCA AES data key */ 10358c2ecf20Sopenharmony_ci if (keylen != sizeof(struct secaeskeytoken)) 10368c2ecf20Sopenharmony_ci return -EINVAL; 10378c2ecf20Sopenharmony_ci if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) 10388c2ecf20Sopenharmony_ci return -EINVAL; 10398c2ecf20Sopenharmony_ci } else if (hdr->version == TOKVER_CCA_VLSC) { 10408c2ecf20Sopenharmony_ci /* CCA AES cipher key */ 10418c2ecf20Sopenharmony_ci if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 10428c2ecf20Sopenharmony_ci return -EINVAL; 10438c2ecf20Sopenharmony_ci if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) 10448c2ecf20Sopenharmony_ci return -EINVAL; 10458c2ecf20Sopenharmony_ci } else { 10468c2ecf20Sopenharmony_ci DEBUG_ERR("%s unknown CCA internal token version %d\n", 10478c2ecf20Sopenharmony_ci __func__, hdr->version); 10488c2ecf20Sopenharmony_ci return -EINVAL; 10498c2ecf20Sopenharmony_ci } 10508c2ecf20Sopenharmony_ci } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { 10518c2ecf20Sopenharmony_ci /* CCA ECC (private) key */ 10528c2ecf20Sopenharmony_ci if (keylen < sizeof(struct eccprivkeytoken)) 10538c2ecf20Sopenharmony_ci return -EINVAL; 10548c2ecf20Sopenharmony_ci if (cca_check_sececckeytoken(debug_info, 3, key, keylen, 1)) 10558c2ecf20Sopenharmony_ci return -EINVAL; 10568c2ecf20Sopenharmony_ci } else if (hdr->type == TOKTYPE_NON_CCA) { 10578c2ecf20Sopenharmony_ci struct pkey_protkey pkey; 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci rc = pkey_nonccatok2pkey(key, keylen, &pkey); 10608c2ecf20Sopenharmony_ci if (rc) 10618c2ecf20Sopenharmony_ci return rc; 10628c2ecf20Sopenharmony_ci memcpy(protkey, pkey.protkey, pkey.len); 10638c2ecf20Sopenharmony_ci *protkeylen = pkey.len; 10648c2ecf20Sopenharmony_ci *protkeytype = pkey.type; 10658c2ecf20Sopenharmony_ci return 0; 10668c2ecf20Sopenharmony_ci } else { 10678c2ecf20Sopenharmony_ci DEBUG_ERR("%s unknown/unsupported blob type %d\n", 10688c2ecf20Sopenharmony_ci __func__, hdr->type); 10698c2ecf20Sopenharmony_ci return -EINVAL; 10708c2ecf20Sopenharmony_ci } 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci /* simple try all apqns from the list */ 10738c2ecf20Sopenharmony_ci for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { 10748c2ecf20Sopenharmony_ci card = apqns[i].card; 10758c2ecf20Sopenharmony_ci dom = apqns[i].domain; 10768c2ecf20Sopenharmony_ci if (hdr->type == TOKTYPE_NON_CCA 10778c2ecf20Sopenharmony_ci && (hdr->version == TOKVER_EP11_AES_WITH_HEADER 10788c2ecf20Sopenharmony_ci || hdr->version == TOKVER_EP11_ECC_WITH_HEADER) 10798c2ecf20Sopenharmony_ci && is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) 10808c2ecf20Sopenharmony_ci rc = ep11_kblob2protkey(card, dom, key, hdr->len, 10818c2ecf20Sopenharmony_ci protkey, protkeylen, protkeytype); 10828c2ecf20Sopenharmony_ci else if (hdr->type == TOKTYPE_NON_CCA 10838c2ecf20Sopenharmony_ci && hdr->version == TOKVER_EP11_AES 10848c2ecf20Sopenharmony_ci && is_ep11_keyblob(key)) 10858c2ecf20Sopenharmony_ci rc = ep11_kblob2protkey(card, dom, key, hdr->len, 10868c2ecf20Sopenharmony_ci protkey, protkeylen, protkeytype); 10878c2ecf20Sopenharmony_ci else if (hdr->type == TOKTYPE_CCA_INTERNAL && 10888c2ecf20Sopenharmony_ci hdr->version == TOKVER_CCA_AES) 10898c2ecf20Sopenharmony_ci rc = cca_sec2protkey(card, dom, key, protkey, 10908c2ecf20Sopenharmony_ci protkeylen, protkeytype); 10918c2ecf20Sopenharmony_ci else if (hdr->type == TOKTYPE_CCA_INTERNAL && 10928c2ecf20Sopenharmony_ci hdr->version == TOKVER_CCA_VLSC) 10938c2ecf20Sopenharmony_ci rc = cca_cipher2protkey(card, dom, key, protkey, 10948c2ecf20Sopenharmony_ci protkeylen, protkeytype); 10958c2ecf20Sopenharmony_ci else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) 10968c2ecf20Sopenharmony_ci rc = cca_ecc2protkey(card, dom, key, protkey, 10978c2ecf20Sopenharmony_ci protkeylen, protkeytype); 10988c2ecf20Sopenharmony_ci else 10998c2ecf20Sopenharmony_ci return -EINVAL; 11008c2ecf20Sopenharmony_ci } 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_ci return rc; 11038c2ecf20Sopenharmony_ci} 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci/* 11068c2ecf20Sopenharmony_ci * File io functions 11078c2ecf20Sopenharmony_ci */ 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_cistatic void *_copy_key_from_user(void __user *ukey, size_t keylen) 11108c2ecf20Sopenharmony_ci{ 11118c2ecf20Sopenharmony_ci if (!ukey || keylen < MINKEYBLOBSIZE || keylen > KEYBLOBBUFSIZE) 11128c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci return memdup_user(ukey, keylen); 11158c2ecf20Sopenharmony_ci} 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_cistatic void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns) 11188c2ecf20Sopenharmony_ci{ 11198c2ecf20Sopenharmony_ci if (!uapqns || nr_apqns == 0) 11208c2ecf20Sopenharmony_ci return NULL; 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ci return memdup_user(uapqns, nr_apqns * sizeof(struct pkey_apqn)); 11238c2ecf20Sopenharmony_ci} 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_cistatic long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, 11268c2ecf20Sopenharmony_ci unsigned long arg) 11278c2ecf20Sopenharmony_ci{ 11288c2ecf20Sopenharmony_ci int rc; 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_ci switch (cmd) { 11318c2ecf20Sopenharmony_ci case PKEY_GENSECK: { 11328c2ecf20Sopenharmony_ci struct pkey_genseck __user *ugs = (void __user *) arg; 11338c2ecf20Sopenharmony_ci struct pkey_genseck kgs; 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_ci if (copy_from_user(&kgs, ugs, sizeof(kgs))) 11368c2ecf20Sopenharmony_ci return -EFAULT; 11378c2ecf20Sopenharmony_ci rc = cca_genseckey(kgs.cardnr, kgs.domain, 11388c2ecf20Sopenharmony_ci kgs.keytype, kgs.seckey.seckey); 11398c2ecf20Sopenharmony_ci DEBUG_DBG("%s cca_genseckey()=%d\n", __func__, rc); 11408c2ecf20Sopenharmony_ci if (rc) 11418c2ecf20Sopenharmony_ci break; 11428c2ecf20Sopenharmony_ci if (copy_to_user(ugs, &kgs, sizeof(kgs))) 11438c2ecf20Sopenharmony_ci return -EFAULT; 11448c2ecf20Sopenharmony_ci break; 11458c2ecf20Sopenharmony_ci } 11468c2ecf20Sopenharmony_ci case PKEY_CLR2SECK: { 11478c2ecf20Sopenharmony_ci struct pkey_clr2seck __user *ucs = (void __user *) arg; 11488c2ecf20Sopenharmony_ci struct pkey_clr2seck kcs; 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ci if (copy_from_user(&kcs, ucs, sizeof(kcs))) 11518c2ecf20Sopenharmony_ci return -EFAULT; 11528c2ecf20Sopenharmony_ci rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, 11538c2ecf20Sopenharmony_ci kcs.clrkey.clrkey, kcs.seckey.seckey); 11548c2ecf20Sopenharmony_ci DEBUG_DBG("%s cca_clr2seckey()=%d\n", __func__, rc); 11558c2ecf20Sopenharmony_ci if (rc) 11568c2ecf20Sopenharmony_ci break; 11578c2ecf20Sopenharmony_ci if (copy_to_user(ucs, &kcs, sizeof(kcs))) 11588c2ecf20Sopenharmony_ci return -EFAULT; 11598c2ecf20Sopenharmony_ci memzero_explicit(&kcs, sizeof(kcs)); 11608c2ecf20Sopenharmony_ci break; 11618c2ecf20Sopenharmony_ci } 11628c2ecf20Sopenharmony_ci case PKEY_SEC2PROTK: { 11638c2ecf20Sopenharmony_ci struct pkey_sec2protk __user *usp = (void __user *) arg; 11648c2ecf20Sopenharmony_ci struct pkey_sec2protk ksp; 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci if (copy_from_user(&ksp, usp, sizeof(ksp))) 11678c2ecf20Sopenharmony_ci return -EFAULT; 11688c2ecf20Sopenharmony_ci rc = cca_sec2protkey(ksp.cardnr, ksp.domain, 11698c2ecf20Sopenharmony_ci ksp.seckey.seckey, ksp.protkey.protkey, 11708c2ecf20Sopenharmony_ci &ksp.protkey.len, &ksp.protkey.type); 11718c2ecf20Sopenharmony_ci DEBUG_DBG("%s cca_sec2protkey()=%d\n", __func__, rc); 11728c2ecf20Sopenharmony_ci if (rc) 11738c2ecf20Sopenharmony_ci break; 11748c2ecf20Sopenharmony_ci if (copy_to_user(usp, &ksp, sizeof(ksp))) 11758c2ecf20Sopenharmony_ci return -EFAULT; 11768c2ecf20Sopenharmony_ci break; 11778c2ecf20Sopenharmony_ci } 11788c2ecf20Sopenharmony_ci case PKEY_CLR2PROTK: { 11798c2ecf20Sopenharmony_ci struct pkey_clr2protk __user *ucp = (void __user *) arg; 11808c2ecf20Sopenharmony_ci struct pkey_clr2protk kcp; 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci if (copy_from_user(&kcp, ucp, sizeof(kcp))) 11838c2ecf20Sopenharmony_ci return -EFAULT; 11848c2ecf20Sopenharmony_ci rc = pkey_clr2protkey(kcp.keytype, 11858c2ecf20Sopenharmony_ci &kcp.clrkey, &kcp.protkey); 11868c2ecf20Sopenharmony_ci DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc); 11878c2ecf20Sopenharmony_ci if (rc) 11888c2ecf20Sopenharmony_ci break; 11898c2ecf20Sopenharmony_ci if (copy_to_user(ucp, &kcp, sizeof(kcp))) 11908c2ecf20Sopenharmony_ci return -EFAULT; 11918c2ecf20Sopenharmony_ci memzero_explicit(&kcp, sizeof(kcp)); 11928c2ecf20Sopenharmony_ci break; 11938c2ecf20Sopenharmony_ci } 11948c2ecf20Sopenharmony_ci case PKEY_FINDCARD: { 11958c2ecf20Sopenharmony_ci struct pkey_findcard __user *ufc = (void __user *) arg; 11968c2ecf20Sopenharmony_ci struct pkey_findcard kfc; 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_ci if (copy_from_user(&kfc, ufc, sizeof(kfc))) 11998c2ecf20Sopenharmony_ci return -EFAULT; 12008c2ecf20Sopenharmony_ci rc = cca_findcard(kfc.seckey.seckey, 12018c2ecf20Sopenharmony_ci &kfc.cardnr, &kfc.domain, 1); 12028c2ecf20Sopenharmony_ci DEBUG_DBG("%s cca_findcard()=%d\n", __func__, rc); 12038c2ecf20Sopenharmony_ci if (rc < 0) 12048c2ecf20Sopenharmony_ci break; 12058c2ecf20Sopenharmony_ci if (copy_to_user(ufc, &kfc, sizeof(kfc))) 12068c2ecf20Sopenharmony_ci return -EFAULT; 12078c2ecf20Sopenharmony_ci break; 12088c2ecf20Sopenharmony_ci } 12098c2ecf20Sopenharmony_ci case PKEY_SKEY2PKEY: { 12108c2ecf20Sopenharmony_ci struct pkey_skey2pkey __user *usp = (void __user *) arg; 12118c2ecf20Sopenharmony_ci struct pkey_skey2pkey ksp; 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci if (copy_from_user(&ksp, usp, sizeof(ksp))) 12148c2ecf20Sopenharmony_ci return -EFAULT; 12158c2ecf20Sopenharmony_ci rc = pkey_skey2pkey(ksp.seckey.seckey, &ksp.protkey); 12168c2ecf20Sopenharmony_ci DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc); 12178c2ecf20Sopenharmony_ci if (rc) 12188c2ecf20Sopenharmony_ci break; 12198c2ecf20Sopenharmony_ci if (copy_to_user(usp, &ksp, sizeof(ksp))) 12208c2ecf20Sopenharmony_ci return -EFAULT; 12218c2ecf20Sopenharmony_ci break; 12228c2ecf20Sopenharmony_ci } 12238c2ecf20Sopenharmony_ci case PKEY_VERIFYKEY: { 12248c2ecf20Sopenharmony_ci struct pkey_verifykey __user *uvk = (void __user *) arg; 12258c2ecf20Sopenharmony_ci struct pkey_verifykey kvk; 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci if (copy_from_user(&kvk, uvk, sizeof(kvk))) 12288c2ecf20Sopenharmony_ci return -EFAULT; 12298c2ecf20Sopenharmony_ci rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain, 12308c2ecf20Sopenharmony_ci &kvk.keysize, &kvk.attributes); 12318c2ecf20Sopenharmony_ci DEBUG_DBG("%s pkey_verifykey()=%d\n", __func__, rc); 12328c2ecf20Sopenharmony_ci if (rc) 12338c2ecf20Sopenharmony_ci break; 12348c2ecf20Sopenharmony_ci if (copy_to_user(uvk, &kvk, sizeof(kvk))) 12358c2ecf20Sopenharmony_ci return -EFAULT; 12368c2ecf20Sopenharmony_ci break; 12378c2ecf20Sopenharmony_ci } 12388c2ecf20Sopenharmony_ci case PKEY_GENPROTK: { 12398c2ecf20Sopenharmony_ci struct pkey_genprotk __user *ugp = (void __user *) arg; 12408c2ecf20Sopenharmony_ci struct pkey_genprotk kgp; 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci if (copy_from_user(&kgp, ugp, sizeof(kgp))) 12438c2ecf20Sopenharmony_ci return -EFAULT; 12448c2ecf20Sopenharmony_ci rc = pkey_genprotkey(kgp.keytype, &kgp.protkey); 12458c2ecf20Sopenharmony_ci DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc); 12468c2ecf20Sopenharmony_ci if (rc) 12478c2ecf20Sopenharmony_ci break; 12488c2ecf20Sopenharmony_ci if (copy_to_user(ugp, &kgp, sizeof(kgp))) 12498c2ecf20Sopenharmony_ci return -EFAULT; 12508c2ecf20Sopenharmony_ci break; 12518c2ecf20Sopenharmony_ci } 12528c2ecf20Sopenharmony_ci case PKEY_VERIFYPROTK: { 12538c2ecf20Sopenharmony_ci struct pkey_verifyprotk __user *uvp = (void __user *) arg; 12548c2ecf20Sopenharmony_ci struct pkey_verifyprotk kvp; 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci if (copy_from_user(&kvp, uvp, sizeof(kvp))) 12578c2ecf20Sopenharmony_ci return -EFAULT; 12588c2ecf20Sopenharmony_ci rc = pkey_verifyprotkey(&kvp.protkey); 12598c2ecf20Sopenharmony_ci DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc); 12608c2ecf20Sopenharmony_ci break; 12618c2ecf20Sopenharmony_ci } 12628c2ecf20Sopenharmony_ci case PKEY_KBLOB2PROTK: { 12638c2ecf20Sopenharmony_ci struct pkey_kblob2pkey __user *utp = (void __user *) arg; 12648c2ecf20Sopenharmony_ci struct pkey_kblob2pkey ktp; 12658c2ecf20Sopenharmony_ci u8 *kkey; 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci if (copy_from_user(&ktp, utp, sizeof(ktp))) 12688c2ecf20Sopenharmony_ci return -EFAULT; 12698c2ecf20Sopenharmony_ci kkey = _copy_key_from_user(ktp.key, ktp.keylen); 12708c2ecf20Sopenharmony_ci if (IS_ERR(kkey)) 12718c2ecf20Sopenharmony_ci return PTR_ERR(kkey); 12728c2ecf20Sopenharmony_ci rc = pkey_keyblob2pkey(kkey, ktp.keylen, &ktp.protkey); 12738c2ecf20Sopenharmony_ci DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); 12748c2ecf20Sopenharmony_ci memzero_explicit(kkey, ktp.keylen); 12758c2ecf20Sopenharmony_ci kfree(kkey); 12768c2ecf20Sopenharmony_ci if (rc) 12778c2ecf20Sopenharmony_ci break; 12788c2ecf20Sopenharmony_ci if (copy_to_user(utp, &ktp, sizeof(ktp))) 12798c2ecf20Sopenharmony_ci return -EFAULT; 12808c2ecf20Sopenharmony_ci break; 12818c2ecf20Sopenharmony_ci } 12828c2ecf20Sopenharmony_ci case PKEY_GENSECK2: { 12838c2ecf20Sopenharmony_ci struct pkey_genseck2 __user *ugs = (void __user *) arg; 12848c2ecf20Sopenharmony_ci struct pkey_genseck2 kgs; 12858c2ecf20Sopenharmony_ci struct pkey_apqn *apqns; 12868c2ecf20Sopenharmony_ci size_t klen = KEYBLOBBUFSIZE; 12878c2ecf20Sopenharmony_ci u8 *kkey; 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci if (copy_from_user(&kgs, ugs, sizeof(kgs))) 12908c2ecf20Sopenharmony_ci return -EFAULT; 12918c2ecf20Sopenharmony_ci apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries); 12928c2ecf20Sopenharmony_ci if (IS_ERR(apqns)) 12938c2ecf20Sopenharmony_ci return PTR_ERR(apqns); 12948c2ecf20Sopenharmony_ci kkey = kmalloc(klen, GFP_KERNEL); 12958c2ecf20Sopenharmony_ci if (!kkey) { 12968c2ecf20Sopenharmony_ci kfree(apqns); 12978c2ecf20Sopenharmony_ci return -ENOMEM; 12988c2ecf20Sopenharmony_ci } 12998c2ecf20Sopenharmony_ci rc = pkey_genseckey2(apqns, kgs.apqn_entries, 13008c2ecf20Sopenharmony_ci kgs.type, kgs.size, kgs.keygenflags, 13018c2ecf20Sopenharmony_ci kkey, &klen); 13028c2ecf20Sopenharmony_ci DEBUG_DBG("%s pkey_genseckey2()=%d\n", __func__, rc); 13038c2ecf20Sopenharmony_ci kfree(apqns); 13048c2ecf20Sopenharmony_ci if (rc) { 13058c2ecf20Sopenharmony_ci kfree(kkey); 13068c2ecf20Sopenharmony_ci break; 13078c2ecf20Sopenharmony_ci } 13088c2ecf20Sopenharmony_ci if (kgs.key) { 13098c2ecf20Sopenharmony_ci if (kgs.keylen < klen) { 13108c2ecf20Sopenharmony_ci kfree(kkey); 13118c2ecf20Sopenharmony_ci return -EINVAL; 13128c2ecf20Sopenharmony_ci } 13138c2ecf20Sopenharmony_ci if (copy_to_user(kgs.key, kkey, klen)) { 13148c2ecf20Sopenharmony_ci kfree(kkey); 13158c2ecf20Sopenharmony_ci return -EFAULT; 13168c2ecf20Sopenharmony_ci } 13178c2ecf20Sopenharmony_ci } 13188c2ecf20Sopenharmony_ci kgs.keylen = klen; 13198c2ecf20Sopenharmony_ci if (copy_to_user(ugs, &kgs, sizeof(kgs))) 13208c2ecf20Sopenharmony_ci rc = -EFAULT; 13218c2ecf20Sopenharmony_ci kfree(kkey); 13228c2ecf20Sopenharmony_ci break; 13238c2ecf20Sopenharmony_ci } 13248c2ecf20Sopenharmony_ci case PKEY_CLR2SECK2: { 13258c2ecf20Sopenharmony_ci struct pkey_clr2seck2 __user *ucs = (void __user *) arg; 13268c2ecf20Sopenharmony_ci struct pkey_clr2seck2 kcs; 13278c2ecf20Sopenharmony_ci struct pkey_apqn *apqns; 13288c2ecf20Sopenharmony_ci size_t klen = KEYBLOBBUFSIZE; 13298c2ecf20Sopenharmony_ci u8 *kkey; 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci if (copy_from_user(&kcs, ucs, sizeof(kcs))) 13328c2ecf20Sopenharmony_ci return -EFAULT; 13338c2ecf20Sopenharmony_ci apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries); 13348c2ecf20Sopenharmony_ci if (IS_ERR(apqns)) 13358c2ecf20Sopenharmony_ci return PTR_ERR(apqns); 13368c2ecf20Sopenharmony_ci kkey = kmalloc(klen, GFP_KERNEL); 13378c2ecf20Sopenharmony_ci if (!kkey) { 13388c2ecf20Sopenharmony_ci kfree(apqns); 13398c2ecf20Sopenharmony_ci return -ENOMEM; 13408c2ecf20Sopenharmony_ci } 13418c2ecf20Sopenharmony_ci rc = pkey_clr2seckey2(apqns, kcs.apqn_entries, 13428c2ecf20Sopenharmony_ci kcs.type, kcs.size, kcs.keygenflags, 13438c2ecf20Sopenharmony_ci kcs.clrkey.clrkey, kkey, &klen); 13448c2ecf20Sopenharmony_ci DEBUG_DBG("%s pkey_clr2seckey2()=%d\n", __func__, rc); 13458c2ecf20Sopenharmony_ci kfree(apqns); 13468c2ecf20Sopenharmony_ci if (rc) { 13478c2ecf20Sopenharmony_ci kfree(kkey); 13488c2ecf20Sopenharmony_ci break; 13498c2ecf20Sopenharmony_ci } 13508c2ecf20Sopenharmony_ci if (kcs.key) { 13518c2ecf20Sopenharmony_ci if (kcs.keylen < klen) { 13528c2ecf20Sopenharmony_ci kfree(kkey); 13538c2ecf20Sopenharmony_ci return -EINVAL; 13548c2ecf20Sopenharmony_ci } 13558c2ecf20Sopenharmony_ci if (copy_to_user(kcs.key, kkey, klen)) { 13568c2ecf20Sopenharmony_ci kfree(kkey); 13578c2ecf20Sopenharmony_ci return -EFAULT; 13588c2ecf20Sopenharmony_ci } 13598c2ecf20Sopenharmony_ci } 13608c2ecf20Sopenharmony_ci kcs.keylen = klen; 13618c2ecf20Sopenharmony_ci if (copy_to_user(ucs, &kcs, sizeof(kcs))) 13628c2ecf20Sopenharmony_ci rc = -EFAULT; 13638c2ecf20Sopenharmony_ci memzero_explicit(&kcs, sizeof(kcs)); 13648c2ecf20Sopenharmony_ci kfree(kkey); 13658c2ecf20Sopenharmony_ci break; 13668c2ecf20Sopenharmony_ci } 13678c2ecf20Sopenharmony_ci case PKEY_VERIFYKEY2: { 13688c2ecf20Sopenharmony_ci struct pkey_verifykey2 __user *uvk = (void __user *) arg; 13698c2ecf20Sopenharmony_ci struct pkey_verifykey2 kvk; 13708c2ecf20Sopenharmony_ci u8 *kkey; 13718c2ecf20Sopenharmony_ci 13728c2ecf20Sopenharmony_ci if (copy_from_user(&kvk, uvk, sizeof(kvk))) 13738c2ecf20Sopenharmony_ci return -EFAULT; 13748c2ecf20Sopenharmony_ci kkey = _copy_key_from_user(kvk.key, kvk.keylen); 13758c2ecf20Sopenharmony_ci if (IS_ERR(kkey)) 13768c2ecf20Sopenharmony_ci return PTR_ERR(kkey); 13778c2ecf20Sopenharmony_ci rc = pkey_verifykey2(kkey, kvk.keylen, 13788c2ecf20Sopenharmony_ci &kvk.cardnr, &kvk.domain, 13798c2ecf20Sopenharmony_ci &kvk.type, &kvk.size, &kvk.flags); 13808c2ecf20Sopenharmony_ci DEBUG_DBG("%s pkey_verifykey2()=%d\n", __func__, rc); 13818c2ecf20Sopenharmony_ci kfree(kkey); 13828c2ecf20Sopenharmony_ci if (rc) 13838c2ecf20Sopenharmony_ci break; 13848c2ecf20Sopenharmony_ci if (copy_to_user(uvk, &kvk, sizeof(kvk))) 13858c2ecf20Sopenharmony_ci return -EFAULT; 13868c2ecf20Sopenharmony_ci break; 13878c2ecf20Sopenharmony_ci } 13888c2ecf20Sopenharmony_ci case PKEY_KBLOB2PROTK2: { 13898c2ecf20Sopenharmony_ci struct pkey_kblob2pkey2 __user *utp = (void __user *) arg; 13908c2ecf20Sopenharmony_ci struct pkey_kblob2pkey2 ktp; 13918c2ecf20Sopenharmony_ci struct pkey_apqn *apqns = NULL; 13928c2ecf20Sopenharmony_ci u8 *kkey; 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_ci if (copy_from_user(&ktp, utp, sizeof(ktp))) 13958c2ecf20Sopenharmony_ci return -EFAULT; 13968c2ecf20Sopenharmony_ci apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); 13978c2ecf20Sopenharmony_ci if (IS_ERR(apqns)) 13988c2ecf20Sopenharmony_ci return PTR_ERR(apqns); 13998c2ecf20Sopenharmony_ci kkey = _copy_key_from_user(ktp.key, ktp.keylen); 14008c2ecf20Sopenharmony_ci if (IS_ERR(kkey)) { 14018c2ecf20Sopenharmony_ci kfree(apqns); 14028c2ecf20Sopenharmony_ci return PTR_ERR(kkey); 14038c2ecf20Sopenharmony_ci } 14048c2ecf20Sopenharmony_ci rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries, 14058c2ecf20Sopenharmony_ci kkey, ktp.keylen, &ktp.protkey); 14068c2ecf20Sopenharmony_ci DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc); 14078c2ecf20Sopenharmony_ci kfree(apqns); 14088c2ecf20Sopenharmony_ci memzero_explicit(kkey, ktp.keylen); 14098c2ecf20Sopenharmony_ci kfree(kkey); 14108c2ecf20Sopenharmony_ci if (rc) 14118c2ecf20Sopenharmony_ci break; 14128c2ecf20Sopenharmony_ci if (copy_to_user(utp, &ktp, sizeof(ktp))) 14138c2ecf20Sopenharmony_ci return -EFAULT; 14148c2ecf20Sopenharmony_ci break; 14158c2ecf20Sopenharmony_ci } 14168c2ecf20Sopenharmony_ci case PKEY_APQNS4K: { 14178c2ecf20Sopenharmony_ci struct pkey_apqns4key __user *uak = (void __user *) arg; 14188c2ecf20Sopenharmony_ci struct pkey_apqns4key kak; 14198c2ecf20Sopenharmony_ci struct pkey_apqn *apqns = NULL; 14208c2ecf20Sopenharmony_ci size_t nr_apqns, len; 14218c2ecf20Sopenharmony_ci u8 *kkey; 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci if (copy_from_user(&kak, uak, sizeof(kak))) 14248c2ecf20Sopenharmony_ci return -EFAULT; 14258c2ecf20Sopenharmony_ci nr_apqns = kak.apqn_entries; 14268c2ecf20Sopenharmony_ci if (nr_apqns) { 14278c2ecf20Sopenharmony_ci apqns = kmalloc_array(nr_apqns, 14288c2ecf20Sopenharmony_ci sizeof(struct pkey_apqn), 14298c2ecf20Sopenharmony_ci GFP_KERNEL); 14308c2ecf20Sopenharmony_ci if (!apqns) 14318c2ecf20Sopenharmony_ci return -ENOMEM; 14328c2ecf20Sopenharmony_ci } 14338c2ecf20Sopenharmony_ci kkey = _copy_key_from_user(kak.key, kak.keylen); 14348c2ecf20Sopenharmony_ci if (IS_ERR(kkey)) { 14358c2ecf20Sopenharmony_ci kfree(apqns); 14368c2ecf20Sopenharmony_ci return PTR_ERR(kkey); 14378c2ecf20Sopenharmony_ci } 14388c2ecf20Sopenharmony_ci rc = pkey_apqns4key(kkey, kak.keylen, kak.flags, 14398c2ecf20Sopenharmony_ci apqns, &nr_apqns); 14408c2ecf20Sopenharmony_ci DEBUG_DBG("%s pkey_apqns4key()=%d\n", __func__, rc); 14418c2ecf20Sopenharmony_ci kfree(kkey); 14428c2ecf20Sopenharmony_ci if (rc && rc != -ENOSPC) { 14438c2ecf20Sopenharmony_ci kfree(apqns); 14448c2ecf20Sopenharmony_ci break; 14458c2ecf20Sopenharmony_ci } 14468c2ecf20Sopenharmony_ci if (!rc && kak.apqns) { 14478c2ecf20Sopenharmony_ci if (nr_apqns > kak.apqn_entries) { 14488c2ecf20Sopenharmony_ci kfree(apqns); 14498c2ecf20Sopenharmony_ci return -EINVAL; 14508c2ecf20Sopenharmony_ci } 14518c2ecf20Sopenharmony_ci len = nr_apqns * sizeof(struct pkey_apqn); 14528c2ecf20Sopenharmony_ci if (len) { 14538c2ecf20Sopenharmony_ci if (copy_to_user(kak.apqns, apqns, len)) { 14548c2ecf20Sopenharmony_ci kfree(apqns); 14558c2ecf20Sopenharmony_ci return -EFAULT; 14568c2ecf20Sopenharmony_ci } 14578c2ecf20Sopenharmony_ci } 14588c2ecf20Sopenharmony_ci } 14598c2ecf20Sopenharmony_ci kak.apqn_entries = nr_apqns; 14608c2ecf20Sopenharmony_ci if (copy_to_user(uak, &kak, sizeof(kak))) 14618c2ecf20Sopenharmony_ci rc = -EFAULT; 14628c2ecf20Sopenharmony_ci kfree(apqns); 14638c2ecf20Sopenharmony_ci break; 14648c2ecf20Sopenharmony_ci } 14658c2ecf20Sopenharmony_ci case PKEY_APQNS4KT: { 14668c2ecf20Sopenharmony_ci struct pkey_apqns4keytype __user *uat = (void __user *) arg; 14678c2ecf20Sopenharmony_ci struct pkey_apqns4keytype kat; 14688c2ecf20Sopenharmony_ci struct pkey_apqn *apqns = NULL; 14698c2ecf20Sopenharmony_ci size_t nr_apqns, len; 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci if (copy_from_user(&kat, uat, sizeof(kat))) 14728c2ecf20Sopenharmony_ci return -EFAULT; 14738c2ecf20Sopenharmony_ci nr_apqns = kat.apqn_entries; 14748c2ecf20Sopenharmony_ci if (nr_apqns) { 14758c2ecf20Sopenharmony_ci apqns = kmalloc_array(nr_apqns, 14768c2ecf20Sopenharmony_ci sizeof(struct pkey_apqn), 14778c2ecf20Sopenharmony_ci GFP_KERNEL); 14788c2ecf20Sopenharmony_ci if (!apqns) 14798c2ecf20Sopenharmony_ci return -ENOMEM; 14808c2ecf20Sopenharmony_ci } 14818c2ecf20Sopenharmony_ci rc = pkey_apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp, 14828c2ecf20Sopenharmony_ci kat.flags, apqns, &nr_apqns); 14838c2ecf20Sopenharmony_ci DEBUG_DBG("%s pkey_apqns4keytype()=%d\n", __func__, rc); 14848c2ecf20Sopenharmony_ci if (rc && rc != -ENOSPC) { 14858c2ecf20Sopenharmony_ci kfree(apqns); 14868c2ecf20Sopenharmony_ci break; 14878c2ecf20Sopenharmony_ci } 14888c2ecf20Sopenharmony_ci if (!rc && kat.apqns) { 14898c2ecf20Sopenharmony_ci if (nr_apqns > kat.apqn_entries) { 14908c2ecf20Sopenharmony_ci kfree(apqns); 14918c2ecf20Sopenharmony_ci return -EINVAL; 14928c2ecf20Sopenharmony_ci } 14938c2ecf20Sopenharmony_ci len = nr_apqns * sizeof(struct pkey_apqn); 14948c2ecf20Sopenharmony_ci if (len) { 14958c2ecf20Sopenharmony_ci if (copy_to_user(kat.apqns, apqns, len)) { 14968c2ecf20Sopenharmony_ci kfree(apqns); 14978c2ecf20Sopenharmony_ci return -EFAULT; 14988c2ecf20Sopenharmony_ci } 14998c2ecf20Sopenharmony_ci } 15008c2ecf20Sopenharmony_ci } 15018c2ecf20Sopenharmony_ci kat.apqn_entries = nr_apqns; 15028c2ecf20Sopenharmony_ci if (copy_to_user(uat, &kat, sizeof(kat))) 15038c2ecf20Sopenharmony_ci rc = -EFAULT; 15048c2ecf20Sopenharmony_ci kfree(apqns); 15058c2ecf20Sopenharmony_ci break; 15068c2ecf20Sopenharmony_ci } 15078c2ecf20Sopenharmony_ci case PKEY_KBLOB2PROTK3: { 15088c2ecf20Sopenharmony_ci struct pkey_kblob2pkey3 __user *utp = (void __user *) arg; 15098c2ecf20Sopenharmony_ci struct pkey_kblob2pkey3 ktp; 15108c2ecf20Sopenharmony_ci struct pkey_apqn *apqns = NULL; 15118c2ecf20Sopenharmony_ci u32 protkeylen = PROTKEYBLOBBUFSIZE; 15128c2ecf20Sopenharmony_ci u8 *kkey, *protkey; 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_ci if (copy_from_user(&ktp, utp, sizeof(ktp))) 15158c2ecf20Sopenharmony_ci return -EFAULT; 15168c2ecf20Sopenharmony_ci apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); 15178c2ecf20Sopenharmony_ci if (IS_ERR(apqns)) 15188c2ecf20Sopenharmony_ci return PTR_ERR(apqns); 15198c2ecf20Sopenharmony_ci kkey = _copy_key_from_user(ktp.key, ktp.keylen); 15208c2ecf20Sopenharmony_ci if (IS_ERR(kkey)) { 15218c2ecf20Sopenharmony_ci kfree(apqns); 15228c2ecf20Sopenharmony_ci return PTR_ERR(kkey); 15238c2ecf20Sopenharmony_ci } 15248c2ecf20Sopenharmony_ci protkey = kmalloc(protkeylen, GFP_KERNEL); 15258c2ecf20Sopenharmony_ci if (!protkey) { 15268c2ecf20Sopenharmony_ci kfree(apqns); 15278c2ecf20Sopenharmony_ci kfree(kkey); 15288c2ecf20Sopenharmony_ci return -ENOMEM; 15298c2ecf20Sopenharmony_ci } 15308c2ecf20Sopenharmony_ci rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries, kkey, 15318c2ecf20Sopenharmony_ci ktp.keylen, &ktp.pkeytype, 15328c2ecf20Sopenharmony_ci protkey, &protkeylen); 15338c2ecf20Sopenharmony_ci DEBUG_DBG("%s pkey_keyblob2pkey3()=%d\n", __func__, rc); 15348c2ecf20Sopenharmony_ci kfree(apqns); 15358c2ecf20Sopenharmony_ci memzero_explicit(kkey, ktp.keylen); 15368c2ecf20Sopenharmony_ci kfree(kkey); 15378c2ecf20Sopenharmony_ci if (rc) { 15388c2ecf20Sopenharmony_ci kfree(protkey); 15398c2ecf20Sopenharmony_ci break; 15408c2ecf20Sopenharmony_ci } 15418c2ecf20Sopenharmony_ci if (ktp.pkey && ktp.pkeylen) { 15428c2ecf20Sopenharmony_ci if (protkeylen > ktp.pkeylen) { 15438c2ecf20Sopenharmony_ci kfree(protkey); 15448c2ecf20Sopenharmony_ci return -EINVAL; 15458c2ecf20Sopenharmony_ci } 15468c2ecf20Sopenharmony_ci if (copy_to_user(ktp.pkey, protkey, protkeylen)) { 15478c2ecf20Sopenharmony_ci kfree(protkey); 15488c2ecf20Sopenharmony_ci return -EFAULT; 15498c2ecf20Sopenharmony_ci } 15508c2ecf20Sopenharmony_ci } 15518c2ecf20Sopenharmony_ci kfree(protkey); 15528c2ecf20Sopenharmony_ci ktp.pkeylen = protkeylen; 15538c2ecf20Sopenharmony_ci if (copy_to_user(utp, &ktp, sizeof(ktp))) 15548c2ecf20Sopenharmony_ci return -EFAULT; 15558c2ecf20Sopenharmony_ci break; 15568c2ecf20Sopenharmony_ci } 15578c2ecf20Sopenharmony_ci default: 15588c2ecf20Sopenharmony_ci /* unknown/unsupported ioctl cmd */ 15598c2ecf20Sopenharmony_ci return -ENOTTY; 15608c2ecf20Sopenharmony_ci } 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_ci return rc; 15638c2ecf20Sopenharmony_ci} 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_ci/* 15668c2ecf20Sopenharmony_ci * Sysfs and file io operations 15678c2ecf20Sopenharmony_ci */ 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ci/* 15708c2ecf20Sopenharmony_ci * Sysfs attribute read function for all protected key binary attributes. 15718c2ecf20Sopenharmony_ci * The implementation can not deal with partial reads, because a new random 15728c2ecf20Sopenharmony_ci * protected key blob is generated with each read. In case of partial reads 15738c2ecf20Sopenharmony_ci * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 15748c2ecf20Sopenharmony_ci */ 15758c2ecf20Sopenharmony_cistatic ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, 15768c2ecf20Sopenharmony_ci loff_t off, size_t count) 15778c2ecf20Sopenharmony_ci{ 15788c2ecf20Sopenharmony_ci struct protaeskeytoken protkeytoken; 15798c2ecf20Sopenharmony_ci struct pkey_protkey protkey; 15808c2ecf20Sopenharmony_ci int rc; 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_ci if (off != 0 || count < sizeof(protkeytoken)) 15838c2ecf20Sopenharmony_ci return -EINVAL; 15848c2ecf20Sopenharmony_ci if (is_xts) 15858c2ecf20Sopenharmony_ci if (count < 2 * sizeof(protkeytoken)) 15868c2ecf20Sopenharmony_ci return -EINVAL; 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci memset(&protkeytoken, 0, sizeof(protkeytoken)); 15898c2ecf20Sopenharmony_ci protkeytoken.type = TOKTYPE_NON_CCA; 15908c2ecf20Sopenharmony_ci protkeytoken.version = TOKVER_PROTECTED_KEY; 15918c2ecf20Sopenharmony_ci protkeytoken.keytype = keytype; 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_ci rc = pkey_genprotkey(protkeytoken.keytype, &protkey); 15948c2ecf20Sopenharmony_ci if (rc) 15958c2ecf20Sopenharmony_ci return rc; 15968c2ecf20Sopenharmony_ci 15978c2ecf20Sopenharmony_ci protkeytoken.len = protkey.len; 15988c2ecf20Sopenharmony_ci memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci memcpy(buf, &protkeytoken, sizeof(protkeytoken)); 16018c2ecf20Sopenharmony_ci 16028c2ecf20Sopenharmony_ci if (is_xts) { 16038c2ecf20Sopenharmony_ci rc = pkey_genprotkey(protkeytoken.keytype, &protkey); 16048c2ecf20Sopenharmony_ci if (rc) 16058c2ecf20Sopenharmony_ci return rc; 16068c2ecf20Sopenharmony_ci 16078c2ecf20Sopenharmony_ci protkeytoken.len = protkey.len; 16088c2ecf20Sopenharmony_ci memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 16098c2ecf20Sopenharmony_ci 16108c2ecf20Sopenharmony_ci memcpy(buf + sizeof(protkeytoken), &protkeytoken, 16118c2ecf20Sopenharmony_ci sizeof(protkeytoken)); 16128c2ecf20Sopenharmony_ci 16138c2ecf20Sopenharmony_ci return 2 * sizeof(protkeytoken); 16148c2ecf20Sopenharmony_ci } 16158c2ecf20Sopenharmony_ci 16168c2ecf20Sopenharmony_ci return sizeof(protkeytoken); 16178c2ecf20Sopenharmony_ci} 16188c2ecf20Sopenharmony_ci 16198c2ecf20Sopenharmony_cistatic ssize_t protkey_aes_128_read(struct file *filp, 16208c2ecf20Sopenharmony_ci struct kobject *kobj, 16218c2ecf20Sopenharmony_ci struct bin_attribute *attr, 16228c2ecf20Sopenharmony_ci char *buf, loff_t off, 16238c2ecf20Sopenharmony_ci size_t count) 16248c2ecf20Sopenharmony_ci{ 16258c2ecf20Sopenharmony_ci return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 16268c2ecf20Sopenharmony_ci off, count); 16278c2ecf20Sopenharmony_ci} 16288c2ecf20Sopenharmony_ci 16298c2ecf20Sopenharmony_cistatic ssize_t protkey_aes_192_read(struct file *filp, 16308c2ecf20Sopenharmony_ci struct kobject *kobj, 16318c2ecf20Sopenharmony_ci struct bin_attribute *attr, 16328c2ecf20Sopenharmony_ci char *buf, loff_t off, 16338c2ecf20Sopenharmony_ci size_t count) 16348c2ecf20Sopenharmony_ci{ 16358c2ecf20Sopenharmony_ci return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 16368c2ecf20Sopenharmony_ci off, count); 16378c2ecf20Sopenharmony_ci} 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_cistatic ssize_t protkey_aes_256_read(struct file *filp, 16408c2ecf20Sopenharmony_ci struct kobject *kobj, 16418c2ecf20Sopenharmony_ci struct bin_attribute *attr, 16428c2ecf20Sopenharmony_ci char *buf, loff_t off, 16438c2ecf20Sopenharmony_ci size_t count) 16448c2ecf20Sopenharmony_ci{ 16458c2ecf20Sopenharmony_ci return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 16468c2ecf20Sopenharmony_ci off, count); 16478c2ecf20Sopenharmony_ci} 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_cistatic ssize_t protkey_aes_128_xts_read(struct file *filp, 16508c2ecf20Sopenharmony_ci struct kobject *kobj, 16518c2ecf20Sopenharmony_ci struct bin_attribute *attr, 16528c2ecf20Sopenharmony_ci char *buf, loff_t off, 16538c2ecf20Sopenharmony_ci size_t count) 16548c2ecf20Sopenharmony_ci{ 16558c2ecf20Sopenharmony_ci return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 16568c2ecf20Sopenharmony_ci off, count); 16578c2ecf20Sopenharmony_ci} 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_cistatic ssize_t protkey_aes_256_xts_read(struct file *filp, 16608c2ecf20Sopenharmony_ci struct kobject *kobj, 16618c2ecf20Sopenharmony_ci struct bin_attribute *attr, 16628c2ecf20Sopenharmony_ci char *buf, loff_t off, 16638c2ecf20Sopenharmony_ci size_t count) 16648c2ecf20Sopenharmony_ci{ 16658c2ecf20Sopenharmony_ci return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 16668c2ecf20Sopenharmony_ci off, count); 16678c2ecf20Sopenharmony_ci} 16688c2ecf20Sopenharmony_ci 16698c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(protkey_aes_128, sizeof(struct protaeskeytoken)); 16708c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(protkey_aes_192, sizeof(struct protaeskeytoken)); 16718c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(protkey_aes_256, sizeof(struct protaeskeytoken)); 16728c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(protkey_aes_128_xts, 2 * sizeof(struct protaeskeytoken)); 16738c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(protkey_aes_256_xts, 2 * sizeof(struct protaeskeytoken)); 16748c2ecf20Sopenharmony_ci 16758c2ecf20Sopenharmony_cistatic struct bin_attribute *protkey_attrs[] = { 16768c2ecf20Sopenharmony_ci &bin_attr_protkey_aes_128, 16778c2ecf20Sopenharmony_ci &bin_attr_protkey_aes_192, 16788c2ecf20Sopenharmony_ci &bin_attr_protkey_aes_256, 16798c2ecf20Sopenharmony_ci &bin_attr_protkey_aes_128_xts, 16808c2ecf20Sopenharmony_ci &bin_attr_protkey_aes_256_xts, 16818c2ecf20Sopenharmony_ci NULL 16828c2ecf20Sopenharmony_ci}; 16838c2ecf20Sopenharmony_ci 16848c2ecf20Sopenharmony_cistatic struct attribute_group protkey_attr_group = { 16858c2ecf20Sopenharmony_ci .name = "protkey", 16868c2ecf20Sopenharmony_ci .bin_attrs = protkey_attrs, 16878c2ecf20Sopenharmony_ci}; 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ci/* 16908c2ecf20Sopenharmony_ci * Sysfs attribute read function for all secure key ccadata binary attributes. 16918c2ecf20Sopenharmony_ci * The implementation can not deal with partial reads, because a new random 16928c2ecf20Sopenharmony_ci * protected key blob is generated with each read. In case of partial reads 16938c2ecf20Sopenharmony_ci * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 16948c2ecf20Sopenharmony_ci */ 16958c2ecf20Sopenharmony_cistatic ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, 16968c2ecf20Sopenharmony_ci loff_t off, size_t count) 16978c2ecf20Sopenharmony_ci{ 16988c2ecf20Sopenharmony_ci int rc; 16998c2ecf20Sopenharmony_ci struct pkey_seckey *seckey = (struct pkey_seckey *) buf; 17008c2ecf20Sopenharmony_ci 17018c2ecf20Sopenharmony_ci if (off != 0 || count < sizeof(struct secaeskeytoken)) 17028c2ecf20Sopenharmony_ci return -EINVAL; 17038c2ecf20Sopenharmony_ci if (is_xts) 17048c2ecf20Sopenharmony_ci if (count < 2 * sizeof(struct secaeskeytoken)) 17058c2ecf20Sopenharmony_ci return -EINVAL; 17068c2ecf20Sopenharmony_ci 17078c2ecf20Sopenharmony_ci rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 17088c2ecf20Sopenharmony_ci if (rc) 17098c2ecf20Sopenharmony_ci return rc; 17108c2ecf20Sopenharmony_ci 17118c2ecf20Sopenharmony_ci if (is_xts) { 17128c2ecf20Sopenharmony_ci seckey++; 17138c2ecf20Sopenharmony_ci rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 17148c2ecf20Sopenharmony_ci if (rc) 17158c2ecf20Sopenharmony_ci return rc; 17168c2ecf20Sopenharmony_ci 17178c2ecf20Sopenharmony_ci return 2 * sizeof(struct secaeskeytoken); 17188c2ecf20Sopenharmony_ci } 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_ci return sizeof(struct secaeskeytoken); 17218c2ecf20Sopenharmony_ci} 17228c2ecf20Sopenharmony_ci 17238c2ecf20Sopenharmony_cistatic ssize_t ccadata_aes_128_read(struct file *filp, 17248c2ecf20Sopenharmony_ci struct kobject *kobj, 17258c2ecf20Sopenharmony_ci struct bin_attribute *attr, 17268c2ecf20Sopenharmony_ci char *buf, loff_t off, 17278c2ecf20Sopenharmony_ci size_t count) 17288c2ecf20Sopenharmony_ci{ 17298c2ecf20Sopenharmony_ci return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 17308c2ecf20Sopenharmony_ci off, count); 17318c2ecf20Sopenharmony_ci} 17328c2ecf20Sopenharmony_ci 17338c2ecf20Sopenharmony_cistatic ssize_t ccadata_aes_192_read(struct file *filp, 17348c2ecf20Sopenharmony_ci struct kobject *kobj, 17358c2ecf20Sopenharmony_ci struct bin_attribute *attr, 17368c2ecf20Sopenharmony_ci char *buf, loff_t off, 17378c2ecf20Sopenharmony_ci size_t count) 17388c2ecf20Sopenharmony_ci{ 17398c2ecf20Sopenharmony_ci return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 17408c2ecf20Sopenharmony_ci off, count); 17418c2ecf20Sopenharmony_ci} 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_cistatic ssize_t ccadata_aes_256_read(struct file *filp, 17448c2ecf20Sopenharmony_ci struct kobject *kobj, 17458c2ecf20Sopenharmony_ci struct bin_attribute *attr, 17468c2ecf20Sopenharmony_ci char *buf, loff_t off, 17478c2ecf20Sopenharmony_ci size_t count) 17488c2ecf20Sopenharmony_ci{ 17498c2ecf20Sopenharmony_ci return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 17508c2ecf20Sopenharmony_ci off, count); 17518c2ecf20Sopenharmony_ci} 17528c2ecf20Sopenharmony_ci 17538c2ecf20Sopenharmony_cistatic ssize_t ccadata_aes_128_xts_read(struct file *filp, 17548c2ecf20Sopenharmony_ci struct kobject *kobj, 17558c2ecf20Sopenharmony_ci struct bin_attribute *attr, 17568c2ecf20Sopenharmony_ci char *buf, loff_t off, 17578c2ecf20Sopenharmony_ci size_t count) 17588c2ecf20Sopenharmony_ci{ 17598c2ecf20Sopenharmony_ci return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 17608c2ecf20Sopenharmony_ci off, count); 17618c2ecf20Sopenharmony_ci} 17628c2ecf20Sopenharmony_ci 17638c2ecf20Sopenharmony_cistatic ssize_t ccadata_aes_256_xts_read(struct file *filp, 17648c2ecf20Sopenharmony_ci struct kobject *kobj, 17658c2ecf20Sopenharmony_ci struct bin_attribute *attr, 17668c2ecf20Sopenharmony_ci char *buf, loff_t off, 17678c2ecf20Sopenharmony_ci size_t count) 17688c2ecf20Sopenharmony_ci{ 17698c2ecf20Sopenharmony_ci return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 17708c2ecf20Sopenharmony_ci off, count); 17718c2ecf20Sopenharmony_ci} 17728c2ecf20Sopenharmony_ci 17738c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(ccadata_aes_128, sizeof(struct secaeskeytoken)); 17748c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(ccadata_aes_192, sizeof(struct secaeskeytoken)); 17758c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(ccadata_aes_256, sizeof(struct secaeskeytoken)); 17768c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(ccadata_aes_128_xts, 2 * sizeof(struct secaeskeytoken)); 17778c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(ccadata_aes_256_xts, 2 * sizeof(struct secaeskeytoken)); 17788c2ecf20Sopenharmony_ci 17798c2ecf20Sopenharmony_cistatic struct bin_attribute *ccadata_attrs[] = { 17808c2ecf20Sopenharmony_ci &bin_attr_ccadata_aes_128, 17818c2ecf20Sopenharmony_ci &bin_attr_ccadata_aes_192, 17828c2ecf20Sopenharmony_ci &bin_attr_ccadata_aes_256, 17838c2ecf20Sopenharmony_ci &bin_attr_ccadata_aes_128_xts, 17848c2ecf20Sopenharmony_ci &bin_attr_ccadata_aes_256_xts, 17858c2ecf20Sopenharmony_ci NULL 17868c2ecf20Sopenharmony_ci}; 17878c2ecf20Sopenharmony_ci 17888c2ecf20Sopenharmony_cistatic struct attribute_group ccadata_attr_group = { 17898c2ecf20Sopenharmony_ci .name = "ccadata", 17908c2ecf20Sopenharmony_ci .bin_attrs = ccadata_attrs, 17918c2ecf20Sopenharmony_ci}; 17928c2ecf20Sopenharmony_ci 17938c2ecf20Sopenharmony_ci#define CCACIPHERTOKENSIZE (sizeof(struct cipherkeytoken) + 80) 17948c2ecf20Sopenharmony_ci 17958c2ecf20Sopenharmony_ci/* 17968c2ecf20Sopenharmony_ci * Sysfs attribute read function for all secure key ccacipher binary attributes. 17978c2ecf20Sopenharmony_ci * The implementation can not deal with partial reads, because a new random 17988c2ecf20Sopenharmony_ci * secure key blob is generated with each read. In case of partial reads 17998c2ecf20Sopenharmony_ci * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 18008c2ecf20Sopenharmony_ci */ 18018c2ecf20Sopenharmony_cistatic ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits, 18028c2ecf20Sopenharmony_ci bool is_xts, char *buf, loff_t off, 18038c2ecf20Sopenharmony_ci size_t count) 18048c2ecf20Sopenharmony_ci{ 18058c2ecf20Sopenharmony_ci int i, rc, card, dom; 18068c2ecf20Sopenharmony_ci u32 nr_apqns, *apqns = NULL; 18078c2ecf20Sopenharmony_ci size_t keysize = CCACIPHERTOKENSIZE; 18088c2ecf20Sopenharmony_ci 18098c2ecf20Sopenharmony_ci if (off != 0 || count < CCACIPHERTOKENSIZE) 18108c2ecf20Sopenharmony_ci return -EINVAL; 18118c2ecf20Sopenharmony_ci if (is_xts) 18128c2ecf20Sopenharmony_ci if (count < 2 * CCACIPHERTOKENSIZE) 18138c2ecf20Sopenharmony_ci return -EINVAL; 18148c2ecf20Sopenharmony_ci 18158c2ecf20Sopenharmony_ci /* build a list of apqns able to generate an cipher key */ 18168c2ecf20Sopenharmony_ci rc = cca_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 18178c2ecf20Sopenharmony_ci ZCRYPT_CEX6, 0, 0, 0, 0); 18188c2ecf20Sopenharmony_ci if (rc) 18198c2ecf20Sopenharmony_ci return rc; 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_ci memset(buf, 0, is_xts ? 2 * keysize : keysize); 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci /* simple try all apqns from the list */ 18248c2ecf20Sopenharmony_ci for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 18258c2ecf20Sopenharmony_ci card = apqns[i] >> 16; 18268c2ecf20Sopenharmony_ci dom = apqns[i] & 0xFFFF; 18278c2ecf20Sopenharmony_ci rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); 18288c2ecf20Sopenharmony_ci if (rc == 0) 18298c2ecf20Sopenharmony_ci break; 18308c2ecf20Sopenharmony_ci } 18318c2ecf20Sopenharmony_ci if (rc) 18328c2ecf20Sopenharmony_ci return rc; 18338c2ecf20Sopenharmony_ci 18348c2ecf20Sopenharmony_ci if (is_xts) { 18358c2ecf20Sopenharmony_ci keysize = CCACIPHERTOKENSIZE; 18368c2ecf20Sopenharmony_ci buf += CCACIPHERTOKENSIZE; 18378c2ecf20Sopenharmony_ci rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); 18388c2ecf20Sopenharmony_ci if (rc == 0) 18398c2ecf20Sopenharmony_ci return 2 * CCACIPHERTOKENSIZE; 18408c2ecf20Sopenharmony_ci } 18418c2ecf20Sopenharmony_ci 18428c2ecf20Sopenharmony_ci return CCACIPHERTOKENSIZE; 18438c2ecf20Sopenharmony_ci} 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_cistatic ssize_t ccacipher_aes_128_read(struct file *filp, 18468c2ecf20Sopenharmony_ci struct kobject *kobj, 18478c2ecf20Sopenharmony_ci struct bin_attribute *attr, 18488c2ecf20Sopenharmony_ci char *buf, loff_t off, 18498c2ecf20Sopenharmony_ci size_t count) 18508c2ecf20Sopenharmony_ci{ 18518c2ecf20Sopenharmony_ci return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, false, buf, 18528c2ecf20Sopenharmony_ci off, count); 18538c2ecf20Sopenharmony_ci} 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_cistatic ssize_t ccacipher_aes_192_read(struct file *filp, 18568c2ecf20Sopenharmony_ci struct kobject *kobj, 18578c2ecf20Sopenharmony_ci struct bin_attribute *attr, 18588c2ecf20Sopenharmony_ci char *buf, loff_t off, 18598c2ecf20Sopenharmony_ci size_t count) 18608c2ecf20Sopenharmony_ci{ 18618c2ecf20Sopenharmony_ci return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_192, false, buf, 18628c2ecf20Sopenharmony_ci off, count); 18638c2ecf20Sopenharmony_ci} 18648c2ecf20Sopenharmony_ci 18658c2ecf20Sopenharmony_cistatic ssize_t ccacipher_aes_256_read(struct file *filp, 18668c2ecf20Sopenharmony_ci struct kobject *kobj, 18678c2ecf20Sopenharmony_ci struct bin_attribute *attr, 18688c2ecf20Sopenharmony_ci char *buf, loff_t off, 18698c2ecf20Sopenharmony_ci size_t count) 18708c2ecf20Sopenharmony_ci{ 18718c2ecf20Sopenharmony_ci return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, false, buf, 18728c2ecf20Sopenharmony_ci off, count); 18738c2ecf20Sopenharmony_ci} 18748c2ecf20Sopenharmony_ci 18758c2ecf20Sopenharmony_cistatic ssize_t ccacipher_aes_128_xts_read(struct file *filp, 18768c2ecf20Sopenharmony_ci struct kobject *kobj, 18778c2ecf20Sopenharmony_ci struct bin_attribute *attr, 18788c2ecf20Sopenharmony_ci char *buf, loff_t off, 18798c2ecf20Sopenharmony_ci size_t count) 18808c2ecf20Sopenharmony_ci{ 18818c2ecf20Sopenharmony_ci return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, true, buf, 18828c2ecf20Sopenharmony_ci off, count); 18838c2ecf20Sopenharmony_ci} 18848c2ecf20Sopenharmony_ci 18858c2ecf20Sopenharmony_cistatic ssize_t ccacipher_aes_256_xts_read(struct file *filp, 18868c2ecf20Sopenharmony_ci struct kobject *kobj, 18878c2ecf20Sopenharmony_ci struct bin_attribute *attr, 18888c2ecf20Sopenharmony_ci char *buf, loff_t off, 18898c2ecf20Sopenharmony_ci size_t count) 18908c2ecf20Sopenharmony_ci{ 18918c2ecf20Sopenharmony_ci return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, true, buf, 18928c2ecf20Sopenharmony_ci off, count); 18938c2ecf20Sopenharmony_ci} 18948c2ecf20Sopenharmony_ci 18958c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(ccacipher_aes_128, CCACIPHERTOKENSIZE); 18968c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(ccacipher_aes_192, CCACIPHERTOKENSIZE); 18978c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(ccacipher_aes_256, CCACIPHERTOKENSIZE); 18988c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(ccacipher_aes_128_xts, 2 * CCACIPHERTOKENSIZE); 18998c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(ccacipher_aes_256_xts, 2 * CCACIPHERTOKENSIZE); 19008c2ecf20Sopenharmony_ci 19018c2ecf20Sopenharmony_cistatic struct bin_attribute *ccacipher_attrs[] = { 19028c2ecf20Sopenharmony_ci &bin_attr_ccacipher_aes_128, 19038c2ecf20Sopenharmony_ci &bin_attr_ccacipher_aes_192, 19048c2ecf20Sopenharmony_ci &bin_attr_ccacipher_aes_256, 19058c2ecf20Sopenharmony_ci &bin_attr_ccacipher_aes_128_xts, 19068c2ecf20Sopenharmony_ci &bin_attr_ccacipher_aes_256_xts, 19078c2ecf20Sopenharmony_ci NULL 19088c2ecf20Sopenharmony_ci}; 19098c2ecf20Sopenharmony_ci 19108c2ecf20Sopenharmony_cistatic struct attribute_group ccacipher_attr_group = { 19118c2ecf20Sopenharmony_ci .name = "ccacipher", 19128c2ecf20Sopenharmony_ci .bin_attrs = ccacipher_attrs, 19138c2ecf20Sopenharmony_ci}; 19148c2ecf20Sopenharmony_ci 19158c2ecf20Sopenharmony_ci/* 19168c2ecf20Sopenharmony_ci * Sysfs attribute read function for all ep11 aes key binary attributes. 19178c2ecf20Sopenharmony_ci * The implementation can not deal with partial reads, because a new random 19188c2ecf20Sopenharmony_ci * secure key blob is generated with each read. In case of partial reads 19198c2ecf20Sopenharmony_ci * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 19208c2ecf20Sopenharmony_ci * This function and the sysfs attributes using it provide EP11 key blobs 19218c2ecf20Sopenharmony_ci * padded to the upper limit of MAXEP11AESKEYBLOBSIZE which is currently 19228c2ecf20Sopenharmony_ci * 320 bytes. 19238c2ecf20Sopenharmony_ci */ 19248c2ecf20Sopenharmony_cistatic ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits, 19258c2ecf20Sopenharmony_ci bool is_xts, char *buf, loff_t off, 19268c2ecf20Sopenharmony_ci size_t count) 19278c2ecf20Sopenharmony_ci{ 19288c2ecf20Sopenharmony_ci int i, rc, card, dom; 19298c2ecf20Sopenharmony_ci u32 nr_apqns, *apqns = NULL; 19308c2ecf20Sopenharmony_ci size_t keysize = MAXEP11AESKEYBLOBSIZE; 19318c2ecf20Sopenharmony_ci 19328c2ecf20Sopenharmony_ci if (off != 0 || count < MAXEP11AESKEYBLOBSIZE) 19338c2ecf20Sopenharmony_ci return -EINVAL; 19348c2ecf20Sopenharmony_ci if (is_xts) 19358c2ecf20Sopenharmony_ci if (count < 2 * MAXEP11AESKEYBLOBSIZE) 19368c2ecf20Sopenharmony_ci return -EINVAL; 19378c2ecf20Sopenharmony_ci 19388c2ecf20Sopenharmony_ci /* build a list of apqns able to generate an cipher key */ 19398c2ecf20Sopenharmony_ci rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 19408c2ecf20Sopenharmony_ci ZCRYPT_CEX7, EP11_API_V, NULL); 19418c2ecf20Sopenharmony_ci if (rc) 19428c2ecf20Sopenharmony_ci return rc; 19438c2ecf20Sopenharmony_ci 19448c2ecf20Sopenharmony_ci memset(buf, 0, is_xts ? 2 * keysize : keysize); 19458c2ecf20Sopenharmony_ci 19468c2ecf20Sopenharmony_ci /* simple try all apqns from the list */ 19478c2ecf20Sopenharmony_ci for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 19488c2ecf20Sopenharmony_ci card = apqns[i] >> 16; 19498c2ecf20Sopenharmony_ci dom = apqns[i] & 0xFFFF; 19508c2ecf20Sopenharmony_ci rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize); 19518c2ecf20Sopenharmony_ci if (rc == 0) 19528c2ecf20Sopenharmony_ci break; 19538c2ecf20Sopenharmony_ci } 19548c2ecf20Sopenharmony_ci if (rc) 19558c2ecf20Sopenharmony_ci return rc; 19568c2ecf20Sopenharmony_ci 19578c2ecf20Sopenharmony_ci if (is_xts) { 19588c2ecf20Sopenharmony_ci keysize = MAXEP11AESKEYBLOBSIZE; 19598c2ecf20Sopenharmony_ci buf += MAXEP11AESKEYBLOBSIZE; 19608c2ecf20Sopenharmony_ci rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize); 19618c2ecf20Sopenharmony_ci if (rc == 0) 19628c2ecf20Sopenharmony_ci return 2 * MAXEP11AESKEYBLOBSIZE; 19638c2ecf20Sopenharmony_ci } 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci return MAXEP11AESKEYBLOBSIZE; 19668c2ecf20Sopenharmony_ci} 19678c2ecf20Sopenharmony_ci 19688c2ecf20Sopenharmony_cistatic ssize_t ep11_aes_128_read(struct file *filp, 19698c2ecf20Sopenharmony_ci struct kobject *kobj, 19708c2ecf20Sopenharmony_ci struct bin_attribute *attr, 19718c2ecf20Sopenharmony_ci char *buf, loff_t off, 19728c2ecf20Sopenharmony_ci size_t count) 19738c2ecf20Sopenharmony_ci{ 19748c2ecf20Sopenharmony_ci return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, false, buf, 19758c2ecf20Sopenharmony_ci off, count); 19768c2ecf20Sopenharmony_ci} 19778c2ecf20Sopenharmony_ci 19788c2ecf20Sopenharmony_cistatic ssize_t ep11_aes_192_read(struct file *filp, 19798c2ecf20Sopenharmony_ci struct kobject *kobj, 19808c2ecf20Sopenharmony_ci struct bin_attribute *attr, 19818c2ecf20Sopenharmony_ci char *buf, loff_t off, 19828c2ecf20Sopenharmony_ci size_t count) 19838c2ecf20Sopenharmony_ci{ 19848c2ecf20Sopenharmony_ci return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_192, false, buf, 19858c2ecf20Sopenharmony_ci off, count); 19868c2ecf20Sopenharmony_ci} 19878c2ecf20Sopenharmony_ci 19888c2ecf20Sopenharmony_cistatic ssize_t ep11_aes_256_read(struct file *filp, 19898c2ecf20Sopenharmony_ci struct kobject *kobj, 19908c2ecf20Sopenharmony_ci struct bin_attribute *attr, 19918c2ecf20Sopenharmony_ci char *buf, loff_t off, 19928c2ecf20Sopenharmony_ci size_t count) 19938c2ecf20Sopenharmony_ci{ 19948c2ecf20Sopenharmony_ci return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, false, buf, 19958c2ecf20Sopenharmony_ci off, count); 19968c2ecf20Sopenharmony_ci} 19978c2ecf20Sopenharmony_ci 19988c2ecf20Sopenharmony_cistatic ssize_t ep11_aes_128_xts_read(struct file *filp, 19998c2ecf20Sopenharmony_ci struct kobject *kobj, 20008c2ecf20Sopenharmony_ci struct bin_attribute *attr, 20018c2ecf20Sopenharmony_ci char *buf, loff_t off, 20028c2ecf20Sopenharmony_ci size_t count) 20038c2ecf20Sopenharmony_ci{ 20048c2ecf20Sopenharmony_ci return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, true, buf, 20058c2ecf20Sopenharmony_ci off, count); 20068c2ecf20Sopenharmony_ci} 20078c2ecf20Sopenharmony_ci 20088c2ecf20Sopenharmony_cistatic ssize_t ep11_aes_256_xts_read(struct file *filp, 20098c2ecf20Sopenharmony_ci struct kobject *kobj, 20108c2ecf20Sopenharmony_ci struct bin_attribute *attr, 20118c2ecf20Sopenharmony_ci char *buf, loff_t off, 20128c2ecf20Sopenharmony_ci size_t count) 20138c2ecf20Sopenharmony_ci{ 20148c2ecf20Sopenharmony_ci return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, true, buf, 20158c2ecf20Sopenharmony_ci off, count); 20168c2ecf20Sopenharmony_ci} 20178c2ecf20Sopenharmony_ci 20188c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(ep11_aes_128, MAXEP11AESKEYBLOBSIZE); 20198c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(ep11_aes_192, MAXEP11AESKEYBLOBSIZE); 20208c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(ep11_aes_256, MAXEP11AESKEYBLOBSIZE); 20218c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(ep11_aes_128_xts, 2 * MAXEP11AESKEYBLOBSIZE); 20228c2ecf20Sopenharmony_cistatic BIN_ATTR_RO(ep11_aes_256_xts, 2 * MAXEP11AESKEYBLOBSIZE); 20238c2ecf20Sopenharmony_ci 20248c2ecf20Sopenharmony_cistatic struct bin_attribute *ep11_attrs[] = { 20258c2ecf20Sopenharmony_ci &bin_attr_ep11_aes_128, 20268c2ecf20Sopenharmony_ci &bin_attr_ep11_aes_192, 20278c2ecf20Sopenharmony_ci &bin_attr_ep11_aes_256, 20288c2ecf20Sopenharmony_ci &bin_attr_ep11_aes_128_xts, 20298c2ecf20Sopenharmony_ci &bin_attr_ep11_aes_256_xts, 20308c2ecf20Sopenharmony_ci NULL 20318c2ecf20Sopenharmony_ci}; 20328c2ecf20Sopenharmony_ci 20338c2ecf20Sopenharmony_cistatic struct attribute_group ep11_attr_group = { 20348c2ecf20Sopenharmony_ci .name = "ep11", 20358c2ecf20Sopenharmony_ci .bin_attrs = ep11_attrs, 20368c2ecf20Sopenharmony_ci}; 20378c2ecf20Sopenharmony_ci 20388c2ecf20Sopenharmony_cistatic const struct attribute_group *pkey_attr_groups[] = { 20398c2ecf20Sopenharmony_ci &protkey_attr_group, 20408c2ecf20Sopenharmony_ci &ccadata_attr_group, 20418c2ecf20Sopenharmony_ci &ccacipher_attr_group, 20428c2ecf20Sopenharmony_ci &ep11_attr_group, 20438c2ecf20Sopenharmony_ci NULL, 20448c2ecf20Sopenharmony_ci}; 20458c2ecf20Sopenharmony_ci 20468c2ecf20Sopenharmony_cistatic const struct file_operations pkey_fops = { 20478c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 20488c2ecf20Sopenharmony_ci .open = nonseekable_open, 20498c2ecf20Sopenharmony_ci .llseek = no_llseek, 20508c2ecf20Sopenharmony_ci .unlocked_ioctl = pkey_unlocked_ioctl, 20518c2ecf20Sopenharmony_ci}; 20528c2ecf20Sopenharmony_ci 20538c2ecf20Sopenharmony_cistatic struct miscdevice pkey_dev = { 20548c2ecf20Sopenharmony_ci .name = "pkey", 20558c2ecf20Sopenharmony_ci .minor = MISC_DYNAMIC_MINOR, 20568c2ecf20Sopenharmony_ci .mode = 0666, 20578c2ecf20Sopenharmony_ci .fops = &pkey_fops, 20588c2ecf20Sopenharmony_ci .groups = pkey_attr_groups, 20598c2ecf20Sopenharmony_ci}; 20608c2ecf20Sopenharmony_ci 20618c2ecf20Sopenharmony_ci/* 20628c2ecf20Sopenharmony_ci * Module init 20638c2ecf20Sopenharmony_ci */ 20648c2ecf20Sopenharmony_cistatic int __init pkey_init(void) 20658c2ecf20Sopenharmony_ci{ 20668c2ecf20Sopenharmony_ci cpacf_mask_t func_mask; 20678c2ecf20Sopenharmony_ci 20688c2ecf20Sopenharmony_ci /* 20698c2ecf20Sopenharmony_ci * The pckmo instruction should be available - even if we don't 20708c2ecf20Sopenharmony_ci * actually invoke it. This instruction comes with MSA 3 which 20718c2ecf20Sopenharmony_ci * is also the minimum level for the kmc instructions which 20728c2ecf20Sopenharmony_ci * are able to work with protected keys. 20738c2ecf20Sopenharmony_ci */ 20748c2ecf20Sopenharmony_ci if (!cpacf_query(CPACF_PCKMO, &func_mask)) 20758c2ecf20Sopenharmony_ci return -ENODEV; 20768c2ecf20Sopenharmony_ci 20778c2ecf20Sopenharmony_ci /* check for kmc instructions available */ 20788c2ecf20Sopenharmony_ci if (!cpacf_query(CPACF_KMC, &func_mask)) 20798c2ecf20Sopenharmony_ci return -ENODEV; 20808c2ecf20Sopenharmony_ci if (!cpacf_test_func(&func_mask, CPACF_KMC_PAES_128) || 20818c2ecf20Sopenharmony_ci !cpacf_test_func(&func_mask, CPACF_KMC_PAES_192) || 20828c2ecf20Sopenharmony_ci !cpacf_test_func(&func_mask, CPACF_KMC_PAES_256)) 20838c2ecf20Sopenharmony_ci return -ENODEV; 20848c2ecf20Sopenharmony_ci 20858c2ecf20Sopenharmony_ci pkey_debug_init(); 20868c2ecf20Sopenharmony_ci 20878c2ecf20Sopenharmony_ci return misc_register(&pkey_dev); 20888c2ecf20Sopenharmony_ci} 20898c2ecf20Sopenharmony_ci 20908c2ecf20Sopenharmony_ci/* 20918c2ecf20Sopenharmony_ci * Module exit 20928c2ecf20Sopenharmony_ci */ 20938c2ecf20Sopenharmony_cistatic void __exit pkey_exit(void) 20948c2ecf20Sopenharmony_ci{ 20958c2ecf20Sopenharmony_ci misc_deregister(&pkey_dev); 20968c2ecf20Sopenharmony_ci pkey_debug_exit(); 20978c2ecf20Sopenharmony_ci} 20988c2ecf20Sopenharmony_ci 20998c2ecf20Sopenharmony_cimodule_cpu_feature_match(MSA, pkey_init); 21008c2ecf20Sopenharmony_cimodule_exit(pkey_exit); 2101