1812141a9SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2e80d4af0SHarald Freudenberger /* 3e80d4af0SHarald Freudenberger * pkey device driver 4e80d4af0SHarald Freudenberger * 5e80d4af0SHarald Freudenberger * Copyright IBM Corp. 2017 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" 27e80d4af0SHarald Freudenberger 28e80d4af0SHarald Freudenberger MODULE_LICENSE("GPL"); 29e80d4af0SHarald Freudenberger MODULE_AUTHOR("IBM Corporation"); 30e80d4af0SHarald Freudenberger MODULE_DESCRIPTION("s390 protected key interface"); 31e80d4af0SHarald Freudenberger 32e80d4af0SHarald Freudenberger /* Size of parameter block used for all cca requests/replies */ 33e80d4af0SHarald Freudenberger #define PARMBSIZE 512 34e80d4af0SHarald Freudenberger 35e80d4af0SHarald Freudenberger /* Size of vardata block used for some of the cca requests/replies */ 36e80d4af0SHarald Freudenberger #define VARDATASIZE 4096 37e80d4af0SHarald 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 /* Key token types */ 660534bde7SIngo Franzki #define TOKTYPE_NON_CCA 0x00 /* Non-CCA key token */ 670534bde7SIngo Franzki #define TOKTYPE_CCA_INTERNAL 0x01 /* CCA internal key token */ 680534bde7SIngo Franzki 690534bde7SIngo Franzki /* For TOKTYPE_NON_CCA: */ 700534bde7SIngo Franzki #define TOKVER_PROTECTED_KEY 0x01 /* Protected key token */ 710534bde7SIngo Franzki 720534bde7SIngo Franzki /* For TOKTYPE_CCA_INTERNAL: */ 730534bde7SIngo Franzki #define TOKVER_CCA_AES 0x04 /* CCA AES key token */ 740534bde7SIngo Franzki 75fb1136d6SIngo Franzki /* header part of a key token */ 76fb1136d6SIngo Franzki struct keytoken_header { 77fb1136d6SIngo Franzki u8 type; /* one of the TOKTYPE values */ 78fb1136d6SIngo Franzki u8 res0[3]; 79fb1136d6SIngo Franzki u8 version; /* one of the TOKVER values */ 80fb1136d6SIngo Franzki u8 res1[3]; 81fb1136d6SIngo Franzki } __packed; 82fb1136d6SIngo Franzki 83e80d4af0SHarald Freudenberger /* inside view of a secure key token (only type 0x01 version 0x04) */ 84e80d4af0SHarald Freudenberger struct secaeskeytoken { 85e80d4af0SHarald Freudenberger u8 type; /* 0x01 for internal key token */ 86e80d4af0SHarald Freudenberger u8 res0[3]; 87e80d4af0SHarald Freudenberger u8 version; /* should be 0x04 */ 88e80d4af0SHarald Freudenberger u8 res1[1]; 89e80d4af0SHarald Freudenberger u8 flag; /* key flags */ 90e80d4af0SHarald Freudenberger u8 res2[1]; 91e80d4af0SHarald Freudenberger u64 mkvp; /* master key verification pattern */ 92e80d4af0SHarald Freudenberger u8 key[32]; /* key value (encrypted) */ 93e80d4af0SHarald Freudenberger u8 cv[8]; /* control vector */ 94e80d4af0SHarald Freudenberger u16 bitsize; /* key bit size */ 95e80d4af0SHarald Freudenberger u16 keysize; /* key byte size */ 96e80d4af0SHarald Freudenberger u8 tvv[4]; /* token validation value */ 97e80d4af0SHarald Freudenberger } __packed; 98e80d4af0SHarald Freudenberger 990534bde7SIngo Franzki /* inside view of a protected key token (only type 0x00 version 0x01) */ 1000534bde7SIngo Franzki struct protaeskeytoken { 1010534bde7SIngo Franzki u8 type; /* 0x00 for PAES specific key tokens */ 1020534bde7SIngo Franzki u8 res0[3]; 1030534bde7SIngo Franzki u8 version; /* should be 0x01 for protected AES key token */ 1040534bde7SIngo Franzki u8 res1[3]; 1050534bde7SIngo Franzki u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ 1060534bde7SIngo Franzki u32 len; /* bytes actually stored in protkey[] */ 1070534bde7SIngo Franzki u8 protkey[MAXPROTKEYSIZE]; /* the protected key blob */ 1080534bde7SIngo Franzki } __packed; 1090534bde7SIngo Franzki 110e80d4af0SHarald Freudenberger /* 111e80d4af0SHarald Freudenberger * Simple check if the token is a valid CCA secure AES key 112e80d4af0SHarald Freudenberger * token. If keybitsize is given, the bitsize of the key is 113e80d4af0SHarald Freudenberger * also checked. Returns 0 on success or errno value on failure. 114e80d4af0SHarald Freudenberger */ 115e61a6134SHarald Freudenberger static int check_secaeskeytoken(const u8 *token, int keybitsize) 116e80d4af0SHarald Freudenberger { 117e80d4af0SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *) token; 118e80d4af0SHarald Freudenberger 1190534bde7SIngo Franzki if (t->type != TOKTYPE_CCA_INTERNAL) { 120e80d4af0SHarald Freudenberger DEBUG_ERR( 1210534bde7SIngo Franzki "%s secure token check failed, type mismatch 0x%02x != 0x%02x\n", 1220534bde7SIngo Franzki __func__, (int) t->type, TOKTYPE_CCA_INTERNAL); 123e80d4af0SHarald Freudenberger return -EINVAL; 124e80d4af0SHarald Freudenberger } 1250534bde7SIngo Franzki if (t->version != TOKVER_CCA_AES) { 126e80d4af0SHarald Freudenberger DEBUG_ERR( 1270534bde7SIngo Franzki "%s secure token check failed, version mismatch 0x%02x != 0x%02x\n", 1280534bde7SIngo Franzki __func__, (int) t->version, TOKVER_CCA_AES); 129e80d4af0SHarald Freudenberger return -EINVAL; 130e80d4af0SHarald Freudenberger } 131e80d4af0SHarald Freudenberger if (keybitsize > 0 && t->bitsize != keybitsize) { 132e80d4af0SHarald Freudenberger DEBUG_ERR( 133ac2b96f3SHarald Freudenberger "%s secure token check failed, bitsize mismatch %d != %d\n", 134ac2b96f3SHarald Freudenberger __func__, (int) t->bitsize, keybitsize); 135e80d4af0SHarald Freudenberger return -EINVAL; 136e80d4af0SHarald Freudenberger } 137e80d4af0SHarald Freudenberger 138e80d4af0SHarald Freudenberger return 0; 139e80d4af0SHarald Freudenberger } 140e80d4af0SHarald Freudenberger 141e80d4af0SHarald Freudenberger /* 142e80d4af0SHarald Freudenberger * Allocate consecutive memory for request CPRB, request param 143e80d4af0SHarald Freudenberger * block, reply CPRB and reply param block and fill in values 144e80d4af0SHarald Freudenberger * for the common fields. Returns 0 on success or errno value 145e80d4af0SHarald Freudenberger * on failure. 146e80d4af0SHarald Freudenberger */ 147e80d4af0SHarald Freudenberger static int alloc_and_prep_cprbmem(size_t paramblen, 148e80d4af0SHarald Freudenberger u8 **pcprbmem, 149e80d4af0SHarald Freudenberger struct CPRBX **preqCPRB, 150e80d4af0SHarald Freudenberger struct CPRBX **prepCPRB) 151e80d4af0SHarald Freudenberger { 152e80d4af0SHarald Freudenberger u8 *cprbmem; 153e80d4af0SHarald Freudenberger size_t cprbplusparamblen = sizeof(struct CPRBX) + paramblen; 154e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 155e80d4af0SHarald Freudenberger 156e80d4af0SHarald Freudenberger /* 157e80d4af0SHarald Freudenberger * allocate consecutive memory for request CPRB, request param 158e80d4af0SHarald Freudenberger * block, reply CPRB and reply param block 159e80d4af0SHarald Freudenberger */ 1606396bb22SKees Cook cprbmem = kcalloc(2, cprbplusparamblen, GFP_KERNEL); 161e80d4af0SHarald Freudenberger if (!cprbmem) 162e80d4af0SHarald Freudenberger return -ENOMEM; 163e80d4af0SHarald Freudenberger 164e80d4af0SHarald Freudenberger preqcblk = (struct CPRBX *) cprbmem; 165e80d4af0SHarald Freudenberger prepcblk = (struct CPRBX *) (cprbmem + cprbplusparamblen); 166e80d4af0SHarald Freudenberger 167e80d4af0SHarald Freudenberger /* fill request cprb struct */ 168e80d4af0SHarald Freudenberger preqcblk->cprb_len = sizeof(struct CPRBX); 169e80d4af0SHarald Freudenberger preqcblk->cprb_ver_id = 0x02; 170e80d4af0SHarald Freudenberger memcpy(preqcblk->func_id, "T2", 2); 171e80d4af0SHarald Freudenberger preqcblk->rpl_msgbl = cprbplusparamblen; 172e80d4af0SHarald Freudenberger if (paramblen) { 173e80d4af0SHarald Freudenberger preqcblk->req_parmb = 174e80d4af0SHarald Freudenberger ((u8 *) preqcblk) + sizeof(struct CPRBX); 175e80d4af0SHarald Freudenberger preqcblk->rpl_parmb = 176e80d4af0SHarald Freudenberger ((u8 *) prepcblk) + sizeof(struct CPRBX); 177e80d4af0SHarald Freudenberger } 178e80d4af0SHarald Freudenberger 179e80d4af0SHarald Freudenberger *pcprbmem = cprbmem; 180e80d4af0SHarald Freudenberger *preqCPRB = preqcblk; 181e80d4af0SHarald Freudenberger *prepCPRB = prepcblk; 182e80d4af0SHarald Freudenberger 183e80d4af0SHarald Freudenberger return 0; 184e80d4af0SHarald Freudenberger } 185e80d4af0SHarald Freudenberger 186e80d4af0SHarald Freudenberger /* 187e80d4af0SHarald Freudenberger * Free the cprb memory allocated with the function above. 188e80d4af0SHarald Freudenberger * If the scrub value is not zero, the memory is filled 189e80d4af0SHarald Freudenberger * with zeros before freeing (useful if there was some 190e80d4af0SHarald Freudenberger * clear key material in there). 191e80d4af0SHarald Freudenberger */ 192e80d4af0SHarald Freudenberger static void free_cprbmem(void *mem, size_t paramblen, int scrub) 193e80d4af0SHarald Freudenberger { 194e80d4af0SHarald Freudenberger if (scrub) 195e80d4af0SHarald Freudenberger memzero_explicit(mem, 2 * (sizeof(struct CPRBX) + paramblen)); 196e80d4af0SHarald Freudenberger kfree(mem); 197e80d4af0SHarald Freudenberger } 198e80d4af0SHarald Freudenberger 199e80d4af0SHarald Freudenberger /* 200e80d4af0SHarald Freudenberger * Helper function to prepare the xcrb struct 201e80d4af0SHarald Freudenberger */ 202e80d4af0SHarald Freudenberger static inline void prep_xcrb(struct ica_xcRB *pxcrb, 203e80d4af0SHarald Freudenberger u16 cardnr, 204e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, 205e80d4af0SHarald Freudenberger struct CPRBX *prepcblk) 206e80d4af0SHarald Freudenberger { 207e80d4af0SHarald Freudenberger memset(pxcrb, 0, sizeof(*pxcrb)); 208e80d4af0SHarald Freudenberger pxcrb->agent_ID = 0x4341; /* 'CA' */ 209e80d4af0SHarald Freudenberger pxcrb->user_defined = (cardnr == 0xFFFF ? AUTOSELECT : cardnr); 210e80d4af0SHarald Freudenberger pxcrb->request_control_blk_length = 211e80d4af0SHarald Freudenberger preqcblk->cprb_len + preqcblk->req_parml; 2127a003637SHeiko Carstens pxcrb->request_control_blk_addr = (void __user *) preqcblk; 213e80d4af0SHarald Freudenberger pxcrb->reply_control_blk_length = preqcblk->rpl_msgbl; 2147a003637SHeiko Carstens pxcrb->reply_control_blk_addr = (void __user *) prepcblk; 215e80d4af0SHarald Freudenberger } 216e80d4af0SHarald Freudenberger 217e80d4af0SHarald Freudenberger /* 218e80d4af0SHarald Freudenberger * Helper function which calls zcrypt_send_cprb with 219e80d4af0SHarald Freudenberger * memory management segment adjusted to kernel space 220e80d4af0SHarald Freudenberger * so that the copy_from_user called within this 221e80d4af0SHarald Freudenberger * function do in fact copy from kernel space. 222e80d4af0SHarald Freudenberger */ 223e80d4af0SHarald Freudenberger static inline int _zcrypt_send_cprb(struct ica_xcRB *xcrb) 224e80d4af0SHarald Freudenberger { 225e80d4af0SHarald Freudenberger int rc; 226e80d4af0SHarald Freudenberger mm_segment_t old_fs = get_fs(); 227e80d4af0SHarald Freudenberger 228e80d4af0SHarald Freudenberger set_fs(KERNEL_DS); 229e80d4af0SHarald Freudenberger rc = zcrypt_send_cprb(xcrb); 230e80d4af0SHarald Freudenberger set_fs(old_fs); 231e80d4af0SHarald Freudenberger 232e80d4af0SHarald Freudenberger return rc; 233e80d4af0SHarald Freudenberger } 234e80d4af0SHarald Freudenberger 235e80d4af0SHarald Freudenberger /* 236e80d4af0SHarald Freudenberger * Generate (random) AES secure key. 237e80d4af0SHarald Freudenberger */ 238e80d4af0SHarald Freudenberger int pkey_genseckey(u16 cardnr, u16 domain, 239e80d4af0SHarald Freudenberger u32 keytype, struct pkey_seckey *seckey) 240e80d4af0SHarald Freudenberger { 241e80d4af0SHarald Freudenberger int i, rc, keysize; 242e80d4af0SHarald Freudenberger int seckeysize; 243e80d4af0SHarald Freudenberger u8 *mem; 244e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 245e80d4af0SHarald Freudenberger struct ica_xcRB xcrb; 246e80d4af0SHarald Freudenberger struct kgreqparm { 247e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 248e80d4af0SHarald Freudenberger u16 rule_array_len; 249e80d4af0SHarald Freudenberger struct lv1 { 250e80d4af0SHarald Freudenberger u16 len; 251e80d4af0SHarald Freudenberger char key_form[8]; 252e80d4af0SHarald Freudenberger char key_length[8]; 253e80d4af0SHarald Freudenberger char key_type1[8]; 254e80d4af0SHarald Freudenberger char key_type2[8]; 255e80d4af0SHarald Freudenberger } lv1; 256e80d4af0SHarald Freudenberger struct lv2 { 257e80d4af0SHarald Freudenberger u16 len; 258e80d4af0SHarald Freudenberger struct keyid { 259e80d4af0SHarald Freudenberger u16 len; 260e80d4af0SHarald Freudenberger u16 attr; 261e80d4af0SHarald Freudenberger u8 data[SECKEYBLOBSIZE]; 262e80d4af0SHarald Freudenberger } keyid[6]; 263e80d4af0SHarald Freudenberger } lv2; 264e80d4af0SHarald Freudenberger } *preqparm; 265e80d4af0SHarald Freudenberger struct kgrepparm { 266e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 267e80d4af0SHarald Freudenberger u16 rule_array_len; 268e80d4af0SHarald Freudenberger struct lv3 { 269e80d4af0SHarald Freudenberger u16 len; 270e80d4af0SHarald Freudenberger u16 keyblocklen; 271e80d4af0SHarald Freudenberger struct { 272e80d4af0SHarald Freudenberger u16 toklen; 273e80d4af0SHarald Freudenberger u16 tokattr; 274e80d4af0SHarald Freudenberger u8 tok[0]; 275e80d4af0SHarald Freudenberger /* ... some more data ... */ 276e80d4af0SHarald Freudenberger } keyblock; 277e80d4af0SHarald Freudenberger } lv3; 278e80d4af0SHarald Freudenberger } *prepparm; 279e80d4af0SHarald Freudenberger 280e80d4af0SHarald Freudenberger /* get already prepared memory for 2 cprbs with param block each */ 281e80d4af0SHarald Freudenberger rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); 282e80d4af0SHarald Freudenberger if (rc) 283e80d4af0SHarald Freudenberger return rc; 284e80d4af0SHarald Freudenberger 285e80d4af0SHarald Freudenberger /* fill request cprb struct */ 286e80d4af0SHarald Freudenberger preqcblk->domain = domain; 287e80d4af0SHarald Freudenberger 288e80d4af0SHarald Freudenberger /* fill request cprb param block with KG request */ 289e80d4af0SHarald Freudenberger preqparm = (struct kgreqparm *) preqcblk->req_parmb; 290e80d4af0SHarald Freudenberger memcpy(preqparm->subfunc_code, "KG", 2); 291e80d4af0SHarald Freudenberger preqparm->rule_array_len = sizeof(preqparm->rule_array_len); 292e80d4af0SHarald Freudenberger preqparm->lv1.len = sizeof(struct lv1); 293e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_form, "OP ", 8); 294e80d4af0SHarald Freudenberger switch (keytype) { 295e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 296e80d4af0SHarald Freudenberger keysize = 16; 297e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_length, "KEYLN16 ", 8); 298e80d4af0SHarald Freudenberger break; 299e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 300e80d4af0SHarald Freudenberger keysize = 24; 301e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_length, "KEYLN24 ", 8); 302e80d4af0SHarald Freudenberger break; 303e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 304e80d4af0SHarald Freudenberger keysize = 32; 305e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_length, "KEYLN32 ", 8); 306e80d4af0SHarald Freudenberger break; 307e80d4af0SHarald Freudenberger default: 308e80d4af0SHarald Freudenberger DEBUG_ERR( 309ac2b96f3SHarald Freudenberger "%s unknown/unsupported keytype %d\n", 310ac2b96f3SHarald Freudenberger __func__, keytype); 311e80d4af0SHarald Freudenberger rc = -EINVAL; 312e80d4af0SHarald Freudenberger goto out; 313e80d4af0SHarald Freudenberger } 314e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_type1, "AESDATA ", 8); 315e80d4af0SHarald Freudenberger preqparm->lv2.len = sizeof(struct lv2); 316e80d4af0SHarald Freudenberger for (i = 0; i < 6; i++) { 317e80d4af0SHarald Freudenberger preqparm->lv2.keyid[i].len = sizeof(struct keyid); 318e80d4af0SHarald Freudenberger preqparm->lv2.keyid[i].attr = (i == 2 ? 0x30 : 0x10); 319e80d4af0SHarald Freudenberger } 320e80d4af0SHarald Freudenberger preqcblk->req_parml = sizeof(struct kgreqparm); 321e80d4af0SHarald Freudenberger 322e80d4af0SHarald Freudenberger /* fill xcrb struct */ 323e80d4af0SHarald Freudenberger prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); 324e80d4af0SHarald Freudenberger 325e80d4af0SHarald Freudenberger /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ 326e80d4af0SHarald Freudenberger rc = _zcrypt_send_cprb(&xcrb); 327e80d4af0SHarald Freudenberger if (rc) { 328e80d4af0SHarald Freudenberger DEBUG_ERR( 329ac2b96f3SHarald Freudenberger "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", 330ac2b96f3SHarald Freudenberger __func__, (int) cardnr, (int) domain, rc); 331e80d4af0SHarald Freudenberger goto out; 332e80d4af0SHarald Freudenberger } 333e80d4af0SHarald Freudenberger 334e80d4af0SHarald Freudenberger /* check response returncode and reasoncode */ 335e80d4af0SHarald Freudenberger if (prepcblk->ccp_rtcode != 0) { 336e80d4af0SHarald Freudenberger DEBUG_ERR( 337ac2b96f3SHarald Freudenberger "%s secure key generate failure, card response %d/%d\n", 338ac2b96f3SHarald Freudenberger __func__, 339e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rtcode, 340e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rscode); 341e80d4af0SHarald Freudenberger rc = -EIO; 342e80d4af0SHarald Freudenberger goto out; 343e80d4af0SHarald Freudenberger } 344e80d4af0SHarald Freudenberger 345e80d4af0SHarald Freudenberger /* process response cprb param block */ 346e80d4af0SHarald Freudenberger prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); 347e80d4af0SHarald Freudenberger prepparm = (struct kgrepparm *) prepcblk->rpl_parmb; 348e80d4af0SHarald Freudenberger 349e80d4af0SHarald Freudenberger /* check length of the returned secure key token */ 350e80d4af0SHarald Freudenberger seckeysize = prepparm->lv3.keyblock.toklen 351e80d4af0SHarald Freudenberger - sizeof(prepparm->lv3.keyblock.toklen) 352e80d4af0SHarald Freudenberger - sizeof(prepparm->lv3.keyblock.tokattr); 353e80d4af0SHarald Freudenberger if (seckeysize != SECKEYBLOBSIZE) { 354e80d4af0SHarald Freudenberger DEBUG_ERR( 355ac2b96f3SHarald Freudenberger "%s secure token size mismatch %d != %d bytes\n", 356ac2b96f3SHarald Freudenberger __func__, seckeysize, SECKEYBLOBSIZE); 357e80d4af0SHarald Freudenberger rc = -EIO; 358e80d4af0SHarald Freudenberger goto out; 359e80d4af0SHarald Freudenberger } 360e80d4af0SHarald Freudenberger 361e80d4af0SHarald Freudenberger /* check secure key token */ 362e80d4af0SHarald Freudenberger rc = check_secaeskeytoken(prepparm->lv3.keyblock.tok, 8*keysize); 363e80d4af0SHarald Freudenberger if (rc) { 364e80d4af0SHarald Freudenberger rc = -EIO; 365e80d4af0SHarald Freudenberger goto out; 366e80d4af0SHarald Freudenberger } 367e80d4af0SHarald Freudenberger 368e80d4af0SHarald Freudenberger /* copy the generated secure key token */ 369e80d4af0SHarald Freudenberger memcpy(seckey->seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE); 370e80d4af0SHarald Freudenberger 371e80d4af0SHarald Freudenberger out: 372e80d4af0SHarald Freudenberger free_cprbmem(mem, PARMBSIZE, 0); 373e80d4af0SHarald Freudenberger return rc; 374e80d4af0SHarald Freudenberger } 375e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_genseckey); 376e80d4af0SHarald Freudenberger 377e80d4af0SHarald Freudenberger /* 378e80d4af0SHarald Freudenberger * Generate an AES secure key with given key value. 379e80d4af0SHarald Freudenberger */ 380e80d4af0SHarald Freudenberger int pkey_clr2seckey(u16 cardnr, u16 domain, u32 keytype, 381e80d4af0SHarald Freudenberger const struct pkey_clrkey *clrkey, 382e80d4af0SHarald Freudenberger struct pkey_seckey *seckey) 383e80d4af0SHarald Freudenberger { 384e80d4af0SHarald Freudenberger int rc, keysize, seckeysize; 385e80d4af0SHarald Freudenberger u8 *mem; 386e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 387e80d4af0SHarald Freudenberger struct ica_xcRB xcrb; 388e80d4af0SHarald Freudenberger struct cmreqparm { 389e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 390e80d4af0SHarald Freudenberger u16 rule_array_len; 391e80d4af0SHarald Freudenberger char rule_array[8]; 392e80d4af0SHarald Freudenberger struct lv1 { 393e80d4af0SHarald Freudenberger u16 len; 394e80d4af0SHarald Freudenberger u8 clrkey[0]; 395e80d4af0SHarald Freudenberger } lv1; 396e80d4af0SHarald Freudenberger struct lv2 { 397e80d4af0SHarald Freudenberger u16 len; 398e80d4af0SHarald Freudenberger struct keyid { 399e80d4af0SHarald Freudenberger u16 len; 400e80d4af0SHarald Freudenberger u16 attr; 401e80d4af0SHarald Freudenberger u8 data[SECKEYBLOBSIZE]; 402e80d4af0SHarald Freudenberger } keyid; 403e80d4af0SHarald Freudenberger } lv2; 404e80d4af0SHarald Freudenberger } *preqparm; 405e80d4af0SHarald Freudenberger struct lv2 *plv2; 406e80d4af0SHarald Freudenberger struct cmrepparm { 407e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 408e80d4af0SHarald Freudenberger u16 rule_array_len; 409e80d4af0SHarald Freudenberger struct lv3 { 410e80d4af0SHarald Freudenberger u16 len; 411e80d4af0SHarald Freudenberger u16 keyblocklen; 412e80d4af0SHarald Freudenberger struct { 413e80d4af0SHarald Freudenberger u16 toklen; 414e80d4af0SHarald Freudenberger u16 tokattr; 415e80d4af0SHarald Freudenberger u8 tok[0]; 416e80d4af0SHarald Freudenberger /* ... some more data ... */ 417e80d4af0SHarald Freudenberger } keyblock; 418e80d4af0SHarald Freudenberger } lv3; 419e80d4af0SHarald Freudenberger } *prepparm; 420e80d4af0SHarald Freudenberger 421e80d4af0SHarald Freudenberger /* get already prepared memory for 2 cprbs with param block each */ 422e80d4af0SHarald Freudenberger rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); 423e80d4af0SHarald Freudenberger if (rc) 424e80d4af0SHarald Freudenberger return rc; 425e80d4af0SHarald Freudenberger 426e80d4af0SHarald Freudenberger /* fill request cprb struct */ 427e80d4af0SHarald Freudenberger preqcblk->domain = domain; 428e80d4af0SHarald Freudenberger 429e80d4af0SHarald Freudenberger /* fill request cprb param block with CM request */ 430e80d4af0SHarald Freudenberger preqparm = (struct cmreqparm *) preqcblk->req_parmb; 431e80d4af0SHarald Freudenberger memcpy(preqparm->subfunc_code, "CM", 2); 432e80d4af0SHarald Freudenberger memcpy(preqparm->rule_array, "AES ", 8); 433e80d4af0SHarald Freudenberger preqparm->rule_array_len = 434e80d4af0SHarald Freudenberger sizeof(preqparm->rule_array_len) + sizeof(preqparm->rule_array); 435e80d4af0SHarald Freudenberger switch (keytype) { 436e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 437e80d4af0SHarald Freudenberger keysize = 16; 438e80d4af0SHarald Freudenberger break; 439e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 440e80d4af0SHarald Freudenberger keysize = 24; 441e80d4af0SHarald Freudenberger break; 442e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 443e80d4af0SHarald Freudenberger keysize = 32; 444e80d4af0SHarald Freudenberger break; 445e80d4af0SHarald Freudenberger default: 446e80d4af0SHarald Freudenberger DEBUG_ERR( 447ac2b96f3SHarald Freudenberger "%s unknown/unsupported keytype %d\n", 448ac2b96f3SHarald Freudenberger __func__, keytype); 449e80d4af0SHarald Freudenberger rc = -EINVAL; 450e80d4af0SHarald Freudenberger goto out; 451e80d4af0SHarald Freudenberger } 452e80d4af0SHarald Freudenberger preqparm->lv1.len = sizeof(struct lv1) + keysize; 453e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.clrkey, clrkey->clrkey, keysize); 454e80d4af0SHarald Freudenberger plv2 = (struct lv2 *) (((u8 *) &preqparm->lv2) + keysize); 455e80d4af0SHarald Freudenberger plv2->len = sizeof(struct lv2); 456e80d4af0SHarald Freudenberger plv2->keyid.len = sizeof(struct keyid); 457e80d4af0SHarald Freudenberger plv2->keyid.attr = 0x30; 458e80d4af0SHarald Freudenberger preqcblk->req_parml = sizeof(struct cmreqparm) + keysize; 459e80d4af0SHarald Freudenberger 460e80d4af0SHarald Freudenberger /* fill xcrb struct */ 461e80d4af0SHarald Freudenberger prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); 462e80d4af0SHarald Freudenberger 463e80d4af0SHarald Freudenberger /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ 464e80d4af0SHarald Freudenberger rc = _zcrypt_send_cprb(&xcrb); 465e80d4af0SHarald Freudenberger if (rc) { 466e80d4af0SHarald Freudenberger DEBUG_ERR( 467ac2b96f3SHarald Freudenberger "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", 468ac2b96f3SHarald Freudenberger __func__, (int) cardnr, (int) domain, rc); 469e80d4af0SHarald Freudenberger goto out; 470e80d4af0SHarald Freudenberger } 471e80d4af0SHarald Freudenberger 472e80d4af0SHarald Freudenberger /* check response returncode and reasoncode */ 473e80d4af0SHarald Freudenberger if (prepcblk->ccp_rtcode != 0) { 474e80d4af0SHarald Freudenberger DEBUG_ERR( 475ac2b96f3SHarald Freudenberger "%s clear key import failure, card response %d/%d\n", 476ac2b96f3SHarald Freudenberger __func__, 477e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rtcode, 478e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rscode); 479e80d4af0SHarald Freudenberger rc = -EIO; 480e80d4af0SHarald Freudenberger goto out; 481e80d4af0SHarald Freudenberger } 482e80d4af0SHarald Freudenberger 483e80d4af0SHarald Freudenberger /* process response cprb param block */ 484e80d4af0SHarald Freudenberger prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); 485e80d4af0SHarald Freudenberger prepparm = (struct cmrepparm *) prepcblk->rpl_parmb; 486e80d4af0SHarald Freudenberger 487e80d4af0SHarald Freudenberger /* check length of the returned secure key token */ 488e80d4af0SHarald Freudenberger seckeysize = prepparm->lv3.keyblock.toklen 489e80d4af0SHarald Freudenberger - sizeof(prepparm->lv3.keyblock.toklen) 490e80d4af0SHarald Freudenberger - sizeof(prepparm->lv3.keyblock.tokattr); 491e80d4af0SHarald Freudenberger if (seckeysize != SECKEYBLOBSIZE) { 492e80d4af0SHarald Freudenberger DEBUG_ERR( 493ac2b96f3SHarald Freudenberger "%s secure token size mismatch %d != %d bytes\n", 494ac2b96f3SHarald Freudenberger __func__, seckeysize, SECKEYBLOBSIZE); 495e80d4af0SHarald Freudenberger rc = -EIO; 496e80d4af0SHarald Freudenberger goto out; 497e80d4af0SHarald Freudenberger } 498e80d4af0SHarald Freudenberger 499e80d4af0SHarald Freudenberger /* check secure key token */ 500e80d4af0SHarald Freudenberger rc = check_secaeskeytoken(prepparm->lv3.keyblock.tok, 8*keysize); 501e80d4af0SHarald Freudenberger if (rc) { 502e80d4af0SHarald Freudenberger rc = -EIO; 503e80d4af0SHarald Freudenberger goto out; 504e80d4af0SHarald Freudenberger } 505e80d4af0SHarald Freudenberger 506e80d4af0SHarald Freudenberger /* copy the generated secure key token */ 507e80d4af0SHarald Freudenberger memcpy(seckey->seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE); 508e80d4af0SHarald Freudenberger 509e80d4af0SHarald Freudenberger out: 510e80d4af0SHarald Freudenberger free_cprbmem(mem, PARMBSIZE, 1); 511e80d4af0SHarald Freudenberger return rc; 512e80d4af0SHarald Freudenberger } 513e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_clr2seckey); 514e80d4af0SHarald Freudenberger 515e80d4af0SHarald Freudenberger /* 516e80d4af0SHarald Freudenberger * Derive a proteced key from the secure key blob. 517e80d4af0SHarald Freudenberger */ 518e80d4af0SHarald Freudenberger int pkey_sec2protkey(u16 cardnr, u16 domain, 519e80d4af0SHarald Freudenberger const struct pkey_seckey *seckey, 520e80d4af0SHarald Freudenberger struct pkey_protkey *protkey) 521e80d4af0SHarald Freudenberger { 522e80d4af0SHarald Freudenberger int rc; 523e80d4af0SHarald Freudenberger u8 *mem; 524e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 525e80d4af0SHarald Freudenberger struct ica_xcRB xcrb; 526e80d4af0SHarald Freudenberger struct uskreqparm { 527e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 528e80d4af0SHarald Freudenberger u16 rule_array_len; 529e80d4af0SHarald Freudenberger struct lv1 { 530e80d4af0SHarald Freudenberger u16 len; 531e80d4af0SHarald Freudenberger u16 attr_len; 532e80d4af0SHarald Freudenberger u16 attr_flags; 533e80d4af0SHarald Freudenberger } lv1; 534e80d4af0SHarald Freudenberger struct lv2 { 535e80d4af0SHarald Freudenberger u16 len; 536e80d4af0SHarald Freudenberger u16 attr_len; 537e80d4af0SHarald Freudenberger u16 attr_flags; 538e80d4af0SHarald Freudenberger u8 token[0]; /* cca secure key token */ 539e80d4af0SHarald Freudenberger } lv2 __packed; 540e80d4af0SHarald Freudenberger } *preqparm; 541e80d4af0SHarald Freudenberger struct uskrepparm { 542e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 543e80d4af0SHarald Freudenberger u16 rule_array_len; 544e80d4af0SHarald Freudenberger struct lv3 { 545e80d4af0SHarald Freudenberger u16 len; 546e80d4af0SHarald Freudenberger u16 attr_len; 547e80d4af0SHarald Freudenberger u16 attr_flags; 548e80d4af0SHarald Freudenberger struct cpacfkeyblock { 549e80d4af0SHarald Freudenberger u8 version; /* version of this struct */ 550e80d4af0SHarald Freudenberger u8 flags[2]; 551e80d4af0SHarald Freudenberger u8 algo; 552e80d4af0SHarald Freudenberger u8 form; 553e80d4af0SHarald Freudenberger u8 pad1[3]; 554e80d4af0SHarald Freudenberger u16 keylen; 555e80d4af0SHarald Freudenberger u8 key[64]; /* the key (keylen bytes) */ 556e80d4af0SHarald Freudenberger u16 keyattrlen; 557e80d4af0SHarald Freudenberger u8 keyattr[32]; 558e80d4af0SHarald Freudenberger u8 pad2[1]; 559e80d4af0SHarald Freudenberger u8 vptype; 560e80d4af0SHarald Freudenberger u8 vp[32]; /* verification pattern */ 561e80d4af0SHarald Freudenberger } keyblock; 562e80d4af0SHarald Freudenberger } lv3 __packed; 563e80d4af0SHarald Freudenberger } *prepparm; 564e80d4af0SHarald Freudenberger 565e80d4af0SHarald Freudenberger /* get already prepared memory for 2 cprbs with param block each */ 566e80d4af0SHarald Freudenberger rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); 567e80d4af0SHarald Freudenberger if (rc) 568e80d4af0SHarald Freudenberger return rc; 569e80d4af0SHarald Freudenberger 570e80d4af0SHarald Freudenberger /* fill request cprb struct */ 571e80d4af0SHarald Freudenberger preqcblk->domain = domain; 572e80d4af0SHarald Freudenberger 573e80d4af0SHarald Freudenberger /* fill request cprb param block with USK request */ 574e80d4af0SHarald Freudenberger preqparm = (struct uskreqparm *) preqcblk->req_parmb; 575e80d4af0SHarald Freudenberger memcpy(preqparm->subfunc_code, "US", 2); 576e80d4af0SHarald Freudenberger preqparm->rule_array_len = sizeof(preqparm->rule_array_len); 577e80d4af0SHarald Freudenberger preqparm->lv1.len = sizeof(struct lv1); 578e80d4af0SHarald Freudenberger preqparm->lv1.attr_len = sizeof(struct lv1) - sizeof(preqparm->lv1.len); 579e80d4af0SHarald Freudenberger preqparm->lv1.attr_flags = 0x0001; 580e80d4af0SHarald Freudenberger preqparm->lv2.len = sizeof(struct lv2) + SECKEYBLOBSIZE; 581e80d4af0SHarald Freudenberger preqparm->lv2.attr_len = sizeof(struct lv2) 582e80d4af0SHarald Freudenberger - sizeof(preqparm->lv2.len) + SECKEYBLOBSIZE; 583e80d4af0SHarald Freudenberger preqparm->lv2.attr_flags = 0x0000; 584e80d4af0SHarald Freudenberger memcpy(preqparm->lv2.token, seckey->seckey, SECKEYBLOBSIZE); 585e80d4af0SHarald Freudenberger preqcblk->req_parml = sizeof(struct uskreqparm) + SECKEYBLOBSIZE; 586e80d4af0SHarald Freudenberger 587e80d4af0SHarald Freudenberger /* fill xcrb struct */ 588e80d4af0SHarald Freudenberger prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); 589e80d4af0SHarald Freudenberger 590e80d4af0SHarald Freudenberger /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ 591e80d4af0SHarald Freudenberger rc = _zcrypt_send_cprb(&xcrb); 592e80d4af0SHarald Freudenberger if (rc) { 593e80d4af0SHarald Freudenberger DEBUG_ERR( 594ac2b96f3SHarald Freudenberger "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", 595ac2b96f3SHarald Freudenberger __func__, (int) cardnr, (int) domain, rc); 596e80d4af0SHarald Freudenberger goto out; 597e80d4af0SHarald Freudenberger } 598e80d4af0SHarald Freudenberger 599e80d4af0SHarald Freudenberger /* check response returncode and reasoncode */ 600e80d4af0SHarald Freudenberger if (prepcblk->ccp_rtcode != 0) { 601e80d4af0SHarald Freudenberger DEBUG_ERR( 602ac2b96f3SHarald Freudenberger "%s unwrap secure key failure, card response %d/%d\n", 603ac2b96f3SHarald Freudenberger __func__, 604e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rtcode, 605e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rscode); 606e80d4af0SHarald Freudenberger rc = -EIO; 607e80d4af0SHarald Freudenberger goto out; 608e80d4af0SHarald Freudenberger } 609ca681ec8SHarald Freudenberger if (prepcblk->ccp_rscode != 0) { 610ca681ec8SHarald Freudenberger DEBUG_WARN( 611ac2b96f3SHarald Freudenberger "%s unwrap secure key warning, card response %d/%d\n", 612ac2b96f3SHarald Freudenberger __func__, 613ca681ec8SHarald Freudenberger (int) prepcblk->ccp_rtcode, 614ca681ec8SHarald Freudenberger (int) prepcblk->ccp_rscode); 615ca681ec8SHarald Freudenberger } 616e80d4af0SHarald Freudenberger 617e80d4af0SHarald Freudenberger /* process response cprb param block */ 618e80d4af0SHarald Freudenberger prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); 619e80d4af0SHarald Freudenberger prepparm = (struct uskrepparm *) prepcblk->rpl_parmb; 620e80d4af0SHarald Freudenberger 621e80d4af0SHarald Freudenberger /* check the returned keyblock */ 622e80d4af0SHarald Freudenberger if (prepparm->lv3.keyblock.version != 0x01) { 623e80d4af0SHarald Freudenberger DEBUG_ERR( 624ac2b96f3SHarald Freudenberger "%s reply param keyblock version mismatch 0x%02x != 0x01\n", 625ac2b96f3SHarald Freudenberger __func__, (int) prepparm->lv3.keyblock.version); 626e80d4af0SHarald Freudenberger rc = -EIO; 627e80d4af0SHarald Freudenberger goto out; 628e80d4af0SHarald Freudenberger } 629e80d4af0SHarald Freudenberger 630e80d4af0SHarald Freudenberger /* copy the tanslated protected key */ 631e80d4af0SHarald Freudenberger switch (prepparm->lv3.keyblock.keylen) { 632e80d4af0SHarald Freudenberger case 16+32: 633e80d4af0SHarald Freudenberger protkey->type = PKEY_KEYTYPE_AES_128; 634e80d4af0SHarald Freudenberger break; 635e80d4af0SHarald Freudenberger case 24+32: 636e80d4af0SHarald Freudenberger protkey->type = PKEY_KEYTYPE_AES_192; 637e80d4af0SHarald Freudenberger break; 638e80d4af0SHarald Freudenberger case 32+32: 639e80d4af0SHarald Freudenberger protkey->type = PKEY_KEYTYPE_AES_256; 640e80d4af0SHarald Freudenberger break; 641e80d4af0SHarald Freudenberger default: 642ac2b96f3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %d\n", 643ac2b96f3SHarald Freudenberger __func__, prepparm->lv3.keyblock.keylen); 644e80d4af0SHarald Freudenberger rc = -EIO; 645e80d4af0SHarald Freudenberger goto out; 646e80d4af0SHarald Freudenberger } 647e80d4af0SHarald Freudenberger protkey->len = prepparm->lv3.keyblock.keylen; 648e80d4af0SHarald Freudenberger memcpy(protkey->protkey, prepparm->lv3.keyblock.key, protkey->len); 649e80d4af0SHarald Freudenberger 650e80d4af0SHarald Freudenberger out: 651e80d4af0SHarald Freudenberger free_cprbmem(mem, PARMBSIZE, 0); 652e80d4af0SHarald Freudenberger return rc; 653e80d4af0SHarald Freudenberger } 654e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_sec2protkey); 655e80d4af0SHarald Freudenberger 656e80d4af0SHarald Freudenberger /* 657e80d4af0SHarald Freudenberger * Create a protected key from a clear key value. 658e80d4af0SHarald Freudenberger */ 659e80d4af0SHarald Freudenberger int pkey_clr2protkey(u32 keytype, 660e80d4af0SHarald Freudenberger const struct pkey_clrkey *clrkey, 661e80d4af0SHarald Freudenberger struct pkey_protkey *protkey) 662e80d4af0SHarald Freudenberger { 663e80d4af0SHarald Freudenberger long fc; 664e80d4af0SHarald Freudenberger int keysize; 665e80d4af0SHarald Freudenberger u8 paramblock[64]; 666e80d4af0SHarald Freudenberger 667e80d4af0SHarald Freudenberger switch (keytype) { 668e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 669e80d4af0SHarald Freudenberger keysize = 16; 670e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_128_KEY; 671e80d4af0SHarald Freudenberger break; 672e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 673e80d4af0SHarald Freudenberger keysize = 24; 674e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_192_KEY; 675e80d4af0SHarald Freudenberger break; 676e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 677e80d4af0SHarald Freudenberger keysize = 32; 678e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_256_KEY; 679e80d4af0SHarald Freudenberger break; 680e80d4af0SHarald Freudenberger default: 681ac2b96f3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %d\n", 682ac2b96f3SHarald Freudenberger __func__, keytype); 683e80d4af0SHarald Freudenberger return -EINVAL; 684e80d4af0SHarald Freudenberger } 685e80d4af0SHarald Freudenberger 686f822ad2cSHarald Freudenberger /* 687f822ad2cSHarald Freudenberger * Check if the needed pckmo subfunction is available. 688f822ad2cSHarald Freudenberger * These subfunctions can be enabled/disabled by customers 689f822ad2cSHarald Freudenberger * in the LPAR profile or may even change on the fly. 690f822ad2cSHarald Freudenberger */ 691f822ad2cSHarald Freudenberger if (!cpacf_test_func(&pckmo_functions, fc)) { 692f822ad2cSHarald Freudenberger DEBUG_ERR("%s pckmo functions not available\n", __func__); 693*58443b67SDavid Hildenbrand return -ENODEV; 694f822ad2cSHarald Freudenberger } 695f822ad2cSHarald Freudenberger 696e80d4af0SHarald Freudenberger /* prepare param block */ 697e80d4af0SHarald Freudenberger memset(paramblock, 0, sizeof(paramblock)); 698e80d4af0SHarald Freudenberger memcpy(paramblock, clrkey->clrkey, keysize); 699e80d4af0SHarald Freudenberger 700e80d4af0SHarald Freudenberger /* call the pckmo instruction */ 701e80d4af0SHarald Freudenberger cpacf_pckmo(fc, paramblock); 702e80d4af0SHarald Freudenberger 703e80d4af0SHarald Freudenberger /* copy created protected key */ 704e80d4af0SHarald Freudenberger protkey->type = keytype; 705e80d4af0SHarald Freudenberger protkey->len = keysize + 32; 706e80d4af0SHarald Freudenberger memcpy(protkey->protkey, paramblock, keysize + 32); 707e80d4af0SHarald Freudenberger 708e80d4af0SHarald Freudenberger return 0; 709e80d4af0SHarald Freudenberger } 710e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_clr2protkey); 711e80d4af0SHarald Freudenberger 712e80d4af0SHarald Freudenberger /* 713e80d4af0SHarald Freudenberger * query cryptographic facility from adapter 714e80d4af0SHarald Freudenberger */ 715e80d4af0SHarald Freudenberger static int query_crypto_facility(u16 cardnr, u16 domain, 716e80d4af0SHarald Freudenberger const char *keyword, 717e80d4af0SHarald Freudenberger u8 *rarray, size_t *rarraylen, 718e80d4af0SHarald Freudenberger u8 *varray, size_t *varraylen) 719e80d4af0SHarald Freudenberger { 720e80d4af0SHarald Freudenberger int rc; 721e80d4af0SHarald Freudenberger u16 len; 722e80d4af0SHarald Freudenberger u8 *mem, *ptr; 723e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 724e80d4af0SHarald Freudenberger struct ica_xcRB xcrb; 725e80d4af0SHarald Freudenberger struct fqreqparm { 726e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 727e80d4af0SHarald Freudenberger u16 rule_array_len; 728e80d4af0SHarald Freudenberger char rule_array[8]; 729e80d4af0SHarald Freudenberger struct lv1 { 730e80d4af0SHarald Freudenberger u16 len; 731e80d4af0SHarald Freudenberger u8 data[VARDATASIZE]; 732e80d4af0SHarald Freudenberger } lv1; 733e80d4af0SHarald Freudenberger u16 dummylen; 734e80d4af0SHarald Freudenberger } *preqparm; 735e80d4af0SHarald Freudenberger size_t parmbsize = sizeof(struct fqreqparm); 736e80d4af0SHarald Freudenberger struct fqrepparm { 737e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 738e80d4af0SHarald Freudenberger u8 lvdata[0]; 739e80d4af0SHarald Freudenberger } *prepparm; 740e80d4af0SHarald Freudenberger 741e80d4af0SHarald Freudenberger /* get already prepared memory for 2 cprbs with param block each */ 742e80d4af0SHarald Freudenberger rc = alloc_and_prep_cprbmem(parmbsize, &mem, &preqcblk, &prepcblk); 743e80d4af0SHarald Freudenberger if (rc) 744e80d4af0SHarald Freudenberger return rc; 745e80d4af0SHarald Freudenberger 746e80d4af0SHarald Freudenberger /* fill request cprb struct */ 747e80d4af0SHarald Freudenberger preqcblk->domain = domain; 748e80d4af0SHarald Freudenberger 749e80d4af0SHarald Freudenberger /* fill request cprb param block with FQ request */ 750e80d4af0SHarald Freudenberger preqparm = (struct fqreqparm *) preqcblk->req_parmb; 751e80d4af0SHarald Freudenberger memcpy(preqparm->subfunc_code, "FQ", 2); 752a09baa95SVasily Gorbik memcpy(preqparm->rule_array, keyword, sizeof(preqparm->rule_array)); 753e80d4af0SHarald Freudenberger preqparm->rule_array_len = 754e80d4af0SHarald Freudenberger sizeof(preqparm->rule_array_len) + sizeof(preqparm->rule_array); 755e80d4af0SHarald Freudenberger preqparm->lv1.len = sizeof(preqparm->lv1); 756e80d4af0SHarald Freudenberger preqparm->dummylen = sizeof(preqparm->dummylen); 757e80d4af0SHarald Freudenberger preqcblk->req_parml = parmbsize; 758e80d4af0SHarald Freudenberger 759e80d4af0SHarald Freudenberger /* fill xcrb struct */ 760e80d4af0SHarald Freudenberger prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); 761e80d4af0SHarald Freudenberger 762e80d4af0SHarald Freudenberger /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ 763e80d4af0SHarald Freudenberger rc = _zcrypt_send_cprb(&xcrb); 764e80d4af0SHarald Freudenberger if (rc) { 765e80d4af0SHarald Freudenberger DEBUG_ERR( 766ac2b96f3SHarald Freudenberger "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", 767ac2b96f3SHarald Freudenberger __func__, (int) cardnr, (int) domain, rc); 768e80d4af0SHarald Freudenberger goto out; 769e80d4af0SHarald Freudenberger } 770e80d4af0SHarald Freudenberger 771e80d4af0SHarald Freudenberger /* check response returncode and reasoncode */ 772e80d4af0SHarald Freudenberger if (prepcblk->ccp_rtcode != 0) { 773e80d4af0SHarald Freudenberger DEBUG_ERR( 774ac2b96f3SHarald Freudenberger "%s unwrap secure key failure, card response %d/%d\n", 775ac2b96f3SHarald Freudenberger __func__, 776e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rtcode, 777e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rscode); 778e80d4af0SHarald Freudenberger rc = -EIO; 779e80d4af0SHarald Freudenberger goto out; 780e80d4af0SHarald Freudenberger } 781e80d4af0SHarald Freudenberger 782e80d4af0SHarald Freudenberger /* process response cprb param block */ 783e80d4af0SHarald Freudenberger prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); 784e80d4af0SHarald Freudenberger prepparm = (struct fqrepparm *) prepcblk->rpl_parmb; 785e80d4af0SHarald Freudenberger ptr = prepparm->lvdata; 786e80d4af0SHarald Freudenberger 787e80d4af0SHarald Freudenberger /* check and possibly copy reply rule array */ 788e80d4af0SHarald Freudenberger len = *((u16 *) ptr); 789e80d4af0SHarald Freudenberger if (len > sizeof(u16)) { 790e80d4af0SHarald Freudenberger ptr += sizeof(u16); 791e80d4af0SHarald Freudenberger len -= sizeof(u16); 792e80d4af0SHarald Freudenberger if (rarray && rarraylen && *rarraylen > 0) { 793e80d4af0SHarald Freudenberger *rarraylen = (len > *rarraylen ? *rarraylen : len); 794e80d4af0SHarald Freudenberger memcpy(rarray, ptr, *rarraylen); 795e80d4af0SHarald Freudenberger } 796e80d4af0SHarald Freudenberger ptr += len; 797e80d4af0SHarald Freudenberger } 798e80d4af0SHarald Freudenberger /* check and possible copy reply var array */ 799e80d4af0SHarald Freudenberger len = *((u16 *) ptr); 800e80d4af0SHarald Freudenberger if (len > sizeof(u16)) { 801e80d4af0SHarald Freudenberger ptr += sizeof(u16); 802e80d4af0SHarald Freudenberger len -= sizeof(u16); 803e80d4af0SHarald Freudenberger if (varray && varraylen && *varraylen > 0) { 804e80d4af0SHarald Freudenberger *varraylen = (len > *varraylen ? *varraylen : len); 805e80d4af0SHarald Freudenberger memcpy(varray, ptr, *varraylen); 806e80d4af0SHarald Freudenberger } 807e80d4af0SHarald Freudenberger ptr += len; 808e80d4af0SHarald Freudenberger } 809e80d4af0SHarald Freudenberger 810e80d4af0SHarald Freudenberger out: 811e80d4af0SHarald Freudenberger free_cprbmem(mem, parmbsize, 0); 812e80d4af0SHarald Freudenberger return rc; 813e80d4af0SHarald Freudenberger } 814e80d4af0SHarald Freudenberger 815e80d4af0SHarald Freudenberger /* 816ca681ec8SHarald Freudenberger * Fetch the current and old mkvp values via 817ca681ec8SHarald Freudenberger * query_crypto_facility from adapter. 818e80d4af0SHarald Freudenberger */ 819ca681ec8SHarald Freudenberger static int fetch_mkvp(u16 cardnr, u16 domain, u64 mkvp[2]) 820e80d4af0SHarald Freudenberger { 821e80d4af0SHarald Freudenberger int rc, found = 0; 822e80d4af0SHarald Freudenberger size_t rlen, vlen; 823e80d4af0SHarald Freudenberger u8 *rarray, *varray, *pg; 824e80d4af0SHarald Freudenberger 825e80d4af0SHarald Freudenberger pg = (u8 *) __get_free_page(GFP_KERNEL); 826e80d4af0SHarald Freudenberger if (!pg) 827e80d4af0SHarald Freudenberger return -ENOMEM; 828e80d4af0SHarald Freudenberger rarray = pg; 829e80d4af0SHarald Freudenberger varray = pg + PAGE_SIZE/2; 830e80d4af0SHarald Freudenberger rlen = vlen = PAGE_SIZE/2; 831e80d4af0SHarald Freudenberger 832e80d4af0SHarald Freudenberger rc = query_crypto_facility(cardnr, domain, "STATICSA", 833e80d4af0SHarald Freudenberger rarray, &rlen, varray, &vlen); 834e80d4af0SHarald Freudenberger if (rc == 0 && rlen > 8*8 && vlen > 184+8) { 835ca681ec8SHarald Freudenberger if (rarray[8*8] == '2') { 836e80d4af0SHarald Freudenberger /* current master key state is valid */ 837ca681ec8SHarald Freudenberger mkvp[0] = *((u64 *)(varray + 184)); 838ca681ec8SHarald Freudenberger mkvp[1] = *((u64 *)(varray + 172)); 839e80d4af0SHarald Freudenberger found = 1; 840e80d4af0SHarald Freudenberger } 841e80d4af0SHarald Freudenberger } 842e80d4af0SHarald Freudenberger 843e80d4af0SHarald Freudenberger free_page((unsigned long) pg); 844e80d4af0SHarald Freudenberger 845e80d4af0SHarald Freudenberger return found ? 0 : -ENOENT; 846e80d4af0SHarald Freudenberger } 847e80d4af0SHarald Freudenberger 848e80d4af0SHarald Freudenberger /* struct to hold cached mkvp info for each card/domain */ 849e80d4af0SHarald Freudenberger struct mkvp_info { 850e80d4af0SHarald Freudenberger struct list_head list; 851e80d4af0SHarald Freudenberger u16 cardnr; 852e80d4af0SHarald Freudenberger u16 domain; 853ca681ec8SHarald Freudenberger u64 mkvp[2]; 854e80d4af0SHarald Freudenberger }; 855e80d4af0SHarald Freudenberger 856e80d4af0SHarald Freudenberger /* a list with mkvp_info entries */ 857e80d4af0SHarald Freudenberger static LIST_HEAD(mkvp_list); 858e80d4af0SHarald Freudenberger static DEFINE_SPINLOCK(mkvp_list_lock); 859e80d4af0SHarald Freudenberger 860ca681ec8SHarald Freudenberger static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 mkvp[2]) 861e80d4af0SHarald Freudenberger { 862e80d4af0SHarald Freudenberger int rc = -ENOENT; 863e80d4af0SHarald Freudenberger struct mkvp_info *ptr; 864e80d4af0SHarald Freudenberger 865e80d4af0SHarald Freudenberger spin_lock_bh(&mkvp_list_lock); 866e80d4af0SHarald Freudenberger list_for_each_entry(ptr, &mkvp_list, list) { 867e80d4af0SHarald Freudenberger if (ptr->cardnr == cardnr && 868e80d4af0SHarald Freudenberger ptr->domain == domain) { 869ca681ec8SHarald Freudenberger memcpy(mkvp, ptr->mkvp, 2 * sizeof(u64)); 870e80d4af0SHarald Freudenberger rc = 0; 871e80d4af0SHarald Freudenberger break; 872e80d4af0SHarald Freudenberger } 873e80d4af0SHarald Freudenberger } 874e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 875e80d4af0SHarald Freudenberger 876e80d4af0SHarald Freudenberger return rc; 877e80d4af0SHarald Freudenberger } 878e80d4af0SHarald Freudenberger 879ca681ec8SHarald Freudenberger static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp[2]) 880e80d4af0SHarald Freudenberger { 881e80d4af0SHarald Freudenberger int found = 0; 882e80d4af0SHarald Freudenberger struct mkvp_info *ptr; 883e80d4af0SHarald Freudenberger 884e80d4af0SHarald Freudenberger spin_lock_bh(&mkvp_list_lock); 885e80d4af0SHarald Freudenberger list_for_each_entry(ptr, &mkvp_list, list) { 886e80d4af0SHarald Freudenberger if (ptr->cardnr == cardnr && 887e80d4af0SHarald Freudenberger ptr->domain == domain) { 888ca681ec8SHarald Freudenberger memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64)); 889e80d4af0SHarald Freudenberger found = 1; 890e80d4af0SHarald Freudenberger break; 891e80d4af0SHarald Freudenberger } 892e80d4af0SHarald Freudenberger } 893e80d4af0SHarald Freudenberger if (!found) { 894e80d4af0SHarald Freudenberger ptr = kmalloc(sizeof(*ptr), GFP_ATOMIC); 895e80d4af0SHarald Freudenberger if (!ptr) { 896e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 897e80d4af0SHarald Freudenberger return; 898e80d4af0SHarald Freudenberger } 899e80d4af0SHarald Freudenberger ptr->cardnr = cardnr; 900e80d4af0SHarald Freudenberger ptr->domain = domain; 901ca681ec8SHarald Freudenberger memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64)); 902e80d4af0SHarald Freudenberger list_add(&ptr->list, &mkvp_list); 903e80d4af0SHarald Freudenberger } 904e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 905e80d4af0SHarald Freudenberger } 906e80d4af0SHarald Freudenberger 907e80d4af0SHarald Freudenberger static void mkvp_cache_scrub(u16 cardnr, u16 domain) 908e80d4af0SHarald Freudenberger { 909e80d4af0SHarald Freudenberger struct mkvp_info *ptr; 910e80d4af0SHarald Freudenberger 911e80d4af0SHarald Freudenberger spin_lock_bh(&mkvp_list_lock); 912e80d4af0SHarald Freudenberger list_for_each_entry(ptr, &mkvp_list, list) { 913e80d4af0SHarald Freudenberger if (ptr->cardnr == cardnr && 914e80d4af0SHarald Freudenberger ptr->domain == domain) { 915e80d4af0SHarald Freudenberger list_del(&ptr->list); 916e80d4af0SHarald Freudenberger kfree(ptr); 917e80d4af0SHarald Freudenberger break; 918e80d4af0SHarald Freudenberger } 919e80d4af0SHarald Freudenberger } 920e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 921e80d4af0SHarald Freudenberger } 922e80d4af0SHarald Freudenberger 923e80d4af0SHarald Freudenberger static void __exit mkvp_cache_free(void) 924e80d4af0SHarald Freudenberger { 925e80d4af0SHarald Freudenberger struct mkvp_info *ptr, *pnext; 926e80d4af0SHarald Freudenberger 927e80d4af0SHarald Freudenberger spin_lock_bh(&mkvp_list_lock); 928e80d4af0SHarald Freudenberger list_for_each_entry_safe(ptr, pnext, &mkvp_list, list) { 929e80d4af0SHarald Freudenberger list_del(&ptr->list); 930e80d4af0SHarald Freudenberger kfree(ptr); 931e80d4af0SHarald Freudenberger } 932e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 933e80d4af0SHarald Freudenberger } 934e80d4af0SHarald Freudenberger 935e80d4af0SHarald Freudenberger /* 936e80d4af0SHarald Freudenberger * Search for a matching crypto card based on the Master Key 937e80d4af0SHarald Freudenberger * Verification Pattern provided inside a secure key. 938e80d4af0SHarald Freudenberger */ 939e80d4af0SHarald Freudenberger int pkey_findcard(const struct pkey_seckey *seckey, 940e80d4af0SHarald Freudenberger u16 *pcardnr, u16 *pdomain, int verify) 941e80d4af0SHarald Freudenberger { 942e80d4af0SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; 943af4a7227SHarald Freudenberger struct zcrypt_device_status_ext *device_status; 944e80d4af0SHarald Freudenberger u16 card, dom; 945ca681ec8SHarald Freudenberger u64 mkvp[2]; 946ca681ec8SHarald Freudenberger int i, rc, oi = -1; 947e80d4af0SHarald Freudenberger 948e80d4af0SHarald Freudenberger /* mkvp must not be zero */ 949e80d4af0SHarald Freudenberger if (t->mkvp == 0) 950e80d4af0SHarald Freudenberger return -EINVAL; 951e80d4af0SHarald Freudenberger 952e80d4af0SHarald Freudenberger /* fetch status of all crypto cards */ 9536da2ec56SKees Cook device_status = kmalloc_array(MAX_ZDEV_ENTRIES_EXT, 9546da2ec56SKees Cook sizeof(struct zcrypt_device_status_ext), 955e80d4af0SHarald Freudenberger GFP_KERNEL); 956af4a7227SHarald Freudenberger if (!device_status) 957e80d4af0SHarald Freudenberger return -ENOMEM; 958af4a7227SHarald Freudenberger zcrypt_device_status_mask_ext(device_status); 959e80d4af0SHarald Freudenberger 960e80d4af0SHarald Freudenberger /* walk through all crypto cards */ 961af4a7227SHarald Freudenberger for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) { 962af4a7227SHarald Freudenberger card = AP_QID_CARD(device_status[i].qid); 963af4a7227SHarald Freudenberger dom = AP_QID_QUEUE(device_status[i].qid); 964af4a7227SHarald Freudenberger if (device_status[i].online && 965af4a7227SHarald Freudenberger device_status[i].functions & 0x04) { 966e80d4af0SHarald Freudenberger /* an enabled CCA Coprocessor card */ 967e80d4af0SHarald Freudenberger /* try cached mkvp */ 968ca681ec8SHarald Freudenberger if (mkvp_cache_fetch(card, dom, mkvp) == 0 && 969ca681ec8SHarald Freudenberger t->mkvp == mkvp[0]) { 970e80d4af0SHarald Freudenberger if (!verify) 971e80d4af0SHarald Freudenberger break; 972e80d4af0SHarald Freudenberger /* verify: fetch mkvp from adapter */ 973ca681ec8SHarald Freudenberger if (fetch_mkvp(card, dom, mkvp) == 0) { 974e80d4af0SHarald Freudenberger mkvp_cache_update(card, dom, mkvp); 975ca681ec8SHarald Freudenberger if (t->mkvp == mkvp[0]) 976e80d4af0SHarald Freudenberger break; 977e80d4af0SHarald Freudenberger } 978e80d4af0SHarald Freudenberger } 979e80d4af0SHarald Freudenberger } else { 980e80d4af0SHarald Freudenberger /* Card is offline and/or not a CCA card. */ 981e80d4af0SHarald Freudenberger /* del mkvp entry from cache if it exists */ 982e80d4af0SHarald Freudenberger mkvp_cache_scrub(card, dom); 983e80d4af0SHarald Freudenberger } 984e80d4af0SHarald Freudenberger } 985af4a7227SHarald Freudenberger if (i >= MAX_ZDEV_ENTRIES_EXT) { 986e80d4af0SHarald Freudenberger /* nothing found, so this time without cache */ 987af4a7227SHarald Freudenberger for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) { 988af4a7227SHarald Freudenberger if (!(device_status[i].online && 989af4a7227SHarald Freudenberger device_status[i].functions & 0x04)) 990e80d4af0SHarald Freudenberger continue; 991af4a7227SHarald Freudenberger card = AP_QID_CARD(device_status[i].qid); 992af4a7227SHarald Freudenberger dom = AP_QID_QUEUE(device_status[i].qid); 993e80d4af0SHarald Freudenberger /* fresh fetch mkvp from adapter */ 994ca681ec8SHarald Freudenberger if (fetch_mkvp(card, dom, mkvp) == 0) { 995e80d4af0SHarald Freudenberger mkvp_cache_update(card, dom, mkvp); 996ca681ec8SHarald Freudenberger if (t->mkvp == mkvp[0]) 997e80d4af0SHarald Freudenberger break; 998ca681ec8SHarald Freudenberger if (t->mkvp == mkvp[1] && oi < 0) 999ca681ec8SHarald Freudenberger oi = i; 1000e80d4af0SHarald Freudenberger } 1001e80d4af0SHarald Freudenberger } 1002af4a7227SHarald Freudenberger if (i >= MAX_ZDEV_ENTRIES_EXT && oi >= 0) { 1003ca681ec8SHarald Freudenberger /* old mkvp matched, use this card then */ 1004af4a7227SHarald Freudenberger card = AP_QID_CARD(device_status[oi].qid); 1005af4a7227SHarald Freudenberger dom = AP_QID_QUEUE(device_status[oi].qid); 1006e80d4af0SHarald Freudenberger } 1007ca681ec8SHarald Freudenberger } 1008af4a7227SHarald Freudenberger if (i < MAX_ZDEV_ENTRIES_EXT || oi >= 0) { 1009e80d4af0SHarald Freudenberger if (pcardnr) 1010e80d4af0SHarald Freudenberger *pcardnr = card; 1011e80d4af0SHarald Freudenberger if (pdomain) 1012e80d4af0SHarald Freudenberger *pdomain = dom; 1013e80d4af0SHarald Freudenberger rc = 0; 1014e80d4af0SHarald Freudenberger } else 1015e80d4af0SHarald Freudenberger rc = -ENODEV; 1016e80d4af0SHarald Freudenberger 1017af4a7227SHarald Freudenberger kfree(device_status); 1018e80d4af0SHarald Freudenberger return rc; 1019e80d4af0SHarald Freudenberger } 1020e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_findcard); 1021e80d4af0SHarald Freudenberger 1022e80d4af0SHarald Freudenberger /* 1023e80d4af0SHarald Freudenberger * Find card and transform secure key into protected key. 1024e80d4af0SHarald Freudenberger */ 1025e80d4af0SHarald Freudenberger int pkey_skey2pkey(const struct pkey_seckey *seckey, 1026e80d4af0SHarald Freudenberger struct pkey_protkey *protkey) 1027e80d4af0SHarald Freudenberger { 1028e80d4af0SHarald Freudenberger u16 cardnr, domain; 1029e80d4af0SHarald Freudenberger int rc, verify; 1030e80d4af0SHarald Freudenberger 1031e80d4af0SHarald Freudenberger /* 1032e80d4af0SHarald Freudenberger * The pkey_sec2protkey call may fail when a card has been 1033e80d4af0SHarald Freudenberger * addressed where the master key was changed after last fetch 1034e80d4af0SHarald Freudenberger * of the mkvp into the cache. So first try without verify then 1035e80d4af0SHarald Freudenberger * with verify enabled (thus refreshing the mkvp for each card). 1036e80d4af0SHarald Freudenberger */ 1037e80d4af0SHarald Freudenberger for (verify = 0; verify < 2; verify++) { 1038e80d4af0SHarald Freudenberger rc = pkey_findcard(seckey, &cardnr, &domain, verify); 1039e80d4af0SHarald Freudenberger if (rc) 1040e80d4af0SHarald Freudenberger continue; 1041e80d4af0SHarald Freudenberger rc = pkey_sec2protkey(cardnr, domain, seckey, protkey); 1042e80d4af0SHarald Freudenberger if (rc == 0) 1043e80d4af0SHarald Freudenberger break; 1044e80d4af0SHarald Freudenberger } 1045e80d4af0SHarald Freudenberger 1046e80d4af0SHarald Freudenberger if (rc) 1047ac2b96f3SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 1048e80d4af0SHarald Freudenberger 1049e80d4af0SHarald Freudenberger return rc; 1050e80d4af0SHarald Freudenberger } 1051e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_skey2pkey); 1052e80d4af0SHarald Freudenberger 1053e80d4af0SHarald Freudenberger /* 1054e61a6134SHarald Freudenberger * Verify key and give back some info about the key. 1055e61a6134SHarald Freudenberger */ 1056e61a6134SHarald Freudenberger int pkey_verifykey(const struct pkey_seckey *seckey, 1057e61a6134SHarald Freudenberger u16 *pcardnr, u16 *pdomain, 1058e61a6134SHarald Freudenberger u16 *pkeysize, u32 *pattributes) 1059e61a6134SHarald Freudenberger { 1060e61a6134SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; 1061e61a6134SHarald Freudenberger u16 cardnr, domain; 1062e61a6134SHarald Freudenberger u64 mkvp[2]; 1063e61a6134SHarald Freudenberger int rc; 1064e61a6134SHarald Freudenberger 1065e61a6134SHarald Freudenberger /* check the secure key for valid AES secure key */ 1066e61a6134SHarald Freudenberger rc = check_secaeskeytoken((u8 *) seckey, 0); 1067e61a6134SHarald Freudenberger if (rc) 1068e61a6134SHarald Freudenberger goto out; 1069e61a6134SHarald Freudenberger if (pattributes) 1070e61a6134SHarald Freudenberger *pattributes = PKEY_VERIFY_ATTR_AES; 1071e61a6134SHarald Freudenberger if (pkeysize) 1072e61a6134SHarald Freudenberger *pkeysize = t->bitsize; 1073e61a6134SHarald Freudenberger 1074e61a6134SHarald Freudenberger /* try to find a card which can handle this key */ 1075e61a6134SHarald Freudenberger rc = pkey_findcard(seckey, &cardnr, &domain, 1); 1076e61a6134SHarald Freudenberger if (rc) 1077e61a6134SHarald Freudenberger goto out; 1078e61a6134SHarald Freudenberger 1079e61a6134SHarald Freudenberger /* check mkvp for old mkvp match */ 1080e61a6134SHarald Freudenberger rc = mkvp_cache_fetch(cardnr, domain, mkvp); 1081e61a6134SHarald Freudenberger if (rc) 1082e61a6134SHarald Freudenberger goto out; 1083ebb7c695SIngo Franzki if (t->mkvp == mkvp[1] && t->mkvp != mkvp[0]) { 1084ac2b96f3SHarald Freudenberger DEBUG_DBG("%s secure key has old mkvp\n", __func__); 1085e61a6134SHarald Freudenberger if (pattributes) 1086e61a6134SHarald Freudenberger *pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP; 1087e61a6134SHarald Freudenberger } 1088e61a6134SHarald Freudenberger 1089e61a6134SHarald Freudenberger if (pcardnr) 1090e61a6134SHarald Freudenberger *pcardnr = cardnr; 1091e61a6134SHarald Freudenberger if (pdomain) 1092e61a6134SHarald Freudenberger *pdomain = domain; 1093e61a6134SHarald Freudenberger 1094e61a6134SHarald Freudenberger out: 1095ac2b96f3SHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 1096e61a6134SHarald Freudenberger return rc; 1097e61a6134SHarald Freudenberger } 1098e61a6134SHarald Freudenberger EXPORT_SYMBOL(pkey_verifykey); 1099e61a6134SHarald Freudenberger 1100e61a6134SHarald Freudenberger /* 1101a45a5c7dSIngo Franzki * Generate a random protected key 1102a45a5c7dSIngo Franzki */ 1103a45a5c7dSIngo Franzki int pkey_genprotkey(__u32 keytype, struct pkey_protkey *protkey) 1104a45a5c7dSIngo Franzki { 1105a45a5c7dSIngo Franzki struct pkey_clrkey clrkey; 1106a45a5c7dSIngo Franzki int keysize; 1107a45a5c7dSIngo Franzki int rc; 1108a45a5c7dSIngo Franzki 1109a45a5c7dSIngo Franzki switch (keytype) { 1110a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_128: 1111a45a5c7dSIngo Franzki keysize = 16; 1112a45a5c7dSIngo Franzki break; 1113a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_192: 1114a45a5c7dSIngo Franzki keysize = 24; 1115a45a5c7dSIngo Franzki break; 1116a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_256: 1117a45a5c7dSIngo Franzki keysize = 32; 1118a45a5c7dSIngo Franzki break; 1119a45a5c7dSIngo Franzki default: 1120a45a5c7dSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 1121a45a5c7dSIngo Franzki keytype); 1122a45a5c7dSIngo Franzki return -EINVAL; 1123a45a5c7dSIngo Franzki } 1124a45a5c7dSIngo Franzki 1125a45a5c7dSIngo Franzki /* generate a dummy random clear key */ 1126a45a5c7dSIngo Franzki get_random_bytes(clrkey.clrkey, keysize); 1127a45a5c7dSIngo Franzki 1128a45a5c7dSIngo Franzki /* convert it to a dummy protected key */ 1129a45a5c7dSIngo Franzki rc = pkey_clr2protkey(keytype, &clrkey, protkey); 1130a45a5c7dSIngo Franzki if (rc) 1131a45a5c7dSIngo Franzki return rc; 1132a45a5c7dSIngo Franzki 1133a45a5c7dSIngo Franzki /* replace the key part of the protected key with random bytes */ 1134a45a5c7dSIngo Franzki get_random_bytes(protkey->protkey, keysize); 1135a45a5c7dSIngo Franzki 1136a45a5c7dSIngo Franzki return 0; 1137a45a5c7dSIngo Franzki } 1138a45a5c7dSIngo Franzki EXPORT_SYMBOL(pkey_genprotkey); 1139a45a5c7dSIngo Franzki 1140a45a5c7dSIngo Franzki /* 1141cb26b9ffSIngo Franzki * Verify if a protected key is still valid 1142cb26b9ffSIngo Franzki */ 1143cb26b9ffSIngo Franzki int pkey_verifyprotkey(const struct pkey_protkey *protkey) 1144cb26b9ffSIngo Franzki { 1145cb26b9ffSIngo Franzki unsigned long fc; 1146cb26b9ffSIngo Franzki struct { 1147cb26b9ffSIngo Franzki u8 iv[AES_BLOCK_SIZE]; 1148cb26b9ffSIngo Franzki u8 key[MAXPROTKEYSIZE]; 1149cb26b9ffSIngo Franzki } param; 1150cb26b9ffSIngo Franzki u8 null_msg[AES_BLOCK_SIZE]; 1151cb26b9ffSIngo Franzki u8 dest_buf[AES_BLOCK_SIZE]; 1152cb26b9ffSIngo Franzki unsigned int k; 1153cb26b9ffSIngo Franzki 1154cb26b9ffSIngo Franzki switch (protkey->type) { 1155cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_128: 1156cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_128; 1157cb26b9ffSIngo Franzki break; 1158cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_192: 1159cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_192; 1160cb26b9ffSIngo Franzki break; 1161cb26b9ffSIngo Franzki case PKEY_KEYTYPE_AES_256: 1162cb26b9ffSIngo Franzki fc = CPACF_KMC_PAES_256; 1163cb26b9ffSIngo Franzki break; 1164cb26b9ffSIngo Franzki default: 1165cb26b9ffSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 1166cb26b9ffSIngo Franzki protkey->type); 1167cb26b9ffSIngo Franzki return -EINVAL; 1168cb26b9ffSIngo Franzki } 1169cb26b9ffSIngo Franzki 1170cb26b9ffSIngo Franzki memset(null_msg, 0, sizeof(null_msg)); 1171cb26b9ffSIngo Franzki 1172cb26b9ffSIngo Franzki memset(param.iv, 0, sizeof(param.iv)); 1173cb26b9ffSIngo Franzki memcpy(param.key, protkey->protkey, sizeof(param.key)); 1174cb26b9ffSIngo Franzki 1175cb26b9ffSIngo Franzki k = cpacf_kmc(fc | CPACF_ENCRYPT, ¶m, null_msg, dest_buf, 1176cb26b9ffSIngo Franzki sizeof(null_msg)); 1177cb26b9ffSIngo Franzki if (k != sizeof(null_msg)) { 1178cb26b9ffSIngo Franzki DEBUG_ERR("%s protected key is not valid\n", __func__); 1179cb26b9ffSIngo Franzki return -EKEYREJECTED; 1180cb26b9ffSIngo Franzki } 1181cb26b9ffSIngo Franzki 1182cb26b9ffSIngo Franzki return 0; 1183cb26b9ffSIngo Franzki } 1184cb26b9ffSIngo Franzki EXPORT_SYMBOL(pkey_verifyprotkey); 1185cb26b9ffSIngo Franzki 1186cb26b9ffSIngo Franzki /* 1187fb1136d6SIngo Franzki * Transform a non-CCA key token into a protected key 1188fb1136d6SIngo Franzki */ 1189fb1136d6SIngo Franzki static int pkey_nonccatok2pkey(const __u8 *key, __u32 keylen, 1190fb1136d6SIngo Franzki struct pkey_protkey *protkey) 1191fb1136d6SIngo Franzki { 1192fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 1193fb1136d6SIngo Franzki struct protaeskeytoken *t; 1194fb1136d6SIngo Franzki 1195fb1136d6SIngo Franzki switch (hdr->version) { 1196fb1136d6SIngo Franzki case TOKVER_PROTECTED_KEY: 1197fb1136d6SIngo Franzki if (keylen != sizeof(struct protaeskeytoken)) 1198fb1136d6SIngo Franzki return -EINVAL; 1199fb1136d6SIngo Franzki 1200fb1136d6SIngo Franzki t = (struct protaeskeytoken *)key; 1201fb1136d6SIngo Franzki protkey->len = t->len; 1202fb1136d6SIngo Franzki protkey->type = t->keytype; 1203fb1136d6SIngo Franzki memcpy(protkey->protkey, t->protkey, 1204fb1136d6SIngo Franzki sizeof(protkey->protkey)); 1205fb1136d6SIngo Franzki 1206fb1136d6SIngo Franzki return pkey_verifyprotkey(protkey); 1207fb1136d6SIngo Franzki default: 1208fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n", 1209fb1136d6SIngo Franzki __func__, hdr->version); 1210fb1136d6SIngo Franzki return -EINVAL; 1211fb1136d6SIngo Franzki } 1212fb1136d6SIngo Franzki } 1213fb1136d6SIngo Franzki 1214fb1136d6SIngo Franzki /* 1215fb1136d6SIngo Franzki * Transform a CCA internal key token into a protected key 1216fb1136d6SIngo Franzki */ 1217fb1136d6SIngo Franzki static int pkey_ccainttok2pkey(const __u8 *key, __u32 keylen, 1218fb1136d6SIngo Franzki struct pkey_protkey *protkey) 1219fb1136d6SIngo Franzki { 1220fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 1221fb1136d6SIngo Franzki 1222fb1136d6SIngo Franzki switch (hdr->version) { 1223fb1136d6SIngo Franzki case TOKVER_CCA_AES: 1224fb1136d6SIngo Franzki if (keylen != sizeof(struct secaeskeytoken)) 1225fb1136d6SIngo Franzki return -EINVAL; 1226fb1136d6SIngo Franzki 1227fb1136d6SIngo Franzki return pkey_skey2pkey((struct pkey_seckey *)key, 1228fb1136d6SIngo Franzki protkey); 1229fb1136d6SIngo Franzki default: 1230fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported CCA internal token version %d\n", 1231fb1136d6SIngo Franzki __func__, hdr->version); 1232fb1136d6SIngo Franzki return -EINVAL; 1233fb1136d6SIngo Franzki } 1234fb1136d6SIngo Franzki } 1235fb1136d6SIngo Franzki 1236fb1136d6SIngo Franzki /* 1237fb1136d6SIngo Franzki * Transform a key blob (of any type) into a protected key 1238fb1136d6SIngo Franzki */ 1239fb1136d6SIngo Franzki int pkey_keyblob2pkey(const __u8 *key, __u32 keylen, 1240fb1136d6SIngo Franzki struct pkey_protkey *protkey) 1241fb1136d6SIngo Franzki { 1242fb1136d6SIngo Franzki struct keytoken_header *hdr = (struct keytoken_header *)key; 1243fb1136d6SIngo Franzki 1244fb1136d6SIngo Franzki if (keylen < sizeof(struct keytoken_header)) 1245fb1136d6SIngo Franzki return -EINVAL; 1246fb1136d6SIngo Franzki 1247fb1136d6SIngo Franzki switch (hdr->type) { 1248fb1136d6SIngo Franzki case TOKTYPE_NON_CCA: 1249fb1136d6SIngo Franzki return pkey_nonccatok2pkey(key, keylen, protkey); 1250fb1136d6SIngo Franzki case TOKTYPE_CCA_INTERNAL: 1251fb1136d6SIngo Franzki return pkey_ccainttok2pkey(key, keylen, protkey); 1252fb1136d6SIngo Franzki default: 1253fb1136d6SIngo Franzki DEBUG_ERR("%s unknown/unsupported blob type %d\n", __func__, 1254fb1136d6SIngo Franzki hdr->type); 1255fb1136d6SIngo Franzki return -EINVAL; 1256fb1136d6SIngo Franzki } 1257fb1136d6SIngo Franzki } 1258fb1136d6SIngo Franzki EXPORT_SYMBOL(pkey_keyblob2pkey); 1259fb1136d6SIngo Franzki 1260fb1136d6SIngo Franzki /* 1261e80d4af0SHarald Freudenberger * File io functions 1262e80d4af0SHarald Freudenberger */ 1263e80d4af0SHarald Freudenberger 1264e80d4af0SHarald Freudenberger static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, 1265e80d4af0SHarald Freudenberger unsigned long arg) 1266e80d4af0SHarald Freudenberger { 1267e80d4af0SHarald Freudenberger int rc; 1268e80d4af0SHarald Freudenberger 1269e80d4af0SHarald Freudenberger switch (cmd) { 1270e80d4af0SHarald Freudenberger case PKEY_GENSECK: { 1271e80d4af0SHarald Freudenberger struct pkey_genseck __user *ugs = (void __user *) arg; 1272e80d4af0SHarald Freudenberger struct pkey_genseck kgs; 1273e80d4af0SHarald Freudenberger 1274e80d4af0SHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 1275e80d4af0SHarald Freudenberger return -EFAULT; 1276e80d4af0SHarald Freudenberger rc = pkey_genseckey(kgs.cardnr, kgs.domain, 1277e80d4af0SHarald Freudenberger kgs.keytype, &kgs.seckey); 1278ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_genseckey()=%d\n", __func__, rc); 1279e80d4af0SHarald Freudenberger if (rc) 1280e80d4af0SHarald Freudenberger break; 1281e80d4af0SHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 1282e80d4af0SHarald Freudenberger return -EFAULT; 1283e80d4af0SHarald Freudenberger break; 1284e80d4af0SHarald Freudenberger } 1285e80d4af0SHarald Freudenberger case PKEY_CLR2SECK: { 1286e80d4af0SHarald Freudenberger struct pkey_clr2seck __user *ucs = (void __user *) arg; 1287e80d4af0SHarald Freudenberger struct pkey_clr2seck kcs; 1288e80d4af0SHarald Freudenberger 1289e80d4af0SHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 1290e80d4af0SHarald Freudenberger return -EFAULT; 1291e80d4af0SHarald Freudenberger rc = pkey_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, 1292e80d4af0SHarald Freudenberger &kcs.clrkey, &kcs.seckey); 1293ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_clr2seckey()=%d\n", __func__, rc); 1294e80d4af0SHarald Freudenberger if (rc) 1295e80d4af0SHarald Freudenberger break; 1296e80d4af0SHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1297e80d4af0SHarald Freudenberger return -EFAULT; 1298e80d4af0SHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1299e80d4af0SHarald Freudenberger break; 1300e80d4af0SHarald Freudenberger } 1301e80d4af0SHarald Freudenberger case PKEY_SEC2PROTK: { 1302e80d4af0SHarald Freudenberger struct pkey_sec2protk __user *usp = (void __user *) arg; 1303e80d4af0SHarald Freudenberger struct pkey_sec2protk ksp; 1304e80d4af0SHarald Freudenberger 1305e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1306e80d4af0SHarald Freudenberger return -EFAULT; 1307e80d4af0SHarald Freudenberger rc = pkey_sec2protkey(ksp.cardnr, ksp.domain, 1308e80d4af0SHarald Freudenberger &ksp.seckey, &ksp.protkey); 1309ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_sec2protkey()=%d\n", __func__, rc); 1310e80d4af0SHarald Freudenberger if (rc) 1311e80d4af0SHarald Freudenberger break; 1312e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1313e80d4af0SHarald Freudenberger return -EFAULT; 1314e80d4af0SHarald Freudenberger break; 1315e80d4af0SHarald Freudenberger } 1316e80d4af0SHarald Freudenberger case PKEY_CLR2PROTK: { 1317e80d4af0SHarald Freudenberger struct pkey_clr2protk __user *ucp = (void __user *) arg; 1318e80d4af0SHarald Freudenberger struct pkey_clr2protk kcp; 1319e80d4af0SHarald Freudenberger 1320e80d4af0SHarald Freudenberger if (copy_from_user(&kcp, ucp, sizeof(kcp))) 1321e80d4af0SHarald Freudenberger return -EFAULT; 1322e80d4af0SHarald Freudenberger rc = pkey_clr2protkey(kcp.keytype, 1323e80d4af0SHarald Freudenberger &kcp.clrkey, &kcp.protkey); 1324ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc); 1325e80d4af0SHarald Freudenberger if (rc) 1326e80d4af0SHarald Freudenberger break; 1327e80d4af0SHarald Freudenberger if (copy_to_user(ucp, &kcp, sizeof(kcp))) 1328e80d4af0SHarald Freudenberger return -EFAULT; 1329e80d4af0SHarald Freudenberger memzero_explicit(&kcp, sizeof(kcp)); 1330e80d4af0SHarald Freudenberger break; 1331e80d4af0SHarald Freudenberger } 1332e80d4af0SHarald Freudenberger case PKEY_FINDCARD: { 1333e80d4af0SHarald Freudenberger struct pkey_findcard __user *ufc = (void __user *) arg; 1334e80d4af0SHarald Freudenberger struct pkey_findcard kfc; 1335e80d4af0SHarald Freudenberger 1336e80d4af0SHarald Freudenberger if (copy_from_user(&kfc, ufc, sizeof(kfc))) 1337e80d4af0SHarald Freudenberger return -EFAULT; 1338e80d4af0SHarald Freudenberger rc = pkey_findcard(&kfc.seckey, 1339e80d4af0SHarald Freudenberger &kfc.cardnr, &kfc.domain, 1); 1340ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_findcard()=%d\n", __func__, rc); 1341e80d4af0SHarald Freudenberger if (rc) 1342e80d4af0SHarald Freudenberger break; 1343e80d4af0SHarald Freudenberger if (copy_to_user(ufc, &kfc, sizeof(kfc))) 1344e80d4af0SHarald Freudenberger return -EFAULT; 1345e80d4af0SHarald Freudenberger break; 1346e80d4af0SHarald Freudenberger } 1347e80d4af0SHarald Freudenberger case PKEY_SKEY2PKEY: { 1348e80d4af0SHarald Freudenberger struct pkey_skey2pkey __user *usp = (void __user *) arg; 1349e80d4af0SHarald Freudenberger struct pkey_skey2pkey ksp; 1350e80d4af0SHarald Freudenberger 1351e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1352e80d4af0SHarald Freudenberger return -EFAULT; 1353e80d4af0SHarald Freudenberger rc = pkey_skey2pkey(&ksp.seckey, &ksp.protkey); 1354ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc); 1355e80d4af0SHarald Freudenberger if (rc) 1356e80d4af0SHarald Freudenberger break; 1357e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1358e80d4af0SHarald Freudenberger return -EFAULT; 1359e80d4af0SHarald Freudenberger break; 1360e80d4af0SHarald Freudenberger } 1361e61a6134SHarald Freudenberger case PKEY_VERIFYKEY: { 1362e61a6134SHarald Freudenberger struct pkey_verifykey __user *uvk = (void __user *) arg; 1363e61a6134SHarald Freudenberger struct pkey_verifykey kvk; 1364e61a6134SHarald Freudenberger 1365e61a6134SHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1366e61a6134SHarald Freudenberger return -EFAULT; 1367e61a6134SHarald Freudenberger rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain, 1368e61a6134SHarald Freudenberger &kvk.keysize, &kvk.attributes); 1369ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_verifykey()=%d\n", __func__, rc); 1370e61a6134SHarald Freudenberger if (rc) 1371e61a6134SHarald Freudenberger break; 1372e61a6134SHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1373e61a6134SHarald Freudenberger return -EFAULT; 1374e61a6134SHarald Freudenberger break; 1375e61a6134SHarald Freudenberger } 1376a45a5c7dSIngo Franzki case PKEY_GENPROTK: { 1377a45a5c7dSIngo Franzki struct pkey_genprotk __user *ugp = (void __user *) arg; 1378a45a5c7dSIngo Franzki struct pkey_genprotk kgp; 1379a45a5c7dSIngo Franzki 1380a45a5c7dSIngo Franzki if (copy_from_user(&kgp, ugp, sizeof(kgp))) 1381a45a5c7dSIngo Franzki return -EFAULT; 1382a45a5c7dSIngo Franzki rc = pkey_genprotkey(kgp.keytype, &kgp.protkey); 1383a45a5c7dSIngo Franzki DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc); 1384a45a5c7dSIngo Franzki if (rc) 1385a45a5c7dSIngo Franzki break; 1386a45a5c7dSIngo Franzki if (copy_to_user(ugp, &kgp, sizeof(kgp))) 1387a45a5c7dSIngo Franzki return -EFAULT; 1388a45a5c7dSIngo Franzki break; 1389a45a5c7dSIngo Franzki } 1390cb26b9ffSIngo Franzki case PKEY_VERIFYPROTK: { 1391cb26b9ffSIngo Franzki struct pkey_verifyprotk __user *uvp = (void __user *) arg; 1392cb26b9ffSIngo Franzki struct pkey_verifyprotk kvp; 1393cb26b9ffSIngo Franzki 1394cb26b9ffSIngo Franzki if (copy_from_user(&kvp, uvp, sizeof(kvp))) 1395cb26b9ffSIngo Franzki return -EFAULT; 1396cb26b9ffSIngo Franzki rc = pkey_verifyprotkey(&kvp.protkey); 1397cb26b9ffSIngo Franzki DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc); 1398cb26b9ffSIngo Franzki break; 1399cb26b9ffSIngo Franzki } 1400fb1136d6SIngo Franzki case PKEY_KBLOB2PROTK: { 1401fb1136d6SIngo Franzki struct pkey_kblob2pkey __user *utp = (void __user *) arg; 1402fb1136d6SIngo Franzki struct pkey_kblob2pkey ktp; 1403fb1136d6SIngo Franzki __u8 __user *ukey; 1404fb1136d6SIngo Franzki __u8 *kkey; 1405fb1136d6SIngo Franzki 1406fb1136d6SIngo Franzki if (copy_from_user(&ktp, utp, sizeof(ktp))) 1407fb1136d6SIngo Franzki return -EFAULT; 1408fb1136d6SIngo Franzki if (ktp.keylen < MINKEYBLOBSIZE || 1409fb1136d6SIngo Franzki ktp.keylen > MAXKEYBLOBSIZE) 1410fb1136d6SIngo Franzki return -EINVAL; 1411fb1136d6SIngo Franzki ukey = ktp.key; 1412fb1136d6SIngo Franzki kkey = kmalloc(ktp.keylen, GFP_KERNEL); 1413fb1136d6SIngo Franzki if (kkey == NULL) 1414fb1136d6SIngo Franzki return -ENOMEM; 1415fb1136d6SIngo Franzki if (copy_from_user(kkey, ukey, ktp.keylen)) { 1416fb1136d6SIngo Franzki kfree(kkey); 1417fb1136d6SIngo Franzki return -EFAULT; 1418fb1136d6SIngo Franzki } 1419fb1136d6SIngo Franzki rc = pkey_keyblob2pkey(kkey, ktp.keylen, &ktp.protkey); 1420fb1136d6SIngo Franzki DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); 1421fb1136d6SIngo Franzki kfree(kkey); 1422fb1136d6SIngo Franzki if (rc) 1423fb1136d6SIngo Franzki break; 1424fb1136d6SIngo Franzki if (copy_to_user(utp, &ktp, sizeof(ktp))) 1425fb1136d6SIngo Franzki return -EFAULT; 1426fb1136d6SIngo Franzki break; 1427fb1136d6SIngo Franzki } 1428e80d4af0SHarald Freudenberger default: 1429e80d4af0SHarald Freudenberger /* unknown/unsupported ioctl cmd */ 1430e80d4af0SHarald Freudenberger return -ENOTTY; 1431e80d4af0SHarald Freudenberger } 1432e80d4af0SHarald Freudenberger 1433e80d4af0SHarald Freudenberger return rc; 1434e80d4af0SHarald Freudenberger } 1435e80d4af0SHarald Freudenberger 1436e80d4af0SHarald Freudenberger /* 1437e80d4af0SHarald Freudenberger * Sysfs and file io operations 1438e80d4af0SHarald Freudenberger */ 1439d632c047SIngo Franzki 1440d632c047SIngo Franzki /* 1441d632c047SIngo Franzki * Sysfs attribute read function for all protected key binary attributes. 1442d632c047SIngo Franzki * The implementation can not deal with partial reads, because a new random 1443d632c047SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1444d632c047SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1445d632c047SIngo Franzki */ 1446d632c047SIngo Franzki static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1447d632c047SIngo Franzki loff_t off, size_t count) 1448d632c047SIngo Franzki { 1449d632c047SIngo Franzki struct protaeskeytoken protkeytoken; 1450d632c047SIngo Franzki struct pkey_protkey protkey; 1451d632c047SIngo Franzki int rc; 1452d632c047SIngo Franzki 1453d632c047SIngo Franzki if (off != 0 || count < sizeof(protkeytoken)) 1454d632c047SIngo Franzki return -EINVAL; 1455d632c047SIngo Franzki if (is_xts) 1456d632c047SIngo Franzki if (count < 2 * sizeof(protkeytoken)) 1457d632c047SIngo Franzki return -EINVAL; 1458d632c047SIngo Franzki 1459d632c047SIngo Franzki memset(&protkeytoken, 0, sizeof(protkeytoken)); 1460d632c047SIngo Franzki protkeytoken.type = TOKTYPE_NON_CCA; 1461d632c047SIngo Franzki protkeytoken.version = TOKVER_PROTECTED_KEY; 1462d632c047SIngo Franzki protkeytoken.keytype = keytype; 1463d632c047SIngo Franzki 1464d632c047SIngo Franzki rc = pkey_genprotkey(protkeytoken.keytype, &protkey); 1465d632c047SIngo Franzki if (rc) 1466d632c047SIngo Franzki return rc; 1467d632c047SIngo Franzki 1468d632c047SIngo Franzki protkeytoken.len = protkey.len; 1469d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1470d632c047SIngo Franzki 1471d632c047SIngo Franzki memcpy(buf, &protkeytoken, sizeof(protkeytoken)); 1472d632c047SIngo Franzki 1473d632c047SIngo Franzki if (is_xts) { 1474d632c047SIngo Franzki rc = pkey_genprotkey(protkeytoken.keytype, &protkey); 1475d632c047SIngo Franzki if (rc) 1476d632c047SIngo Franzki return rc; 1477d632c047SIngo Franzki 1478d632c047SIngo Franzki protkeytoken.len = protkey.len; 1479d632c047SIngo Franzki memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); 1480d632c047SIngo Franzki 1481d632c047SIngo Franzki memcpy(buf + sizeof(protkeytoken), &protkeytoken, 1482d632c047SIngo Franzki sizeof(protkeytoken)); 1483d632c047SIngo Franzki 1484d632c047SIngo Franzki return 2 * sizeof(protkeytoken); 1485d632c047SIngo Franzki } 1486d632c047SIngo Franzki 1487d632c047SIngo Franzki return sizeof(protkeytoken); 1488d632c047SIngo Franzki } 1489d632c047SIngo Franzki 1490d632c047SIngo Franzki static ssize_t protkey_aes_128_read(struct file *filp, 1491d632c047SIngo Franzki struct kobject *kobj, 1492d632c047SIngo Franzki struct bin_attribute *attr, 1493d632c047SIngo Franzki char *buf, loff_t off, 1494d632c047SIngo Franzki size_t count) 1495d632c047SIngo Franzki { 1496d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1497d632c047SIngo Franzki off, count); 1498d632c047SIngo Franzki } 1499d632c047SIngo Franzki 1500d632c047SIngo Franzki static ssize_t protkey_aes_192_read(struct file *filp, 1501d632c047SIngo Franzki struct kobject *kobj, 1502d632c047SIngo Franzki struct bin_attribute *attr, 1503d632c047SIngo Franzki char *buf, loff_t off, 1504d632c047SIngo Franzki size_t count) 1505d632c047SIngo Franzki { 1506d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1507d632c047SIngo Franzki off, count); 1508d632c047SIngo Franzki } 1509d632c047SIngo Franzki 1510d632c047SIngo Franzki static ssize_t protkey_aes_256_read(struct file *filp, 1511d632c047SIngo Franzki struct kobject *kobj, 1512d632c047SIngo Franzki struct bin_attribute *attr, 1513d632c047SIngo Franzki char *buf, loff_t off, 1514d632c047SIngo Franzki size_t count) 1515d632c047SIngo Franzki { 1516d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1517d632c047SIngo Franzki off, count); 1518d632c047SIngo Franzki } 1519d632c047SIngo Franzki 1520d632c047SIngo Franzki static ssize_t protkey_aes_128_xts_read(struct file *filp, 1521d632c047SIngo Franzki struct kobject *kobj, 1522d632c047SIngo Franzki struct bin_attribute *attr, 1523d632c047SIngo Franzki char *buf, loff_t off, 1524d632c047SIngo Franzki size_t count) 1525d632c047SIngo Franzki { 1526d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1527d632c047SIngo Franzki off, count); 1528d632c047SIngo Franzki } 1529d632c047SIngo Franzki 1530d632c047SIngo Franzki static ssize_t protkey_aes_256_xts_read(struct file *filp, 1531d632c047SIngo Franzki struct kobject *kobj, 1532d632c047SIngo Franzki struct bin_attribute *attr, 1533d632c047SIngo Franzki char *buf, loff_t off, 1534d632c047SIngo Franzki size_t count) 1535d632c047SIngo Franzki { 1536d632c047SIngo Franzki return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1537d632c047SIngo Franzki off, count); 1538d632c047SIngo Franzki } 1539d632c047SIngo Franzki 1540d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128, sizeof(struct protaeskeytoken)); 1541d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_192, sizeof(struct protaeskeytoken)); 1542d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256, sizeof(struct protaeskeytoken)); 1543d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_128_xts, 2 * sizeof(struct protaeskeytoken)); 1544d632c047SIngo Franzki static BIN_ATTR_RO(protkey_aes_256_xts, 2 * sizeof(struct protaeskeytoken)); 1545d632c047SIngo Franzki 1546d632c047SIngo Franzki static struct bin_attribute *protkey_attrs[] = { 1547d632c047SIngo Franzki &bin_attr_protkey_aes_128, 1548d632c047SIngo Franzki &bin_attr_protkey_aes_192, 1549d632c047SIngo Franzki &bin_attr_protkey_aes_256, 1550d632c047SIngo Franzki &bin_attr_protkey_aes_128_xts, 1551d632c047SIngo Franzki &bin_attr_protkey_aes_256_xts, 1552d632c047SIngo Franzki NULL 1553d632c047SIngo Franzki }; 1554d632c047SIngo Franzki 1555d632c047SIngo Franzki static struct attribute_group protkey_attr_group = { 1556d632c047SIngo Franzki .name = "protkey", 1557d632c047SIngo Franzki .bin_attrs = protkey_attrs, 1558d632c047SIngo Franzki }; 1559d632c047SIngo Franzki 1560af504452SIngo Franzki /* 1561af504452SIngo Franzki * Sysfs attribute read function for all secure key ccadata binary attributes. 1562af504452SIngo Franzki * The implementation can not deal with partial reads, because a new random 1563af504452SIngo Franzki * protected key blob is generated with each read. In case of partial reads 1564af504452SIngo Franzki * (i.e. off != 0 or count < key blob size) -EINVAL is returned. 1565af504452SIngo Franzki */ 1566af504452SIngo Franzki static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, 1567af504452SIngo Franzki loff_t off, size_t count) 1568af504452SIngo Franzki { 1569af504452SIngo Franzki int rc; 1570af504452SIngo Franzki 1571af504452SIngo Franzki if (off != 0 || count < sizeof(struct secaeskeytoken)) 1572af504452SIngo Franzki return -EINVAL; 1573af504452SIngo Franzki if (is_xts) 1574af504452SIngo Franzki if (count < 2 * sizeof(struct secaeskeytoken)) 1575af504452SIngo Franzki return -EINVAL; 1576af504452SIngo Franzki 1577af504452SIngo Franzki rc = pkey_genseckey(-1, -1, keytype, (struct pkey_seckey *)buf); 1578af504452SIngo Franzki if (rc) 1579af504452SIngo Franzki return rc; 1580af504452SIngo Franzki 1581af504452SIngo Franzki if (is_xts) { 1582af504452SIngo Franzki buf += sizeof(struct pkey_seckey); 1583af504452SIngo Franzki rc = pkey_genseckey(-1, -1, keytype, (struct pkey_seckey *)buf); 1584af504452SIngo Franzki if (rc) 1585af504452SIngo Franzki return rc; 1586af504452SIngo Franzki 1587af504452SIngo Franzki return 2 * sizeof(struct secaeskeytoken); 1588af504452SIngo Franzki } 1589af504452SIngo Franzki 1590af504452SIngo Franzki return sizeof(struct secaeskeytoken); 1591af504452SIngo Franzki } 1592af504452SIngo Franzki 1593af504452SIngo Franzki static ssize_t ccadata_aes_128_read(struct file *filp, 1594af504452SIngo Franzki struct kobject *kobj, 1595af504452SIngo Franzki struct bin_attribute *attr, 1596af504452SIngo Franzki char *buf, loff_t off, 1597af504452SIngo Franzki size_t count) 1598af504452SIngo Franzki { 1599af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, 1600af504452SIngo Franzki off, count); 1601af504452SIngo Franzki } 1602af504452SIngo Franzki 1603af504452SIngo Franzki static ssize_t ccadata_aes_192_read(struct file *filp, 1604af504452SIngo Franzki struct kobject *kobj, 1605af504452SIngo Franzki struct bin_attribute *attr, 1606af504452SIngo Franzki char *buf, loff_t off, 1607af504452SIngo Franzki size_t count) 1608af504452SIngo Franzki { 1609af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, 1610af504452SIngo Franzki off, count); 1611af504452SIngo Franzki } 1612af504452SIngo Franzki 1613af504452SIngo Franzki static ssize_t ccadata_aes_256_read(struct file *filp, 1614af504452SIngo Franzki struct kobject *kobj, 1615af504452SIngo Franzki struct bin_attribute *attr, 1616af504452SIngo Franzki char *buf, loff_t off, 1617af504452SIngo Franzki size_t count) 1618af504452SIngo Franzki { 1619af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, 1620af504452SIngo Franzki off, count); 1621af504452SIngo Franzki } 1622af504452SIngo Franzki 1623af504452SIngo Franzki static ssize_t ccadata_aes_128_xts_read(struct file *filp, 1624af504452SIngo Franzki struct kobject *kobj, 1625af504452SIngo Franzki struct bin_attribute *attr, 1626af504452SIngo Franzki char *buf, loff_t off, 1627af504452SIngo Franzki size_t count) 1628af504452SIngo Franzki { 1629af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, 1630af504452SIngo Franzki off, count); 1631af504452SIngo Franzki } 1632af504452SIngo Franzki 1633af504452SIngo Franzki static ssize_t ccadata_aes_256_xts_read(struct file *filp, 1634af504452SIngo Franzki struct kobject *kobj, 1635af504452SIngo Franzki struct bin_attribute *attr, 1636af504452SIngo Franzki char *buf, loff_t off, 1637af504452SIngo Franzki size_t count) 1638af504452SIngo Franzki { 1639af504452SIngo Franzki return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, 1640af504452SIngo Franzki off, count); 1641af504452SIngo Franzki } 1642af504452SIngo Franzki 1643af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128, sizeof(struct secaeskeytoken)); 1644af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_192, sizeof(struct secaeskeytoken)); 1645af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256, sizeof(struct secaeskeytoken)); 1646af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_128_xts, 2 * sizeof(struct secaeskeytoken)); 1647af504452SIngo Franzki static BIN_ATTR_RO(ccadata_aes_256_xts, 2 * sizeof(struct secaeskeytoken)); 1648af504452SIngo Franzki 1649af504452SIngo Franzki static struct bin_attribute *ccadata_attrs[] = { 1650af504452SIngo Franzki &bin_attr_ccadata_aes_128, 1651af504452SIngo Franzki &bin_attr_ccadata_aes_192, 1652af504452SIngo Franzki &bin_attr_ccadata_aes_256, 1653af504452SIngo Franzki &bin_attr_ccadata_aes_128_xts, 1654af504452SIngo Franzki &bin_attr_ccadata_aes_256_xts, 1655af504452SIngo Franzki NULL 1656af504452SIngo Franzki }; 1657af504452SIngo Franzki 1658af504452SIngo Franzki static struct attribute_group ccadata_attr_group = { 1659af504452SIngo Franzki .name = "ccadata", 1660af504452SIngo Franzki .bin_attrs = ccadata_attrs, 1661af504452SIngo Franzki }; 1662af504452SIngo Franzki 1663d632c047SIngo Franzki static const struct attribute_group *pkey_attr_groups[] = { 1664d632c047SIngo Franzki &protkey_attr_group, 1665af504452SIngo Franzki &ccadata_attr_group, 1666d632c047SIngo Franzki NULL, 1667d632c047SIngo Franzki }; 1668d632c047SIngo Franzki 1669e80d4af0SHarald Freudenberger static const struct file_operations pkey_fops = { 1670e80d4af0SHarald Freudenberger .owner = THIS_MODULE, 1671e80d4af0SHarald Freudenberger .open = nonseekable_open, 1672e80d4af0SHarald Freudenberger .llseek = no_llseek, 1673e80d4af0SHarald Freudenberger .unlocked_ioctl = pkey_unlocked_ioctl, 1674e80d4af0SHarald Freudenberger }; 1675e80d4af0SHarald Freudenberger 1676e80d4af0SHarald Freudenberger static struct miscdevice pkey_dev = { 1677e80d4af0SHarald Freudenberger .name = "pkey", 1678e80d4af0SHarald Freudenberger .minor = MISC_DYNAMIC_MINOR, 1679e80d4af0SHarald Freudenberger .mode = 0666, 1680e80d4af0SHarald Freudenberger .fops = &pkey_fops, 1681d632c047SIngo Franzki .groups = pkey_attr_groups, 1682e80d4af0SHarald Freudenberger }; 1683e80d4af0SHarald Freudenberger 1684e80d4af0SHarald Freudenberger /* 1685e80d4af0SHarald Freudenberger * Module init 1686e80d4af0SHarald Freudenberger */ 1687cb4ef3c2SHeiko Carstens static int __init pkey_init(void) 1688e80d4af0SHarald Freudenberger { 1689f822ad2cSHarald Freudenberger cpacf_mask_t kmc_functions; 1690e80d4af0SHarald Freudenberger 1691f822ad2cSHarald Freudenberger /* 1692f822ad2cSHarald Freudenberger * The pckmo instruction should be available - even if we don't 1693f822ad2cSHarald Freudenberger * actually invoke it. This instruction comes with MSA 3 which 1694f822ad2cSHarald Freudenberger * is also the minimum level for the kmc instructions which 1695f822ad2cSHarald Freudenberger * are able to work with protected keys. 1696f822ad2cSHarald Freudenberger */ 1697e80d4af0SHarald Freudenberger if (!cpacf_query(CPACF_PCKMO, &pckmo_functions)) 1698*58443b67SDavid Hildenbrand return -ENODEV; 1699e80d4af0SHarald Freudenberger 1700cb26b9ffSIngo Franzki /* check for kmc instructions available */ 1701cb26b9ffSIngo Franzki if (!cpacf_query(CPACF_KMC, &kmc_functions)) 1702*58443b67SDavid Hildenbrand return -ENODEV; 1703cb26b9ffSIngo Franzki if (!cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_128) || 1704cb26b9ffSIngo Franzki !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_192) || 1705cb26b9ffSIngo Franzki !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_256)) 1706*58443b67SDavid Hildenbrand return -ENODEV; 1707cb26b9ffSIngo Franzki 1708e80d4af0SHarald Freudenberger pkey_debug_init(); 1709e80d4af0SHarald Freudenberger 1710e80d4af0SHarald Freudenberger return misc_register(&pkey_dev); 1711e80d4af0SHarald Freudenberger } 1712e80d4af0SHarald Freudenberger 1713e80d4af0SHarald Freudenberger /* 1714e80d4af0SHarald Freudenberger * Module exit 1715e80d4af0SHarald Freudenberger */ 1716e80d4af0SHarald Freudenberger static void __exit pkey_exit(void) 1717e80d4af0SHarald Freudenberger { 1718e80d4af0SHarald Freudenberger misc_deregister(&pkey_dev); 1719e80d4af0SHarald Freudenberger mkvp_cache_free(); 1720e80d4af0SHarald Freudenberger pkey_debug_exit(); 1721e80d4af0SHarald Freudenberger } 1722e80d4af0SHarald Freudenberger 172363c19be0SIngo Franzki module_cpu_feature_match(MSA, pkey_init); 1724e80d4af0SHarald Freudenberger module_exit(pkey_exit); 1725