PKCS#11 does not define a CKA_VALUE for public keys and is missused
OpenSC opennssl.c in sc_pkcs11_verify_data assumes that it can retieve the CKA_VALUE for a public key object, and expect it to be usable as RSA. But internally sc_pkcs15_pubkey can have a "raw" or "spki" version of the public key as defined by PKCS#15. Card drivers or pkcs15-<card> routines may store either the "raw" or "spki" versions. A get attribute request for CKA_VALUE for a public key will return either the raw, spki or will derived rsa verison of the pubkey. This commit will test if the CKA_VALUE is a spki and use d2i_PUBKEY which takes a spki version and returns an EVP_KEY. If it not an spki the current method, d21_PublicKey(EVP_PKEY_RSA,...) is used which only works for RSA. The problem was found while testing pkcs11-tool -t -l where the verify tests would fail with a CKR_GENERAL_ERROR because the card driver stored the public key as a spki. On branch verify-pubkey-as-spki-2 Changes to be committed: modified: src/pkcs11/openssl.c Date: Fri Apr 07 07:50:00 2017 -0600
This commit is contained in:
parent
f5aa3f5cc6
commit
d48f438581
|
@ -405,7 +405,9 @@ CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, int pubkey_len,
|
|||
{
|
||||
int res;
|
||||
CK_RV rv = CKR_GENERAL_ERROR;
|
||||
EVP_PKEY *pkey;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
const unsigned char *pubkey_tmp;
|
||||
int is_spki = 0;
|
||||
|
||||
if (mech == CKM_GOSTR3410)
|
||||
{
|
||||
|
@ -419,7 +421,38 @@ CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, int pubkey_len,
|
|||
#endif
|
||||
}
|
||||
|
||||
pkey = d2i_PublicKey(EVP_PKEY_RSA, NULL, &pubkey, pubkey_len);
|
||||
/*
|
||||
* PKCS#11 does not define CKA_VALUE for public keys, and different cards
|
||||
* return either the raw or spki versions as defined in PKCS#15
|
||||
* And we need to support more then just RSA.
|
||||
* We can use d2i_PUBKEY which works for SPKI and any key type.
|
||||
*/
|
||||
pubkey_tmp = pubkey; /* pass in so pubkey pointer is not modified */
|
||||
/* SPKI ASN.1 starts with SEQUENCE, SEQUENCE, OBJECT IDENTIFIER */
|
||||
if (*pubkey_tmp++ == 0x30) {
|
||||
if (*pubkey_tmp & 0x80)
|
||||
pubkey_tmp += *pubkey_tmp & 0x7F;
|
||||
|
||||
pubkey_tmp++;
|
||||
if (*pubkey_tmp++ == 0x30) {
|
||||
if (*pubkey_tmp & 0x80)
|
||||
pubkey_tmp += *pubkey_tmp & 0x7F;
|
||||
|
||||
pubkey_tmp += 1;
|
||||
if (*pubkey_tmp == 0x06)
|
||||
is_spki = 1;
|
||||
}
|
||||
}
|
||||
|
||||
pubkey_tmp = pubkey; /* pass in so pubkey pointer is not modified */
|
||||
|
||||
if (is_spki) {
|
||||
pkey = d2i_PUBKEY(NULL, &pubkey_tmp, pubkey_len);
|
||||
}else {
|
||||
/* Assume it is RSA */
|
||||
/* TODO support others but GOST is done above, and EC always uses SPKI */
|
||||
pkey = d2i_PublicKey(EVP_PKEY_RSA, NULL, &pubkey_tmp, pubkey_len);
|
||||
}
|
||||
if (pkey == NULL)
|
||||
return CKR_GENERAL_ERROR;
|
||||
|
||||
|
@ -449,6 +482,7 @@ CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, int pubkey_len,
|
|||
case CKM_RSA_X_509:
|
||||
pad = RSA_NO_PADDING;
|
||||
break;
|
||||
/* TODO support more then RSA */
|
||||
default:
|
||||
EVP_PKEY_free(pkey);
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
|
|
Loading…
Reference in New Issue