-
Notifications
You must be signed in to change notification settings - Fork 190
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
Add PKCS11_generate_ec_key() for private EC key generation #379
base: master
Are you sure you want to change the base?
Conversation
@@ -336,6 +336,10 @@ extern int pkcs11_generate_key(PKCS11_TOKEN * token, | |||
int algorithm, unsigned int bits, | |||
char *label, unsigned char* id, size_t id_len); | |||
|
|||
/* Generate and store a private EC key on the token */ | |||
extern int pkcs11_generate_ec_key(PKCS11_TOKEN * token, const char *curve, | |||
char *label, unsigned char* id, size_t id_len); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A question. We had internal discussion about the constness of label and id. As the pkcs11_generate_key() did not have the const decided not to add in here. But logically it would make library users life a bit easier if the signature would be:
extern int pkcs11_generate_ec_key(PKCS11_TOKEN * token, const char *curve,
const char *label, const unsigned char* id, size_t id_len);
I understand that in the PKCS#11 world there is no concept of 'const' so from that design point of view it should be as what is now in the PR.
LGTM based on testing with SoftHSMv2. |
Signed-off-by: Vesa Jääskeläinen <[email protected]>
684a5f1
to
350d6a1
Compare
See the related #378 (comment) for a way to implement this functionality without changing the public API. We really should avoid adding new functions for each key type and use the EVP_PKEY interface instead. Could you please update your PR? |
How would you do the ID and label assignments with that API? |
Could we (mis)use |
Hmm... With: There is option
If this could be expanded for something like:
I try to to experiment with the concept. |
Finally got more time to look at this. In theory it is easy until you look under the hood 🤨. These pages gives some examples of keygen usage: Basically the problem is that where to store temporary the options. Planned to start with RSA keygen but even that has an issue on how to get numbits out. OpenSSL provides setter for the value (which internally does ctrl) but no getter. I can easily hook into ctrl commands and capture those arguments. But there is nowhere to store it easily. Our playground here for key generation is Now back to RSA keygen issue.
Then one asks why current implementation then works in signing as it somehow must have reference to Cryptoki stuff. It uses ex data ( Have been thinking different hackish methods to abuse the stuff a bit but there does not seem to be a good place without a danger that some other engine would do the same thing and then we would have random crashes which no one wants to have. In theory one could become full blow engine and use Cryptoki to fuller extend but that kinda makes it harder to utilize transparency what the current method allows. Eg. use software engine for verify operation with public key and also encrypt with public key then there are bunch of other functions that would be better left as software solutions as those are often faster. One could make shadowed Then alternative for that would be some kind of shared map with If one would want to use @mtrojnar do you have any recommendations on which way to go and try? And if you think that map method would be way to go then if you have preferences which kind of map/which implementation to use. |
And about the app data -- I believe it should be left for user application as they may have C++ class or so where this would be needed. Especially if one does callbacks or so. |
The ex_data is a stack so each application or lib can hang data off the same structure. See: Depending on your timing you may want to target OpenSSL-3.0. OpenSSL-3.0 adds EVP_KEY to the list of structures that can have ex_data: It also has "functions to create keys and key parameters from user data": Here is an example from an OpenSC card driver for an EC public key: |
@dengert Which method do you recommend for supplying additional parameters? |
@mtrojnar I am not sure what you are asking: "Which method do you recommend for supplying additional parameters? If you mean the difference of the OpenSC pkcs11-tool or NSS's certutil, I prefer the OpenSC. The reference for card-piv.c has changed to: |
@dengert Good point. My question was too generic. Let's focus on the task at hand. Should we merge this PR as it is, or should we look for an alternative approach? |
This PR is over a years old and it is adding EC keys are created for use with ECDSA or ECDH, but not usually both. The templates are setting both. Do you want to to allow separate usage bits? (Although to generate a certificate request, the key needs to sign it) even if the key is only going to be used with ECDH. And certificate also contains keyUsage bits that also specify how the key will be used. |
@dengert I prefer adding something like I understand this PR is quite old. I was busy with other projects. I'm going to have more time for libp11 now. |
Sounds good
…On Tue, Mar 22, 2022, 2:38 PM Michał Trojnara ***@***.***> wrote:
@dengert <https://github.com/dengert> I prefer adding something like
PKCS11_generate_key_ex() with a flexible set of parameters over a
separate API function for each key type. I also agree that we need a
parameter for key usage (I hope I understood you correctly).
I understand this PR is quite old. I was busy with other projects. I'm
going to have more time for libp11 now.
—
Reply to this email directly, view it on GitHub
<#379 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAGTIMIATYZ4OKFYW47XFU3VBIOTPANCNFSM4UWZ234A>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Hey @mtrojnar, are there any plans on implementing keygen functionality? I went with your suggestion by (mis)using |
As discussed in OpenSC#379 and OpenSC#378 we need a generic interface that supports multiple algorithms for key generation. Attempt was made to create a new keygen method and register it in PKCS11_pkey_meths()in p11_pkey.c but multiple design issues appeared. How and where do you pass the key ID, token label and alike was the first question. As suggested by the maintainer here: OpenSC#379 (comment), app_data was (mis)used and that worked well. The reason why this approach was abandoned is because a good (or bad) way to get a handle of the PKCS11_CTX_private, that is necessary for the Cryptoki call, was not found. The way other operations work is that they rely on the key being loaded _first_ through ENGINE_load_public(private)_key because this is when the PKCS11_CTX gets initialized and a handle to PKCS11_OBJECT_private gets set to the ex_data of the underlying key. Key generation obviously cannot rely on that mechanism since key doesn't yet exist. Instead, a generic PKCS11_generate_key interface was made that takes a structure describing the key generation algorithm. For now it only contains simple options like curve name for ECC or number of bits for RSA key generation. This interface can then be used as any other PKCS11 wrapper interface or using the ENGINE control commands. Using it with ENGINE control commands is demonstrated in the new tests/keygen.c file. Code for ECC keygen was taken from: OpenSC#379 and reworked to compile and work with some new additions to libp11 i.e. templates.
As discussed in OpenSC#379 and OpenSC#378 we need a generic interface that supports multiple algorithms for key generation. Attempt was made to create a new keygen method and register it in PKCS11_pkey_meths() in p11_pkey.c (so that it's possible to generate keys using OpenSSL's EVP_PKEY_* API) but multiple design issues appeared. How and where do you pass the key ID, token label and alike was the first question. As suggested by the maintainer here: OpenSC#379 (comment), app_data from EVP_PKEY_CTX was (mis)used and that worked well. The reason why this approach was abandoned is because a good (or bad) way to get a handle of the PKCS11_CTX_private, that is necessary for the Cryptoki call, was not found. The way other operations work is that they rely on the key being loaded *_first_* through ENGINE_load_public(private)_key because this is when the PKCS11_CTX gets initialized and a handle to PKCS11_OBJECT_private gets set to the ex_data of the underlying key. Key generation obviously cannot rely on that mechanism since key doesn't yet exist. Instead, a generic PKCS11_generate_key interface was made that takes a structure describing the key generation algorithm. For now it only contains simple options like curve name for ECC or number of bits for RSA key generation. This interface can then be used as any other PKCS11 wrapper interface or using the ENGINE control commands. Using it with ENGINE control commands is demonstrated in the new tests/keygen.c file. Code for ECC keygen was taken from: OpenSC#379 and reworked to compile and work with some new additions to libp11 i.e. templates.
As discussed in OpenSC#379 and OpenSC#378 we need a generic interface that supports multiple algorithms for key generation. Attempt was made to create a new keygen method and register it in PKCS11_pkey_meths() in p11_pkey.c (so that it's possible to generate keys using OpenSSL's EVP_PKEY_* API) but multiple design issues appeared. How and where do you pass the key ID, token label and alike was the first question. As suggested by the maintainer here: OpenSC#379 (comment), app_data from EVP_PKEY_CTX was (mis)used and that worked well. The reason why this approach was abandoned is because a good (or bad) way to get a handle of the PKCS11_CTX_private, that is necessary for the Cryptoki call, was not found. The way other operations work is that they rely on the key being loaded *_first_* through ENGINE_load_public(private)_key because this is when the PKCS11_CTX gets initialized and a handle to PKCS11_OBJECT_private gets set to the ex_data of the underlying key. Key generation obviously cannot rely on that mechanism since key doesn't yet exist. Instead, a generic PKCS11_generate_key interface was made that takes a structure describing the key generation algorithm. For now it only contains simple options like curve name for ECC or number of bits for RSA key generation. This interface can then be used as any other PKCS11 wrapper interface or using the ENGINE control commands. Using it with ENGINE control commands is demonstrated in the new tests/keygen.c file. Code for ECC keygen was taken from: OpenSC#379 and reworked to compile and work with some new additions to libp11 i.e. templates.
As discussed in OpenSC#379 and OpenSC#378 we need a generic interface that supports multiple algorithms for key generation. Attempt was made to create a new keygen method and register it in PKCS11_pkey_meths() in p11_pkey.c (so that it's possible to generate keys using OpenSSL's EVP_PKEY_* API) but multiple design issues appeared. How and where do you pass the key ID, token label and alike was the first question. As suggested by the maintainer here: OpenSC#379 (comment), app_data from EVP_PKEY_CTX was (mis)used and that worked well. The reason why this approach was abandoned is because a good (or bad) way to get a handle of the PKCS11_CTX_private, that is necessary for the Cryptoki call, was not found. The way other operations work is that they rely on the key being loaded *_first_* through ENGINE_load_public(private)_key because this is when the PKCS11_CTX gets initialized and a handle to PKCS11_OBJECT_private gets set to the ex_data of the underlying key. Key generation obviously cannot rely on that mechanism since key doesn't yet exist. Instead, a generic PKCS11_generate_key interface was made that takes a structure describing the key generation algorithm. For now it only contains simple options like curve name for ECC or number of bits for RSA key generation. This interface can then be used as any other PKCS11 wrapper interface or using the ENGINE control commands. Using it with ENGINE control commands is demonstrated in the new tests/keygen.c file. Code for ECC keygen was taken from: OpenSC#379 and reworked to compile and work with some new additions to libp11 i.e. templates.
* Introduce generic keypair generation interface and engine ctrl command As discussed in OpenSC#379 and OpenSC#378 we need a generic interface that supports multiple algorithms for key generation. Attempt was made to create a new keygen method and register it in PKCS11_pkey_meths() in p11_pkey.c (so that it's possible to generate keys using OpenSSL's EVP_PKEY_* API) but multiple design issues appeared. How and where do you pass the key ID, token label and alike was the first question. As suggested by the maintainer here: OpenSC#379 (comment), app_data from EVP_PKEY_CTX was (mis)used and that worked well. The reason why this approach was abandoned is because a good (or bad) way to get a handle of the PKCS11_CTX_private, that is necessary for the Cryptoki call, was not found. The way other operations work is that they rely on the key being loaded *_first_* through ENGINE_load_public(private)_key because this is when the PKCS11_CTX gets initialized and a handle to PKCS11_OBJECT_private gets set to the ex_data of the underlying key. Key generation obviously cannot rely on that mechanism since key doesn't yet exist. Instead, a generic PKCS11_generate_key interface was made that takes a structure describing the key generation algorithm. For now it only contains simple options like curve name for ECC or number of bits for RSA key generation. This interface can then be used as any other PKCS11 wrapper interface or using the ENGINE control commands. Using it with ENGINE control commands is demonstrated in the new tests/keygen.c file. Code for ECC keygen was taken from: OpenSC#379 and reworked to compile and work with some new additions to libp11 i.e. templates. * Add a comment that explains "type" member. Since openssl uses #defines for identifying operations and libp11 already uses these identifiers, we keep using these for consistency.
This PR adds support to allow client libraries to generate elliptic curve keys within the PKCS#11 token.
Existing PKCS11_generate_key() has a limitation that it can only do RSA keys, as there are existing users for the API this adds new API specific to EC key generation.
Observed that the result is more or less the same as:
or with NSS's certutil (except that certutil doesn't set the label for some reason):
certutil -d sql:/etc/pki/nssdb -h device -f /run/pki/pin -z /run/pki/noise -R -k ec -q nistp256 -n ecdsa-client -a -o ecdsa-client.csr.pem -Z SHA256 -s "CN=example" --keyUsage digitalSignature,keyAgreement --extKeyUsage serverAuth,clientAuth
Example code snippet