OpenSC / libp11

PKCS#11 wrapper library
GNU Lesser General Public License v2.1
311 stars 189 forks source link

Which key data should p11_ec.c check and provide when asked for a public/private key? #83

Closed DDvO closed 8 years ago

DDvO commented 8 years ago

It is clear from the PKCS#11 spec that a module should allow to retrieve the EC domain params and the curve point Q when asked for an EC public key, and to retrieve the EC params and the private value d (if exportable) when asked for an EC private key. As discussed for commit 874154bc49d28c1358037f923e8d773ba0472b9d, libp11 should - and meanwhile does - make sure that this data is present in the EVP_PKEY structure for the case of public keys. For private keys residing on the module/card, only their params may be accessible.

The private key object and the related public key object of a key pair are supposed to have the same ID, such that one should be able to access the public key using the ID of a private key and the related private key meta-data using the ID of a public key.

@dengert wrote:

The OpenSC pkcs11 module goes to extra lengths to make sure the EC parameters are provided for both the pubkey and privkey. Libp11 will go as far as to read the pubkey to find the parameters when a request for the privkey is made.

I confirm this behavior, but here are three related subtle issues:

  1. Suppose for a given ID of an EC key pair a module/card provides EC parameters for both the pubkey object and privkey object for that ID, how to react if the parameters returned disagree? Maybe libp11 should check for this error condition, as it indicates an incoherence of the module/card storage?
  2. At the moment, libp11 retrieves the EC parameters for the type of key requested and does not check for potential disagreement. As Doug wrote, it even takes over the EC params of private key objects when retrieving data including the curve point of the related public key. I'd say that in this case it should better retrieve the params of the public key object, to be on the safe side.
  3. How to handle the case that a privkey object is present on the module/card but not a pubkey object with the same ID? When asked for the private key, libp11 in this case returns - without flagging an error - in the EVP_PKEY structure the privkey aspect of the EC key pair only. This will be sufficient for pure signature applications, but in case the application in addition then tries making use of the public curve point, it will crash because the respective pointer is NULL. One could argue that the application should have asked for the public key instead (or in addition), but it seems that traditionally when one has a pointer to EVP_PKEY, both the public and private key aspects of it should be usable. This can be justified from the general observation for both RSA and EC cryptography: if one has a private key (including its meta data), one can derive the related public key from it.
dengert commented 8 years ago

As said in previous note RFC 5840 says certificate MUST have EC nameCurve. This is the way of enforcing the certificate is authoritative source for the EC parameters. As you point out PKCS#11 is vague on this, and the EC parameters may not be present in a pubkey or privkey.

On 4/25/2016 5:11 AM, David von Oheimb wrote:

It is clear from the PKCS#11 spec that a module should allow to retrieve the EC domain params and the curve point Q when asked for an EC public key, and to retrieve the EC params and the private value d (if exportable) when asked for an EC private key. As discussed for commit 874154bc49d28c1358037f923e8d773ba0472b9d https://github.com/OpenSC/libp11/commit/874154bc49d28c1358037f923e8d773ba0472b9d, libp11 should - and meanwhile does - make sure that this data is present in the EVP_PKEY structure for the case of public keys. For private keys residing on the module/card, only their params may be accessible.

The private key object and the related public key object of a key pair are supposed to have the same ID, such that one should be able to access the public key using the ID of a private key and the related private key meta-data using the ID of a public key.

@dengert https://github.com/dengert wrote:

The OpenSC pkcs11 module goes to extra lengths to make sure the EC parameters are provided for both the pubkey and privkey. Libp11 will go as far as to read the pubkey to find the parameters when
a request for the privkey is made.

I confirm this behavior, but here are three related subtle issues:

  1. Suppose for a given ID of an EC key pair a module/card provides EC parameters for both the pubkey object and privkey object for that ID, how to react if the parameters returned disagree? Maybe libp11 should check for this error condition, as it indicates an incoherence of the module/card storage?

It could. I would also consider if they differ, then the card issuer has made an error. For example both keys not updated together. Note that from PKCS#11 this is not an error. But libp11 combines the PKCS#11 pubkey and privkey into a single EVP_KEY for OpenSSL. So in that case it could be considered an error if both are present but different.

  1. At the moment, libp11 retrieves the EC parameters for the type of key requested and does not check for potential disagreement. As Doug wrote, it even takes over the EC params of private key objects when retrieving data including the curve point of the related public key. I'd say that in this case it should better retrieve the params of the public key object, to be on the safe side.

From the perspective of the card I am most familiar with, PIV, the EC parameters are only available from the certificate on the card. (During key generation the card generates a keypair and returns the public key. The Card Management System then takes this makes a certificate request that ends up as a certificate and the CMS writes the certificate to the card.) The card does not store a separate pubkey object on the card.

  1. How to handle the case that a privkey object is present on the module/card but not a pubkey object with the same ID? When asked for the private key, libp11 in this case returns - without flagging an error - in the |EVP_PKEY| structure the privkey aspect of the EC key pair only. This will be sufficient for pure signature applications, but in case the application in addition then tries making use of the public curve point, it will crash because the respective pointer is NULL. One could argue that the application should have asked for the public key instead (or in addition), but it seems that traditionally when one has a pointer to |EVP_PKEY|, both the public and private key aspects of it should be usable. This can be justified from the general observation for both RSA and EC cryptography: if one has a private key (including its meta data), one can derive the related public key from it.

We are getting into specifics for a card, and specifics for what a PKCS#11 module returns. Can the module/card return the EC parameters based on what is on the card. If the CardOS module has issues, it could be the module or the CMS that has made some error.

Whatever changes get made, consider what is an error or not if libp11 is being used in a CMS and it is working with a partially initialized card. For example the CMS knows the EC parameters and has generated a key, but the public key and certificate have not been written to the card yet. The card has the private key and knows the parameters but the card may not allow for the extraction of the ec parameters from the card's private key.

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/OpenSC/libp11/issues/83

Douglas E. Engert DEEngert@gmail.com

DDvO commented 8 years ago

@dengert, thanks for your quick comments.

Let me first clarify that the issues I brought up here are independent of CardOS (or any other specific module or card). I came across them when experimenting with an enhanced version of the pkcs11-tool that allows for reading and writing individual public and private keys, for both RSA and EC.

For instance, I uploaded to my card some private keys but not the corresponding public keys (with the same ID). The same effect could be achieved by generating key pairs on the card and modifying the ID of the public key object. Even without being able to access the corresponding public key object, my certificate enrollment application was able to retrieve and use the public key corresponding to an RSA private key on the card, while it crashes on the same use case for EC keys (which is analyzed in my item 3 above).

So we agree on item 1. On the others, you do not give a clear opinion/advice, but I appreciate the further considerations you mention.

Unfortunately, even when the application like a CMS knows the EC params, this is not sufficient to compute the curve point, i.e., the data missing to form a full pubkey.

Good point that a certificate potentially stored on the module/card with the same ID could also act as an alternative source of EC params (and of curve points, of course).

An ideal solution for items 2 and 3 would be if in case a module/card holds a private key (and thus knows internally everything needed to return the EC params and point for EC keys) it allowed for retrieving the public key data corresponding to the private key even if it does not hold the corresponding pubkey object. Yet this is not required according to PKCS#11 (and the CardOS card does this for RSA but not for EC).

mouse07410 commented 8 years ago

Suppose for a given ID of an EC key pair a module/card provides EC parameters for both the pubkey object and privkey object for that ID, how to react if the parameters returned disagree? Maybe libp11 should check for this error condition, as it indicates an incoherence of the module/card storage?

Have you ever encountered such a case? I don't think it's worth messing around checking for an error that can't be there.

How to handle the case that a privkey object is present on the module/card but not a pubkey object with the same ID?

Have you ever seen a card that doesn't have both private and public keys set? Or have you ever encountered a card that would allow setting or overwriting one key of the pair without affecting the other one?

What's the threat model that you're assuming here? A user crafting a maliciously modified hardware token - to do/accomplish what?

Update The proposed "fix" (for any operation with a key retrieve both public and private keys and compare their parameters for consistency) would screw up applications that need only public key, because now these applications would have to provide security PIN.

I think this is a solution in search of a problem. IMHO this issue can/should be closed.

DDvO commented 8 years ago

Suppose for a given ID of an EC key pair a module/card provides EC parameters for both the pubkey object and privkey object for that ID, how to react if the parameters returned disagree? Maybe libp11 should check for this error condition, as it indicates an incoherence of the module/card storage?

Have you ever encountered such a case? I don't think it's worth messing around checking for an error that can't be there.

Not in the wild, but I can imagine various scenarios: the private and public key objects may have been uploaded individually with their IDs or contents having been mixed up, or multiple key pairs with same ID exist and the card may return them in non-canonical order such that the pubkey and privkey found first do not match. Of course, there could also be bugs in the module or card firmware leading to such mismatches.

How to handle the case that a privkey object is present on the module/card but not a pubkey object with the same ID?

Have you ever seen a card that doesn't have both private and public keys set?

Similarly to the case above: Not in the wild, but I can imagine various scenarios: the private and public key objects may have been uploaded individually with non-matching IDs, or the pubkey object may have been deleted due to a mistake or hardware failure. Of course, there could also be bugs in the module or card firmware leading to such mismatches.

Or have you ever encountered a card that would allow setting or overwriting one key of the pair without affecting the other one?

All cards I've tried so far allow (to some extent at least) for individual manipulation of pubkey and privkey objects via PKCS#11. I've done many such experiments with various tools, including BTW an enhanced version of pkcs11-tool which I'm going to share soon.

dengert commented 8 years ago

On 4/25/2016 2:46 PM, Mouse wrote:

Suppose for a given ID of an EC key pair a module/card provides EC parameters for both the pubkey object and privkey object for that ID, how to react if the parameters returned disagree? Maybe
libp11 should check for this error condition, as it indicates an incoherence of the module/card storage?

Have you ever encountered such a case? I don't think it's worth messing around checking for an error that can't be there.

How to handle the case that a privkey object is present on the module/card but not a pubkey object with the same ID?

Have you ever seen a card that doesn't have both private and public keys set? Or have you ever encountered a card that would allow setting or overwriting one key of the pair without affecting the other one?

Yes, and that is why you need a card management system! A card may have the info, but will not allow it to be read, or at least not read by the end user.

PIV for example. Card has private key, but end user can not read the RSA modulus and exponent or EC_point from the card. The pubkey is only available via the certificate which was written to the card by the CMS. A CMS would make sure they match. Although OpenSC does not provide a CMS, the piv-tool can create the above situation if the instructions in https://github.com/OpenSC/OpenSC/wiki/PivTool are not followed. "(This needs to done if there is already a certificate on the card, otherwise a generate cert request may use the public key from the old certificate, rather the the one just generated.)"

Most cards are very dumb, they do not do any internal consistency checks they expect that the CMS has taken care of these.

If the intent of this thread is to develop a CMS, then the CMS application software needs to make sure the information on the card is consistent.

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/OpenSC/libp11/issues/83#issuecomment-214496421

Douglas E. Engert DEEngert@gmail.com

mouse07410 commented 8 years ago

I see. Thanks for explaining. I would welcome introduction of CMS (as a separate piece of software, possibly utilizing or "stealing" code from OpenSC and/or libp11), but still think that the libp11 library itself is not the right place for it (CMS), and trying to make it into one is bound to cause more harm than good.

DDvO commented 8 years ago

My intention creating this issue was not to introduce CMS functionality within libp11, but to make it (and any applications using it, including CMS) more stable on potential inconsistencies w.r.t EC pubkey and privkey objects stored on modules/cards.

mouse07410 commented 8 years ago

If it would mean the need to request PIN (and thus break scripts that work now), I say no thanks. For me it is stable enough as is. Let the application that cares do the checks. libp11 provides all the tools and API to do so. I am strongly against introducing such a change to libp11 itself.

DDvO commented 8 years ago

Unfortunately, there is an inconsistency already in PKCS#11: for RSA, it requires the public attributes of key material (namely, CKA_MODULUS and CKA_PUBLIC_EXPONENT) for both public and private key objects, while for EC it only requires part of the public attributes (namely, CKA_EC_PARAMS, but not CKA_ECDSA_PARAMS) for both public and private key objects.

While trying to compensate for this to some extent, libp11 behaves inconsistently between RSA and EC in two aspects:

  1. When trying to find a public key object related to a private key object, pkcs11_get_rsa() considers only the modulus (while allowing for non-matching ID), while pkcs11_get_ec() considers only the ID (while allowing for non-matching EC parameters). I consider this a bug. Is suggest using both the ID and the modulus when matching RSA keys and both the ID and params when matching EC keys.
  2. libp11 guarantees that a valid modulus and public exponent is present whenever pkcs11_get_rsa() returns non-NULL, while pkcs11_get_ec() gives up on the point (and yields a non-NULL result with an invalid curve point) in case it cannot find a related public key object. As mentioned, this may lead to crashes in the layers above, in particular because programmers using OpenSSL will assume that EC and RSA key material, when packaged into a EVP_PKEY structure, can be used pretty interchangeably.
dengert commented 8 years ago

On 4/27/2016 2:32 AM, David von Oheimb wrote:

Unfortunately, there is an inconsistency already in PKCS#11: for RSA, it requires the public attributes of key material (namely, CKA_MODULUS and CKA_PUBLIC_EXPONENT) for both public and private key objects, while for EC it only requires part of the public attributes (namely, CKA_EC_PARAMS, but not CKA_ECDSA_PARAMS) for both public and private keys.

CKA_EC_PARAMS and CKA_ECDSA_PARAMS are two names for the same attribute. Probably introduced in some early version of PKCS#11 when only ECDSA was defined.

define CKA_ECDSA_PARAMS 0x00000180UL

define CKA_EC_PARAMS 0x00000180UL

While trying to compensate for this to some extent, libp11 behaves inconsistently between RSA and EC in two aspects:

  1. When trying to find a public key object related to a private key object, |pkcs11_get_rsa()| considers only the modulus (while allowing for non-matching ID), while |pkcs11_get_ec()| considers only the ID (while allowing for non-matching EC parameters). I consider this a bug. Is suggest using both the ID and the modulus for matching RSA keys and both the ID and params when matching EC keys.

Yes there is some inconsistency.

PKCS#11 says:"The CKA_ID attribute is intended as a means of distinguishing multiple public-key/private-key pairs held by the same subject (whether stored in the same token or not)."

Note that CK_ID is optional and it is not a requirement to have matching CKA_ID, although I don't know of any tokens or middleware that would not generate a matching CKA_ID for keypairs stored on the token.

The EC was matching on CKA_ID and point as some tokens or middleware may not return the CKA_EC_PARAMS. The reason it is doing the matching is to find the CKA_EC_PARAMS. Its not clear if this should be considered a failure or not, and the calling application may know the parameters from some other source.

I would still like to see a SPY output using the "Offical CardOS" you have used in previous notes that would show if it will return the CKA_EC_PARAMS and CKA_EC_POINT for both a public and private key.

Since there are no extra parameters for RSA matching, the modulus works and matching on CKA_ID is not required. But with EC, matching with the point is not good enough, so it tries to match using the CKA_ID

What I am saying matching may be done to fill in some information and matching may not work.

  1. libp11 guarantees that a valid modulus and public exponent is present whenever |pkcs11_get_rsa()| returns non-NULL, while |pkcs11_get_ec()| gives up on the point (and yields a non-NULL result with an invalid point) in case it cannot find a related public key object. As mentioned, this may lead to crashes in the layers above, in particular because programmers using OpenSSL will assume that EC and RSA key material, when packaged into a |EVP_PKEY| structure, can be used pretty interchangeably.

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/OpenSC/libp11/issues/83#issuecomment-214994048

Douglas E. Engert DEEngert@gmail.com

DDvO commented 8 years ago

Indeed CKA_EC_PARAMS and CKA_ECDSA_PARAMS are two names for the same attribute. Moreover there was a copy&paste error in my above statement. Sorry for the confusion; here is a corrected revision of it:

Unfortunately, there is an inconsistency already in PKCS#11: for RSA, it requires the public attributes of key material (namely, CKA_MODULUS and CKA_PUBLIC_EXPONENT) for both public and private key objects, while for EC it only requires part of the public attributes (namely, CKA_EC(DSA)_PARAMS, but not CKA_EC_POINT) for both public and private key objects.

Note that CK_ID is optional and it is not a requirement to have matching CKA_ID, although I don't know of any tokens or middleware that would not generate a matching CKA_ID for keypairs stored on the token.

Correct; this is also my experience. The situation w.r.t. object IDs is actually even worse: Both PKCS#11 and many (if not all) implementations allow for multiple entirely unrelated objects to have equal IDs. For instance, I can upload several different public keys under the same ID without pkcs11-tool or the module or the card complaining.

The EC was matching on CKA_ID and point as some tokens or middleware may not return the CKA_EC_PARAMS. The reason it is doing the matching is to find the CKA_EC_PARAMS

I understand this w.r.t. the EC params, but just note that libp11 tries matching on the ID only but not on the point.

Its not clear if this should be considered a failure or not, and the calling application may know the parameters from some other source.

Yes.

I would still like to see a SPY output using the "Offical CardOS" you have used in previous notes that would show if it will return the CKA_EC_PARAMS and CKA_EC_POINT for both a public and private key.

All right, here is a trace for retrieving the params and point for an EC public key: pkcs11-spy_read-EC-params-point_pubkey.txt and a trace for tentatively doing the same for an EC private key: pkcs11-spy_read-EC-params-point_privkey.txt As you can see, as required by PKCS#11 that CardOS module returns the params in both cases, while it does not return the point for private keys. (As mentioned, it would have been more useful and more consistent with RSA in both PKCS#11 and its implementations if the point could be retrieved also for EC private keys.)

Since there are no extra parameters for RSA matching, the modulus works and matching on CKA_ID is not required.

I agree. Yet in case the ID is present, it would be better to use it in addition for matching.

But with EC, matching with the point is not good enough, so it tries to match using the CKA_ID

lipb11 does not match on the point. It tries to match on the ID, and my revised proposal for EC is that it should also try matching on the params in order to retrieve the point also if asked for a private key.

What I am saying matching may be done to fill in some information and matching may not work.

Yes.

dengert commented 8 years ago

On 4/29/2016 5:23 AM, David von Oheimb wrote:

Indeed CKA_EC_PARAMS and CKA_ECDSA_PARAMS are two names for the same attribute. Moreover there was a copy&paste error in my above statement. Sorry for the confusion; here is a corrected revision of it:

Unfortunately, there is an inconsistency already in PKCS#11: for RSA, it requires the public attributes of key material (namely, CKA_MODULUS and CKA_PUBLIC_EXPONENT) for both public and private key objects, while for EC it only requires part of the public attributes (namely, CKA_EC(DSA)_PARAMS, but not CKA_EC_POINT) for both public and private key objects.

Yes, CKA_EC_POINT is not an attribute of the private key, so in the trace of the return of CKR_ATTRIBUTE_TYPE_INVALID is correct.

Note that CK_ID is optional and it is not a requirement to have matching CKA_ID, although I don't know of any tokens or middleware that would not generate a matching CKA_ID for keypairs stored on
the token.

Correct; this is also my experience. The situation w.r.t. object IDs is actually even worse: Both PKCS#11 and many (if not all) implementations allow for multiple entirely unrelated objects to have equal IDs. For instance, I can upload several different public keys under the same ID without pkcs11-tool or the module or the card complaining.

The way I read PKCS#11 is that the the CKA_ID can be used to match public keys, private keys and certificates.

If you are finding some tokens using the same CKA_ID for the same CKA_CLASS of objects, I would call that a problem of the code used to initialize the token. Most tokens have no concept of PKCS#11 or even PKCS#15. Its the middleware that maps what the token provides to what PKCS#11 wants as attributes.

The EC was matching on CKA_ID and point as some tokens or middleware may not return the CKA_EC_PARAMS. The reason it is doing the matching is to find the CKA_EC_PARAMS

I understand this w.r.t. the EC params, but just note that libp11 tries matching on the ID only but not on the point.

Yes, as noted above, and in the libp11 code, PKCS#11 does not have a CKA_EC_POINT attribute for a private key, and may not provide the CKA_EC_PARAMS either.

Its not clear if this should be considered a failure or not, and the calling application may know the parameters from some other source.

Yes.

I would still like to see a SPY output using the "Offical CardOS" you have used in previous notes that would show if it will return the CKA_EC_PARAMS and CKA_EC_POINT for both a public and private
key.

All right, here is a trace for retrieving the params and point for an EC public key: pkcs11-spy_read-EC-params-point_pubkey.txt https://github.com/OpenSC/libp11/files/242090/pkcs11-spy_read-EC-params-point_pubkey.txt and a trace for tentatively doing the same for an EC private key: pkcs11-spy_read-EC-params-point_privkey.txt https://github.com/OpenSC/libp11/files/242091/pkcs11-spy_read-EC-params-point_privkey.txt As you can see, as required by PKCS#11 that CardOS module returns the params in both cases, while it does not return the point for private keys. (As mentioned, it would have been more useful and more consistent with RSA in both PKCS#11 and its implementations if the point could be retrieved also for EC private keys.)

Since there are no extra parameters for RSA matching, the modulus works and matching on CKA_ID is not required.

I agree. Yet in case the ID is present, it would be better to use it in addition for matching.

But with EC, matching with the point is not good enough, so it tries to match using the CKA_ID

lipb11 does not match on the point. It tries to match on the ID, and my revised proposal for EC is that it should also try matching on the params in order to retrieve the point also if asked for a private key.

libp11 could match on the CKA_EC_PARAMS too, but is it needed? It would only be needed if the the CKA_IDs are screwed up, which should not happen with a properly issued token. If they don't match its an error.

What I am saying matching may be done to fill in some information and matching may not work.

Yes.

The question in the subject of this issue is "Which key data should p11_ec.c check and provide when asked for a public/private key?"

If the pubkey is requested and has both point and parameters no matching privkey need be present. If parameters are missing for pubkey then if a privkey is present and has parameters, use then with pubkey.

If the privkey is requested, it may have the parameters and this may be good enough for a sign operation so no pubkey need be present. and no point is returned.

I believe that this is what static EC_KEY pkcs11_get_ec(PKCS11_KEY key) is doing. The only match is when line 114: pubkey = key->isPrivate ? pkcs11_find_key_from_key(key) : key; and if the pubkey is not found the privkey is returned anyway.

If you believe there is a problem, what is the proposed fix? Do you have a PR?

If the problem is the parameters are needed for a privkey, say for ECDH, and there are not present, then that code could be added to added to look for them in a matching pubkey.

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/OpenSC/libp11/issues/83#issuecomment-215678661

Douglas E. Engert DEEngert@gmail.com

DDvO commented 8 years ago

Yes, CKA_EC_POINT is not an attribute of the private key, so in the trace of the return of CKR_ATTRIBUTE_TYPE_INVALID is correct.

The way I read PKCS#11 is that the CKA_ID can be used to match public keys, private keys and certificates.

Yep.

If you are finding some tokens using the same CKA_ID for the same CKA_CLASS of objects, I would call that a problem of the code used to initialize the token. Most tokens have no concept of PKCS#11 or even PKCS#15. Its the middleware that maps what the token provides to what PKCS#11 wants as attributes.

Yes, and since libp11 does have a concept of PKCS#11 it could flag such situations as an error (or maybe better just give a warning), but I don't request to actually do this. (This point is issue 1 of my initial post in this thread.)

Yes, as noted above, and in the libp11 code, PKCS#11 does not have a CKA_EC_POINT attribute for a private key, and may not provide the CKA_EC_PARAMS either. libp11 could match on the CKA_EC_PARAMS too, but is it needed? It would only be needed if the CKA_IDs are screwed up, which should not happen with a properly issued token. If they don't match its an error.

Right.

The question in the subject of this issue is "Which key data should p11_ec.c check and provide when asked for a public/private key?" If the pubkey is requested and has both point and parameters no matching privkey need be present.

Yes. (BTW, there was a mistake in issue 2 as I stated it above.) So nothing to improve in this case.

If parameters are missing for pubkey then if a privkey is present and has parameters, use then with pubkey.

That would be helpful, but in this case pkcs11_get_ec() currently gives up returning NULL for the key - which is already better than returning a public key with missing parameters, but it would be best to try taking them over from the private key with matching ID if present. I request this as an enhancement.

If the privkey is requested, it may have the parameters and this may be good enough for a sign operation so no pubkey need be present. and no point is returned. I believe that this is what static EC_KEY pkcs11_get_ec(PKCS11_KEY key) is doing. The only match is when line 114: pubkey = key->isPrivate ? pkcs11_find_key_from_key(key) : key; and if the pubkey is not found the privkey is returned anyway.

Correct.

If you believe there is a problem,

As already mentioned (in particular stated as issue 3 above), this _is _a problem because usually, when one has an OpenSSL EVP_PKEY *pointer, both the private and public key aspects of the key pair are usable. As mentioned, libp11 provides this already for the RSA case, where things are better designed already in the PKCS#11 spec. Yet for EC keys the application may get an incomplete EVP_PKEY structure and if it happens to reference the point info, which it can expected to be present, it will crash.

what is the proposed fix? Do you have a PR?

I don't understand what you mean by 'PR', but one option would be is to be strict and return NULL instead of incomplete key information, preventing potential crashes. The drawback would be that this would rule out use cases where the point data is not needed anyway. So what I suggest for this case is to give at least a warning (though I'm not sure how best to implement it - maybe just print it on the console).

If the problem is the parameters are needed for a privkey, say for ECDH, and there are not present, then that code could be added to added to look for them in a matching pubkey.

Yes, that would be helpful, and I request this enhancement as well.

dengert commented 8 years ago

A PR is a github.com Pull Request. Rebase your DDvO/libp11 repository on OpenSC/libp11, add a new branch, add your proposed change(s) push your repository to github, then on https://github.com/DDvO/libp11 page, select your branch and click on "new pull request" Your PR will show up on https://github.com/OpenSC/libp11/pulls

Also see: https://github.com/OpenSC/libp11#submitting-pull-requests

On 5/3/2016 3:50 AM, David von Oheimb wrote:

Yes, CKA_EC_POINT is not an attribute of the private key, so in the trace of the return of CKR_ATTRIBUTE_TYPE_INVALID is correct.

The way I read PKCS#11 is that the CKA_ID can be used to match public keys, private keys and certificates.

Yep.

If you are finding some tokens using the same CKA_ID for the same CKA_CLASS of objects, I would call that a problem of the code used to initialize the token. Most tokens have no concept of PKCS#11
or even PKCS#15. Its the middleware that maps what the token provides to what PKCS#11 wants as attributes.

Yes, and since libp11 does have a concept of PKCS#11 it could flag such situations as an error (or maybe better just give a warning), but I don't request to actually do this. (This point is issue 1 of my initial post in this thread.)

Yes, as noted above, and in the libp11 code, PKCS#11 does not have a CKA_EC_POINT attribute for a private key, and may not provide the CKA_EC_PARAMS either.
libp11 could match on the CKA_EC_PARAMS too, but is it needed? It would only be needed if the CKA_IDs are screwed up, which should not happen with a properly issued token. If they don't match its
an error.

Right.

The question in the subject of this issue is "Which key data should p11_ec.c check and provide when asked for a public/private key?"
If the pubkey is requested and has both point and parameters no matching privkey need be present.

Yes. (BTW, there was a mistake in issue 2 as I stated it above.) So nothing to improve in this case.

If parameters are missing for pubkey then if a privkey is present and has parameters, use then with pubkey.

That would be helpful, but in this case pkcs11_get_ec() currently gives up returning NULL for the key - which is already better than returning a public key with missing parameters, but it would be best to try taking them over from the private key with matching ID if present. I request this as an enhancement.

If the privkey is requested, it may have the parameters and this may be good enough for a sign operation so no pubkey need be present. and no point is returned. I believe that this is what static
EC_KEY *pkcs11_get_ec(PKCS11_KEY *key) is doing. The only match is when line 114: pubkey = key->isPrivate ? pkcs11_find_key_from_key(key) : key; and if the pubkey is not found the privkey is
returned anyway.

Correct.

If you believe there is a problem,

As already mentioned (in particular stated as issue 3 above), this _is _a problem because usually, when one has an OpenSSL EVP_PKEY *pointer, both the private and public key aspects of the key pair are usable. As mentioned, libp11 provides this already for the RSA case, where things are better designed already in the PKCS#11 spec. Yet for EC keys the application may get an incomplete EVP_PKEY structure and if it happens to reference the point info, which it can expected to be present, it will crash.

what is the proposed fix? Do you have a PR?

I don't understand what you mean by 'PR', but one option would be is to be strict and return NULL instead of incomplete key information, preventing potential crashes. The drawback would be that this would rule out use cases where the point data is not needed anyway. So what I suggest for this case is to give at least a warning (though I'm not sure how best to implement it - maybe just print it on the console).

If the problem is the parameters are needed for a privkey, say for ECDH, and there are not present, then that code could be added to added to look for them in a matching pubkey.

Yes, that would be helpful, and I request this enhancement as well.

— You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub https://github.com/OpenSC/libp11/issues/83#issuecomment-216470927

Douglas E. Engert DEEngert@gmail.com

mouse07410 commented 8 years ago

...usually, when one has an OpenSSL EVP_PKEY *pointer, both the private and public key aspects of the key pair are usable. As mentioned, libp11 provides this already for the RSA case, where things are better designed already in the PKCS#11 spec. Yet for EC keys the application may get an incomplete EVP_PKEY structure and if it happens to reference the point info, which it can expected to be present, it will crash.

I agree that when the private key does not have the necessary parameters, it would be useful to try to obtain them from the public key (assuming it is available). I strongly disagree with going the other way - trying to get private key to augment what's given in the public key.

DDvO commented 8 years ago

@mouse07410, why do you 'strongly disagree' with consulting the private key object (if present) in case the parameter attribute, which is public, is missing from the public key object? Note that we're not talking about trying to retrieve any private information (i.e., the value d), which would not make sense and would result in an error anyway.

@dengert, I can provide a little pull request when there is agreement here on the details of the proposed enhancement.

mouse07410 commented 8 years ago

why do you 'strongly disagree' with consulting the private key object (if present) ...

Because retrieving (or accessing) private key requires submitting the PIN - a whole different ballgame. My biggest objection is doing something that would require the user (or the application!) to request/enter a PIN when currently it doesn't (have to) do so.

If by "if present" you mean "if private key has already been accessed" (and so the PIN has already been provided), then I'd be OK with it.

DDvO commented 8 years ago

Ah, good point, I did not think of the PIN. How to detect in pkcs11_get_ec() if we're already logged in? Once I know this, I can provide a PR.

mtrojnar commented 8 years ago

spriv->loggedIn