import openssl-ibmca-2.3.1-2.el9

This commit is contained in:
CentOS Sources 2023-03-28 09:21:24 +00:00 committed by Stepan Oksanichenko
parent 0ebd86497e
commit 8617aa0a2d
6 changed files with 870 additions and 699 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/openssl-ibmca-2.3.0.tar.gz
SOURCES/openssl-ibmca-2.3.1.tar.gz

View File

@ -1 +1 @@
826976fdb0a4de24affe6b7c6678665bea8cdda0 SOURCES/openssl-ibmca-2.3.0.tar.gz
5e5ac182d30787788c94b5dcdf9a3a21d209bbaf SOURCES/openssl-ibmca-2.3.1.tar.gz

View File

@ -1,689 +0,0 @@
From 1a75586c2821a55deeaa76861b1fc0539e6a3ca1 Mon Sep 17 00:00:00 2001
From: Ingo Franzki <ifranzki@linux.ibm.com>
Date: Fri, 1 Apr 2022 10:47:45 +0200
Subject: [PATCH 1/5] SPEC: Fix version number in provider-spec file
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
openssl-ibmca-provider.spec | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/openssl-ibmca-provider.spec b/openssl-ibmca-provider.spec
index a3ef1a6..6c95b54 100644
--- a/openssl-ibmca-provider.spec
+++ b/openssl-ibmca-provider.spec
@@ -5,7 +5,7 @@
# %global modulesdir %(pkg-config --variable=modulesdir libcrypto)
Name: openssl-ibmca
-Version: 2.2.3
+Version: 2.3.0
Release: 1%{?dist}
Summary: An IBMCA OpenSSL dynamic provider
@@ -45,6 +45,10 @@ mv -f src/provider/openssl.cnf.sample src/provider/openssl.cnf.sample.%{_arch}
%dir %attr(777,root,root) %{_localstatedir}/log/ibmca
%changelog
+* Fri Mar 25 2022 Juergen Christ <jchrist@linux.ibm.com> 2.3.0
+- First version including the provider
+- Fix for engine build without OpenSSL 3.0 sources
+
* Wed March 3 2022 Ingo Franzki <ifranzki@linux.ibm.com>
- Add provider support
--
2.36.1
From 76341149f2102bb628da61c2653e5911ddb81084 Mon Sep 17 00:00:00 2001
From: Juergen Christ <jchrist@linux.ibm.com>
Date: Thu, 7 Apr 2022 12:32:36 +0200
Subject: [PATCH 2/5] Adjust to new libica.
libica recently added function ica_cleanup to be called to free internal
OpenSSL 3.0 resources. This collided with our internal ica_cleanup function.
Rename that and call ica_cleanup if present.
Signed-off-by: Juergen Christ <jchrist@linux.ibm.com>
---
configure.ac | 2 ++
src/engine/e_ibmca.c | 13 ++++++++++---
src/engine/ibmca.h | 3 +++
src/provider/p_ibmca.c | 3 +++
4 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/configure.ac b/configure.ac
index 46ad10e..6434056 100644
--- a/configure.ac
+++ b/configure.ac
@@ -130,6 +130,8 @@ if test "x$enable_provider" = xyes; then
[#include <ica_api.h>])
fi
+AC_CHECK_DECLS([ica_cleanup],,,[#include <ica_api.h>])
+
AC_CONFIG_FILES([
Makefile
src/Makefile
diff --git a/src/engine/e_ibmca.c b/src/engine/e_ibmca.c
index ef17349..7335246 100644
--- a/src/engine/e_ibmca.c
+++ b/src/engine/e_ibmca.c
@@ -102,6 +102,7 @@ ica_aes_gcm_initialize_t p_ica_aes_gcm_initialize;
ica_aes_gcm_intermediate_t p_ica_aes_gcm_intermediate;
ica_aes_gcm_last_t p_ica_aes_gcm_last;
#endif
+ica_cleanup_t p_ica_cleanup;
/* save libcrypto's default ec methods */
#ifndef NO_EC
@@ -652,8 +653,10 @@ static void ibmca_destructor(void)
free((void *)LIBICA_NAME);
}
-static void ica_cleanup(void)
+static void do_ica_cleanup(void)
{
+ if (p_ica_cleanup)
+ p_ica_cleanup();
if (ibmca_dso && dlclose(ibmca_dso)) {
IBMCAerr(IBMCA_F_IBMCA_FINISH, IBMCA_R_DSO_FAILURE);
return;
@@ -725,6 +728,7 @@ static void ica_cleanup(void)
p_ica_x448_ctx_del = NULL;
p_ica_ed25519_ctx_del = NULL;
p_ica_ed448_ctx_del = NULL;
+ p_ica_cleanup = NULL;
}
static int ibmca_init(ENGINE *e)
@@ -806,6 +810,9 @@ static int ibmca_init(ENGINE *e)
BIND(ibmca_dso, ica_ed25519_ctx_del);
BIND(ibmca_dso, ica_ed448_ctx_del);
+ /* ica_cleanup is not always present and only needed for newer libraries */
+ p_ica_cleanup = (ica_cleanup_t)dlsym(ibmca_dso, "ica_cleanup");
+
/* disable fallbacks on Libica */
if (BIND(ibmca_dso, ica_set_fallback_mode))
p_ica_set_fallback_mode(0);
@@ -821,7 +828,7 @@ static int ibmca_init(ENGINE *e)
return 1;
err:
- ica_cleanup();
+ do_ica_cleanup();
return 0;
}
@@ -884,7 +891,7 @@ static int ibmca_finish(ENGINE *e)
if (p_ica_close_adapter)
p_ica_close_adapter(ibmca_handle);
- ica_cleanup();
+ do_ica_cleanup();
memset(&ibmca_registration, 0, sizeof(ibmca_registration));
return 1;
}
diff --git a/src/engine/ibmca.h b/src/engine/ibmca.h
index 382a45d..53f4ca1 100644
--- a/src/engine/ibmca.h
+++ b/src/engine/ibmca.h
@@ -616,6 +616,8 @@ int (*ica_ed25519_ctx_del_t)(ICA_ED25519_CTX **ctx);
typedef
int (*ica_ed448_ctx_del_t)(ICA_ED448_CTX **ctx);
+typedef void (*ica_cleanup_t)(void);
+
/* entry points into libica, filled out at DSO load time */
extern ica_get_functionlist_t p_ica_get_functionlist;
extern ica_set_fallback_mode_t p_ica_set_fallback_mode;
@@ -681,3 +683,4 @@ extern ica_x25519_ctx_del_t p_ica_x25519_ctx_del;
extern ica_x448_ctx_del_t p_ica_x448_ctx_del;
extern ica_ed25519_ctx_del_t p_ica_ed25519_ctx_del;
extern ica_ed448_ctx_del_t p_ica_ed448_ctx_del;
+extern ica_cleanup_t p_ica_cleanup;
diff --git a/src/provider/p_ibmca.c b/src/provider/p_ibmca.c
index d8045ba..80f0368 100644
--- a/src/provider/p_ibmca.c
+++ b/src/provider/p_ibmca.c
@@ -633,6 +633,9 @@ static void ibmca_teardown(void *vprovctx)
pthread_mutex_destroy(&provctx->debug_mutex);
P_FREE(provctx, provctx);
+#if HAVE_DECL_ICA_CLEANUP == 1
+ ica_cleanup();
+#endif
}
static const OSSL_PARAM ibmca_param_types[] = {
--
2.36.1
From 688273ec77530a44d43ad5133155e646a945bc88 Mon Sep 17 00:00:00 2001
From: Juergen Christ <jchrist@linux.ibm.com>
Date: Thu, 7 Apr 2022 12:33:44 +0200
Subject: [PATCH 3/5] Support tests in remote builds.
If the build is not wihin the source tree, tests failed since they could not
find the key files. Add support for this.
Signed-off-by: Juergen Christ <jchrist@linux.ibm.com>
---
test/engine/test.pm | 26 ++++++++++++++------------
test/provider/tls.pl | 13 +++++++------
2 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/test/engine/test.pm b/test/engine/test.pm
index 8e4b8ab..3a313e1 100644
--- a/test/engine/test.pm
+++ b/test/engine/test.pm
@@ -3,6 +3,8 @@
use strict;
use warnings;
+use FindBin;
+
package test;
sub osslversion1 {
@@ -69,16 +71,16 @@ sub rsaencdec {
my $bytes = 1 + int(rand($max_file_size));
# engine enc, no-engine dec
`openssl rand $bytes > rsaencdec.${i}.${keylen}.data.in`;
- `$eng openssl rsautl -encrypt -inkey rsa$keylen.key -in rsaencdec.${i}.${keylen}.data.in -out rsaencdec.${i}.${keylen}.data.out`;
- `openssl rsautl -decrypt -inkey rsa$keylen.key -in rsaencdec.${i}.${keylen}.data.out -out rsaencdec.${i}.${keylen}.data.dec`;
+ `$eng openssl rsautl -encrypt -inkey $FindBin::Bin/rsa$keylen.key -in rsaencdec.${i}.${keylen}.data.in -out rsaencdec.${i}.${keylen}.data.out`;
+ `openssl rsautl -decrypt -inkey $FindBin::Bin/rsa$keylen.key -in rsaencdec.${i}.${keylen}.data.out -out rsaencdec.${i}.${keylen}.data.dec`;
`cmp rsaencdec.${i}.${keylen}.data.in rsaencdec.${i}.${keylen}.data.dec`;
exit(99) if ($?);
`rm -f rsaencdec.${i}.${keylen}.data.in rsaencdec.${i}.${keylen}.out rsaencdec.${i}.${keylen}.dec`;
# no-engine enc, engine dec
`openssl rand $bytes > rsaencdec.${i}.${keylen}.data.in`;
- `openssl rsautl -encrypt -inkey rsa$keylen.key -in rsaencdec.${i}.${keylen}.data.in -out rsaencdec.${i}.${keylen}.data.out`;
- `$eng openssl rsautl -decrypt -inkey rsa$keylen.key -in rsaencdec.${i}.${keylen}.data.out -out rsaencdec.${i}.${keylen}.data.dec`;
+ `openssl rsautl -encrypt -inkey $FindBin::Bin/rsa$keylen.key -in rsaencdec.${i}.${keylen}.data.in -out rsaencdec.${i}.${keylen}.data.out`;
+ `$eng openssl rsautl -decrypt -inkey $FindBin::Bin/rsa$keylen.key -in rsaencdec.${i}.${keylen}.data.out -out rsaencdec.${i}.${keylen}.data.dec`;
`cmp rsaencdec.${i}.${keylen}.data.in rsaencdec.${i}.${keylen}.data.dec`;
exit(99) if ($?);
`rm -f rsaencdec.${i}.${keylen}.data.in rsaencdec.${i}.${keylen}.out rsaencdec.${i}.${keylen}.dec`;
@@ -100,16 +102,16 @@ sub rsasignverify {
$key .= $hex[rand(@hex)] for (1..$keylen);
# engine sign, no-engine verify
`openssl rand $bytes > rsasignverify.${i}.${keylen}.data.in`;
- `$eng openssl rsautl -sign -inkey rsa$keylen.key -in rsasignverify.${i}.${keylen}.data.in -out rsasignverify.${i}.${keylen}.data.out`;
- `openssl rsautl -verify -inkey rsa$keylen.key -in rsasignverify.${i}.${keylen}.data.out -out rsasignverify.${i}.${keylen}.data.rec`;
+ `$eng openssl rsautl -sign -inkey $FindBin::Bin/rsa$keylen.key -in rsasignverify.${i}.${keylen}.data.in -out rsasignverify.${i}.${keylen}.data.out`;
+ `openssl rsautl -verify -inkey $FindBin::Bin/rsa$keylen.key -in rsasignverify.${i}.${keylen}.data.out -out rsasignverify.${i}.${keylen}.data.rec`;
`cmp rsasignverify.${i}.${keylen}.data.in rsasignverify.${i}.${keylen}.data.rec`;
exit(99) if ($?);
`rm -f rsasignverify.${i}.${keylen}.data.in rsasignverify.${i}.${keylen}.data.out rsasignverify.${i}.${keylen}.data.rec`;
# no-engine sign, engine verify
`openssl rand $bytes > rsasignverify.${i}.${keylen}.data.in`;
- `openssl rsautl -sign -inkey rsa$keylen.key -in rsasignverify.${i}.${keylen}.data.in -out rsasignverify.${i}.${keylen}.data.out`;
- `$eng openssl rsautl -verify -inkey rsa$keylen.key -in rsasignverify.${i}.${keylen}.data.out -out rsasignverify.${i}.${keylen}.data.rec`;
+ `openssl rsautl -sign -inkey $FindBin::Bin/rsa$keylen.key -in rsasignverify.${i}.${keylen}.data.in -out rsasignverify.${i}.${keylen}.data.out`;
+ `$eng openssl rsautl -verify -inkey $FindBin::Bin/rsa$keylen.key -in rsasignverify.${i}.${keylen}.data.out -out rsasignverify.${i}.${keylen}.data.rec`;
`cmp rsasignverify.${i}.${keylen}.data.in rsasignverify.${i}.${keylen}.data.rec`;
exit(99) if ($?);
`rm -f rsasignverify.${i}.${keylen}.data.in rsasignverify.${i}.${keylen}.data.out rsasignverify.${i}.${keylen}.data.rec`;
@@ -131,15 +133,15 @@ sub dsasignverify {
my $bytes = 1 + int(rand($max_file_size));
# engine sign, no-engine verify
`openssl rand $bytes > dsa.${i}.${keylen}.data.in`;
- `$eng openssl dgst -sign dsa$keylen.key -out dsa.${i}.${keylen}.data.out dsa.${i}.${keylen}.data.in`;
- `openssl dgst -verify dsa${keylen}_pub.key -signature dsa.${i}.${keylen}.data.out dsa.${i}.${keylen}.data.in`;
+ `$eng openssl dgst -sign $FindBin::Bin/dsa$keylen.key -out dsa.${i}.${keylen}.data.out dsa.${i}.${keylen}.data.in`;
+ `openssl dgst -verify $FindBin::Bin/dsa${keylen}_pub.key -signature dsa.${i}.${keylen}.data.out dsa.${i}.${keylen}.data.in`;
exit(99) if ($?);
`rm -f dsa.${i}.${keylen}.data.in dsa.${i}.${keylen}.data.out`;
# no-engine sign, engine verify
`openssl rand $bytes > dsa.${i}.${keylen}.data.in`;
- `openssl dgst -sign dsa$keylen.key -out dsa.${i}.${keylen}.data.out dsa.${i}.${keylen}.data.in`;
- `$eng openssl dgst -verify dsa${keylen}_pub.key -signature dsa.${i}.${keylen}.data.out dsa.${i}.${keylen}.data.in`;
+ `openssl dgst -sign $FindBin::Bin/dsa$keylen.key -out dsa.${i}.${keylen}.data.out dsa.${i}.${keylen}.data.in`;
+ `$eng openssl dgst -verify $FindBin::Bin/dsa${keylen}_pub.key -signature dsa.${i}.${keylen}.data.out dsa.${i}.${keylen}.data.in`;
exit(99) if ($?);
`rm -f dsa.${i}.${keylen}.data.in dsa.${i}.${keylen}.data.out`;
}
diff --git a/test/provider/tls.pl b/test/provider/tls.pl
index c8871d4..0d9df6d 100755
--- a/test/provider/tls.pl
+++ b/test/provider/tls.pl
@@ -19,17 +19,18 @@
use strict;
use warnings;
use test;
+use FindBin;
# TLS 1.3 with RSA signatures
-test::tls(10001, "server-key-rsa.pem", "server-cert-rsa.pem", "ALL", "TLS_AES_256_GCM_SHA384", "-tls1_3");
+test::tls(10001, "$FindBin::Bin/server-key-rsa.pem", "$FindBin::Bin/server-cert-rsa.pem", "ALL", "TLS_AES_256_GCM_SHA384", "-tls1_3");
# TLS 1.3 with EC signatures
-test::tls(10002, "server-key-ec.pem", "server-cert-ec.pem", "ALL", "TLS_AES_256_GCM_SHA384", "-tls1_3");
+test::tls(10002, "$FindBin::Bin/server-key-ec.pem", "$FindBin::Bin/server-cert-ec.pem", "ALL", "TLS_AES_256_GCM_SHA384", "-tls1_3");
# TLS 1.2 with RSA signatures and ECDH key exchange
-test::tls(10003, "server-key-rsa.pem", "server-cert-rsa.pem", "ECDHE-RSA-AES256-GCM-SHA384", "\"\"", "-no_tls1_3");
+test::tls(10003, "$FindBin::Bin/server-key-rsa.pem", "$FindBin::Bin/server-cert-rsa.pem", "ECDHE-RSA-AES256-GCM-SHA384", "\"\"", "-no_tls1_3");
# TLS 1.2 with ECDSA signatures and ECDH key exchange
-test::tls(10004, "server-key-ec.pem", "server-cert-ec.pem", "ECDHE-ECDSA-AES256-GCM-SHA384", "\"\"", "-no_tls1_3");
+test::tls(10004, "$FindBin::Bin/server-key-ec.pem", "$FindBin::Bin/server-cert-ec.pem", "ECDHE-ECDSA-AES256-GCM-SHA384", "\"\"", "-no_tls1_3");
# TLS 1.2 with RSA signatures and DH key exchange
-test::tls(10005, "server-key-rsa.pem", "server-cert-rsa.pem", "DHE-RSA-AES256-GCM-SHA384", "\"\"", "-no_tls1_3");
+test::tls(10005, "$FindBin::Bin/server-key-rsa.pem", "$FindBin::Bin/server-cert-rsa.pem", "DHE-RSA-AES256-GCM-SHA384", "\"\"", "-no_tls1_3");
# TLS 1.2 with RSA signatures and RSA key exchange
-test::tls(10006, "server-key-rsa.pem", "server-cert-rsa.pem", "AES256-GCM-SHA384", "\"\"", "-no_tls1_3");
+test::tls(10006, "$FindBin::Bin/server-key-rsa.pem", "$FindBin::Bin/server-cert-rsa.pem", "AES256-GCM-SHA384", "\"\"", "-no_tls1_3");
--
2.36.1
From c0d384b72f280a4bd1c71407df0583da1847f5cb Mon Sep 17 00:00:00 2001
From: Ingo Franzki <ifranzki@linux.ibm.com>
Date: Thu, 12 May 2022 11:20:18 +0200
Subject: [PATCH 4/5] provider: Adapt keymgmt_match() implementations to
OpenSSL
OpenSSL commit ee22a3741e3fc27c981e7f7e9bcb8d3342b0c65a changed the
OpenSSL provider's keymgmt_match() function to be not so strict with
the selector bits in regards to matching different key parts.
Adapt the provider's match functions accordingly.
This means, that if the public key is selected to be matched, and the
public key matches (together with any also selected parameters),
then the private key is no longer checked, although it may also be
selected to be matched. This is according to how the OpenSSL function
EVP_PKEY_eq() is supposed to behave.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
src/provider/dh_keymgmt.c | 2 +-
src/provider/ec_keymgmt.c | 5 +++--
src/provider/rsa_keymgmt.c | 8 +++++---
3 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/src/provider/dh_keymgmt.c b/src/provider/dh_keymgmt.c
index 48ba739..3180158 100644
--- a/src/provider/dh_keymgmt.c
+++ b/src/provider/dh_keymgmt.c
@@ -1000,7 +1000,7 @@ static int ibmca_keymgmt_dh_match(const void *vkey1, const void *vkey2,
}
}
- if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ if (!checked && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
if (key1->dh.priv != NULL || key2->dh.priv != NULL) {
ok = ok && (BN_cmp(key1->dh.priv, key2->dh.priv) == 0);
checked = 1;
diff --git a/src/provider/ec_keymgmt.c b/src/provider/ec_keymgmt.c
index d898c6a..d39b1e2 100644
--- a/src/provider/ec_keymgmt.c
+++ b/src/provider/ec_keymgmt.c
@@ -751,7 +751,7 @@ static int ibmca_keymgmt_ec_match(const void *vkey1, const void *vkey2,
const struct ibmca_key *key2 = vkey2;
BIGNUM *x1 = NULL, *y1 = NULL, *d1 = NULL;
BIGNUM *x2 = NULL, *y2 = NULL, *d2 = NULL;
- int ok = 1, rc1, rc2;
+ int ok = 1, rc1, rc2, checked = 0;
if (key1 == NULL || key2 == NULL)
return 0;
@@ -781,9 +781,10 @@ static int ibmca_keymgmt_ec_match(const void *vkey1, const void *vkey2,
ok = ok && (rc1 == rc2 && (rc1 == -1 ||
(BN_cmp(x1, x2) == 0 && BN_cmp(y1, y2) == 0)));
+ checked = 1;
}
- if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+ if (!checked && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
rc1 = ibmca_keymgmt_ec_priv_key_as_bn(key1, &d1);
if (rc1 == 0) {
ok = 0;
diff --git a/src/provider/rsa_keymgmt.c b/src/provider/rsa_keymgmt.c
index 61f7744..9278327 100644
--- a/src/provider/rsa_keymgmt.c
+++ b/src/provider/rsa_keymgmt.c
@@ -641,7 +641,7 @@ static int ibmca_keymgmt_rsa_match(const void *vkey1, const void *vkey2,
{
const struct ibmca_key *key1 = vkey1;
const struct ibmca_key *key2 = vkey2;
- int ok = 1;
+ int ok = 1, checked = 0;
if (key1 == NULL || key2 == NULL)
return 0;
@@ -652,7 +652,7 @@ static int ibmca_keymgmt_rsa_match(const void *vkey1, const void *vkey2,
if (ibmca_keymgmt_match(key1, key2) == 0)
return 0;
- if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
ok = ok && (key1->rsa.public.key_length ==
key2->rsa.public.key_length &&
memcmp(key1->rsa.public.exponent,
@@ -661,8 +661,10 @@ static int ibmca_keymgmt_rsa_match(const void *vkey1, const void *vkey2,
memcmp(key1->rsa.public.modulus,
key2->rsa.public.modulus,
key1->rsa.public.key_length) == 0);
+ checked = 1;
+ }
- if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ if (!checked && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
ok = ok && (key1->rsa.private.key_length ==
key2->rsa.private.key_length &&
CRYPTO_memcmp(key1->rsa.private.p,
--
2.36.1
From 49be3a5c9c1258e0dc15bbc50d5aa04a0ba4ba66 Mon Sep 17 00:00:00 2001
From: Ingo Franzki <ifranzki@linux.ibm.com>
Date: Wed, 18 May 2022 15:41:12 +0200
Subject: [PATCH 5/5] tests: skip tests if libica does not support required
algorithms
Before actually running the tests, check if libica supports the
required algorithms. Skip the whole test if not.
This can happen when running the test on a system without appropriate
crypto adapters. This would lead to the situation that the provider would
not register itself for the required algorithms, and thus the OpenSSL
default provider would be used. This would make the tests to fail, because
it is not running with the IBMCA provider as expected by the test.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
test/provider/Makefile.am | 18 ++++++++++---
test/provider/dhkey.c | 56 ++++++++++++++++++++++++++++++++++++++
test/provider/eckey.c | 57 +++++++++++++++++++++++++++++++++++++++
test/provider/rsakey.c | 56 ++++++++++++++++++++++++++++++++++++++
4 files changed, 184 insertions(+), 3 deletions(-)
diff --git a/test/provider/Makefile.am b/test/provider/Makefile.am
index f5cb97d..b007682 100644
--- a/test/provider/Makefile.am
+++ b/test/provider/Makefile.am
@@ -20,13 +20,25 @@ TESTS = \
check_PROGRAMS = rsakey eckey dhkey threadtest
dhkey_SOURCES = dhkey.c
-dhkey_LDADD = -lcrypto
+if PROVIDER_FULL_LIBICA
+dhkey_LDADD = -lcrypto -lica
+else
+dhkey_LDADD = -lcrypto -lica-cex
+endif
eckey_SOURCES = eckey.c
-eckey_LDADD = -lcrypto
+if PROVIDER_FULL_LIBICA
+eckey_LDADD = -lcrypto -lica
+else
+eckey_LDADD = -lcrypto -lica-cex
+endif
rsakey_SOURCES = rsakey.c
-rsakey_LDADD = -lcrypto
+if PROVIDER_FULL_LIBICA
+rsakey_LDADD = -lcrypto -lica
+else
+rsakey_LDADD = -lcrypto -lica-cex
+endif
threadtest_SOURCES = threadtest.c
threadtest_LDADD = -lcrypto -lpthread
diff --git a/test/provider/dhkey.c b/test/provider/dhkey.c
index a9cea13..8829ecc 100644
--- a/test/provider/dhkey.c
+++ b/test/provider/dhkey.c
@@ -27,6 +27,8 @@
#include <openssl/core_names.h>
#include <openssl/err.h>
+#include <ica_api.h>
+
#define UNUSED(var) ((void)(var))
void setup(void)
@@ -349,6 +351,56 @@ int check_dhkey(int nid, const char *name, const char *algo)
return ret;
}
+static const unsigned int required_ica_mechs[] = { RSA_ME };
+static const unsigned int required_ica_mechs_len =
+ sizeof(required_ica_mechs) / sizeof(unsigned int);
+
+int check_libica()
+{
+ unsigned int mech_len, i, k, found = 0;
+ libica_func_list_element *mech_list = NULL;
+ int rc;
+
+ rc = ica_get_functionlist(NULL, &mech_len);
+ if (rc != 0) {
+ fprintf(stderr, "Failed to get function list from libica!\n");
+ return 77;
+ }
+
+ mech_list = calloc(sizeof(libica_func_list_element), mech_len);
+ if (mech_list == NULL) {
+ fprintf(stderr, "Failed to allocate memory for function list!\n");
+ return 77;
+ }
+
+ rc = ica_get_functionlist(mech_list, &mech_len);
+ if (rc != 0) {
+ fprintf(stderr, "Failed to get function list from libica!\n");
+ free(mech_list);
+ return 77;
+ }
+
+ for (i = 0; i < mech_len; i++) {
+ for (k = 0; k < required_ica_mechs_len; k++) {
+ if (mech_list[i].mech_mode_id == required_ica_mechs[k]) {
+ if (mech_list[i].flags &
+ (ICA_FLAG_SW | ICA_FLAG_SHW | ICA_FLAG_DHW))
+ found++;
+ }
+ }
+ }
+
+ free(mech_list);
+
+ if (found < required_ica_mechs_len) {
+ fprintf(stderr,
+ "Libica does not support the required algorithms, skipping.\n");
+ return 77;
+ }
+
+ return 0;
+}
+
int main(int argc, char **argv)
{
static const struct testparams {
@@ -389,6 +441,10 @@ int main(int argc, char **argv)
return 77;
}
+ ret = check_libica();
+ if (ret != 0)
+ return ret;
+
setup();
for (i = 0; i < (int)(sizeof(params) / sizeof(struct testparams)); ++i) {
if (!check_dhkey(params[i].nid, params[i].name, "DH")) {
diff --git a/test/provider/eckey.c b/test/provider/eckey.c
index 279b942..b2334d7 100644
--- a/test/provider/eckey.c
+++ b/test/provider/eckey.c
@@ -27,6 +27,8 @@
#include <openssl/core_names.h>
#include <openssl/err.h>
+#include <ica_api.h>
+
#define UNUSED(var) ((void)(var))
void setup(void)
@@ -781,6 +783,57 @@ int check_eckey(int nid, const char *name)
return ret;
}
+static const unsigned int required_ica_mechs[] = { EC_DH, EC_DSA_SIGN,
+ EC_DSA_VERIFY, EC_KGEN, };
+static const unsigned int required_ica_mechs_len =
+ sizeof(required_ica_mechs) / sizeof(unsigned int);
+
+int check_libica()
+{
+ unsigned int mech_len, i, k, found = 0;
+ libica_func_list_element *mech_list = NULL;
+ int rc;
+
+ rc = ica_get_functionlist(NULL, &mech_len);
+ if (rc != 0) {
+ fprintf(stderr, "Failed to get function list from libica!\n");
+ return 77;
+ }
+
+ mech_list = calloc(sizeof(libica_func_list_element), mech_len);
+ if (mech_list == NULL) {
+ fprintf(stderr, "Failed to allocate memory for function list!\n");
+ return 77;
+ }
+
+ rc = ica_get_functionlist(mech_list, &mech_len);
+ if (rc != 0) {
+ fprintf(stderr, "Failed to get function list from libica!\n");
+ free(mech_list);
+ return 77;
+ }
+
+ for (i = 0; i < mech_len; i++) {
+ for (k = 0; k < required_ica_mechs_len; k++) {
+ if (mech_list[i].mech_mode_id == required_ica_mechs[k]) {
+ if (mech_list[i].flags &
+ (ICA_FLAG_SW | ICA_FLAG_SHW | ICA_FLAG_DHW))
+ found++;
+ }
+ }
+ }
+
+ free(mech_list);
+
+ if (found < required_ica_mechs_len) {
+ fprintf(stderr,
+ "Libica does not support the required algorithms, skipping.\n");
+ return 77;
+ }
+
+ return 0;
+}
+
int main(int argc, char **argv)
{
static const struct testparams {
@@ -822,6 +875,10 @@ int main(int argc, char **argv)
return 77;
}
+ ret = check_libica();
+ if (ret != 0)
+ return ret;
+
setup();
for (i = 0; i < (int)(sizeof(params) / sizeof(struct testparams)); ++i) {
if (!check_eckey(params[i].nid, params[i].name)) {
diff --git a/test/provider/rsakey.c b/test/provider/rsakey.c
index 0adface..366b503 100644
--- a/test/provider/rsakey.c
+++ b/test/provider/rsakey.c
@@ -26,6 +26,8 @@
#include <openssl/provider.h>
#include <openssl/err.h>
+#include <ica_api.h>
+
#define UNUSED(var) ((void)(var))
void setup(void)
@@ -729,6 +731,56 @@ int check_rsakey(int bits, const char *algo, const char *name)
return ret;
}
+static const unsigned int required_ica_mechs[] = { RSA_ME, RSA_CRT };
+static const unsigned int required_ica_mechs_len =
+ sizeof(required_ica_mechs) / sizeof(unsigned int);
+
+int check_libica()
+{
+ unsigned int mech_len, i, k, found = 0;
+ libica_func_list_element *mech_list = NULL;
+ int rc;
+
+ rc = ica_get_functionlist(NULL, &mech_len);
+ if (rc != 0) {
+ fprintf(stderr, "Failed to get function list from libica!\n");
+ return 77;
+ }
+
+ mech_list = calloc(sizeof(libica_func_list_element), mech_len);
+ if (mech_list == NULL) {
+ fprintf(stderr, "Failed to allocate memory for function list!\n");
+ return 77;
+ }
+
+ rc = ica_get_functionlist(mech_list, &mech_len);
+ if (rc != 0) {
+ fprintf(stderr, "Failed to get function list from libica!\n");
+ free(mech_list);
+ return 77;
+ }
+
+ for (i = 0; i < mech_len; i++) {
+ for (k = 0; k < required_ica_mechs_len; k++) {
+ if (mech_list[i].mech_mode_id == required_ica_mechs[k]) {
+ if (mech_list[i].flags &
+ (ICA_FLAG_SW | ICA_FLAG_SHW | ICA_FLAG_DHW))
+ found++;
+ }
+ }
+ }
+
+ free(mech_list);
+
+ if (found < required_ica_mechs_len) {
+ fprintf(stderr,
+ "Libica does not support the required algorithms, skipping.\n");
+ return 77;
+ }
+
+ return 0;
+}
+
int main(int argc, char **argv)
{
static const struct testparams {
@@ -767,6 +819,10 @@ int main(int argc, char **argv)
return 77;
}
+ ret = check_libica();
+ if (ret != 0)
+ return ret;
+
setup();
for (i = 0; i < (int)(sizeof(params) / sizeof(struct testparams)); ++i) {
if (!check_rsakey(params[i].bits, params[i].algo, params[i].name)) {
--
2.36.1

View File

@ -0,0 +1,27 @@
From b72865d57bf129c058bdb4e7301b9cb7ce16938e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dan=20Hor=C3=A1k?= <dan@danny.cz>
Date: Fri, 13 Jan 2023 18:09:49 +0100
Subject: [ibmca PATCH] warn the user when configuring the engine
The engine feature is deprecated in OpenSSL 3.0 and will be removed.
Thus warn the user and recommend using the provider instead.
---
src/engine/ibmca-engine-opensslconfig.in | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/engine/ibmca-engine-opensslconfig.in b/src/engine/ibmca-engine-opensslconfig.in
index e4b168b..ec7fbfc 100644
--- a/src/engine/ibmca-engine-opensslconfig.in
+++ b/src/engine/ibmca-engine-opensslconfig.in
@@ -140,4 +140,8 @@ this file.
|;
}
+print "WARNING: The OpenSSL engine feature is DEPRECATED since OpenSSL 3.0.\n";
+print "WARNING: It will be removed in the future.\n";
+print "WARNING: Please use the OpenSSL provider instead.\n";
+
generate();
--
2.39.0

View File

@ -0,0 +1,827 @@
From ec926d577754babce01db22274a582988c5c4e44 Mon Sep 17 00:00:00 2001
From: Ingo Franzki <ifranzki@linux.ibm.com>
Date: Wed, 12 Oct 2022 09:40:27 +0200
Subject: [PATCH 1/4] provider: Support EC parameter generation with named
curve
In general the IBMCA provider does not support EC parameter generation,
because libica only supports certain named curves. However, one can
also use EC parameter generation with a named curve, and then use such
parameter key object as template for generating other keys. One example
for this is the openssl speed utility.
Like for EC key generation, EC parameter generation only supports
parameters 'group', 'point-format', 'encoding', and 'use-cofactor-flag',
where the only accepted value for parameter 'encoding' is 'named_curve',
and the only accepted value for parameter 'use-cofactor-flag' is '0'.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
src/provider/ec_keymgmt.c | 10 ++++++++--
src/provider/p_ibmca.h | 1 +
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/provider/ec_keymgmt.c b/src/provider/ec_keymgmt.c
index d39b1e2..97516f1 100644
--- a/src/provider/ec_keymgmt.c
+++ b/src/provider/ec_keymgmt.c
@@ -928,9 +928,10 @@ static void *ibmca_keymgmt_ec_gen_init(void *vprovctx, int selection,
for (p = params; p != NULL && p->key != NULL; p++)
ibmca_debug_ctx(provctx, "param: %s", p->key);
- if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) {
+ if ((selection & (OSSL_KEYMGMT_SELECT_KEYPAIR |
+ OSSL_KEYMGMT_SELECT_ALL_PARAMETERS)) == 0) {
put_error_ctx(provctx, IBMCA_ERR_INVALID_PARAM,
- "selection is not KEYPAIR");
+ "selection is not KEYPAIR and/or parameters");
return NULL;
}
@@ -943,6 +944,7 @@ static void *ibmca_keymgmt_ec_gen_init(void *vprovctx, int selection,
}
/* set defaults */
+ ctx->ec.gen.selection = selection;
ctx->ec.gen.curve_nid = NID_undef;
ctx->ec.gen.format = POINT_CONVERSION_UNCOMPRESSED;
@@ -1223,6 +1225,9 @@ static void *ibmca_keymgmt_ec_gen(void *vgenctx, OSSL_CALLBACK *osslcb,
ibmca_debug_op_ctx(genctx, "prime_size: %lu", key->ec.prime_size);
+ if ((genctx->ec.gen.selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
+ goto out;
+
key->ec.key = ica_ec_key_new(key->ec.curve_nid, &privlen);
if (key->ec.key == NULL || key->ec.prime_size != privlen) {
ibmca_debug_op_ctx(genctx, "ica_ec_key_new failed");
@@ -1267,6 +1272,7 @@ static void *ibmca_keymgmt_ec_gen(void *vgenctx, OSSL_CALLBACK *osslcb,
return NULL;
}
+out:
ibmca_debug_op_ctx(genctx, "key: %p", key);
return key;
diff --git a/src/provider/p_ibmca.h b/src/provider/p_ibmca.h
index fa0e1ee..2b4ff8e 100644
--- a/src/provider/p_ibmca.h
+++ b/src/provider/p_ibmca.h
@@ -216,6 +216,7 @@ struct ibmca_op_ctx {
} rsa; /* For type EVP_PKEY_RSA and EVP_PKEY_RSA_PSS */
union {
struct {
+ int selection;
int curve_nid;
point_conversion_form_t format;
} gen; /* For operation EVP_PKEY_OP_KEYGEN */
--
2.39.0
From a462093d2478b287cb9a7a25131788eba16b7640 Mon Sep 17 00:00:00 2001
From: Ingo Franzki <ifranzki@linux.ibm.com>
Date: Fri, 14 Oct 2022 11:31:16 +0200
Subject: [PATCH 2/4] engine: EC: Cache ICA key in EC_KEY object
Creating a new ICA EC key via ica_ec_key_init() is time consuming, because
libica performs EC key checks on the key components.
Currently every sign, verify or derive operation creates a new ICA key, and
thus suffers from the long taking EC key checks with every operation.
Change this to create an ICA key on the first usage of an EC key, and attach
the ICA key to the EC_KEY object as ex-data. That way, subsequent operations
using the same key will reuse the attached ICA key and do not have to create
a new ICA key again.
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
src/engine/e_ibmca.c | 5 +
src/engine/ibmca.h | 1 +
src/engine/ibmca_ec.c | 411 ++++++++++++++++++++++++++++++------------
3 files changed, 306 insertions(+), 111 deletions(-)
diff --git a/src/engine/e_ibmca.c b/src/engine/e_ibmca.c
index d045828..fe21897 100644
--- a/src/engine/e_ibmca.c
+++ b/src/engine/e_ibmca.c
@@ -833,6 +833,11 @@ static int ibmca_init(ENGINE *e)
goto err;
}
+#ifndef NO_EC
+ if (!ibmca_ec_init())
+ goto err;
+#endif
+
if (!set_supported_meths(e))
goto err;
diff --git a/src/engine/ibmca.h b/src/engine/ibmca.h
index 37bdfd8..7281a5b 100644
--- a/src/engine/ibmca.h
+++ b/src/engine/ibmca.h
@@ -298,6 +298,7 @@ void ibmca_dh_destroy(void);
#define IBMCA_EC_MAX_Z_LEN IBMCA_EC_MAX_D_LEN
#ifndef OPENSSL_NO_EC
+int ibmca_ec_init(void);
void ibmca_ec_destroy(void);
int ibmca_ecdh_compute_key(unsigned char **pout, size_t *poutlen,
diff --git a/src/engine/ibmca_ec.c b/src/engine/ibmca_ec.c
index 8bc6cbf..5206ae3 100644
--- a/src/engine/ibmca_ec.c
+++ b/src/engine/ibmca_ec.c
@@ -16,6 +16,7 @@
*/
#include <stdlib.h>
+#include <pthread.h>
#include "ibmca.h"
#include "e_ibmca_err.h"
@@ -31,6 +32,251 @@ ica_ec_key_get_public_key_t p_ica_ec_key_get_public_key;
ica_ec_key_get_private_key_t p_ica_ec_key_get_private_key;
ica_ec_key_free_t p_ica_ec_key_free;
+int ec_ex_data_index = -1;
+pthread_mutex_t ec_ex_data_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+struct ibmca_ec_ex_data {
+ ICA_EC_KEY *ica_key;
+ int nid;
+ unsigned int privlen;
+};
+
+void ibmca_ec_ex_data_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
+ int idx, long argl, void *argp)
+{
+ struct ibmca_ec_ex_data *data = ptr;
+
+ if (data == NULL)
+ return;
+
+ p_ica_ec_key_free(data->ica_key);
+ OPENSSL_free(data);
+}
+
+int ibmca_ec_ex_data_dup(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from,
+#ifdef OPENSSL_VERSION_PREREQ
+ void **pptr, int idx, long argl, void *argp)
+#else
+ void *from_d, int idx, long argl, void *argp)
+#endif
+{
+#ifndef OPENSSL_VERSION_PREREQ
+ void **pptr = (void **)from_d;
+#endif
+ struct ibmca_ec_ex_data *from_data;
+ struct ibmca_ec_ex_data *to_data;
+ unsigned char Q[2 * IBMCA_EC_MAX_D_LEN];
+ unsigned char D[IBMCA_EC_MAX_D_LEN];
+ unsigned int len;
+ int rc;
+
+ if (pptr == NULL)
+ return 0;
+
+ from_data = (struct ibmca_ec_ex_data *)*pptr;
+ if (from_data == NULL)
+ return 0;
+
+ to_data = OPENSSL_zalloc(sizeof(*to_data));
+ if (to_data == NULL) {
+ return 0;
+ }
+
+ to_data->nid = from_data->nid;
+ to_data->ica_key = p_ica_ec_key_new(to_data->nid, &to_data->privlen);
+ if (to_data->ica_key == NULL) {
+ IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_ICA_EC_KEY_INIT);
+ goto error;
+ }
+
+ if (p_ica_ec_key_get_private_key(from_data->ica_key, D, &len) == 0) {
+ rc = p_ica_ec_key_init(NULL, NULL, D, to_data->ica_key);
+ if (rc != 0) {
+ IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc);
+ goto error;
+ }
+ }
+
+ if (p_ica_ec_key_get_public_key(from_data->ica_key, Q, &len) == 0) {
+ rc = p_ica_ec_key_init(Q, Q + to_data->privlen, NULL, to_data->ica_key);
+ if (rc != 0) {
+ IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc);
+ goto error;
+ }
+ }
+
+ *pptr = to_data;
+
+ return 1;
+
+error:
+ if (to_data->ica_key != NULL)
+ p_ica_ec_key_free(to_data->ica_key);
+ OPENSSL_free(to_data);
+
+ return 0;
+}
+
+static ICA_EC_KEY *ibmca_ec_make_ica_key(EC_KEY *ec_key, int *nid,
+ unsigned int *privlen)
+{
+ ICA_EC_KEY *icakey;
+ const EC_GROUP *group;
+ const EC_POINT *q;
+ const BIGNUM *bn_d;
+ BIGNUM *bn_x = NULL, *bn_y = NULL;
+ unsigned char D[IBMCA_EC_MAX_D_LEN];
+ unsigned char X[IBMCA_EC_MAX_D_LEN];
+ unsigned char Y[IBMCA_EC_MAX_D_LEN];
+ int rc, n;
+
+ /* Get group */
+ if ((group = EC_KEY_get0_group(ec_key)) == NULL) {
+ IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_INVALID_PARM);
+ return NULL;
+ }
+
+ /* Get curve nid */
+ *nid = EC_GROUP_get_curve_name(group);
+ if (*nid <= 0) {
+ IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_UNSUPPORTED_CURVE);
+ return NULL;
+ }
+
+ /* Create ICA_EC_KEY object */
+ icakey = p_ica_ec_key_new(*nid, privlen);
+ if (icakey == NULL) {
+ IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_ICA_EC_KEY_INIT);
+ return NULL;
+ }
+
+ /* Get private (D) value from EC_KEY (if available) */
+ bn_d = EC_KEY_get0_private_key(ec_key);
+ if (bn_d != NULL) {
+ /* Format (D) as char array, with leading zeros if necessary */
+ n = *privlen - BN_num_bytes(bn_d);
+ memset(D, 0, n);
+ BN_bn2bin(bn_d, &(D[n]));
+
+ /* Initialize private ICA_EC_KEY */
+ rc = p_ica_ec_key_init(NULL, NULL, D, icakey);
+ if (rc != 0) {
+ IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc);
+ goto error;
+ }
+ }
+
+ /* Get public (X and Y) values from EC_KEY (if available) */
+ q = EC_KEY_get0_public_key(ec_key);
+ if (q != NULL) {
+ /* Provide public key (X,Y) */
+ bn_x = BN_new();
+ bn_y = BN_new();
+ if (!EC_POINT_get_affine_coordinates_GFp(group, q, bn_x, bn_y, NULL)) {
+ IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_INTERNAL_ERROR);
+ goto error;
+ }
+
+ /* Format (X) as char array with leading nulls if necessary */
+ n = *privlen - BN_num_bytes(bn_x);
+ memset(X, 0, n);
+ BN_bn2bin(bn_x, &X[n]);
+
+ /* Format (Y) as char array with leading nulls if necessary */
+ n = *privlen - BN_num_bytes(bn_y);
+ memset(Y, 0, n);
+ BN_bn2bin(bn_y, &Y[n]);
+
+ /* Initialize public ICA_EC_KEY */
+ rc = p_ica_ec_key_init(X, Y, NULL, icakey);
+ if (rc != 0) {
+ IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc);
+ goto error;
+ }
+ }
+
+out:
+ BN_clear_free(bn_x);
+ BN_clear_free(bn_y);
+
+ return icakey;
+
+error:
+ p_ica_ec_key_free(icakey);
+ icakey = NULL;
+ goto out;
+}
+
+static ICA_EC_KEY *ibmca_ec_make_and_cache_ica_key(EC_KEY *ec_key,
+ unsigned int *privlen)
+{
+ struct ibmca_ec_ex_data *data, *data2;
+
+ data = OPENSSL_zalloc(sizeof(*data));
+ if (data == NULL)
+ return NULL;
+
+ data->ica_key = ibmca_ec_make_ica_key(ec_key, &data->nid, &data->privlen);
+ if (data->ica_key == NULL) {
+ OPENSSL_free(data);
+ return NULL;
+ }
+
+ /*
+ * Note that another thread could have allocated and set the ex_data for
+ * that key after the caller of this function has checked if there is
+ * already ex_data available for the key. So once we have the lock, we
+ * check again, and if there now is ex_data available, we return the
+ * ICA key from the ex_data, and free the one just created.
+ */
+ if (pthread_mutex_lock(&ec_ex_data_mutex) != 0) {
+ IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ data2 = EC_KEY_get_ex_data(ec_key, ec_ex_data_index);
+ if (data2 != NULL) {
+ pthread_mutex_unlock(&ec_ex_data_mutex);
+
+ p_ica_ec_key_free(data->ica_key);
+ OPENSSL_free(data);
+
+ *privlen = data2->privlen;
+
+ return data2->ica_key;
+ }
+
+ if (EC_KEY_set_ex_data(ec_key, ec_ex_data_index, data) != 1) {
+ IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_INTERNAL_ERROR);
+ pthread_mutex_unlock(&ec_ex_data_mutex);
+ OPENSSL_free(data);
+ return NULL;
+ }
+
+ pthread_mutex_unlock(&ec_ex_data_mutex);
+
+ *privlen = data->privlen;
+
+ return data->ica_key;
+}
+
+int ibmca_ec_init(void)
+{
+#ifdef OLDER_OPENSSL
+ return 0;
+#else
+ ec_ex_data_index = EC_KEY_get_ex_new_index(0, NULL, NULL,
+ ibmca_ec_ex_data_dup,
+ ibmca_ec_ex_data_free);
+ if (ec_ex_data_index < 0) {
+ IBMCAerr(IBMCA_F_IBMCA_INIT, IBMCA_R_EC_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return 1;
+#endif
+}
+
void ibmca_ec_destroy(void)
{
#ifdef OLDER_OPENSSL
@@ -39,6 +285,10 @@ void ibmca_ec_destroy(void)
if (ibmca_ecdh)
ECDSA_METHOD_free(ibmca_ecdsa);
#else
+ if (ec_ex_data_index >= 0) {
+ CRYPTO_free_ex_index(CRYPTO_EX_INDEX_EC_KEY, ec_ex_data_index);
+ ec_ex_data_index = -1;
+ }
if (ibmca_ec)
EC_KEY_METHOD_free(ibmca_ec);
#endif
@@ -55,17 +305,17 @@ int ibmca_ecdh_compute_key(unsigned char **pout, size_t *poutlen,
{
ICA_EC_KEY *ica_pubkey = NULL, *ica_privkey = NULL;
const EC_GROUP *group;
- BIGNUM *bn_d, *bn_x, *bn_y;
+ BIGNUM *bn_x = NULL, *bn_y = NULL;
unsigned int n, privlen;
unsigned char X[IBMCA_EC_MAX_D_LEN];
unsigned char Y[IBMCA_EC_MAX_D_LEN];
- unsigned char D[IBMCA_EC_MAX_D_LEN];
unsigned char *z_buf = NULL;
int rc, ret = 0, nid;
#ifndef OLDER_OPENSSL
int (*compute_key_sw)(unsigned char **pout, size_t *poutlen,
const EC_POINT *pub_key, const EC_KEY *ecdh) = NULL;
#endif
+ struct ibmca_ec_ex_data *data = EC_KEY_get_ex_data(ecdh, ec_ex_data_index);
/* Get group from EC_KEY */
if ((group = EC_KEY_get0_group(ecdh)) == NULL) {
@@ -76,10 +326,40 @@ int ibmca_ecdh_compute_key(unsigned char **pout, size_t *poutlen,
/* Determine curve nid */
nid = EC_GROUP_get_curve_name(group);
if (nid <= 0) {
- IBMCAerr(IBMCA_F_IBMCA_ECDH_COMPUTE_KEY, IBMCA_R_EC_INTERNAL_ERROR);
+ IBMCAerr(IBMCA_F_IBMCA_ECDH_COMPUTE_KEY, IBMCA_R_EC_UNSUPPORTED_CURVE);
+ return 0;
+ }
+
+ if (data != NULL) {
+ ica_privkey = data->ica_key;
+ privlen = data->privlen;
+ goto do_derive;
+ }
+
+ /* Create ICA_EC_KEY object for private key */
+ ica_privkey = ibmca_ec_make_and_cache_ica_key((EC_KEY*)ecdh, &privlen);
+ if (ica_privkey == NULL) {
+ /* This curve is not supported by libica. */
+ #ifdef OLDER_OPENSSL
return 0;
+ #else
+ /*
+ * EC_KEY_METHOD_get_compute_key misses the const-qualifier of the
+ * parameter in some openssl versions.
+ */
+ EC_KEY_METHOD_get_compute_key((EC_KEY_METHOD *)ossl_ec,
+ &compute_key_sw);
+ if (compute_key_sw == NULL) {
+ IBMCAerr(IBMCA_F_IBMCA_ECDH_COMPUTE_KEY,
+ IBMCA_R_EC_INTERNAL_ERROR);
+ return 0;
+ }
+
+ return compute_key_sw(pout, poutlen, pub_key, ecdh);
+ #endif
}
+do_derive:
/* Create ICA_EC_KEY object for public key */
ica_pubkey = p_ica_ec_key_new(nid, &privlen);
if (ica_pubkey == NULL) {
@@ -128,32 +408,6 @@ int ibmca_ecdh_compute_key(unsigned char **pout, size_t *poutlen,
goto end;
}
- /* Create ICA_EC_KEY object for private key */
- ica_privkey = p_ica_ec_key_new(nid, &privlen);
- if (!ica_privkey) {
- IBMCAerr(IBMCA_F_ICA_EC_KEY_NEW, IBMCA_R_EC_INTERNAL_ERROR);
- goto end;
- }
-
- /* Get private (D) value from EC_KEY */
- bn_d = (BIGNUM*)EC_KEY_get0_private_key((EC_KEY*)ecdh);
- if (bn_d == NULL) {
- IBMCAerr(IBMCA_F_IBMCA_ECDH_COMPUTE_KEY, IBMCA_R_EC_INTERNAL_ERROR);
- goto end;
- }
-
- /* Format (D) as char array, with leading zeros if necessary */
- n = privlen - BN_num_bytes(bn_d);
- memset(D, 0, n);
- BN_bn2bin(bn_d, &(D[n]));
-
- /* Initialize private ICA_EC_KEY with (D) */
- rc = p_ica_ec_key_init(NULL, NULL, D, ica_privkey);
- if (rc != 0) {
- IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc);
- goto end;
- }
-
/* Allocate memory for shared secret z, will be freed by caller */
if ((z_buf = OPENSSL_malloc(privlen)) == NULL) {
IBMCAerr(IBMCA_F_IBMCA_ECDH_COMPUTE_KEY, IBMCA_R_EC_INTERNAL_ERROR);
@@ -193,7 +447,6 @@ int ibmca_ecdh_compute_key(unsigned char **pout, size_t *poutlen,
end:
p_ica_ec_key_free(ica_pubkey);
- p_ica_ec_key_free(ica_privkey);
BN_clear_free(bn_x);
BN_clear_free(bn_y);
return ret;
@@ -210,12 +463,10 @@ ECDSA_SIG *ibmca_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
{
ECDSA_SIG *sig = NULL;
ICA_EC_KEY *icakey = NULL;
- const EC_GROUP *group;
unsigned int privlen;
- BIGNUM *r, *s, *bn_d, *kinv;
- unsigned char D[IBMCA_EC_MAX_D_LEN];
+ BIGNUM *r, *s, *kinv;
unsigned char sigret[IBMCA_EC_MAX_SIG_LEN];
- int n, nid, rc;
+ int rc;
#ifndef OLDER_OPENSSL
int (*sign_sw)(int type, const unsigned char *dgst, int dlen,
unsigned char *sig, unsigned int *siglen,
@@ -227,6 +478,7 @@ ECDSA_SIG *ibmca_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
const BIGNUM *in_kinv, const BIGNUM *in_r,
EC_KEY *eckey) = NULL;
BN_CTX *ctx;
+ struct ibmca_ec_ex_data *data = EC_KEY_get_ex_data(eckey, ec_ex_data_index);
/* Check parms: precomputed (k,r) are not supported by ibmca */
if (in_kinv != NULL || in_r != NULL) {
@@ -234,12 +486,6 @@ ECDSA_SIG *ibmca_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
return NULL;
}
- /* Get group */
- if ((group = EC_KEY_get0_group(eckey)) == NULL) {
- IBMCAerr(IBMCA_F_IBMCA_ECDSA_SIGN_SIG, IBMCA_R_EC_INVALID_PARM);
- return NULL;
- }
-
/* Check if key usable */
#ifndef OLDER_OPENSSL
if (!EC_KEY_can_sign(eckey)) {
@@ -249,15 +495,14 @@ ECDSA_SIG *ibmca_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
}
#endif
- /* Get curve nid */
- nid = EC_GROUP_get_curve_name(group);
- if (nid <= 0) {
- IBMCAerr(IBMCA_F_IBMCA_ECDSA_SIGN_SIG, IBMCA_R_EC_UNSUPPORTED_CURVE);
- return NULL;
+ if (data != NULL) {
+ icakey = data->ica_key;
+ privlen = data->privlen;
+ goto do_sign;
}
/* Create ICA_EC_KEY object */
- icakey = p_ica_ec_key_new(nid, &privlen);
+ icakey = ibmca_ec_make_and_cache_ica_key(eckey, &privlen);
if (icakey == NULL) {
/* This curve is not supported by libica. */
#ifdef OLDER_OPENSSL
@@ -287,25 +532,7 @@ ECDSA_SIG *ibmca_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
return sig;
}
- /* Get private (D) value from EC_KEY */
- bn_d = (BIGNUM*)EC_KEY_get0_private_key(eckey);
- if (bn_d == NULL) {
- IBMCAerr(IBMCA_F_IBMCA_ECDSA_SIGN_SIG, IBMCA_R_EC_INTERNAL_ERROR);
- goto end;
- }
-
- /* Format (D) as char array, with leading zeros if necessary */
- n = privlen - BN_num_bytes(bn_d);
- memset(D, 0, n);
- BN_bn2bin(bn_d, &(D[n]));
-
- /* Initialize private ICA_EC_KEY */
- rc = p_ica_ec_key_init(NULL, NULL, D, icakey);
- if (rc != 0) {
- IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc);
- goto end;
- }
-
+do_sign:
/* Call libica signing routine */
rc = p_ica_ecdsa_sign(ibmca_handle, icakey, dgst, dgst_len, sigret,
sizeof(sigret));
@@ -343,7 +570,6 @@ ECDSA_SIG *ibmca_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
s = BN_bin2bn(sigret + privlen, privlen, NULL);
sig = ECDSA_SIG_new();
-end:
#ifndef OLDER_OPENSSL
if (sig)
ECDSA_SIG_set0(sig, r, s);
@@ -357,7 +583,6 @@ end:
#endif
end2:
- p_ica_ec_key_free(icakey);
return sig;
}
@@ -372,16 +597,12 @@ end2:
int ibmca_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
const ECDSA_SIG *sig, EC_KEY *eckey)
{
- const EC_GROUP *group;
- const EC_POINT *q;
- unsigned char x_array[IBMCA_EC_MAX_D_LEN];
- unsigned char y_array[IBMCA_EC_MAX_D_LEN];
unsigned char sig_array[IBMCA_EC_MAX_Q_LEN];
BIGNUM *bn_x = NULL, *bn_y = NULL;
const BIGNUM *bn_r, *bn_s;
unsigned int privlen;
ICA_EC_KEY *icakey = NULL;
- int rc, n, nid;
+ int rc, n;
int ret = -1;
#ifndef OLDER_OPENSSL
int (*verify_sw)(int type, const unsigned char *dgst, int dgst_len,
@@ -389,6 +610,7 @@ int ibmca_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
#endif
int (*verify_sig_sw)(const unsigned char *dgst, int dgst_len,
const ECDSA_SIG *sig, EC_KEY *eckey) = NULL;
+ struct ibmca_ec_ex_data *data = EC_KEY_get_ex_data(eckey, ec_ex_data_index);
/* Check parms */
if (eckey == NULL || sig == NULL) {
@@ -404,21 +626,14 @@ int ibmca_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
}
#endif
- /* Get group */
- if ((group = EC_KEY_get0_group(eckey)) == NULL) {
- IBMCAerr(IBMCA_F_IBMCA_ECDSA_VERIFY_SIG, IBMCA_R_EC_INTERNAL_ERROR);
- return ret;
- }
-
- /* Get curve nid */
- nid = EC_GROUP_get_curve_name(group);
- if (nid <= 0) {
- IBMCAerr(IBMCA_F_IBMCA_ECDSA_VERIFY_SIG, IBMCA_R_EC_UNSUPPORTED_CURVE);
- return ret;
+ if (data != NULL) {
+ icakey = data->ica_key;
+ privlen = data->privlen;
+ goto do_verify;
}
/* Create ICA_EC_KEY object */
- icakey = p_ica_ec_key_new(nid, &privlen);
+ icakey = ibmca_ec_make_and_cache_ica_key(eckey, &privlen);
if (icakey == NULL) {
/* This curve is not supported by libica. */
#ifdef OLDER_OPENSSL
@@ -440,32 +655,7 @@ int ibmca_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
return verify_sig_sw(dgst, dgst_len, sig, eckey);
}
- /* Provide public key (X,Y) */
- bn_x = BN_new();
- bn_y = BN_new();
- q = EC_KEY_get0_public_key(eckey);
- if (!EC_POINT_get_affine_coordinates_GFp(group, q, bn_x, bn_y, NULL)) {
- IBMCAerr(IBMCA_F_IBMCA_ECDSA_VERIFY_SIG, IBMCA_R_EC_INTERNAL_ERROR);
- goto end;
- }
-
- /* Format (X) as char array with leading nulls if necessary */
- n = privlen - BN_num_bytes(bn_x);
- memset(x_array, 0, n);
- BN_bn2bin(bn_x, &(x_array[n]));
-
- /* Format (Y) as char array with leading nulls if necessary */
- n = privlen - BN_num_bytes(bn_y);
- memset(y_array, 0, n);
- BN_bn2bin(bn_y, &(y_array[n]));
-
- /* Initialize ICA_EC_KEY */
- rc = p_ica_ec_key_init(x_array, y_array, NULL, icakey);
- if (rc != 0) {
- IBMCAerr(IBMCA_F_ICA_EC_KEY_INIT, rc);
- goto end;
- }
-
+do_verify:
/* Get (r,s) from ECDSA_SIG */
#ifdef OLDER_OPENSSL
bn_r = sig->r;
@@ -517,7 +707,6 @@ int ibmca_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
}
end:
- p_ica_ec_key_free(icakey);
BN_clear_free(bn_x);
BN_clear_free(bn_y);
--
2.39.0
From 072e32bb199ff772148f1cbe0b2faadf9ab33c12 Mon Sep 17 00:00:00 2001
From: Juergen Christ <jchrist@linux.ibm.com>
Date: Thu, 27 Oct 2022 16:13:01 +0200
Subject: [PATCH 3/4] provider: Fix configuration script
Small typo in the configuration script created an invalid configuration.
Signed-off-by: Juergen Christ <jchrist@linux.ibm.com>
---
src/provider/ibmca-provider-opensslconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/provider/ibmca-provider-opensslconfig b/src/provider/ibmca-provider-opensslconfig
index 21ed6f6..d45428e 100755
--- a/src/provider/ibmca-provider-opensslconfig
+++ b/src/provider/ibmca-provider-opensslconfig
@@ -83,7 +83,7 @@ sub generate()
}
if ($providersect && $line =~ /\[\s*$providersect\s*\]/) {
print $oh "ibmca_provider = ibmca_provider_section\n";
- print $oh # Make sure that you have configured and activated at least one other provider!\n";
+ print $oh "# Make sure that you have configured and activated at least one other provider!\n";
print "WARNING: The IBMCA provider was added to section [$providersect].\n";
print "Make sure that you have configured and activated at least one other provider, e.g. the default provider!\n";
}
--
2.39.0
From e90203dbc9bf0d9a4488af470adf11852860991a Mon Sep 17 00:00:00 2001
From: Juergen Christ <jchrist@linux.ibm.com>
Date: Wed, 2 Nov 2022 14:29:35 +0100
Subject: [PATCH 4/4] provider: Fix order of providers in configuration
Since libica requires a provider that supports HMAC to be loaded and
available, fix the order of providers loaded by our sample configuration
generator. The "default" provider has to come first such that libica can do
the file integrity test with a HMAC provided by this provider when being
loaded via the ibmca provider.
Signed-off-by: Juergen Christ <jchrist@linux.ibm.com>
---
src/provider/ibmca-provider-opensslconfig | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/src/provider/ibmca-provider-opensslconfig b/src/provider/ibmca-provider-opensslconfig
index d45428e..d87fa8e 100755
--- a/src/provider/ibmca-provider-opensslconfig
+++ b/src/provider/ibmca-provider-opensslconfig
@@ -30,7 +30,7 @@ use warnings;
sub generate()
{
my ($osslconfpath);
- my ($ih, $line, $oh, $defaultcnfsect, $indefaultsect, $providersect);
+ my ($ih, $line, $oh, $defaultcnfsect, $indefaultsect, $providersect, $inprovidersect);
my ($inalgsect, $algsection);
$osslconfpath = `openssl version -d` || die "Please install openssl binary";
@@ -43,6 +43,7 @@ sub generate()
$defaultcnfsect = undef;
$indefaultsect = 0;
$providersect = undef;
+ $inprovidersect = 0;
while ($line = <$ih>) {
if ($line =~ /openssl_conf\s*=\s*(.*)/) {
$defaultcnfsect = $1;
@@ -67,13 +68,22 @@ sub generate()
} elsif ($inalgsect) {
if ($line =~ /\[\s*\w+\s*\]/) {
print $oh "default_properties = ?provider=ibmca\n";
+ $inalgsect = 0;
} elsif ($line =~ /^\s*default_properties\s*=\s*(\w+)\s*/) {
print $oh "default_properties = ?provider=ibmca\n";
print $oh "# The following was commented out by ibmca-provider-opensslconfig script\n";
print "WARNING: The default_properties in $algsection was modified by this script.\n";
$line = "# $line";
}
- }
+ } elsif ($inprovidersect) {
+ if ($line =~ /\[\s*\w+\s*\]/) {
+ $inprovidersect = 0;
+ print $oh "ibmca_provider = ibmca_provider_section\n";
+ print $oh "# Make sure that you have configured and activated at least one other provider!\n";
+ print "WARNING: The IBMCA provider was added to section [$providersect].\n";
+ print "Make sure that you have configured and activated at least one other provider, e.g. the default provider!\n";
+ }
+ }
print $oh "$line";
if ($defaultcnfsect && $line =~ /\[\s*$defaultcnfsect\s*\]/) {
$indefaultsect = 1;
@@ -81,11 +91,8 @@ sub generate()
if ($algsection && $line =~ /\[\s*$algsection\s*\]/) {
$inalgsect = 1;
}
- if ($providersect && $line =~ /\[\s*$providersect\s*\]/) {
- print $oh "ibmca_provider = ibmca_provider_section\n";
- print $oh "# Make sure that you have configured and activated at least one other provider!\n";
- print "WARNING: The IBMCA provider was added to section [$providersect].\n";
- print "Make sure that you have configured and activated at least one other provider, e.g. the default provider!\n";
+ if ($providersect && $line =~ /\[\s*$providersect\s*\]/) {
+ $inprovidersect = 1;
}
}
@@ -100,8 +107,8 @@ providers = provider_section
if (!$providersect) {
print $oh qq|
[provider_section]
-ibmca_provider = ibmca_provider_section
default = default_sect
+ibmca_provider = ibmca_provider_section
[default_sect]
activate = 1
--
2.39.0

View File

@ -1,9 +1,5 @@
%global enginesdir %(pkg-config --variable=enginesdir libcrypto)
%global modulesdir %(openssl version -m | grep -o '".*"' | tr -d '"')
# Above can be replaced by the following once OpenSSL commit
# https://github.com/openssl/openssl/commit/7fde39de848f062d6db45bf9e69439db2100b9bb
# has been included into the distribution:
# %%global modulesdir %%(pkg-config --variable=modulesdir libcrypto)
%global modulesdir %(pkg-config --variable=modulesdir libcrypto)
%if 0%{?fedora} >= 36 || 0%{?rhel} >= 9
%global with_openssl3 1
@ -12,19 +8,21 @@
Summary: A dynamic OpenSSL engine for IBMCA
Name: openssl-ibmca
Version: 2.3.0
Release: 1%{?dist}
Version: 2.3.1
Release: 2%{?dist}
License: ASL 2.0
URL: https://github.com/opencryptoki
Source0: https://github.com/opencryptoki/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz
# post GA fixes
Patch0: %{name}-%{version}-fixes.patch
# warn the user about engine being deprecated
Patch1: %{name}-2.3.1-engine-warning.patch
Requires: libica >= 4.0.0
BuildRequires: make
BuildRequires: gcc
BuildRequires: libica-devel >= 4.0.0
BuildRequires: automake libtool
BuildRequires: openssl
BuildRequires: openssl >= 3.0.5
BuildRequires: perl(FindBin)
ExclusiveArch: s390 s390x
@ -80,6 +78,14 @@ make check
%changelog
* Fri Jan 13 2023 Dan Horák <dhorak@redhat.com> - 2.3.1-2
- fix provider configuration script (#2140028)
- Resolves: #2140028
* Thu Jan 12 2023 Dan Horák <dhorak@redhat.com> - 2.3.1-1
- updated to 2.3.1 (#2110378)
- Resolves: #2110378
* Thu May 19 2022 Dan Horák <dhorak@redhat.com> - 2.3.0-1
- updated to 2.3.0 (#2044177)
- add provider for openssl 3.x (#2044185)