in crypto/pkey_api.c [1015:1118]
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)
{
int i, card, dom, rc;
struct keytoken_header *hdr = (struct keytoken_header *)key;
/* check for at least one apqn given */
if (!apqns || !nr_apqns)
return -EINVAL;
if (keylen < sizeof(struct keytoken_header))
return -EINVAL;
if (hdr->type == TOKTYPE_NON_CCA
&& hdr->version == TOKVER_EP11_AES_WITH_HEADER
&& is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {
/* EP11 AES key blob with header */
if (ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1))
return -EINVAL;
} else if (hdr->type == TOKTYPE_NON_CCA
&& hdr->version == TOKVER_EP11_ECC_WITH_HEADER
&& is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {
/* EP11 ECC key blob with header */
if (ep11_check_ecc_key_with_hdr(debug_info, 3, key, keylen, 1))
return -EINVAL;
} else if (hdr->type == TOKTYPE_NON_CCA
&& hdr->version == TOKVER_EP11_AES
&& is_ep11_keyblob(key)) {
/* EP11 AES key blob with header in session field */
if (ep11_check_aes_key(debug_info, 3, key, keylen, 1))
return -EINVAL;
} else if (hdr->type == TOKTYPE_CCA_INTERNAL) {
if (hdr->version == TOKVER_CCA_AES) {
/* CCA AES data key */
if (keylen != sizeof(struct secaeskeytoken))
return -EINVAL;
if (cca_check_secaeskeytoken(debug_info, 3, key, 0))
return -EINVAL;
} else if (hdr->version == TOKVER_CCA_VLSC) {
/* CCA AES cipher key */
if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE)
return -EINVAL;
if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1))
return -EINVAL;
} else {
DEBUG_ERR("%s unknown CCA internal token version %d\n",
__func__, hdr->version);
return -EINVAL;
}
} else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {
/* CCA ECC (private) key */
if (keylen < sizeof(struct eccprivkeytoken))
return -EINVAL;
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;
} else {
DEBUG_ERR("%s unknown/unsupported blob type %d\n",
__func__, hdr->type);
return -EINVAL;
}
/* simple try all apqns from the list */
for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
card = apqns[i].card;
dom = apqns[i].domain;
if (hdr->type == TOKTYPE_NON_CCA
&& (hdr->version == TOKVER_EP11_AES_WITH_HEADER
|| hdr->version == TOKVER_EP11_ECC_WITH_HEADER)
&& is_ep11_keyblob(key + sizeof(struct ep11kblob_header)))
rc = ep11_kblob2protkey(card, dom, key, hdr->len,
protkey, protkeylen, protkeytype);
else if (hdr->type == TOKTYPE_NON_CCA
&& hdr->version == TOKVER_EP11_AES
&& is_ep11_keyblob(key))
rc = ep11_kblob2protkey(card, dom, key, hdr->len,
protkey, protkeylen, protkeytype);
else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
hdr->version == TOKVER_CCA_AES)
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, protkey,
protkeylen, protkeytype);
else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA)
rc = cca_ecc2protkey(card, dom, key, protkey,
protkeylen, protkeytype);
else
return -EINVAL;
}
return rc;
}