Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PKCS#11 does not define a CKA_VALUE for public keys and is missused #1018

Merged
merged 3 commits into from
Apr 26, 2017

Conversation

dengert
Copy link
Member

@dengert dengert commented Apr 7, 2017

This is a replacement for #991. It tests if the CKA_VALUE is a spki before calling d2i_PUBKEY. The previous pull request referred to "direct" and "spki", but should have used "raw" and "spki"

OpenSC openssl.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- 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

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
@dengert dengert mentioned this pull request Apr 7, 2017
if (*pubkey_tmp == 0x06)
is_spki = 1;
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the Idea of determining the type beforehand. However, you should at least use the ASN.1 parsing routines of OpenSC. Even better, you should check whether you can reuse the existing code that parses this kind of data

@dengert
Copy link
Member Author

dengert commented Apr 7, 2017

OK, I will withdraw this PR too.

The real problem is sc_pkcs11_verify_final in pkcs11./mechanism.c is trying to use the CKA_VALUE of a public key. PKCS#11 does NOT define a CKA_VALUE for a CKO_PUBLIC_KEY. Each of the CKK_* key types have their own set of key specific attributes. OpenSC tries to define a CKA_VALUE, which can end up as either the "raw" or "spki" as from PKCS#15, but there is no way to tell them apart other then to pars them.

The code in pkcs15_pubkey_get_attribute in framework-pkcs15.c that tries to return something for a CKA_VALUE. It should return only a spki or should be removed or, at least, not used internally in sc_pkcs11_verify_final. Are there any requirements to support a CKA_VALUE of a CKO_PUBLIC_KEY?

git blame framwork-pkcs15.c shows in lines 3978 - 4020 that @viktorTarasov and @frankmorgner in 2014 introduced the ambiguous code that would return the CKA_VALUE as a raw or spki for any CKO_PUBLIC_KEY.

I also don't agree with your statement:
"PKCS#15 forces RSA if it's not spki, so the above comment can be removed."
Each of the PKCS#15 ASN.1 define what "raw" can be based on the key type:

RSAPublicKeyChoice ::= CHOICE {
raw RSAPublicKey -- See PKCS #1,
spki [1] SubjectPublicKeyInfo, -- See X.509. Must contain a public RSA key
...
}

ECPublicKeyChoice ::= CHOICE {
raw ECPoint,
spki SubjectPublicKeyInfo, -- See X.509. Must contain a public EC key
...
}

DHPublicKeyChoice ::= CHOICE {
raw DiffieHellmanPublicNumber,
spki SubjectPublicKeyInfo, -- See X.509. Must contain a public D-H key
...
}

DSAPublicKeyChoice ::= CHOICE {
raw INTEGER,
spki SubjectPublicKeyInfo, -- See X.509. Must contain a public DSA key.
...
}

KEAPublicKeyChoice ::= CHOICE {
raw INTEGER,
spki SubjectPublicKeyInfo, -- See X.509. Must contain a public KEA key
...
}

@frankmorgner
Copy link
Member

No need to withdraw the PR, simply push more changes on top. We'll do the squashing later.

Sorry, I only looked at RSAPublicKeyChoice. You're right that RSA is not being forced if the type is not spki.

Regarding the commits, I think you meant dd5115b followed by 808fff2, which I was not concerned with. Anyway, for whatever reason you need a workaround, I'd like to make sure that it's not only a quick hack. If possible, I'd like to see a real fix, but currently I don't have the insights how that may look like.

CKA_SPKI is a vendor defined attribute to be used internally
as input to to OpenSSL d2i_PUBKEY

 On branch verify-pubkey-as-spki-2
 Changes to be committed:
	modified:   framework-pkcs15.c
	modified:   mechanism.c
	modified:   openssl.c
	modified:   pkcs11-opensc.h
 On branch verify-pubkey-as-spki-2
 Changes to be committed:
	modified:   framework-pkcs15.c
@dengert
Copy link
Member Author

dengert commented Apr 8, 2017

5c5a540 and fcef1ba
now adds a CKA_SPKI to be used internally in place of the CKA_VALUE. CKA_SPKI returns an SPKI.

I have tested this with pkcs11-tool -t -l. It needs to be tested with older cards that use the "raw" format of the PKCS#15 CHOICE. It also needs to be tested with GOST.

This should also allow for ECDSA signatures to be verified.

The GOST code was treated special in previous code and that was not touched.

@frankmorgner
Copy link
Member

I'll leave this open for an other week to see if someone with a raw public key encoding can test this...

@frankmorgner frankmorgner merged commit 35bae65 into OpenSC:master Apr 26, 2017
@dengert dengert deleted the verify-pubkey-as-spki-2 branch May 29, 2018 16:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants