static int pkey_keyblob2pkey3()

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;
}