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> 19*a45a5c7dSIngo Franzki #include <linux/random.h> 20e80d4af0SHarald Freudenberger #include <asm/zcrypt.h> 21e80d4af0SHarald Freudenberger #include <asm/cpacf.h> 22e80d4af0SHarald Freudenberger #include <asm/pkey.h> 23e80d4af0SHarald Freudenberger 24e80d4af0SHarald Freudenberger #include "zcrypt_api.h" 25e80d4af0SHarald Freudenberger 26e80d4af0SHarald Freudenberger MODULE_LICENSE("GPL"); 27e80d4af0SHarald Freudenberger MODULE_AUTHOR("IBM Corporation"); 28e80d4af0SHarald Freudenberger MODULE_DESCRIPTION("s390 protected key interface"); 29e80d4af0SHarald Freudenberger 30e80d4af0SHarald Freudenberger /* Size of parameter block used for all cca requests/replies */ 31e80d4af0SHarald Freudenberger #define PARMBSIZE 512 32e80d4af0SHarald Freudenberger 33e80d4af0SHarald Freudenberger /* Size of vardata block used for some of the cca requests/replies */ 34e80d4af0SHarald Freudenberger #define VARDATASIZE 4096 35e80d4af0SHarald Freudenberger 36e80d4af0SHarald Freudenberger /* 37e80d4af0SHarald Freudenberger * debug feature data and functions 38e80d4af0SHarald Freudenberger */ 39e80d4af0SHarald Freudenberger 40e80d4af0SHarald Freudenberger static debug_info_t *debug_info; 41e80d4af0SHarald Freudenberger 42e80d4af0SHarald Freudenberger #define DEBUG_DBG(...) debug_sprintf_event(debug_info, 6, ##__VA_ARGS__) 43e80d4af0SHarald Freudenberger #define DEBUG_INFO(...) debug_sprintf_event(debug_info, 5, ##__VA_ARGS__) 44e80d4af0SHarald Freudenberger #define DEBUG_WARN(...) debug_sprintf_event(debug_info, 4, ##__VA_ARGS__) 45e80d4af0SHarald Freudenberger #define DEBUG_ERR(...) debug_sprintf_event(debug_info, 3, ##__VA_ARGS__) 46e80d4af0SHarald Freudenberger 47e80d4af0SHarald Freudenberger static void __init pkey_debug_init(void) 48e80d4af0SHarald Freudenberger { 49e80d4af0SHarald Freudenberger debug_info = debug_register("pkey", 1, 1, 4 * sizeof(long)); 50e80d4af0SHarald Freudenberger debug_register_view(debug_info, &debug_sprintf_view); 51e80d4af0SHarald Freudenberger debug_set_level(debug_info, 3); 52e80d4af0SHarald Freudenberger } 53e80d4af0SHarald Freudenberger 54e80d4af0SHarald Freudenberger static void __exit pkey_debug_exit(void) 55e80d4af0SHarald Freudenberger { 56e80d4af0SHarald Freudenberger debug_unregister(debug_info); 57e80d4af0SHarald Freudenberger } 58e80d4af0SHarald Freudenberger 59e80d4af0SHarald Freudenberger /* inside view of a secure key token (only type 0x01 version 0x04) */ 60e80d4af0SHarald Freudenberger struct secaeskeytoken { 61e80d4af0SHarald Freudenberger u8 type; /* 0x01 for internal key token */ 62e80d4af0SHarald Freudenberger u8 res0[3]; 63e80d4af0SHarald Freudenberger u8 version; /* should be 0x04 */ 64e80d4af0SHarald Freudenberger u8 res1[1]; 65e80d4af0SHarald Freudenberger u8 flag; /* key flags */ 66e80d4af0SHarald Freudenberger u8 res2[1]; 67e80d4af0SHarald Freudenberger u64 mkvp; /* master key verification pattern */ 68e80d4af0SHarald Freudenberger u8 key[32]; /* key value (encrypted) */ 69e80d4af0SHarald Freudenberger u8 cv[8]; /* control vector */ 70e80d4af0SHarald Freudenberger u16 bitsize; /* key bit size */ 71e80d4af0SHarald Freudenberger u16 keysize; /* key byte size */ 72e80d4af0SHarald Freudenberger u8 tvv[4]; /* token validation value */ 73e80d4af0SHarald Freudenberger } __packed; 74e80d4af0SHarald Freudenberger 75e80d4af0SHarald Freudenberger /* 76e80d4af0SHarald Freudenberger * Simple check if the token is a valid CCA secure AES key 77e80d4af0SHarald Freudenberger * token. If keybitsize is given, the bitsize of the key is 78e80d4af0SHarald Freudenberger * also checked. Returns 0 on success or errno value on failure. 79e80d4af0SHarald Freudenberger */ 80e61a6134SHarald Freudenberger static int check_secaeskeytoken(const u8 *token, int keybitsize) 81e80d4af0SHarald Freudenberger { 82e80d4af0SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *) token; 83e80d4af0SHarald Freudenberger 84e80d4af0SHarald Freudenberger if (t->type != 0x01) { 85e80d4af0SHarald Freudenberger DEBUG_ERR( 86ac2b96f3SHarald Freudenberger "%s secure token check failed, type mismatch 0x%02x != 0x01\n", 87ac2b96f3SHarald Freudenberger __func__, (int) t->type); 88e80d4af0SHarald Freudenberger return -EINVAL; 89e80d4af0SHarald Freudenberger } 90e80d4af0SHarald Freudenberger if (t->version != 0x04) { 91e80d4af0SHarald Freudenberger DEBUG_ERR( 92ac2b96f3SHarald Freudenberger "%s secure token check failed, version mismatch 0x%02x != 0x04\n", 93ac2b96f3SHarald Freudenberger __func__, (int) t->version); 94e80d4af0SHarald Freudenberger return -EINVAL; 95e80d4af0SHarald Freudenberger } 96e80d4af0SHarald Freudenberger if (keybitsize > 0 && t->bitsize != keybitsize) { 97e80d4af0SHarald Freudenberger DEBUG_ERR( 98ac2b96f3SHarald Freudenberger "%s secure token check failed, bitsize mismatch %d != %d\n", 99ac2b96f3SHarald Freudenberger __func__, (int) t->bitsize, keybitsize); 100e80d4af0SHarald Freudenberger return -EINVAL; 101e80d4af0SHarald Freudenberger } 102e80d4af0SHarald Freudenberger 103e80d4af0SHarald Freudenberger return 0; 104e80d4af0SHarald Freudenberger } 105e80d4af0SHarald Freudenberger 106e80d4af0SHarald Freudenberger /* 107e80d4af0SHarald Freudenberger * Allocate consecutive memory for request CPRB, request param 108e80d4af0SHarald Freudenberger * block, reply CPRB and reply param block and fill in values 109e80d4af0SHarald Freudenberger * for the common fields. Returns 0 on success or errno value 110e80d4af0SHarald Freudenberger * on failure. 111e80d4af0SHarald Freudenberger */ 112e80d4af0SHarald Freudenberger static int alloc_and_prep_cprbmem(size_t paramblen, 113e80d4af0SHarald Freudenberger u8 **pcprbmem, 114e80d4af0SHarald Freudenberger struct CPRBX **preqCPRB, 115e80d4af0SHarald Freudenberger struct CPRBX **prepCPRB) 116e80d4af0SHarald Freudenberger { 117e80d4af0SHarald Freudenberger u8 *cprbmem; 118e80d4af0SHarald Freudenberger size_t cprbplusparamblen = sizeof(struct CPRBX) + paramblen; 119e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 120e80d4af0SHarald Freudenberger 121e80d4af0SHarald Freudenberger /* 122e80d4af0SHarald Freudenberger * allocate consecutive memory for request CPRB, request param 123e80d4af0SHarald Freudenberger * block, reply CPRB and reply param block 124e80d4af0SHarald Freudenberger */ 1256396bb22SKees Cook cprbmem = kcalloc(2, cprbplusparamblen, GFP_KERNEL); 126e80d4af0SHarald Freudenberger if (!cprbmem) 127e80d4af0SHarald Freudenberger return -ENOMEM; 128e80d4af0SHarald Freudenberger 129e80d4af0SHarald Freudenberger preqcblk = (struct CPRBX *) cprbmem; 130e80d4af0SHarald Freudenberger prepcblk = (struct CPRBX *) (cprbmem + cprbplusparamblen); 131e80d4af0SHarald Freudenberger 132e80d4af0SHarald Freudenberger /* fill request cprb struct */ 133e80d4af0SHarald Freudenberger preqcblk->cprb_len = sizeof(struct CPRBX); 134e80d4af0SHarald Freudenberger preqcblk->cprb_ver_id = 0x02; 135e80d4af0SHarald Freudenberger memcpy(preqcblk->func_id, "T2", 2); 136e80d4af0SHarald Freudenberger preqcblk->rpl_msgbl = cprbplusparamblen; 137e80d4af0SHarald Freudenberger if (paramblen) { 138e80d4af0SHarald Freudenberger preqcblk->req_parmb = 139e80d4af0SHarald Freudenberger ((u8 *) preqcblk) + sizeof(struct CPRBX); 140e80d4af0SHarald Freudenberger preqcblk->rpl_parmb = 141e80d4af0SHarald Freudenberger ((u8 *) prepcblk) + sizeof(struct CPRBX); 142e80d4af0SHarald Freudenberger } 143e80d4af0SHarald Freudenberger 144e80d4af0SHarald Freudenberger *pcprbmem = cprbmem; 145e80d4af0SHarald Freudenberger *preqCPRB = preqcblk; 146e80d4af0SHarald Freudenberger *prepCPRB = prepcblk; 147e80d4af0SHarald Freudenberger 148e80d4af0SHarald Freudenberger return 0; 149e80d4af0SHarald Freudenberger } 150e80d4af0SHarald Freudenberger 151e80d4af0SHarald Freudenberger /* 152e80d4af0SHarald Freudenberger * Free the cprb memory allocated with the function above. 153e80d4af0SHarald Freudenberger * If the scrub value is not zero, the memory is filled 154e80d4af0SHarald Freudenberger * with zeros before freeing (useful if there was some 155e80d4af0SHarald Freudenberger * clear key material in there). 156e80d4af0SHarald Freudenberger */ 157e80d4af0SHarald Freudenberger static void free_cprbmem(void *mem, size_t paramblen, int scrub) 158e80d4af0SHarald Freudenberger { 159e80d4af0SHarald Freudenberger if (scrub) 160e80d4af0SHarald Freudenberger memzero_explicit(mem, 2 * (sizeof(struct CPRBX) + paramblen)); 161e80d4af0SHarald Freudenberger kfree(mem); 162e80d4af0SHarald Freudenberger } 163e80d4af0SHarald Freudenberger 164e80d4af0SHarald Freudenberger /* 165e80d4af0SHarald Freudenberger * Helper function to prepare the xcrb struct 166e80d4af0SHarald Freudenberger */ 167e80d4af0SHarald Freudenberger static inline void prep_xcrb(struct ica_xcRB *pxcrb, 168e80d4af0SHarald Freudenberger u16 cardnr, 169e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, 170e80d4af0SHarald Freudenberger struct CPRBX *prepcblk) 171e80d4af0SHarald Freudenberger { 172e80d4af0SHarald Freudenberger memset(pxcrb, 0, sizeof(*pxcrb)); 173e80d4af0SHarald Freudenberger pxcrb->agent_ID = 0x4341; /* 'CA' */ 174e80d4af0SHarald Freudenberger pxcrb->user_defined = (cardnr == 0xFFFF ? AUTOSELECT : cardnr); 175e80d4af0SHarald Freudenberger pxcrb->request_control_blk_length = 176e80d4af0SHarald Freudenberger preqcblk->cprb_len + preqcblk->req_parml; 1777a003637SHeiko Carstens pxcrb->request_control_blk_addr = (void __user *) preqcblk; 178e80d4af0SHarald Freudenberger pxcrb->reply_control_blk_length = preqcblk->rpl_msgbl; 1797a003637SHeiko Carstens pxcrb->reply_control_blk_addr = (void __user *) prepcblk; 180e80d4af0SHarald Freudenberger } 181e80d4af0SHarald Freudenberger 182e80d4af0SHarald Freudenberger /* 183e80d4af0SHarald Freudenberger * Helper function which calls zcrypt_send_cprb with 184e80d4af0SHarald Freudenberger * memory management segment adjusted to kernel space 185e80d4af0SHarald Freudenberger * so that the copy_from_user called within this 186e80d4af0SHarald Freudenberger * function do in fact copy from kernel space. 187e80d4af0SHarald Freudenberger */ 188e80d4af0SHarald Freudenberger static inline int _zcrypt_send_cprb(struct ica_xcRB *xcrb) 189e80d4af0SHarald Freudenberger { 190e80d4af0SHarald Freudenberger int rc; 191e80d4af0SHarald Freudenberger mm_segment_t old_fs = get_fs(); 192e80d4af0SHarald Freudenberger 193e80d4af0SHarald Freudenberger set_fs(KERNEL_DS); 194e80d4af0SHarald Freudenberger rc = zcrypt_send_cprb(xcrb); 195e80d4af0SHarald Freudenberger set_fs(old_fs); 196e80d4af0SHarald Freudenberger 197e80d4af0SHarald Freudenberger return rc; 198e80d4af0SHarald Freudenberger } 199e80d4af0SHarald Freudenberger 200e80d4af0SHarald Freudenberger /* 201e80d4af0SHarald Freudenberger * Generate (random) AES secure key. 202e80d4af0SHarald Freudenberger */ 203e80d4af0SHarald Freudenberger int pkey_genseckey(u16 cardnr, u16 domain, 204e80d4af0SHarald Freudenberger u32 keytype, struct pkey_seckey *seckey) 205e80d4af0SHarald Freudenberger { 206e80d4af0SHarald Freudenberger int i, rc, keysize; 207e80d4af0SHarald Freudenberger int seckeysize; 208e80d4af0SHarald Freudenberger u8 *mem; 209e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 210e80d4af0SHarald Freudenberger struct ica_xcRB xcrb; 211e80d4af0SHarald Freudenberger struct kgreqparm { 212e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 213e80d4af0SHarald Freudenberger u16 rule_array_len; 214e80d4af0SHarald Freudenberger struct lv1 { 215e80d4af0SHarald Freudenberger u16 len; 216e80d4af0SHarald Freudenberger char key_form[8]; 217e80d4af0SHarald Freudenberger char key_length[8]; 218e80d4af0SHarald Freudenberger char key_type1[8]; 219e80d4af0SHarald Freudenberger char key_type2[8]; 220e80d4af0SHarald Freudenberger } lv1; 221e80d4af0SHarald Freudenberger struct lv2 { 222e80d4af0SHarald Freudenberger u16 len; 223e80d4af0SHarald Freudenberger struct keyid { 224e80d4af0SHarald Freudenberger u16 len; 225e80d4af0SHarald Freudenberger u16 attr; 226e80d4af0SHarald Freudenberger u8 data[SECKEYBLOBSIZE]; 227e80d4af0SHarald Freudenberger } keyid[6]; 228e80d4af0SHarald Freudenberger } lv2; 229e80d4af0SHarald Freudenberger } *preqparm; 230e80d4af0SHarald Freudenberger struct kgrepparm { 231e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 232e80d4af0SHarald Freudenberger u16 rule_array_len; 233e80d4af0SHarald Freudenberger struct lv3 { 234e80d4af0SHarald Freudenberger u16 len; 235e80d4af0SHarald Freudenberger u16 keyblocklen; 236e80d4af0SHarald Freudenberger struct { 237e80d4af0SHarald Freudenberger u16 toklen; 238e80d4af0SHarald Freudenberger u16 tokattr; 239e80d4af0SHarald Freudenberger u8 tok[0]; 240e80d4af0SHarald Freudenberger /* ... some more data ... */ 241e80d4af0SHarald Freudenberger } keyblock; 242e80d4af0SHarald Freudenberger } lv3; 243e80d4af0SHarald Freudenberger } *prepparm; 244e80d4af0SHarald Freudenberger 245e80d4af0SHarald Freudenberger /* get already prepared memory for 2 cprbs with param block each */ 246e80d4af0SHarald Freudenberger rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); 247e80d4af0SHarald Freudenberger if (rc) 248e80d4af0SHarald Freudenberger return rc; 249e80d4af0SHarald Freudenberger 250e80d4af0SHarald Freudenberger /* fill request cprb struct */ 251e80d4af0SHarald Freudenberger preqcblk->domain = domain; 252e80d4af0SHarald Freudenberger 253e80d4af0SHarald Freudenberger /* fill request cprb param block with KG request */ 254e80d4af0SHarald Freudenberger preqparm = (struct kgreqparm *) preqcblk->req_parmb; 255e80d4af0SHarald Freudenberger memcpy(preqparm->subfunc_code, "KG", 2); 256e80d4af0SHarald Freudenberger preqparm->rule_array_len = sizeof(preqparm->rule_array_len); 257e80d4af0SHarald Freudenberger preqparm->lv1.len = sizeof(struct lv1); 258e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_form, "OP ", 8); 259e80d4af0SHarald Freudenberger switch (keytype) { 260e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 261e80d4af0SHarald Freudenberger keysize = 16; 262e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_length, "KEYLN16 ", 8); 263e80d4af0SHarald Freudenberger break; 264e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 265e80d4af0SHarald Freudenberger keysize = 24; 266e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_length, "KEYLN24 ", 8); 267e80d4af0SHarald Freudenberger break; 268e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 269e80d4af0SHarald Freudenberger keysize = 32; 270e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_length, "KEYLN32 ", 8); 271e80d4af0SHarald Freudenberger break; 272e80d4af0SHarald Freudenberger default: 273e80d4af0SHarald Freudenberger DEBUG_ERR( 274ac2b96f3SHarald Freudenberger "%s unknown/unsupported keytype %d\n", 275ac2b96f3SHarald Freudenberger __func__, keytype); 276e80d4af0SHarald Freudenberger rc = -EINVAL; 277e80d4af0SHarald Freudenberger goto out; 278e80d4af0SHarald Freudenberger } 279e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.key_type1, "AESDATA ", 8); 280e80d4af0SHarald Freudenberger preqparm->lv2.len = sizeof(struct lv2); 281e80d4af0SHarald Freudenberger for (i = 0; i < 6; i++) { 282e80d4af0SHarald Freudenberger preqparm->lv2.keyid[i].len = sizeof(struct keyid); 283e80d4af0SHarald Freudenberger preqparm->lv2.keyid[i].attr = (i == 2 ? 0x30 : 0x10); 284e80d4af0SHarald Freudenberger } 285e80d4af0SHarald Freudenberger preqcblk->req_parml = sizeof(struct kgreqparm); 286e80d4af0SHarald Freudenberger 287e80d4af0SHarald Freudenberger /* fill xcrb struct */ 288e80d4af0SHarald Freudenberger prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); 289e80d4af0SHarald Freudenberger 290e80d4af0SHarald Freudenberger /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ 291e80d4af0SHarald Freudenberger rc = _zcrypt_send_cprb(&xcrb); 292e80d4af0SHarald Freudenberger if (rc) { 293e80d4af0SHarald Freudenberger DEBUG_ERR( 294ac2b96f3SHarald Freudenberger "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", 295ac2b96f3SHarald Freudenberger __func__, (int) cardnr, (int) domain, rc); 296e80d4af0SHarald Freudenberger goto out; 297e80d4af0SHarald Freudenberger } 298e80d4af0SHarald Freudenberger 299e80d4af0SHarald Freudenberger /* check response returncode and reasoncode */ 300e80d4af0SHarald Freudenberger if (prepcblk->ccp_rtcode != 0) { 301e80d4af0SHarald Freudenberger DEBUG_ERR( 302ac2b96f3SHarald Freudenberger "%s secure key generate failure, card response %d/%d\n", 303ac2b96f3SHarald Freudenberger __func__, 304e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rtcode, 305e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rscode); 306e80d4af0SHarald Freudenberger rc = -EIO; 307e80d4af0SHarald Freudenberger goto out; 308e80d4af0SHarald Freudenberger } 309e80d4af0SHarald Freudenberger 310e80d4af0SHarald Freudenberger /* process response cprb param block */ 311e80d4af0SHarald Freudenberger prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); 312e80d4af0SHarald Freudenberger prepparm = (struct kgrepparm *) prepcblk->rpl_parmb; 313e80d4af0SHarald Freudenberger 314e80d4af0SHarald Freudenberger /* check length of the returned secure key token */ 315e80d4af0SHarald Freudenberger seckeysize = prepparm->lv3.keyblock.toklen 316e80d4af0SHarald Freudenberger - sizeof(prepparm->lv3.keyblock.toklen) 317e80d4af0SHarald Freudenberger - sizeof(prepparm->lv3.keyblock.tokattr); 318e80d4af0SHarald Freudenberger if (seckeysize != SECKEYBLOBSIZE) { 319e80d4af0SHarald Freudenberger DEBUG_ERR( 320ac2b96f3SHarald Freudenberger "%s secure token size mismatch %d != %d bytes\n", 321ac2b96f3SHarald Freudenberger __func__, seckeysize, SECKEYBLOBSIZE); 322e80d4af0SHarald Freudenberger rc = -EIO; 323e80d4af0SHarald Freudenberger goto out; 324e80d4af0SHarald Freudenberger } 325e80d4af0SHarald Freudenberger 326e80d4af0SHarald Freudenberger /* check secure key token */ 327e80d4af0SHarald Freudenberger rc = check_secaeskeytoken(prepparm->lv3.keyblock.tok, 8*keysize); 328e80d4af0SHarald Freudenberger if (rc) { 329e80d4af0SHarald Freudenberger rc = -EIO; 330e80d4af0SHarald Freudenberger goto out; 331e80d4af0SHarald Freudenberger } 332e80d4af0SHarald Freudenberger 333e80d4af0SHarald Freudenberger /* copy the generated secure key token */ 334e80d4af0SHarald Freudenberger memcpy(seckey->seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE); 335e80d4af0SHarald Freudenberger 336e80d4af0SHarald Freudenberger out: 337e80d4af0SHarald Freudenberger free_cprbmem(mem, PARMBSIZE, 0); 338e80d4af0SHarald Freudenberger return rc; 339e80d4af0SHarald Freudenberger } 340e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_genseckey); 341e80d4af0SHarald Freudenberger 342e80d4af0SHarald Freudenberger /* 343e80d4af0SHarald Freudenberger * Generate an AES secure key with given key value. 344e80d4af0SHarald Freudenberger */ 345e80d4af0SHarald Freudenberger int pkey_clr2seckey(u16 cardnr, u16 domain, u32 keytype, 346e80d4af0SHarald Freudenberger const struct pkey_clrkey *clrkey, 347e80d4af0SHarald Freudenberger struct pkey_seckey *seckey) 348e80d4af0SHarald Freudenberger { 349e80d4af0SHarald Freudenberger int rc, keysize, seckeysize; 350e80d4af0SHarald Freudenberger u8 *mem; 351e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 352e80d4af0SHarald Freudenberger struct ica_xcRB xcrb; 353e80d4af0SHarald Freudenberger struct cmreqparm { 354e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 355e80d4af0SHarald Freudenberger u16 rule_array_len; 356e80d4af0SHarald Freudenberger char rule_array[8]; 357e80d4af0SHarald Freudenberger struct lv1 { 358e80d4af0SHarald Freudenberger u16 len; 359e80d4af0SHarald Freudenberger u8 clrkey[0]; 360e80d4af0SHarald Freudenberger } lv1; 361e80d4af0SHarald Freudenberger struct lv2 { 362e80d4af0SHarald Freudenberger u16 len; 363e80d4af0SHarald Freudenberger struct keyid { 364e80d4af0SHarald Freudenberger u16 len; 365e80d4af0SHarald Freudenberger u16 attr; 366e80d4af0SHarald Freudenberger u8 data[SECKEYBLOBSIZE]; 367e80d4af0SHarald Freudenberger } keyid; 368e80d4af0SHarald Freudenberger } lv2; 369e80d4af0SHarald Freudenberger } *preqparm; 370e80d4af0SHarald Freudenberger struct lv2 *plv2; 371e80d4af0SHarald Freudenberger struct cmrepparm { 372e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 373e80d4af0SHarald Freudenberger u16 rule_array_len; 374e80d4af0SHarald Freudenberger struct lv3 { 375e80d4af0SHarald Freudenberger u16 len; 376e80d4af0SHarald Freudenberger u16 keyblocklen; 377e80d4af0SHarald Freudenberger struct { 378e80d4af0SHarald Freudenberger u16 toklen; 379e80d4af0SHarald Freudenberger u16 tokattr; 380e80d4af0SHarald Freudenberger u8 tok[0]; 381e80d4af0SHarald Freudenberger /* ... some more data ... */ 382e80d4af0SHarald Freudenberger } keyblock; 383e80d4af0SHarald Freudenberger } lv3; 384e80d4af0SHarald Freudenberger } *prepparm; 385e80d4af0SHarald Freudenberger 386e80d4af0SHarald Freudenberger /* get already prepared memory for 2 cprbs with param block each */ 387e80d4af0SHarald Freudenberger rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); 388e80d4af0SHarald Freudenberger if (rc) 389e80d4af0SHarald Freudenberger return rc; 390e80d4af0SHarald Freudenberger 391e80d4af0SHarald Freudenberger /* fill request cprb struct */ 392e80d4af0SHarald Freudenberger preqcblk->domain = domain; 393e80d4af0SHarald Freudenberger 394e80d4af0SHarald Freudenberger /* fill request cprb param block with CM request */ 395e80d4af0SHarald Freudenberger preqparm = (struct cmreqparm *) preqcblk->req_parmb; 396e80d4af0SHarald Freudenberger memcpy(preqparm->subfunc_code, "CM", 2); 397e80d4af0SHarald Freudenberger memcpy(preqparm->rule_array, "AES ", 8); 398e80d4af0SHarald Freudenberger preqparm->rule_array_len = 399e80d4af0SHarald Freudenberger sizeof(preqparm->rule_array_len) + sizeof(preqparm->rule_array); 400e80d4af0SHarald Freudenberger switch (keytype) { 401e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 402e80d4af0SHarald Freudenberger keysize = 16; 403e80d4af0SHarald Freudenberger break; 404e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 405e80d4af0SHarald Freudenberger keysize = 24; 406e80d4af0SHarald Freudenberger break; 407e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 408e80d4af0SHarald Freudenberger keysize = 32; 409e80d4af0SHarald Freudenberger break; 410e80d4af0SHarald Freudenberger default: 411e80d4af0SHarald Freudenberger DEBUG_ERR( 412ac2b96f3SHarald Freudenberger "%s unknown/unsupported keytype %d\n", 413ac2b96f3SHarald Freudenberger __func__, keytype); 414e80d4af0SHarald Freudenberger rc = -EINVAL; 415e80d4af0SHarald Freudenberger goto out; 416e80d4af0SHarald Freudenberger } 417e80d4af0SHarald Freudenberger preqparm->lv1.len = sizeof(struct lv1) + keysize; 418e80d4af0SHarald Freudenberger memcpy(preqparm->lv1.clrkey, clrkey->clrkey, keysize); 419e80d4af0SHarald Freudenberger plv2 = (struct lv2 *) (((u8 *) &preqparm->lv2) + keysize); 420e80d4af0SHarald Freudenberger plv2->len = sizeof(struct lv2); 421e80d4af0SHarald Freudenberger plv2->keyid.len = sizeof(struct keyid); 422e80d4af0SHarald Freudenberger plv2->keyid.attr = 0x30; 423e80d4af0SHarald Freudenberger preqcblk->req_parml = sizeof(struct cmreqparm) + keysize; 424e80d4af0SHarald Freudenberger 425e80d4af0SHarald Freudenberger /* fill xcrb struct */ 426e80d4af0SHarald Freudenberger prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); 427e80d4af0SHarald Freudenberger 428e80d4af0SHarald Freudenberger /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ 429e80d4af0SHarald Freudenberger rc = _zcrypt_send_cprb(&xcrb); 430e80d4af0SHarald Freudenberger if (rc) { 431e80d4af0SHarald Freudenberger DEBUG_ERR( 432ac2b96f3SHarald Freudenberger "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", 433ac2b96f3SHarald Freudenberger __func__, (int) cardnr, (int) domain, rc); 434e80d4af0SHarald Freudenberger goto out; 435e80d4af0SHarald Freudenberger } 436e80d4af0SHarald Freudenberger 437e80d4af0SHarald Freudenberger /* check response returncode and reasoncode */ 438e80d4af0SHarald Freudenberger if (prepcblk->ccp_rtcode != 0) { 439e80d4af0SHarald Freudenberger DEBUG_ERR( 440ac2b96f3SHarald Freudenberger "%s clear key import failure, card response %d/%d\n", 441ac2b96f3SHarald Freudenberger __func__, 442e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rtcode, 443e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rscode); 444e80d4af0SHarald Freudenberger rc = -EIO; 445e80d4af0SHarald Freudenberger goto out; 446e80d4af0SHarald Freudenberger } 447e80d4af0SHarald Freudenberger 448e80d4af0SHarald Freudenberger /* process response cprb param block */ 449e80d4af0SHarald Freudenberger prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); 450e80d4af0SHarald Freudenberger prepparm = (struct cmrepparm *) prepcblk->rpl_parmb; 451e80d4af0SHarald Freudenberger 452e80d4af0SHarald Freudenberger /* check length of the returned secure key token */ 453e80d4af0SHarald Freudenberger seckeysize = prepparm->lv3.keyblock.toklen 454e80d4af0SHarald Freudenberger - sizeof(prepparm->lv3.keyblock.toklen) 455e80d4af0SHarald Freudenberger - sizeof(prepparm->lv3.keyblock.tokattr); 456e80d4af0SHarald Freudenberger if (seckeysize != SECKEYBLOBSIZE) { 457e80d4af0SHarald Freudenberger DEBUG_ERR( 458ac2b96f3SHarald Freudenberger "%s secure token size mismatch %d != %d bytes\n", 459ac2b96f3SHarald Freudenberger __func__, seckeysize, SECKEYBLOBSIZE); 460e80d4af0SHarald Freudenberger rc = -EIO; 461e80d4af0SHarald Freudenberger goto out; 462e80d4af0SHarald Freudenberger } 463e80d4af0SHarald Freudenberger 464e80d4af0SHarald Freudenberger /* check secure key token */ 465e80d4af0SHarald Freudenberger rc = check_secaeskeytoken(prepparm->lv3.keyblock.tok, 8*keysize); 466e80d4af0SHarald Freudenberger if (rc) { 467e80d4af0SHarald Freudenberger rc = -EIO; 468e80d4af0SHarald Freudenberger goto out; 469e80d4af0SHarald Freudenberger } 470e80d4af0SHarald Freudenberger 471e80d4af0SHarald Freudenberger /* copy the generated secure key token */ 472e80d4af0SHarald Freudenberger memcpy(seckey->seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE); 473e80d4af0SHarald Freudenberger 474e80d4af0SHarald Freudenberger out: 475e80d4af0SHarald Freudenberger free_cprbmem(mem, PARMBSIZE, 1); 476e80d4af0SHarald Freudenberger return rc; 477e80d4af0SHarald Freudenberger } 478e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_clr2seckey); 479e80d4af0SHarald Freudenberger 480e80d4af0SHarald Freudenberger /* 481e80d4af0SHarald Freudenberger * Derive a proteced key from the secure key blob. 482e80d4af0SHarald Freudenberger */ 483e80d4af0SHarald Freudenberger int pkey_sec2protkey(u16 cardnr, u16 domain, 484e80d4af0SHarald Freudenberger const struct pkey_seckey *seckey, 485e80d4af0SHarald Freudenberger struct pkey_protkey *protkey) 486e80d4af0SHarald Freudenberger { 487e80d4af0SHarald Freudenberger int rc; 488e80d4af0SHarald Freudenberger u8 *mem; 489e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 490e80d4af0SHarald Freudenberger struct ica_xcRB xcrb; 491e80d4af0SHarald Freudenberger struct uskreqparm { 492e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 493e80d4af0SHarald Freudenberger u16 rule_array_len; 494e80d4af0SHarald Freudenberger struct lv1 { 495e80d4af0SHarald Freudenberger u16 len; 496e80d4af0SHarald Freudenberger u16 attr_len; 497e80d4af0SHarald Freudenberger u16 attr_flags; 498e80d4af0SHarald Freudenberger } lv1; 499e80d4af0SHarald Freudenberger struct lv2 { 500e80d4af0SHarald Freudenberger u16 len; 501e80d4af0SHarald Freudenberger u16 attr_len; 502e80d4af0SHarald Freudenberger u16 attr_flags; 503e80d4af0SHarald Freudenberger u8 token[0]; /* cca secure key token */ 504e80d4af0SHarald Freudenberger } lv2 __packed; 505e80d4af0SHarald Freudenberger } *preqparm; 506e80d4af0SHarald Freudenberger struct uskrepparm { 507e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 508e80d4af0SHarald Freudenberger u16 rule_array_len; 509e80d4af0SHarald Freudenberger struct lv3 { 510e80d4af0SHarald Freudenberger u16 len; 511e80d4af0SHarald Freudenberger u16 attr_len; 512e80d4af0SHarald Freudenberger u16 attr_flags; 513e80d4af0SHarald Freudenberger struct cpacfkeyblock { 514e80d4af0SHarald Freudenberger u8 version; /* version of this struct */ 515e80d4af0SHarald Freudenberger u8 flags[2]; 516e80d4af0SHarald Freudenberger u8 algo; 517e80d4af0SHarald Freudenberger u8 form; 518e80d4af0SHarald Freudenberger u8 pad1[3]; 519e80d4af0SHarald Freudenberger u16 keylen; 520e80d4af0SHarald Freudenberger u8 key[64]; /* the key (keylen bytes) */ 521e80d4af0SHarald Freudenberger u16 keyattrlen; 522e80d4af0SHarald Freudenberger u8 keyattr[32]; 523e80d4af0SHarald Freudenberger u8 pad2[1]; 524e80d4af0SHarald Freudenberger u8 vptype; 525e80d4af0SHarald Freudenberger u8 vp[32]; /* verification pattern */ 526e80d4af0SHarald Freudenberger } keyblock; 527e80d4af0SHarald Freudenberger } lv3 __packed; 528e80d4af0SHarald Freudenberger } *prepparm; 529e80d4af0SHarald Freudenberger 530e80d4af0SHarald Freudenberger /* get already prepared memory for 2 cprbs with param block each */ 531e80d4af0SHarald Freudenberger rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); 532e80d4af0SHarald Freudenberger if (rc) 533e80d4af0SHarald Freudenberger return rc; 534e80d4af0SHarald Freudenberger 535e80d4af0SHarald Freudenberger /* fill request cprb struct */ 536e80d4af0SHarald Freudenberger preqcblk->domain = domain; 537e80d4af0SHarald Freudenberger 538e80d4af0SHarald Freudenberger /* fill request cprb param block with USK request */ 539e80d4af0SHarald Freudenberger preqparm = (struct uskreqparm *) preqcblk->req_parmb; 540e80d4af0SHarald Freudenberger memcpy(preqparm->subfunc_code, "US", 2); 541e80d4af0SHarald Freudenberger preqparm->rule_array_len = sizeof(preqparm->rule_array_len); 542e80d4af0SHarald Freudenberger preqparm->lv1.len = sizeof(struct lv1); 543e80d4af0SHarald Freudenberger preqparm->lv1.attr_len = sizeof(struct lv1) - sizeof(preqparm->lv1.len); 544e80d4af0SHarald Freudenberger preqparm->lv1.attr_flags = 0x0001; 545e80d4af0SHarald Freudenberger preqparm->lv2.len = sizeof(struct lv2) + SECKEYBLOBSIZE; 546e80d4af0SHarald Freudenberger preqparm->lv2.attr_len = sizeof(struct lv2) 547e80d4af0SHarald Freudenberger - sizeof(preqparm->lv2.len) + SECKEYBLOBSIZE; 548e80d4af0SHarald Freudenberger preqparm->lv2.attr_flags = 0x0000; 549e80d4af0SHarald Freudenberger memcpy(preqparm->lv2.token, seckey->seckey, SECKEYBLOBSIZE); 550e80d4af0SHarald Freudenberger preqcblk->req_parml = sizeof(struct uskreqparm) + SECKEYBLOBSIZE; 551e80d4af0SHarald Freudenberger 552e80d4af0SHarald Freudenberger /* fill xcrb struct */ 553e80d4af0SHarald Freudenberger prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); 554e80d4af0SHarald Freudenberger 555e80d4af0SHarald Freudenberger /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ 556e80d4af0SHarald Freudenberger rc = _zcrypt_send_cprb(&xcrb); 557e80d4af0SHarald Freudenberger if (rc) { 558e80d4af0SHarald Freudenberger DEBUG_ERR( 559ac2b96f3SHarald Freudenberger "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", 560ac2b96f3SHarald Freudenberger __func__, (int) cardnr, (int) domain, rc); 561e80d4af0SHarald Freudenberger goto out; 562e80d4af0SHarald Freudenberger } 563e80d4af0SHarald Freudenberger 564e80d4af0SHarald Freudenberger /* check response returncode and reasoncode */ 565e80d4af0SHarald Freudenberger if (prepcblk->ccp_rtcode != 0) { 566e80d4af0SHarald Freudenberger DEBUG_ERR( 567ac2b96f3SHarald Freudenberger "%s unwrap secure key failure, card response %d/%d\n", 568ac2b96f3SHarald Freudenberger __func__, 569e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rtcode, 570e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rscode); 571e80d4af0SHarald Freudenberger rc = -EIO; 572e80d4af0SHarald Freudenberger goto out; 573e80d4af0SHarald Freudenberger } 574ca681ec8SHarald Freudenberger if (prepcblk->ccp_rscode != 0) { 575ca681ec8SHarald Freudenberger DEBUG_WARN( 576ac2b96f3SHarald Freudenberger "%s unwrap secure key warning, card response %d/%d\n", 577ac2b96f3SHarald Freudenberger __func__, 578ca681ec8SHarald Freudenberger (int) prepcblk->ccp_rtcode, 579ca681ec8SHarald Freudenberger (int) prepcblk->ccp_rscode); 580ca681ec8SHarald Freudenberger } 581e80d4af0SHarald Freudenberger 582e80d4af0SHarald Freudenberger /* process response cprb param block */ 583e80d4af0SHarald Freudenberger prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); 584e80d4af0SHarald Freudenberger prepparm = (struct uskrepparm *) prepcblk->rpl_parmb; 585e80d4af0SHarald Freudenberger 586e80d4af0SHarald Freudenberger /* check the returned keyblock */ 587e80d4af0SHarald Freudenberger if (prepparm->lv3.keyblock.version != 0x01) { 588e80d4af0SHarald Freudenberger DEBUG_ERR( 589ac2b96f3SHarald Freudenberger "%s reply param keyblock version mismatch 0x%02x != 0x01\n", 590ac2b96f3SHarald Freudenberger __func__, (int) prepparm->lv3.keyblock.version); 591e80d4af0SHarald Freudenberger rc = -EIO; 592e80d4af0SHarald Freudenberger goto out; 593e80d4af0SHarald Freudenberger } 594e80d4af0SHarald Freudenberger 595e80d4af0SHarald Freudenberger /* copy the tanslated protected key */ 596e80d4af0SHarald Freudenberger switch (prepparm->lv3.keyblock.keylen) { 597e80d4af0SHarald Freudenberger case 16+32: 598e80d4af0SHarald Freudenberger protkey->type = PKEY_KEYTYPE_AES_128; 599e80d4af0SHarald Freudenberger break; 600e80d4af0SHarald Freudenberger case 24+32: 601e80d4af0SHarald Freudenberger protkey->type = PKEY_KEYTYPE_AES_192; 602e80d4af0SHarald Freudenberger break; 603e80d4af0SHarald Freudenberger case 32+32: 604e80d4af0SHarald Freudenberger protkey->type = PKEY_KEYTYPE_AES_256; 605e80d4af0SHarald Freudenberger break; 606e80d4af0SHarald Freudenberger default: 607ac2b96f3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %d\n", 608ac2b96f3SHarald Freudenberger __func__, prepparm->lv3.keyblock.keylen); 609e80d4af0SHarald Freudenberger rc = -EIO; 610e80d4af0SHarald Freudenberger goto out; 611e80d4af0SHarald Freudenberger } 612e80d4af0SHarald Freudenberger protkey->len = prepparm->lv3.keyblock.keylen; 613e80d4af0SHarald Freudenberger memcpy(protkey->protkey, prepparm->lv3.keyblock.key, protkey->len); 614e80d4af0SHarald Freudenberger 615e80d4af0SHarald Freudenberger out: 616e80d4af0SHarald Freudenberger free_cprbmem(mem, PARMBSIZE, 0); 617e80d4af0SHarald Freudenberger return rc; 618e80d4af0SHarald Freudenberger } 619e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_sec2protkey); 620e80d4af0SHarald Freudenberger 621e80d4af0SHarald Freudenberger /* 622e80d4af0SHarald Freudenberger * Create a protected key from a clear key value. 623e80d4af0SHarald Freudenberger */ 624e80d4af0SHarald Freudenberger int pkey_clr2protkey(u32 keytype, 625e80d4af0SHarald Freudenberger const struct pkey_clrkey *clrkey, 626e80d4af0SHarald Freudenberger struct pkey_protkey *protkey) 627e80d4af0SHarald Freudenberger { 628e80d4af0SHarald Freudenberger long fc; 629e80d4af0SHarald Freudenberger int keysize; 630e80d4af0SHarald Freudenberger u8 paramblock[64]; 631e80d4af0SHarald Freudenberger 632e80d4af0SHarald Freudenberger switch (keytype) { 633e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_128: 634e80d4af0SHarald Freudenberger keysize = 16; 635e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_128_KEY; 636e80d4af0SHarald Freudenberger break; 637e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_192: 638e80d4af0SHarald Freudenberger keysize = 24; 639e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_192_KEY; 640e80d4af0SHarald Freudenberger break; 641e80d4af0SHarald Freudenberger case PKEY_KEYTYPE_AES_256: 642e80d4af0SHarald Freudenberger keysize = 32; 643e80d4af0SHarald Freudenberger fc = CPACF_PCKMO_ENC_AES_256_KEY; 644e80d4af0SHarald Freudenberger break; 645e80d4af0SHarald Freudenberger default: 646ac2b96f3SHarald Freudenberger DEBUG_ERR("%s unknown/unsupported keytype %d\n", 647ac2b96f3SHarald Freudenberger __func__, keytype); 648e80d4af0SHarald Freudenberger return -EINVAL; 649e80d4af0SHarald Freudenberger } 650e80d4af0SHarald Freudenberger 651e80d4af0SHarald Freudenberger /* prepare param block */ 652e80d4af0SHarald Freudenberger memset(paramblock, 0, sizeof(paramblock)); 653e80d4af0SHarald Freudenberger memcpy(paramblock, clrkey->clrkey, keysize); 654e80d4af0SHarald Freudenberger 655e80d4af0SHarald Freudenberger /* call the pckmo instruction */ 656e80d4af0SHarald Freudenberger cpacf_pckmo(fc, paramblock); 657e80d4af0SHarald Freudenberger 658e80d4af0SHarald Freudenberger /* copy created protected key */ 659e80d4af0SHarald Freudenberger protkey->type = keytype; 660e80d4af0SHarald Freudenberger protkey->len = keysize + 32; 661e80d4af0SHarald Freudenberger memcpy(protkey->protkey, paramblock, keysize + 32); 662e80d4af0SHarald Freudenberger 663e80d4af0SHarald Freudenberger return 0; 664e80d4af0SHarald Freudenberger } 665e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_clr2protkey); 666e80d4af0SHarald Freudenberger 667e80d4af0SHarald Freudenberger /* 668e80d4af0SHarald Freudenberger * query cryptographic facility from adapter 669e80d4af0SHarald Freudenberger */ 670e80d4af0SHarald Freudenberger static int query_crypto_facility(u16 cardnr, u16 domain, 671e80d4af0SHarald Freudenberger const char *keyword, 672e80d4af0SHarald Freudenberger u8 *rarray, size_t *rarraylen, 673e80d4af0SHarald Freudenberger u8 *varray, size_t *varraylen) 674e80d4af0SHarald Freudenberger { 675e80d4af0SHarald Freudenberger int rc; 676e80d4af0SHarald Freudenberger u16 len; 677e80d4af0SHarald Freudenberger u8 *mem, *ptr; 678e80d4af0SHarald Freudenberger struct CPRBX *preqcblk, *prepcblk; 679e80d4af0SHarald Freudenberger struct ica_xcRB xcrb; 680e80d4af0SHarald Freudenberger struct fqreqparm { 681e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 682e80d4af0SHarald Freudenberger u16 rule_array_len; 683e80d4af0SHarald Freudenberger char rule_array[8]; 684e80d4af0SHarald Freudenberger struct lv1 { 685e80d4af0SHarald Freudenberger u16 len; 686e80d4af0SHarald Freudenberger u8 data[VARDATASIZE]; 687e80d4af0SHarald Freudenberger } lv1; 688e80d4af0SHarald Freudenberger u16 dummylen; 689e80d4af0SHarald Freudenberger } *preqparm; 690e80d4af0SHarald Freudenberger size_t parmbsize = sizeof(struct fqreqparm); 691e80d4af0SHarald Freudenberger struct fqrepparm { 692e80d4af0SHarald Freudenberger u8 subfunc_code[2]; 693e80d4af0SHarald Freudenberger u8 lvdata[0]; 694e80d4af0SHarald Freudenberger } *prepparm; 695e80d4af0SHarald Freudenberger 696e80d4af0SHarald Freudenberger /* get already prepared memory for 2 cprbs with param block each */ 697e80d4af0SHarald Freudenberger rc = alloc_and_prep_cprbmem(parmbsize, &mem, &preqcblk, &prepcblk); 698e80d4af0SHarald Freudenberger if (rc) 699e80d4af0SHarald Freudenberger return rc; 700e80d4af0SHarald Freudenberger 701e80d4af0SHarald Freudenberger /* fill request cprb struct */ 702e80d4af0SHarald Freudenberger preqcblk->domain = domain; 703e80d4af0SHarald Freudenberger 704e80d4af0SHarald Freudenberger /* fill request cprb param block with FQ request */ 705e80d4af0SHarald Freudenberger preqparm = (struct fqreqparm *) preqcblk->req_parmb; 706e80d4af0SHarald Freudenberger memcpy(preqparm->subfunc_code, "FQ", 2); 707a09baa95SVasily Gorbik memcpy(preqparm->rule_array, keyword, sizeof(preqparm->rule_array)); 708e80d4af0SHarald Freudenberger preqparm->rule_array_len = 709e80d4af0SHarald Freudenberger sizeof(preqparm->rule_array_len) + sizeof(preqparm->rule_array); 710e80d4af0SHarald Freudenberger preqparm->lv1.len = sizeof(preqparm->lv1); 711e80d4af0SHarald Freudenberger preqparm->dummylen = sizeof(preqparm->dummylen); 712e80d4af0SHarald Freudenberger preqcblk->req_parml = parmbsize; 713e80d4af0SHarald Freudenberger 714e80d4af0SHarald Freudenberger /* fill xcrb struct */ 715e80d4af0SHarald Freudenberger prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); 716e80d4af0SHarald Freudenberger 717e80d4af0SHarald Freudenberger /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ 718e80d4af0SHarald Freudenberger rc = _zcrypt_send_cprb(&xcrb); 719e80d4af0SHarald Freudenberger if (rc) { 720e80d4af0SHarald Freudenberger DEBUG_ERR( 721ac2b96f3SHarald Freudenberger "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", 722ac2b96f3SHarald Freudenberger __func__, (int) cardnr, (int) domain, rc); 723e80d4af0SHarald Freudenberger goto out; 724e80d4af0SHarald Freudenberger } 725e80d4af0SHarald Freudenberger 726e80d4af0SHarald Freudenberger /* check response returncode and reasoncode */ 727e80d4af0SHarald Freudenberger if (prepcblk->ccp_rtcode != 0) { 728e80d4af0SHarald Freudenberger DEBUG_ERR( 729ac2b96f3SHarald Freudenberger "%s unwrap secure key failure, card response %d/%d\n", 730ac2b96f3SHarald Freudenberger __func__, 731e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rtcode, 732e80d4af0SHarald Freudenberger (int) prepcblk->ccp_rscode); 733e80d4af0SHarald Freudenberger rc = -EIO; 734e80d4af0SHarald Freudenberger goto out; 735e80d4af0SHarald Freudenberger } 736e80d4af0SHarald Freudenberger 737e80d4af0SHarald Freudenberger /* process response cprb param block */ 738e80d4af0SHarald Freudenberger prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); 739e80d4af0SHarald Freudenberger prepparm = (struct fqrepparm *) prepcblk->rpl_parmb; 740e80d4af0SHarald Freudenberger ptr = prepparm->lvdata; 741e80d4af0SHarald Freudenberger 742e80d4af0SHarald Freudenberger /* check and possibly copy reply rule array */ 743e80d4af0SHarald Freudenberger len = *((u16 *) ptr); 744e80d4af0SHarald Freudenberger if (len > sizeof(u16)) { 745e80d4af0SHarald Freudenberger ptr += sizeof(u16); 746e80d4af0SHarald Freudenberger len -= sizeof(u16); 747e80d4af0SHarald Freudenberger if (rarray && rarraylen && *rarraylen > 0) { 748e80d4af0SHarald Freudenberger *rarraylen = (len > *rarraylen ? *rarraylen : len); 749e80d4af0SHarald Freudenberger memcpy(rarray, ptr, *rarraylen); 750e80d4af0SHarald Freudenberger } 751e80d4af0SHarald Freudenberger ptr += len; 752e80d4af0SHarald Freudenberger } 753e80d4af0SHarald Freudenberger /* check and possible copy reply var array */ 754e80d4af0SHarald Freudenberger len = *((u16 *) ptr); 755e80d4af0SHarald Freudenberger if (len > sizeof(u16)) { 756e80d4af0SHarald Freudenberger ptr += sizeof(u16); 757e80d4af0SHarald Freudenberger len -= sizeof(u16); 758e80d4af0SHarald Freudenberger if (varray && varraylen && *varraylen > 0) { 759e80d4af0SHarald Freudenberger *varraylen = (len > *varraylen ? *varraylen : len); 760e80d4af0SHarald Freudenberger memcpy(varray, ptr, *varraylen); 761e80d4af0SHarald Freudenberger } 762e80d4af0SHarald Freudenberger ptr += len; 763e80d4af0SHarald Freudenberger } 764e80d4af0SHarald Freudenberger 765e80d4af0SHarald Freudenberger out: 766e80d4af0SHarald Freudenberger free_cprbmem(mem, parmbsize, 0); 767e80d4af0SHarald Freudenberger return rc; 768e80d4af0SHarald Freudenberger } 769e80d4af0SHarald Freudenberger 770e80d4af0SHarald Freudenberger /* 771ca681ec8SHarald Freudenberger * Fetch the current and old mkvp values via 772ca681ec8SHarald Freudenberger * query_crypto_facility from adapter. 773e80d4af0SHarald Freudenberger */ 774ca681ec8SHarald Freudenberger static int fetch_mkvp(u16 cardnr, u16 domain, u64 mkvp[2]) 775e80d4af0SHarald Freudenberger { 776e80d4af0SHarald Freudenberger int rc, found = 0; 777e80d4af0SHarald Freudenberger size_t rlen, vlen; 778e80d4af0SHarald Freudenberger u8 *rarray, *varray, *pg; 779e80d4af0SHarald Freudenberger 780e80d4af0SHarald Freudenberger pg = (u8 *) __get_free_page(GFP_KERNEL); 781e80d4af0SHarald Freudenberger if (!pg) 782e80d4af0SHarald Freudenberger return -ENOMEM; 783e80d4af0SHarald Freudenberger rarray = pg; 784e80d4af0SHarald Freudenberger varray = pg + PAGE_SIZE/2; 785e80d4af0SHarald Freudenberger rlen = vlen = PAGE_SIZE/2; 786e80d4af0SHarald Freudenberger 787e80d4af0SHarald Freudenberger rc = query_crypto_facility(cardnr, domain, "STATICSA", 788e80d4af0SHarald Freudenberger rarray, &rlen, varray, &vlen); 789e80d4af0SHarald Freudenberger if (rc == 0 && rlen > 8*8 && vlen > 184+8) { 790ca681ec8SHarald Freudenberger if (rarray[8*8] == '2') { 791e80d4af0SHarald Freudenberger /* current master key state is valid */ 792ca681ec8SHarald Freudenberger mkvp[0] = *((u64 *)(varray + 184)); 793ca681ec8SHarald Freudenberger mkvp[1] = *((u64 *)(varray + 172)); 794e80d4af0SHarald Freudenberger found = 1; 795e80d4af0SHarald Freudenberger } 796e80d4af0SHarald Freudenberger } 797e80d4af0SHarald Freudenberger 798e80d4af0SHarald Freudenberger free_page((unsigned long) pg); 799e80d4af0SHarald Freudenberger 800e80d4af0SHarald Freudenberger return found ? 0 : -ENOENT; 801e80d4af0SHarald Freudenberger } 802e80d4af0SHarald Freudenberger 803e80d4af0SHarald Freudenberger /* struct to hold cached mkvp info for each card/domain */ 804e80d4af0SHarald Freudenberger struct mkvp_info { 805e80d4af0SHarald Freudenberger struct list_head list; 806e80d4af0SHarald Freudenberger u16 cardnr; 807e80d4af0SHarald Freudenberger u16 domain; 808ca681ec8SHarald Freudenberger u64 mkvp[2]; 809e80d4af0SHarald Freudenberger }; 810e80d4af0SHarald Freudenberger 811e80d4af0SHarald Freudenberger /* a list with mkvp_info entries */ 812e80d4af0SHarald Freudenberger static LIST_HEAD(mkvp_list); 813e80d4af0SHarald Freudenberger static DEFINE_SPINLOCK(mkvp_list_lock); 814e80d4af0SHarald Freudenberger 815ca681ec8SHarald Freudenberger static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 mkvp[2]) 816e80d4af0SHarald Freudenberger { 817e80d4af0SHarald Freudenberger int rc = -ENOENT; 818e80d4af0SHarald Freudenberger struct mkvp_info *ptr; 819e80d4af0SHarald Freudenberger 820e80d4af0SHarald Freudenberger spin_lock_bh(&mkvp_list_lock); 821e80d4af0SHarald Freudenberger list_for_each_entry(ptr, &mkvp_list, list) { 822e80d4af0SHarald Freudenberger if (ptr->cardnr == cardnr && 823e80d4af0SHarald Freudenberger ptr->domain == domain) { 824ca681ec8SHarald Freudenberger memcpy(mkvp, ptr->mkvp, 2 * sizeof(u64)); 825e80d4af0SHarald Freudenberger rc = 0; 826e80d4af0SHarald Freudenberger break; 827e80d4af0SHarald Freudenberger } 828e80d4af0SHarald Freudenberger } 829e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 830e80d4af0SHarald Freudenberger 831e80d4af0SHarald Freudenberger return rc; 832e80d4af0SHarald Freudenberger } 833e80d4af0SHarald Freudenberger 834ca681ec8SHarald Freudenberger static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp[2]) 835e80d4af0SHarald Freudenberger { 836e80d4af0SHarald Freudenberger int found = 0; 837e80d4af0SHarald Freudenberger struct mkvp_info *ptr; 838e80d4af0SHarald Freudenberger 839e80d4af0SHarald Freudenberger spin_lock_bh(&mkvp_list_lock); 840e80d4af0SHarald Freudenberger list_for_each_entry(ptr, &mkvp_list, list) { 841e80d4af0SHarald Freudenberger if (ptr->cardnr == cardnr && 842e80d4af0SHarald Freudenberger ptr->domain == domain) { 843ca681ec8SHarald Freudenberger memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64)); 844e80d4af0SHarald Freudenberger found = 1; 845e80d4af0SHarald Freudenberger break; 846e80d4af0SHarald Freudenberger } 847e80d4af0SHarald Freudenberger } 848e80d4af0SHarald Freudenberger if (!found) { 849e80d4af0SHarald Freudenberger ptr = kmalloc(sizeof(*ptr), GFP_ATOMIC); 850e80d4af0SHarald Freudenberger if (!ptr) { 851e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 852e80d4af0SHarald Freudenberger return; 853e80d4af0SHarald Freudenberger } 854e80d4af0SHarald Freudenberger ptr->cardnr = cardnr; 855e80d4af0SHarald Freudenberger ptr->domain = domain; 856ca681ec8SHarald Freudenberger memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64)); 857e80d4af0SHarald Freudenberger list_add(&ptr->list, &mkvp_list); 858e80d4af0SHarald Freudenberger } 859e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 860e80d4af0SHarald Freudenberger } 861e80d4af0SHarald Freudenberger 862e80d4af0SHarald Freudenberger static void mkvp_cache_scrub(u16 cardnr, u16 domain) 863e80d4af0SHarald Freudenberger { 864e80d4af0SHarald Freudenberger struct mkvp_info *ptr; 865e80d4af0SHarald Freudenberger 866e80d4af0SHarald Freudenberger spin_lock_bh(&mkvp_list_lock); 867e80d4af0SHarald Freudenberger list_for_each_entry(ptr, &mkvp_list, list) { 868e80d4af0SHarald Freudenberger if (ptr->cardnr == cardnr && 869e80d4af0SHarald Freudenberger ptr->domain == domain) { 870e80d4af0SHarald Freudenberger list_del(&ptr->list); 871e80d4af0SHarald Freudenberger kfree(ptr); 872e80d4af0SHarald Freudenberger break; 873e80d4af0SHarald Freudenberger } 874e80d4af0SHarald Freudenberger } 875e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 876e80d4af0SHarald Freudenberger } 877e80d4af0SHarald Freudenberger 878e80d4af0SHarald Freudenberger static void __exit mkvp_cache_free(void) 879e80d4af0SHarald Freudenberger { 880e80d4af0SHarald Freudenberger struct mkvp_info *ptr, *pnext; 881e80d4af0SHarald Freudenberger 882e80d4af0SHarald Freudenberger spin_lock_bh(&mkvp_list_lock); 883e80d4af0SHarald Freudenberger list_for_each_entry_safe(ptr, pnext, &mkvp_list, list) { 884e80d4af0SHarald Freudenberger list_del(&ptr->list); 885e80d4af0SHarald Freudenberger kfree(ptr); 886e80d4af0SHarald Freudenberger } 887e80d4af0SHarald Freudenberger spin_unlock_bh(&mkvp_list_lock); 888e80d4af0SHarald Freudenberger } 889e80d4af0SHarald Freudenberger 890e80d4af0SHarald Freudenberger /* 891e80d4af0SHarald Freudenberger * Search for a matching crypto card based on the Master Key 892e80d4af0SHarald Freudenberger * Verification Pattern provided inside a secure key. 893e80d4af0SHarald Freudenberger */ 894e80d4af0SHarald Freudenberger int pkey_findcard(const struct pkey_seckey *seckey, 895e80d4af0SHarald Freudenberger u16 *pcardnr, u16 *pdomain, int verify) 896e80d4af0SHarald Freudenberger { 897e80d4af0SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; 898af4a7227SHarald Freudenberger struct zcrypt_device_status_ext *device_status; 899e80d4af0SHarald Freudenberger u16 card, dom; 900ca681ec8SHarald Freudenberger u64 mkvp[2]; 901ca681ec8SHarald Freudenberger int i, rc, oi = -1; 902e80d4af0SHarald Freudenberger 903e80d4af0SHarald Freudenberger /* mkvp must not be zero */ 904e80d4af0SHarald Freudenberger if (t->mkvp == 0) 905e80d4af0SHarald Freudenberger return -EINVAL; 906e80d4af0SHarald Freudenberger 907e80d4af0SHarald Freudenberger /* fetch status of all crypto cards */ 9086da2ec56SKees Cook device_status = kmalloc_array(MAX_ZDEV_ENTRIES_EXT, 9096da2ec56SKees Cook sizeof(struct zcrypt_device_status_ext), 910e80d4af0SHarald Freudenberger GFP_KERNEL); 911af4a7227SHarald Freudenberger if (!device_status) 912e80d4af0SHarald Freudenberger return -ENOMEM; 913af4a7227SHarald Freudenberger zcrypt_device_status_mask_ext(device_status); 914e80d4af0SHarald Freudenberger 915e80d4af0SHarald Freudenberger /* walk through all crypto cards */ 916af4a7227SHarald Freudenberger for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) { 917af4a7227SHarald Freudenberger card = AP_QID_CARD(device_status[i].qid); 918af4a7227SHarald Freudenberger dom = AP_QID_QUEUE(device_status[i].qid); 919af4a7227SHarald Freudenberger if (device_status[i].online && 920af4a7227SHarald Freudenberger device_status[i].functions & 0x04) { 921e80d4af0SHarald Freudenberger /* an enabled CCA Coprocessor card */ 922e80d4af0SHarald Freudenberger /* try cached mkvp */ 923ca681ec8SHarald Freudenberger if (mkvp_cache_fetch(card, dom, mkvp) == 0 && 924ca681ec8SHarald Freudenberger t->mkvp == mkvp[0]) { 925e80d4af0SHarald Freudenberger if (!verify) 926e80d4af0SHarald Freudenberger break; 927e80d4af0SHarald Freudenberger /* verify: fetch mkvp from adapter */ 928ca681ec8SHarald Freudenberger if (fetch_mkvp(card, dom, mkvp) == 0) { 929e80d4af0SHarald Freudenberger mkvp_cache_update(card, dom, mkvp); 930ca681ec8SHarald Freudenberger if (t->mkvp == mkvp[0]) 931e80d4af0SHarald Freudenberger break; 932e80d4af0SHarald Freudenberger } 933e80d4af0SHarald Freudenberger } 934e80d4af0SHarald Freudenberger } else { 935e80d4af0SHarald Freudenberger /* Card is offline and/or not a CCA card. */ 936e80d4af0SHarald Freudenberger /* del mkvp entry from cache if it exists */ 937e80d4af0SHarald Freudenberger mkvp_cache_scrub(card, dom); 938e80d4af0SHarald Freudenberger } 939e80d4af0SHarald Freudenberger } 940af4a7227SHarald Freudenberger if (i >= MAX_ZDEV_ENTRIES_EXT) { 941e80d4af0SHarald Freudenberger /* nothing found, so this time without cache */ 942af4a7227SHarald Freudenberger for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) { 943af4a7227SHarald Freudenberger if (!(device_status[i].online && 944af4a7227SHarald Freudenberger device_status[i].functions & 0x04)) 945e80d4af0SHarald Freudenberger continue; 946af4a7227SHarald Freudenberger card = AP_QID_CARD(device_status[i].qid); 947af4a7227SHarald Freudenberger dom = AP_QID_QUEUE(device_status[i].qid); 948e80d4af0SHarald Freudenberger /* fresh fetch mkvp from adapter */ 949ca681ec8SHarald Freudenberger if (fetch_mkvp(card, dom, mkvp) == 0) { 950e80d4af0SHarald Freudenberger mkvp_cache_update(card, dom, mkvp); 951ca681ec8SHarald Freudenberger if (t->mkvp == mkvp[0]) 952e80d4af0SHarald Freudenberger break; 953ca681ec8SHarald Freudenberger if (t->mkvp == mkvp[1] && oi < 0) 954ca681ec8SHarald Freudenberger oi = i; 955e80d4af0SHarald Freudenberger } 956e80d4af0SHarald Freudenberger } 957af4a7227SHarald Freudenberger if (i >= MAX_ZDEV_ENTRIES_EXT && oi >= 0) { 958ca681ec8SHarald Freudenberger /* old mkvp matched, use this card then */ 959af4a7227SHarald Freudenberger card = AP_QID_CARD(device_status[oi].qid); 960af4a7227SHarald Freudenberger dom = AP_QID_QUEUE(device_status[oi].qid); 961e80d4af0SHarald Freudenberger } 962ca681ec8SHarald Freudenberger } 963af4a7227SHarald Freudenberger if (i < MAX_ZDEV_ENTRIES_EXT || oi >= 0) { 964e80d4af0SHarald Freudenberger if (pcardnr) 965e80d4af0SHarald Freudenberger *pcardnr = card; 966e80d4af0SHarald Freudenberger if (pdomain) 967e80d4af0SHarald Freudenberger *pdomain = dom; 968e80d4af0SHarald Freudenberger rc = 0; 969e80d4af0SHarald Freudenberger } else 970e80d4af0SHarald Freudenberger rc = -ENODEV; 971e80d4af0SHarald Freudenberger 972af4a7227SHarald Freudenberger kfree(device_status); 973e80d4af0SHarald Freudenberger return rc; 974e80d4af0SHarald Freudenberger } 975e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_findcard); 976e80d4af0SHarald Freudenberger 977e80d4af0SHarald Freudenberger /* 978e80d4af0SHarald Freudenberger * Find card and transform secure key into protected key. 979e80d4af0SHarald Freudenberger */ 980e80d4af0SHarald Freudenberger int pkey_skey2pkey(const struct pkey_seckey *seckey, 981e80d4af0SHarald Freudenberger struct pkey_protkey *protkey) 982e80d4af0SHarald Freudenberger { 983e80d4af0SHarald Freudenberger u16 cardnr, domain; 984e80d4af0SHarald Freudenberger int rc, verify; 985e80d4af0SHarald Freudenberger 986e80d4af0SHarald Freudenberger /* 987e80d4af0SHarald Freudenberger * The pkey_sec2protkey call may fail when a card has been 988e80d4af0SHarald Freudenberger * addressed where the master key was changed after last fetch 989e80d4af0SHarald Freudenberger * of the mkvp into the cache. So first try without verify then 990e80d4af0SHarald Freudenberger * with verify enabled (thus refreshing the mkvp for each card). 991e80d4af0SHarald Freudenberger */ 992e80d4af0SHarald Freudenberger for (verify = 0; verify < 2; verify++) { 993e80d4af0SHarald Freudenberger rc = pkey_findcard(seckey, &cardnr, &domain, verify); 994e80d4af0SHarald Freudenberger if (rc) 995e80d4af0SHarald Freudenberger continue; 996e80d4af0SHarald Freudenberger rc = pkey_sec2protkey(cardnr, domain, seckey, protkey); 997e80d4af0SHarald Freudenberger if (rc == 0) 998e80d4af0SHarald Freudenberger break; 999e80d4af0SHarald Freudenberger } 1000e80d4af0SHarald Freudenberger 1001e80d4af0SHarald Freudenberger if (rc) 1002ac2b96f3SHarald Freudenberger DEBUG_DBG("%s failed rc=%d\n", __func__, rc); 1003e80d4af0SHarald Freudenberger 1004e80d4af0SHarald Freudenberger return rc; 1005e80d4af0SHarald Freudenberger } 1006e80d4af0SHarald Freudenberger EXPORT_SYMBOL(pkey_skey2pkey); 1007e80d4af0SHarald Freudenberger 1008e80d4af0SHarald Freudenberger /* 1009e61a6134SHarald Freudenberger * Verify key and give back some info about the key. 1010e61a6134SHarald Freudenberger */ 1011e61a6134SHarald Freudenberger int pkey_verifykey(const struct pkey_seckey *seckey, 1012e61a6134SHarald Freudenberger u16 *pcardnr, u16 *pdomain, 1013e61a6134SHarald Freudenberger u16 *pkeysize, u32 *pattributes) 1014e61a6134SHarald Freudenberger { 1015e61a6134SHarald Freudenberger struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; 1016e61a6134SHarald Freudenberger u16 cardnr, domain; 1017e61a6134SHarald Freudenberger u64 mkvp[2]; 1018e61a6134SHarald Freudenberger int rc; 1019e61a6134SHarald Freudenberger 1020e61a6134SHarald Freudenberger /* check the secure key for valid AES secure key */ 1021e61a6134SHarald Freudenberger rc = check_secaeskeytoken((u8 *) seckey, 0); 1022e61a6134SHarald Freudenberger if (rc) 1023e61a6134SHarald Freudenberger goto out; 1024e61a6134SHarald Freudenberger if (pattributes) 1025e61a6134SHarald Freudenberger *pattributes = PKEY_VERIFY_ATTR_AES; 1026e61a6134SHarald Freudenberger if (pkeysize) 1027e61a6134SHarald Freudenberger *pkeysize = t->bitsize; 1028e61a6134SHarald Freudenberger 1029e61a6134SHarald Freudenberger /* try to find a card which can handle this key */ 1030e61a6134SHarald Freudenberger rc = pkey_findcard(seckey, &cardnr, &domain, 1); 1031e61a6134SHarald Freudenberger if (rc) 1032e61a6134SHarald Freudenberger goto out; 1033e61a6134SHarald Freudenberger 1034e61a6134SHarald Freudenberger /* check mkvp for old mkvp match */ 1035e61a6134SHarald Freudenberger rc = mkvp_cache_fetch(cardnr, domain, mkvp); 1036e61a6134SHarald Freudenberger if (rc) 1037e61a6134SHarald Freudenberger goto out; 1038e61a6134SHarald Freudenberger if (t->mkvp == mkvp[1]) { 1039ac2b96f3SHarald Freudenberger DEBUG_DBG("%s secure key has old mkvp\n", __func__); 1040e61a6134SHarald Freudenberger if (pattributes) 1041e61a6134SHarald Freudenberger *pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP; 1042e61a6134SHarald Freudenberger } 1043e61a6134SHarald Freudenberger 1044e61a6134SHarald Freudenberger if (pcardnr) 1045e61a6134SHarald Freudenberger *pcardnr = cardnr; 1046e61a6134SHarald Freudenberger if (pdomain) 1047e61a6134SHarald Freudenberger *pdomain = domain; 1048e61a6134SHarald Freudenberger 1049e61a6134SHarald Freudenberger out: 1050ac2b96f3SHarald Freudenberger DEBUG_DBG("%s rc=%d\n", __func__, rc); 1051e61a6134SHarald Freudenberger return rc; 1052e61a6134SHarald Freudenberger } 1053e61a6134SHarald Freudenberger EXPORT_SYMBOL(pkey_verifykey); 1054e61a6134SHarald Freudenberger 1055e61a6134SHarald Freudenberger /* 1056*a45a5c7dSIngo Franzki * Generate a random protected key 1057*a45a5c7dSIngo Franzki */ 1058*a45a5c7dSIngo Franzki int pkey_genprotkey(__u32 keytype, struct pkey_protkey *protkey) 1059*a45a5c7dSIngo Franzki { 1060*a45a5c7dSIngo Franzki struct pkey_clrkey clrkey; 1061*a45a5c7dSIngo Franzki int keysize; 1062*a45a5c7dSIngo Franzki int rc; 1063*a45a5c7dSIngo Franzki 1064*a45a5c7dSIngo Franzki switch (keytype) { 1065*a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_128: 1066*a45a5c7dSIngo Franzki keysize = 16; 1067*a45a5c7dSIngo Franzki break; 1068*a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_192: 1069*a45a5c7dSIngo Franzki keysize = 24; 1070*a45a5c7dSIngo Franzki break; 1071*a45a5c7dSIngo Franzki case PKEY_KEYTYPE_AES_256: 1072*a45a5c7dSIngo Franzki keysize = 32; 1073*a45a5c7dSIngo Franzki break; 1074*a45a5c7dSIngo Franzki default: 1075*a45a5c7dSIngo Franzki DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, 1076*a45a5c7dSIngo Franzki keytype); 1077*a45a5c7dSIngo Franzki return -EINVAL; 1078*a45a5c7dSIngo Franzki } 1079*a45a5c7dSIngo Franzki 1080*a45a5c7dSIngo Franzki /* generate a dummy random clear key */ 1081*a45a5c7dSIngo Franzki get_random_bytes(clrkey.clrkey, keysize); 1082*a45a5c7dSIngo Franzki 1083*a45a5c7dSIngo Franzki /* convert it to a dummy protected key */ 1084*a45a5c7dSIngo Franzki rc = pkey_clr2protkey(keytype, &clrkey, protkey); 1085*a45a5c7dSIngo Franzki if (rc) 1086*a45a5c7dSIngo Franzki return rc; 1087*a45a5c7dSIngo Franzki 1088*a45a5c7dSIngo Franzki /* replace the key part of the protected key with random bytes */ 1089*a45a5c7dSIngo Franzki get_random_bytes(protkey->protkey, keysize); 1090*a45a5c7dSIngo Franzki 1091*a45a5c7dSIngo Franzki return 0; 1092*a45a5c7dSIngo Franzki } 1093*a45a5c7dSIngo Franzki EXPORT_SYMBOL(pkey_genprotkey); 1094*a45a5c7dSIngo Franzki 1095*a45a5c7dSIngo Franzki /* 1096e80d4af0SHarald Freudenberger * File io functions 1097e80d4af0SHarald Freudenberger */ 1098e80d4af0SHarald Freudenberger 1099e80d4af0SHarald Freudenberger static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, 1100e80d4af0SHarald Freudenberger unsigned long arg) 1101e80d4af0SHarald Freudenberger { 1102e80d4af0SHarald Freudenberger int rc; 1103e80d4af0SHarald Freudenberger 1104e80d4af0SHarald Freudenberger switch (cmd) { 1105e80d4af0SHarald Freudenberger case PKEY_GENSECK: { 1106e80d4af0SHarald Freudenberger struct pkey_genseck __user *ugs = (void __user *) arg; 1107e80d4af0SHarald Freudenberger struct pkey_genseck kgs; 1108e80d4af0SHarald Freudenberger 1109e80d4af0SHarald Freudenberger if (copy_from_user(&kgs, ugs, sizeof(kgs))) 1110e80d4af0SHarald Freudenberger return -EFAULT; 1111e80d4af0SHarald Freudenberger rc = pkey_genseckey(kgs.cardnr, kgs.domain, 1112e80d4af0SHarald Freudenberger kgs.keytype, &kgs.seckey); 1113ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_genseckey()=%d\n", __func__, rc); 1114e80d4af0SHarald Freudenberger if (rc) 1115e80d4af0SHarald Freudenberger break; 1116e80d4af0SHarald Freudenberger if (copy_to_user(ugs, &kgs, sizeof(kgs))) 1117e80d4af0SHarald Freudenberger return -EFAULT; 1118e80d4af0SHarald Freudenberger break; 1119e80d4af0SHarald Freudenberger } 1120e80d4af0SHarald Freudenberger case PKEY_CLR2SECK: { 1121e80d4af0SHarald Freudenberger struct pkey_clr2seck __user *ucs = (void __user *) arg; 1122e80d4af0SHarald Freudenberger struct pkey_clr2seck kcs; 1123e80d4af0SHarald Freudenberger 1124e80d4af0SHarald Freudenberger if (copy_from_user(&kcs, ucs, sizeof(kcs))) 1125e80d4af0SHarald Freudenberger return -EFAULT; 1126e80d4af0SHarald Freudenberger rc = pkey_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, 1127e80d4af0SHarald Freudenberger &kcs.clrkey, &kcs.seckey); 1128ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_clr2seckey()=%d\n", __func__, rc); 1129e80d4af0SHarald Freudenberger if (rc) 1130e80d4af0SHarald Freudenberger break; 1131e80d4af0SHarald Freudenberger if (copy_to_user(ucs, &kcs, sizeof(kcs))) 1132e80d4af0SHarald Freudenberger return -EFAULT; 1133e80d4af0SHarald Freudenberger memzero_explicit(&kcs, sizeof(kcs)); 1134e80d4af0SHarald Freudenberger break; 1135e80d4af0SHarald Freudenberger } 1136e80d4af0SHarald Freudenberger case PKEY_SEC2PROTK: { 1137e80d4af0SHarald Freudenberger struct pkey_sec2protk __user *usp = (void __user *) arg; 1138e80d4af0SHarald Freudenberger struct pkey_sec2protk ksp; 1139e80d4af0SHarald Freudenberger 1140e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1141e80d4af0SHarald Freudenberger return -EFAULT; 1142e80d4af0SHarald Freudenberger rc = pkey_sec2protkey(ksp.cardnr, ksp.domain, 1143e80d4af0SHarald Freudenberger &ksp.seckey, &ksp.protkey); 1144ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_sec2protkey()=%d\n", __func__, rc); 1145e80d4af0SHarald Freudenberger if (rc) 1146e80d4af0SHarald Freudenberger break; 1147e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1148e80d4af0SHarald Freudenberger return -EFAULT; 1149e80d4af0SHarald Freudenberger break; 1150e80d4af0SHarald Freudenberger } 1151e80d4af0SHarald Freudenberger case PKEY_CLR2PROTK: { 1152e80d4af0SHarald Freudenberger struct pkey_clr2protk __user *ucp = (void __user *) arg; 1153e80d4af0SHarald Freudenberger struct pkey_clr2protk kcp; 1154e80d4af0SHarald Freudenberger 1155e80d4af0SHarald Freudenberger if (copy_from_user(&kcp, ucp, sizeof(kcp))) 1156e80d4af0SHarald Freudenberger return -EFAULT; 1157e80d4af0SHarald Freudenberger rc = pkey_clr2protkey(kcp.keytype, 1158e80d4af0SHarald Freudenberger &kcp.clrkey, &kcp.protkey); 1159ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc); 1160e80d4af0SHarald Freudenberger if (rc) 1161e80d4af0SHarald Freudenberger break; 1162e80d4af0SHarald Freudenberger if (copy_to_user(ucp, &kcp, sizeof(kcp))) 1163e80d4af0SHarald Freudenberger return -EFAULT; 1164e80d4af0SHarald Freudenberger memzero_explicit(&kcp, sizeof(kcp)); 1165e80d4af0SHarald Freudenberger break; 1166e80d4af0SHarald Freudenberger } 1167e80d4af0SHarald Freudenberger case PKEY_FINDCARD: { 1168e80d4af0SHarald Freudenberger struct pkey_findcard __user *ufc = (void __user *) arg; 1169e80d4af0SHarald Freudenberger struct pkey_findcard kfc; 1170e80d4af0SHarald Freudenberger 1171e80d4af0SHarald Freudenberger if (copy_from_user(&kfc, ufc, sizeof(kfc))) 1172e80d4af0SHarald Freudenberger return -EFAULT; 1173e80d4af0SHarald Freudenberger rc = pkey_findcard(&kfc.seckey, 1174e80d4af0SHarald Freudenberger &kfc.cardnr, &kfc.domain, 1); 1175ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_findcard()=%d\n", __func__, rc); 1176e80d4af0SHarald Freudenberger if (rc) 1177e80d4af0SHarald Freudenberger break; 1178e80d4af0SHarald Freudenberger if (copy_to_user(ufc, &kfc, sizeof(kfc))) 1179e80d4af0SHarald Freudenberger return -EFAULT; 1180e80d4af0SHarald Freudenberger break; 1181e80d4af0SHarald Freudenberger } 1182e80d4af0SHarald Freudenberger case PKEY_SKEY2PKEY: { 1183e80d4af0SHarald Freudenberger struct pkey_skey2pkey __user *usp = (void __user *) arg; 1184e80d4af0SHarald Freudenberger struct pkey_skey2pkey ksp; 1185e80d4af0SHarald Freudenberger 1186e80d4af0SHarald Freudenberger if (copy_from_user(&ksp, usp, sizeof(ksp))) 1187e80d4af0SHarald Freudenberger return -EFAULT; 1188e80d4af0SHarald Freudenberger rc = pkey_skey2pkey(&ksp.seckey, &ksp.protkey); 1189ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc); 1190e80d4af0SHarald Freudenberger if (rc) 1191e80d4af0SHarald Freudenberger break; 1192e80d4af0SHarald Freudenberger if (copy_to_user(usp, &ksp, sizeof(ksp))) 1193e80d4af0SHarald Freudenberger return -EFAULT; 1194e80d4af0SHarald Freudenberger break; 1195e80d4af0SHarald Freudenberger } 1196e61a6134SHarald Freudenberger case PKEY_VERIFYKEY: { 1197e61a6134SHarald Freudenberger struct pkey_verifykey __user *uvk = (void __user *) arg; 1198e61a6134SHarald Freudenberger struct pkey_verifykey kvk; 1199e61a6134SHarald Freudenberger 1200e61a6134SHarald Freudenberger if (copy_from_user(&kvk, uvk, sizeof(kvk))) 1201e61a6134SHarald Freudenberger return -EFAULT; 1202e61a6134SHarald Freudenberger rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain, 1203e61a6134SHarald Freudenberger &kvk.keysize, &kvk.attributes); 1204ac2b96f3SHarald Freudenberger DEBUG_DBG("%s pkey_verifykey()=%d\n", __func__, rc); 1205e61a6134SHarald Freudenberger if (rc) 1206e61a6134SHarald Freudenberger break; 1207e61a6134SHarald Freudenberger if (copy_to_user(uvk, &kvk, sizeof(kvk))) 1208e61a6134SHarald Freudenberger return -EFAULT; 1209e61a6134SHarald Freudenberger break; 1210e61a6134SHarald Freudenberger } 1211*a45a5c7dSIngo Franzki case PKEY_GENPROTK: { 1212*a45a5c7dSIngo Franzki struct pkey_genprotk __user *ugp = (void __user *) arg; 1213*a45a5c7dSIngo Franzki struct pkey_genprotk kgp; 1214*a45a5c7dSIngo Franzki 1215*a45a5c7dSIngo Franzki if (copy_from_user(&kgp, ugp, sizeof(kgp))) 1216*a45a5c7dSIngo Franzki return -EFAULT; 1217*a45a5c7dSIngo Franzki rc = pkey_genprotkey(kgp.keytype, &kgp.protkey); 1218*a45a5c7dSIngo Franzki DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc); 1219*a45a5c7dSIngo Franzki if (rc) 1220*a45a5c7dSIngo Franzki break; 1221*a45a5c7dSIngo Franzki if (copy_to_user(ugp, &kgp, sizeof(kgp))) 1222*a45a5c7dSIngo Franzki return -EFAULT; 1223*a45a5c7dSIngo Franzki break; 1224*a45a5c7dSIngo Franzki } 1225e80d4af0SHarald Freudenberger default: 1226e80d4af0SHarald Freudenberger /* unknown/unsupported ioctl cmd */ 1227e80d4af0SHarald Freudenberger return -ENOTTY; 1228e80d4af0SHarald Freudenberger } 1229e80d4af0SHarald Freudenberger 1230e80d4af0SHarald Freudenberger return rc; 1231e80d4af0SHarald Freudenberger } 1232e80d4af0SHarald Freudenberger 1233e80d4af0SHarald Freudenberger /* 1234e80d4af0SHarald Freudenberger * Sysfs and file io operations 1235e80d4af0SHarald Freudenberger */ 1236e80d4af0SHarald Freudenberger static const struct file_operations pkey_fops = { 1237e80d4af0SHarald Freudenberger .owner = THIS_MODULE, 1238e80d4af0SHarald Freudenberger .open = nonseekable_open, 1239e80d4af0SHarald Freudenberger .llseek = no_llseek, 1240e80d4af0SHarald Freudenberger .unlocked_ioctl = pkey_unlocked_ioctl, 1241e80d4af0SHarald Freudenberger }; 1242e80d4af0SHarald Freudenberger 1243e80d4af0SHarald Freudenberger static struct miscdevice pkey_dev = { 1244e80d4af0SHarald Freudenberger .name = "pkey", 1245e80d4af0SHarald Freudenberger .minor = MISC_DYNAMIC_MINOR, 1246e80d4af0SHarald Freudenberger .mode = 0666, 1247e80d4af0SHarald Freudenberger .fops = &pkey_fops, 1248e80d4af0SHarald Freudenberger }; 1249e80d4af0SHarald Freudenberger 1250e80d4af0SHarald Freudenberger /* 1251e80d4af0SHarald Freudenberger * Module init 1252e80d4af0SHarald Freudenberger */ 1253cb4ef3c2SHeiko Carstens static int __init pkey_init(void) 1254e80d4af0SHarald Freudenberger { 1255e80d4af0SHarald Freudenberger cpacf_mask_t pckmo_functions; 1256e80d4af0SHarald Freudenberger 1257e80d4af0SHarald Freudenberger /* check for pckmo instructions available */ 1258e80d4af0SHarald Freudenberger if (!cpacf_query(CPACF_PCKMO, &pckmo_functions)) 1259e80d4af0SHarald Freudenberger return -EOPNOTSUPP; 1260e80d4af0SHarald Freudenberger if (!cpacf_test_func(&pckmo_functions, CPACF_PCKMO_ENC_AES_128_KEY) || 1261e80d4af0SHarald Freudenberger !cpacf_test_func(&pckmo_functions, CPACF_PCKMO_ENC_AES_192_KEY) || 1262e80d4af0SHarald Freudenberger !cpacf_test_func(&pckmo_functions, CPACF_PCKMO_ENC_AES_256_KEY)) 1263e80d4af0SHarald Freudenberger return -EOPNOTSUPP; 1264e80d4af0SHarald Freudenberger 1265e80d4af0SHarald Freudenberger pkey_debug_init(); 1266e80d4af0SHarald Freudenberger 1267e80d4af0SHarald Freudenberger return misc_register(&pkey_dev); 1268e80d4af0SHarald Freudenberger } 1269e80d4af0SHarald Freudenberger 1270e80d4af0SHarald Freudenberger /* 1271e80d4af0SHarald Freudenberger * Module exit 1272e80d4af0SHarald Freudenberger */ 1273e80d4af0SHarald Freudenberger static void __exit pkey_exit(void) 1274e80d4af0SHarald Freudenberger { 1275e80d4af0SHarald Freudenberger misc_deregister(&pkey_dev); 1276e80d4af0SHarald Freudenberger mkvp_cache_free(); 1277e80d4af0SHarald Freudenberger pkey_debug_exit(); 1278e80d4af0SHarald Freudenberger } 1279e80d4af0SHarald Freudenberger 1280e80d4af0SHarald Freudenberger module_init(pkey_init); 1281e80d4af0SHarald Freudenberger module_exit(pkey_exit); 1282