in crypto/zcrypt_ep11misc.c [1266:1384]
int ep11_kblob2protkey(u16 card, u16 dom, const u8 *keyblob, size_t keybloblen,
u8 *protkey, u32 *protkeylen, u32 *protkeytype)
{
int rc = -EIO;
u8 *wkbuf = NULL;
size_t wkbuflen, keylen;
struct wk_info {
u16 version;
u8 res1[16];
u32 pkeytype;
u32 pkeybitsize;
u64 pkeysize;
u8 res2[8];
u8 pkey[0];
} __packed * wki;
const u8 *key;
struct ep11kblob_header *hdr;
/* key with or without header ? */
hdr = (struct ep11kblob_header *) keyblob;
if (hdr->type == TOKTYPE_NON_CCA
&& (hdr->version == TOKVER_EP11_AES_WITH_HEADER
|| hdr->version == TOKVER_EP11_ECC_WITH_HEADER)
&& is_ep11_keyblob(keyblob + sizeof(struct ep11kblob_header))) {
/* EP11 AES or ECC key with header */
key = keyblob + sizeof(struct ep11kblob_header);
keylen = hdr->len - sizeof(struct ep11kblob_header);
} else if (hdr->type == TOKTYPE_NON_CCA
&& hdr->version == TOKVER_EP11_AES
&& is_ep11_keyblob(keyblob)) {
/* EP11 AES key (old style) */
key = keyblob;
keylen = hdr->len;
} else if (is_ep11_keyblob(keyblob)) {
/* raw EP11 key blob */
key = keyblob;
keylen = keybloblen;
} else
return -EINVAL;
/* alloc temp working buffer */
wkbuflen = (keylen + AES_BLOCK_SIZE) & (~(AES_BLOCK_SIZE - 1));
wkbuf = kmalloc(wkbuflen, GFP_ATOMIC);
if (!wkbuf)
return -ENOMEM;
/* ep11 secure key -> protected key + info */
rc = ep11_wrapkey(card, dom, key, keylen,
0, def_iv, wkbuf, &wkbuflen);
if (rc) {
DEBUG_ERR(
"%s rewrapping ep11 key to pkey failed, rc=%d\n",
__func__, rc);
goto out;
}
wki = (struct wk_info *) wkbuf;
/* check struct version and pkey type */
if (wki->version != 1 || wki->pkeytype < 1 || wki->pkeytype > 5) {
DEBUG_ERR("%s wk info version %d or pkeytype %d mismatch.\n",
__func__, (int) wki->version, (int) wki->pkeytype);
rc = -EIO;
goto out;
}
/* check protected key type field */
switch (wki->pkeytype) {
case 1: /* AES */
switch (wki->pkeysize) {
case 16+32:
/* AES 128 protected key */
if (protkeytype)
*protkeytype = PKEY_KEYTYPE_AES_128;
break;
case 24+32:
/* AES 192 protected key */
if (protkeytype)
*protkeytype = PKEY_KEYTYPE_AES_192;
break;
case 32+32:
/* AES 256 protected key */
if (protkeytype)
*protkeytype = PKEY_KEYTYPE_AES_256;
break;
default:
DEBUG_ERR("%s unknown/unsupported AES pkeysize %d\n",
__func__, (int) wki->pkeysize);
rc = -EIO;
goto out;
}
break;
case 3: /* EC-P */
case 4: /* EC-ED */
case 5: /* EC-BP */
if (protkeytype)
*protkeytype = PKEY_KEYTYPE_ECC;
break;
case 2: /* TDES */
default:
DEBUG_ERR("%s unknown/unsupported key type %d\n",
__func__, (int) wki->pkeytype);
rc = -EIO;
goto out;
}
/* copy the tanslated protected key */
if (wki->pkeysize > *protkeylen) {
DEBUG_ERR("%s wk info pkeysize %llu > protkeysize %u\n",
__func__, wki->pkeysize, *protkeylen);
rc = -EINVAL;
goto out;
}
memcpy(protkey, wki->pkey, wki->pkeysize);
*protkeylen = wki->pkeysize;
out:
kfree(wkbuf);
return rc;
}