diff options
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/crypto/pkey_api.c | 512 |
1 files changed, 338 insertions, 174 deletions
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index 5a05d1cdfec2..e58bfd225323 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c @@ -2,7 +2,8 @@ /* * pkey device driver * - * Copyright IBM Corp. 2017,2019 + * Copyright IBM Corp. 2017, 2023 + * * Author(s): Harald Freudenberger */ @@ -32,8 +33,10 @@ MODULE_AUTHOR("IBM Corporation"); MODULE_DESCRIPTION("s390 protected key interface"); #define KEYBLOBBUFSIZE 8192 /* key buffer size used for internal processing */ +#define MINKEYBLOBBUFSIZE (sizeof(struct keytoken_header)) #define PROTKEYBLOBBUFSIZE 256 /* protected key buffer size used internal */ #define MAXAPQNSINLIST 64 /* max 64 apqns within a apqn list */ +#define AES_WK_VP_SIZE 32 /* Size of WK VP block appended to a prot key */ /* * debug feature data and functions @@ -71,49 +74,106 @@ struct protaeskeytoken { } __packed; /* inside view of a clear key token (type 0x00 version 0x02) */ -struct clearaeskeytoken { - u8 type; /* 0x00 for PAES specific key tokens */ +struct clearkeytoken { + u8 type; /* 0x00 for PAES specific key tokens */ u8 res0[3]; - u8 version; /* 0x02 for clear AES key token */ + u8 version; /* 0x02 for clear key token */ u8 res1[3]; - u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ - u32 len; /* bytes actually stored in clearkey[] */ + u32 keytype; /* key type, one of the PKEY_KEYTYPE_* values */ + u32 len; /* bytes actually stored in clearkey[] */ u8 clearkey[]; /* clear key value */ } __packed; +/* helper function which translates the PKEY_KEYTYPE_AES_* to their keysize */ +static inline u32 pkey_keytype_aes_to_size(u32 keytype) +{ + switch (keytype) { + case PKEY_KEYTYPE_AES_128: + return 16; + case PKEY_KEYTYPE_AES_192: + return 24; + case PKEY_KEYTYPE_AES_256: + return 32; + default: + return 0; + } +} + /* - * Create a protected key from a clear key value. + * Create a protected key from a clear key value via PCKMO instruction. */ -static int pkey_clr2protkey(u32 keytype, - const struct pkey_clrkey *clrkey, - struct pkey_protkey *protkey) +static int pkey_clr2protkey(u32 keytype, const u8 *clrkey, + u8 *protkey, u32 *protkeylen, u32 *protkeytype) { /* mask of available pckmo subfunctions */ static cpacf_mask_t pckmo_functions; - long fc; + u8 paramblock[112]; + u32 pkeytype; int keysize; - u8 paramblock[64]; + long fc; switch (keytype) { case PKEY_KEYTYPE_AES_128: + /* 16 byte key, 32 byte aes wkvp, total 48 bytes */ keysize = 16; + pkeytype = keytype; fc = CPACF_PCKMO_ENC_AES_128_KEY; break; case PKEY_KEYTYPE_AES_192: + /* 24 byte key, 32 byte aes wkvp, total 56 bytes */ keysize = 24; + pkeytype = keytype; fc = CPACF_PCKMO_ENC_AES_192_KEY; break; case PKEY_KEYTYPE_AES_256: + /* 32 byte key, 32 byte aes wkvp, total 64 bytes */ keysize = 32; + pkeytype = keytype; fc = CPACF_PCKMO_ENC_AES_256_KEY; break; + case PKEY_KEYTYPE_ECC_P256: + /* 32 byte key, 32 byte aes wkvp, total 64 bytes */ + keysize = 32; + pkeytype = PKEY_KEYTYPE_ECC; + fc = CPACF_PCKMO_ENC_ECC_P256_KEY; + break; + case PKEY_KEYTYPE_ECC_P384: + /* 48 byte key, 32 byte aes wkvp, total 80 bytes */ + keysize = 48; + pkeytype = PKEY_KEYTYPE_ECC; + fc = CPACF_PCKMO_ENC_ECC_P384_KEY; + break; + case PKEY_KEYTYPE_ECC_P521: + /* 80 byte key, 32 byte aes wkvp, total 112 bytes */ + keysize = 80; + pkeytype = PKEY_KEYTYPE_ECC; + fc = CPACF_PCKMO_ENC_ECC_P521_KEY; + break; + case PKEY_KEYTYPE_ECC_ED25519: + /* 32 byte key, 32 byte aes wkvp, total 64 bytes */ + keysize = 32; + pkeytype = PKEY_KEYTYPE_ECC; + fc = CPACF_PCKMO_ENC_ECC_ED25519_KEY; + break; + case PKEY_KEYTYPE_ECC_ED448: + /* 64 byte key, 32 byte aes wkvp, total 96 bytes */ + keysize = 64; + pkeytype = PKEY_KEYTYPE_ECC; + fc = CPACF_PCKMO_ENC_ECC_ED448_KEY; + break; default: - DEBUG_ERR("%s unknown/unsupported keytype %d\n", + DEBUG_ERR("%s unknown/unsupported keytype %u\n", __func__, keytype); return -EINVAL; } + if (*protkeylen < keysize + AES_WK_VP_SIZE) { + DEBUG_ERR("%s prot key buffer size too small: %u < %d\n", + __func__, *protkeylen, keysize + AES_WK_VP_SIZE); + return -EINVAL; + } + /* Did we already check for PCKMO ? */ if (!pckmo_functions.bytes[0]) { /* no, so check now */ @@ -128,15 +188,15 @@ static int pkey_clr2protkey(u32 keytype, /* prepare param block */ memset(paramblock, 0, sizeof(paramblock)); - memcpy(paramblock, clrkey->clrkey, keysize); + memcpy(paramblock, clrkey, keysize); /* call the pckmo instruction */ cpacf_pckmo(fc, paramblock); - /* copy created protected key */ - protkey->type = keytype; - protkey->len = keysize + 32; - memcpy(protkey->protkey, paramblock, keysize + 32); + /* copy created protected key to key buffer including the wkvp block */ + *protkeylen = keysize + AES_WK_VP_SIZE; + memcpy(protkey, paramblock, *protkeylen); + *protkeytype = pkeytype; return 0; } @@ -144,11 +204,12 @@ static int pkey_clr2protkey(u32 keytype, /* * Find card and transform secure key into protected key. */ -static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey) +static int pkey_skey2pkey(const u8 *key, u8 *protkey, + u32 *protkeylen, u32 *protkeytype) { - int rc, verify; - u16 cardnr, domain; struct keytoken_header *hdr = (struct keytoken_header *)key; + u16 cardnr, domain; + int rc, verify; zcrypt_wait_api_operational(); @@ -167,14 +228,13 @@ static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey) continue; switch (hdr->version) { case TOKVER_CCA_AES: - rc = cca_sec2protkey(cardnr, domain, - key, pkey->protkey, - &pkey->len, &pkey->type); + rc = cca_sec2protkey(cardnr, domain, key, + protkey, protkeylen, protkeytype); break; case TOKVER_CCA_VLSC: - rc = cca_cipher2protkey(cardnr, domain, - key, pkey->protkey, - &pkey->len, &pkey->type); + rc = cca_cipher2protkey(cardnr, domain, key, + protkey, protkeylen, + protkeytype); break; default: return -EINVAL; @@ -195,9 +255,9 @@ static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey) static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen, u8 *keybuf, size_t *keybuflen) { - int i, rc; - u16 card, dom; u32 nr_apqns, *apqns = NULL; + u16 card, dom; + int i, rc; zcrypt_wait_api_operational(); @@ -227,12 +287,13 @@ out: /* * Find card and transform EP11 secure key into protected key. */ -static int pkey_ep11key2pkey(const u8 *key, struct pkey_protkey *pkey) +static int pkey_ep11key2pkey(const u8 *key, u8 *protkey, + u32 *protkeylen, u32 *protkeytype) { - int i, rc; - u16 card, dom; - u32 nr_apqns, *apqns = NULL; struct ep11keyblob *kb = (struct ep11keyblob *)key; + u32 nr_apqns, *apqns = NULL; + u16 card, dom; + int i, rc; zcrypt_wait_api_operational(); @@ -246,9 +307,8 @@ static int pkey_ep11key2pkey(const u8 *key, struct pkey_protkey *pkey) for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { card = apqns[i] >> 16; dom = apqns[i] & 0xFFFF; - pkey->len = sizeof(pkey->protkey); rc = ep11_kblob2protkey(card, dom, key, kb->head.len, - pkey->protkey, &pkey->len, &pkey->type); + protkey, protkeylen, protkeytype); if (rc == 0) break; } @@ -306,38 +366,31 @@ out: /* * Generate a random protected key */ -static int pkey_genprotkey(u32 keytype, struct pkey_protkey *protkey) +static int pkey_genprotkey(u32 keytype, u8 *protkey, + u32 *protkeylen, u32 *protkeytype) { - struct pkey_clrkey clrkey; + u8 clrkey[32]; int keysize; int rc; - switch (keytype) { - case PKEY_KEYTYPE_AES_128: - keysize = 16; - break; - case PKEY_KEYTYPE_AES_192: - keysize = 24; - break; - case PKEY_KEYTYPE_AES_256: - keysize = 32; - break; - default: + keysize = pkey_keytype_aes_to_size(keytype); + if (!keysize) { DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, keytype); return -EINVAL; } /* generate a dummy random clear key */ - get_random_bytes(clrkey.clrkey, keysize); + get_random_bytes(clrkey, keysize); /* convert it to a dummy protected key */ - rc = pkey_clr2protkey(keytype, &clrkey, protkey); + rc = pkey_clr2protkey(keytype, clrkey, + protkey, protkeylen, protkeytype); if (rc) return rc; /* replace the key part of the protected key with random bytes */ - get_random_bytes(protkey->protkey, keysize); + get_random_bytes(protkey, keysize); return 0; } @@ -345,37 +398,46 @@ static int pkey_genprotkey(u32 keytype, struct pkey_protkey *protkey) /* * Verify if a protected key is still valid */ -static int pkey_verifyprotkey(const struct pkey_protkey *protkey) +static int pkey_verifyprotkey(const u8 *protkey, u32 protkeylen, + u32 protkeytype) { - unsigned long fc; struct { u8 iv[AES_BLOCK_SIZE]; u8 key[MAXPROTKEYSIZE]; } param; u8 null_msg[AES_BLOCK_SIZE]; u8 dest_buf[AES_BLOCK_SIZE]; - unsigned int k; + unsigned int k, pkeylen; + unsigned long fc; - switch (protkey->type) { + switch (protkeytype) { case PKEY_KEYTYPE_AES_128: + pkeylen = 16 + AES_WK_VP_SIZE; fc = CPACF_KMC_PAES_128; break; case PKEY_KEYTYPE_AES_192: + pkeylen = 24 + AES_WK_VP_SIZE; fc = CPACF_KMC_PAES_192; break; case PKEY_KEYTYPE_AES_256: + pkeylen = 32 + AES_WK_VP_SIZE; fc = CPACF_KMC_PAES_256; break; default: - DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__, - protkey->type); + DEBUG_ERR("%s unknown/unsupported keytype %u\n", __func__, + protkeytype); + return -EINVAL; + } + if (protkeylen != pkeylen) { + DEBUG_ERR("%s invalid protected key size %u for keytype %u\n", + __func__, protkeylen, protkeytype); return -EINVAL; } memset(null_msg, 0, sizeof(null_msg)); memset(param.iv, 0, sizeof(param.iv)); - memcpy(param.key, protkey->protkey, sizeof(param.key)); + memcpy(param.key, protkey, protkeylen); k = cpacf_kmc(fc | CPACF_ENCRYPT, ¶m, null_msg, dest_buf, sizeof(null_msg)); @@ -387,15 +449,119 @@ static int pkey_verifyprotkey(const struct pkey_protkey *protkey) return 0; } +/* Helper for pkey_nonccatok2pkey, handles aes clear key token */ +static int nonccatokaes2pkey(const struct clearkeytoken *t, + u8 *protkey, u32 *protkeylen, u32 *protkeytype) +{ + size_t tmpbuflen = max_t(size_t, SECKEYBLOBSIZE, MAXEP11AESKEYBLOBSIZE); + u8 *tmpbuf = NULL; + u32 keysize; + int rc; + + keysize = pkey_keytype_aes_to_size(t->keytype); + if (!keysize) { + DEBUG_ERR("%s unknown/unsupported keytype %u\n", + __func__, t->keytype); + return -EINVAL; + } + if (t->len != keysize) { + DEBUG_ERR("%s non clear key aes token: invalid key len %u\n", + __func__, t->len); + return -EINVAL; + } + + /* try direct way with the PCKMO instruction */ + rc = pkey_clr2protkey(t->keytype, t->clearkey, + protkey, protkeylen, protkeytype); + if (!rc) + goto out; + + /* PCKMO failed, so try the CCA secure key way */ + tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC); + if (!tmpbuf) + return -ENOMEM; + zcrypt_wait_api_operational(); + rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, t->clearkey, tmpbuf); + if (rc) + goto try_via_ep11; + rc = pkey_skey2pkey(tmpbuf, + protkey, protkeylen, protkeytype); + if (!rc) + goto out; + +try_via_ep11: + /* if the CCA way also failed, let's try via EP11 */ + rc = pkey_clr2ep11key(t->clearkey, t->len, + tmpbuf, &tmpbuflen); + if (rc) + goto failure; + rc = pkey_ep11key2pkey(tmpbuf, + protkey, protkeylen, protkeytype); + if (!rc) + goto out; + +failure: + DEBUG_ERR("%s unable to build protected key from clear", __func__); + +out: + kfree(tmpbuf); + return rc; +} + +/* Helper for pkey_nonccatok2pkey, handles ecc clear key token */ +static int nonccatokecc2pkey(const struct clearkeytoken *t, + u8 *protkey, u32 *protkeylen, u32 *protkeytype) +{ + u32 keylen; + int rc; + + switch (t->keytype) { + case PKEY_KEYTYPE_ECC_P256: + keylen = 32; + break; + case PKEY_KEYTYPE_ECC_P384: + keylen = 48; + break; + case PKEY_KEYTYPE_ECC_P521: + keylen = 80; + break; + case PKEY_KEYTYPE_ECC_ED25519: + keylen = 32; + break; + case PKEY_KEYTYPE_ECC_ED448: + keylen = 64; + break; + default: + DEBUG_ERR("%s unknown/unsupported keytype %u\n", + __func__, t->keytype); + return -EINVAL; + } + + if (t->len != keylen) { + DEBUG_ERR("%s non clear key ecc token: invalid key len %u\n", + __func__, t->len); + return -EINVAL; + } + + /* only one path possible: via PCKMO instruction */ + rc = pkey_clr2protkey(t->keytype, t->clearkey, + protkey, protkeylen, protkeytype); + if (rc) { + DEBUG_ERR("%s unable to build protected key from clear", + __func__); + } + + return rc; +} + /* * Transform a non-CCA key token into a protected key */ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, - struct pkey_protkey *protkey) + u8 *protkey, u32 *protkeylen, u32 *protkeytype) { - int rc = -EINVAL; - u8 *tmpbuf = NULL; struct keytoken_header *hdr = (struct keytoken_header *)key; + int rc = -EINVAL; switch (hdr->version) { case TOKVER_PROTECTED_KEY: { @@ -404,59 +570,40 @@ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, if (keylen != sizeof(struct protaeskeytoken)) goto out; t = (struct protaeskeytoken *)key; - protkey->len = t->len; - protkey->type = t->keytype; - memcpy(protkey->protkey, t->protkey, - sizeof(protkey->protkey)); - rc = pkey_verifyprotkey(protkey); + rc = pkey_verifyprotkey(t->protkey, t->len, t->keytype); + if (rc) + goto out; + memcpy(protkey, t->protkey, t->len); + *protkeylen = t->len; + *protkeytype = t->keytype; break; } case TOKVER_CLEAR_KEY: { - struct clearaeskeytoken *t; - struct pkey_clrkey ckey; - union u_tmpbuf { - u8 skey[SECKEYBLOBSIZE]; - u8 ep11key[MAXEP11AESKEYBLOBSIZE]; - }; - size_t tmpbuflen = sizeof(union u_tmpbuf); - - if (keylen < sizeof(struct clearaeskeytoken)) - goto out; - t = (struct clearaeskeytoken *)key; - if (keylen != sizeof(*t) + t->len) - goto out; - if ((t->keytype == PKEY_KEYTYPE_AES_128 && t->len == 16) || - (t->keytype == PKEY_KEYTYPE_AES_192 && t->len == 24) || - (t->keytype == PKEY_KEYTYPE_AES_256 && t->len == 32)) - memcpy(ckey.clrkey, t->clearkey, t->len); - else - goto out; - /* alloc temp key buffer space */ - tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC); - if (!tmpbuf) { - rc = -ENOMEM; + struct clearkeytoken *t = (struct clearkeytoken *)key; + + if (keylen < sizeof(struct clearkeytoken) || + keylen != sizeof(*t) + t->len) goto out; - } - /* try direct way with the PCKMO instruction */ - rc = pkey_clr2protkey(t->keytype, &ckey, protkey); - if (rc == 0) + switch (t->keytype) { + case PKEY_KEYTYPE_AES_128: + case PKEY_KEYTYPE_AES_192: + case PKEY_KEYTYPE_AES_256: + rc = nonccatokaes2pkey(t, protkey, + protkeylen, protkeytype); break; - /* PCKMO failed, so try the CCA secure key way */ - zcrypt_wait_api_operational(); - rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, - ckey.clrkey, tmpbuf); - if (rc == 0) - rc = pkey_skey2pkey(tmpbuf, protkey); - if (rc == 0) + case PKEY_KEYTYPE_ECC_P256: + case PKEY_KEYTYPE_ECC_P384: + case PKEY_KEYTYPE_ECC_P521: + case PKEY_KEYTYPE_ECC_ED25519: + case PKEY_KEYTYPE_ECC_ED448: + rc = nonccatokecc2pkey(t, protkey, + protkeylen, protkeytype); break; - /* if the CCA way also failed, let's try via EP11 */ - rc = pkey_clr2ep11key(ckey.clrkey, t->len, - tmpbuf, &tmpbuflen); - if (rc == 0) - rc = pkey_ep11key2pkey(tmpbuf, protkey); - /* now we should really have an protected key */ - DEBUG_ERR("%s unable to build protected key from clear", - __func__); + default: + DEBUG_ERR("%s unknown/unsupported non cca clear key type %u\n", + __func__, t->keytype); + return -EINVAL; + } break; } case TOKVER_EP11_AES: { @@ -464,7 +611,8 @@ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); if (rc) goto out; - rc = pkey_ep11key2pkey(key, protkey); + rc = pkey_ep11key2pkey(key, + protkey, protkeylen, protkeytype); break; } case TOKVER_EP11_AES_WITH_HEADER: @@ -473,16 +621,14 @@ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, if (rc) goto out; rc = pkey_ep11key2pkey(key + sizeof(struct ep11kblob_header), - protkey); + protkey, protkeylen, protkeytype); break; default: DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n", __func__, hdr->version); - rc = -EINVAL; } out: - kfree(tmpbuf); return rc; } @@ -490,7 +636,7 @@ out: * Transform a CCA internal key token into a protected key */ static int pkey_ccainttok2pkey(const u8 *key, u32 keylen, - struct pkey_protkey *protkey) + u8 *protkey, u32 *protkeylen, u32 *protkeytype) { struct keytoken_header *hdr = (struct keytoken_header *)key; @@ -509,17 +655,17 @@ static int pkey_ccainttok2pkey(const u8 *key, u32 keylen, return -EINVAL; } - return pkey_skey2pkey(key, protkey); + return pkey_skey2pkey(key, protkey, protkeylen, protkeytype); } /* * Transform a key blob (of any type) into a protected key */ int pkey_keyblob2pkey(const u8 *key, u32 keylen, - struct pkey_protkey *protkey) + u8 *protkey, u32 *protkeylen, u32 *protkeytype) { - int rc; struct keytoken_header *hdr = (struct keytoken_header *)key; + int rc; if (keylen < sizeof(struct keytoken_header)) { DEBUG_ERR("%s invalid keylen %d\n", __func__, keylen); @@ -528,10 +674,12 @@ int pkey_keyblob2pkey(const u8 *key, u32 keylen, switch (hdr->type) { case TOKTYPE_NON_CCA: - rc = pkey_nonccatok2pkey(key, keylen, protkey); + rc = pkey_nonccatok2pkey(key, keylen, + protkey, protkeylen, protkeytype); break; case TOKTYPE_CCA_INTERNAL: - rc = pkey_ccainttok2pkey(key, keylen, protkey); + rc = pkey_ccainttok2pkey(key, keylen, + protkey, protkeylen, protkeytype); break; default: DEBUG_ERR("%s unknown/unsupported blob type %d\n", @@ -663,9 +811,9 @@ static int pkey_verifykey2(const u8 *key, size_t keylen, enum pkey_key_type *ktype, enum pkey_key_size *ksize, u32 *flags) { - int rc; - u32 _nr_apqns, *_apqns = NULL; struct keytoken_header *hdr = (struct keytoken_header *)key; + u32 _nr_apqns, *_apqns = NULL; + int rc; if (keylen < sizeof(struct keytoken_header)) return -EINVAL; @@ -771,10 +919,10 @@ out: static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, const u8 *key, size_t keylen, - struct pkey_protkey *pkey) + u8 *protkey, u32 *protkeylen, u32 *protkeytype) { - int i, card, dom, rc; struct keytoken_header *hdr = (struct keytoken_header *)key; + int i, card, dom, rc; /* check for at least one apqn given */ if (!apqns || !nr_apqns) @@ -806,7 +954,9 @@ static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) return -EINVAL; } else { - return pkey_nonccatok2pkey(key, keylen, pkey); + return pkey_nonccatok2pkey(key, keylen, + protkey, protkeylen, + protkeytype); } } else { DEBUG_ERR("%s unknown/unsupported blob type %d\n", @@ -822,20 +972,20 @@ static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, dom = apqns[i].domain; if (hdr->type == TOKTYPE_CCA_INTERNAL && hdr->version == TOKVER_CCA_AES) { - rc = cca_sec2protkey(card, dom, key, pkey->protkey, - &pkey->len, &pkey->type); + rc = cca_sec2protkey(card, dom, key, + protkey, protkeylen, protkeytype); } else if (hdr->type == TOKTYPE_CCA_INTERNAL && hdr->version == TOKVER_CCA_VLSC) { - rc = cca_cipher2protkey(card, dom, key, pkey->protkey, - &pkey->len, &pkey->type); + rc = cca_cipher2protkey(card, dom, key, + protkey, protkeylen, + protkeytype); } else { /* EP11 AES secure key blob */ struct ep11keyblob *kb = (struct ep11keyblob *)key; - pkey->len = sizeof(pkey->protkey); rc = ep11_kblob2protkey(card, dom, key, kb->head.len, - pkey->protkey, &pkey->len, - &pkey->type); + protkey, protkeylen, + protkeytype); } if (rc == 0) break; @@ -847,9 +997,9 @@ static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, struct pkey_apqn *apqns, size_t *nr_apqns) { - int rc; - u32 _nr_apqns, *_apqns = NULL; struct keytoken_header *hdr = (struct keytoken_header *)key; + u32 _nr_apqns, *_apqns = NULL; + int rc; if (keylen < sizeof(struct keytoken_header) || flags == 0) return -EINVAL; @@ -860,9 +1010,9 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, (hdr->version == TOKVER_EP11_AES_WITH_HEADER || hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { - int minhwtype = 0, api = 0; struct ep11keyblob *kb = (struct ep11keyblob *) (key + sizeof(struct ep11kblob_header)); + int minhwtype = 0, api = 0; if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) return -EINVAL; @@ -877,8 +1027,8 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, } else if (hdr->type == TOKTYPE_NON_CCA && hdr->version == TOKVER_EP11_AES && is_ep11_keyblob(key)) { - int minhwtype = 0, api = 0; struct ep11keyblob *kb = (struct ep11keyblob *)key; + int minhwtype = 0, api = 0; if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) return -EINVAL; @@ -891,8 +1041,8 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, if (rc) goto out; } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { - int minhwtype = ZCRYPT_CEX3C; u64 cur_mkvp = 0, old_mkvp = 0; + int minhwtype = ZCRYPT_CEX3C; if (hdr->version == TOKVER_CCA_AES) { struct secaeskeytoken *t = (struct secaeskeytoken *)key; @@ -919,8 +1069,8 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, if (rc) goto out; } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { - u64 cur_mkvp = 0, old_mkvp = 0; struct eccprivkeytoken *t = (struct eccprivkeytoken *)key; + u64 cur_mkvp = 0, old_mkvp = 0; if (t->secid == 0x20) { if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) @@ -957,8 +1107,8 @@ static int pkey_apqns4keytype(enum pkey_key_type ktype, u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, struct pkey_apqn *apqns, size_t *nr_apqns) { - int rc; u32 _nr_apqns, *_apqns = NULL; + int rc; zcrypt_wait_api_operational(); @@ -1020,11 +1170,11 @@ out: } static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns, - const u8 *key, size_t keylen, u32 *protkeytype, - u8 *protkey, u32 *protkeylen) + const u8 *key, size_t keylen, + u8 *protkey, u32 *protkeylen, u32 *protkeytype) { - int i, card, dom, rc; struct keytoken_header *hdr = (struct keytoken_header *)key; + int i, card, dom, rc; /* check for at least one apqn given */ if (!apqns || !nr_apqns) @@ -1076,15 +1226,8 @@ static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns, if (cca_check_sececckeytoken(debug_info, 3, key, keylen, 1)) return -EINVAL; } else if (hdr->type == TOKTYPE_NON_CCA) { - struct pkey_protkey pkey; - - rc = pkey_nonccatok2pkey(key, keylen, &pkey); - if (rc) - return rc; - memcpy(protkey, pkey.protkey, pkey.len); - *protkeylen = pkey.len; - *protkeytype = pkey.type; - return 0; + return pkey_nonccatok2pkey(key, keylen, + protkey, protkeylen, protkeytype); } else { DEBUG_ERR("%s unknown/unsupported blob type %d\n", __func__, hdr->type); @@ -1130,7 +1273,7 @@ static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns, static void *_copy_key_from_user(void __user *ukey, size_t keylen) { - if (!ukey || keylen < MINKEYBLOBSIZE || keylen > KEYBLOBBUFSIZE) + if (!ukey || keylen < MINKEYBLOBBUFSIZE || keylen > KEYBLOBBUFSIZE) return ERR_PTR(-EINVAL); return memdup_user(ukey, keylen); @@ -1187,6 +1330,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, if (copy_from_user(&ksp, usp, sizeof(ksp))) return -EFAULT; + ksp.protkey.len = sizeof(ksp.protkey.protkey); rc = cca_sec2protkey(ksp.cardnr, ksp.domain, ksp.seckey.seckey, ksp.protkey.protkey, &ksp.protkey.len, &ksp.protkey.type); @@ -1203,8 +1347,10 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, if (copy_from_user(&kcp, ucp, sizeof(kcp))) return -EFAULT; - rc = pkey_clr2protkey(kcp.keytype, - &kcp.clrkey, &kcp.protkey); + kcp.protkey.len = sizeof(kcp.protkey.protkey); + rc = pkey_clr2protkey(kcp.keytype, kcp.clrkey.clrkey, + kcp.protkey.protkey, + &kcp.protkey.len, &kcp.protkey.type); DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc); if (rc) break; @@ -1234,7 +1380,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, if (copy_from_user(&ksp, usp, sizeof(ksp))) return -EFAULT; - rc = pkey_skey2pkey(ksp.seckey.seckey, &ksp.protkey); + ksp.protkey.len = sizeof(ksp.protkey.protkey); + rc = pkey_skey2pkey(ksp.seckey.seckey, ksp.protkey.protkey, + &ksp.protkey.len, &ksp.protkey.type); DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc); if (rc) break; @@ -1263,7 +1411,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, if (copy_from_user(&kgp, ugp, sizeof(kgp))) return -EFAULT; - rc = pkey_genprotkey(kgp.keytype, &kgp.protkey); + kgp.protkey.len = sizeof(kgp.protkey.protkey); + rc = pkey_genprotkey(kgp.keytype, kgp.protkey.protkey, + &kgp.protkey.len, &kgp.protkey.type); DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc); if (rc) break; @@ -1277,7 +1427,8 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, if (copy_from_user(&kvp, uvp, sizeof(kvp))) return -EFAULT; - rc = pkey_verifyprotkey(&kvp.protkey); + rc = pkey_verifyprotkey(kvp.protkey.protkey, + kvp.protkey.len, kvp.protkey.type); DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc); break; } @@ -1291,8 +1442,11 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, kkey = _copy_key_from_user(ktp.key, ktp.keylen); if (IS_ERR(kkey)) return PTR_ERR(kkey); - rc = pkey_keyblob2pkey(kkey, ktp.keylen, &ktp.protkey); + ktp.protkey.len = sizeof(ktp.protkey.protkey); + rc = pkey_keyblob2pkey(kkey, ktp.keylen, ktp.protkey.protkey, + &ktp.protkey.len, &ktp.protkey.type); DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); + memzero_explicit(kkey, ktp.keylen); kfree(kkey); if (rc) break; @@ -1302,9 +1456,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, } case PKEY_GENSECK2: { struct pkey_genseck2 __user *ugs = (void __user *)arg; + size_t klen = KEYBLOBBUFSIZE; struct pkey_genseck2 kgs; struct pkey_apqn *apqns; - size_t klen = KEYBLOBBUFSIZE; u8 *kkey; if (copy_from_user(&kgs, ugs, sizeof(kgs))) @@ -1344,9 +1498,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, } case PKEY_CLR2SECK2: { struct pkey_clr2seck2 __user *ucs = (void __user *)arg; + size_t klen = KEYBLOBBUFSIZE; struct pkey_clr2seck2 kcs; struct pkey_apqn *apqns; - size_t klen = KEYBLOBBUFSIZE; u8 *kkey; if (copy_from_user(&kcs, ucs, sizeof(kcs))) @@ -1408,8 +1562,8 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, } case PKEY_KBLOB2PROTK2: { struct pkey_kblob2pkey2 __user *utp = (void __user *)arg; - struct pkey_kblob2pkey2 ktp; struct pkey_apqn *apqns = NULL; + struct pkey_kblob2pkey2 ktp; u8 *kkey; if (copy_from_user(&ktp, utp, sizeof(ktp))) @@ -1422,10 +1576,14 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, kfree(apqns); return PTR_ERR(kkey); } + ktp.protkey.len = sizeof(ktp.protkey.protkey); rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries, - kkey, ktp.keylen, &ktp.protkey); + kkey, ktp.keylen, + ktp.protkey.protkey, &ktp.protkey.len, + &ktp.protkey.type); DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc); kfree(apqns); + memzero_explicit(kkey, ktp.keylen); kfree(kkey); if (rc) break; @@ -1435,8 +1593,8 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, } case PKEY_APQNS4K: { struct pkey_apqns4key __user *uak = (void __user *)arg; - struct pkey_apqns4key kak; struct pkey_apqn *apqns = NULL; + struct pkey_apqns4key kak; size_t nr_apqns, len; u8 *kkey; @@ -1484,8 +1642,8 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, } case PKEY_APQNS4KT: { struct pkey_apqns4keytype __user *uat = (void __user *)arg; - struct pkey_apqns4keytype kat; struct pkey_apqn *apqns = NULL; + struct pkey_apqns4keytype kat; size_t nr_apqns, len; if (copy_from_user(&kat, uat, sizeof(kat))) @@ -1526,9 +1684,9 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, } case PKEY_KBLOB2PROTK3: { struct pkey_kblob2pkey3 __user *utp = (void __user *)arg; - struct pkey_kblob2pkey3 ktp; - struct pkey_apqn *apqns = NULL; u32 protkeylen = PROTKEYBLOBBUFSIZE; + struct pkey_apqn *apqns = NULL; + struct pkey_kblob2pkey3 ktp; u8 *kkey, *protkey; if (copy_from_user(&ktp, utp, sizeof(ktp))) @@ -1547,11 +1705,12 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, kfree(kkey); return -ENOMEM; } - rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries, kkey, - ktp.keylen, &ktp.pkeytype, - protkey, &protkeylen); + rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries, + kkey, ktp.keylen, + protkey, &protkeylen, &ktp.pkeytype); DEBUG_DBG("%s pkey_keyblob2pkey3()=%d\n", __func__, rc); kfree(apqns); + memzero_explicit(kkey, ktp.keylen); kfree(kkey); if (rc) { kfree(protkey); @@ -1609,7 +1768,9 @@ static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, protkeytoken.version = TOKVER_PROTECTED_KEY; protkeytoken.keytype = keytype; - rc = pkey_genprotkey(protkeytoken.keytype, &protkey); + protkey.len = sizeof(protkey.protkey); + rc = pkey_genprotkey(protkeytoken.keytype, + protkey.protkey, &protkey.len, &protkey.type); if (rc) return rc; @@ -1619,7 +1780,10 @@ static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, memcpy(buf, &protkeytoken, sizeof(protkeytoken)); if (is_xts) { - rc = pkey_genprotkey(protkeytoken.keytype, &protkey); + /* xts needs a second protected key, reuse protkey struct */ + protkey.len = sizeof(protkey.protkey); + rc = pkey_genprotkey(protkeytoken.keytype, + protkey.protkey, &protkey.len, &protkey.type); if (rc) return rc; @@ -1714,8 +1878,8 @@ static struct attribute_group protkey_attr_group = { static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, loff_t off, size_t count) { - int rc; struct pkey_seckey *seckey = (struct pkey_seckey *)buf; + int rc; if (off != 0 || count < sizeof(struct secaeskeytoken)) return -EINVAL; @@ -1821,9 +1985,9 @@ static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits, bool is_xts, char *buf, loff_t off, size_t count) { - int i, rc, card, dom; - u32 nr_apqns, *apqns = NULL; size_t keysize = CCACIPHERTOKENSIZE; + u32 nr_apqns, *apqns = NULL; + int i, rc, card, dom; if (off != 0 || count < CCACIPHERTOKENSIZE) return -EINVAL; @@ -1944,9 +2108,9 @@ static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits, bool is_xts, char *buf, loff_t off, size_t count) { - int i, rc, card, dom; - u32 nr_apqns, *apqns = NULL; size_t keysize = MAXEP11AESKEYBLOBSIZE; + u32 nr_apqns, *apqns = NULL; + int i, rc, card, dom; if (off != 0 || count < MAXEP11AESKEYBLOBSIZE) return -EINVAL; |