1812141a9SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2e80d4af0SHarald Freudenberger /* 3e80d4af0SHarald Freudenberger * pkey device driver 4e80d4af0SHarald Freudenberger * 5183cb469SHarald Freudenberger * Copyright IBM Corp. 2017,2019 6e80d4af0SHarald Freudenberger * Author(s): Harald Freudenberger 7e80d4af0SHarald Freudenberger */ 8e80d4af0SHarald Freudenberger 9e80d4af0SHarald Freudenberger #define KMSG_COMPONENT "pkey" 10e80d4af0SHarald Freudenberger #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 11e80d4af0SHarald Freudenberger 12e80d4af0SHarald Freudenberger #include <linux/fs.h> 13e80d4af0SHarald Freudenberger #include <linux/init.h> 14e80d4af0SHarald Freudenberger #include <linux/miscdevice.h> 15e80d4af0SHarald Freudenberger #include <linux/module.h> 16e80d4af0SHarald Freudenberger #include <linux/slab.h> 17e80d4af0SHarald Freudenberger #include <linux/kallsyms.h> 18e80d4af0SHarald Freudenberger #include <linux/debugfs.h> 19a45a5c7dSIngo Franzki #include <linux/random.h> 2063c19be0SIngo Franzki #include <linux/cpufeature.h> 21e80d4af0SHarald Freudenberger #include <asm/zcrypt.h> 22e80d4af0SHarald Freudenberger #include <asm/cpacf.h> 23e80d4af0SHarald Freudenberger #include <asm/pkey.h> 24cb26b9ffSIngo Franzki #include <crypto/aes.h> 25e80d4af0SHarald Freudenberger 26e80d4af0SHarald Freudenberger #include "zcrypt_api.h" 27efc598e6SHarald Freudenberger #include "zcrypt_ccamisc.h" 2855d0a513SHarald Freudenberger #include "zcrypt_ep11misc.h" 29e80d4af0SHarald Freudenberger 30e80d4af0SHarald Freudenberger MODULE_LICENSE("GPL"); 31e80d4af0SHarald Freudenberger MODULE_AUTHOR("IBM Corporation"); 32e80d4af0SHarald Freudenberger MODULE_DESCRIPTION("s390 protected key interface"); 33e80d4af0SHarald Freudenberger 34f2bbc96eSHarald Freudenberger #define KEYBLOBBUFSIZE 8192 /* key buffer size used for internal processing */ 35*fa6999e3SHarald Freudenberger #define PROTKEYBLOBBUFSIZE 256 /* protected key buffer size used internal */ 36f2bbc96eSHarald Freudenberger #define MAXAPQNSINLIST 64 /* max 64 apqns within a apqn list */ 37f2bbc96eSHarald Freudenberger 38f822ad2cSHarald Freudenberger /* mask of available pckmo subfunctions, fetched once at module init */ 39f822ad2cSHarald Freudenberger static cpacf_mask_t pckmo_functions; 40f822ad2cSHarald Freudenberger 41e80d4af0SHarald Freudenberger /* 42e80d4af0SHarald Freudenberger * debug feature data and functions 43e80d4af0SHarald Freudenberger */ 44e80d4af0SHarald Freudenberger 45e80d4af0SHarald Freudenberger static debug_info_t *debug_info; 46e80d4af0SHarald Freudenberger 47e80d4af0SHarald Freudenberger #define DEBUG_DBG(...) debug_sprintf_event(debug_info, 6, ##__VA_ARGS__) 48e80d4af0SHarald Freudenberger #define DEBUG_INFO(...) debug_sprintf_event(debug_info, 5, ##__VA_ARGS__) 49e80d4af0SHarald Freudenberger #define DEBUG_WARN(...) debug_sprintf_event(debug_info, 4, ##__VA_ARGS__) 50e80d4af0SHarald Freudenberger #define DEBUG_ERR(...) debug_sprintf_event(debug_info, 3, ##__VA_ARGS__) 51e80d4af0SHarald Freudenberger 52e80d4af0SHarald Freudenberger static void __init pkey_debug_init(void) 53e80d4af0SHarald Freudenberger { 546b1f16baSHarald Freudenberger /* 5 arguments per dbf entry (including the format string ptr) */ 556b1f16baSHarald Freudenberger debug_info = debug_register("pkey", 1, 1, 5 * sizeof(long)); 56e80d4af0SHarald Freudenberger debug_register_view(debug_info, &debug_sprintf_view); 57e80d4af0SHarald Freudenberger debug_set_level(debug_info, 3); 58e80d4af0SHarald Freudenberger } 59e80d4af0SHarald Freudenberger 60e80d4af0SHarald Freudenberger static void __exit pkey_debug_exit(void) 61e80d4af0SHarald Freudenberger { 62e80d4af0SHarald Freudenberger debug_unregister(debug_info); 63e80d4af0SHarald Freudenberger } 64e80d4af0SHarald Freudenberger 650534bde7SIngo Franzki /* inside view of a protected key token (only type 0x00 version 0x01) */ 660534bde7SIngo Franzki struct protaeskeytoken { 670534bde7SIngo Franzki u8 type; /* 0x00 for PAES specific key tokens */ 680534bde7SIngo Franzki u8 res0[3]; 690534bde7SIngo Franzki u8 version; /* should be 0x01 for protected AES key token */ 700534bde7SIngo Franzki u8 res1[3]; 710534bde7SIngo Franzki u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ 720534bde7SIngo Franzki u32 len; /* bytes actually stored in protkey[] */ 730534bde7SIngo Franzki u8 protkey[MAXPROTKEYSIZE]; /* the protected key blob */ 740534bde7SIngo Franzki } __packed; 750534bde7SIngo Franzki 76888edbc4SHarald Freudenberger /* inside view of a clear key token (type 0x00 version 0x02) */ 77888edbc4SHarald Freudenberger struct clearaeskeytoken { 78888edbc4SHarald Freudenberger u8 type; /* 0x00 for PAES specific key tokens */ 79888edbc4SHarald Freudenberger u8 res0[3]; 80888edbc4SHarald Freudenberger u8 version; /* 0x02 for clear AES key token */ 81888edbc4SHarald Freudenberger u8 res1[3]; 82888edbc4SHarald Freudenberger u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ 83888edbc4SHarald Freudenberger u32 len; /* bytes actually stored in clearkey[] */ 84fa226f1dSGustavo A. R. Silva u8 clearkey[]; /* clear key value */ 85888edbc4SHarald Freudenberger } __packed; 86888edbc4SHarald Freudenberger 87e80d4af0SHarald Freudenberger /* 88e80d4af0SHarald Freudenberger * Create a protected key from a clear key value. 89e80d4af0SHarald Freudenberger */ 90183cb469SHarald Freudenberger static int pkey_clr2protkey(u32 keytype, 91e80d4af0SHarald Freudenberger const struct pkey_clrkey *clrkey, 92e80d4af0SHarald Freudenberger struct pkey_protkey *protkey) 93e80d4af0SHarald Freudenberger { 94e80d4af0SHarald Freudenberger long fc; 95e80d4af0SHarald Freudenberger int keysize; 96e80d4af0SHarald Freudenberger u8 paramblock[64]; 97e80d4af0SHarald Freudenberger 98e80d4af0SHarald Freudenberger switch (keytype) { 99e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 100e80d4af0SHarald Freudenberger keysize = 16; 101e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_128_KEY; 102e80d4af0SHarald Freudenberger break; 103e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 104e80d4af0SHarald Freudenberger keysize = 24; 105e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_192_KEY; 106e80d4af0SHarald Freudenberger break; 107e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 108e80d4af0SHarald Freudenberger keysize = 32; 109e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_256_KEY; 110e80d4af0SHarald Freudenberger break; 111e80d4af0SHarald Freudenberger default: 112ac2b96f3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %d\n", 113ac2b96f3SHarald Freudenberger __func__, keytype); 114e80d4af0SHarald Freudenberger return -EINVAL; 115e80d4af0SHarald Freudenberger } 116e80d4af0SHarald Freudenberger 117f822ad2cSHarald Freudenberger /* 118f822ad2cSHarald Freudenberger * Check if the needed pckmo subfunction is available. 119f822ad2cSHarald Freudenberger * These subfunctions can be enabled/disabled by customers 120f822ad2cSHarald Freudenberger * in the LPAR profile or may even change on the fly. 121f822ad2cSHarald Freudenberger */ 122f822ad2cSHarald Freudenberger if (!cpacf_test_func(&pckmo_functions, fc)) { 123f822ad2cSHarald Freudenberger DEBUG_ERR("%s pckmo functions not available\n", __func__); 12458443b67SDavid Hildenbrand return -ENODEV; 125f822ad2cSHarald Freudenberger } 126f822ad2cSHarald Freudenberger 127e80d4af0SHarald Freudenberger /* prepare param block */ 128e80d4af0SHarald Freudenberger memset(paramblock, 0, sizeof(paramblock)); 129e80d4af0SHarald Freudenberger memcpy(paramblock, clrkey->clrkey, keysize); 130e80d4af0SHarald Freudenberger 131e80d4af0SHarald Freudenberger /* call the pckmo instruction */ 132e80d4af0SHarald Freudenberger cpacf_pckmo(fc, paramblock); 133e80d4af0SHarald Freudenberger 134e80d4af0SHarald Freudenberger /* copy created protected key */ 135e80d4af0SHarald Freudenberger protkey->type = keytype; 136e80d4af0SHarald Freudenberger protkey->len = keysize + 32; 137e80d4af0SHarald Freudenberger memcpy(protkey->protkey, paramblock, keysize + 32); 138e80d4af0SHarald Freudenberger 139e80d4af0SHarald Freudenberger return 0; 140e80d4af0SHarald Freudenberger } 141e80d4af0SHarald Freudenberger 142e80d4af0SHarald Freudenberger /* 143e80d4af0SHarald Freudenberger * Find card and transform secure key into protected key. 144e80d4af0SHarald Freudenberger */ 145f2bbc96eSHarald Freudenberger static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey) 146e80d4af0SHarald Freudenberger { 147e80d4af0SHarald Freudenberger int rc, verify; 148f2bbc96eSHarald Freudenberger u16 cardnr, domain; 149f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 150e80d4af0SHarald Freudenberger 151e80d4af0SHarald Freudenberger /* 152f2bbc96eSHarald Freudenberger * The cca_xxx2protkey call may fail when a card has been 153e80d4af0SHarald Freudenberger * addressed where the master key was changed after last fetch 154efc598e6SHarald Freudenberger * of the mkvp into the cache. Try 3 times: First witout verify 155efc598e6SHarald Freudenberger * then with verify and last round with verify and old master 156efc598e6SHarald Freudenberger * key verification pattern match not ignored. 157e80d4af0SHarald Freudenberger */ 158efc598e6SHarald Freudenberger for (verify = 0; verify < 3; verify++) { 159f2bbc96eSHarald Freudenberger rc = cca_findcard(key, &cardnr, &domain, verify); 160efc598e6SHarald Freudenberger if (rc < 0) 161e80d4af0SHarald Freudenberger continue; 162efc598e6SHarald Freudenberger if (rc > 0 && verify < 2) 163efc598e6SHarald Freudenberger continue; 164f2bbc96eSHarald Freudenberger switch (hdr->version) { 165f2bbc96eSHarald Freudenberger case TOKVER_CCA_AES: 166f2bbc96eSHarald Freudenberger rc = cca_sec2protkey(cardnr, domain, 167f2bbc96eSHarald Freudenberger key, pkey->protkey, 168f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 169f2bbc96eSHarald Freudenberger break; 170f2bbc96eSHarald Freudenberger case TOKVER_CCA_VLSC: 171f2bbc96eSHarald Freudenberger rc = cca_cipher2protkey(cardnr, domain, 172f2bbc96eSHarald Freudenberger key, pkey->protkey, 173f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 174f2bbc96eSHarald Freudenberger break; 175f2bbc96eSHarald Freudenberger default: 176f2bbc96eSHarald Freudenberger return -EINVAL; 177f2bbc96eSHarald Freudenberger } 178e80d4af0SHarald Freudenberger if (rc == 0) 179e80d4af0SHarald Freudenberger break; 180e80d4af0SHarald Freudenberger } 181e80d4af0SHarald Freudenberger 182e80d4af0SHarald Freudenberger if (rc) 183ac2b96f3SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 184e80d4af0SHarald Freudenberger 185e80d4af0SHarald Freudenberger return rc; 186e80d4af0SHarald Freudenberger } 187e80d4af0SHarald Freudenberger 188e80d4af0SHarald Freudenberger /* 18955d0a513SHarald Freudenberger * Construct EP11 key with given clear key value. 19055d0a513SHarald Freudenberger */ 19155d0a513SHarald Freudenberger static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen, 19255d0a513SHarald Freudenberger u8 *keybuf, size_t *keybuflen) 19355d0a513SHarald Freudenberger { 19455d0a513SHarald Freudenberger int i, rc; 19555d0a513SHarald Freudenberger u16 card, dom; 19655d0a513SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 19755d0a513SHarald Freudenberger 19855d0a513SHarald Freudenberger /* build a list of apqns suitable for ep11 keys with cpacf support */ 19955d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 20055d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, NULL); 20155d0a513SHarald Freudenberger if (rc) 20255d0a513SHarald Freudenberger goto out; 20355d0a513SHarald Freudenberger 20455d0a513SHarald Freudenberger /* go through the list of apqns and try to bild an ep11 key */ 20555d0a513SHarald Freudenberger for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { 20655d0a513SHarald Freudenberger card = apqns[i] >> 16; 20755d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 20855d0a513SHarald Freudenberger rc = ep11_clr2keyblob(card, dom, clrkeylen * 8, 20955d0a513SHarald Freudenberger 0, clrkey, keybuf, keybuflen); 21055d0a513SHarald Freudenberger if (rc == 0) 21155d0a513SHarald Freudenberger break; 21255d0a513SHarald Freudenberger } 21355d0a513SHarald Freudenberger 21455d0a513SHarald Freudenberger out: 21555d0a513SHarald Freudenberger kfree(apqns); 21655d0a513SHarald Freudenberger if (rc) 21755d0a513SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 21855d0a513SHarald Freudenberger return rc; 21955d0a513SHarald Freudenberger } 22055d0a513SHarald Freudenberger 22155d0a513SHarald Freudenberger /* 22255d0a513SHarald Freudenberger * Find card and transform EP11 secure key into protected key. 22355d0a513SHarald Freudenberger */ 22455d0a513SHarald Freudenberger static int pkey_ep11key2pkey(const u8 *key, struct pkey_protkey *pkey) 22555d0a513SHarald Freudenberger { 22655d0a513SHarald Freudenberger int i, rc; 22755d0a513SHarald Freudenberger u16 card, dom; 22855d0a513SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 22955d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *) key; 23055d0a513SHarald Freudenberger 23155d0a513SHarald Freudenberger /* build a list of apqns suitable for this key */ 23255d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 23355d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, kb->wkvp); 23455d0a513SHarald Freudenberger if (rc) 23555d0a513SHarald Freudenberger goto out; 23655d0a513SHarald Freudenberger 23755d0a513SHarald Freudenberger /* go through the list of apqns and try to derive an pkey */ 23855d0a513SHarald Freudenberger for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { 23955d0a513SHarald Freudenberger card = apqns[i] >> 16; 24055d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 241*fa6999e3SHarald Freudenberger pkey->len = sizeof(pkey->protkey); 242*fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, kb->head.len, 24355d0a513SHarald Freudenberger pkey->protkey, &pkey->len, &pkey->type); 24455d0a513SHarald Freudenberger if (rc == 0) 24555d0a513SHarald Freudenberger break; 24655d0a513SHarald Freudenberger } 24755d0a513SHarald Freudenberger 24855d0a513SHarald Freudenberger out: 24955d0a513SHarald Freudenberger kfree(apqns); 25055d0a513SHarald Freudenberger if (rc) 25155d0a513SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 25255d0a513SHarald Freudenberger return rc; 25355d0a513SHarald Freudenberger } 25455d0a513SHarald Freudenberger 25555d0a513SHarald Freudenberger /* 256e61a6134SHarald Freudenberger * Verify key and give back some info about the key. 257e61a6134SHarald Freudenberger */ 258183cb469SHarald Freudenberger static int pkey_verifykey(const struct pkey_seckey *seckey, 259e61a6134SHarald Freudenberger u16 *pcardnr, u16 *pdomain, 260e61a6134SHarald Freudenberger u16 *pkeysize, u32 *pattributes) 261e61a6134SHarald Freudenberger { 262e61a6134SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; 263e61a6134SHarald Freudenberger u16 cardnr, domain; 264e61a6134SHarald Freudenberger int rc; 265e61a6134SHarald Freudenberger 266e61a6134SHarald Freudenberger /* check the secure key for valid AES secure key */ 267efc598e6SHarald Freudenberger rc = cca_check_secaeskeytoken(debug_info, 3, (u8 *) seckey, 0); 268e61a6134SHarald Freudenberger if (rc) 269e61a6134SHarald Freudenberger goto out; 270e61a6134SHarald Freudenberger if (pattributes) 271e61a6134SHarald Freudenberger *pattributes = PKEY_VERIFY_ATTR_AES; 272e61a6134SHarald Freudenberger if (pkeysize) 273e61a6134SHarald Freudenberger *pkeysize = t->bitsize; 274e61a6134SHarald Freudenberger 275e61a6134SHarald Freudenberger /* try to find a card which can handle this key */ 276efc598e6SHarald Freudenberger rc = cca_findcard(seckey->seckey, &cardnr, &domain, 1); 277efc598e6SHarald Freudenberger if (rc < 0) 278e61a6134SHarald Freudenberger goto out; 279e61a6134SHarald Freudenberger 280efc598e6SHarald Freudenberger if (rc > 0) { 281efc598e6SHarald Freudenberger /* key mkvp matches to old master key mkvp */ 282ac2b96f3SHarald Freudenberger DEBUG_DBG("%s secure key has old mkvp\n", __func__); 283e61a6134SHarald Freudenberger if (pattributes) 284e61a6134SHarald Freudenberger *pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP; 285efc598e6SHarald Freudenberger rc = 0; 286e61a6134SHarald Freudenberger } 287e61a6134SHarald Freudenberger 288e61a6134SHarald Freudenberger if (pcardnr) 289e61a6134SHarald Freudenberger *pcardnr = cardnr; 290e61a6134SHarald Freudenberger if (pdomain) 291e61a6134SHarald Freudenberger *pdomain = domain; 292e61a6134SHarald Freudenberger 293e61a6134SHarald Freudenberger out: 294ac2b96f3SHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 295e61a6134SHarald Freudenberger return rc; 296e61a6134SHarald Freudenberger } 297e61a6134SHarald Freudenberger 298e61a6134SHarald Freudenberger /* 299a45a5c7dSIngo Franzki * Generate a random protected key 300a45a5c7dSIngo Franzki */ 301183cb469SHarald Freudenberger static int pkey_genprotkey(u32 keytype, struct pkey_protkey *protkey) 302a45a5c7dSIngo Franzki { 303a45a5c7dSIngo Franzki struct pkey_clrkey clrkey; 304a45a5c7dSIngo Franzki int keysize; 305a45a5c7dSIngo Franzki int rc; 306a45a5c7dSIngo Franzki 307a45a5c7dSIngo Franzki switch (keytype) { 308a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_128: 309a45a5c7dSIngo Franzki keysize = 16; 310a45a5c7dSIngo Franzki break; 311a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_192: 312a45a5c7dSIngo Franzki keysize = 24; 313a45a5c7dSIngo Franzki break; 314a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_256: 315a45a5c7dSIngo Franzki keysize = 32; 316a45a5c7dSIngo Franzki break; 317a45a5c7dSIngo Franzki default: 318a45a5c7dSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 319a45a5c7dSIngo Franzki keytype); 320a45a5c7dSIngo Franzki return -EINVAL; 321a45a5c7dSIngo Franzki } 322a45a5c7dSIngo Franzki 323a45a5c7dSIngo Franzki /* generate a dummy random clear key */ 324a45a5c7dSIngo Franzki get_random_bytes(clrkey.clrkey, keysize); 325a45a5c7dSIngo Franzki 326a45a5c7dSIngo Franzki /* convert it to a dummy protected key */ 327a45a5c7dSIngo Franzki rc = pkey_clr2protkey(keytype, &clrkey, protkey); 328a45a5c7dSIngo Franzki if (rc) 329a45a5c7dSIngo Franzki return rc; 330a45a5c7dSIngo Franzki 331a45a5c7dSIngo Franzki /* replace the key part of the protected key with random bytes */ 332a45a5c7dSIngo Franzki get_random_bytes(protkey->protkey, keysize); 333a45a5c7dSIngo Franzki 334a45a5c7dSIngo Franzki return 0; 335a45a5c7dSIngo Franzki } 336a45a5c7dSIngo Franzki 337a45a5c7dSIngo Franzki /* 338cb26b9ffSIngo Franzki * Verify if a protected key is still valid 339cb26b9ffSIngo Franzki */ 340183cb469SHarald Freudenberger static int pkey_verifyprotkey(const struct pkey_protkey *protkey) 341cb26b9ffSIngo Franzki { 342cb26b9ffSIngo Franzki unsigned long fc; 343cb26b9ffSIngo Franzki struct { 344cb26b9ffSIngo Franzki u8 iv[AES_BLOCK_SIZE]; 345cb26b9ffSIngo Franzki u8 key[MAXPROTKEYSIZE]; 346cb26b9ffSIngo Franzki } param; 347cb26b9ffSIngo Franzki u8 null_msg[AES_BLOCK_SIZE]; 348cb26b9ffSIngo Franzki u8 dest_buf[AES_BLOCK_SIZE]; 349cb26b9ffSIngo Franzki unsigned int k; 350cb26b9ffSIngo Franzki 351cb26b9ffSIngo Franzki switch (protkey->type) { 352cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_128: 353cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_128; 354cb26b9ffSIngo Franzki break; 355cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_192: 356cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_192; 357cb26b9ffSIngo Franzki break; 358cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_256: 359cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_256; 360cb26b9ffSIngo Franzki break; 361cb26b9ffSIngo Franzki default: 362cb26b9ffSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 363cb26b9ffSIngo Franzki protkey->type); 364cb26b9ffSIngo Franzki return -EINVAL; 365cb26b9ffSIngo Franzki } 366cb26b9ffSIngo Franzki 367cb26b9ffSIngo Franzki memset(null_msg, 0, sizeof(null_msg)); 368cb26b9ffSIngo Franzki 369cb26b9ffSIngo Franzki memset(param.iv, 0, sizeof(param.iv)); 370cb26b9ffSIngo Franzki memcpy(param.key, protkey->protkey, sizeof(param.key)); 371cb26b9ffSIngo Franzki 372cb26b9ffSIngo Franzki k = cpacf_kmc(fc | CPACF_ENCRYPT, ¶m, null_msg, dest_buf, 373cb26b9ffSIngo Franzki sizeof(null_msg)); 374cb26b9ffSIngo Franzki if (k != sizeof(null_msg)) { 375cb26b9ffSIngo Franzki DEBUG_ERR("%s protected key is not valid\n", __func__); 376cb26b9ffSIngo Franzki return -EKEYREJECTED; 377cb26b9ffSIngo Franzki } 378cb26b9ffSIngo Franzki 379cb26b9ffSIngo Franzki return 0; 380cb26b9ffSIngo Franzki } 381cb26b9ffSIngo Franzki 382cb26b9ffSIngo Franzki /* 383fb1136d6SIngo Franzki * Transform a non-CCA key token into a protected key 384fb1136d6SIngo Franzki */ 385183cb469SHarald Freudenberger static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, 386fb1136d6SIngo Franzki struct pkey_protkey *protkey) 387fb1136d6SIngo Franzki { 388888edbc4SHarald Freudenberger int rc = -EINVAL; 38955d0a513SHarald Freudenberger u8 *tmpbuf = NULL; 390fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 391fb1136d6SIngo Franzki 392fb1136d6SIngo Franzki switch (hdr->version) { 393888edbc4SHarald Freudenberger case TOKVER_PROTECTED_KEY: { 394888edbc4SHarald Freudenberger struct protaeskeytoken *t; 395fb1136d6SIngo Franzki 396888edbc4SHarald Freudenberger if (keylen != sizeof(struct protaeskeytoken)) 397888edbc4SHarald Freudenberger goto out; 398fb1136d6SIngo Franzki t = (struct protaeskeytoken *)key; 399fb1136d6SIngo Franzki protkey->len = t->len; 400fb1136d6SIngo Franzki protkey->type = t->keytype; 401fb1136d6SIngo Franzki memcpy(protkey->protkey, t->protkey, 402fb1136d6SIngo Franzki sizeof(protkey->protkey)); 403888edbc4SHarald Freudenberger rc = pkey_verifyprotkey(protkey); 404888edbc4SHarald Freudenberger break; 405888edbc4SHarald Freudenberger } 406888edbc4SHarald Freudenberger case TOKVER_CLEAR_KEY: { 407888edbc4SHarald Freudenberger struct clearaeskeytoken *t; 408888edbc4SHarald Freudenberger struct pkey_clrkey ckey; 40955d0a513SHarald Freudenberger union u_tmpbuf { 41055d0a513SHarald Freudenberger u8 skey[SECKEYBLOBSIZE]; 41155d0a513SHarald Freudenberger u8 ep11key[MAXEP11AESKEYBLOBSIZE]; 41255d0a513SHarald Freudenberger }; 41355d0a513SHarald Freudenberger size_t tmpbuflen = sizeof(union u_tmpbuf); 414fb1136d6SIngo Franzki 415888edbc4SHarald Freudenberger if (keylen < sizeof(struct clearaeskeytoken)) 416888edbc4SHarald Freudenberger goto out; 417888edbc4SHarald Freudenberger t = (struct clearaeskeytoken *)key; 418888edbc4SHarald Freudenberger if (keylen != sizeof(*t) + t->len) 419888edbc4SHarald Freudenberger goto out; 420888edbc4SHarald Freudenberger if ((t->keytype == PKEY_KEYTYPE_AES_128 && t->len == 16) 421888edbc4SHarald Freudenberger || (t->keytype == PKEY_KEYTYPE_AES_192 && t->len == 24) 422888edbc4SHarald Freudenberger || (t->keytype == PKEY_KEYTYPE_AES_256 && t->len == 32)) 423888edbc4SHarald Freudenberger memcpy(ckey.clrkey, t->clearkey, t->len); 424888edbc4SHarald Freudenberger else 425888edbc4SHarald Freudenberger goto out; 42655d0a513SHarald Freudenberger /* alloc temp key buffer space */ 42755d0a513SHarald Freudenberger tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC); 42855d0a513SHarald Freudenberger if (!tmpbuf) { 42955d0a513SHarald Freudenberger rc = -ENOMEM; 43055d0a513SHarald Freudenberger goto out; 43155d0a513SHarald Freudenberger } 432888edbc4SHarald Freudenberger /* try direct way with the PCKMO instruction */ 433888edbc4SHarald Freudenberger rc = pkey_clr2protkey(t->keytype, &ckey, protkey); 434888edbc4SHarald Freudenberger if (rc == 0) 435888edbc4SHarald Freudenberger break; 436888edbc4SHarald Freudenberger /* PCKMO failed, so try the CCA secure key way */ 437888edbc4SHarald Freudenberger rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, 43855d0a513SHarald Freudenberger ckey.clrkey, tmpbuf); 439888edbc4SHarald Freudenberger if (rc == 0) 44055d0a513SHarald Freudenberger rc = pkey_skey2pkey(tmpbuf, protkey); 441888edbc4SHarald Freudenberger if (rc == 0) 442888edbc4SHarald Freudenberger break; 44355d0a513SHarald Freudenberger /* if the CCA way also failed, let's try via EP11 */ 44455d0a513SHarald Freudenberger rc = pkey_clr2ep11key(ckey.clrkey, t->len, 44555d0a513SHarald Freudenberger tmpbuf, &tmpbuflen); 44655d0a513SHarald Freudenberger if (rc == 0) 44755d0a513SHarald Freudenberger rc = pkey_ep11key2pkey(tmpbuf, protkey); 44855d0a513SHarald Freudenberger /* now we should really have an protected key */ 449888edbc4SHarald Freudenberger DEBUG_ERR("%s unable to build protected key from clear", 450888edbc4SHarald Freudenberger __func__); 451888edbc4SHarald Freudenberger break; 452888edbc4SHarald Freudenberger } 45355d0a513SHarald Freudenberger case TOKVER_EP11_AES: { 45455d0a513SHarald Freudenberger /* check ep11 key for exportable as protected key */ 455*fa6999e3SHarald Freudenberger rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); 45655d0a513SHarald Freudenberger if (rc) 45755d0a513SHarald Freudenberger goto out; 45855d0a513SHarald Freudenberger rc = pkey_ep11key2pkey(key, protkey); 45955d0a513SHarald Freudenberger break; 46055d0a513SHarald Freudenberger } 461*fa6999e3SHarald Freudenberger case TOKVER_EP11_AES_WITH_HEADER: 462*fa6999e3SHarald Freudenberger /* check ep11 key with header for exportable as protected key */ 463*fa6999e3SHarald Freudenberger rc = ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1); 464*fa6999e3SHarald Freudenberger if (rc) 465*fa6999e3SHarald Freudenberger goto out; 466*fa6999e3SHarald Freudenberger rc = pkey_ep11key2pkey(key + sizeof(struct ep11kblob_header), 467*fa6999e3SHarald Freudenberger protkey); 468*fa6999e3SHarald Freudenberger break; 469fb1136d6SIngo Franzki default: 470fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n", 471fb1136d6SIngo Franzki __func__, hdr->version); 472888edbc4SHarald Freudenberger rc = -EINVAL; 473fb1136d6SIngo Franzki } 474888edbc4SHarald Freudenberger 475888edbc4SHarald Freudenberger out: 47655d0a513SHarald Freudenberger kfree(tmpbuf); 477888edbc4SHarald Freudenberger return rc; 478fb1136d6SIngo Franzki } 479fb1136d6SIngo Franzki 480fb1136d6SIngo Franzki /* 481fb1136d6SIngo Franzki * Transform a CCA internal key token into a protected key 482fb1136d6SIngo Franzki */ 483183cb469SHarald Freudenberger static int pkey_ccainttok2pkey(const u8 *key, u32 keylen, 484fb1136d6SIngo Franzki struct pkey_protkey *protkey) 485fb1136d6SIngo Franzki { 486fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 487fb1136d6SIngo Franzki 488fb1136d6SIngo Franzki switch (hdr->version) { 489fb1136d6SIngo Franzki case TOKVER_CCA_AES: 490fb1136d6SIngo Franzki if (keylen != sizeof(struct secaeskeytoken)) 491fb1136d6SIngo Franzki return -EINVAL; 492f2bbc96eSHarald Freudenberger break; 493f2bbc96eSHarald Freudenberger case TOKVER_CCA_VLSC: 494f2bbc96eSHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 495f2bbc96eSHarald Freudenberger return -EINVAL; 496f2bbc96eSHarald Freudenberger break; 497fb1136d6SIngo Franzki default: 498fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported CCA internal token version %d\n", 499fb1136d6SIngo Franzki __func__, hdr->version); 500fb1136d6SIngo Franzki return -EINVAL; 501fb1136d6SIngo Franzki } 502f2bbc96eSHarald Freudenberger 503f2bbc96eSHarald Freudenberger return pkey_skey2pkey(key, protkey); 504fb1136d6SIngo Franzki } 505fb1136d6SIngo Franzki 506fb1136d6SIngo Franzki /* 507fb1136d6SIngo Franzki * Transform a key blob (of any type) into a protected key 508fb1136d6SIngo Franzki */ 509183cb469SHarald Freudenberger int pkey_keyblob2pkey(const u8 *key, u32 keylen, 510fb1136d6SIngo Franzki struct pkey_protkey *protkey) 511fb1136d6SIngo Franzki { 512f2bbc96eSHarald Freudenberger int rc; 513fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 514fb1136d6SIngo Franzki 515f2bbc96eSHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) { 516f2bbc96eSHarald Freudenberger DEBUG_ERR("%s invalid keylen %d\n", __func__, keylen); 517f2bbc96eSHarald Freudenberger return -EINVAL; 518f2bbc96eSHarald Freudenberger } 519f2bbc96eSHarald Freudenberger 520f2bbc96eSHarald Freudenberger switch (hdr->type) { 521f2bbc96eSHarald Freudenberger case TOKTYPE_NON_CCA: 522f2bbc96eSHarald Freudenberger rc = pkey_nonccatok2pkey(key, keylen, protkey); 523f2bbc96eSHarald Freudenberger break; 524f2bbc96eSHarald Freudenberger case TOKTYPE_CCA_INTERNAL: 525f2bbc96eSHarald Freudenberger rc = pkey_ccainttok2pkey(key, keylen, protkey); 526f2bbc96eSHarald Freudenberger break; 527f2bbc96eSHarald Freudenberger default: 528f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 529f2bbc96eSHarald Freudenberger __func__, hdr->type); 530f2bbc96eSHarald Freudenberger return -EINVAL; 531f2bbc96eSHarald Freudenberger } 532f2bbc96eSHarald Freudenberger 533f2bbc96eSHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 534f2bbc96eSHarald Freudenberger return rc; 535f2bbc96eSHarald Freudenberger 536f2bbc96eSHarald Freudenberger } 537f2bbc96eSHarald Freudenberger EXPORT_SYMBOL(pkey_keyblob2pkey); 538f2bbc96eSHarald Freudenberger 539f2bbc96eSHarald Freudenberger static int pkey_genseckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 540f2bbc96eSHarald Freudenberger enum pkey_key_type ktype, enum pkey_key_size ksize, 541f2bbc96eSHarald Freudenberger u32 kflags, u8 *keybuf, size_t *keybufsize) 542f2bbc96eSHarald Freudenberger { 543f2bbc96eSHarald Freudenberger int i, card, dom, rc; 544f2bbc96eSHarald Freudenberger 545f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 546f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 547f2bbc96eSHarald Freudenberger return -EINVAL; 548f2bbc96eSHarald Freudenberger 549f2bbc96eSHarald Freudenberger /* check key type and size */ 550f2bbc96eSHarald Freudenberger switch (ktype) { 551f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_DATA: 552f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 553f2bbc96eSHarald Freudenberger if (*keybufsize < SECKEYBLOBSIZE) 554f2bbc96eSHarald Freudenberger return -EINVAL; 555f2bbc96eSHarald Freudenberger break; 55655d0a513SHarald Freudenberger case PKEY_TYPE_EP11: 55755d0a513SHarald Freudenberger if (*keybufsize < MINEP11AESKEYBLOBSIZE) 55855d0a513SHarald Freudenberger return -EINVAL; 55955d0a513SHarald Freudenberger break; 560f2bbc96eSHarald Freudenberger default: 561f2bbc96eSHarald Freudenberger return -EINVAL; 562f2bbc96eSHarald Freudenberger } 563f2bbc96eSHarald Freudenberger switch (ksize) { 564f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 565f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 566f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 567f2bbc96eSHarald Freudenberger break; 568f2bbc96eSHarald Freudenberger default: 569f2bbc96eSHarald Freudenberger return -EINVAL; 570f2bbc96eSHarald Freudenberger } 571f2bbc96eSHarald Freudenberger 572f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 573f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 574f2bbc96eSHarald Freudenberger card = apqns[i].card; 575f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 57655d0a513SHarald Freudenberger if (ktype == PKEY_TYPE_EP11) { 57755d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, ksize, kflags, 57855d0a513SHarald Freudenberger keybuf, keybufsize); 57955d0a513SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_DATA) { 580f2bbc96eSHarald Freudenberger rc = cca_genseckey(card, dom, ksize, keybuf); 581f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 582f2bbc96eSHarald Freudenberger } else /* TOKVER_CCA_VLSC */ 583f2bbc96eSHarald Freudenberger rc = cca_gencipherkey(card, dom, ksize, kflags, 584f2bbc96eSHarald Freudenberger keybuf, keybufsize); 585f2bbc96eSHarald Freudenberger if (rc == 0) 586f2bbc96eSHarald Freudenberger break; 587f2bbc96eSHarald Freudenberger } 588f2bbc96eSHarald Freudenberger 589f2bbc96eSHarald Freudenberger return rc; 590f2bbc96eSHarald Freudenberger } 591f2bbc96eSHarald Freudenberger 592f2bbc96eSHarald Freudenberger static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 593f2bbc96eSHarald Freudenberger enum pkey_key_type ktype, enum pkey_key_size ksize, 594f2bbc96eSHarald Freudenberger u32 kflags, const u8 *clrkey, 595f2bbc96eSHarald Freudenberger u8 *keybuf, size_t *keybufsize) 596f2bbc96eSHarald Freudenberger { 597f2bbc96eSHarald Freudenberger int i, card, dom, rc; 598f2bbc96eSHarald Freudenberger 599f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 600f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 601f2bbc96eSHarald Freudenberger return -EINVAL; 602f2bbc96eSHarald Freudenberger 603f2bbc96eSHarald Freudenberger /* check key type and size */ 604f2bbc96eSHarald Freudenberger switch (ktype) { 605f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_DATA: 606f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 607f2bbc96eSHarald Freudenberger if (*keybufsize < SECKEYBLOBSIZE) 608f2bbc96eSHarald Freudenberger return -EINVAL; 609f2bbc96eSHarald Freudenberger break; 61055d0a513SHarald Freudenberger case PKEY_TYPE_EP11: 61155d0a513SHarald Freudenberger if (*keybufsize < MINEP11AESKEYBLOBSIZE) 61255d0a513SHarald Freudenberger return -EINVAL; 61355d0a513SHarald Freudenberger break; 614f2bbc96eSHarald Freudenberger default: 615f2bbc96eSHarald Freudenberger return -EINVAL; 616f2bbc96eSHarald Freudenberger } 617f2bbc96eSHarald Freudenberger switch (ksize) { 618f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 619f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 620f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 621f2bbc96eSHarald Freudenberger break; 622f2bbc96eSHarald Freudenberger default: 623f2bbc96eSHarald Freudenberger return -EINVAL; 624f2bbc96eSHarald Freudenberger } 625f2bbc96eSHarald Freudenberger 626f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 627f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 628f2bbc96eSHarald Freudenberger card = apqns[i].card; 629f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 63055d0a513SHarald Freudenberger if (ktype == PKEY_TYPE_EP11) { 63155d0a513SHarald Freudenberger rc = ep11_clr2keyblob(card, dom, ksize, kflags, 63255d0a513SHarald Freudenberger clrkey, keybuf, keybufsize); 63355d0a513SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_DATA) { 634f2bbc96eSHarald Freudenberger rc = cca_clr2seckey(card, dom, ksize, 635f2bbc96eSHarald Freudenberger clrkey, keybuf); 636f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 637f2bbc96eSHarald Freudenberger } else /* TOKVER_CCA_VLSC */ 638f2bbc96eSHarald Freudenberger rc = cca_clr2cipherkey(card, dom, ksize, kflags, 639f2bbc96eSHarald Freudenberger clrkey, keybuf, keybufsize); 640f2bbc96eSHarald Freudenberger if (rc == 0) 641f2bbc96eSHarald Freudenberger break; 642f2bbc96eSHarald Freudenberger } 643f2bbc96eSHarald Freudenberger 644f2bbc96eSHarald Freudenberger return rc; 645f2bbc96eSHarald Freudenberger } 646f2bbc96eSHarald Freudenberger 647f2bbc96eSHarald Freudenberger static int pkey_verifykey2(const u8 *key, size_t keylen, 648f2bbc96eSHarald Freudenberger u16 *cardnr, u16 *domain, 649f2bbc96eSHarald Freudenberger enum pkey_key_type *ktype, 650f2bbc96eSHarald Freudenberger enum pkey_key_size *ksize, u32 *flags) 651f2bbc96eSHarald Freudenberger { 652f2bbc96eSHarald Freudenberger int rc; 653f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 654f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 655f2bbc96eSHarald Freudenberger 65655d0a513SHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) 657f2bbc96eSHarald Freudenberger return -EINVAL; 658f2bbc96eSHarald Freudenberger 65955d0a513SHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL 66055d0a513SHarald Freudenberger && hdr->version == TOKVER_CCA_AES) { 661f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 662f2bbc96eSHarald Freudenberger 663f2bbc96eSHarald Freudenberger rc = cca_check_secaeskeytoken(debug_info, 3, key, 0); 664f2bbc96eSHarald Freudenberger if (rc) 665f2bbc96eSHarald Freudenberger goto out; 666f2bbc96eSHarald Freudenberger if (ktype) 667f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_DATA; 668f2bbc96eSHarald Freudenberger if (ksize) 669f2bbc96eSHarald Freudenberger *ksize = (enum pkey_key_size) t->bitsize; 670f2bbc96eSHarald Freudenberger 671f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 67232ca04bbSHarald Freudenberger ZCRYPT_CEX3C, AES_MK_SET, t->mkvp, 0, 1); 673f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 674f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 675f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 676f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 677f2bbc96eSHarald Freudenberger *cardnr, *domain, 67832ca04bbSHarald Freudenberger ZCRYPT_CEX3C, AES_MK_SET, 67932ca04bbSHarald Freudenberger 0, t->mkvp, 1); 680f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 681f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 682f2bbc96eSHarald Freudenberger } 683f2bbc96eSHarald Freudenberger if (rc) 684f2bbc96eSHarald Freudenberger goto out; 685f2bbc96eSHarald Freudenberger 686f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 687f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 688f2bbc96eSHarald Freudenberger 68955d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL 69055d0a513SHarald Freudenberger && hdr->version == TOKVER_CCA_VLSC) { 691f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 692f2bbc96eSHarald Freudenberger 693f2bbc96eSHarald Freudenberger rc = cca_check_secaescipherkey(debug_info, 3, key, 0, 1); 694f2bbc96eSHarald Freudenberger if (rc) 695f2bbc96eSHarald Freudenberger goto out; 696f2bbc96eSHarald Freudenberger if (ktype) 697f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_CIPHER; 698f2bbc96eSHarald Freudenberger if (ksize) { 699f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_UNKNOWN; 700f2bbc96eSHarald Freudenberger if (!t->plfver && t->wpllen == 512) 701f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_128; 702f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 576) 703f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_192; 704f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 640) 705f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_256; 706f2bbc96eSHarald Freudenberger } 707f2bbc96eSHarald Freudenberger 708f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 70932ca04bbSHarald Freudenberger ZCRYPT_CEX6, AES_MK_SET, t->mkvp0, 0, 1); 710f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 711f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 712f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 713f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 714f2bbc96eSHarald Freudenberger *cardnr, *domain, 71532ca04bbSHarald Freudenberger ZCRYPT_CEX6, AES_MK_SET, 71632ca04bbSHarald Freudenberger 0, t->mkvp0, 1); 717f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 718f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 719f2bbc96eSHarald Freudenberger } 720f2bbc96eSHarald Freudenberger if (rc) 721f2bbc96eSHarald Freudenberger goto out; 722f2bbc96eSHarald Freudenberger 723f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 724f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 725f2bbc96eSHarald Freudenberger 72655d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA 72755d0a513SHarald Freudenberger && hdr->version == TOKVER_EP11_AES) { 72855d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *)key; 72955d0a513SHarald Freudenberger 730*fa6999e3SHarald Freudenberger rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); 73155d0a513SHarald Freudenberger if (rc) 73255d0a513SHarald Freudenberger goto out; 73355d0a513SHarald Freudenberger if (ktype) 73455d0a513SHarald Freudenberger *ktype = PKEY_TYPE_EP11; 73555d0a513SHarald Freudenberger if (ksize) 73655d0a513SHarald Freudenberger *ksize = kb->head.keybitlen; 73755d0a513SHarald Freudenberger 73855d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 73955d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, kb->wkvp); 74055d0a513SHarald Freudenberger if (rc) 74155d0a513SHarald Freudenberger goto out; 74255d0a513SHarald Freudenberger 74355d0a513SHarald Freudenberger if (flags) 74455d0a513SHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 74555d0a513SHarald Freudenberger 74655d0a513SHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 74755d0a513SHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 74855d0a513SHarald Freudenberger 749f2bbc96eSHarald Freudenberger } else 750f2bbc96eSHarald Freudenberger rc = -EINVAL; 751f2bbc96eSHarald Freudenberger 752f2bbc96eSHarald Freudenberger out: 753f2bbc96eSHarald Freudenberger kfree(_apqns); 754f2bbc96eSHarald Freudenberger return rc; 755f2bbc96eSHarald Freudenberger } 756f2bbc96eSHarald Freudenberger 757f2bbc96eSHarald Freudenberger static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, 758f2bbc96eSHarald Freudenberger const u8 *key, size_t keylen, 759f2bbc96eSHarald Freudenberger struct pkey_protkey *pkey) 760f2bbc96eSHarald Freudenberger { 761f2bbc96eSHarald Freudenberger int i, card, dom, rc; 762f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 763f2bbc96eSHarald Freudenberger 764f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 765f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 766f2bbc96eSHarald Freudenberger return -EINVAL; 767f2bbc96eSHarald Freudenberger 768fb1136d6SIngo Franzki if (keylen < sizeof(struct keytoken_header)) 769fb1136d6SIngo Franzki return -EINVAL; 770fb1136d6SIngo Franzki 77155d0a513SHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL) { 77255d0a513SHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 773f2bbc96eSHarald Freudenberger if (keylen != sizeof(struct secaeskeytoken)) 774f2bbc96eSHarald Freudenberger return -EINVAL; 775f2bbc96eSHarald Freudenberger if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) 776f2bbc96eSHarald Freudenberger return -EINVAL; 77755d0a513SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 778f2bbc96eSHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 779f2bbc96eSHarald Freudenberger return -EINVAL; 780f2bbc96eSHarald Freudenberger if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) 781f2bbc96eSHarald Freudenberger return -EINVAL; 78255d0a513SHarald Freudenberger } else { 783f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown CCA internal token version %d\n", 784f2bbc96eSHarald Freudenberger __func__, hdr->version); 785fb1136d6SIngo Franzki return -EINVAL; 786fb1136d6SIngo Franzki } 78755d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA) { 78855d0a513SHarald Freudenberger if (hdr->version == TOKVER_EP11_AES) { 78955d0a513SHarald Freudenberger if (keylen < sizeof(struct ep11keyblob)) 79055d0a513SHarald Freudenberger return -EINVAL; 791*fa6999e3SHarald Freudenberger if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) 79255d0a513SHarald Freudenberger return -EINVAL; 79355d0a513SHarald Freudenberger } else { 79455d0a513SHarald Freudenberger return pkey_nonccatok2pkey(key, keylen, pkey); 79555d0a513SHarald Freudenberger } 79655d0a513SHarald Freudenberger } else { 797f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 798f2bbc96eSHarald Freudenberger __func__, hdr->type); 799f2bbc96eSHarald Freudenberger return -EINVAL; 800fb1136d6SIngo Franzki } 801f2bbc96eSHarald Freudenberger 802f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 803f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 804f2bbc96eSHarald Freudenberger card = apqns[i].card; 805f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 80655d0a513SHarald Freudenberger if (hdr->type == TOKTYPE_CCA_INTERNAL 80755d0a513SHarald Freudenberger && hdr->version == TOKVER_CCA_AES) 808f2bbc96eSHarald Freudenberger rc = cca_sec2protkey(card, dom, key, pkey->protkey, 809f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 81055d0a513SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL 81155d0a513SHarald Freudenberger && hdr->version == TOKVER_CCA_VLSC) 812f2bbc96eSHarald Freudenberger rc = cca_cipher2protkey(card, dom, key, pkey->protkey, 813f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 81455d0a513SHarald Freudenberger else { /* EP11 AES secure key blob */ 81555d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *) key; 81655d0a513SHarald Freudenberger 817*fa6999e3SHarald Freudenberger pkey->len = sizeof(pkey->protkey); 818*fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, kb->head.len, 81955d0a513SHarald Freudenberger pkey->protkey, &pkey->len, 82055d0a513SHarald Freudenberger &pkey->type); 82155d0a513SHarald Freudenberger } 822f2bbc96eSHarald Freudenberger if (rc == 0) 823f2bbc96eSHarald Freudenberger break; 824f2bbc96eSHarald Freudenberger } 825f2bbc96eSHarald Freudenberger 826f2bbc96eSHarald Freudenberger return rc; 827f2bbc96eSHarald Freudenberger } 828f2bbc96eSHarald Freudenberger 829f2bbc96eSHarald Freudenberger static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, 830f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 831f2bbc96eSHarald Freudenberger { 83275be6b98STianjia Zhang int rc; 833f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 834f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 835f2bbc96eSHarald Freudenberger 83655d0a513SHarald Freudenberger if (keylen < sizeof(struct keytoken_header) || flags == 0) 837f2bbc96eSHarald Freudenberger return -EINVAL; 838f2bbc96eSHarald Freudenberger 839*fa6999e3SHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA 840*fa6999e3SHarald Freudenberger && (hdr->version == TOKVER_EP11_AES_WITH_HEADER 841*fa6999e3SHarald Freudenberger || hdr->version == TOKVER_EP11_ECC_WITH_HEADER) 842*fa6999e3SHarald Freudenberger && is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 843*fa6999e3SHarald Freudenberger int minhwtype = 0, api = 0; 844*fa6999e3SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *) 845*fa6999e3SHarald Freudenberger (key + sizeof(struct ep11kblob_header)); 846*fa6999e3SHarald Freudenberger 847*fa6999e3SHarald Freudenberger if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) 848*fa6999e3SHarald Freudenberger return -EINVAL; 849*fa6999e3SHarald Freudenberger if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { 850*fa6999e3SHarald Freudenberger minhwtype = ZCRYPT_CEX7; 851*fa6999e3SHarald Freudenberger api = EP11_API_V; 852*fa6999e3SHarald Freudenberger } 853*fa6999e3SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 854*fa6999e3SHarald Freudenberger minhwtype, api, kb->wkvp); 855*fa6999e3SHarald Freudenberger if (rc) 856*fa6999e3SHarald Freudenberger goto out; 857*fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA 858*fa6999e3SHarald Freudenberger && hdr->version == TOKVER_EP11_AES 859*fa6999e3SHarald Freudenberger && is_ep11_keyblob(key)) { 86055d0a513SHarald Freudenberger int minhwtype = 0, api = 0; 86155d0a513SHarald Freudenberger struct ep11keyblob *kb = (struct ep11keyblob *) key; 86255d0a513SHarald Freudenberger 86355d0a513SHarald Freudenberger if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) 86455d0a513SHarald Freudenberger return -EINVAL; 86555d0a513SHarald Freudenberger if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { 86655d0a513SHarald Freudenberger minhwtype = ZCRYPT_CEX7; 86755d0a513SHarald Freudenberger api = EP11_API_V; 86855d0a513SHarald Freudenberger } 86955d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 87055d0a513SHarald Freudenberger minhwtype, api, kb->wkvp); 87155d0a513SHarald Freudenberger if (rc) 87255d0a513SHarald Freudenberger goto out; 87355d0a513SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { 874f2bbc96eSHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 875f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 876f2bbc96eSHarald Freudenberger 877f2bbc96eSHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 878f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 879f2bbc96eSHarald Freudenberger 880f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 881f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp; 882f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 883f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp; 88455d0a513SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 885f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 886f2bbc96eSHarald Freudenberger 887f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 888f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 889f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp0; 890f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 891f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp0; 89255d0a513SHarald Freudenberger } else { 89355d0a513SHarald Freudenberger /* unknown cca internal token type */ 89455d0a513SHarald Freudenberger return -EINVAL; 895f2bbc96eSHarald Freudenberger } 896f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 89732ca04bbSHarald Freudenberger minhwtype, AES_MK_SET, 89832ca04bbSHarald Freudenberger cur_mkvp, old_mkvp, 1); 899f2bbc96eSHarald Freudenberger if (rc) 900f2bbc96eSHarald Freudenberger goto out; 901*fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { 902*fa6999e3SHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 903*fa6999e3SHarald Freudenberger struct eccprivkeytoken *t = (struct eccprivkeytoken *)key; 904*fa6999e3SHarald Freudenberger 905*fa6999e3SHarald Freudenberger if (t->secid == 0x20) { 906*fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 907*fa6999e3SHarald Freudenberger cur_mkvp = t->mkvp; 908*fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 909*fa6999e3SHarald Freudenberger old_mkvp = t->mkvp; 910*fa6999e3SHarald Freudenberger } else { 911*fa6999e3SHarald Freudenberger /* unknown cca internal 2 token type */ 912*fa6999e3SHarald Freudenberger return -EINVAL; 913*fa6999e3SHarald Freudenberger } 914*fa6999e3SHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 915*fa6999e3SHarald Freudenberger ZCRYPT_CEX7, APKA_MK_SET, 916*fa6999e3SHarald Freudenberger cur_mkvp, old_mkvp, 1); 917*fa6999e3SHarald Freudenberger if (rc) 918*fa6999e3SHarald Freudenberger goto out; 91955d0a513SHarald Freudenberger } else 92055d0a513SHarald Freudenberger return -EINVAL; 92155d0a513SHarald Freudenberger 922f2bbc96eSHarald Freudenberger if (apqns) { 923f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 924f2bbc96eSHarald Freudenberger rc = -ENOSPC; 925f2bbc96eSHarald Freudenberger else 926f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 927f2bbc96eSHarald Freudenberger } 928f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 929f2bbc96eSHarald Freudenberger 930f2bbc96eSHarald Freudenberger out: 931f2bbc96eSHarald Freudenberger kfree(_apqns); 932f2bbc96eSHarald Freudenberger return rc; 933f2bbc96eSHarald Freudenberger } 934f2bbc96eSHarald Freudenberger 935f2bbc96eSHarald Freudenberger static int pkey_apqns4keytype(enum pkey_key_type ktype, 936f2bbc96eSHarald Freudenberger u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, 937f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 938f2bbc96eSHarald Freudenberger { 93975be6b98STianjia Zhang int rc; 940f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 941f2bbc96eSHarald Freudenberger 942f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) { 943f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 944f2bbc96eSHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 945f2bbc96eSHarald Freudenberger 946f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 947f2bbc96eSHarald Freudenberger cur_mkvp = *((u64 *) cur_mkvp); 948f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 949f2bbc96eSHarald Freudenberger old_mkvp = *((u64 *) alt_mkvp); 950f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_CIPHER) 951f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 952f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 95332ca04bbSHarald Freudenberger minhwtype, AES_MK_SET, 95432ca04bbSHarald Freudenberger cur_mkvp, old_mkvp, 1); 955f2bbc96eSHarald Freudenberger if (rc) 956f2bbc96eSHarald Freudenberger goto out; 957*fa6999e3SHarald Freudenberger } else if (ktype == PKEY_TYPE_CCA_ECC) { 958*fa6999e3SHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 959*fa6999e3SHarald Freudenberger 960*fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 961*fa6999e3SHarald Freudenberger cur_mkvp = *((u64 *) cur_mkvp); 962*fa6999e3SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 963*fa6999e3SHarald Freudenberger old_mkvp = *((u64 *) alt_mkvp); 964*fa6999e3SHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 965*fa6999e3SHarald Freudenberger ZCRYPT_CEX7, APKA_MK_SET, 966*fa6999e3SHarald Freudenberger cur_mkvp, old_mkvp, 1); 967*fa6999e3SHarald Freudenberger if (rc) 968*fa6999e3SHarald Freudenberger goto out; 969*fa6999e3SHarald Freudenberger 970*fa6999e3SHarald Freudenberger } else if (ktype == PKEY_TYPE_EP11 || 971*fa6999e3SHarald Freudenberger ktype == PKEY_TYPE_EP11_AES || 972*fa6999e3SHarald Freudenberger ktype == PKEY_TYPE_EP11_ECC) { 97355d0a513SHarald Freudenberger u8 *wkvp = NULL; 97455d0a513SHarald Freudenberger 97555d0a513SHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 97655d0a513SHarald Freudenberger wkvp = cur_mkvp; 97755d0a513SHarald Freudenberger rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 97855d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, wkvp); 97955d0a513SHarald Freudenberger if (rc) 98055d0a513SHarald Freudenberger goto out; 98155d0a513SHarald Freudenberger 98255d0a513SHarald Freudenberger } else 98355d0a513SHarald Freudenberger return -EINVAL; 98455d0a513SHarald Freudenberger 985f2bbc96eSHarald Freudenberger if (apqns) { 986f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 987f2bbc96eSHarald Freudenberger rc = -ENOSPC; 988f2bbc96eSHarald Freudenberger else 989f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 990f2bbc96eSHarald Freudenberger } 991f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 992f2bbc96eSHarald Freudenberger 993f2bbc96eSHarald Freudenberger out: 994f2bbc96eSHarald Freudenberger kfree(_apqns); 995f2bbc96eSHarald Freudenberger return rc; 996f2bbc96eSHarald Freudenberger } 997fb1136d6SIngo Franzki 998*fa6999e3SHarald Freudenberger static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns, 999*fa6999e3SHarald Freudenberger const u8 *key, size_t keylen, u32 *protkeytype, 1000*fa6999e3SHarald Freudenberger u8 *protkey, u32 *protkeylen) 1001*fa6999e3SHarald Freudenberger { 1002*fa6999e3SHarald Freudenberger int i, card, dom, rc; 1003*fa6999e3SHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 1004*fa6999e3SHarald Freudenberger 1005*fa6999e3SHarald Freudenberger /* check for at least one apqn given */ 1006*fa6999e3SHarald Freudenberger if (!apqns || !nr_apqns) 1007*fa6999e3SHarald Freudenberger return -EINVAL; 1008*fa6999e3SHarald Freudenberger 1009*fa6999e3SHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) 1010*fa6999e3SHarald Freudenberger return -EINVAL; 1011*fa6999e3SHarald Freudenberger 1012*fa6999e3SHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA 1013*fa6999e3SHarald Freudenberger && hdr->version == TOKVER_EP11_AES_WITH_HEADER 1014*fa6999e3SHarald Freudenberger && is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 1015*fa6999e3SHarald Freudenberger /* EP11 AES key blob with header */ 1016*fa6999e3SHarald Freudenberger if (ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1)) 1017*fa6999e3SHarald Freudenberger return -EINVAL; 1018*fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA 1019*fa6999e3SHarald Freudenberger && hdr->version == TOKVER_EP11_ECC_WITH_HEADER 1020*fa6999e3SHarald Freudenberger && is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { 1021*fa6999e3SHarald Freudenberger /* EP11 ECC key blob with header */ 1022*fa6999e3SHarald Freudenberger if (ep11_check_ecc_key_with_hdr(debug_info, 3, key, keylen, 1)) 1023*fa6999e3SHarald Freudenberger return -EINVAL; 1024*fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA 1025*fa6999e3SHarald Freudenberger && hdr->version == TOKVER_EP11_AES 1026*fa6999e3SHarald Freudenberger && is_ep11_keyblob(key)) { 1027*fa6999e3SHarald Freudenberger /* EP11 AES key blob with header in session field */ 1028*fa6999e3SHarald Freudenberger if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) 1029*fa6999e3SHarald Freudenberger return -EINVAL; 1030*fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { 1031*fa6999e3SHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 1032*fa6999e3SHarald Freudenberger /* CCA AES data key */ 1033*fa6999e3SHarald Freudenberger if (keylen != sizeof(struct secaeskeytoken)) 1034*fa6999e3SHarald Freudenberger return -EINVAL; 1035*fa6999e3SHarald Freudenberger if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) 1036*fa6999e3SHarald Freudenberger return -EINVAL; 1037*fa6999e3SHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 1038*fa6999e3SHarald Freudenberger /* CCA AES cipher key */ 1039*fa6999e3SHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 1040*fa6999e3SHarald Freudenberger return -EINVAL; 1041*fa6999e3SHarald Freudenberger if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) 1042*fa6999e3SHarald Freudenberger return -EINVAL; 1043*fa6999e3SHarald Freudenberger } else { 1044*fa6999e3SHarald Freudenberger DEBUG_ERR("%s unknown CCA internal token version %d\n", 1045*fa6999e3SHarald Freudenberger __func__, hdr->version); 1046*fa6999e3SHarald Freudenberger return -EINVAL; 1047*fa6999e3SHarald Freudenberger } 1048*fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { 1049*fa6999e3SHarald Freudenberger /* CCA ECC (private) key */ 1050*fa6999e3SHarald Freudenberger if (keylen < sizeof(struct eccprivkeytoken)) 1051*fa6999e3SHarald Freudenberger return -EINVAL; 1052*fa6999e3SHarald Freudenberger if (cca_check_sececckeytoken(debug_info, 3, key, keylen, 1)) 1053*fa6999e3SHarald Freudenberger return -EINVAL; 1054*fa6999e3SHarald Freudenberger } else if (hdr->type == TOKTYPE_NON_CCA) { 1055*fa6999e3SHarald Freudenberger struct pkey_protkey pkey; 1056*fa6999e3SHarald Freudenberger 1057*fa6999e3SHarald Freudenberger rc = pkey_nonccatok2pkey(key, keylen, &pkey); 1058*fa6999e3SHarald Freudenberger if (rc) 1059*fa6999e3SHarald Freudenberger return rc; 1060*fa6999e3SHarald Freudenberger memcpy(protkey, pkey.protkey, pkey.len); 1061*fa6999e3SHarald Freudenberger *protkeylen = pkey.len; 1062*fa6999e3SHarald Freudenberger *protkeytype = pkey.type; 1063*fa6999e3SHarald Freudenberger return 0; 1064*fa6999e3SHarald Freudenberger } else { 1065*fa6999e3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 1066*fa6999e3SHarald Freudenberger __func__, hdr->type); 1067*fa6999e3SHarald Freudenberger return -EINVAL; 1068*fa6999e3SHarald Freudenberger } 1069*fa6999e3SHarald Freudenberger 1070*fa6999e3SHarald Freudenberger /* simple try all apqns from the list */ 1071*fa6999e3SHarald Freudenberger for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { 1072*fa6999e3SHarald Freudenberger card = apqns[i].card; 1073*fa6999e3SHarald Freudenberger dom = apqns[i].domain; 1074*fa6999e3SHarald Freudenberger if (hdr->type == TOKTYPE_NON_CCA 1075*fa6999e3SHarald Freudenberger && (hdr->version == TOKVER_EP11_AES_WITH_HEADER 1076*fa6999e3SHarald Freudenberger || hdr->version == TOKVER_EP11_ECC_WITH_HEADER) 1077*fa6999e3SHarald Freudenberger && is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) 1078*fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, hdr->len, 1079*fa6999e3SHarald Freudenberger protkey, protkeylen, protkeytype); 1080*fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_NON_CCA 1081*fa6999e3SHarald Freudenberger && hdr->version == TOKVER_EP11_AES 1082*fa6999e3SHarald Freudenberger && is_ep11_keyblob(key)) 1083*fa6999e3SHarald Freudenberger rc = ep11_kblob2protkey(card, dom, key, hdr->len, 1084*fa6999e3SHarald Freudenberger protkey, protkeylen, protkeytype); 1085*fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL && 1086*fa6999e3SHarald Freudenberger hdr->version == TOKVER_CCA_AES) 1087*fa6999e3SHarald Freudenberger rc = cca_sec2protkey(card, dom, key, protkey, 1088*fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1089*fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL && 1090*fa6999e3SHarald Freudenberger hdr->version == TOKVER_CCA_VLSC) 1091*fa6999e3SHarald Freudenberger rc = cca_cipher2protkey(card, dom, key, protkey, 1092*fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1093*fa6999e3SHarald Freudenberger else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) 1094*fa6999e3SHarald Freudenberger rc = cca_ecc2protkey(card, dom, key, protkey, 1095*fa6999e3SHarald Freudenberger protkeylen, protkeytype); 1096*fa6999e3SHarald Freudenberger else 1097*fa6999e3SHarald Freudenberger return -EINVAL; 1098*fa6999e3SHarald Freudenberger } 1099*fa6999e3SHarald Freudenberger 1100*fa6999e3SHarald Freudenberger return rc; 1101*fa6999e3SHarald Freudenberger } 1102*fa6999e3SHarald Freudenberger 1103fb1136d6SIngo Franzki /* 1104e80d4af0SHarald Freudenberger * File io functions 1105e80d4af0SHarald Freudenberger */ 1106e80d4af0SHarald Freudenberger 1107f2bbc96eSHarald Freudenberger static void *_copy_key_from_user(void __user *ukey, size_t keylen) 1108f2bbc96eSHarald Freudenberger { 1109f2bbc96eSHarald Freudenberger if (!ukey || keylen < MINKEYBLOBSIZE || keylen > KEYBLOBBUFSIZE) 1110f2bbc96eSHarald Freudenberger return ERR_PTR(-EINVAL); 1111f2bbc96eSHarald Freudenberger 11128b57e7c8SMarkus Elfring return memdup_user(ukey, keylen); 1113f2bbc96eSHarald Freudenberger } 1114f2bbc96eSHarald Freudenberger 1115f2bbc96eSHarald Freudenberger static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns) 1116f2bbc96eSHarald Freudenberger { 11178b57e7c8SMarkus Elfring if (!uapqns || nr_apqns == 0) 11188b57e7c8SMarkus Elfring return NULL; 1119f2bbc96eSHarald Freudenberger 11208b57e7c8SMarkus Elfring return memdup_user(uapqns, nr_apqns * sizeof(struct pkey_apqn)); 1121f2bbc96eSHarald Freudenberger } 1122f2bbc96eSHarald Freudenberger 1123e80d4af0SHarald Freudenberger static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, 1124e80d4af0SHarald Freudenberger unsigned long arg) 1125e80d4af0SHarald Freudenberger { 1126e80d4af0SHarald Freudenberger int rc; 1127e80d4af0SHarald Freudenberger 1128e80d4af0SHarald Freudenberger switch (cmd) { 1129e80d4af0SHarald Freudenberger case PKEY_GENSECK: { 1130e80d4af0SHarald Freudenberger struct pkey_genseck __user *ugs = (void __user *) arg; 1131e80d4af0SHarald Freudenberger struct pkey_genseck kgs; 1132e80d4af0SHarald Freudenberger 1133e80d4af0SHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 1134e80d4af0SHarald Freudenberger return -EFAULT; 1135efc598e6SHarald Freudenberger rc = cca_genseckey(kgs.cardnr, kgs.domain, 1136efc598e6SHarald Freudenberger kgs.keytype, kgs.seckey.seckey); 1137efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_genseckey()=%d\n", __func__, rc); 1138e80d4af0SHarald Freudenberger if (rc) 1139e80d4af0SHarald Freudenberger break; 1140e80d4af0SHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 1141e80d4af0SHarald Freudenberger return -EFAULT; 1142e80d4af0SHarald Freudenberger break; 1143e80d4af0SHarald Freudenberger } 1144e80d4af0SHarald Freudenberger case PKEY_CLR2SECK: { 1145e80d4af0SHarald Freudenberger struct pkey_clr2seck __user *ucs = (void __user *) arg; 1146e80d4af0SHarald Freudenberger struct pkey_clr2seck kcs; 1147e80d4af0SHarald Freudenberger 1148e80d4af0SHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 1149e80d4af0SHarald Freudenberger return -EFAULT; 1150efc598e6SHarald Freudenberger rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, 1151efc598e6SHarald Freudenberger kcs.clrkey.clrkey, kcs.seckey.seckey); 1152efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_clr2seckey()=%d\n", __func__, rc); 1153e80d4af0SHarald Freudenberger if (rc) 1154e80d4af0SHarald Freudenberger break; 1155e80d4af0SHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1156e80d4af0SHarald Freudenberger return -EFAULT; 1157e80d4af0SHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1158e80d4af0SHarald Freudenberger break; 1159e80d4af0SHarald Freudenberger } 1160e80d4af0SHarald Freudenberger case PKEY_SEC2PROTK: { 1161e80d4af0SHarald Freudenberger struct pkey_sec2protk __user *usp = (void __user *) arg; 1162e80d4af0SHarald Freudenberger struct pkey_sec2protk ksp; 1163e80d4af0SHarald Freudenberger 1164e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1165e80d4af0SHarald Freudenberger return -EFAULT; 1166efc598e6SHarald Freudenberger rc = cca_sec2protkey(ksp.cardnr, ksp.domain, 1167efc598e6SHarald Freudenberger ksp.seckey.seckey, ksp.protkey.protkey, 1168aab73d27SHarald Freudenberger &ksp.protkey.len, &ksp.protkey.type); 1169efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_sec2protkey()=%d\n", __func__, rc); 1170e80d4af0SHarald Freudenberger if (rc) 1171e80d4af0SHarald Freudenberger break; 1172e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1173e80d4af0SHarald Freudenberger return -EFAULT; 1174e80d4af0SHarald Freudenberger break; 1175e80d4af0SHarald Freudenberger } 1176e80d4af0SHarald Freudenberger case PKEY_CLR2PROTK: { 1177e80d4af0SHarald Freudenberger struct pkey_clr2protk __user *ucp = (void __user *) arg; 1178e80d4af0SHarald Freudenberger struct pkey_clr2protk kcp; 1179e80d4af0SHarald Freudenberger 1180e80d4af0SHarald Freudenberger if (copy_from_user(&kcp, ucp, sizeof(kcp))) 1181e80d4af0SHarald Freudenberger return -EFAULT; 1182e80d4af0SHarald Freudenberger rc = pkey_clr2protkey(kcp.keytype, 1183e80d4af0SHarald Freudenberger &kcp.clrkey, &kcp.protkey); 1184ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc); 1185e80d4af0SHarald Freudenberger if (rc) 1186e80d4af0SHarald Freudenberger break; 1187e80d4af0SHarald Freudenberger if (copy_to_user(ucp, &kcp, sizeof(kcp))) 1188e80d4af0SHarald Freudenberger return -EFAULT; 1189e80d4af0SHarald Freudenberger memzero_explicit(&kcp, sizeof(kcp)); 1190e80d4af0SHarald Freudenberger break; 1191e80d4af0SHarald Freudenberger } 1192e80d4af0SHarald Freudenberger case PKEY_FINDCARD: { 1193e80d4af0SHarald Freudenberger struct pkey_findcard __user *ufc = (void __user *) arg; 1194e80d4af0SHarald Freudenberger struct pkey_findcard kfc; 1195e80d4af0SHarald Freudenberger 1196e80d4af0SHarald Freudenberger if (copy_from_user(&kfc, ufc, sizeof(kfc))) 1197e80d4af0SHarald Freudenberger return -EFAULT; 1198efc598e6SHarald Freudenberger rc = cca_findcard(kfc.seckey.seckey, 1199e80d4af0SHarald Freudenberger &kfc.cardnr, &kfc.domain, 1); 1200efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_findcard()=%d\n", __func__, rc); 1201efc598e6SHarald Freudenberger if (rc < 0) 1202e80d4af0SHarald Freudenberger break; 1203e80d4af0SHarald Freudenberger if (copy_to_user(ufc, &kfc, sizeof(kfc))) 1204e80d4af0SHarald Freudenberger return -EFAULT; 1205e80d4af0SHarald Freudenberger break; 1206e80d4af0SHarald Freudenberger } 1207e80d4af0SHarald Freudenberger case PKEY_SKEY2PKEY: { 1208e80d4af0SHarald Freudenberger struct pkey_skey2pkey __user *usp = (void __user *) arg; 1209e80d4af0SHarald Freudenberger struct pkey_skey2pkey ksp; 1210e80d4af0SHarald Freudenberger 1211e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1212e80d4af0SHarald Freudenberger return -EFAULT; 1213f2bbc96eSHarald Freudenberger rc = pkey_skey2pkey(ksp.seckey.seckey, &ksp.protkey); 1214ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc); 1215e80d4af0SHarald Freudenberger if (rc) 1216e80d4af0SHarald Freudenberger break; 1217e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1218e80d4af0SHarald Freudenberger return -EFAULT; 1219e80d4af0SHarald Freudenberger break; 1220e80d4af0SHarald Freudenberger } 1221e61a6134SHarald Freudenberger case PKEY_VERIFYKEY: { 1222e61a6134SHarald Freudenberger struct pkey_verifykey __user *uvk = (void __user *) arg; 1223e61a6134SHarald Freudenberger struct pkey_verifykey kvk; 1224e61a6134SHarald Freudenberger 1225e61a6134SHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1226e61a6134SHarald Freudenberger return -EFAULT; 1227e61a6134SHarald Freudenberger rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain, 1228e61a6134SHarald Freudenberger &kvk.keysize, &kvk.attributes); 1229ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_verifykey()=%d\n", __func__, rc); 1230e61a6134SHarald Freudenberger if (rc) 1231e61a6134SHarald Freudenberger break; 1232e61a6134SHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1233e61a6134SHarald Freudenberger return -EFAULT; 1234e61a6134SHarald Freudenberger break; 1235e61a6134SHarald Freudenberger } 1236a45a5c7dSIngo Franzki case PKEY_GENPROTK: { 1237a45a5c7dSIngo Franzki struct pkey_genprotk __user *ugp = (void __user *) arg; 1238a45a5c7dSIngo Franzki struct pkey_genprotk kgp; 1239a45a5c7dSIngo Franzki 1240a45a5c7dSIngo Franzki if (copy_from_user(&kgp, ugp, sizeof(kgp))) 1241a45a5c7dSIngo Franzki return -EFAULT; 1242a45a5c7dSIngo Franzki rc = pkey_genprotkey(kgp.keytype, &kgp.protkey); 1243a45a5c7dSIngo Franzki DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc); 1244a45a5c7dSIngo Franzki if (rc) 1245a45a5c7dSIngo Franzki break; 1246a45a5c7dSIngo Franzki if (copy_to_user(ugp, &kgp, sizeof(kgp))) 1247a45a5c7dSIngo Franzki return -EFAULT; 1248a45a5c7dSIngo Franzki break; 1249a45a5c7dSIngo Franzki } 1250cb26b9ffSIngo Franzki case PKEY_VERIFYPROTK: { 1251cb26b9ffSIngo Franzki struct pkey_verifyprotk __user *uvp = (void __user *) arg; 1252cb26b9ffSIngo Franzki struct pkey_verifyprotk kvp; 1253cb26b9ffSIngo Franzki 1254cb26b9ffSIngo Franzki if (copy_from_user(&kvp, uvp, sizeof(kvp))) 1255cb26b9ffSIngo Franzki return -EFAULT; 1256cb26b9ffSIngo Franzki rc = pkey_verifyprotkey(&kvp.protkey); 1257cb26b9ffSIngo Franzki DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc); 1258cb26b9ffSIngo Franzki break; 1259cb26b9ffSIngo Franzki } 1260fb1136d6SIngo Franzki case PKEY_KBLOB2PROTK: { 1261fb1136d6SIngo Franzki struct pkey_kblob2pkey __user *utp = (void __user *) arg; 1262fb1136d6SIngo Franzki struct pkey_kblob2pkey ktp; 1263183cb469SHarald Freudenberger u8 *kkey; 1264fb1136d6SIngo Franzki 1265fb1136d6SIngo Franzki if (copy_from_user(&ktp, utp, sizeof(ktp))) 1266fb1136d6SIngo Franzki return -EFAULT; 1267f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1268f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 1269f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1270fb1136d6SIngo Franzki rc = pkey_keyblob2pkey(kkey, ktp.keylen, &ktp.protkey); 1271fb1136d6SIngo Franzki DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); 1272fb1136d6SIngo Franzki kfree(kkey); 1273fb1136d6SIngo Franzki if (rc) 1274fb1136d6SIngo Franzki break; 1275fb1136d6SIngo Franzki if (copy_to_user(utp, &ktp, sizeof(ktp))) 1276fb1136d6SIngo Franzki return -EFAULT; 1277fb1136d6SIngo Franzki break; 1278fb1136d6SIngo Franzki } 1279f2bbc96eSHarald Freudenberger case PKEY_GENSECK2: { 1280f2bbc96eSHarald Freudenberger struct pkey_genseck2 __user *ugs = (void __user *) arg; 1281f2bbc96eSHarald Freudenberger struct pkey_genseck2 kgs; 1282f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 1283f2bbc96eSHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 1284f2bbc96eSHarald Freudenberger u8 *kkey; 1285f2bbc96eSHarald Freudenberger 1286f2bbc96eSHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 1287f2bbc96eSHarald Freudenberger return -EFAULT; 1288f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries); 1289f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1290f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1291f2bbc96eSHarald Freudenberger kkey = kmalloc(klen, GFP_KERNEL); 1292f2bbc96eSHarald Freudenberger if (!kkey) { 1293f2bbc96eSHarald Freudenberger kfree(apqns); 1294f2bbc96eSHarald Freudenberger return -ENOMEM; 1295f2bbc96eSHarald Freudenberger } 1296f2bbc96eSHarald Freudenberger rc = pkey_genseckey2(apqns, kgs.apqn_entries, 1297f2bbc96eSHarald Freudenberger kgs.type, kgs.size, kgs.keygenflags, 1298f2bbc96eSHarald Freudenberger kkey, &klen); 1299f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_genseckey2()=%d\n", __func__, rc); 1300f2bbc96eSHarald Freudenberger kfree(apqns); 1301f2bbc96eSHarald Freudenberger if (rc) { 1302f2bbc96eSHarald Freudenberger kfree(kkey); 1303f2bbc96eSHarald Freudenberger break; 1304f2bbc96eSHarald Freudenberger } 1305f2bbc96eSHarald Freudenberger if (kgs.key) { 1306f2bbc96eSHarald Freudenberger if (kgs.keylen < klen) { 1307f2bbc96eSHarald Freudenberger kfree(kkey); 1308f2bbc96eSHarald Freudenberger return -EINVAL; 1309f2bbc96eSHarald Freudenberger } 1310f2bbc96eSHarald Freudenberger if (copy_to_user(kgs.key, kkey, klen)) { 1311f2bbc96eSHarald Freudenberger kfree(kkey); 1312f2bbc96eSHarald Freudenberger return -EFAULT; 1313f2bbc96eSHarald Freudenberger } 1314f2bbc96eSHarald Freudenberger } 1315f2bbc96eSHarald Freudenberger kgs.keylen = klen; 1316f2bbc96eSHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 1317f2bbc96eSHarald Freudenberger rc = -EFAULT; 1318f2bbc96eSHarald Freudenberger kfree(kkey); 1319f2bbc96eSHarald Freudenberger break; 1320f2bbc96eSHarald Freudenberger } 1321f2bbc96eSHarald Freudenberger case PKEY_CLR2SECK2: { 1322f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 __user *ucs = (void __user *) arg; 1323f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 kcs; 1324f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 1325f2bbc96eSHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 1326f2bbc96eSHarald Freudenberger u8 *kkey; 1327f2bbc96eSHarald Freudenberger 1328f2bbc96eSHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 1329f2bbc96eSHarald Freudenberger return -EFAULT; 1330f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries); 1331f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1332f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1333f2bbc96eSHarald Freudenberger kkey = kmalloc(klen, GFP_KERNEL); 1334f2bbc96eSHarald Freudenberger if (!kkey) { 1335f2bbc96eSHarald Freudenberger kfree(apqns); 1336f2bbc96eSHarald Freudenberger return -ENOMEM; 1337f2bbc96eSHarald Freudenberger } 1338f2bbc96eSHarald Freudenberger rc = pkey_clr2seckey2(apqns, kcs.apqn_entries, 1339f2bbc96eSHarald Freudenberger kcs.type, kcs.size, kcs.keygenflags, 1340f2bbc96eSHarald Freudenberger kcs.clrkey.clrkey, kkey, &klen); 1341f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_clr2seckey2()=%d\n", __func__, rc); 1342f2bbc96eSHarald Freudenberger kfree(apqns); 1343f2bbc96eSHarald Freudenberger if (rc) { 1344f2bbc96eSHarald Freudenberger kfree(kkey); 1345f2bbc96eSHarald Freudenberger break; 1346f2bbc96eSHarald Freudenberger } 1347f2bbc96eSHarald Freudenberger if (kcs.key) { 1348f2bbc96eSHarald Freudenberger if (kcs.keylen < klen) { 1349f2bbc96eSHarald Freudenberger kfree(kkey); 1350f2bbc96eSHarald Freudenberger return -EINVAL; 1351f2bbc96eSHarald Freudenberger } 1352f2bbc96eSHarald Freudenberger if (copy_to_user(kcs.key, kkey, klen)) { 1353f2bbc96eSHarald Freudenberger kfree(kkey); 1354f2bbc96eSHarald Freudenberger return -EFAULT; 1355f2bbc96eSHarald Freudenberger } 1356f2bbc96eSHarald Freudenberger } 1357f2bbc96eSHarald Freudenberger kcs.keylen = klen; 1358f2bbc96eSHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1359f2bbc96eSHarald Freudenberger rc = -EFAULT; 1360f2bbc96eSHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1361f2bbc96eSHarald Freudenberger kfree(kkey); 1362f2bbc96eSHarald Freudenberger break; 1363f2bbc96eSHarald Freudenberger } 1364f2bbc96eSHarald Freudenberger case PKEY_VERIFYKEY2: { 1365f2bbc96eSHarald Freudenberger struct pkey_verifykey2 __user *uvk = (void __user *) arg; 1366f2bbc96eSHarald Freudenberger struct pkey_verifykey2 kvk; 1367f2bbc96eSHarald Freudenberger u8 *kkey; 1368f2bbc96eSHarald Freudenberger 1369f2bbc96eSHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1370f2bbc96eSHarald Freudenberger return -EFAULT; 1371f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kvk.key, kvk.keylen); 1372f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 1373f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1374f2bbc96eSHarald Freudenberger rc = pkey_verifykey2(kkey, kvk.keylen, 1375f2bbc96eSHarald Freudenberger &kvk.cardnr, &kvk.domain, 1376f2bbc96eSHarald Freudenberger &kvk.type, &kvk.size, &kvk.flags); 1377f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_verifykey2()=%d\n", __func__, rc); 1378f2bbc96eSHarald Freudenberger kfree(kkey); 1379f2bbc96eSHarald Freudenberger if (rc) 1380f2bbc96eSHarald Freudenberger break; 1381f2bbc96eSHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1382f2bbc96eSHarald Freudenberger return -EFAULT; 1383f2bbc96eSHarald Freudenberger break; 1384f2bbc96eSHarald Freudenberger } 1385f2bbc96eSHarald Freudenberger case PKEY_KBLOB2PROTK2: { 1386f2bbc96eSHarald Freudenberger struct pkey_kblob2pkey2 __user *utp = (void __user *) arg; 1387f2bbc96eSHarald Freudenberger struct pkey_kblob2pkey2 ktp; 1388f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 1389f2bbc96eSHarald Freudenberger u8 *kkey; 1390f2bbc96eSHarald Freudenberger 1391f2bbc96eSHarald Freudenberger if (copy_from_user(&ktp, utp, sizeof(ktp))) 1392f2bbc96eSHarald Freudenberger return -EFAULT; 1393f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); 1394f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1395f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1396f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1397f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1398f2bbc96eSHarald Freudenberger kfree(apqns); 1399f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1400f2bbc96eSHarald Freudenberger } 1401f2bbc96eSHarald Freudenberger rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries, 1402f2bbc96eSHarald Freudenberger kkey, ktp.keylen, &ktp.protkey); 1403f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc); 1404f2bbc96eSHarald Freudenberger kfree(apqns); 1405f2bbc96eSHarald Freudenberger kfree(kkey); 1406f2bbc96eSHarald Freudenberger if (rc) 1407f2bbc96eSHarald Freudenberger break; 1408f2bbc96eSHarald Freudenberger if (copy_to_user(utp, &ktp, sizeof(ktp))) 1409f2bbc96eSHarald Freudenberger return -EFAULT; 1410f2bbc96eSHarald Freudenberger break; 1411f2bbc96eSHarald Freudenberger } 1412f2bbc96eSHarald Freudenberger case PKEY_APQNS4K: { 1413f2bbc96eSHarald Freudenberger struct pkey_apqns4key __user *uak = (void __user *) arg; 1414f2bbc96eSHarald Freudenberger struct pkey_apqns4key kak; 1415f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 1416f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1417f2bbc96eSHarald Freudenberger u8 *kkey; 1418f2bbc96eSHarald Freudenberger 1419f2bbc96eSHarald Freudenberger if (copy_from_user(&kak, uak, sizeof(kak))) 1420f2bbc96eSHarald Freudenberger return -EFAULT; 1421f2bbc96eSHarald Freudenberger nr_apqns = kak.apqn_entries; 1422f2bbc96eSHarald Freudenberger if (nr_apqns) { 1423f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1424f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1425f2bbc96eSHarald Freudenberger GFP_KERNEL); 1426f2bbc96eSHarald Freudenberger if (!apqns) 1427f2bbc96eSHarald Freudenberger return -ENOMEM; 1428f2bbc96eSHarald Freudenberger } 1429f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kak.key, kak.keylen); 1430f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1431f2bbc96eSHarald Freudenberger kfree(apqns); 1432f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1433f2bbc96eSHarald Freudenberger } 1434f2bbc96eSHarald Freudenberger rc = pkey_apqns4key(kkey, kak.keylen, kak.flags, 1435f2bbc96eSHarald Freudenberger apqns, &nr_apqns); 1436f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4key()=%d\n", __func__, rc); 1437f2bbc96eSHarald Freudenberger kfree(kkey); 1438f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1439f2bbc96eSHarald Freudenberger kfree(apqns); 1440f2bbc96eSHarald Freudenberger break; 1441f2bbc96eSHarald Freudenberger } 1442f2bbc96eSHarald Freudenberger if (!rc && kak.apqns) { 1443f2bbc96eSHarald Freudenberger if (nr_apqns > kak.apqn_entries) { 1444f2bbc96eSHarald Freudenberger kfree(apqns); 1445f2bbc96eSHarald Freudenberger return -EINVAL; 1446f2bbc96eSHarald Freudenberger } 1447f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1448f2bbc96eSHarald Freudenberger if (len) { 1449f2bbc96eSHarald Freudenberger if (copy_to_user(kak.apqns, apqns, len)) { 1450f2bbc96eSHarald Freudenberger kfree(apqns); 1451f2bbc96eSHarald Freudenberger return -EFAULT; 1452f2bbc96eSHarald Freudenberger } 1453f2bbc96eSHarald Freudenberger } 1454f2bbc96eSHarald Freudenberger } 1455f2bbc96eSHarald Freudenberger kak.apqn_entries = nr_apqns; 1456f2bbc96eSHarald Freudenberger if (copy_to_user(uak, &kak, sizeof(kak))) 1457f2bbc96eSHarald Freudenberger rc = -EFAULT; 1458f2bbc96eSHarald Freudenberger kfree(apqns); 1459f2bbc96eSHarald Freudenberger break; 1460f2bbc96eSHarald Freudenberger } 1461f2bbc96eSHarald Freudenberger case PKEY_APQNS4KT: { 1462f2bbc96eSHarald Freudenberger struct pkey_apqns4keytype __user *uat = (void __user *) arg; 1463f2bbc96eSHarald Freudenberger struct pkey_apqns4keytype kat; 1464f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 1465f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1466f2bbc96eSHarald Freudenberger 1467f2bbc96eSHarald Freudenberger if (copy_from_user(&kat, uat, sizeof(kat))) 1468f2bbc96eSHarald Freudenberger return -EFAULT; 1469f2bbc96eSHarald Freudenberger nr_apqns = kat.apqn_entries; 1470f2bbc96eSHarald Freudenberger if (nr_apqns) { 1471f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1472f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1473f2bbc96eSHarald Freudenberger GFP_KERNEL); 1474f2bbc96eSHarald Freudenberger if (!apqns) 1475f2bbc96eSHarald Freudenberger return -ENOMEM; 1476f2bbc96eSHarald Freudenberger } 1477f2bbc96eSHarald Freudenberger rc = pkey_apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp, 1478f2bbc96eSHarald Freudenberger kat.flags, apqns, &nr_apqns); 1479f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4keytype()=%d\n", __func__, rc); 1480f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1481f2bbc96eSHarald Freudenberger kfree(apqns); 1482f2bbc96eSHarald Freudenberger break; 1483f2bbc96eSHarald Freudenberger } 1484f2bbc96eSHarald Freudenberger if (!rc && kat.apqns) { 1485f2bbc96eSHarald Freudenberger if (nr_apqns > kat.apqn_entries) { 1486f2bbc96eSHarald Freudenberger kfree(apqns); 1487f2bbc96eSHarald Freudenberger return -EINVAL; 1488f2bbc96eSHarald Freudenberger } 1489f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1490f2bbc96eSHarald Freudenberger if (len) { 1491f2bbc96eSHarald Freudenberger if (copy_to_user(kat.apqns, apqns, len)) { 1492f2bbc96eSHarald Freudenberger kfree(apqns); 1493f2bbc96eSHarald Freudenberger return -EFAULT; 1494f2bbc96eSHarald Freudenberger } 1495f2bbc96eSHarald Freudenberger } 1496f2bbc96eSHarald Freudenberger } 1497f2bbc96eSHarald Freudenberger kat.apqn_entries = nr_apqns; 1498f2bbc96eSHarald Freudenberger if (copy_to_user(uat, &kat, sizeof(kat))) 1499f2bbc96eSHarald Freudenberger rc = -EFAULT; 1500f2bbc96eSHarald Freudenberger kfree(apqns); 1501f2bbc96eSHarald Freudenberger break; 1502f2bbc96eSHarald Freudenberger } 1503*fa6999e3SHarald Freudenberger case PKEY_KBLOB2PROTK3: { 1504*fa6999e3SHarald Freudenberger struct pkey_kblob2pkey3 __user *utp = (void __user *) arg; 1505*fa6999e3SHarald Freudenberger struct pkey_kblob2pkey3 ktp; 1506*fa6999e3SHarald Freudenberger struct pkey_apqn *apqns = NULL; 1507*fa6999e3SHarald Freudenberger u32 protkeylen = PROTKEYBLOBBUFSIZE; 1508*fa6999e3SHarald Freudenberger u8 *kkey, *protkey; 1509*fa6999e3SHarald Freudenberger 1510*fa6999e3SHarald Freudenberger if (copy_from_user(&ktp, utp, sizeof(ktp))) 1511*fa6999e3SHarald Freudenberger return -EFAULT; 1512*fa6999e3SHarald Freudenberger apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); 1513*fa6999e3SHarald Freudenberger if (IS_ERR(apqns)) 1514*fa6999e3SHarald Freudenberger return PTR_ERR(apqns); 1515*fa6999e3SHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1516*fa6999e3SHarald Freudenberger if (IS_ERR(kkey)) { 1517*fa6999e3SHarald Freudenberger kfree(apqns); 1518*fa6999e3SHarald Freudenberger return PTR_ERR(kkey); 1519*fa6999e3SHarald Freudenberger } 1520*fa6999e3SHarald Freudenberger protkey = kmalloc(protkeylen, GFP_KERNEL); 1521*fa6999e3SHarald Freudenberger if (!protkey) { 1522*fa6999e3SHarald Freudenberger kfree(apqns); 1523*fa6999e3SHarald Freudenberger kfree(kkey); 1524*fa6999e3SHarald Freudenberger return -ENOMEM; 1525*fa6999e3SHarald Freudenberger } 1526*fa6999e3SHarald Freudenberger rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries, kkey, 1527*fa6999e3SHarald Freudenberger ktp.keylen, &ktp.pkeytype, 1528*fa6999e3SHarald Freudenberger protkey, &protkeylen); 1529*fa6999e3SHarald Freudenberger DEBUG_DBG("%s pkey_keyblob2pkey3()=%d\n", __func__, rc); 1530*fa6999e3SHarald Freudenberger kfree(apqns); 1531*fa6999e3SHarald Freudenberger kfree(kkey); 1532*fa6999e3SHarald Freudenberger if (rc) { 1533*fa6999e3SHarald Freudenberger kfree(protkey); 1534*fa6999e3SHarald Freudenberger break; 1535*fa6999e3SHarald Freudenberger } 1536*fa6999e3SHarald Freudenberger if (ktp.pkey && ktp.pkeylen) { 1537*fa6999e3SHarald Freudenberger if (protkeylen > ktp.pkeylen) { 1538*fa6999e3SHarald Freudenberger kfree(protkey); 1539*fa6999e3SHarald Freudenberger return -EINVAL; 1540*fa6999e3SHarald Freudenberger } 1541*fa6999e3SHarald Freudenberger if (copy_to_user(ktp.pkey, protkey, protkeylen)) { 1542*fa6999e3SHarald Freudenberger kfree(protkey); 1543*fa6999e3SHarald Freudenberger return -EFAULT; 1544*fa6999e3SHarald Freudenberger } 1545*fa6999e3SHarald Freudenberger } 1546*fa6999e3SHarald Freudenberger kfree(protkey); 1547*fa6999e3SHarald Freudenberger ktp.pkeylen = protkeylen; 1548*fa6999e3SHarald Freudenberger if (copy_to_user(utp, &ktp, sizeof(ktp))) 1549*fa6999e3SHarald Freudenberger return -EFAULT; 1550*fa6999e3SHarald Freudenberger break; 1551*fa6999e3SHarald Freudenberger } 1552e80d4af0SHarald Freudenberger default: 1553e80d4af0SHarald Freudenberger /* unknown/unsupported ioctl cmd */ 1554e80d4af0SHarald Freudenberger return -ENOTTY; 1555e80d4af0SHarald Freudenberger } 1556e80d4af0SHarald Freudenberger 1557e80d4af0SHarald Freudenberger return rc; 1558e80d4af0SHarald Freudenberger } 1559e80d4af0SHarald Freudenberger 1560e80d4af0SHarald Freudenberger /* 1561e80d4af0SHarald Freudenberger * Sysfs and file io operations 1562e80d4af0SHarald Freudenberger */ 1563d632c047SIngo Franzki 1564d632c047SIngo Franzki /* 1565d632c047SIngo Franzki * Sysfs attribute read function for all protected key binary attributes. 1566d632c047SIngo Franzki * The implementation can not deal with partial reads, because a new random 1567d632c047SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1568d632c047SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1569d632c047SIngo Franzki */ 1570d632c047SIngo Franzki static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1571d632c047SIngo Franzki loff_t off, size_t count) 1572d632c047SIngo Franzki { 1573d632c047SIngo Franzki struct protaeskeytoken protkeytoken; 1574d632c047SIngo Franzki struct pkey_protkey protkey; 1575d632c047SIngo Franzki int rc; 1576d632c047SIngo Franzki 1577d632c047SIngo Franzki if (off != 0 || count < sizeof(protkeytoken)) 1578d632c047SIngo Franzki return -EINVAL; 1579d632c047SIngo Franzki if (is_xts) 1580d632c047SIngo Franzki if (count < 2 * sizeof(protkeytoken)) 1581d632c047SIngo Franzki return -EINVAL; 1582d632c047SIngo Franzki 1583d632c047SIngo Franzki memset(&protkeytoken, 0, sizeof(protkeytoken)); 1584d632c047SIngo Franzki protkeytoken.type = TOKTYPE_NON_CCA; 1585d632c047SIngo Franzki protkeytoken.version = TOKVER_PROTECTED_KEY; 1586d632c047SIngo Franzki protkeytoken.keytype = keytype; 1587d632c047SIngo Franzki 1588d632c047SIngo Franzki rc = pkey_genprotkey(protkeytoken.keytype, &protkey); 1589d632c047SIngo Franzki if (rc) 1590d632c047SIngo Franzki return rc; 1591d632c047SIngo Franzki 1592d632c047SIngo Franzki protkeytoken.len = protkey.len; 1593d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1594d632c047SIngo Franzki 1595d632c047SIngo Franzki memcpy(buf, &protkeytoken, sizeof(protkeytoken)); 1596d632c047SIngo Franzki 1597d632c047SIngo Franzki if (is_xts) { 1598d632c047SIngo Franzki rc = pkey_genprotkey(protkeytoken.keytype, &protkey); 1599d632c047SIngo Franzki if (rc) 1600d632c047SIngo Franzki return rc; 1601d632c047SIngo Franzki 1602d632c047SIngo Franzki protkeytoken.len = protkey.len; 1603d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1604d632c047SIngo Franzki 1605d632c047SIngo Franzki memcpy(buf + sizeof(protkeytoken), &protkeytoken, 1606d632c047SIngo Franzki sizeof(protkeytoken)); 1607d632c047SIngo Franzki 1608d632c047SIngo Franzki return 2 * sizeof(protkeytoken); 1609d632c047SIngo Franzki } 1610d632c047SIngo Franzki 1611d632c047SIngo Franzki return sizeof(protkeytoken); 1612d632c047SIngo Franzki } 1613d632c047SIngo Franzki 1614d632c047SIngo Franzki static ssize_t protkey_aes_128_read(struct file *filp, 1615d632c047SIngo Franzki struct kobject *kobj, 1616d632c047SIngo Franzki struct bin_attribute *attr, 1617d632c047SIngo Franzki char *buf, loff_t off, 1618d632c047SIngo Franzki size_t count) 1619d632c047SIngo Franzki { 1620d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1621d632c047SIngo Franzki off, count); 1622d632c047SIngo Franzki } 1623d632c047SIngo Franzki 1624d632c047SIngo Franzki static ssize_t protkey_aes_192_read(struct file *filp, 1625d632c047SIngo Franzki struct kobject *kobj, 1626d632c047SIngo Franzki struct bin_attribute *attr, 1627d632c047SIngo Franzki char *buf, loff_t off, 1628d632c047SIngo Franzki size_t count) 1629d632c047SIngo Franzki { 1630d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1631d632c047SIngo Franzki off, count); 1632d632c047SIngo Franzki } 1633d632c047SIngo Franzki 1634d632c047SIngo Franzki static ssize_t protkey_aes_256_read(struct file *filp, 1635d632c047SIngo Franzki struct kobject *kobj, 1636d632c047SIngo Franzki struct bin_attribute *attr, 1637d632c047SIngo Franzki char *buf, loff_t off, 1638d632c047SIngo Franzki size_t count) 1639d632c047SIngo Franzki { 1640d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1641d632c047SIngo Franzki off, count); 1642d632c047SIngo Franzki } 1643d632c047SIngo Franzki 1644d632c047SIngo Franzki static ssize_t protkey_aes_128_xts_read(struct file *filp, 1645d632c047SIngo Franzki struct kobject *kobj, 1646d632c047SIngo Franzki struct bin_attribute *attr, 1647d632c047SIngo Franzki char *buf, loff_t off, 1648d632c047SIngo Franzki size_t count) 1649d632c047SIngo Franzki { 1650d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1651d632c047SIngo Franzki off, count); 1652d632c047SIngo Franzki } 1653d632c047SIngo Franzki 1654d632c047SIngo Franzki static ssize_t protkey_aes_256_xts_read(struct file *filp, 1655d632c047SIngo Franzki struct kobject *kobj, 1656d632c047SIngo Franzki struct bin_attribute *attr, 1657d632c047SIngo Franzki char *buf, loff_t off, 1658d632c047SIngo Franzki size_t count) 1659d632c047SIngo Franzki { 1660d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1661d632c047SIngo Franzki off, count); 1662d632c047SIngo Franzki } 1663d632c047SIngo Franzki 1664d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128, sizeof(struct protaeskeytoken)); 1665d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_192, sizeof(struct protaeskeytoken)); 1666d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256, sizeof(struct protaeskeytoken)); 1667d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128_xts, 2 * sizeof(struct protaeskeytoken)); 1668d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256_xts, 2 * sizeof(struct protaeskeytoken)); 1669d632c047SIngo Franzki 1670d632c047SIngo Franzki static struct bin_attribute *protkey_attrs[] = { 1671d632c047SIngo Franzki &bin_attr_protkey_aes_128, 1672d632c047SIngo Franzki &bin_attr_protkey_aes_192, 1673d632c047SIngo Franzki &bin_attr_protkey_aes_256, 1674d632c047SIngo Franzki &bin_attr_protkey_aes_128_xts, 1675d632c047SIngo Franzki &bin_attr_protkey_aes_256_xts, 1676d632c047SIngo Franzki NULL 1677d632c047SIngo Franzki }; 1678d632c047SIngo Franzki 1679d632c047SIngo Franzki static struct attribute_group protkey_attr_group = { 1680d632c047SIngo Franzki .name = "protkey", 1681d632c047SIngo Franzki .bin_attrs = protkey_attrs, 1682d632c047SIngo Franzki }; 1683d632c047SIngo Franzki 1684af504452SIngo Franzki /* 1685af504452SIngo Franzki * Sysfs attribute read function for all secure key ccadata binary attributes. 1686af504452SIngo Franzki * The implementation can not deal with partial reads, because a new random 1687af504452SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1688af504452SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1689af504452SIngo Franzki */ 1690af504452SIngo Franzki static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1691af504452SIngo Franzki loff_t off, size_t count) 1692af504452SIngo Franzki { 1693af504452SIngo Franzki int rc; 1694efc598e6SHarald Freudenberger struct pkey_seckey *seckey = (struct pkey_seckey *) buf; 1695af504452SIngo Franzki 1696af504452SIngo Franzki if (off != 0 || count < sizeof(struct secaeskeytoken)) 1697af504452SIngo Franzki return -EINVAL; 1698af504452SIngo Franzki if (is_xts) 1699af504452SIngo Franzki if (count < 2 * sizeof(struct secaeskeytoken)) 1700af504452SIngo Franzki return -EINVAL; 1701af504452SIngo Franzki 1702efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1703af504452SIngo Franzki if (rc) 1704af504452SIngo Franzki return rc; 1705af504452SIngo Franzki 1706af504452SIngo Franzki if (is_xts) { 1707efc598e6SHarald Freudenberger seckey++; 1708efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1709af504452SIngo Franzki if (rc) 1710af504452SIngo Franzki return rc; 1711af504452SIngo Franzki 1712af504452SIngo Franzki return 2 * sizeof(struct secaeskeytoken); 1713af504452SIngo Franzki } 1714af504452SIngo Franzki 1715af504452SIngo Franzki return sizeof(struct secaeskeytoken); 1716af504452SIngo Franzki } 1717af504452SIngo Franzki 1718af504452SIngo Franzki static ssize_t ccadata_aes_128_read(struct file *filp, 1719af504452SIngo Franzki struct kobject *kobj, 1720af504452SIngo Franzki struct bin_attribute *attr, 1721af504452SIngo Franzki char *buf, loff_t off, 1722af504452SIngo Franzki size_t count) 1723af504452SIngo Franzki { 1724af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1725af504452SIngo Franzki off, count); 1726af504452SIngo Franzki } 1727af504452SIngo Franzki 1728af504452SIngo Franzki static ssize_t ccadata_aes_192_read(struct file *filp, 1729af504452SIngo Franzki struct kobject *kobj, 1730af504452SIngo Franzki struct bin_attribute *attr, 1731af504452SIngo Franzki char *buf, loff_t off, 1732af504452SIngo Franzki size_t count) 1733af504452SIngo Franzki { 1734af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1735af504452SIngo Franzki off, count); 1736af504452SIngo Franzki } 1737af504452SIngo Franzki 1738af504452SIngo Franzki static ssize_t ccadata_aes_256_read(struct file *filp, 1739af504452SIngo Franzki struct kobject *kobj, 1740af504452SIngo Franzki struct bin_attribute *attr, 1741af504452SIngo Franzki char *buf, loff_t off, 1742af504452SIngo Franzki size_t count) 1743af504452SIngo Franzki { 1744af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1745af504452SIngo Franzki off, count); 1746af504452SIngo Franzki } 1747af504452SIngo Franzki 1748af504452SIngo Franzki static ssize_t ccadata_aes_128_xts_read(struct file *filp, 1749af504452SIngo Franzki struct kobject *kobj, 1750af504452SIngo Franzki struct bin_attribute *attr, 1751af504452SIngo Franzki char *buf, loff_t off, 1752af504452SIngo Franzki size_t count) 1753af504452SIngo Franzki { 1754af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1755af504452SIngo Franzki off, count); 1756af504452SIngo Franzki } 1757af504452SIngo Franzki 1758af504452SIngo Franzki static ssize_t ccadata_aes_256_xts_read(struct file *filp, 1759af504452SIngo Franzki struct kobject *kobj, 1760af504452SIngo Franzki struct bin_attribute *attr, 1761af504452SIngo Franzki char *buf, loff_t off, 1762af504452SIngo Franzki size_t count) 1763af504452SIngo Franzki { 1764af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1765af504452SIngo Franzki off, count); 1766af504452SIngo Franzki } 1767af504452SIngo Franzki 1768af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128, sizeof(struct secaeskeytoken)); 1769af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_192, sizeof(struct secaeskeytoken)); 1770af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256, sizeof(struct secaeskeytoken)); 1771af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128_xts, 2 * sizeof(struct secaeskeytoken)); 1772af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256_xts, 2 * sizeof(struct secaeskeytoken)); 1773af504452SIngo Franzki 1774af504452SIngo Franzki static struct bin_attribute *ccadata_attrs[] = { 1775af504452SIngo Franzki &bin_attr_ccadata_aes_128, 1776af504452SIngo Franzki &bin_attr_ccadata_aes_192, 1777af504452SIngo Franzki &bin_attr_ccadata_aes_256, 1778af504452SIngo Franzki &bin_attr_ccadata_aes_128_xts, 1779af504452SIngo Franzki &bin_attr_ccadata_aes_256_xts, 1780af504452SIngo Franzki NULL 1781af504452SIngo Franzki }; 1782af504452SIngo Franzki 1783af504452SIngo Franzki static struct attribute_group ccadata_attr_group = { 1784af504452SIngo Franzki .name = "ccadata", 1785af504452SIngo Franzki .bin_attrs = ccadata_attrs, 1786af504452SIngo Franzki }; 1787af504452SIngo Franzki 1788f71fee27SIngo Franzki #define CCACIPHERTOKENSIZE (sizeof(struct cipherkeytoken) + 80) 1789f71fee27SIngo Franzki 1790f71fee27SIngo Franzki /* 1791f71fee27SIngo Franzki * Sysfs attribute read function for all secure key ccacipher binary attributes. 1792f71fee27SIngo Franzki * The implementation can not deal with partial reads, because a new random 1793f71fee27SIngo Franzki * secure key blob is generated with each read. In case of partial reads 1794f71fee27SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1795f71fee27SIngo Franzki */ 1796f71fee27SIngo Franzki static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits, 1797f71fee27SIngo Franzki bool is_xts, char *buf, loff_t off, 1798f71fee27SIngo Franzki size_t count) 1799f71fee27SIngo Franzki { 180055d0a513SHarald Freudenberger int i, rc, card, dom; 180155d0a513SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 180255d0a513SHarald Freudenberger size_t keysize = CCACIPHERTOKENSIZE; 1803f71fee27SIngo Franzki 1804f71fee27SIngo Franzki if (off != 0 || count < CCACIPHERTOKENSIZE) 1805f71fee27SIngo Franzki return -EINVAL; 1806f71fee27SIngo Franzki if (is_xts) 1807f71fee27SIngo Franzki if (count < 2 * CCACIPHERTOKENSIZE) 1808f71fee27SIngo Franzki return -EINVAL; 1809f71fee27SIngo Franzki 181055d0a513SHarald Freudenberger /* build a list of apqns able to generate an cipher key */ 181155d0a513SHarald Freudenberger rc = cca_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 181232ca04bbSHarald Freudenberger ZCRYPT_CEX6, 0, 0, 0, 0); 1813f71fee27SIngo Franzki if (rc) 1814f71fee27SIngo Franzki return rc; 181555d0a513SHarald Freudenberger 181655d0a513SHarald Freudenberger memset(buf, 0, is_xts ? 2 * keysize : keysize); 181755d0a513SHarald Freudenberger 181855d0a513SHarald Freudenberger /* simple try all apqns from the list */ 181955d0a513SHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 182055d0a513SHarald Freudenberger card = apqns[i] >> 16; 182155d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 182255d0a513SHarald Freudenberger rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); 182355d0a513SHarald Freudenberger if (rc == 0) 182455d0a513SHarald Freudenberger break; 182555d0a513SHarald Freudenberger } 182655d0a513SHarald Freudenberger if (rc) 182755d0a513SHarald Freudenberger return rc; 1828f71fee27SIngo Franzki 1829f71fee27SIngo Franzki if (is_xts) { 1830f71fee27SIngo Franzki keysize = CCACIPHERTOKENSIZE; 183155d0a513SHarald Freudenberger buf += CCACIPHERTOKENSIZE; 183255d0a513SHarald Freudenberger rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); 183355d0a513SHarald Freudenberger if (rc == 0) 1834f71fee27SIngo Franzki return 2 * CCACIPHERTOKENSIZE; 1835f71fee27SIngo Franzki } 1836f71fee27SIngo Franzki 1837f71fee27SIngo Franzki return CCACIPHERTOKENSIZE; 1838f71fee27SIngo Franzki } 1839f71fee27SIngo Franzki 1840f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_read(struct file *filp, 1841f71fee27SIngo Franzki struct kobject *kobj, 1842f71fee27SIngo Franzki struct bin_attribute *attr, 1843f71fee27SIngo Franzki char *buf, loff_t off, 1844f71fee27SIngo Franzki size_t count) 1845f71fee27SIngo Franzki { 1846f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, false, buf, 1847f71fee27SIngo Franzki off, count); 1848f71fee27SIngo Franzki } 1849f71fee27SIngo Franzki 1850f71fee27SIngo Franzki static ssize_t ccacipher_aes_192_read(struct file *filp, 1851f71fee27SIngo Franzki struct kobject *kobj, 1852f71fee27SIngo Franzki struct bin_attribute *attr, 1853f71fee27SIngo Franzki char *buf, loff_t off, 1854f71fee27SIngo Franzki size_t count) 1855f71fee27SIngo Franzki { 1856f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_192, false, buf, 1857f71fee27SIngo Franzki off, count); 1858f71fee27SIngo Franzki } 1859f71fee27SIngo Franzki 1860f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_read(struct file *filp, 1861f71fee27SIngo Franzki struct kobject *kobj, 1862f71fee27SIngo Franzki struct bin_attribute *attr, 1863f71fee27SIngo Franzki char *buf, loff_t off, 1864f71fee27SIngo Franzki size_t count) 1865f71fee27SIngo Franzki { 1866f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, false, buf, 1867f71fee27SIngo Franzki off, count); 1868f71fee27SIngo Franzki } 1869f71fee27SIngo Franzki 1870f71fee27SIngo Franzki static ssize_t ccacipher_aes_128_xts_read(struct file *filp, 1871f71fee27SIngo Franzki struct kobject *kobj, 1872f71fee27SIngo Franzki struct bin_attribute *attr, 1873f71fee27SIngo Franzki char *buf, loff_t off, 1874f71fee27SIngo Franzki size_t count) 1875f71fee27SIngo Franzki { 1876f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, true, buf, 1877f71fee27SIngo Franzki off, count); 1878f71fee27SIngo Franzki } 1879f71fee27SIngo Franzki 1880f71fee27SIngo Franzki static ssize_t ccacipher_aes_256_xts_read(struct file *filp, 1881f71fee27SIngo Franzki struct kobject *kobj, 1882f71fee27SIngo Franzki struct bin_attribute *attr, 1883f71fee27SIngo Franzki char *buf, loff_t off, 1884f71fee27SIngo Franzki size_t count) 1885f71fee27SIngo Franzki { 1886f71fee27SIngo Franzki return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, true, buf, 1887f71fee27SIngo Franzki off, count); 1888f71fee27SIngo Franzki } 1889f71fee27SIngo Franzki 1890f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128, CCACIPHERTOKENSIZE); 1891f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_192, CCACIPHERTOKENSIZE); 1892f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256, CCACIPHERTOKENSIZE); 1893f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_128_xts, 2 * CCACIPHERTOKENSIZE); 1894f71fee27SIngo Franzki static BIN_ATTR_RO(ccacipher_aes_256_xts, 2 * CCACIPHERTOKENSIZE); 1895f71fee27SIngo Franzki 1896f71fee27SIngo Franzki static struct bin_attribute *ccacipher_attrs[] = { 1897f71fee27SIngo Franzki &bin_attr_ccacipher_aes_128, 1898f71fee27SIngo Franzki &bin_attr_ccacipher_aes_192, 1899f71fee27SIngo Franzki &bin_attr_ccacipher_aes_256, 1900f71fee27SIngo Franzki &bin_attr_ccacipher_aes_128_xts, 1901f71fee27SIngo Franzki &bin_attr_ccacipher_aes_256_xts, 1902f71fee27SIngo Franzki NULL 1903f71fee27SIngo Franzki }; 1904f71fee27SIngo Franzki 1905f71fee27SIngo Franzki static struct attribute_group ccacipher_attr_group = { 1906f71fee27SIngo Franzki .name = "ccacipher", 1907f71fee27SIngo Franzki .bin_attrs = ccacipher_attrs, 1908f71fee27SIngo Franzki }; 1909f71fee27SIngo Franzki 191055d0a513SHarald Freudenberger /* 191155d0a513SHarald Freudenberger * Sysfs attribute read function for all ep11 aes key binary attributes. 191255d0a513SHarald Freudenberger * The implementation can not deal with partial reads, because a new random 191355d0a513SHarald Freudenberger * secure key blob is generated with each read. In case of partial reads 191455d0a513SHarald Freudenberger * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 191555d0a513SHarald Freudenberger * This function and the sysfs attributes using it provide EP11 key blobs 191655d0a513SHarald Freudenberger * padded to the upper limit of MAXEP11AESKEYBLOBSIZE which is currently 191755d0a513SHarald Freudenberger * 320 bytes. 191855d0a513SHarald Freudenberger */ 191955d0a513SHarald Freudenberger static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits, 192055d0a513SHarald Freudenberger bool is_xts, char *buf, loff_t off, 192155d0a513SHarald Freudenberger size_t count) 192255d0a513SHarald Freudenberger { 192355d0a513SHarald Freudenberger int i, rc, card, dom; 192455d0a513SHarald Freudenberger u32 nr_apqns, *apqns = NULL; 192555d0a513SHarald Freudenberger size_t keysize = MAXEP11AESKEYBLOBSIZE; 192655d0a513SHarald Freudenberger 192755d0a513SHarald Freudenberger if (off != 0 || count < MAXEP11AESKEYBLOBSIZE) 192855d0a513SHarald Freudenberger return -EINVAL; 192955d0a513SHarald Freudenberger if (is_xts) 193055d0a513SHarald Freudenberger if (count < 2 * MAXEP11AESKEYBLOBSIZE) 193155d0a513SHarald Freudenberger return -EINVAL; 193255d0a513SHarald Freudenberger 193355d0a513SHarald Freudenberger /* build a list of apqns able to generate an cipher key */ 193455d0a513SHarald Freudenberger rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, 193555d0a513SHarald Freudenberger ZCRYPT_CEX7, EP11_API_V, NULL); 193655d0a513SHarald Freudenberger if (rc) 193755d0a513SHarald Freudenberger return rc; 193855d0a513SHarald Freudenberger 193955d0a513SHarald Freudenberger memset(buf, 0, is_xts ? 2 * keysize : keysize); 194055d0a513SHarald Freudenberger 194155d0a513SHarald Freudenberger /* simple try all apqns from the list */ 194255d0a513SHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 194355d0a513SHarald Freudenberger card = apqns[i] >> 16; 194455d0a513SHarald Freudenberger dom = apqns[i] & 0xFFFF; 194555d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize); 194655d0a513SHarald Freudenberger if (rc == 0) 194755d0a513SHarald Freudenberger break; 194855d0a513SHarald Freudenberger } 194955d0a513SHarald Freudenberger if (rc) 195055d0a513SHarald Freudenberger return rc; 195155d0a513SHarald Freudenberger 195255d0a513SHarald Freudenberger if (is_xts) { 195355d0a513SHarald Freudenberger keysize = MAXEP11AESKEYBLOBSIZE; 195455d0a513SHarald Freudenberger buf += MAXEP11AESKEYBLOBSIZE; 195555d0a513SHarald Freudenberger rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize); 195655d0a513SHarald Freudenberger if (rc == 0) 195755d0a513SHarald Freudenberger return 2 * MAXEP11AESKEYBLOBSIZE; 195855d0a513SHarald Freudenberger } 195955d0a513SHarald Freudenberger 196055d0a513SHarald Freudenberger return MAXEP11AESKEYBLOBSIZE; 196155d0a513SHarald Freudenberger } 196255d0a513SHarald Freudenberger 196355d0a513SHarald Freudenberger static ssize_t ep11_aes_128_read(struct file *filp, 196455d0a513SHarald Freudenberger struct kobject *kobj, 196555d0a513SHarald Freudenberger struct bin_attribute *attr, 196655d0a513SHarald Freudenberger char *buf, loff_t off, 196755d0a513SHarald Freudenberger size_t count) 196855d0a513SHarald Freudenberger { 196955d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, false, buf, 197055d0a513SHarald Freudenberger off, count); 197155d0a513SHarald Freudenberger } 197255d0a513SHarald Freudenberger 197355d0a513SHarald Freudenberger static ssize_t ep11_aes_192_read(struct file *filp, 197455d0a513SHarald Freudenberger struct kobject *kobj, 197555d0a513SHarald Freudenberger struct bin_attribute *attr, 197655d0a513SHarald Freudenberger char *buf, loff_t off, 197755d0a513SHarald Freudenberger size_t count) 197855d0a513SHarald Freudenberger { 197955d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_192, false, buf, 198055d0a513SHarald Freudenberger off, count); 198155d0a513SHarald Freudenberger } 198255d0a513SHarald Freudenberger 198355d0a513SHarald Freudenberger static ssize_t ep11_aes_256_read(struct file *filp, 198455d0a513SHarald Freudenberger struct kobject *kobj, 198555d0a513SHarald Freudenberger struct bin_attribute *attr, 198655d0a513SHarald Freudenberger char *buf, loff_t off, 198755d0a513SHarald Freudenberger size_t count) 198855d0a513SHarald Freudenberger { 198955d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, false, buf, 199055d0a513SHarald Freudenberger off, count); 199155d0a513SHarald Freudenberger } 199255d0a513SHarald Freudenberger 199355d0a513SHarald Freudenberger static ssize_t ep11_aes_128_xts_read(struct file *filp, 199455d0a513SHarald Freudenberger struct kobject *kobj, 199555d0a513SHarald Freudenberger struct bin_attribute *attr, 199655d0a513SHarald Freudenberger char *buf, loff_t off, 199755d0a513SHarald Freudenberger size_t count) 199855d0a513SHarald Freudenberger { 199955d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, true, buf, 200055d0a513SHarald Freudenberger off, count); 200155d0a513SHarald Freudenberger } 200255d0a513SHarald Freudenberger 200355d0a513SHarald Freudenberger static ssize_t ep11_aes_256_xts_read(struct file *filp, 200455d0a513SHarald Freudenberger struct kobject *kobj, 200555d0a513SHarald Freudenberger struct bin_attribute *attr, 200655d0a513SHarald Freudenberger char *buf, loff_t off, 200755d0a513SHarald Freudenberger size_t count) 200855d0a513SHarald Freudenberger { 200955d0a513SHarald Freudenberger return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, true, buf, 201055d0a513SHarald Freudenberger off, count); 201155d0a513SHarald Freudenberger } 201255d0a513SHarald Freudenberger 201355d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128, MAXEP11AESKEYBLOBSIZE); 201455d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_192, MAXEP11AESKEYBLOBSIZE); 201555d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256, MAXEP11AESKEYBLOBSIZE); 201655d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_128_xts, 2 * MAXEP11AESKEYBLOBSIZE); 201755d0a513SHarald Freudenberger static BIN_ATTR_RO(ep11_aes_256_xts, 2 * MAXEP11AESKEYBLOBSIZE); 201855d0a513SHarald Freudenberger 201955d0a513SHarald Freudenberger static struct bin_attribute *ep11_attrs[] = { 202055d0a513SHarald Freudenberger &bin_attr_ep11_aes_128, 202155d0a513SHarald Freudenberger &bin_attr_ep11_aes_192, 202255d0a513SHarald Freudenberger &bin_attr_ep11_aes_256, 202355d0a513SHarald Freudenberger &bin_attr_ep11_aes_128_xts, 202455d0a513SHarald Freudenberger &bin_attr_ep11_aes_256_xts, 202555d0a513SHarald Freudenberger NULL 202655d0a513SHarald Freudenberger }; 202755d0a513SHarald Freudenberger 202855d0a513SHarald Freudenberger static struct attribute_group ep11_attr_group = { 202955d0a513SHarald Freudenberger .name = "ep11", 203055d0a513SHarald Freudenberger .bin_attrs = ep11_attrs, 203155d0a513SHarald Freudenberger }; 203255d0a513SHarald Freudenberger 2033d632c047SIngo Franzki static const struct attribute_group *pkey_attr_groups[] = { 2034d632c047SIngo Franzki &protkey_attr_group, 2035af504452SIngo Franzki &ccadata_attr_group, 2036f71fee27SIngo Franzki &ccacipher_attr_group, 203755d0a513SHarald Freudenberger &ep11_attr_group, 2038d632c047SIngo Franzki NULL, 2039d632c047SIngo Franzki }; 2040d632c047SIngo Franzki 2041e80d4af0SHarald Freudenberger static const struct file_operations pkey_fops = { 2042e80d4af0SHarald Freudenberger .owner = THIS_MODULE, 2043e80d4af0SHarald Freudenberger .open = nonseekable_open, 2044e80d4af0SHarald Freudenberger .llseek = no_llseek, 2045e80d4af0SHarald Freudenberger .unlocked_ioctl = pkey_unlocked_ioctl, 2046e80d4af0SHarald Freudenberger }; 2047e80d4af0SHarald Freudenberger 2048e80d4af0SHarald Freudenberger static struct miscdevice pkey_dev = { 2049e80d4af0SHarald Freudenberger .name = "pkey", 2050e80d4af0SHarald Freudenberger .minor = MISC_DYNAMIC_MINOR, 2051e80d4af0SHarald Freudenberger .mode = 0666, 2052e80d4af0SHarald Freudenberger .fops = &pkey_fops, 2053d632c047SIngo Franzki .groups = pkey_attr_groups, 2054e80d4af0SHarald Freudenberger }; 2055e80d4af0SHarald Freudenberger 2056e80d4af0SHarald Freudenberger /* 2057e80d4af0SHarald Freudenberger * Module init 2058e80d4af0SHarald Freudenberger */ 2059cb4ef3c2SHeiko Carstens static int __init pkey_init(void) 2060e80d4af0SHarald Freudenberger { 2061f822ad2cSHarald Freudenberger cpacf_mask_t kmc_functions; 2062e80d4af0SHarald Freudenberger 2063f822ad2cSHarald Freudenberger /* 2064f822ad2cSHarald Freudenberger * The pckmo instruction should be available - even if we don't 2065f822ad2cSHarald Freudenberger * actually invoke it. This instruction comes with MSA 3 which 2066f822ad2cSHarald Freudenberger * is also the minimum level for the kmc instructions which 2067f822ad2cSHarald Freudenberger * are able to work with protected keys. 2068f822ad2cSHarald Freudenberger */ 2069e80d4af0SHarald Freudenberger if (!cpacf_query(CPACF_PCKMO, &pckmo_functions)) 207058443b67SDavid Hildenbrand return -ENODEV; 2071e80d4af0SHarald Freudenberger 2072cb26b9ffSIngo Franzki /* check for kmc instructions available */ 2073cb26b9ffSIngo Franzki if (!cpacf_query(CPACF_KMC, &kmc_functions)) 207458443b67SDavid Hildenbrand return -ENODEV; 2075cb26b9ffSIngo Franzki if (!cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_128) || 2076cb26b9ffSIngo Franzki !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_192) || 2077cb26b9ffSIngo Franzki !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_256)) 207858443b67SDavid Hildenbrand return -ENODEV; 2079cb26b9ffSIngo Franzki 2080e80d4af0SHarald Freudenberger pkey_debug_init(); 2081e80d4af0SHarald Freudenberger 2082e80d4af0SHarald Freudenberger return misc_register(&pkey_dev); 2083e80d4af0SHarald Freudenberger } 2084e80d4af0SHarald Freudenberger 2085e80d4af0SHarald Freudenberger /* 2086e80d4af0SHarald Freudenberger * Module exit 2087e80d4af0SHarald Freudenberger */ 2088e80d4af0SHarald Freudenberger static void __exit pkey_exit(void) 2089e80d4af0SHarald Freudenberger { 2090e80d4af0SHarald Freudenberger misc_deregister(&pkey_dev); 2091e80d4af0SHarald Freudenberger pkey_debug_exit(); 2092e80d4af0SHarald Freudenberger } 2093e80d4af0SHarald Freudenberger 209463c19be0SIngo Franzki module_cpu_feature_match(MSA, pkey_init); 2095e80d4af0SHarald Freudenberger module_exit(pkey_exit); 2096