-
Notifications
You must be signed in to change notification settings - Fork 194
Introduce keypair generation as engine ctrl command #474
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
Conversation
23ac33d to
97ee3ce
Compare
|
Hello @mtrojnar, does this approach to key generation seem plausible at all to you? |
|
what is the status of this PR? has it been abandoned as well? It seems there was a previous attempt at implementing EC keygen which didn't prosper either (#379). is there are reason not to pursue either of them? |
is there are reason not to pursue either of them? IMHO biggest issue with both of these is when will OpenSSL drops engine support and what happens to libp11. |
This patch uses experimental change in libp11 to generate EC keypairs instead of RSA:2048: OpenSC/libp11#474 The patches from this PR need to be built with libp11 for lmp-device-register to compile. Signed-off-by: Milosz Wasilewski <[email protected]>
|
Is there an alternative way of generating EC key pairs on the token? It is currently possible to generate EC keys with pkcs11-tool, but not libp11 API. |
No alternative way for EC keys. |
Patch: OpenSC/libp11#474 Rework docker setup to allow for adding files to the image. This is not possible when using " - < " and reading from STDIN because there is no Docker Build Context there which is necessary for ADD and COPY commands.
Patch: OpenSC/libp11#474 Rework docker setup to allow for adding files to the image. This is not possible when using " - < " and reading from STDIN because there is no Docker Build Context there which is necessary for ADD and COPY commands.
Patch: OpenSC/libp11#474 Rework docker setup to allow for adding files to the image. This is not possible when using " - < " and reading from STDIN because there is no Docker Build Context there which is necessary for ADD and COPY commands.
Patch: OpenSC/libp11#474 Rework docker setup to allow for adding files to the image. This is not possible when using " - < " and reading from STDIN because there is no Docker Build Context there which is necessary for ADD and COPY commands.
Patch: OpenSC/libp11#474 Rework docker setup to allow for adding files to the image. This is not possible when using " - < " and reading from STDIN because there is no Docker Build Context there which is necessary for ADD and COPY commands.
- Patch: OpenSC/libp11#474 - Reworked docker setup to allow adding files to the image. This is not possible when using " - < " and reading from STDIN because there is no Docker Build Context there which is necessary for ADD and COPY commands. - Built libp11 the same way upstream builds it in their CI. This requires libtool package.
- Patch: OpenSC/libp11#474 - Reworked docker setup to allow adding files to the image. This is not possible when using " - < " and reading from STDIN because there is no Docker Build Context there which is necessary for ADD and COPY commands. - Built libp11 the same way upstream builds it in their CI. This requires libtool package.
|
The engine interface looks good to me. On the other hand, changing the definition of |
|
Hello @mtrojnar , can you please check if the PR is good for you now? I requested Ivan access for change the patch. I do not known what to do with the hex_to_bin in the p11_front.c, but I do not want to introduce even more changes to the PR. |
|
The API looks better now. I think it should be possible to merge this feature. @olszomal and myself are in the middle of implementing PKCS#11 provider. More internal changes in PIN UI will be implemented soon. Please wait a few weeks for the code changes to stabilize, and then I'll ask you to rebase your PR on top of the new code. What do you think? |
|
@rafajunio |
PR474 was now rebased on top of libp11-0.4.13 OpenSC/libp11#474 | * 98ebc16 (istepic/master, istepic/HEAD) Fix typo | * 79a7937 Fix build for ubuntu | * e837a0e update to the latest version of libp11 |/ * 7addb3c Cleanup * 958c8e8 Fix debug_level for UTIL_CTX_log() * 1a780a0 Make UTIL_CTX opaque * 761ef67 Further util_uri.c separation * 3b80c73 Remove dead code * 3c7b2cc Fix Windows build * 6dc51cf Initial util_uri.c separation * dba1add Reorder CMD_DEBUG_LEVEL processing to match definition order * 4852910 Fix from CKK_GENERIC_SECRET keys * 7300cb8 Add configure option to enable the static PKCS11 engine * 5be6422 Formatting * 22832d3 Simplify implementation of the QUIET control command * 2c747ad Restore the VERBOSE engine control command * 50b1363 Enhance libp11 logging system (#573) * e177b3b Starting 0.4.14_git * 6d66918 (HEAD -> master, tag: libp11-0.4.13, tag: devtool-patched, tag: devtool-base, devtool) Fixed tests in distribution tarball Signed-off-by: Jose Quaresma <[email protected]>
PR474 was now rebased on top of libp11-0.4.13 OpenSC/libp11#474 | * 98ebc16 (istepic/master, istepic/HEAD) Fix typo | * 79a7937 Fix build for ubuntu | * e837a0e update to the latest version of libp11 |/ * 7addb3c Cleanup * 958c8e8 Fix debug_level for UTIL_CTX_log() * 1a780a0 Make UTIL_CTX opaque * 761ef67 Further util_uri.c separation * 3b80c73 Remove dead code * 3c7b2cc Fix Windows build * 6dc51cf Initial util_uri.c separation * dba1add Reorder CMD_DEBUG_LEVEL processing to match definition order * 4852910 Fix from CKK_GENERIC_SECRET keys * 7300cb8 Add configure option to enable the static PKCS11 engine * 5be6422 Formatting * 22832d3 Simplify implementation of the QUIET control command * 2c747ad Restore the VERBOSE engine control command * 50b1363 Enhance libp11 logging system (#573) * e177b3b Starting 0.4.14_git * 6d66918 (HEAD -> master, tag: libp11-0.4.13, tag: devtool-patched, tag: devtool-base, devtool) Fixed tests in distribution tarball Signed-off-by: Jose Quaresma <[email protected]>
PR474 was now rebased on top of libp11-0.4.13 OpenSC/libp11#474 | * 98ebc16 (istepic/master, istepic/HEAD) Fix typo | * 79a7937 Fix build for ubuntu | * e837a0e update to the latest version of libp11 |/ * 7addb3c Cleanup * 958c8e8 Fix debug_level for UTIL_CTX_log() * 1a780a0 Make UTIL_CTX opaque * 761ef67 Further util_uri.c separation * 3b80c73 Remove dead code * 3c7b2cc Fix Windows build * 6dc51cf Initial util_uri.c separation * dba1add Reorder CMD_DEBUG_LEVEL processing to match definition order * 4852910 Fix from CKK_GENERIC_SECRET keys * 7300cb8 Add configure option to enable the static PKCS11 engine * 5be6422 Formatting * 22832d3 Simplify implementation of the QUIET control command * 2c747ad Restore the VERBOSE engine control command * 50b1363 Enhance libp11 logging system (#573) * e177b3b Starting 0.4.14_git * 6d66918 (HEAD -> master, tag: libp11-0.4.13, tag: devtool-patched, tag: devtool-base, devtool) Fixed tests in distribution tarball Signed-off-by: Jose Quaresma <[email protected]>
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. It also possible to configure CKA_SENSITIVE and CKA_EXTRACTABLE key attributes. 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. Upstream-Status: Denied [OpenSC#474] Signed-off-by: istepic <[email protected]> Signed-off-by: cps-b <[email protected]>
|
@mtrojnar |
olszomal
left a comment
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.
Excellent work – the code is clean and well-structured, making it easy to review.
I confirm that key pair generation works correctly for both the libp11 library and the engine.
Unfortunately, the OpenSSL provider currently only supports retrieving objects from the token, meaning it cannot be used for key generation. Please remove the key generation test for the provider.
| exit 1 | ||
| fi | ||
|
|
||
| echo "Checking pkcs11-tool result..." |
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.
Restore LD_LIBRARY_PATH before calling list_objects.
| cleanup: | ||
| if (!engine) | ||
| ENGINE_finish(engine); | ||
|
|
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.
Remember to call EVP_PKEY_free()
tests/keygen.c
Outdated
| display_openssl_errors(__LINE__); | ||
| goto cleanup; | ||
| } | ||
|
|
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.
ENGINE_init() returns a functional reference, so release the structural reference obtained from ENGINE_by_id() and use ENGINE_free(engine).
tests/keygen.c
Outdated
| /* | ||
| * EC key generation test | ||
| */ | ||
| PKCS11_EC_KGEN ec = { |
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.
Declare structures and variables at the beginning of the code block, following the C89/C90 standard.
| printf("ECC Sign-verify success\n"); | ||
|
|
||
| /* | ||
| * RSA key generation test |
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.
Split the test into two separate cases for RSA and EC key generation to maintain consistency with existing tests.
src/eng_back.c
Outdated
| } | ||
| } | ||
|
|
||
| // Try with logging in |
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.
This project uses C-style comments instead of C++.
src/eng_back.c
Outdated
| if (!found_slot) | ||
| return 0; | ||
|
|
||
| /* If login is not forced, try to generate key without logging in first. |
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.
Remove the attempt to generate a key without logging in.
If token login is required, UTIL_CTX_login() must be called, as a private object cannot be created unless the session is logged in as a normal user (CKR_USER_NOT_LOGGED_IN error).
src/util.h
Outdated
| void UTIL_CTX_set_vlog_a(UTIL_CTX *ctx, PKCS11_VLOG_A_CB vlog); | ||
| void UTIL_CTX_set_debug_level(UTIL_CTX *ctx, int debug_level); | ||
| void UTIL_CTX_log(UTIL_CTX *ctx, int level, const char *format, ...); | ||
| int UTIL_CTX_hex_to_bin(UTIL_CTX *ctx, const char *in, char *out, size_t *outlen); |
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.
Remove the unused function UTIL_CTX_hex_to_bin().
tests/keygen-prov.c
Outdated
| char *key_pass = argv[3]; | ||
|
|
||
| /* Load pkcs11prov and default providers */ | ||
| if (!providers_load()) { |
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.
Unfortunately, the OpenSSL provider currently only supports retrieving objects from the token, meaning it cannot be used for key generation.
Please remove the key generation test for the provider.
src/util.h
Outdated
|
|
||
| int UTIL_CTX_set_pin(UTIL_CTX *ctx, const char *pin); | ||
| void UTIL_CTX_set_force_login(UTIL_CTX *ctx, int force_login); | ||
| int UTIL_CTX_get_force_login(UTIL_CTX *ctx); |
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.
Remove the unused function UTIL_CTX_get_force_login().
olszomal
left a comment
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.
Generally well done! Some minor style tweaks, but also a significant issue that needs attention.
src/eng_back.c
Outdated
|
|
||
| /* Try with logging in */ | ||
| ERR_clear_error(); | ||
| if (found_slot->token->loginRequired && UTIL_CTX_login(ctx->util_ctx, |
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.
If token login is required, UTIL_CTX_login() must be called. However, try to generate a key pair.
src/p11_key.c
Outdated
| curve_obj = OBJ_nid2obj(curve_nid); | ||
| if (!curve_obj) | ||
| return -1; | ||
| // convert to DER format and take just the length |
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.
Use C-style comments instead of C++. This note applies to all comments; sorry for the confusion.
tests/Makefile.am
Outdated
| rsa_oaep_prov_SOURCES = rsa-oaep-prov.c helpers_prov.c | ||
| store_cert_prov_SOURCES = store-cert-prov.c helpers_prov.c | ||
| check_all_prov_SOURCES = check-all-prov.c helpers_prov.c | ||
| keygen_prov_SOURCES = keygen-prov.c helpers_prov.c |
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.
Unused
tests/ec-keygen.c
Outdated
| printf("Could not generate ECC keys\n"); | ||
| goto cleanup; | ||
| } | ||
| printf("ECC keys generated\n"); | ||
|
|
||
| ecpb = ENGINE_load_public_key(engine, "2233", NULL, NULL); | ||
| ecpr = ENGINE_load_private_key(engine, "2233", NULL, NULL); | ||
| if ((ret = sign_verify_test(ecpr, ecpb)) < 0) { | ||
| printf("ECC Sign-verify failed with err code: %d\n", ret); | ||
| goto cleanup; | ||
| } | ||
| printf("ECC Sign-verify success\n"); |
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.
Formally, it should be EC keys instead of ECC keys, as EC refers specifically to Elliptic Curve keys, while ECC refers to the broader field of Elliptic Curve Cryptography.
| char *label, unsigned char *id, size_t id_len); | ||
| extern int pkcs11_rsa_keygen(PKCS11_SLOT_private *tpriv, | ||
| unsigned int bits, const char *label, const unsigned char* id, | ||
| size_t id_len, const PKCS11_params* params); |
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.
Please use TYPE *ptr instead of TYPE* ptr to follow the project's convention.
tests/ec-keygen.c
Outdated
|
|
||
| ret = 0; | ||
| cleanup: | ||
| if (!engine) |
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.
This condition is incorrect.
ENGINE_finish(engine) should be called unconditionally to release the functional reference obtained via ENGINE_init(). Please remove the if statement and call ENGINE_finish(engine); directly. Skipping it when engine == NULL is safe, as the function handles that internally.
tests/rsa-keygen.c
Outdated
|
|
||
| ret = 0; | ||
| cleanup: | ||
| if (!engine) |
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.
The condition is incorrect.
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. It also possible to configure CKA_SENSITIVE and CKA_EXTRACTABLE key attributes. 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.
olszomal
left a comment
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.
Looks good — thanks for the changes!
I’ll take care of the small style issue separately to keep things moving.
|
Please, if possible check all the source code there are a lot of identation using space instead of tab. I recomend use checkpatch from kernel to update the style. Really thank you =) |
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. Upstream-Status: Submitted [OpenSC#474] Signed-off-by: Jorge Ramirez-Ortiz <[email protected]>
Upstream-Status: Submitted [OpenSC#474] Signed-off-by: Jorge Ramirez-Ortiz <[email protected]>
These changes depend on EC support being merged [ie, OpenSC#474] Until then, this code is not upstreamable. Upstream-Status: Inappropriate [lmp specific] Signed-off-by: Jorge Ramirez-Ortiz <[email protected]>
| }; | ||
| CK_ULONG num_bits = bits; | ||
| CK_BYTE public_exponent[] = { 1, 0, 1 }; | ||
| CK_BYTE public_exponent[] = { 1, 0, 0, 0, 1 }; |
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.
Hi, I'm regularly running some tests with SoftHSM 2.6.1 and libp11. I've noticed that ever since this commit the exponent attribute has changed from the usual 65537 (0x10001) to a surprising 4294967297 (0x100000001).
Before this commit, libp11 would pass the byte array [1, 0, 1] which SoftHSM would unwrap to 65537. The new array [1, 0, 0, 0, 1 ] is unwrapped to 4294967297 obviously raising some questions.
Was this public_exponent change intentional? I'm trying to understand what the intended behavior is.
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.
Could it be an attack against implementations that assume a 32-bit public exponent? Otherwise, a non-standard composite (641 * 6700417) public exponent does not seem to be dangerous.
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.
Interesting! So the value is indeed a valid exponent? Sorry, I'm not too well-versed in cryptography. It seems then that the real limitation that got me here is that the software I use that signs the CSR does not support large public key exponents. Is there a way to specify desired public key exponent in libp11 during key generation? Also let me know if you'd rather I open an issue to move this discussion elsewhere.
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.
@istepic Would you kindly share your rationale for changing { 1, 0, 1 } to { 1, 0, 0, 0, 1 }?
As discussed in #379 and
#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:
#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:
#379 and reworked to compile and
work with some new additions to libp11 i.e. templates.