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" 28e80d4af0SHarald Freudenberger 29e80d4af0SHarald Freudenberger MODULE_LICENSE("GPL"); 30e80d4af0SHarald Freudenberger MODULE_AUTHOR("IBM Corporation"); 31e80d4af0SHarald Freudenberger MODULE_DESCRIPTION("s390 protected key interface"); 32e80d4af0SHarald Freudenberger 33*f2bbc96eSHarald Freudenberger #define KEYBLOBBUFSIZE 8192 /* key buffer size used for internal processing */ 34*f2bbc96eSHarald Freudenberger #define MAXAPQNSINLIST 64 /* max 64 apqns within a apqn list */ 35*f2bbc96eSHarald Freudenberger 36f822ad2cSHarald Freudenberger /* mask of available pckmo subfunctions, fetched once at module init */ 37f822ad2cSHarald Freudenberger static cpacf_mask_t pckmo_functions; 38f822ad2cSHarald Freudenberger 39e80d4af0SHarald Freudenberger /* 40e80d4af0SHarald Freudenberger * debug feature data and functions 41e80d4af0SHarald Freudenberger */ 42e80d4af0SHarald Freudenberger 43e80d4af0SHarald Freudenberger static debug_info_t *debug_info; 44e80d4af0SHarald Freudenberger 45e80d4af0SHarald Freudenberger #define DEBUG_DBG(...) debug_sprintf_event(debug_info, 6, ##__VA_ARGS__) 46e80d4af0SHarald Freudenberger #define DEBUG_INFO(...) debug_sprintf_event(debug_info, 5, ##__VA_ARGS__) 47e80d4af0SHarald Freudenberger #define DEBUG_WARN(...) debug_sprintf_event(debug_info, 4, ##__VA_ARGS__) 48e80d4af0SHarald Freudenberger #define DEBUG_ERR(...) debug_sprintf_event(debug_info, 3, ##__VA_ARGS__) 49e80d4af0SHarald Freudenberger 50e80d4af0SHarald Freudenberger static void __init pkey_debug_init(void) 51e80d4af0SHarald Freudenberger { 526b1f16baSHarald Freudenberger /* 5 arguments per dbf entry (including the format string ptr) */ 536b1f16baSHarald Freudenberger debug_info = debug_register("pkey", 1, 1, 5 * sizeof(long)); 54e80d4af0SHarald Freudenberger debug_register_view(debug_info, &debug_sprintf_view); 55e80d4af0SHarald Freudenberger debug_set_level(debug_info, 3); 56e80d4af0SHarald Freudenberger } 57e80d4af0SHarald Freudenberger 58e80d4af0SHarald Freudenberger static void __exit pkey_debug_exit(void) 59e80d4af0SHarald Freudenberger { 60e80d4af0SHarald Freudenberger debug_unregister(debug_info); 61e80d4af0SHarald Freudenberger } 62e80d4af0SHarald Freudenberger 630534bde7SIngo Franzki /* inside view of a protected key token (only type 0x00 version 0x01) */ 640534bde7SIngo Franzki struct protaeskeytoken { 650534bde7SIngo Franzki u8 type; /* 0x00 for PAES specific key tokens */ 660534bde7SIngo Franzki u8 res0[3]; 670534bde7SIngo Franzki u8 version; /* should be 0x01 for protected AES key token */ 680534bde7SIngo Franzki u8 res1[3]; 690534bde7SIngo Franzki u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ 700534bde7SIngo Franzki u32 len; /* bytes actually stored in protkey[] */ 710534bde7SIngo Franzki u8 protkey[MAXPROTKEYSIZE]; /* the protected key blob */ 720534bde7SIngo Franzki } __packed; 730534bde7SIngo Franzki 74e80d4af0SHarald Freudenberger /* 75e80d4af0SHarald Freudenberger * Create a protected key from a clear key value. 76e80d4af0SHarald Freudenberger */ 77183cb469SHarald Freudenberger static int pkey_clr2protkey(u32 keytype, 78e80d4af0SHarald Freudenberger const struct pkey_clrkey *clrkey, 79e80d4af0SHarald Freudenberger struct pkey_protkey *protkey) 80e80d4af0SHarald Freudenberger { 81e80d4af0SHarald Freudenberger long fc; 82e80d4af0SHarald Freudenberger int keysize; 83e80d4af0SHarald Freudenberger u8 paramblock[64]; 84e80d4af0SHarald Freudenberger 85e80d4af0SHarald Freudenberger switch (keytype) { 86e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 87e80d4af0SHarald Freudenberger keysize = 16; 88e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_128_KEY; 89e80d4af0SHarald Freudenberger break; 90e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 91e80d4af0SHarald Freudenberger keysize = 24; 92e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_192_KEY; 93e80d4af0SHarald Freudenberger break; 94e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 95e80d4af0SHarald Freudenberger keysize = 32; 96e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_256_KEY; 97e80d4af0SHarald Freudenberger break; 98e80d4af0SHarald Freudenberger default: 99ac2b96f3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %d\n", 100ac2b96f3SHarald Freudenberger __func__, keytype); 101e80d4af0SHarald Freudenberger return -EINVAL; 102e80d4af0SHarald Freudenberger } 103e80d4af0SHarald Freudenberger 104f822ad2cSHarald Freudenberger /* 105f822ad2cSHarald Freudenberger * Check if the needed pckmo subfunction is available. 106f822ad2cSHarald Freudenberger * These subfunctions can be enabled/disabled by customers 107f822ad2cSHarald Freudenberger * in the LPAR profile or may even change on the fly. 108f822ad2cSHarald Freudenberger */ 109f822ad2cSHarald Freudenberger if (!cpacf_test_func(&pckmo_functions, fc)) { 110f822ad2cSHarald Freudenberger DEBUG_ERR("%s pckmo functions not available\n", __func__); 11158443b67SDavid Hildenbrand return -ENODEV; 112f822ad2cSHarald Freudenberger } 113f822ad2cSHarald Freudenberger 114e80d4af0SHarald Freudenberger /* prepare param block */ 115e80d4af0SHarald Freudenberger memset(paramblock, 0, sizeof(paramblock)); 116e80d4af0SHarald Freudenberger memcpy(paramblock, clrkey->clrkey, keysize); 117e80d4af0SHarald Freudenberger 118e80d4af0SHarald Freudenberger /* call the pckmo instruction */ 119e80d4af0SHarald Freudenberger cpacf_pckmo(fc, paramblock); 120e80d4af0SHarald Freudenberger 121e80d4af0SHarald Freudenberger /* copy created protected key */ 122e80d4af0SHarald Freudenberger protkey->type = keytype; 123e80d4af0SHarald Freudenberger protkey->len = keysize + 32; 124e80d4af0SHarald Freudenberger memcpy(protkey->protkey, paramblock, keysize + 32); 125e80d4af0SHarald Freudenberger 126e80d4af0SHarald Freudenberger return 0; 127e80d4af0SHarald Freudenberger } 128e80d4af0SHarald Freudenberger 129e80d4af0SHarald Freudenberger /* 130e80d4af0SHarald Freudenberger * Find card and transform secure key into protected key. 131e80d4af0SHarald Freudenberger */ 132*f2bbc96eSHarald Freudenberger static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey) 133e80d4af0SHarald Freudenberger { 134e80d4af0SHarald Freudenberger int rc, verify; 135*f2bbc96eSHarald Freudenberger u16 cardnr, domain; 136*f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 137e80d4af0SHarald Freudenberger 138e80d4af0SHarald Freudenberger /* 139*f2bbc96eSHarald Freudenberger * The cca_xxx2protkey call may fail when a card has been 140e80d4af0SHarald Freudenberger * addressed where the master key was changed after last fetch 141efc598e6SHarald Freudenberger * of the mkvp into the cache. Try 3 times: First witout verify 142efc598e6SHarald Freudenberger * then with verify and last round with verify and old master 143efc598e6SHarald Freudenberger * key verification pattern match not ignored. 144e80d4af0SHarald Freudenberger */ 145efc598e6SHarald Freudenberger for (verify = 0; verify < 3; verify++) { 146*f2bbc96eSHarald Freudenberger rc = cca_findcard(key, &cardnr, &domain, verify); 147efc598e6SHarald Freudenberger if (rc < 0) 148e80d4af0SHarald Freudenberger continue; 149efc598e6SHarald Freudenberger if (rc > 0 && verify < 2) 150efc598e6SHarald Freudenberger continue; 151*f2bbc96eSHarald Freudenberger switch (hdr->version) { 152*f2bbc96eSHarald Freudenberger case TOKVER_CCA_AES: 153*f2bbc96eSHarald Freudenberger rc = cca_sec2protkey(cardnr, domain, 154*f2bbc96eSHarald Freudenberger key, pkey->protkey, 155*f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 156*f2bbc96eSHarald Freudenberger break; 157*f2bbc96eSHarald Freudenberger case TOKVER_CCA_VLSC: 158*f2bbc96eSHarald Freudenberger rc = cca_cipher2protkey(cardnr, domain, 159*f2bbc96eSHarald Freudenberger key, pkey->protkey, 160*f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 161*f2bbc96eSHarald Freudenberger break; 162*f2bbc96eSHarald Freudenberger default: 163*f2bbc96eSHarald Freudenberger return -EINVAL; 164*f2bbc96eSHarald Freudenberger } 165e80d4af0SHarald Freudenberger if (rc == 0) 166e80d4af0SHarald Freudenberger break; 167e80d4af0SHarald Freudenberger } 168e80d4af0SHarald Freudenberger 169e80d4af0SHarald Freudenberger if (rc) 170ac2b96f3SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 171e80d4af0SHarald Freudenberger 172e80d4af0SHarald Freudenberger return rc; 173e80d4af0SHarald Freudenberger } 174e80d4af0SHarald Freudenberger 175e80d4af0SHarald Freudenberger /* 176e61a6134SHarald Freudenberger * Verify key and give back some info about the key. 177e61a6134SHarald Freudenberger */ 178183cb469SHarald Freudenberger static int pkey_verifykey(const struct pkey_seckey *seckey, 179e61a6134SHarald Freudenberger u16 *pcardnr, u16 *pdomain, 180e61a6134SHarald Freudenberger u16 *pkeysize, u32 *pattributes) 181e61a6134SHarald Freudenberger { 182e61a6134SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; 183e61a6134SHarald Freudenberger u16 cardnr, domain; 184e61a6134SHarald Freudenberger int rc; 185e61a6134SHarald Freudenberger 186e61a6134SHarald Freudenberger /* check the secure key for valid AES secure key */ 187efc598e6SHarald Freudenberger rc = cca_check_secaeskeytoken(debug_info, 3, (u8 *) seckey, 0); 188e61a6134SHarald Freudenberger if (rc) 189e61a6134SHarald Freudenberger goto out; 190e61a6134SHarald Freudenberger if (pattributes) 191e61a6134SHarald Freudenberger *pattributes = PKEY_VERIFY_ATTR_AES; 192e61a6134SHarald Freudenberger if (pkeysize) 193e61a6134SHarald Freudenberger *pkeysize = t->bitsize; 194e61a6134SHarald Freudenberger 195e61a6134SHarald Freudenberger /* try to find a card which can handle this key */ 196efc598e6SHarald Freudenberger rc = cca_findcard(seckey->seckey, &cardnr, &domain, 1); 197efc598e6SHarald Freudenberger if (rc < 0) 198e61a6134SHarald Freudenberger goto out; 199e61a6134SHarald Freudenberger 200efc598e6SHarald Freudenberger if (rc > 0) { 201efc598e6SHarald Freudenberger /* key mkvp matches to old master key mkvp */ 202ac2b96f3SHarald Freudenberger DEBUG_DBG("%s secure key has old mkvp\n", __func__); 203e61a6134SHarald Freudenberger if (pattributes) 204e61a6134SHarald Freudenberger *pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP; 205efc598e6SHarald Freudenberger rc = 0; 206e61a6134SHarald Freudenberger } 207e61a6134SHarald Freudenberger 208e61a6134SHarald Freudenberger if (pcardnr) 209e61a6134SHarald Freudenberger *pcardnr = cardnr; 210e61a6134SHarald Freudenberger if (pdomain) 211e61a6134SHarald Freudenberger *pdomain = domain; 212e61a6134SHarald Freudenberger 213e61a6134SHarald Freudenberger out: 214ac2b96f3SHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 215e61a6134SHarald Freudenberger return rc; 216e61a6134SHarald Freudenberger } 217e61a6134SHarald Freudenberger 218e61a6134SHarald Freudenberger /* 219a45a5c7dSIngo Franzki * Generate a random protected key 220a45a5c7dSIngo Franzki */ 221183cb469SHarald Freudenberger static int pkey_genprotkey(u32 keytype, struct pkey_protkey *protkey) 222a45a5c7dSIngo Franzki { 223a45a5c7dSIngo Franzki struct pkey_clrkey clrkey; 224a45a5c7dSIngo Franzki int keysize; 225a45a5c7dSIngo Franzki int rc; 226a45a5c7dSIngo Franzki 227a45a5c7dSIngo Franzki switch (keytype) { 228a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_128: 229a45a5c7dSIngo Franzki keysize = 16; 230a45a5c7dSIngo Franzki break; 231a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_192: 232a45a5c7dSIngo Franzki keysize = 24; 233a45a5c7dSIngo Franzki break; 234a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_256: 235a45a5c7dSIngo Franzki keysize = 32; 236a45a5c7dSIngo Franzki break; 237a45a5c7dSIngo Franzki default: 238a45a5c7dSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 239a45a5c7dSIngo Franzki keytype); 240a45a5c7dSIngo Franzki return -EINVAL; 241a45a5c7dSIngo Franzki } 242a45a5c7dSIngo Franzki 243a45a5c7dSIngo Franzki /* generate a dummy random clear key */ 244a45a5c7dSIngo Franzki get_random_bytes(clrkey.clrkey, keysize); 245a45a5c7dSIngo Franzki 246a45a5c7dSIngo Franzki /* convert it to a dummy protected key */ 247a45a5c7dSIngo Franzki rc = pkey_clr2protkey(keytype, &clrkey, protkey); 248a45a5c7dSIngo Franzki if (rc) 249a45a5c7dSIngo Franzki return rc; 250a45a5c7dSIngo Franzki 251a45a5c7dSIngo Franzki /* replace the key part of the protected key with random bytes */ 252a45a5c7dSIngo Franzki get_random_bytes(protkey->protkey, keysize); 253a45a5c7dSIngo Franzki 254a45a5c7dSIngo Franzki return 0; 255a45a5c7dSIngo Franzki } 256a45a5c7dSIngo Franzki 257a45a5c7dSIngo Franzki /* 258cb26b9ffSIngo Franzki * Verify if a protected key is still valid 259cb26b9ffSIngo Franzki */ 260183cb469SHarald Freudenberger static int pkey_verifyprotkey(const struct pkey_protkey *protkey) 261cb26b9ffSIngo Franzki { 262cb26b9ffSIngo Franzki unsigned long fc; 263cb26b9ffSIngo Franzki struct { 264cb26b9ffSIngo Franzki u8 iv[AES_BLOCK_SIZE]; 265cb26b9ffSIngo Franzki u8 key[MAXPROTKEYSIZE]; 266cb26b9ffSIngo Franzki } param; 267cb26b9ffSIngo Franzki u8 null_msg[AES_BLOCK_SIZE]; 268cb26b9ffSIngo Franzki u8 dest_buf[AES_BLOCK_SIZE]; 269cb26b9ffSIngo Franzki unsigned int k; 270cb26b9ffSIngo Franzki 271cb26b9ffSIngo Franzki switch (protkey->type) { 272cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_128: 273cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_128; 274cb26b9ffSIngo Franzki break; 275cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_192: 276cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_192; 277cb26b9ffSIngo Franzki break; 278cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_256: 279cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_256; 280cb26b9ffSIngo Franzki break; 281cb26b9ffSIngo Franzki default: 282cb26b9ffSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 283cb26b9ffSIngo Franzki protkey->type); 284cb26b9ffSIngo Franzki return -EINVAL; 285cb26b9ffSIngo Franzki } 286cb26b9ffSIngo Franzki 287cb26b9ffSIngo Franzki memset(null_msg, 0, sizeof(null_msg)); 288cb26b9ffSIngo Franzki 289cb26b9ffSIngo Franzki memset(param.iv, 0, sizeof(param.iv)); 290cb26b9ffSIngo Franzki memcpy(param.key, protkey->protkey, sizeof(param.key)); 291cb26b9ffSIngo Franzki 292cb26b9ffSIngo Franzki k = cpacf_kmc(fc | CPACF_ENCRYPT, ¶m, null_msg, dest_buf, 293cb26b9ffSIngo Franzki sizeof(null_msg)); 294cb26b9ffSIngo Franzki if (k != sizeof(null_msg)) { 295cb26b9ffSIngo Franzki DEBUG_ERR("%s protected key is not valid\n", __func__); 296cb26b9ffSIngo Franzki return -EKEYREJECTED; 297cb26b9ffSIngo Franzki } 298cb26b9ffSIngo Franzki 299cb26b9ffSIngo Franzki return 0; 300cb26b9ffSIngo Franzki } 301cb26b9ffSIngo Franzki 302cb26b9ffSIngo Franzki /* 303fb1136d6SIngo Franzki * Transform a non-CCA key token into a protected key 304fb1136d6SIngo Franzki */ 305183cb469SHarald Freudenberger static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, 306fb1136d6SIngo Franzki struct pkey_protkey *protkey) 307fb1136d6SIngo Franzki { 308fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 309fb1136d6SIngo Franzki struct protaeskeytoken *t; 310fb1136d6SIngo Franzki 311fb1136d6SIngo Franzki switch (hdr->version) { 312fb1136d6SIngo Franzki case TOKVER_PROTECTED_KEY: 313fb1136d6SIngo Franzki if (keylen != sizeof(struct protaeskeytoken)) 314fb1136d6SIngo Franzki return -EINVAL; 315fb1136d6SIngo Franzki 316fb1136d6SIngo Franzki t = (struct protaeskeytoken *)key; 317fb1136d6SIngo Franzki protkey->len = t->len; 318fb1136d6SIngo Franzki protkey->type = t->keytype; 319fb1136d6SIngo Franzki memcpy(protkey->protkey, t->protkey, 320fb1136d6SIngo Franzki sizeof(protkey->protkey)); 321fb1136d6SIngo Franzki 322fb1136d6SIngo Franzki return pkey_verifyprotkey(protkey); 323fb1136d6SIngo Franzki default: 324fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n", 325fb1136d6SIngo Franzki __func__, hdr->version); 326fb1136d6SIngo Franzki return -EINVAL; 327fb1136d6SIngo Franzki } 328fb1136d6SIngo Franzki } 329fb1136d6SIngo Franzki 330fb1136d6SIngo Franzki /* 331fb1136d6SIngo Franzki * Transform a CCA internal key token into a protected key 332fb1136d6SIngo Franzki */ 333183cb469SHarald Freudenberger static int pkey_ccainttok2pkey(const u8 *key, u32 keylen, 334fb1136d6SIngo Franzki struct pkey_protkey *protkey) 335fb1136d6SIngo Franzki { 336fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 337fb1136d6SIngo Franzki 338fb1136d6SIngo Franzki switch (hdr->version) { 339fb1136d6SIngo Franzki case TOKVER_CCA_AES: 340fb1136d6SIngo Franzki if (keylen != sizeof(struct secaeskeytoken)) 341fb1136d6SIngo Franzki return -EINVAL; 342*f2bbc96eSHarald Freudenberger break; 343*f2bbc96eSHarald Freudenberger case TOKVER_CCA_VLSC: 344*f2bbc96eSHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 345*f2bbc96eSHarald Freudenberger return -EINVAL; 346*f2bbc96eSHarald Freudenberger break; 347fb1136d6SIngo Franzki default: 348fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported CCA internal token version %d\n", 349fb1136d6SIngo Franzki __func__, hdr->version); 350fb1136d6SIngo Franzki return -EINVAL; 351fb1136d6SIngo Franzki } 352*f2bbc96eSHarald Freudenberger 353*f2bbc96eSHarald Freudenberger return pkey_skey2pkey(key, protkey); 354fb1136d6SIngo Franzki } 355fb1136d6SIngo Franzki 356fb1136d6SIngo Franzki /* 357fb1136d6SIngo Franzki * Transform a key blob (of any type) into a protected key 358fb1136d6SIngo Franzki */ 359183cb469SHarald Freudenberger int pkey_keyblob2pkey(const u8 *key, u32 keylen, 360fb1136d6SIngo Franzki struct pkey_protkey *protkey) 361fb1136d6SIngo Franzki { 362*f2bbc96eSHarald Freudenberger int rc; 363fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 364fb1136d6SIngo Franzki 365*f2bbc96eSHarald Freudenberger if (keylen < sizeof(struct keytoken_header)) { 366*f2bbc96eSHarald Freudenberger DEBUG_ERR("%s invalid keylen %d\n", __func__, keylen); 367*f2bbc96eSHarald Freudenberger return -EINVAL; 368*f2bbc96eSHarald Freudenberger } 369*f2bbc96eSHarald Freudenberger 370*f2bbc96eSHarald Freudenberger switch (hdr->type) { 371*f2bbc96eSHarald Freudenberger case TOKTYPE_NON_CCA: 372*f2bbc96eSHarald Freudenberger rc = pkey_nonccatok2pkey(key, keylen, protkey); 373*f2bbc96eSHarald Freudenberger break; 374*f2bbc96eSHarald Freudenberger case TOKTYPE_CCA_INTERNAL: 375*f2bbc96eSHarald Freudenberger rc = pkey_ccainttok2pkey(key, keylen, protkey); 376*f2bbc96eSHarald Freudenberger break; 377*f2bbc96eSHarald Freudenberger default: 378*f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 379*f2bbc96eSHarald Freudenberger __func__, hdr->type); 380*f2bbc96eSHarald Freudenberger return -EINVAL; 381*f2bbc96eSHarald Freudenberger } 382*f2bbc96eSHarald Freudenberger 383*f2bbc96eSHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 384*f2bbc96eSHarald Freudenberger return rc; 385*f2bbc96eSHarald Freudenberger 386*f2bbc96eSHarald Freudenberger } 387*f2bbc96eSHarald Freudenberger EXPORT_SYMBOL(pkey_keyblob2pkey); 388*f2bbc96eSHarald Freudenberger 389*f2bbc96eSHarald Freudenberger static int pkey_genseckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 390*f2bbc96eSHarald Freudenberger enum pkey_key_type ktype, enum pkey_key_size ksize, 391*f2bbc96eSHarald Freudenberger u32 kflags, u8 *keybuf, size_t *keybufsize) 392*f2bbc96eSHarald Freudenberger { 393*f2bbc96eSHarald Freudenberger int i, card, dom, rc; 394*f2bbc96eSHarald Freudenberger 395*f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 396*f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 397*f2bbc96eSHarald Freudenberger return -EINVAL; 398*f2bbc96eSHarald Freudenberger 399*f2bbc96eSHarald Freudenberger /* check key type and size */ 400*f2bbc96eSHarald Freudenberger switch (ktype) { 401*f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_DATA: 402*f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 403*f2bbc96eSHarald Freudenberger if (*keybufsize < SECKEYBLOBSIZE) 404*f2bbc96eSHarald Freudenberger return -EINVAL; 405*f2bbc96eSHarald Freudenberger break; 406*f2bbc96eSHarald Freudenberger default: 407*f2bbc96eSHarald Freudenberger return -EINVAL; 408*f2bbc96eSHarald Freudenberger } 409*f2bbc96eSHarald Freudenberger switch (ksize) { 410*f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 411*f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 412*f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 413*f2bbc96eSHarald Freudenberger break; 414*f2bbc96eSHarald Freudenberger default: 415*f2bbc96eSHarald Freudenberger return -EINVAL; 416*f2bbc96eSHarald Freudenberger } 417*f2bbc96eSHarald Freudenberger 418*f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 419*f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 420*f2bbc96eSHarald Freudenberger card = apqns[i].card; 421*f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 422*f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_DATA) { 423*f2bbc96eSHarald Freudenberger rc = cca_genseckey(card, dom, ksize, keybuf); 424*f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 425*f2bbc96eSHarald Freudenberger } else /* TOKVER_CCA_VLSC */ 426*f2bbc96eSHarald Freudenberger rc = cca_gencipherkey(card, dom, ksize, kflags, 427*f2bbc96eSHarald Freudenberger keybuf, keybufsize); 428*f2bbc96eSHarald Freudenberger if (rc == 0) 429*f2bbc96eSHarald Freudenberger break; 430*f2bbc96eSHarald Freudenberger } 431*f2bbc96eSHarald Freudenberger 432*f2bbc96eSHarald Freudenberger return rc; 433*f2bbc96eSHarald Freudenberger } 434*f2bbc96eSHarald Freudenberger 435*f2bbc96eSHarald Freudenberger static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns, 436*f2bbc96eSHarald Freudenberger enum pkey_key_type ktype, enum pkey_key_size ksize, 437*f2bbc96eSHarald Freudenberger u32 kflags, const u8 *clrkey, 438*f2bbc96eSHarald Freudenberger u8 *keybuf, size_t *keybufsize) 439*f2bbc96eSHarald Freudenberger { 440*f2bbc96eSHarald Freudenberger int i, card, dom, rc; 441*f2bbc96eSHarald Freudenberger 442*f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 443*f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 444*f2bbc96eSHarald Freudenberger return -EINVAL; 445*f2bbc96eSHarald Freudenberger 446*f2bbc96eSHarald Freudenberger /* check key type and size */ 447*f2bbc96eSHarald Freudenberger switch (ktype) { 448*f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_DATA: 449*f2bbc96eSHarald Freudenberger case PKEY_TYPE_CCA_CIPHER: 450*f2bbc96eSHarald Freudenberger if (*keybufsize < SECKEYBLOBSIZE) 451*f2bbc96eSHarald Freudenberger return -EINVAL; 452*f2bbc96eSHarald Freudenberger break; 453*f2bbc96eSHarald Freudenberger default: 454*f2bbc96eSHarald Freudenberger return -EINVAL; 455*f2bbc96eSHarald Freudenberger } 456*f2bbc96eSHarald Freudenberger switch (ksize) { 457*f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_128: 458*f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_192: 459*f2bbc96eSHarald Freudenberger case PKEY_SIZE_AES_256: 460*f2bbc96eSHarald Freudenberger break; 461*f2bbc96eSHarald Freudenberger default: 462*f2bbc96eSHarald Freudenberger return -EINVAL; 463*f2bbc96eSHarald Freudenberger } 464*f2bbc96eSHarald Freudenberger 465*f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 466*f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 467*f2bbc96eSHarald Freudenberger card = apqns[i].card; 468*f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 469*f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_DATA) { 470*f2bbc96eSHarald Freudenberger rc = cca_clr2seckey(card, dom, ksize, 471*f2bbc96eSHarald Freudenberger clrkey, keybuf); 472*f2bbc96eSHarald Freudenberger *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); 473*f2bbc96eSHarald Freudenberger } else /* TOKVER_CCA_VLSC */ 474*f2bbc96eSHarald Freudenberger rc = cca_clr2cipherkey(card, dom, ksize, kflags, 475*f2bbc96eSHarald Freudenberger clrkey, keybuf, keybufsize); 476*f2bbc96eSHarald Freudenberger if (rc == 0) 477*f2bbc96eSHarald Freudenberger break; 478*f2bbc96eSHarald Freudenberger } 479*f2bbc96eSHarald Freudenberger 480*f2bbc96eSHarald Freudenberger return rc; 481*f2bbc96eSHarald Freudenberger } 482*f2bbc96eSHarald Freudenberger 483*f2bbc96eSHarald Freudenberger static int pkey_verifykey2(const u8 *key, size_t keylen, 484*f2bbc96eSHarald Freudenberger u16 *cardnr, u16 *domain, 485*f2bbc96eSHarald Freudenberger enum pkey_key_type *ktype, 486*f2bbc96eSHarald Freudenberger enum pkey_key_size *ksize, u32 *flags) 487*f2bbc96eSHarald Freudenberger { 488*f2bbc96eSHarald Freudenberger int rc; 489*f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 490*f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 491*f2bbc96eSHarald Freudenberger 492*f2bbc96eSHarald Freudenberger if (keylen < sizeof(struct keytoken_header) || 493*f2bbc96eSHarald Freudenberger hdr->type != TOKTYPE_CCA_INTERNAL) 494*f2bbc96eSHarald Freudenberger return -EINVAL; 495*f2bbc96eSHarald Freudenberger 496*f2bbc96eSHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 497*f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 498*f2bbc96eSHarald Freudenberger 499*f2bbc96eSHarald Freudenberger rc = cca_check_secaeskeytoken(debug_info, 3, key, 0); 500*f2bbc96eSHarald Freudenberger if (rc) 501*f2bbc96eSHarald Freudenberger goto out; 502*f2bbc96eSHarald Freudenberger if (ktype) 503*f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_DATA; 504*f2bbc96eSHarald Freudenberger if (ksize) 505*f2bbc96eSHarald Freudenberger *ksize = (enum pkey_key_size) t->bitsize; 506*f2bbc96eSHarald Freudenberger 507*f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 508*f2bbc96eSHarald Freudenberger ZCRYPT_CEX3C, t->mkvp, 0, 1); 509*f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 510*f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 511*f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 512*f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 513*f2bbc96eSHarald Freudenberger *cardnr, *domain, 514*f2bbc96eSHarald Freudenberger ZCRYPT_CEX3C, 0, t->mkvp, 1); 515*f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 516*f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 517*f2bbc96eSHarald Freudenberger } 518*f2bbc96eSHarald Freudenberger if (rc) 519*f2bbc96eSHarald Freudenberger goto out; 520*f2bbc96eSHarald Freudenberger 521*f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 522*f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 523*f2bbc96eSHarald Freudenberger 524*f2bbc96eSHarald Freudenberger } else if (hdr->version == TOKVER_CCA_VLSC) { 525*f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 526*f2bbc96eSHarald Freudenberger 527*f2bbc96eSHarald Freudenberger rc = cca_check_secaescipherkey(debug_info, 3, key, 0, 1); 528*f2bbc96eSHarald Freudenberger if (rc) 529*f2bbc96eSHarald Freudenberger goto out; 530*f2bbc96eSHarald Freudenberger if (ktype) 531*f2bbc96eSHarald Freudenberger *ktype = PKEY_TYPE_CCA_CIPHER; 532*f2bbc96eSHarald Freudenberger if (ksize) { 533*f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_UNKNOWN; 534*f2bbc96eSHarald Freudenberger if (!t->plfver && t->wpllen == 512) 535*f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_128; 536*f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 576) 537*f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_192; 538*f2bbc96eSHarald Freudenberger else if (!t->plfver && t->wpllen == 640) 539*f2bbc96eSHarald Freudenberger *ksize = PKEY_SIZE_AES_256; 540*f2bbc96eSHarald Freudenberger } 541*f2bbc96eSHarald Freudenberger 542*f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, 543*f2bbc96eSHarald Freudenberger ZCRYPT_CEX6, t->mkvp0, 0, 1); 544*f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 545*f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_CUR_MKVP; 546*f2bbc96eSHarald Freudenberger if (rc == -ENODEV) { 547*f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 548*f2bbc96eSHarald Freudenberger *cardnr, *domain, 549*f2bbc96eSHarald Freudenberger ZCRYPT_CEX6, 0, t->mkvp0, 1); 550*f2bbc96eSHarald Freudenberger if (rc == 0 && flags) 551*f2bbc96eSHarald Freudenberger *flags = PKEY_FLAGS_MATCH_ALT_MKVP; 552*f2bbc96eSHarald Freudenberger } 553*f2bbc96eSHarald Freudenberger if (rc) 554*f2bbc96eSHarald Freudenberger goto out; 555*f2bbc96eSHarald Freudenberger 556*f2bbc96eSHarald Freudenberger *cardnr = ((struct pkey_apqn *)_apqns)->card; 557*f2bbc96eSHarald Freudenberger *domain = ((struct pkey_apqn *)_apqns)->domain; 558*f2bbc96eSHarald Freudenberger 559*f2bbc96eSHarald Freudenberger } else 560*f2bbc96eSHarald Freudenberger rc = -EINVAL; 561*f2bbc96eSHarald Freudenberger 562*f2bbc96eSHarald Freudenberger out: 563*f2bbc96eSHarald Freudenberger kfree(_apqns); 564*f2bbc96eSHarald Freudenberger return rc; 565*f2bbc96eSHarald Freudenberger } 566*f2bbc96eSHarald Freudenberger 567*f2bbc96eSHarald Freudenberger static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, 568*f2bbc96eSHarald Freudenberger const u8 *key, size_t keylen, 569*f2bbc96eSHarald Freudenberger struct pkey_protkey *pkey) 570*f2bbc96eSHarald Freudenberger { 571*f2bbc96eSHarald Freudenberger int i, card, dom, rc; 572*f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 573*f2bbc96eSHarald Freudenberger 574*f2bbc96eSHarald Freudenberger /* check for at least one apqn given */ 575*f2bbc96eSHarald Freudenberger if (!apqns || !nr_apqns) 576*f2bbc96eSHarald Freudenberger return -EINVAL; 577*f2bbc96eSHarald Freudenberger 578fb1136d6SIngo Franzki if (keylen < sizeof(struct keytoken_header)) 579fb1136d6SIngo Franzki return -EINVAL; 580fb1136d6SIngo Franzki 581fb1136d6SIngo Franzki switch (hdr->type) { 582fb1136d6SIngo Franzki case TOKTYPE_NON_CCA: 583*f2bbc96eSHarald Freudenberger return pkey_nonccatok2pkey(key, keylen, pkey); 584fb1136d6SIngo Franzki case TOKTYPE_CCA_INTERNAL: 585*f2bbc96eSHarald Freudenberger switch (hdr->version) { 586*f2bbc96eSHarald Freudenberger case TOKVER_CCA_AES: 587*f2bbc96eSHarald Freudenberger if (keylen != sizeof(struct secaeskeytoken)) 588*f2bbc96eSHarald Freudenberger return -EINVAL; 589*f2bbc96eSHarald Freudenberger if (cca_check_secaeskeytoken(debug_info, 3, key, 0)) 590*f2bbc96eSHarald Freudenberger return -EINVAL; 591*f2bbc96eSHarald Freudenberger break; 592*f2bbc96eSHarald Freudenberger case TOKVER_CCA_VLSC: 593*f2bbc96eSHarald Freudenberger if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) 594*f2bbc96eSHarald Freudenberger return -EINVAL; 595*f2bbc96eSHarald Freudenberger if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1)) 596*f2bbc96eSHarald Freudenberger return -EINVAL; 597*f2bbc96eSHarald Freudenberger break; 598fb1136d6SIngo Franzki default: 599*f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown CCA internal token version %d\n", 600*f2bbc96eSHarald Freudenberger __func__, hdr->version); 601fb1136d6SIngo Franzki return -EINVAL; 602fb1136d6SIngo Franzki } 603*f2bbc96eSHarald Freudenberger break; 604*f2bbc96eSHarald Freudenberger default: 605*f2bbc96eSHarald Freudenberger DEBUG_ERR("%s unknown/unsupported blob type %d\n", 606*f2bbc96eSHarald Freudenberger __func__, hdr->type); 607*f2bbc96eSHarald Freudenberger return -EINVAL; 608fb1136d6SIngo Franzki } 609*f2bbc96eSHarald Freudenberger 610*f2bbc96eSHarald Freudenberger /* simple try all apqns from the list */ 611*f2bbc96eSHarald Freudenberger for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { 612*f2bbc96eSHarald Freudenberger card = apqns[i].card; 613*f2bbc96eSHarald Freudenberger dom = apqns[i].domain; 614*f2bbc96eSHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) 615*f2bbc96eSHarald Freudenberger rc = cca_sec2protkey(card, dom, key, pkey->protkey, 616*f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 617*f2bbc96eSHarald Freudenberger else /* TOKVER_CCA_VLSC */ 618*f2bbc96eSHarald Freudenberger rc = cca_cipher2protkey(card, dom, key, pkey->protkey, 619*f2bbc96eSHarald Freudenberger &pkey->len, &pkey->type); 620*f2bbc96eSHarald Freudenberger if (rc == 0) 621*f2bbc96eSHarald Freudenberger break; 622*f2bbc96eSHarald Freudenberger } 623*f2bbc96eSHarald Freudenberger 624*f2bbc96eSHarald Freudenberger return rc; 625*f2bbc96eSHarald Freudenberger } 626*f2bbc96eSHarald Freudenberger 627*f2bbc96eSHarald Freudenberger static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, 628*f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 629*f2bbc96eSHarald Freudenberger { 630*f2bbc96eSHarald Freudenberger int rc = EINVAL; 631*f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 632*f2bbc96eSHarald Freudenberger struct keytoken_header *hdr = (struct keytoken_header *)key; 633*f2bbc96eSHarald Freudenberger 634*f2bbc96eSHarald Freudenberger if (keylen < sizeof(struct keytoken_header) || 635*f2bbc96eSHarald Freudenberger hdr->type != TOKTYPE_CCA_INTERNAL || 636*f2bbc96eSHarald Freudenberger flags == 0) 637*f2bbc96eSHarald Freudenberger return -EINVAL; 638*f2bbc96eSHarald Freudenberger 639*f2bbc96eSHarald Freudenberger if (hdr->version == TOKVER_CCA_AES || hdr->version == TOKVER_CCA_VLSC) { 640*f2bbc96eSHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 641*f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 642*f2bbc96eSHarald Freudenberger 643*f2bbc96eSHarald Freudenberger if (hdr->version == TOKVER_CCA_AES) { 644*f2bbc96eSHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *)key; 645*f2bbc96eSHarald Freudenberger 646*f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 647*f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp; 648*f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 649*f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp; 650*f2bbc96eSHarald Freudenberger } else { 651*f2bbc96eSHarald Freudenberger struct cipherkeytoken *t = (struct cipherkeytoken *)key; 652*f2bbc96eSHarald Freudenberger 653*f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 654*f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 655*f2bbc96eSHarald Freudenberger cur_mkvp = t->mkvp0; 656*f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 657*f2bbc96eSHarald Freudenberger old_mkvp = t->mkvp0; 658*f2bbc96eSHarald Freudenberger } 659*f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 660*f2bbc96eSHarald Freudenberger minhwtype, cur_mkvp, old_mkvp, 1); 661*f2bbc96eSHarald Freudenberger if (rc) 662*f2bbc96eSHarald Freudenberger goto out; 663*f2bbc96eSHarald Freudenberger if (apqns) { 664*f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 665*f2bbc96eSHarald Freudenberger rc = -ENOSPC; 666*f2bbc96eSHarald Freudenberger else 667*f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 668*f2bbc96eSHarald Freudenberger } 669*f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 670*f2bbc96eSHarald Freudenberger } 671*f2bbc96eSHarald Freudenberger 672*f2bbc96eSHarald Freudenberger out: 673*f2bbc96eSHarald Freudenberger kfree(_apqns); 674*f2bbc96eSHarald Freudenberger return rc; 675*f2bbc96eSHarald Freudenberger } 676*f2bbc96eSHarald Freudenberger 677*f2bbc96eSHarald Freudenberger static int pkey_apqns4keytype(enum pkey_key_type ktype, 678*f2bbc96eSHarald Freudenberger u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, 679*f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns, size_t *nr_apqns) 680*f2bbc96eSHarald Freudenberger { 681*f2bbc96eSHarald Freudenberger int rc = -EINVAL; 682*f2bbc96eSHarald Freudenberger u32 _nr_apqns, *_apqns = NULL; 683*f2bbc96eSHarald Freudenberger 684*f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) { 685*f2bbc96eSHarald Freudenberger u64 cur_mkvp = 0, old_mkvp = 0; 686*f2bbc96eSHarald Freudenberger int minhwtype = ZCRYPT_CEX3C; 687*f2bbc96eSHarald Freudenberger 688*f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) 689*f2bbc96eSHarald Freudenberger cur_mkvp = *((u64 *) cur_mkvp); 690*f2bbc96eSHarald Freudenberger if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) 691*f2bbc96eSHarald Freudenberger old_mkvp = *((u64 *) alt_mkvp); 692*f2bbc96eSHarald Freudenberger if (ktype == PKEY_TYPE_CCA_CIPHER) 693*f2bbc96eSHarald Freudenberger minhwtype = ZCRYPT_CEX6; 694*f2bbc96eSHarald Freudenberger rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, 695*f2bbc96eSHarald Freudenberger minhwtype, cur_mkvp, old_mkvp, 1); 696*f2bbc96eSHarald Freudenberger if (rc) 697*f2bbc96eSHarald Freudenberger goto out; 698*f2bbc96eSHarald Freudenberger if (apqns) { 699*f2bbc96eSHarald Freudenberger if (*nr_apqns < _nr_apqns) 700*f2bbc96eSHarald Freudenberger rc = -ENOSPC; 701*f2bbc96eSHarald Freudenberger else 702*f2bbc96eSHarald Freudenberger memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); 703*f2bbc96eSHarald Freudenberger } 704*f2bbc96eSHarald Freudenberger *nr_apqns = _nr_apqns; 705*f2bbc96eSHarald Freudenberger } 706*f2bbc96eSHarald Freudenberger 707*f2bbc96eSHarald Freudenberger out: 708*f2bbc96eSHarald Freudenberger kfree(_apqns); 709*f2bbc96eSHarald Freudenberger return rc; 710*f2bbc96eSHarald Freudenberger } 711fb1136d6SIngo Franzki 712fb1136d6SIngo Franzki /* 713e80d4af0SHarald Freudenberger * File io functions 714e80d4af0SHarald Freudenberger */ 715e80d4af0SHarald Freudenberger 716*f2bbc96eSHarald Freudenberger static void *_copy_key_from_user(void __user *ukey, size_t keylen) 717*f2bbc96eSHarald Freudenberger { 718*f2bbc96eSHarald Freudenberger void *kkey; 719*f2bbc96eSHarald Freudenberger 720*f2bbc96eSHarald Freudenberger if (!ukey || keylen < MINKEYBLOBSIZE || keylen > KEYBLOBBUFSIZE) 721*f2bbc96eSHarald Freudenberger return ERR_PTR(-EINVAL); 722*f2bbc96eSHarald Freudenberger kkey = kmalloc(keylen, GFP_KERNEL); 723*f2bbc96eSHarald Freudenberger if (!kkey) 724*f2bbc96eSHarald Freudenberger return ERR_PTR(-ENOMEM); 725*f2bbc96eSHarald Freudenberger if (copy_from_user(kkey, ukey, keylen)) { 726*f2bbc96eSHarald Freudenberger kfree(kkey); 727*f2bbc96eSHarald Freudenberger return ERR_PTR(-EFAULT); 728*f2bbc96eSHarald Freudenberger } 729*f2bbc96eSHarald Freudenberger 730*f2bbc96eSHarald Freudenberger return kkey; 731*f2bbc96eSHarald Freudenberger } 732*f2bbc96eSHarald Freudenberger 733*f2bbc96eSHarald Freudenberger static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns) 734*f2bbc96eSHarald Freudenberger { 735*f2bbc96eSHarald Freudenberger void *kapqns = NULL; 736*f2bbc96eSHarald Freudenberger size_t nbytes; 737*f2bbc96eSHarald Freudenberger 738*f2bbc96eSHarald Freudenberger if (uapqns && nr_apqns > 0) { 739*f2bbc96eSHarald Freudenberger nbytes = nr_apqns * sizeof(struct pkey_apqn); 740*f2bbc96eSHarald Freudenberger kapqns = kmalloc(nbytes, GFP_KERNEL); 741*f2bbc96eSHarald Freudenberger if (!kapqns) 742*f2bbc96eSHarald Freudenberger return ERR_PTR(-ENOMEM); 743*f2bbc96eSHarald Freudenberger if (copy_from_user(kapqns, uapqns, nbytes)) 744*f2bbc96eSHarald Freudenberger return ERR_PTR(-EFAULT); 745*f2bbc96eSHarald Freudenberger } 746*f2bbc96eSHarald Freudenberger 747*f2bbc96eSHarald Freudenberger return kapqns; 748*f2bbc96eSHarald Freudenberger } 749*f2bbc96eSHarald Freudenberger 750e80d4af0SHarald Freudenberger static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, 751e80d4af0SHarald Freudenberger unsigned long arg) 752e80d4af0SHarald Freudenberger { 753e80d4af0SHarald Freudenberger int rc; 754e80d4af0SHarald Freudenberger 755e80d4af0SHarald Freudenberger switch (cmd) { 756e80d4af0SHarald Freudenberger case PKEY_GENSECK: { 757e80d4af0SHarald Freudenberger struct pkey_genseck __user *ugs = (void __user *) arg; 758e80d4af0SHarald Freudenberger struct pkey_genseck kgs; 759e80d4af0SHarald Freudenberger 760e80d4af0SHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 761e80d4af0SHarald Freudenberger return -EFAULT; 762efc598e6SHarald Freudenberger rc = cca_genseckey(kgs.cardnr, kgs.domain, 763efc598e6SHarald Freudenberger kgs.keytype, kgs.seckey.seckey); 764efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_genseckey()=%d\n", __func__, rc); 765e80d4af0SHarald Freudenberger if (rc) 766e80d4af0SHarald Freudenberger break; 767e80d4af0SHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 768e80d4af0SHarald Freudenberger return -EFAULT; 769e80d4af0SHarald Freudenberger break; 770e80d4af0SHarald Freudenberger } 771e80d4af0SHarald Freudenberger case PKEY_CLR2SECK: { 772e80d4af0SHarald Freudenberger struct pkey_clr2seck __user *ucs = (void __user *) arg; 773e80d4af0SHarald Freudenberger struct pkey_clr2seck kcs; 774e80d4af0SHarald Freudenberger 775e80d4af0SHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 776e80d4af0SHarald Freudenberger return -EFAULT; 777efc598e6SHarald Freudenberger rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, 778efc598e6SHarald Freudenberger kcs.clrkey.clrkey, kcs.seckey.seckey); 779efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_clr2seckey()=%d\n", __func__, rc); 780e80d4af0SHarald Freudenberger if (rc) 781e80d4af0SHarald Freudenberger break; 782e80d4af0SHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 783e80d4af0SHarald Freudenberger return -EFAULT; 784e80d4af0SHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 785e80d4af0SHarald Freudenberger break; 786e80d4af0SHarald Freudenberger } 787e80d4af0SHarald Freudenberger case PKEY_SEC2PROTK: { 788e80d4af0SHarald Freudenberger struct pkey_sec2protk __user *usp = (void __user *) arg; 789e80d4af0SHarald Freudenberger struct pkey_sec2protk ksp; 790e80d4af0SHarald Freudenberger 791e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 792e80d4af0SHarald Freudenberger return -EFAULT; 793efc598e6SHarald Freudenberger rc = cca_sec2protkey(ksp.cardnr, ksp.domain, 794efc598e6SHarald Freudenberger ksp.seckey.seckey, ksp.protkey.protkey, 795efc598e6SHarald Freudenberger NULL, &ksp.protkey.type); 796efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_sec2protkey()=%d\n", __func__, rc); 797e80d4af0SHarald Freudenberger if (rc) 798e80d4af0SHarald Freudenberger break; 799e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 800e80d4af0SHarald Freudenberger return -EFAULT; 801e80d4af0SHarald Freudenberger break; 802e80d4af0SHarald Freudenberger } 803e80d4af0SHarald Freudenberger case PKEY_CLR2PROTK: { 804e80d4af0SHarald Freudenberger struct pkey_clr2protk __user *ucp = (void __user *) arg; 805e80d4af0SHarald Freudenberger struct pkey_clr2protk kcp; 806e80d4af0SHarald Freudenberger 807e80d4af0SHarald Freudenberger if (copy_from_user(&kcp, ucp, sizeof(kcp))) 808e80d4af0SHarald Freudenberger return -EFAULT; 809e80d4af0SHarald Freudenberger rc = pkey_clr2protkey(kcp.keytype, 810e80d4af0SHarald Freudenberger &kcp.clrkey, &kcp.protkey); 811ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc); 812e80d4af0SHarald Freudenberger if (rc) 813e80d4af0SHarald Freudenberger break; 814e80d4af0SHarald Freudenberger if (copy_to_user(ucp, &kcp, sizeof(kcp))) 815e80d4af0SHarald Freudenberger return -EFAULT; 816e80d4af0SHarald Freudenberger memzero_explicit(&kcp, sizeof(kcp)); 817e80d4af0SHarald Freudenberger break; 818e80d4af0SHarald Freudenberger } 819e80d4af0SHarald Freudenberger case PKEY_FINDCARD: { 820e80d4af0SHarald Freudenberger struct pkey_findcard __user *ufc = (void __user *) arg; 821e80d4af0SHarald Freudenberger struct pkey_findcard kfc; 822e80d4af0SHarald Freudenberger 823e80d4af0SHarald Freudenberger if (copy_from_user(&kfc, ufc, sizeof(kfc))) 824e80d4af0SHarald Freudenberger return -EFAULT; 825efc598e6SHarald Freudenberger rc = cca_findcard(kfc.seckey.seckey, 826e80d4af0SHarald Freudenberger &kfc.cardnr, &kfc.domain, 1); 827efc598e6SHarald Freudenberger DEBUG_DBG("%s cca_findcard()=%d\n", __func__, rc); 828efc598e6SHarald Freudenberger if (rc < 0) 829e80d4af0SHarald Freudenberger break; 830e80d4af0SHarald Freudenberger if (copy_to_user(ufc, &kfc, sizeof(kfc))) 831e80d4af0SHarald Freudenberger return -EFAULT; 832e80d4af0SHarald Freudenberger break; 833e80d4af0SHarald Freudenberger } 834e80d4af0SHarald Freudenberger case PKEY_SKEY2PKEY: { 835e80d4af0SHarald Freudenberger struct pkey_skey2pkey __user *usp = (void __user *) arg; 836e80d4af0SHarald Freudenberger struct pkey_skey2pkey ksp; 837e80d4af0SHarald Freudenberger 838e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 839e80d4af0SHarald Freudenberger return -EFAULT; 840*f2bbc96eSHarald Freudenberger rc = pkey_skey2pkey(ksp.seckey.seckey, &ksp.protkey); 841ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc); 842e80d4af0SHarald Freudenberger if (rc) 843e80d4af0SHarald Freudenberger break; 844e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 845e80d4af0SHarald Freudenberger return -EFAULT; 846e80d4af0SHarald Freudenberger break; 847e80d4af0SHarald Freudenberger } 848e61a6134SHarald Freudenberger case PKEY_VERIFYKEY: { 849e61a6134SHarald Freudenberger struct pkey_verifykey __user *uvk = (void __user *) arg; 850e61a6134SHarald Freudenberger struct pkey_verifykey kvk; 851e61a6134SHarald Freudenberger 852e61a6134SHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 853e61a6134SHarald Freudenberger return -EFAULT; 854e61a6134SHarald Freudenberger rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain, 855e61a6134SHarald Freudenberger &kvk.keysize, &kvk.attributes); 856ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_verifykey()=%d\n", __func__, rc); 857e61a6134SHarald Freudenberger if (rc) 858e61a6134SHarald Freudenberger break; 859e61a6134SHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 860e61a6134SHarald Freudenberger return -EFAULT; 861e61a6134SHarald Freudenberger break; 862e61a6134SHarald Freudenberger } 863a45a5c7dSIngo Franzki case PKEY_GENPROTK: { 864a45a5c7dSIngo Franzki struct pkey_genprotk __user *ugp = (void __user *) arg; 865a45a5c7dSIngo Franzki struct pkey_genprotk kgp; 866a45a5c7dSIngo Franzki 867a45a5c7dSIngo Franzki if (copy_from_user(&kgp, ugp, sizeof(kgp))) 868a45a5c7dSIngo Franzki return -EFAULT; 869a45a5c7dSIngo Franzki rc = pkey_genprotkey(kgp.keytype, &kgp.protkey); 870a45a5c7dSIngo Franzki DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc); 871a45a5c7dSIngo Franzki if (rc) 872a45a5c7dSIngo Franzki break; 873a45a5c7dSIngo Franzki if (copy_to_user(ugp, &kgp, sizeof(kgp))) 874a45a5c7dSIngo Franzki return -EFAULT; 875a45a5c7dSIngo Franzki break; 876a45a5c7dSIngo Franzki } 877cb26b9ffSIngo Franzki case PKEY_VERIFYPROTK: { 878cb26b9ffSIngo Franzki struct pkey_verifyprotk __user *uvp = (void __user *) arg; 879cb26b9ffSIngo Franzki struct pkey_verifyprotk kvp; 880cb26b9ffSIngo Franzki 881cb26b9ffSIngo Franzki if (copy_from_user(&kvp, uvp, sizeof(kvp))) 882cb26b9ffSIngo Franzki return -EFAULT; 883cb26b9ffSIngo Franzki rc = pkey_verifyprotkey(&kvp.protkey); 884cb26b9ffSIngo Franzki DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc); 885cb26b9ffSIngo Franzki break; 886cb26b9ffSIngo Franzki } 887fb1136d6SIngo Franzki case PKEY_KBLOB2PROTK: { 888fb1136d6SIngo Franzki struct pkey_kblob2pkey __user *utp = (void __user *) arg; 889fb1136d6SIngo Franzki struct pkey_kblob2pkey ktp; 890183cb469SHarald Freudenberger u8 *kkey; 891fb1136d6SIngo Franzki 892fb1136d6SIngo Franzki if (copy_from_user(&ktp, utp, sizeof(ktp))) 893fb1136d6SIngo Franzki return -EFAULT; 894*f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 895*f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 896*f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 897fb1136d6SIngo Franzki rc = pkey_keyblob2pkey(kkey, ktp.keylen, &ktp.protkey); 898fb1136d6SIngo Franzki DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); 899fb1136d6SIngo Franzki kfree(kkey); 900fb1136d6SIngo Franzki if (rc) 901fb1136d6SIngo Franzki break; 902fb1136d6SIngo Franzki if (copy_to_user(utp, &ktp, sizeof(ktp))) 903fb1136d6SIngo Franzki return -EFAULT; 904fb1136d6SIngo Franzki break; 905fb1136d6SIngo Franzki } 906*f2bbc96eSHarald Freudenberger case PKEY_GENSECK2: { 907*f2bbc96eSHarald Freudenberger struct pkey_genseck2 __user *ugs = (void __user *) arg; 908*f2bbc96eSHarald Freudenberger struct pkey_genseck2 kgs; 909*f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 910*f2bbc96eSHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 911*f2bbc96eSHarald Freudenberger u8 *kkey; 912*f2bbc96eSHarald Freudenberger 913*f2bbc96eSHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 914*f2bbc96eSHarald Freudenberger return -EFAULT; 915*f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries); 916*f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 917*f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 918*f2bbc96eSHarald Freudenberger kkey = kmalloc(klen, GFP_KERNEL); 919*f2bbc96eSHarald Freudenberger if (!kkey) { 920*f2bbc96eSHarald Freudenberger kfree(apqns); 921*f2bbc96eSHarald Freudenberger return -ENOMEM; 922*f2bbc96eSHarald Freudenberger } 923*f2bbc96eSHarald Freudenberger rc = pkey_genseckey2(apqns, kgs.apqn_entries, 924*f2bbc96eSHarald Freudenberger kgs.type, kgs.size, kgs.keygenflags, 925*f2bbc96eSHarald Freudenberger kkey, &klen); 926*f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_genseckey2()=%d\n", __func__, rc); 927*f2bbc96eSHarald Freudenberger kfree(apqns); 928*f2bbc96eSHarald Freudenberger if (rc) { 929*f2bbc96eSHarald Freudenberger kfree(kkey); 930*f2bbc96eSHarald Freudenberger break; 931*f2bbc96eSHarald Freudenberger } 932*f2bbc96eSHarald Freudenberger if (kgs.key) { 933*f2bbc96eSHarald Freudenberger if (kgs.keylen < klen) { 934*f2bbc96eSHarald Freudenberger kfree(kkey); 935*f2bbc96eSHarald Freudenberger return -EINVAL; 936*f2bbc96eSHarald Freudenberger } 937*f2bbc96eSHarald Freudenberger if (copy_to_user(kgs.key, kkey, klen)) { 938*f2bbc96eSHarald Freudenberger kfree(kkey); 939*f2bbc96eSHarald Freudenberger return -EFAULT; 940*f2bbc96eSHarald Freudenberger } 941*f2bbc96eSHarald Freudenberger } 942*f2bbc96eSHarald Freudenberger kgs.keylen = klen; 943*f2bbc96eSHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 944*f2bbc96eSHarald Freudenberger rc = -EFAULT; 945*f2bbc96eSHarald Freudenberger kfree(kkey); 946*f2bbc96eSHarald Freudenberger break; 947*f2bbc96eSHarald Freudenberger } 948*f2bbc96eSHarald Freudenberger case PKEY_CLR2SECK2: { 949*f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 __user *ucs = (void __user *) arg; 950*f2bbc96eSHarald Freudenberger struct pkey_clr2seck2 kcs; 951*f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns; 952*f2bbc96eSHarald Freudenberger size_t klen = KEYBLOBBUFSIZE; 953*f2bbc96eSHarald Freudenberger u8 *kkey; 954*f2bbc96eSHarald Freudenberger 955*f2bbc96eSHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 956*f2bbc96eSHarald Freudenberger return -EFAULT; 957*f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries); 958*f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 959*f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 960*f2bbc96eSHarald Freudenberger kkey = kmalloc(klen, GFP_KERNEL); 961*f2bbc96eSHarald Freudenberger if (!kkey) { 962*f2bbc96eSHarald Freudenberger kfree(apqns); 963*f2bbc96eSHarald Freudenberger return -ENOMEM; 964*f2bbc96eSHarald Freudenberger } 965*f2bbc96eSHarald Freudenberger rc = pkey_clr2seckey2(apqns, kcs.apqn_entries, 966*f2bbc96eSHarald Freudenberger kcs.type, kcs.size, kcs.keygenflags, 967*f2bbc96eSHarald Freudenberger kcs.clrkey.clrkey, kkey, &klen); 968*f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_clr2seckey2()=%d\n", __func__, rc); 969*f2bbc96eSHarald Freudenberger kfree(apqns); 970*f2bbc96eSHarald Freudenberger if (rc) { 971*f2bbc96eSHarald Freudenberger kfree(kkey); 972*f2bbc96eSHarald Freudenberger break; 973*f2bbc96eSHarald Freudenberger } 974*f2bbc96eSHarald Freudenberger if (kcs.key) { 975*f2bbc96eSHarald Freudenberger if (kcs.keylen < klen) { 976*f2bbc96eSHarald Freudenberger kfree(kkey); 977*f2bbc96eSHarald Freudenberger return -EINVAL; 978*f2bbc96eSHarald Freudenberger } 979*f2bbc96eSHarald Freudenberger if (copy_to_user(kcs.key, kkey, klen)) { 980*f2bbc96eSHarald Freudenberger kfree(kkey); 981*f2bbc96eSHarald Freudenberger return -EFAULT; 982*f2bbc96eSHarald Freudenberger } 983*f2bbc96eSHarald Freudenberger } 984*f2bbc96eSHarald Freudenberger kcs.keylen = klen; 985*f2bbc96eSHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 986*f2bbc96eSHarald Freudenberger rc = -EFAULT; 987*f2bbc96eSHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 988*f2bbc96eSHarald Freudenberger kfree(kkey); 989*f2bbc96eSHarald Freudenberger break; 990*f2bbc96eSHarald Freudenberger } 991*f2bbc96eSHarald Freudenberger case PKEY_VERIFYKEY2: { 992*f2bbc96eSHarald Freudenberger struct pkey_verifykey2 __user *uvk = (void __user *) arg; 993*f2bbc96eSHarald Freudenberger struct pkey_verifykey2 kvk; 994*f2bbc96eSHarald Freudenberger u8 *kkey; 995*f2bbc96eSHarald Freudenberger 996*f2bbc96eSHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 997*f2bbc96eSHarald Freudenberger return -EFAULT; 998*f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kvk.key, kvk.keylen); 999*f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) 1000*f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1001*f2bbc96eSHarald Freudenberger rc = pkey_verifykey2(kkey, kvk.keylen, 1002*f2bbc96eSHarald Freudenberger &kvk.cardnr, &kvk.domain, 1003*f2bbc96eSHarald Freudenberger &kvk.type, &kvk.size, &kvk.flags); 1004*f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_verifykey2()=%d\n", __func__, rc); 1005*f2bbc96eSHarald Freudenberger kfree(kkey); 1006*f2bbc96eSHarald Freudenberger if (rc) 1007*f2bbc96eSHarald Freudenberger break; 1008*f2bbc96eSHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1009*f2bbc96eSHarald Freudenberger return -EFAULT; 1010*f2bbc96eSHarald Freudenberger break; 1011*f2bbc96eSHarald Freudenberger } 1012*f2bbc96eSHarald Freudenberger case PKEY_KBLOB2PROTK2: { 1013*f2bbc96eSHarald Freudenberger struct pkey_kblob2pkey2 __user *utp = (void __user *) arg; 1014*f2bbc96eSHarald Freudenberger struct pkey_kblob2pkey2 ktp; 1015*f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 1016*f2bbc96eSHarald Freudenberger u8 *kkey; 1017*f2bbc96eSHarald Freudenberger 1018*f2bbc96eSHarald Freudenberger if (copy_from_user(&ktp, utp, sizeof(ktp))) 1019*f2bbc96eSHarald Freudenberger return -EFAULT; 1020*f2bbc96eSHarald Freudenberger apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); 1021*f2bbc96eSHarald Freudenberger if (IS_ERR(apqns)) 1022*f2bbc96eSHarald Freudenberger return PTR_ERR(apqns); 1023*f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(ktp.key, ktp.keylen); 1024*f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1025*f2bbc96eSHarald Freudenberger kfree(apqns); 1026*f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1027*f2bbc96eSHarald Freudenberger } 1028*f2bbc96eSHarald Freudenberger rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries, 1029*f2bbc96eSHarald Freudenberger kkey, ktp.keylen, &ktp.protkey); 1030*f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc); 1031*f2bbc96eSHarald Freudenberger kfree(apqns); 1032*f2bbc96eSHarald Freudenberger kfree(kkey); 1033*f2bbc96eSHarald Freudenberger if (rc) 1034*f2bbc96eSHarald Freudenberger break; 1035*f2bbc96eSHarald Freudenberger if (copy_to_user(utp, &ktp, sizeof(ktp))) 1036*f2bbc96eSHarald Freudenberger return -EFAULT; 1037*f2bbc96eSHarald Freudenberger break; 1038*f2bbc96eSHarald Freudenberger } 1039*f2bbc96eSHarald Freudenberger case PKEY_APQNS4K: { 1040*f2bbc96eSHarald Freudenberger struct pkey_apqns4key __user *uak = (void __user *) arg; 1041*f2bbc96eSHarald Freudenberger struct pkey_apqns4key kak; 1042*f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 1043*f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1044*f2bbc96eSHarald Freudenberger u8 *kkey; 1045*f2bbc96eSHarald Freudenberger 1046*f2bbc96eSHarald Freudenberger if (copy_from_user(&kak, uak, sizeof(kak))) 1047*f2bbc96eSHarald Freudenberger return -EFAULT; 1048*f2bbc96eSHarald Freudenberger nr_apqns = kak.apqn_entries; 1049*f2bbc96eSHarald Freudenberger if (nr_apqns) { 1050*f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1051*f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1052*f2bbc96eSHarald Freudenberger GFP_KERNEL); 1053*f2bbc96eSHarald Freudenberger if (!apqns) 1054*f2bbc96eSHarald Freudenberger return -ENOMEM; 1055*f2bbc96eSHarald Freudenberger } 1056*f2bbc96eSHarald Freudenberger kkey = _copy_key_from_user(kak.key, kak.keylen); 1057*f2bbc96eSHarald Freudenberger if (IS_ERR(kkey)) { 1058*f2bbc96eSHarald Freudenberger kfree(apqns); 1059*f2bbc96eSHarald Freudenberger return PTR_ERR(kkey); 1060*f2bbc96eSHarald Freudenberger } 1061*f2bbc96eSHarald Freudenberger rc = pkey_apqns4key(kkey, kak.keylen, kak.flags, 1062*f2bbc96eSHarald Freudenberger apqns, &nr_apqns); 1063*f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4key()=%d\n", __func__, rc); 1064*f2bbc96eSHarald Freudenberger kfree(kkey); 1065*f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1066*f2bbc96eSHarald Freudenberger kfree(apqns); 1067*f2bbc96eSHarald Freudenberger break; 1068*f2bbc96eSHarald Freudenberger } 1069*f2bbc96eSHarald Freudenberger if (!rc && kak.apqns) { 1070*f2bbc96eSHarald Freudenberger if (nr_apqns > kak.apqn_entries) { 1071*f2bbc96eSHarald Freudenberger kfree(apqns); 1072*f2bbc96eSHarald Freudenberger return -EINVAL; 1073*f2bbc96eSHarald Freudenberger } 1074*f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1075*f2bbc96eSHarald Freudenberger if (len) { 1076*f2bbc96eSHarald Freudenberger if (copy_to_user(kak.apqns, apqns, len)) { 1077*f2bbc96eSHarald Freudenberger kfree(apqns); 1078*f2bbc96eSHarald Freudenberger return -EFAULT; 1079*f2bbc96eSHarald Freudenberger } 1080*f2bbc96eSHarald Freudenberger } 1081*f2bbc96eSHarald Freudenberger } 1082*f2bbc96eSHarald Freudenberger kak.apqn_entries = nr_apqns; 1083*f2bbc96eSHarald Freudenberger if (copy_to_user(uak, &kak, sizeof(kak))) 1084*f2bbc96eSHarald Freudenberger rc = -EFAULT; 1085*f2bbc96eSHarald Freudenberger kfree(apqns); 1086*f2bbc96eSHarald Freudenberger break; 1087*f2bbc96eSHarald Freudenberger } 1088*f2bbc96eSHarald Freudenberger case PKEY_APQNS4KT: { 1089*f2bbc96eSHarald Freudenberger struct pkey_apqns4keytype __user *uat = (void __user *) arg; 1090*f2bbc96eSHarald Freudenberger struct pkey_apqns4keytype kat; 1091*f2bbc96eSHarald Freudenberger struct pkey_apqn *apqns = NULL; 1092*f2bbc96eSHarald Freudenberger size_t nr_apqns, len; 1093*f2bbc96eSHarald Freudenberger 1094*f2bbc96eSHarald Freudenberger if (copy_from_user(&kat, uat, sizeof(kat))) 1095*f2bbc96eSHarald Freudenberger return -EFAULT; 1096*f2bbc96eSHarald Freudenberger nr_apqns = kat.apqn_entries; 1097*f2bbc96eSHarald Freudenberger if (nr_apqns) { 1098*f2bbc96eSHarald Freudenberger apqns = kmalloc_array(nr_apqns, 1099*f2bbc96eSHarald Freudenberger sizeof(struct pkey_apqn), 1100*f2bbc96eSHarald Freudenberger GFP_KERNEL); 1101*f2bbc96eSHarald Freudenberger if (!apqns) 1102*f2bbc96eSHarald Freudenberger return -ENOMEM; 1103*f2bbc96eSHarald Freudenberger } 1104*f2bbc96eSHarald Freudenberger rc = pkey_apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp, 1105*f2bbc96eSHarald Freudenberger kat.flags, apqns, &nr_apqns); 1106*f2bbc96eSHarald Freudenberger DEBUG_DBG("%s pkey_apqns4keytype()=%d\n", __func__, rc); 1107*f2bbc96eSHarald Freudenberger if (rc && rc != -ENOSPC) { 1108*f2bbc96eSHarald Freudenberger kfree(apqns); 1109*f2bbc96eSHarald Freudenberger break; 1110*f2bbc96eSHarald Freudenberger } 1111*f2bbc96eSHarald Freudenberger if (!rc && kat.apqns) { 1112*f2bbc96eSHarald Freudenberger if (nr_apqns > kat.apqn_entries) { 1113*f2bbc96eSHarald Freudenberger kfree(apqns); 1114*f2bbc96eSHarald Freudenberger return -EINVAL; 1115*f2bbc96eSHarald Freudenberger } 1116*f2bbc96eSHarald Freudenberger len = nr_apqns * sizeof(struct pkey_apqn); 1117*f2bbc96eSHarald Freudenberger if (len) { 1118*f2bbc96eSHarald Freudenberger if (copy_to_user(kat.apqns, apqns, len)) { 1119*f2bbc96eSHarald Freudenberger kfree(apqns); 1120*f2bbc96eSHarald Freudenberger return -EFAULT; 1121*f2bbc96eSHarald Freudenberger } 1122*f2bbc96eSHarald Freudenberger } 1123*f2bbc96eSHarald Freudenberger } 1124*f2bbc96eSHarald Freudenberger kat.apqn_entries = nr_apqns; 1125*f2bbc96eSHarald Freudenberger if (copy_to_user(uat, &kat, sizeof(kat))) 1126*f2bbc96eSHarald Freudenberger rc = -EFAULT; 1127*f2bbc96eSHarald Freudenberger kfree(apqns); 1128*f2bbc96eSHarald Freudenberger break; 1129*f2bbc96eSHarald Freudenberger } 1130e80d4af0SHarald Freudenberger default: 1131e80d4af0SHarald Freudenberger /* unknown/unsupported ioctl cmd */ 1132e80d4af0SHarald Freudenberger return -ENOTTY; 1133e80d4af0SHarald Freudenberger } 1134e80d4af0SHarald Freudenberger 1135e80d4af0SHarald Freudenberger return rc; 1136e80d4af0SHarald Freudenberger } 1137e80d4af0SHarald Freudenberger 1138e80d4af0SHarald Freudenberger /* 1139e80d4af0SHarald Freudenberger * Sysfs and file io operations 1140e80d4af0SHarald Freudenberger */ 1141d632c047SIngo Franzki 1142d632c047SIngo Franzki /* 1143d632c047SIngo Franzki * Sysfs attribute read function for all protected key binary attributes. 1144d632c047SIngo Franzki * The implementation can not deal with partial reads, because a new random 1145d632c047SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1146d632c047SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1147d632c047SIngo Franzki */ 1148d632c047SIngo Franzki static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1149d632c047SIngo Franzki loff_t off, size_t count) 1150d632c047SIngo Franzki { 1151d632c047SIngo Franzki struct protaeskeytoken protkeytoken; 1152d632c047SIngo Franzki struct pkey_protkey protkey; 1153d632c047SIngo Franzki int rc; 1154d632c047SIngo Franzki 1155d632c047SIngo Franzki if (off != 0 || count < sizeof(protkeytoken)) 1156d632c047SIngo Franzki return -EINVAL; 1157d632c047SIngo Franzki if (is_xts) 1158d632c047SIngo Franzki if (count < 2 * sizeof(protkeytoken)) 1159d632c047SIngo Franzki return -EINVAL; 1160d632c047SIngo Franzki 1161d632c047SIngo Franzki memset(&protkeytoken, 0, sizeof(protkeytoken)); 1162d632c047SIngo Franzki protkeytoken.type = TOKTYPE_NON_CCA; 1163d632c047SIngo Franzki protkeytoken.version = TOKVER_PROTECTED_KEY; 1164d632c047SIngo Franzki protkeytoken.keytype = keytype; 1165d632c047SIngo Franzki 1166d632c047SIngo Franzki rc = pkey_genprotkey(protkeytoken.keytype, &protkey); 1167d632c047SIngo Franzki if (rc) 1168d632c047SIngo Franzki return rc; 1169d632c047SIngo Franzki 1170d632c047SIngo Franzki protkeytoken.len = protkey.len; 1171d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1172d632c047SIngo Franzki 1173d632c047SIngo Franzki memcpy(buf, &protkeytoken, sizeof(protkeytoken)); 1174d632c047SIngo Franzki 1175d632c047SIngo Franzki if (is_xts) { 1176d632c047SIngo Franzki rc = pkey_genprotkey(protkeytoken.keytype, &protkey); 1177d632c047SIngo Franzki if (rc) 1178d632c047SIngo Franzki return rc; 1179d632c047SIngo Franzki 1180d632c047SIngo Franzki protkeytoken.len = protkey.len; 1181d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1182d632c047SIngo Franzki 1183d632c047SIngo Franzki memcpy(buf + sizeof(protkeytoken), &protkeytoken, 1184d632c047SIngo Franzki sizeof(protkeytoken)); 1185d632c047SIngo Franzki 1186d632c047SIngo Franzki return 2 * sizeof(protkeytoken); 1187d632c047SIngo Franzki } 1188d632c047SIngo Franzki 1189d632c047SIngo Franzki return sizeof(protkeytoken); 1190d632c047SIngo Franzki } 1191d632c047SIngo Franzki 1192d632c047SIngo Franzki static ssize_t protkey_aes_128_read(struct file *filp, 1193d632c047SIngo Franzki struct kobject *kobj, 1194d632c047SIngo Franzki struct bin_attribute *attr, 1195d632c047SIngo Franzki char *buf, loff_t off, 1196d632c047SIngo Franzki size_t count) 1197d632c047SIngo Franzki { 1198d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1199d632c047SIngo Franzki off, count); 1200d632c047SIngo Franzki } 1201d632c047SIngo Franzki 1202d632c047SIngo Franzki static ssize_t protkey_aes_192_read(struct file *filp, 1203d632c047SIngo Franzki struct kobject *kobj, 1204d632c047SIngo Franzki struct bin_attribute *attr, 1205d632c047SIngo Franzki char *buf, loff_t off, 1206d632c047SIngo Franzki size_t count) 1207d632c047SIngo Franzki { 1208d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1209d632c047SIngo Franzki off, count); 1210d632c047SIngo Franzki } 1211d632c047SIngo Franzki 1212d632c047SIngo Franzki static ssize_t protkey_aes_256_read(struct file *filp, 1213d632c047SIngo Franzki struct kobject *kobj, 1214d632c047SIngo Franzki struct bin_attribute *attr, 1215d632c047SIngo Franzki char *buf, loff_t off, 1216d632c047SIngo Franzki size_t count) 1217d632c047SIngo Franzki { 1218d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1219d632c047SIngo Franzki off, count); 1220d632c047SIngo Franzki } 1221d632c047SIngo Franzki 1222d632c047SIngo Franzki static ssize_t protkey_aes_128_xts_read(struct file *filp, 1223d632c047SIngo Franzki struct kobject *kobj, 1224d632c047SIngo Franzki struct bin_attribute *attr, 1225d632c047SIngo Franzki char *buf, loff_t off, 1226d632c047SIngo Franzki size_t count) 1227d632c047SIngo Franzki { 1228d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1229d632c047SIngo Franzki off, count); 1230d632c047SIngo Franzki } 1231d632c047SIngo Franzki 1232d632c047SIngo Franzki static ssize_t protkey_aes_256_xts_read(struct file *filp, 1233d632c047SIngo Franzki struct kobject *kobj, 1234d632c047SIngo Franzki struct bin_attribute *attr, 1235d632c047SIngo Franzki char *buf, loff_t off, 1236d632c047SIngo Franzki size_t count) 1237d632c047SIngo Franzki { 1238d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1239d632c047SIngo Franzki off, count); 1240d632c047SIngo Franzki } 1241d632c047SIngo Franzki 1242d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128, sizeof(struct protaeskeytoken)); 1243d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_192, sizeof(struct protaeskeytoken)); 1244d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256, sizeof(struct protaeskeytoken)); 1245d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128_xts, 2 * sizeof(struct protaeskeytoken)); 1246d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256_xts, 2 * sizeof(struct protaeskeytoken)); 1247d632c047SIngo Franzki 1248d632c047SIngo Franzki static struct bin_attribute *protkey_attrs[] = { 1249d632c047SIngo Franzki &bin_attr_protkey_aes_128, 1250d632c047SIngo Franzki &bin_attr_protkey_aes_192, 1251d632c047SIngo Franzki &bin_attr_protkey_aes_256, 1252d632c047SIngo Franzki &bin_attr_protkey_aes_128_xts, 1253d632c047SIngo Franzki &bin_attr_protkey_aes_256_xts, 1254d632c047SIngo Franzki NULL 1255d632c047SIngo Franzki }; 1256d632c047SIngo Franzki 1257d632c047SIngo Franzki static struct attribute_group protkey_attr_group = { 1258d632c047SIngo Franzki .name = "protkey", 1259d632c047SIngo Franzki .bin_attrs = protkey_attrs, 1260d632c047SIngo Franzki }; 1261d632c047SIngo Franzki 1262af504452SIngo Franzki /* 1263af504452SIngo Franzki * Sysfs attribute read function for all secure key ccadata binary attributes. 1264af504452SIngo Franzki * The implementation can not deal with partial reads, because a new random 1265af504452SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1266af504452SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1267af504452SIngo Franzki */ 1268af504452SIngo Franzki static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1269af504452SIngo Franzki loff_t off, size_t count) 1270af504452SIngo Franzki { 1271af504452SIngo Franzki int rc; 1272efc598e6SHarald Freudenberger struct pkey_seckey *seckey = (struct pkey_seckey *) buf; 1273af504452SIngo Franzki 1274af504452SIngo Franzki if (off != 0 || count < sizeof(struct secaeskeytoken)) 1275af504452SIngo Franzki return -EINVAL; 1276af504452SIngo Franzki if (is_xts) 1277af504452SIngo Franzki if (count < 2 * sizeof(struct secaeskeytoken)) 1278af504452SIngo Franzki return -EINVAL; 1279af504452SIngo Franzki 1280efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1281af504452SIngo Franzki if (rc) 1282af504452SIngo Franzki return rc; 1283af504452SIngo Franzki 1284af504452SIngo Franzki if (is_xts) { 1285efc598e6SHarald Freudenberger seckey++; 1286efc598e6SHarald Freudenberger rc = cca_genseckey(-1, -1, keytype, seckey->seckey); 1287af504452SIngo Franzki if (rc) 1288af504452SIngo Franzki return rc; 1289af504452SIngo Franzki 1290af504452SIngo Franzki return 2 * sizeof(struct secaeskeytoken); 1291af504452SIngo Franzki } 1292af504452SIngo Franzki 1293af504452SIngo Franzki return sizeof(struct secaeskeytoken); 1294af504452SIngo Franzki } 1295af504452SIngo Franzki 1296af504452SIngo Franzki static ssize_t ccadata_aes_128_read(struct file *filp, 1297af504452SIngo Franzki struct kobject *kobj, 1298af504452SIngo Franzki struct bin_attribute *attr, 1299af504452SIngo Franzki char *buf, loff_t off, 1300af504452SIngo Franzki size_t count) 1301af504452SIngo Franzki { 1302af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1303af504452SIngo Franzki off, count); 1304af504452SIngo Franzki } 1305af504452SIngo Franzki 1306af504452SIngo Franzki static ssize_t ccadata_aes_192_read(struct file *filp, 1307af504452SIngo Franzki struct kobject *kobj, 1308af504452SIngo Franzki struct bin_attribute *attr, 1309af504452SIngo Franzki char *buf, loff_t off, 1310af504452SIngo Franzki size_t count) 1311af504452SIngo Franzki { 1312af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1313af504452SIngo Franzki off, count); 1314af504452SIngo Franzki } 1315af504452SIngo Franzki 1316af504452SIngo Franzki static ssize_t ccadata_aes_256_read(struct file *filp, 1317af504452SIngo Franzki struct kobject *kobj, 1318af504452SIngo Franzki struct bin_attribute *attr, 1319af504452SIngo Franzki char *buf, loff_t off, 1320af504452SIngo Franzki size_t count) 1321af504452SIngo Franzki { 1322af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1323af504452SIngo Franzki off, count); 1324af504452SIngo Franzki } 1325af504452SIngo Franzki 1326af504452SIngo Franzki static ssize_t ccadata_aes_128_xts_read(struct file *filp, 1327af504452SIngo Franzki struct kobject *kobj, 1328af504452SIngo Franzki struct bin_attribute *attr, 1329af504452SIngo Franzki char *buf, loff_t off, 1330af504452SIngo Franzki size_t count) 1331af504452SIngo Franzki { 1332af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1333af504452SIngo Franzki off, count); 1334af504452SIngo Franzki } 1335af504452SIngo Franzki 1336af504452SIngo Franzki static ssize_t ccadata_aes_256_xts_read(struct file *filp, 1337af504452SIngo Franzki struct kobject *kobj, 1338af504452SIngo Franzki struct bin_attribute *attr, 1339af504452SIngo Franzki char *buf, loff_t off, 1340af504452SIngo Franzki size_t count) 1341af504452SIngo Franzki { 1342af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1343af504452SIngo Franzki off, count); 1344af504452SIngo Franzki } 1345af504452SIngo Franzki 1346af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128, sizeof(struct secaeskeytoken)); 1347af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_192, sizeof(struct secaeskeytoken)); 1348af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256, sizeof(struct secaeskeytoken)); 1349af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128_xts, 2 * sizeof(struct secaeskeytoken)); 1350af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256_xts, 2 * sizeof(struct secaeskeytoken)); 1351af504452SIngo Franzki 1352af504452SIngo Franzki static struct bin_attribute *ccadata_attrs[] = { 1353af504452SIngo Franzki &bin_attr_ccadata_aes_128, 1354af504452SIngo Franzki &bin_attr_ccadata_aes_192, 1355af504452SIngo Franzki &bin_attr_ccadata_aes_256, 1356af504452SIngo Franzki &bin_attr_ccadata_aes_128_xts, 1357af504452SIngo Franzki &bin_attr_ccadata_aes_256_xts, 1358af504452SIngo Franzki NULL 1359af504452SIngo Franzki }; 1360af504452SIngo Franzki 1361af504452SIngo Franzki static struct attribute_group ccadata_attr_group = { 1362af504452SIngo Franzki .name = "ccadata", 1363af504452SIngo Franzki .bin_attrs = ccadata_attrs, 1364af504452SIngo Franzki }; 1365af504452SIngo Franzki 1366d632c047SIngo Franzki static const struct attribute_group *pkey_attr_groups[] = { 1367d632c047SIngo Franzki &protkey_attr_group, 1368af504452SIngo Franzki &ccadata_attr_group, 1369d632c047SIngo Franzki NULL, 1370d632c047SIngo Franzki }; 1371d632c047SIngo Franzki 1372e80d4af0SHarald Freudenberger static const struct file_operations pkey_fops = { 1373e80d4af0SHarald Freudenberger .owner = THIS_MODULE, 1374e80d4af0SHarald Freudenberger .open = nonseekable_open, 1375e80d4af0SHarald Freudenberger .llseek = no_llseek, 1376e80d4af0SHarald Freudenberger .unlocked_ioctl = pkey_unlocked_ioctl, 1377e80d4af0SHarald Freudenberger }; 1378e80d4af0SHarald Freudenberger 1379e80d4af0SHarald Freudenberger static struct miscdevice pkey_dev = { 1380e80d4af0SHarald Freudenberger .name = "pkey", 1381e80d4af0SHarald Freudenberger .minor = MISC_DYNAMIC_MINOR, 1382e80d4af0SHarald Freudenberger .mode = 0666, 1383e80d4af0SHarald Freudenberger .fops = &pkey_fops, 1384d632c047SIngo Franzki .groups = pkey_attr_groups, 1385e80d4af0SHarald Freudenberger }; 1386e80d4af0SHarald Freudenberger 1387e80d4af0SHarald Freudenberger /* 1388e80d4af0SHarald Freudenberger * Module init 1389e80d4af0SHarald Freudenberger */ 1390cb4ef3c2SHeiko Carstens static int __init pkey_init(void) 1391e80d4af0SHarald Freudenberger { 1392f822ad2cSHarald Freudenberger cpacf_mask_t kmc_functions; 1393e80d4af0SHarald Freudenberger 1394f822ad2cSHarald Freudenberger /* 1395f822ad2cSHarald Freudenberger * The pckmo instruction should be available - even if we don't 1396f822ad2cSHarald Freudenberger * actually invoke it. This instruction comes with MSA 3 which 1397f822ad2cSHarald Freudenberger * is also the minimum level for the kmc instructions which 1398f822ad2cSHarald Freudenberger * are able to work with protected keys. 1399f822ad2cSHarald Freudenberger */ 1400e80d4af0SHarald Freudenberger if (!cpacf_query(CPACF_PCKMO, &pckmo_functions)) 140158443b67SDavid Hildenbrand return -ENODEV; 1402e80d4af0SHarald Freudenberger 1403cb26b9ffSIngo Franzki /* check for kmc instructions available */ 1404cb26b9ffSIngo Franzki if (!cpacf_query(CPACF_KMC, &kmc_functions)) 140558443b67SDavid Hildenbrand return -ENODEV; 1406cb26b9ffSIngo Franzki if (!cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_128) || 1407cb26b9ffSIngo Franzki !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_192) || 1408cb26b9ffSIngo Franzki !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_256)) 140958443b67SDavid Hildenbrand return -ENODEV; 1410cb26b9ffSIngo Franzki 1411e80d4af0SHarald Freudenberger pkey_debug_init(); 1412e80d4af0SHarald Freudenberger 1413e80d4af0SHarald Freudenberger return misc_register(&pkey_dev); 1414e80d4af0SHarald Freudenberger } 1415e80d4af0SHarald Freudenberger 1416e80d4af0SHarald Freudenberger /* 1417e80d4af0SHarald Freudenberger * Module exit 1418e80d4af0SHarald Freudenberger */ 1419e80d4af0SHarald Freudenberger static void __exit pkey_exit(void) 1420e80d4af0SHarald Freudenberger { 1421e80d4af0SHarald Freudenberger misc_deregister(&pkey_dev); 1422e80d4af0SHarald Freudenberger pkey_debug_exit(); 1423e80d4af0SHarald Freudenberger } 1424e80d4af0SHarald Freudenberger 142563c19be0SIngo Franzki module_cpu_feature_match(MSA, pkey_init); 1426e80d4af0SHarald Freudenberger module_exit(pkey_exit); 1427