Compare commits

...

No commits in common. "c8" and "c9-beta" have entirely different histories.
c8 ... c9-beta

15 changed files with 1679 additions and 1210 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/libp11-0.4.10.tar.gz
SOURCES/libp11-0.4.11.tar.gz

View File

@ -1 +1 @@
9407888f8f8fd144d0003390c20729cbfb75997f SOURCES/libp11-0.4.10.tar.gz
25bd6376a41b7e10713157c7fd51e4bf5d57cdc7 SOURCES/libp11-0.4.11.tar.gz

View File

@ -0,0 +1,44 @@
From 1492020acd161ad4ba75be87041ebdecde77f54b Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Tue, 20 Apr 2021 19:07:10 +0200
Subject: [PATCH] Free memory on errors
Thanks coverity
---
src/p11_cert.c | 4 +++-
src/p11_key.c | 4 +++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/p11_cert.c b/src/p11_cert.c
index 5cc5333..d027441 100644
--- a/src/p11_cert.c
+++ b/src/p11_cert.c
@@ -185,8 +185,10 @@ static int pkcs11_init_cert(PKCS11_CTX *ctx, PKCS11_TOKEN *token,
tpriv = PRIVTOKEN(token);
tmp = OPENSSL_realloc(tpriv->certs,
(tpriv->ncerts + 1) * sizeof(PKCS11_CERT));
- if (!tmp)
+ if (!tmp) {
+ OPENSSL_free(cpriv);
return -1;
+ }
tpriv->certs = tmp;
cert = tpriv->certs + tpriv->ncerts++;
memset(cert, 0, sizeof(PKCS11_CERT));
diff --git a/src/p11_key.c b/src/p11_key.c
index 494520f..451398a 100644
--- a/src/p11_key.c
+++ b/src/p11_key.c
@@ -553,8 +553,10 @@ static int pkcs11_init_key(PKCS11_CTX *ctx, PKCS11_TOKEN *token,
return -1;
memset(kpriv, 0, sizeof(PKCS11_KEY_private));
tmp = OPENSSL_realloc(keys->keys, (keys->num + 1) * sizeof(PKCS11_KEY));
- if (!tmp)
+ if (!tmp) {
+ OPENSSL_free(kpriv);
return -1;
+ }
keys->keys = tmp;
key = keys->keys + keys->num++;
memset(key, 0, sizeof(PKCS11_KEY));

View File

@ -1,105 +0,0 @@
From 66ebbaac74a1f6f1960ea1049eb8e75ebbdf9782 Mon Sep 17 00:00:00 2001
From: Michal Trojnara <Michal.Trojnara@stunnel.org>
Date: Fri, 28 Feb 2020 05:42:47 +0100
Subject: [PATCH] Revert "fix use-after-free on PKCS11_pkey_meths."
This reverts commit e64496a198d4d2eb0310a22dc21be8b81367d319.
Upstream-Status: Backport [https://github.com/OpenSC/libp11/commit/66ebbaac74a1f6f1960ea1049eb8e75ebbdf9782]
---
src/p11_pkey.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/p11_pkey.c b/src/p11_pkey.c
index 8df45abd..4ed98f65 100644
--- a/src/p11_pkey.c
+++ b/src/p11_pkey.c
@@ -673,8 +673,8 @@ int PKCS11_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
EVP_PKEY_EC,
0
};
- EVP_PKEY_METHOD *pkey_method_rsa = NULL;
- EVP_PKEY_METHOD *pkey_method_ec = NULL;
+ static EVP_PKEY_METHOD *pkey_method_rsa = NULL;
+ static EVP_PKEY_METHOD *pkey_method_ec = NULL;
(void)e; /* squash the unused parameter warning */
/* all PKCS#11 engines currently share the same pkey_meths */
@@ -687,14 +687,16 @@ int PKCS11_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
/* get the EVP_PKEY_METHOD */
switch (nid) {
case EVP_PKEY_RSA:
- pkey_method_rsa = pkcs11_pkey_method_rsa();
+ if (!pkey_method_rsa)
+ pkey_method_rsa = pkcs11_pkey_method_rsa();
if (pkey_method_rsa == NULL)
return 0;
*pmeth = pkey_method_rsa;
return 1; /* success */
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
- pkey_method_ec = pkcs11_pkey_method_ec();
+ if (!pkey_method_ec)
+ pkey_method_ec = pkcs11_pkey_method_ec();
if (pkey_method_ec == NULL)
return 0;
*pmeth = pkey_method_ec;
From 5aa56b4ac45655aab20bd49bb918e649875b0f4d Mon Sep 17 00:00:00 2001
From: Michal Trojnara <Michal.Trojnara@stunnel.org>
Date: Fri, 28 Feb 2020 07:09:42 +0100
Subject: [PATCH] Disable EVP_PKEY_FLAG_DYNAMIC
Fixes #328
Upstream-Status: Backport [https://github.com/OpenSC/libp11/commit/5aa56b4ac45655aab20bd49bb918e649875b0f4d]
---
src/p11_pkey.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/p11_pkey.c b/src/p11_pkey.c
index 4ed98f65..4e0956bf 100644
--- a/src/p11_pkey.c
+++ b/src/p11_pkey.c
@@ -36,7 +36,6 @@ static int (*orig_pkey_ec_sign) (EVP_PKEY_CTX *ctx,
const unsigned char *tbs, size_t tbslen);
#endif /* OPENSSL_NO_EC */
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
struct evp_pkey_method_st {
int pkey_id;
int flags;
@@ -75,6 +74,9 @@ struct evp_pkey_method_st {
int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1, void *p2);
int (*ctrl_str) (EVP_PKEY_CTX *ctx, const char *type, const char *value);
} /* EVP_PKEY_METHOD */ ;
+
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+#define EVP_PKEY_FLAG_DYNAMIC 1
#endif
#if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER)
@@ -516,6 +518,11 @@ static EVP_PKEY_METHOD *pkcs11_pkey_method_rsa()
new_meth = EVP_PKEY_meth_new(EVP_PKEY_RSA,
EVP_PKEY_FLAG_AUTOARGLEN);
+#ifdef EVP_PKEY_FLAG_DYNAMIC
+ /* do not allow OpenSSL to free this object */
+ new_meth->flags &= ~EVP_PKEY_FLAG_DYNAMIC;
+#endif
+
EVP_PKEY_meth_copy(new_meth, orig_meth);
EVP_PKEY_meth_set_sign(new_meth,
@@ -655,6 +662,11 @@ static EVP_PKEY_METHOD *pkcs11_pkey_method_ec()
new_meth = EVP_PKEY_meth_new(EVP_PKEY_EC,
EVP_PKEY_FLAG_AUTOARGLEN);
+#ifdef EVP_PKEY_FLAG_DYNAMIC
+ /* do not allow OpenSSL to free this object */
+ new_meth->flags &= ~EVP_PKEY_FLAG_DYNAMIC;
+#endif
+
EVP_PKEY_meth_copy(new_meth, orig_meth);
EVP_PKEY_meth_set_sign(new_meth,

View File

@ -1,38 +0,0 @@
From d2f900a51de27f2d9229b0ae785c02ac272bd525 Mon Sep 17 00:00:00 2001
From: Mateusz Kwiatkowski <m.kwiatkowski@avsystem.com>
Date: Thu, 10 Sep 2020 15:47:41 +0200
Subject: [PATCH] Fix potential leak in RSA method
Upstream-Status: Backport [https://github.com/OpenSC/libp11/commit/5caa2779762c3d760f33b70cd9e1f70f15f3ea57]
---
src/p11_rsa.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/p11_rsa.c b/src/p11_rsa.c
index 221513c7..b6beef0b 100644
--- a/src/p11_rsa.c
+++ b/src/p11_rsa.c
@@ -352,6 +352,11 @@ int (*RSA_meth_get_priv_dec(const RSA_METHOD *meth))
return meth->rsa_priv_dec;
}
+static int (*RSA_meth_get_finish(const RSA_METHOD *meth)) (RSA *rsa)
+{
+ return meth->finish;
+}
+
#endif
static int pkcs11_rsa_priv_dec_method(int flen, const unsigned char *from,
@@ -383,6 +388,11 @@ static int pkcs11_rsa_priv_enc_method(int flen, const unsigned char *from,
static int pkcs11_rsa_free_method(RSA *rsa)
{
RSA_set_ex_data(rsa, rsa_ex_index, NULL);
+ int (*orig_rsa_free_method)(RSA *rsa) =
+ RSA_meth_get_finish(RSA_get_default_method());
+ if (orig_rsa_free_method) {
+ return orig_rsa_free_method(rsa);
+ }
return 1;
}

View File

@ -0,0 +1,59 @@
From 433947efff5712a6a3960c53e8b99e4fe123aace Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Wed, 19 May 2021 14:23:27 +0200
Subject: [PATCH] Do not modify EC/RSA structures after assigning them to
EVP_PKEY
This was causing OpenSSL 3.0 to fail detect our RSA/EC methods and
failing the tests ({ec,rsa}-testfork.softhsm).
The OpenSSL issue:
https://github.com/openssl/openssl/issues/15350
---
src/p11_ec.c | 2 +-
src/p11_rsa.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/p11_ec.c b/src/p11_ec.c
index 294cbad..9c5ee0f 100644
--- a/src/p11_ec.c
+++ b/src/p11_ec.c
@@ -365,7 +365,6 @@ static EVP_PKEY *pkcs11_get_evp_key_ec(PKCS11_KEY *key)
EC_KEY_free(ec);
return NULL;
}
- EVP_PKEY_set1_EC_KEY(pk, ec); /* Also increments the ec ref count */
if (key->isPrivate) {
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
@@ -379,6 +378,7 @@ static EVP_PKEY *pkcs11_get_evp_key_ec(PKCS11_KEY *key)
* unless the key has the "sensitive" attribute set */
pkcs11_set_ex_data_ec(ec, key);
+ EVP_PKEY_set1_EC_KEY(pk, ec); /* Also increments the ec ref count */
EC_KEY_free(ec); /* Drops our reference to it */
return pk;
}
diff --git a/src/p11_rsa.c b/src/p11_rsa.c
index f2f3eb3..183cce2 100644
--- a/src/p11_rsa.c
+++ b/src/p11_rsa.c
@@ -286,8 +286,6 @@ static EVP_PKEY *pkcs11_get_evp_key_rsa(PKCS11_KEY *key)
RSA_free(rsa);
return NULL;
}
- EVP_PKEY_set1_RSA(pk, rsa); /* Also increments the rsa ref count */
-
if (key->isPrivate) {
RSA_set_method(rsa, PKCS11_get_rsa_method());
#if OPENSSL_VERSION_NUMBER >= 0x10100005L && !defined(LIBRESSL_VERSION_NUMBER)
@@ -304,6 +302,8 @@ static EVP_PKEY *pkcs11_get_evp_key_rsa(PKCS11_KEY *key)
rsa->flags |= RSA_FLAG_SIGN_VER;
#endif
pkcs11_set_ex_data_rsa(rsa, key);
+
+ EVP_PKEY_set1_RSA(pk, rsa); /* Also increments the rsa ref count */
RSA_free(rsa); /* Drops our reference to it */
return pk;
}

View File

@ -1,929 +0,0 @@
From 3e219e92aecad385ba003c2276d58db3e80387cc Mon Sep 17 00:00:00 2001
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Date: Thu, 5 Sep 2019 18:29:53 +0200
Subject: [PATCH 1/4] tests/rsa-common: Add function to create various tokens
This allows the creation of multiple devices in the test scripts.
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
(cherry picked from commit 712e869189610f900ebf8c50090e228167b6bf8f)
---
tests/rsa-common.sh | 54 +++++++++++++++++++++++++++++++++++----------
1 file changed, 42 insertions(+), 12 deletions(-)
diff --git a/tests/rsa-common.sh b/tests/rsa-common.sh
index 7db5ba0..e6e12cb 100755
--- a/tests/rsa-common.sh
+++ b/tests/rsa-common.sh
@@ -86,13 +86,13 @@ init_db () {
# Create a new device
init_card () {
- PIN="$1"
- PUK="$2"
- DEV_LABEL="$3"
+ pin="$1"
+ puk="$2"
+ dev_label="$3"
- echo -n "* Initializing smart card... "
- ${SOFTHSM_TOOL} --init-token ${SLOT} --label "${DEV_LABEL}" \
- --so-pin "${PUK}" --pin "${PIN}" >/dev/null
+ echo -n "* Initializing smart card ${dev_label}..."
+ ${SOFTHSM_TOOL} --init-token ${SLOT} --label "${dev_label}" \
+ --so-pin "${puk}" --pin "${pin}" >/dev/null
if test $? = 0; then
echo ok
else
@@ -103,22 +103,26 @@ init_card () {
# Import objects to the token
import_objects () {
- ID=$1
- OBJ_LABEL=$2
+ id=$1
+ obj_label=$2
+ token_label=$3
- pkcs11-tool -p ${PIN} --module ${MODULE} -d ${ID} -a ${OBJ_LABEL} -l -w \
+ pkcs11-tool -p ${PIN} --module ${MODULE} -d ${id} \
+ --token-label ${token_label} -a ${obj_label} -l -w \
${srcdir}/rsa-prvkey.der -y privkey >/dev/null
if test $? != 0;then
exit 1;
fi
- pkcs11-tool -p ${PIN} --module ${MODULE} -d ${ID} -a ${OBJ_LABEL} -l -w \
+ pkcs11-tool -p ${PIN} --module ${MODULE} -d ${id} \
+ --token-label ${token_label} -a ${obj_label} -l -w \
${srcdir}/rsa-pubkey.der -y pubkey >/dev/null
if test $? != 0;then
exit 1;
fi
- pkcs11-tool -p ${PIN} --module ${MODULE} -d ${ID} -a ${OBJ_LABEL} -l -w \
+ pkcs11-tool -p ${PIN} --module ${MODULE} -d ${id} \
+ --token-label ${token_label} -a ${obj_label} -l -w \
${srcdir}/rsa-cert.der -y cert >/dev/null
if test $? != 0;then
exit 1;
@@ -148,8 +152,34 @@ common_init () {
echo Importing
# Import the used objects (private key, public key, and certificate)
- import_objects 01020304 "server-key"
+ import_objects 01020304 "server-key" "libp11-test"
# List the imported objects
list_objects
}
+
+create_devices () {
+ num_devices=$1
+ pin="$2"
+ puk="$3"
+ common_label="$4"
+ object_label="$5"
+
+ i=0
+ while [ $i -le ${num_devices} ]; do
+ init_card ${pin} ${puk} "${common_label}-$i"
+
+ echo "Importing objects to token ${common_label}-$i"
+ # Import objects with different labels
+ import_objects 01020304 "${object_label}-$i" "${common_label}-$i"
+
+ pkcs11-tool -p ${pin} --module ${MODULE} -l -O --token-label \
+ "${common_label}-$i"
+ if test $? != 0;then
+ echo Failed!
+ exit 1;
+ fi
+
+ i=$(($i + 1))
+ done
+}
--
2.21.0
From 7530dc3ae1350a9968733a9318825f187bd09f77 Mon Sep 17 00:00:00 2001
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Date: Tue, 3 Sep 2019 19:04:27 +0200
Subject: [PATCH 2/4] eng_back: Search objects in all matching tokens
Previously, the search for objects would stop in the first matching
token when a more generic PKCS#11 URI was provided (e.g.
"pkcs11:type=public"). This change makes the search continue past the
first matching token if the object was not found.
In ctx_load_{key, cert}(), the search will try to login only if a single
token matched the search. This is to avoid trying the provided PIN
against all matching tokens which could lock the devices.
This also makes the search for objects to ignore uninitialized tokens
and to avoid trying to login when the token does not require login.
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
(cherry picked from commit 85a91f4502d48371df0d392d19cecfbced2388c0)
---
src/eng_back.c | 393 +++++++++++++++--------
tests/Makefile.am | 4 +-
tests/pkcs11-uri-without-token.softhsm | 62 ++++
tests/search-all-matching-tokens.softhsm | 106 ++++++
4 files changed, 426 insertions(+), 139 deletions(-)
create mode 100755 tests/pkcs11-uri-without-token.softhsm
create mode 100755 tests/search-all-matching-tokens.softhsm
diff --git a/src/eng_back.c b/src/eng_back.c
index 39a685a..afa6271 100644
--- a/src/eng_back.c
+++ b/src/eng_back.c
@@ -375,7 +375,7 @@ static X509 *ctx_load_cert(ENGINE_CTX *ctx, const char *s_slot_cert_id,
const int login)
{
PKCS11_SLOT *slot;
- PKCS11_SLOT *found_slot = NULL;
+ PKCS11_SLOT *found_slot = NULL, **matched_slots = NULL;
PKCS11_TOKEN *tok, *match_tok = NULL;
PKCS11_CERT *certs, *selected_cert = NULL;
X509 *x509;
@@ -387,6 +387,7 @@ static X509 *ctx_load_cert(ENGINE_CTX *ctx, const char *s_slot_cert_id,
size_t tmp_pin_len = MAX_PIN_LENGTH;
int slot_nr = -1;
char flags[64];
+ size_t matched_count = 0;
if (ctx_init_libp11(ctx)) /* Delayed libp11 initialization */
return NULL;
@@ -401,11 +402,9 @@ static X509 *ctx_load_cert(ENGINE_CTX *ctx, const char *s_slot_cert_id,
"The certificate ID is not a valid PKCS#11 URI\n"
"The PKCS#11 URI format is defined by RFC7512\n");
ENGerr(ENG_F_CTX_LOAD_CERT, ENG_R_INVALID_ID);
- return NULL;
+ goto error;
}
if (tmp_pin_len > 0 && tmp_pin[0] != 0) {
- if (!login)
- return NULL; /* Process on second attempt */
ctx_destroy_pin(ctx);
ctx->pin = OPENSSL_malloc(MAX_PIN_LENGTH+1);
if (ctx->pin != NULL) {
@@ -424,7 +423,7 @@ static X509 *ctx_load_cert(ENGINE_CTX *ctx, const char *s_slot_cert_id,
"The legacy ENGINE_pkcs11 ID format is also "
"still accepted for now\n");
ENGerr(ENG_F_CTX_LOAD_CERT, ENG_R_INVALID_ID);
- return NULL;
+ goto error;
}
}
ctx_log(ctx, 1, "Looking in slot %d for certificate: ",
@@ -440,6 +439,13 @@ static X509 *ctx_load_cert(ENGINE_CTX *ctx, const char *s_slot_cert_id,
ctx_log(ctx, 1, "\n");
}
+ matched_slots = (PKCS11_SLOT **)calloc(ctx->slot_count,
+ sizeof(PKCS11_SLOT *));
+ if (matched_slots == NULL) {
+ ctx_log(ctx, 0, "Could not allocate memory for matched slots\n");
+ goto error;
+ }
+
for (n = 0; n < ctx->slot_count; n++) {
slot = ctx->slot_list + n;
flags[0] = '\0';
@@ -463,6 +469,7 @@ static X509 *ctx_load_cert(ENGINE_CTX *ctx, const char *s_slot_cert_id,
slot_nr == (int)PKCS11_get_slotid_from_slot(slot)) {
found_slot = slot;
}
+
if (match_tok && slot->token &&
(match_tok->label == NULL ||
!strcmp(match_tok->label, slot->token->label)) &&
@@ -483,75 +490,115 @@ static X509 *ctx_load_cert(ENGINE_CTX *ctx, const char *s_slot_cert_id,
slot->token->label : "no label");
}
ctx_log(ctx, 1, "\n");
- }
- if (match_tok) {
- OPENSSL_free(match_tok->model);
- OPENSSL_free(match_tok->manufacturer);
- OPENSSL_free(match_tok->serialnr);
- OPENSSL_free(match_tok->label);
- OPENSSL_free(match_tok);
- }
- if (found_slot) {
- slot = found_slot;
- } else if (match_tok) {
- ctx_log(ctx, 0, "Specified object not found\n");
- return NULL;
- } else if (slot_nr == -1) {
- if (!(slot = PKCS11_find_token(ctx->pkcs11_ctx,
- ctx->slot_list, ctx->slot_count))) {
- ctx_log(ctx, 0, "No tokens found\n");
- return NULL;
- }
- } else {
- ctx_log(ctx, 0, "Invalid slot number: %d\n", slot_nr);
- return NULL;
- }
- tok = slot->token;
+ if (found_slot && found_slot->token && !found_slot->token->initialized)
+ ctx_log(ctx, 0, "Found uninitialized token\n");
- if (tok == NULL) {
- ctx_log(ctx, 0, "Empty token found\n");
- return NULL;
+ /* Ignore slots without tokens or with uninitialized token */
+ if (found_slot && found_slot->token && found_slot->token->initialized) {
+ matched_slots[matched_count] = found_slot;
+ matched_count++;
+ }
+ found_slot = NULL;
}
- ctx_log(ctx, 1, "Found slot: %s\n", slot->description);
- ctx_log(ctx, 1, "Found token: %s\n", slot->token->label);
+ if (matched_count == 0) {
+ if (match_tok) {
+ ctx_log(ctx, 0, "Specified object not found\n");
+ goto error;
+ }
- /* In several tokens certificates are marked as private */
- if (login && !ctx_login(ctx, slot, tok,
- ctx->ui_method, ctx->callback_data)) {
- ctx_log(ctx, 0, "Login to token failed, returning NULL...\n");
- return NULL;
+ /* If the legacy slot ID format was used */
+ if (slot_nr != -1) {
+ ctx_log(ctx, 0, "Invalid slot number: %d\n", slot_nr);
+ goto error;
+ } else {
+ found_slot = PKCS11_find_token(ctx->pkcs11_ctx,
+ ctx->slot_list, ctx->slot_count);
+ /* Ignore if the the token is not initialized */
+ if (found_slot && found_slot->token &&
+ found_slot->token->initialized) {
+ matched_slots[matched_count] = found_slot;
+ matched_count++;
+ } else {
+ ctx_log(ctx, 0, "No tokens found\n");
+ goto error;
+ }
+ }
}
- if (PKCS11_enumerate_certs(tok, &certs, &cert_count)) {
- ctx_log(ctx, 0, "Unable to enumerate certificates\n");
- return NULL;
- }
+ for (n = 0; n < matched_count; n++) {
+ slot = matched_slots[n];
+ tok = slot->token;
+ if (tok == NULL) {
+ ctx_log(ctx, 0, "Empty token found\n");
+ break;
+ }
- ctx_log(ctx, 1, "Found %u cert%s:\n", cert_count,
- (cert_count <= 1) ? "" : "s");
- if ((s_slot_cert_id && *s_slot_cert_id) &&
- (cert_id_len != 0 || cert_label != NULL)) {
- for (n = 0; n < cert_count; n++) {
- PKCS11_CERT *k = certs + n;
+ ctx_log(ctx, 1, "Found slot: %s\n", slot->description);
+ ctx_log(ctx, 1, "Found token: %s\n", slot->token->label);
+
+ /* In several tokens certificates are marked as private */
+ if (login) {
+ /* Only try to login if login is required */
+ if (tok->loginRequired) {
+ /* Only try to login if a single slot matched to avoiding trying
+ * the PIN against all matching slots */
+ if (matched_count == 1) {
+ if (!ctx_login(ctx, slot, tok,
+ ctx->ui_method, ctx->callback_data)) {
+ ctx_log(ctx, 0, "Login to token failed, returning NULL...\n");
+ goto error;
+ }
+ } else {
+ ctx_log(ctx, 0, "Multiple matching slots (%lu); will not try to"
+ " login\n", matched_count);
+ for (m = 0; m < matched_count; m++){
+ slot = matched_slots[m];
+ ctx_log(ctx, 0, "[%u] %s: %s\n", m + 1,
+ slot->description? slot->description:
+ "(no description)",
+ (slot->token && slot->token->label)?
+ slot->token->label: "no label");
+ }
+ goto error;
+ }
+ }
+ }
- if (cert_label != NULL && strcmp(k->label, cert_label) == 0)
- selected_cert = k;
- if (cert_id_len != 0 && k->id_len == cert_id_len &&
- memcmp(k->id, cert_id, cert_id_len) == 0)
- selected_cert = k;
+ if (PKCS11_enumerate_certs(tok, &certs, &cert_count)) {
+ ctx_log(ctx, 0, "Unable to enumerate certificates\n");
+ continue;
}
- } else {
- for (n = 0; n < cert_count; n++) {
- PKCS11_CERT *k = certs + n;
- if (k->id && *(k->id)) {
- selected_cert = k; /* Use the first certificate with nonempty id */
- break;
+
+ ctx_log(ctx, 1, "Found %u cert%s:\n", cert_count,
+ (cert_count <= 1) ? "" : "s");
+ if ((s_slot_cert_id && *s_slot_cert_id) &&
+ (cert_id_len != 0 || cert_label != NULL)) {
+ for (m = 0; m < cert_count; m++) {
+ PKCS11_CERT *k = certs + m;
+
+ if (cert_label != NULL && strcmp(k->label, cert_label) == 0)
+ selected_cert = k;
+ if (cert_id_len != 0 && k->id_len == cert_id_len &&
+ memcmp(k->id, cert_id, cert_id_len) == 0)
+ selected_cert = k;
+ }
+ } else {
+ for (m = 0; m < cert_count; m++) {
+ PKCS11_CERT *k = certs + m;
+ if (k->id && *(k->id)) {
+ selected_cert = k; /* Use the first certificate with nonempty id */
+ break;
+ }
}
+ if (!selected_cert)
+ selected_cert = certs; /* Use the first certificate */
+ }
+
+ if (selected_cert) {
+ break;
}
- if (!selected_cert)
- selected_cert = certs; /* Use the first certificate */
}
if (selected_cert != NULL) {
@@ -561,8 +608,20 @@ static X509 *ctx_load_cert(ENGINE_CTX *ctx, const char *s_slot_cert_id,
ctx_log(ctx, 0, "Certificate not found.\n");
x509 = NULL;
}
+error:
+ /* Free the searched token data */
+ if (match_tok) {
+ OPENSSL_free(match_tok->model);
+ OPENSSL_free(match_tok->manufacturer);
+ OPENSSL_free(match_tok->serialnr);
+ OPENSSL_free(match_tok->label);
+ OPENSSL_free(match_tok);
+ }
+
if (cert_label != NULL)
OPENSSL_free(cert_label);
+ if (matched_slots != NULL)
+ free(matched_slots);
return x509;
}
@@ -605,7 +664,7 @@ static EVP_PKEY *ctx_load_key(ENGINE_CTX *ctx, const char *s_slot_key_id,
const int isPrivate, const int login)
{
PKCS11_SLOT *slot;
- PKCS11_SLOT *found_slot = NULL;
+ PKCS11_SLOT *found_slot = NULL, **matched_slots = NULL;
PKCS11_TOKEN *tok, *match_tok = NULL;
PKCS11_KEY *keys, *selected_key = NULL;
EVP_PKEY *pk = NULL;
@@ -617,6 +676,7 @@ static EVP_PKEY *ctx_load_key(ENGINE_CTX *ctx, const char *s_slot_key_id,
char tmp_pin[MAX_PIN_LENGTH+1];
size_t tmp_pin_len = MAX_PIN_LENGTH;
char flags[64];
+ size_t matched_count = 0;
if (ctx_init_libp11(ctx)) /* Delayed libp11 initialization */
goto error;
@@ -637,7 +697,9 @@ static EVP_PKEY *ctx_load_key(ENGINE_CTX *ctx, const char *s_slot_key_id,
goto error;
}
if (tmp_pin_len > 0 && tmp_pin[0] != 0) {
- if (!login)
+ /* If the searched key is public, try without login once even
+ * when the PIN is provided */
+ if (!login && isPrivate)
goto error; /* Process on second attempt */
ctx_destroy_pin(ctx);
ctx->pin = OPENSSL_malloc(MAX_PIN_LENGTH+1);
@@ -673,6 +735,13 @@ static EVP_PKEY *ctx_load_key(ENGINE_CTX *ctx, const char *s_slot_key_id,
ctx_log(ctx, 1, "\n");
}
+ matched_slots = (PKCS11_SLOT **)calloc(ctx->slot_count,
+ sizeof(PKCS11_SLOT *));
+ if (matched_slots == NULL) {
+ ctx_log(ctx, 0, "Could not allocate memory for matched slots\n");
+ goto error;
+ }
+
for (n = 0; n < ctx->slot_count; n++) {
slot = ctx->slot_list + n;
flags[0] = '\0';
@@ -696,6 +765,7 @@ static EVP_PKEY *ctx_load_key(ENGINE_CTX *ctx, const char *s_slot_key_id,
slot_nr == (int)PKCS11_get_slotid_from_slot(slot)) {
found_slot = slot;
}
+
if (match_tok && slot->token &&
(match_tok->label == NULL ||
!strcmp(match_tok->label, slot->token->label)) &&
@@ -716,92 +786,128 @@ static EVP_PKEY *ctx_load_key(ENGINE_CTX *ctx, const char *s_slot_key_id,
slot->token->label : "no label");
}
ctx_log(ctx, 1, "\n");
- }
- if (match_tok) {
- OPENSSL_free(match_tok->model);
- OPENSSL_free(match_tok->manufacturer);
- OPENSSL_free(match_tok->serialnr);
- OPENSSL_free(match_tok->label);
- OPENSSL_free(match_tok);
+ if (found_slot && found_slot->token && !found_slot->token->initialized)
+ ctx_log(ctx, 0, "Found uninitialized token\n");
+
+ /* Ignore slots without tokens or with uninitialized token */
+ if (found_slot && found_slot->token && found_slot->token->initialized) {
+ matched_slots[matched_count] = found_slot;
+ matched_count++;
+ }
+ found_slot = NULL;
}
- if (found_slot) {
- slot = found_slot;
- } else if (match_tok) {
- ctx_log(ctx, 0, "Specified object not found\n");
- goto error;
- } else if (slot_nr == -1) {
- if (!(slot = PKCS11_find_token(ctx->pkcs11_ctx,
- ctx->slot_list, ctx->slot_count))) {
- ctx_log(ctx, 0, "No tokens found\n");
+
+ if (matched_count == 0) {
+ if (match_tok) {
+ ctx_log(ctx, 0, "Specified object not found\n");
goto error;
}
- } else {
- ctx_log(ctx, 0, "Invalid slot number: %d\n", slot_nr);
- goto error;
- }
- tok = slot->token;
- if (tok == NULL) {
- ctx_log(ctx, 0, "Found empty token\n");
- goto error;
+ /* If the legacy slot ID format was used */
+ if (slot_nr != -1) {
+ ctx_log(ctx, 0, "Invalid slot number: %d\n", slot_nr);
+ goto error;
+ } else {
+ found_slot = PKCS11_find_token(ctx->pkcs11_ctx,
+ ctx->slot_list, ctx->slot_count);
+ /* Ignore if the the token is not initialized */
+ if (found_slot && found_slot->token &&
+ found_slot->token->initialized) {
+ matched_slots[matched_count] = found_slot;
+ matched_count++;
+ } else {
+ ctx_log(ctx, 0, "No tokens found\n");
+ goto error;
+ }
+ }
}
- /* The following check is non-critical to ensure interoperability
- * with some other (which ones?) PKCS#11 libraries */
- if (!tok->initialized)
- ctx_log(ctx, 0, "Found uninitialized token\n");
- ctx_log(ctx, 1, "Found slot: %s\n", slot->description);
- ctx_log(ctx, 1, "Found token: %s\n", slot->token->label);
+ for (n = 0; n < matched_count; n++) {
+ slot = matched_slots[n];
+ tok = slot->token;
+ if (tok == NULL) {
+ ctx_log(ctx, 0, "Found empty token\n");
+ break;
+ }
- /* Both private and public keys can have the CKA_PRIVATE attribute
- * set and thus require login (even to retrieve attributes!) */
- if (login && !ctx_login(ctx, slot, tok, ui_method, callback_data)) {
- ctx_log(ctx, 0, "Login to token failed, returning NULL...\n");
- goto error;
- }
+ ctx_log(ctx, 1, "Found slot: %s\n", slot->description);
+ ctx_log(ctx, 1, "Found token: %s\n", slot->token->label);
+
+ /* Both private and public keys can have the CKA_PRIVATE attribute
+ * set and thus require login (even to retrieve attributes!) */
+ if (login) {
+ /* Try to login only if login is required */
+ if (tok->loginRequired) {
+ /* Try to login only if a single slot matched to avoiding trying
+ * the PIN against all matching slots */
+ if (matched_count == 1) {
+ if (!ctx_login(ctx, slot, tok, ui_method, callback_data)) {
+ ctx_log(ctx, 0, "Login to token failed, returning NULL...\n");
+ goto error;
+ }
+ } else {
+ ctx_log(ctx, 0, "Multiple matching slots (%lu); will not try to"
+ " login\n", matched_count);
+ for (m = 0; m < matched_count; m++){
+ slot = matched_slots[m];
+ ctx_log(ctx, 1, "[%u] %s: %s\n", m + 1,
+ slot->description? slot->description:
+ "(no description)",
+ (slot->token && slot->token->label)?
+ slot->token->label: "no label");
+ }
+ goto error;
+ }
+ }
+ }
- if (isPrivate) {
- /* Make sure there is at least one private key on the token */
- if (PKCS11_enumerate_keys(tok, &keys, &key_count)) {
- ctx_log(ctx, 0, "Unable to enumerate private keys\n");
- goto error;
+ if (isPrivate) {
+ /* Make sure there is at least one private key on the token */
+ if (PKCS11_enumerate_keys(tok, &keys, &key_count)) {
+ ctx_log(ctx, 0, "Unable to enumerate private keys\n");
+ continue;
+ }
+ } else {
+ /* Make sure there is at least one public key on the token */
+ if (PKCS11_enumerate_public_keys(tok, &keys, &key_count)) {
+ ctx_log(ctx, 0, "Unable to enumerate public keys\n");
+ continue;
+ }
}
- } else {
- /* Make sure there is at least one public key on the token */
- if (PKCS11_enumerate_public_keys(tok, &keys, &key_count)) {
- ctx_log(ctx, 0, "Unable to enumerate public keys\n");
- goto error;
+ if (key_count == 0) {
+ if (login) /* Only print the error on the second attempt */
+ ctx_log(ctx, 0, "No %s keys found.\n",
+ (char *)(isPrivate ? "private" : "public"));
+ continue;
}
- }
- if (key_count == 0) {
- if (login) /* Only print the error on the second attempt */
- ctx_log(ctx, 0, "No %s keys found.\n",
- (char *)(isPrivate ? "private" : "public"));
- goto error;
- }
- ctx_log(ctx, 1, "Found %u %s key%s:\n", key_count,
- (char *)(isPrivate ? "private" : "public"),
- (key_count == 1) ? "" : "s");
-
- if (s_slot_key_id && *s_slot_key_id &&
- (key_id_len != 0 || key_label != NULL)) {
- for (n = 0; n < key_count; n++) {
- PKCS11_KEY *k = keys + n;
-
- ctx_log(ctx, 1, " %2u %c%c id=", n + 1,
- k->isPrivate ? 'P' : ' ',
- k->needLogin ? 'L' : ' ');
- dump_hex(ctx, 1, k->id, k->id_len);
- ctx_log(ctx, 1, " label=%s\n", k->label);
- if (key_label != NULL && strcmp(k->label, key_label) == 0)
- selected_key = k;
- if (key_id_len != 0 && k->id_len == key_id_len
- && memcmp(k->id, key_id, key_id_len) == 0)
- selected_key = k;
+ ctx_log(ctx, 1, "Found %u %s key%s:\n", key_count,
+ (char *)(isPrivate ? "private" : "public"),
+ (key_count == 1) ? "" : "s");
+
+ if (s_slot_key_id && *s_slot_key_id &&
+ (key_id_len != 0 || key_label != NULL)) {
+ for (m = 0; m < key_count; m++) {
+ PKCS11_KEY *k = keys + m;
+
+ ctx_log(ctx, 1, " %2u %c%c id=", m + 1,
+ k->isPrivate ? 'P' : ' ',
+ k->needLogin ? 'L' : ' ');
+ dump_hex(ctx, 1, k->id, k->id_len);
+ ctx_log(ctx, 1, " label=%s\n", k->label);
+ if (key_label != NULL && strcmp(k->label, key_label) == 0)
+ selected_key = k;
+ if (key_id_len != 0 && k->id_len == key_id_len
+ && memcmp(k->id, key_id, key_id_len) == 0)
+ selected_key = k;
+ }
+ } else {
+ selected_key = keys; /* Use the first key */
+ }
+
+ if (selected_key) {
+ break;
}
- } else {
- selected_key = keys; /* Use the first key */
}
if (selected_key != NULL) {
@@ -813,9 +919,20 @@ static EVP_PKEY *ctx_load_key(ENGINE_CTX *ctx, const char *s_slot_key_id,
ctx_log(ctx, 0, "Key not found.\n");
pk = NULL;
}
+
error:
+ /* Free the searched token data */
+ if (match_tok) {
+ OPENSSL_free(match_tok->model);
+ OPENSSL_free(match_tok->manufacturer);
+ OPENSSL_free(match_tok->serialnr);
+ OPENSSL_free(match_tok->label);
+ OPENSSL_free(match_tok);
+ }
if (key_label != NULL)
OPENSSL_free(key_label);
+ if (matched_slots != NULL)
+ free(matched_slots);
return pk;
}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 2a84403..18886df 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -28,7 +28,9 @@ dist_check_SCRIPTS = \
rsa-pss-sign.softhsm \
rsa-oaep.softhsm \
case-insensitive.softhsm \
- ec-check-privkey.softhsm
+ ec-check-privkey.softhsm \
+ pkcs11-uri-without-token.softhsm \
+ search-all-matching-tokens.softhsm
dist_check_DATA = \
rsa-cert.der rsa-prvkey.der rsa-pubkey.der \
ec-cert.der ec-prvkey.der ec-pubkey.der
diff --git a/tests/pkcs11-uri-without-token.softhsm b/tests/pkcs11-uri-without-token.softhsm
new file mode 100755
index 0000000..f82e1f4
--- /dev/null
+++ b/tests/pkcs11-uri-without-token.softhsm
@@ -0,0 +1,62 @@
+#!/bin/sh
+
+# Copyright (C) 2015 Nikos Mavrogiannopoulos
+#
+# GnuTLS is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3 of the License, or (at
+# your option) any later version.
+#
+# GnuTLS is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GnuTLS; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# This test checks if it is possible to use the keys without specifying the
+# token if there is only one initialized token available.
+
+outdir="output.$$"
+
+# Load common test functions
+. ${srcdir}/rsa-common.sh
+
+# Do the common test initialization
+common_init
+
+sed -e "s|@MODULE_PATH@|${MODULE}|g" -e \
+ "s|@ENGINE_PATH@|../src/.libs/pkcs11.so|g" \
+ <"${srcdir}/engines.cnf.in" >"${outdir}/engines.cnf"
+
+export OPENSSL_ENGINES="../src/.libs/"
+export OPENSSL_CONF="${outdir}/engines.cnf"
+
+# These URIs don't contain the token specification
+PRIVATE_KEY="pkcs11:object=server-key;type=private;pin-value=1234"
+PUBLIC_KEY="pkcs11:object=server-key;type=public;pin-value=1234"
+
+# Create input file
+echo "secret" >"${outdir}/in.txt"
+
+# Generate signature without specifying the token in the PKCS#11 URI
+openssl pkeyutl -engine pkcs11 -keyform engine -inkey "${PRIVATE_KEY}" \
+ -sign -out "${outdir}/signature.bin" -in "${outdir}/in.txt"
+if test $? != 0;then
+ echo "Failed to generate signature using PKCS#11 URI ${PRIVATE_KEY}"
+ exit 1;
+fi
+
+# Verify the signature without specifying the token in the PKCS#11 URI
+openssl pkeyutl -engine pkcs11 -keyform engine -pubin -inkey "${PUBLIC_KEY}" \
+ -verify -sigfile "${outdir}/signature.bin" -in "${outdir}/in.txt"
+if test $? != 0;then
+ echo "Failed to verify signature using PKCS#11 URI ${PUBLIC_KEY}"
+ exit 1;
+fi
+
+rm -rf "$outdir"
+
+exit 0
diff --git a/tests/search-all-matching-tokens.softhsm b/tests/search-all-matching-tokens.softhsm
new file mode 100755
index 0000000..d0810c4
--- /dev/null
+++ b/tests/search-all-matching-tokens.softhsm
@@ -0,0 +1,106 @@
+#!/bin/sh
+
+# Copyright (C) 2015 Nikos Mavrogiannopoulos
+#
+# GnuTLS is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3 of the License, or (at
+# your option) any later version.
+#
+# GnuTLS is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GnuTLS; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# This test checks if the search for objects in tokens will continue past the
+# first token found.
+#
+# Generic PKCS#11 URIs are used to make the search to match more than one
+# token. The search should be able to find the objects in each device, which are
+# labeled differently per token.
+#
+# This test also contains a negative test to verify that the engine will not try
+# to login to a token if more than one token matched the search. This is why it
+# is required to have only one match to be able to use a private key.
+
+outdir="output.$$"
+
+# Load common test functions
+. ${srcdir}/rsa-common.sh
+
+PIN=1234
+PUK=1234
+
+NUM_DEVICES=5
+
+# Initialize the SoftHSM DB
+init_db
+
+# Create some devices
+create_devices $NUM_DEVICES $PIN $PUK "libp11-test" "label"
+
+sed -e "s|@MODULE_PATH@|${MODULE}|g" -e "s|@ENGINE_PATH@|../src/.libs/pkcs11.so|g" <"${srcdir}/engines.cnf.in" >"${outdir}/engines.cnf"
+
+export OPENSSL_ENGINES="../src/.libs/"
+export OPENSSL_CONF="${outdir}/engines.cnf"
+
+PRIVATE_KEY="pkcs11:token=libp11-test-3;object=label-3;type=private;pin-value=1234"
+PRIVATE_KEY_WITHOUT_TOKEN="pkcs11:object=label-3;type=private;pin-value=1234"
+PUBLIC_KEY_ANY="pkcs11:type=public"
+CERTIFICATE="pkcs11:object=label-3;type=cert;pin-value=1234"
+
+# Create input file
+echo "secret" > "${outdir}/in.txt"
+
+# Verify that it doesn't try to login if more than one token matched the search
+openssl pkeyutl -engine pkcs11 -keyform engine \
+ -inkey "${PRIVATE_KEY_WITHOUT_TOKEN}" \
+ -sign -out "${outdir}/signature.bin" -in "${outdir}/in.txt"
+if test $? = 0;then
+ echo "Did not fail when the PKCS#11 URI matched multiple tokens"
+fi
+
+# Generate signature specifying the token in the PKCS#11 URI
+openssl pkeyutl -engine pkcs11 -keyform engine -inkey "${PRIVATE_KEY}" \
+ -sign -out "${outdir}/signature.bin" -in "${outdir}/in.txt"
+if test $? != 0;then
+ echo "Failed to sign file using PKCS#11 URI ${PRIVATE_KEY}"
+ exit 1;
+fi
+
+# Verify the signature using the public key from each token
+i=0
+while [ $i -le ${NUM_DEVICES} ]; do
+ pubkey="pkcs11:object=label-$i;type=public;pin-value=1234"
+ openssl pkeyutl -engine pkcs11 -keyform engine -pubin -inkey "${pubkey}" \
+ -verify -sigfile "${outdir}/signature.bin" -in "${outdir}/in.txt"
+ if test $? != 0;then
+ echo "Failed to verify the signature using the PKCS#11 URI ${pubkey}"
+ exit 1;
+ fi
+ i=$(($i + 1))
+done
+
+# Verify the signature using a certificate without specifying the token
+openssl pkeyutl -engine pkcs11 -keyform engine -pubin -inkey "${CERTIFICATE}" \
+ -verify -sigfile "${outdir}/signature.bin" -in "${outdir}/in.txt"
+if test $? != 0;then
+ echo "Failed to verify the signature using the PKCS#11 URI ${CERTIFICATE}"
+ exit 1;
+fi
+
+# Verify the signature using the first public key found
+openssl pkeyutl -engine pkcs11 -keyform engine -pubin -inkey "${PUBLIC_KEY_ANY}" \
+ -verify -sigfile "${outdir}/signature.bin" -in "${outdir}/in.txt"
+if test $? != 0;then
+ echo "Failed to verify the signature using the PKCS#11 URI ${PUBLIC_KEY_ANY}."
+ exit 1;
+fi
+
+rm -rf "$outdir"
+
+exit 0
--
2.21.0
From f7e9c100386e8ed9c0670e36c6023d4c928d132f Mon Sep 17 00:00:00 2001
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Date: Thu, 21 Nov 2019 16:40:45 +0100
Subject: [PATCH 3/4] eng_back: Initialize variable
The unitialized variable could be returned to the caller in case of
error, being the value undefined.
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
(cherry picked from commit f9fd7e65f15d20d4f4f767bb84dfccce02f834e5)
---
src/eng_back.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/eng_back.c b/src/eng_back.c
index afa6271..0dd697d 100644
--- a/src/eng_back.c
+++ b/src/eng_back.c
@@ -378,7 +378,7 @@ static X509 *ctx_load_cert(ENGINE_CTX *ctx, const char *s_slot_cert_id,
PKCS11_SLOT *found_slot = NULL, **matched_slots = NULL;
PKCS11_TOKEN *tok, *match_tok = NULL;
PKCS11_CERT *certs, *selected_cert = NULL;
- X509 *x509;
+ X509 *x509 = NULL;
unsigned int cert_count, n, m;
unsigned char cert_id[MAX_VALUE_LEN / 2];
size_t cert_id_len = sizeof(cert_id);
--
2.21.0
From 823a97403c80d475c5a0ba88e1f63923dd540db8 Mon Sep 17 00:00:00 2001
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Date: Mon, 25 Nov 2019 16:00:33 +0100
Subject: [PATCH 4/4] tests: Add missing exit when test case fail
The missing exit would make the test to pass even when the test case
failed.
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
(cherry picked from commit a41cbb29083545ceee8da35fa0067e402ed7d676)
---
tests/search-all-matching-tokens.softhsm | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/search-all-matching-tokens.softhsm b/tests/search-all-matching-tokens.softhsm
index d0810c4..0db697e 100755
--- a/tests/search-all-matching-tokens.softhsm
+++ b/tests/search-all-matching-tokens.softhsm
@@ -62,6 +62,7 @@ openssl pkeyutl -engine pkcs11 -keyform engine \
-sign -out "${outdir}/signature.bin" -in "${outdir}/in.txt"
if test $? = 0;then
echo "Did not fail when the PKCS#11 URI matched multiple tokens"
+ exit 1;
fi
# Generate signature specifying the token in the PKCS#11 URI
--
2.21.0

View File

@ -1,7 +1,7 @@
--- a/src/p11_rsa.c 2019-04-03 21:58:18.000000000 +0200
+++ b/src/p11_rsa.c 2019-11-28 15:46:18.898258545 +0100
@@ -478,7 +478,7 @@
if (ops == NULL)
if (!ops)
return NULL;
RSA_meth_set1_name(ops, "libp11 RSA method");
- RSA_meth_set_flags(ops, 0);

View File

@ -1,112 +0,0 @@
From 987ad38fbb16e5c4fb2f7e8ba7be50f54d108417 Mon Sep 17 00:00:00 2001
From: Henrik Riomar <henrik.riomar@gmail.com>
Date: Wed, 10 Apr 2019 13:54:17 +0200
Subject: [PATCH 1/3] add needed include for getpid()
Fixes:
p11_atfork.c: In function '_P11_get_forkid':
p11_atfork.c:78:9: warning: implicit declaration of function 'getpid'; did you mean 'getenv'? [-Wimplicit-function-declaration]
return getpid();
(cherry picked from commit 97700cb51ac1e84f5ac8bc402e6f9e0fc271d76b)
---
src/p11_atfork.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/p11_atfork.c b/src/p11_atfork.c
index 8fc8689..43c38f7 100644
--- a/src/p11_atfork.c
+++ b/src/p11_atfork.c
@@ -23,6 +23,7 @@
#include "libp11-int.h"
#ifndef _WIN32
+#include <unistd.h>
#ifndef __STDC_VERSION__
/* older than C90 */
--
2.21.0
From 8103e98e452624e254beef0fd788f66d13fc8ae6 Mon Sep 17 00:00:00 2001
From: ucq <ucq@cyberdefense.jp>
Date: Tue, 14 May 2019 12:17:45 +0900
Subject: [PATCH 2/3] fix use-after-free on PKCS11_pkey_meths.
(cherry picked from commit e64496a198d4d2eb0310a22dc21be8b81367d319)
---
src/p11_pkey.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/src/p11_pkey.c b/src/p11_pkey.c
index 7eaf761..2995881 100644
--- a/src/p11_pkey.c
+++ b/src/p11_pkey.c
@@ -666,8 +666,8 @@ int PKCS11_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
EVP_PKEY_EC,
0
};
- static EVP_PKEY_METHOD *pkey_method_rsa = NULL;
- static EVP_PKEY_METHOD *pkey_method_ec = NULL;
+ EVP_PKEY_METHOD *pkey_method_rsa = NULL;
+ EVP_PKEY_METHOD *pkey_method_ec = NULL;
(void)e; /* squash the unused parameter warning */
/* all PKCS#11 engines currently share the same pkey_meths */
@@ -680,16 +680,14 @@ int PKCS11_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
/* get the EVP_PKEY_METHOD */
switch (nid) {
case EVP_PKEY_RSA:
- if (pkey_method_rsa == NULL)
- pkey_method_rsa = pkcs11_pkey_method_rsa();
+ pkey_method_rsa = pkcs11_pkey_method_rsa();
if (pkey_method_rsa == NULL)
return 0;
*pmeth = pkey_method_rsa;
return 1; /* success */
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
- if (pkey_method_ec == NULL)
- pkey_method_ec = pkcs11_pkey_method_ec();
+ pkey_method_ec = pkcs11_pkey_method_ec();
if (pkey_method_ec == NULL)
return 0;
*pmeth = pkey_method_ec;
--
2.21.0
From d24c5dfa149a15c002d202964c513624d7ae1380 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Trojnara?= <Michal.Trojnara@stunnel.org>
Date: Wed, 14 Aug 2019 15:23:41 +0200
Subject: [PATCH 3/3] Remove an unused variable
(cherry picked from commit 5d48d2ff75918409684a6aefe5b1f3e5d8ec7f0d)
---
src/p11_pkey.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/p11_pkey.c b/src/p11_pkey.c
index 2995881..de0277e 100644
--- a/src/p11_pkey.c
+++ b/src/p11_pkey.c
@@ -545,7 +545,7 @@ static int pkcs11_try_pkey_ec_sign(EVP_PKEY_CTX *evp_pkey_ctx,
ossl_sig = ECDSA_SIG_new();
if (ossl_sig == NULL)
- return-1;
+ return -1;
pkey = EVP_PKEY_CTX_get0_pkey(evp_pkey_ctx);
if (pkey == NULL)
@@ -578,7 +578,6 @@ static int pkcs11_try_pkey_ec_sign(EVP_PKEY_CTX *evp_pkey_ctx,
return -1;
if (!cpriv->sign_initialized) {
- int padding;
CK_MECHANISM mechanism;
memset(&mechanism, 0, sizeof mechanism);
--
2.21.0

View File

@ -0,0 +1,64 @@
From 1441c57837b71bf861081c33bb9270c65cdb5e5c Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Fri, 8 Sep 2023 10:50:02 +0200
Subject: [PATCH 1/2] Avoid unsing uninitialized value exp while dumping expiry
reported by coverity scan
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
---
src/eng_back.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/eng_back.c b/src/eng_back.c
index 022b3ea..cb7d18c 100644
--- a/src/eng_back.c
+++ b/src/eng_back.c
@@ -105,6 +105,7 @@ static void dump_expiry(ENGINE_CTX *ctx, int level,
if (!cert || !cert->x509 || !(exp = X509_get0_notAfter(cert->x509))) {
ctx_log(ctx, level, "none");
+ return;
}
if ((bio = BIO_new(BIO_s_mem())) == NULL) {
--
2.41.0
From 0de198f15a592adb656ea9f0e308a3508512050b Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Fri, 8 Sep 2023 11:29:01 +0200
Subject: [PATCH 2/2] Remove dead code
reported by coverity scan
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
---
src/eng_back.c | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/src/eng_back.c b/src/eng_back.c
index cb7d18c..28b3292 100644
--- a/src/eng_back.c
+++ b/src/eng_back.c
@@ -498,14 +498,8 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
if (matched_count == 0) {
if (match_tok) {
- if (found_slot) {
- ctx_log(ctx, 0, "The %s was not found on token %s\n",
- object_typestr, found_slot->token->label[0] ?
- found_slot->token->label : "no label");
- } else {
- ctx_log(ctx, 0, "No matching initialized token was found for %s\n",
- object_typestr);
- }
+ ctx_log(ctx, 0, "No matching initialized token was found for %s\n",
+ object_typestr);
goto error;
}
--
2.41.0

View File

@ -0,0 +1,497 @@
From b56082faa03ce5d85fbce13583b27a7a563ebeb1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Trojnara?= <Michal.Trojnara@stunnel.org>
Date: Mon, 9 Aug 2021 01:29:12 +0200
Subject: [PATCH] Fix object searching by label
Removed checking whether obj_id is not NULL, because obj_id is a stack
pointer declared as "unsigned char obj_id[MAX_VALUE_LEN / 2]".
Removed checking whether *obj_id is not (unsigned char)0, because this
is an uninitialized stack memory reference unless an "id" value was
provided in the URI.
closes #417
closes #418
---
src/eng_back.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/eng_back.c b/src/eng_back.c
index 82eb06ec..e0a0988e 100644
--- a/src/eng_back.c
+++ b/src/eng_back.c
@@ -619,7 +619,7 @@ static void *match_cert(ENGINE_CTX *ctx, PKCS11_TOKEN *tok,
return NULL;
ctx_log(ctx, 1, "Found %u cert%s:\n", cert_count, cert_count <= 1 ? "s" : "");
- if (obj_id && *obj_id && (obj_id_len != 0 || obj_label)) {
+ if (obj_id_len != 0 || obj_label) {
for (m = 0; m < cert_count; m++) {
PKCS11_CERT *k = certs + m;
@@ -688,7 +688,7 @@ static void *match_key(ENGINE_CTX *ctx, const char *key_type,
ctx_log(ctx, 1, "Found %u %s key%s:\n", key_count, key_type,
key_count <= 1 ? "" : "s");
- if (obj_id && *obj_id && (obj_id_len != 0 || obj_label)) {
+ if (obj_id_len != 0 || obj_label) {
for (m = 0; m < key_count; m++) {
PKCS11_KEY *k = keys + m;
From ef53f58462a41dbd5033e5827a3db9f8f1f4c02c Mon Sep 17 00:00:00 2001
From: minfrin <minfrin@users.noreply.github.com>
Date: Tue, 7 Dec 2021 13:48:38 +0200
Subject: [PATCH 1/4] Tighten up debug logging to include detail of each step.
Make lists more obvious. Include details of the module being loaded,
the tokens being scanned, and the reasons for not finding objects.
---
src/eng_back.c | 31 +++++++++++++++++++------------
1 file changed, 19 insertions(+), 12 deletions(-)
diff --git a/src/eng_back.c b/src/eng_back.c
index e0a0988e..ae563593 100644
--- a/src/eng_back.c
+++ b/src/eng_back.c
@@ -298,7 +298,7 @@ static int ctx_init_libp11_unlocked(ENGINE_CTX *ctx)
if (ctx->pkcs11_ctx && ctx->slot_list)
return 0;
- ctx_log(ctx, 1, "PKCS#11: Initializing the engine\n");
+ ctx_log(ctx, 1, "PKCS#11: Initializing the engine: %s\n", ctx->module);
pkcs11_ctx = PKCS11_CTX_new();
PKCS11_CTX_init_args(pkcs11_ctx, ctx->init_args);
@@ -388,6 +388,8 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
ctx->pin_length = tmp_pin_len;
}
}
+ ctx_log(ctx, 1, "Looking in slots for %s %s login: ",
+ object_typestr, login ? "with" : "without");
} else {
n = parse_slot_id_string(ctx, object_uri, &slot_nr,
obj_id, &obj_id_len, &obj_label);
@@ -401,9 +403,9 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
ENGerr(ENG_F_CTX_LOAD_OBJECT, ENG_R_INVALID_ID);
goto error;
}
+ ctx_log(ctx, 1, "Looking in slot %d for %s %s login: ",
+ slot_nr, object_typestr, login ? "with" : "without");
}
- ctx_log(ctx, 1, "Looking in slot %d for %s: ",
- slot_nr, object_typestr);
if (obj_id_len != 0) {
ctx_log(ctx, 1, "id=");
dump_hex(ctx, 1, obj_id, obj_id_len);
@@ -457,7 +459,7 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
!strcmp(match_tok->model, slot->token->model))) {
found_slot = slot;
}
- ctx_log(ctx, 1, "[%lu] %-25.25s %-16s",
+ ctx_log(ctx, 1, "- [%lu] %-25.25s %-36s",
PKCS11_get_slotid_from_slot(slot),
slot->description, flags);
if (slot->token) {
@@ -467,9 +469,6 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
}
ctx_log(ctx, 1, "\n");
- if (found_slot && found_slot->token && !found_slot->token->initialized)
- ctx_log(ctx, 0, "Found uninitialized token\n");
-
/* Ignore slots without tokens or with uninitialized token */
if (found_slot && found_slot->token && found_slot->token->initialized) {
matched_slots[matched_count] = found_slot;
@@ -480,13 +479,20 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
if (matched_count == 0) {
if (match_tok) {
- ctx_log(ctx, 0, "Specified object not found\n");
+ if (found_slot) {
+ ctx_log(ctx, 0, "The %s was not found on token %s\n",
+ object_typestr, found_slot->token->label[0] ?
+ found_slot->token->label : "no label");
+ } else {
+ ctx_log(ctx, 0, "No matching initialized token was found for %s\n",
+ object_typestr);
+ }
goto error;
}
/* If the legacy slot ID format was used */
if (slot_nr != -1) {
- ctx_log(ctx, 0, "Invalid slot number: %d\n", slot_nr);
+ ctx_log(ctx, 0, "The %s was not found on slot %d\n", object_typestr, slot_nr);
goto error;
} else {
found_slot = PKCS11_find_token(ctx->pkcs11_ctx,
@@ -507,7 +513,7 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
slot = matched_slots[n];
tok = slot->token;
if (!tok) {
- ctx_log(ctx, 0, "Empty token found\n");
+ ctx_log(ctx, 0, "Empty slot found\n");
break;
}
@@ -531,7 +537,7 @@ static void *ctx_try_load_object(ENGINE_CTX *ctx,
" login\n", matched_count);
for (m = 0; m < matched_count; m++){
slot = matched_slots[m];
- ctx_log(ctx, 0, "[%u] %s: %s\n", m + 1,
+ ctx_log(ctx, 0, "- [%u] %s: %s\n", m + 1,
slot->description? slot->description:
"(no description)",
(slot->token && slot->token->label)?
@@ -593,7 +599,8 @@ static void *ctx_load_object(ENGINE_CTX *ctx,
obj = ctx_try_load_object(ctx, object_typestr, match_func,
object_uri, 1, ui_method, callback_data);
if (!obj) {
- ctx_log(ctx, 0, "The %s was not found.\n", object_typestr);
+ ctx_log(ctx, 0, "The %s was not found at: %s\n",
+ object_typestr, object_uri);
}
}
From 8e16e4a312636ef7ec8bfede8c476c796123bb61 Mon Sep 17 00:00:00 2001
From: minfrin <minfrin@users.noreply.github.com>
Date: Tue, 7 Dec 2021 16:42:21 +0200
Subject: [PATCH 2/4] Correct the handling of the plural on certificates.
---
src/eng_back.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/eng_back.c b/src/eng_back.c
index ae563593..355007b2 100644
--- a/src/eng_back.c
+++ b/src/eng_back.c
@@ -625,7 +625,7 @@ static void *match_cert(ENGINE_CTX *ctx, PKCS11_TOKEN *tok,
if (cert_count == 0)
return NULL;
- ctx_log(ctx, 1, "Found %u cert%s:\n", cert_count, cert_count <= 1 ? "s" : "");
+ ctx_log(ctx, 1, "Found %u certificate%s:\n", cert_count, cert_count == 1 ? "" : "s");
if (obj_id_len != 0 || obj_label) {
for (m = 0; m < cert_count; m++) {
PKCS11_CERT *k = certs + m;
From 0fe47096494db3929c99653fe9f6ecb1efbd524b Mon Sep 17 00:00:00 2001
From: minfrin <minfrin@users.noreply.github.com>
Date: Tue, 7 Dec 2021 18:04:18 +0200
Subject: [PATCH 3/4] Log how we came to choose a certificate or key.
---
src/eng_back.c | 43 +++++++++++++++++++++++++++++++++++++++----
1 file changed, 39 insertions(+), 4 deletions(-)
diff --git a/src/eng_back.c b/src/eng_back.c
index 355007b2..0372afe1 100644
--- a/src/eng_back.c
+++ b/src/eng_back.c
@@ -617,6 +617,7 @@ static void *match_cert(ENGINE_CTX *ctx, PKCS11_TOKEN *tok,
{
PKCS11_CERT *certs, *selected_cert = NULL;
unsigned int m, cert_count;
+ const char *which;
if (PKCS11_enumerate_certs(tok, &certs, &cert_count)) {
ctx_log(ctx, 0, "Unable to enumerate certificates\n");
@@ -627,9 +628,14 @@ static void *match_cert(ENGINE_CTX *ctx, PKCS11_TOKEN *tok,
ctx_log(ctx, 1, "Found %u certificate%s:\n", cert_count, cert_count == 1 ? "" : "s");
if (obj_id_len != 0 || obj_label) {
+ which = "last matching";
for (m = 0; m < cert_count; m++) {
PKCS11_CERT *k = certs + m;
+ ctx_log(ctx, 1, " %2u id=", m + 1);
+ dump_hex(ctx, 1, k->id, k->id_len);
+ ctx_log(ctx, 1, " label=%s\n", k->label ? k->label : "(null)");
+
if (obj_label && k->label && strcmp(k->label, obj_label) == 0)
selected_cert = k;
if (obj_id_len != 0 && k->id_len == obj_id_len &&
@@ -637,16 +643,32 @@ static void *match_cert(ENGINE_CTX *ctx, PKCS11_TOKEN *tok,
selected_cert = k;
}
} else {
+ which = "first (with id present)";
for (m = 0; m < cert_count; m++) {
PKCS11_CERT *k = certs + m;
- if (k->id && *k->id) {
+
+ ctx_log(ctx, 1, " %2u id=", m + 1);
+ dump_hex(ctx, 1, k->id, k->id_len);
+ ctx_log(ctx, 1, " label=%s\n", k->label ? k->label : "(null)");
+
+ if (!selected_cert && k->id && *k->id) {
selected_cert = k; /* Use the first certificate with nonempty id */
- break;
}
}
- if (!selected_cert)
+ if (!selected_cert) {
+ which = "first";
selected_cert = certs; /* Use the first certificate */
+ }
}
+
+ if (selected_cert) {
+ ctx_log(ctx, 1, "Returning %s certificate: id=", which);
+ dump_hex(ctx, 1, selected_cert->id, selected_cert->id_len);
+ ctx_log(ctx, 1, " label=%s\n", selected_cert->label ? selected_cert->label : "(null)");
+ } else {
+ ctx_log(ctx, 1, "No matching certificate returned.\n");
+ }
+
return selected_cert;
}
@@ -688,14 +710,16 @@ static void *match_key(ENGINE_CTX *ctx, const char *key_type,
{
PKCS11_KEY *selected_key = NULL;
unsigned int m;
+ const char *which;
if (key_count == 0)
return NULL;
ctx_log(ctx, 1, "Found %u %s key%s:\n", key_count, key_type,
- key_count <= 1 ? "" : "s");
+ key_count == 1 ? "" : "s");
if (obj_id_len != 0 || obj_label) {
+ which = "last matching";
for (m = 0; m < key_count; m++) {
PKCS11_KEY *k = keys + m;
@@ -704,6 +728,7 @@ static void *match_key(ENGINE_CTX *ctx, const char *key_type,
k->needLogin ? 'L' : ' ');
dump_hex(ctx, 1, k->id, k->id_len);
ctx_log(ctx, 1, " label=%s\n", k->label ? k->label : "(null)");
+
if (obj_label && k->label && strcmp(k->label, obj_label) == 0)
selected_key = k;
if (obj_id_len != 0 && k->id_len == obj_id_len
@@ -711,8 +736,18 @@ static void *match_key(ENGINE_CTX *ctx, const char *key_type,
selected_key = k;
}
} else {
+ which = "first";
selected_key = keys; /* Use the first key */
}
+
+ if (selected_key) {
+ ctx_log(ctx, 1, "Returning %s %s key: id=", which, key_type);
+ dump_hex(ctx, 1, selected_key->id, selected_key->id_len);
+ ctx_log(ctx, 1, " label=%s\n", selected_key->label ? selected_key->label : "(null)");
+ } else {
+ ctx_log(ctx, 1, "No matching %s key returned.\n", key_type);
+ }
+
return selected_key;
}
From 4eb1a0132ef34943bca78a61d2bdd8b4736a029a Mon Sep 17 00:00:00 2001
From: minfrin <minfrin@users.noreply.github.com>
Date: Thu, 9 Dec 2021 16:10:57 +0200
Subject: [PATCH 4/4] When ID and label are specified, both need to match, not
either.
To fix this id-match OR label-match was replaced with id-match AND
label-match.
A tiebreak was added when multiple matching certificates could be
returned. The certificate with the latest expiry wins, and if we
still have a tie we deterministically choose a certificate using
X509_cmp().
If we do not specify a certificate, we return the first certificate
(or first certificate with an ID) as before.
Debug logging updated to show the expiry date used in the decision.
---
src/eng_back.c | 123 +++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 108 insertions(+), 15 deletions(-)
diff --git a/src/eng_back.c b/src/eng_back.c
index 0372afe1..bb6788a1 100644
--- a/src/eng_back.c
+++ b/src/eng_back.c
@@ -87,6 +87,38 @@ static void dump_hex(ENGINE_CTX *ctx, int level,
ctx_log(ctx, level, "%02x", val[n]);
}
+static void dump_expiry(ENGINE_CTX *ctx, int level,
+ const PKCS11_CERT *cert)
+{
+ BIO *bio;
+ const ASN1_TIME *exp;
+
+ char *data = NULL;
+ int len = 0;
+
+ if (level > ctx->verbose) {
+ return;
+ }
+
+ if (!cert || !cert->x509 || !(exp = X509_get0_notAfter(cert->x509))) {
+ ctx_log(ctx, level, "none");
+ }
+
+ if ((bio = BIO_new(BIO_s_mem())) == NULL) {
+ return;
+ }
+
+ ASN1_TIME_print(bio, exp);
+
+ len = BIO_get_mem_data(bio, &data);
+
+ ctx_log(ctx, level, "%.*s", len, data);
+
+ BIO_free(bio);
+
+ return;
+}
+
/******************************************************************************/
/* PIN handling */
/******************************************************************************/
@@ -612,6 +644,39 @@ static void *ctx_load_object(ENGINE_CTX *ctx,
/* Certificate handling */
/******************************************************************************/
+static PKCS11_CERT *cert_cmp(PKCS11_CERT *a, PKCS11_CERT *b, time_t *ptime)
+{
+ const ASN1_TIME *aa, *ba;
+ int pday, psec;
+
+ /* the best certificate exists */
+ if (!a || !a->x509) {
+ return b;
+ }
+ if (!b || !b->x509) {
+ return a;
+ }
+
+ aa = X509_get0_notAfter(a->x509);
+ ba = X509_get0_notAfter(b->x509);
+
+ /* the best certificate expires last */
+ if (ASN1_TIME_diff(&pday, &psec, aa, ba)) {
+ if (pday < 0 || psec < 0) {
+ return a;
+ } else if (pday > 0 || psec > 0) {
+ return b;
+ }
+ }
+
+ /* deterministic tie break */
+ if (X509_cmp(a->x509, b->x509) < 1) {
+ return b;
+ } else {
+ return a;
+ }
+}
+
static void *match_cert(ENGINE_CTX *ctx, PKCS11_TOKEN *tok,
const unsigned char *obj_id, size_t obj_id_len, const char *obj_label)
{
@@ -628,19 +693,32 @@ static void *match_cert(ENGINE_CTX *ctx, PKCS11_TOKEN *tok,
ctx_log(ctx, 1, "Found %u certificate%s:\n", cert_count, cert_count == 1 ? "" : "s");
if (obj_id_len != 0 || obj_label) {
- which = "last matching";
+ which = "longest expiry matching";
for (m = 0; m < cert_count; m++) {
PKCS11_CERT *k = certs + m;
ctx_log(ctx, 1, " %2u id=", m + 1);
dump_hex(ctx, 1, k->id, k->id_len);
- ctx_log(ctx, 1, " label=%s\n", k->label ? k->label : "(null)");
-
- if (obj_label && k->label && strcmp(k->label, obj_label) == 0)
- selected_cert = k;
- if (obj_id_len != 0 && k->id_len == obj_id_len &&
- memcmp(k->id, obj_id, obj_id_len) == 0)
- selected_cert = k;
+ ctx_log(ctx, 1, " label=%s expiry=", k->label ? k->label : "(null)");
+ dump_expiry(ctx, 1, k);
+ ctx_log(ctx, 1, "\n");
+
+ if (obj_label && obj_id_len != 0) {
+ if (k->label && strcmp(k->label, obj_label) == 0 &&
+ k->id_len == obj_id_len &&
+ memcmp(k->id, obj_id, obj_id_len) == 0) {
+ selected_cert = cert_cmp(selected_cert, k, NULL);
+ }
+ } else if (obj_label && !obj_id_len) {
+ if (k->label && strcmp(k->label, obj_label) == 0) {
+ selected_cert = cert_cmp(selected_cert, k, NULL);
+ }
+ } else if (obj_id_len && !obj_label) {
+ if (k->id_len == obj_id_len &&
+ memcmp(k->id, obj_id, obj_id_len) == 0) {
+ selected_cert = cert_cmp(selected_cert, k, NULL);
+ }
+ }
}
} else {
which = "first (with id present)";
@@ -649,7 +727,9 @@ static void *match_cert(ENGINE_CTX *ctx, PKCS11_TOKEN *tok,
ctx_log(ctx, 1, " %2u id=", m + 1);
dump_hex(ctx, 1, k->id, k->id_len);
- ctx_log(ctx, 1, " label=%s\n", k->label ? k->label : "(null)");
+ ctx_log(ctx, 1, " label=%s expiry=", k->label ? k->label : "(null)");
+ dump_expiry(ctx, 1, k);
+ ctx_log(ctx, 1, "\n");
if (!selected_cert && k->id && *k->id) {
selected_cert = k; /* Use the first certificate with nonempty id */
@@ -664,7 +744,9 @@ static void *match_cert(ENGINE_CTX *ctx, PKCS11_TOKEN *tok,
if (selected_cert) {
ctx_log(ctx, 1, "Returning %s certificate: id=", which);
dump_hex(ctx, 1, selected_cert->id, selected_cert->id_len);
- ctx_log(ctx, 1, " label=%s\n", selected_cert->label ? selected_cert->label : "(null)");
+ ctx_log(ctx, 1, " label=%s expiry=", selected_cert->label ? selected_cert->label : "(null)");
+ dump_expiry(ctx, 1, selected_cert);
+ ctx_log(ctx, 1, "\n");
} else {
ctx_log(ctx, 1, "No matching certificate returned.\n");
}
@@ -729,11 +811,22 @@ static void *match_key(ENGINE_CTX *ctx, const char *key_type,
dump_hex(ctx, 1, k->id, k->id_len);
ctx_log(ctx, 1, " label=%s\n", k->label ? k->label : "(null)");
- if (obj_label && k->label && strcmp(k->label, obj_label) == 0)
- selected_key = k;
- if (obj_id_len != 0 && k->id_len == obj_id_len
- && memcmp(k->id, obj_id, obj_id_len) == 0)
- selected_key = k;
+ if (obj_label && obj_id_len != 0) {
+ if (k->label && strcmp(k->label, obj_label) == 0 &&
+ k->id_len == obj_id_len &&
+ memcmp(k->id, obj_id, obj_id_len) == 0) {
+ selected_key = k;
+ }
+ } else if (obj_label && !obj_id_len) {
+ if (k->label && strcmp(k->label, obj_label) == 0) {
+ selected_key = k;
+ }
+ } else if (obj_id_len && !obj_label) {
+ if (k->id_len == obj_id_len &&
+ memcmp(k->id, obj_id, obj_id_len) == 0) {
+ selected_key = k;
+ }
+ }
}
} else {
which = "first";

View File

@ -0,0 +1,25 @@
From 668b2bd03942f3d371f0553fc252ea6c64253a19 Mon Sep 17 00:00:00 2001
From: S-P Chan <shihping.chan@gmail.com>
Date: Fri, 11 Mar 2022 23:42:22 +0800
Subject: [PATCH] Fix OAEP source param
The only supported value is 1UL CKZ_DATA_SPECIFIED
---
src/p11_pkey.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/p11_pkey.c b/src/p11_pkey.c
index f1a98b18..63e0e197 100644
--- a/src/p11_pkey.c
+++ b/src/p11_pkey.c
@@ -301,8 +301,8 @@ static int pkcs11_params_oaep(CK_RSA_PKCS_OAEP_PARAMS *oaep,
if (!oaep->hashAlg || !oaep->mgf)
return -1;
/* we do not support the OAEP "label" parameter yet... */
- oaep->source = 0UL; /* empty parameter (label) */
- oaep->pSourceData = NULL;
+ oaep->source = CKZ_DATA_SPECIFIED;
+ oaep->pSourceData = NULL; /* empty parameter (label) */
oaep->ulSourceDataLen = 0;
return 0;
}

View File

@ -0,0 +1,155 @@
From 7275c4b8f681846cc5d9acc4ae9e6b186f8267bf Mon Sep 17 00:00:00 2001
From: Markus Koetter <koetter@luis.uni-hannover.de>
Date: Tue, 30 Mar 2021 13:33:05 +0200
Subject: [PATCH 1/2] add re-numeration of slots as engine ctrl command
This was broken in 14cd0d328fff96b79fabcc30257e358399c8ad25.
Previously, the engine would re-enumerate before loading keys/certs
Not re-enumerating the slots results in un-awareness of changes in slots
and tokens.
This awareness is required to be able to change the token in a slot at
runtime, else you use invalid sessions
(PKCS#11 module:pkcs11_find_keys:Session handle invalid:p11_key.c:512)
The patch adds the command RE_ENUMERATE as engine control, providing the
ability to re-enumerate on demand/when required.
---
src/eng_back.c | 38 +++++++++++++++++++++++++++-----------
src/eng_front.c | 4 ++++
src/engine.h | 1 +
3 files changed, 32 insertions(+), 11 deletions(-)
diff --git a/src/eng_back.c b/src/eng_back.c
index 37ee076b..4ba069e7 100644
--- a/src/eng_back.c
+++ b/src/eng_back.c
@@ -264,24 +264,17 @@ int ctx_destroy(ENGINE_CTX *ctx)
return 1;
}
-/* Initialize libp11 data: ctx->pkcs11_ctx and ctx->slot_list */
-static void ctx_init_libp11_unlocked(ENGINE_CTX *ctx)
+static int ctx_enumerate_slots(ENGINE_CTX *ctx, PKCS11_CTX *pkcs11_ctx)
{
- PKCS11_CTX *pkcs11_ctx;
PKCS11_SLOT *slot_list = NULL;
unsigned int slot_count = 0;
- ctx_log(ctx, 1, "PKCS#11: Initializing the engine\n");
-
- pkcs11_ctx = PKCS11_CTX_new();
- PKCS11_CTX_init_args(pkcs11_ctx, ctx->init_args);
- PKCS11_set_ui_method(pkcs11_ctx, ctx->ui_method, ctx->callback_data);
/* PKCS11_CTX_load() uses C_GetSlotList() via p11-kit */
if (PKCS11_CTX_load(pkcs11_ctx, ctx->module) < 0) {
ctx_log(ctx, 0, "Unable to load module %s\n", ctx->module);
PKCS11_CTX_free(pkcs11_ctx);
- return;
+ return 0;
}
/* PKCS11_enumerate_slots() uses C_GetSlotList() via libp11 */
@@ -289,17 +282,38 @@ static void ctx_init_libp11_unlocked(ENGINE_CTX *ctx)
ctx_log(ctx, 0, "Failed to enumerate slots\n");
PKCS11_CTX_unload(pkcs11_ctx);
PKCS11_CTX_free(pkcs11_ctx);
- return;
+ return 0;
}
ctx_log(ctx, 1, "Found %u slot%s\n", slot_count,
slot_count <= 1 ? "" : "s");
- ctx->pkcs11_ctx = pkcs11_ctx;
ctx->slot_list = slot_list;
ctx->slot_count = slot_count;
+
+ return 1;
+}
+
+
+/* Initialize libp11 data: ctx->pkcs11_ctx and ctx->slot_list */
+static void ctx_init_libp11_unlocked(ENGINE_CTX *ctx)
+{
+ PKCS11_CTX *pkcs11_ctx;
+
+ ctx_log(ctx, 1, "PKCS#11: Initializing the engine\n");
+
+ pkcs11_ctx = PKCS11_CTX_new();
+ PKCS11_CTX_init_args(pkcs11_ctx, ctx->init_args);
+ PKCS11_set_ui_method(pkcs11_ctx, ctx->ui_method, ctx->callback_data);
+
+ if (ctx_enumerate_slots(ctx, pkcs11_ctx) != 1)
+ return;
+
+ ctx->pkcs11_ctx = pkcs11_ctx;
}
+
+
static int ctx_init_libp11(ENGINE_CTX *ctx)
{
#if OPENSSL_VERSION_NUMBER >= 0x10100004L && !defined(LIBRESSL_VERSION_NUMBER)
@@ -1092,6 +1106,8 @@ int ctx_engine_ctrl(ENGINE_CTX *ctx, int cmd, long i, void *p, void (*f)())
return ctx_ctrl_set_callback_data(ctx, p);
case CMD_FORCE_LOGIN:
return ctx_ctrl_force_login(ctx);
+ case CMD_RE_ENUMERATE:
+ return ctx_enumerate_slots(ctx, ctx->pkcs11_ctx);
default:
ENGerr(ENG_F_CTX_ENGINE_CTRL, ENG_R_UNKNOWN_COMMAND);
break;
diff --git a/src/eng_front.c b/src/eng_front.c
index b2cc8b4c..3a3c8910 100644
--- a/src/eng_front.c
+++ b/src/eng_front.c
@@ -75,6 +75,10 @@ static const ENGINE_CMD_DEFN engine_cmd_defns[] = {
"FORCE_LOGIN",
"Force login to the PKCS#11 module",
ENGINE_CMD_FLAG_NO_INPUT},
+ {CMD_RE_ENUMERATE,
+ "RE_ENUMERATE",
+ "re enumerate slots",
+ ENGINE_CMD_FLAG_NO_INPUT},
{0, NULL, NULL, 0}
};
diff --git a/src/engine.h b/src/engine.h
index f46cf4e3..54bdcf03 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -51,6 +51,7 @@
#define CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 7)
#define CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 8)
#define CMD_FORCE_LOGIN (ENGINE_CMD_BASE+9)
+#define CMD_RE_ENUMERATE (ENGINE_CMD_BASE+10)
typedef struct st_engine_ctx ENGINE_CTX; /* opaque */
From 0d24455ec402ff6bd75f0a94c160426e7f2159d5 Mon Sep 17 00:00:00 2001
From: commonism <commonism@users.noreply.github.com>
Date: Wed, 7 Apr 2021 15:36:23 +0200
Subject: [PATCH 2/2] Update README.md
add RE_ENUMERATE
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index d1550846..d3c68bdd 100644
--- a/README.md
+++ b/README.md
@@ -168,6 +168,7 @@ The supported engine controls are the following.
* **SET_USER_INTERFACE**: Set the global user interface
* **SET_CALLBACK_DATA**: Set the global user interface extra data
* **FORCE_LOGIN**: Force login to the PKCS#11 module
+* **RE_ENUMERATE**: re-enumerate the slots/tokens, required when adding/removing tokens/slots
An example code snippet setting specific module is shown below.

View File

@ -0,0 +1,746 @@
From 2b593a224d38e68f562deaa2a887e2ee155374ea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
Date: Sun, 30 May 2021 20:38:31 +0300
Subject: [PATCH] Simplify engine code to load certificates, public and private
keys
It was mostly copy paste, so remove the duplicate code to simplify
code maintenance and readability. The per-slot object matching code
is made a callback because the internally cached structs do not
share a common header portion. Make the helper functions do as much
as possible to minimize duplicate code.
---
src/eng_back.c | 581 ++++++++++++++++---------------------------------
src/eng_err.h | 1 +
2 files changed, 186 insertions(+), 396 deletions(-)
diff --git a/src/eng_back.c b/src/eng_back.c
index 878cf5d2..703a567e 100644
--- a/src/eng_back.c
+++ b/src/eng_back.c
@@ -280,10 +280,13 @@ static int ctx_enumerate_slots(ENGINE_CTX *ctx, PKCS11_CTX *pkcs11_ctx)
/* Initialize libp11 data: ctx->pkcs11_ctx and ctx->slot_list */
-static void ctx_init_libp11_unlocked(ENGINE_CTX *ctx)
+static int ctx_init_libp11_unlocked(ENGINE_CTX *ctx)
{
PKCS11_CTX *pkcs11_ctx;
+ if (ctx->pkcs11_ctx && ctx->slot_list)
+ return 0;
+
ctx_log(ctx, 1, "PKCS#11: Initializing the engine\n");
pkcs11_ctx = PKCS11_CTX_new();
@@ -291,29 +294,9 @@ static void ctx_init_libp11_unlocked(ENGINE_CTX *ctx)
PKCS11_set_ui_method(pkcs11_ctx, ctx->ui_method, ctx->callback_data);
if (ctx_enumerate_slots(ctx, pkcs11_ctx) != 1)
- return;
+ return -1;
ctx->pkcs11_ctx = pkcs11_ctx;
-}
-
-
-
-static int ctx_init_libp11(ENGINE_CTX *ctx)
-{
-#if OPENSSL_VERSION_NUMBER >= 0x10100004L && !defined(LIBRESSL_VERSION_NUMBER)
- CRYPTO_THREAD_write_lock(ctx->rwlock);
-#else
- if (ctx->rwlock)
- CRYPTO_w_lock(ctx->rwlock);
-#endif
- if (!ctx->pkcs11_ctx|| !ctx->slot_list)
- ctx_init_libp11_unlocked(ctx);
-#if OPENSSL_VERSION_NUMBER >= 0x10100004L && !defined(LIBRESSL_VERSION_NUMBER)
- CRYPTO_THREAD_unlock(ctx->rwlock);
-#else
- if (ctx->rwlock)
- CRYPTO_w_unlock(ctx->rwlock);
-#endif
return ctx->pkcs11_ctx && ctx->slot_list ? 0 : -1;
}
@@ -343,43 +332,40 @@ int ctx_finish(ENGINE_CTX *ctx)
}
/******************************************************************************/
-/* Certificate handling */
+/* Utilities common to public, private key and certificate handling */
/******************************************************************************/
-/* prototype for OpenSSL ENGINE_load_cert */
-/* used by load_cert_ctrl via ENGINE_ctrl for now */
-
-static X509 *ctx_load_cert(ENGINE_CTX *ctx, const char *s_slot_cert_id,
- const int login)
+static void *ctx_try_load_object(ENGINE_CTX *ctx,
+ const char *object_typestr,
+ void *(*match_func)(ENGINE_CTX *, PKCS11_TOKEN *,
+ const unsigned char *, size_t, const char *),
+ const char *object_uri, const int login,
+ UI_METHOD *ui_method, void *callback_data)
{
PKCS11_SLOT *slot;
PKCS11_SLOT *found_slot = NULL, **matched_slots = NULL;
PKCS11_TOKEN *tok, *match_tok = NULL;
- PKCS11_CERT *certs, *selected_cert = NULL;
- X509 *x509 = NULL;
- unsigned int cert_count, n, m;
- unsigned char cert_id[MAX_VALUE_LEN / 2];
- size_t cert_id_len = sizeof(cert_id);
- char *cert_label = NULL;
+ unsigned int n, m;
+ unsigned char obj_id[MAX_VALUE_LEN / 2];
+ size_t obj_id_len = sizeof(obj_id);
+ char *obj_label = NULL;
char tmp_pin[MAX_PIN_LENGTH+1];
size_t tmp_pin_len = MAX_PIN_LENGTH;
int slot_nr = -1;
char flags[64];
size_t matched_count = 0;
+ void *object = NULL;
- if (ctx_init_libp11(ctx)) /* Delayed libp11 initialization */
- return NULL;
-
- if (s_slot_cert_id && *s_slot_cert_id) {
- if (!strncasecmp(s_slot_cert_id, "pkcs11:", 7)) {
- n = parse_pkcs11_uri(ctx, s_slot_cert_id, &match_tok,
- cert_id, &cert_id_len,
- tmp_pin, &tmp_pin_len, &cert_label);
+ if (object_uri && *object_uri) {
+ if (!strncasecmp(object_uri, "pkcs11:", 7)) {
+ n = parse_pkcs11_uri(ctx, object_uri, &match_tok,
+ obj_id, &obj_id_len, tmp_pin, &tmp_pin_len, &obj_label);
if (!n) {
ctx_log(ctx, 0,
- "The certificate ID is not a valid PKCS#11 URI\n"
- "The PKCS#11 URI format is defined by RFC7512\n");
- ENGerr(ENG_F_CTX_LOAD_CERT, ENG_R_INVALID_ID);
+ "The %s ID is not a valid PKCS#11 URI\n"
+ "The PKCS#11 URI format is defined by RFC7512\n",
+ object_typestr);
+ ENGerr(ENG_F_CTX_LOAD_OBJECT, ENG_R_INVALID_ID);
goto error;
}
if (tmp_pin_len > 0 && tmp_pin[0] != 0) {
@@ -389,28 +378,29 @@ static X509 *ctx_load_cert(ENGINE_CTX *ctx, const char *s_slot_cert_id,
}
}
} else {
- n = parse_slot_id_string(ctx, s_slot_cert_id, &slot_nr,
- cert_id, &cert_id_len, &cert_label);
+ n = parse_slot_id_string(ctx, object_uri, &slot_nr,
+ obj_id, &obj_id_len, &obj_label);
if (!n) {
ctx_log(ctx, 0,
- "The certificate ID is not a valid PKCS#11 URI\n"
+ "The %s ID is not a valid PKCS#11 URI\n"
"The PKCS#11 URI format is defined by RFC7512\n"
"The legacy ENGINE_pkcs11 ID format is also "
- "still accepted for now\n");
- ENGerr(ENG_F_CTX_LOAD_CERT, ENG_R_INVALID_ID);
+ "still accepted for now\n",
+ object_typestr);
+ ENGerr(ENG_F_CTX_LOAD_OBJECT, ENG_R_INVALID_ID);
goto error;
}
}
- ctx_log(ctx, 1, "Looking in slot %d for certificate: ",
- slot_nr);
- if (cert_id_len != 0) {
+ ctx_log(ctx, 1, "Looking in slot %d for %s: ",
+ slot_nr, object_typestr);
+ if (obj_id_len != 0) {
ctx_log(ctx, 1, "id=");
- dump_hex(ctx, 1, cert_id, cert_id_len);
+ dump_hex(ctx, 1, obj_id, obj_id_len);
}
- if (cert_id_len != 0 && cert_label)
+ if (obj_id_len != 0 && obj_label)
ctx_log(ctx, 1, " ");
- if (cert_label)
- ctx_log(ctx, 1, "label=%s", cert_label);
+ if (obj_label)
+ ctx_log(ctx, 1, "label=%s", obj_label);
ctx_log(ctx, 1, "\n");
}
@@ -521,7 +511,7 @@ static X509 *ctx_load_cert(ENGINE_CTX *ctx, const char *s_slot_cert_id,
* the PIN against all matching slots */
if (matched_count == 1) {
if (!ctx_login(ctx, slot, tok,
- ctx->ui_method, ctx->callback_data)) {
+ ui_method, callback_data)) {
ctx_log(ctx, 0, "Login to token failed, returning NULL...\n");
goto error;
}
@@ -541,48 +531,11 @@ static X509 *ctx_load_cert(ENGINE_CTX *ctx, const char *s_slot_cert_id,
}
}
- if (PKCS11_enumerate_certs(tok, &certs, &cert_count)) {
- ctx_log(ctx, 0, "Unable to enumerate certificates\n");
- continue;
- }
-
- ctx_log(ctx, 1, "Found %u cert%s:\n", cert_count,
- (cert_count <= 1) ? "" : "s");
- if ((s_slot_cert_id && *s_slot_cert_id) &&
- (cert_id_len != 0 || cert_label)) {
- for (m = 0; m < cert_count; m++) {
- PKCS11_CERT *k = certs + m;
-
- if (cert_label && k->label && strcmp(k->label, cert_label) == 0)
- selected_cert = k;
- if (cert_id_len != 0 && k->id_len == cert_id_len &&
- memcmp(k->id, cert_id, cert_id_len) == 0)
- selected_cert = k;
- }
- } else {
- for (m = 0; m < cert_count; m++) {
- PKCS11_CERT *k = certs + m;
- if (k->id && *(k->id)) {
- selected_cert = k; /* Use the first certificate with nonempty id */
- break;
- }
- }
- if (!selected_cert)
- selected_cert = certs; /* Use the first certificate */
- }
-
- if (selected_cert) {
+ object = match_func(ctx, tok, obj_id, obj_id_len, obj_label);
+ if (object)
break;
- }
}
- if (selected_cert) {
- x509 = X509_dup(selected_cert->x509);
- } else {
- if (login) /* Only print the error on the second attempt */
- ctx_log(ctx, 0, "Certificate not found.\n");
- x509 = NULL;
- }
error:
/* Free the searched token data */
if (match_tok) {
@@ -593,11 +546,86 @@ static X509 *ctx_load_cert(ENGINE_CTX *ctx, const char *s_slot_cert_id,
OPENSSL_free(match_tok);
}
- if (cert_label)
- OPENSSL_free(cert_label);
+ if (obj_label)
+ OPENSSL_free(obj_label);
if (matched_slots)
free(matched_slots);
- return x509;
+ return object;
+}
+
+static void *ctx_load_object(ENGINE_CTX *ctx,
+ const char *object_typestr,
+ void *(*match_func)(ENGINE_CTX *, PKCS11_TOKEN *,
+ const unsigned char *, size_t, const char *),
+ const char *object_uri, UI_METHOD *ui_method, void *callback_data)
+{
+ void *obj = NULL;
+
+ /* Delayed libp11 initialization */
+ if (ctx_init_libp11_unlocked(ctx)) {
+ ENGerr(ENG_F_CTX_LOAD_OBJECT, ENG_R_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ if (!ctx->force_login) {
+ ERR_clear_error();
+ obj = ctx_try_load_object(ctx, object_typestr, match_func,
+ object_uri, 0, ui_method, callback_data);
+ }
+
+ if (!obj) {
+ /* Try again with login */
+ ERR_clear_error();
+ obj = ctx_try_load_object(ctx, object_typestr, match_func,
+ object_uri, 1, ui_method, callback_data);
+ if (!obj) {
+ ctx_log(ctx, 0, "The %s was not found.\n", object_typestr);
+ }
+ }
+
+ return obj;
+}
+
+/******************************************************************************/
+/* Certificate handling */
+/******************************************************************************/
+
+static void *match_cert(ENGINE_CTX *ctx, PKCS11_TOKEN *tok,
+ const unsigned char *obj_id, size_t obj_id_len, const char *obj_label)
+{
+ PKCS11_CERT *certs, *selected_cert = NULL;
+ unsigned int m, cert_count;
+
+ if (PKCS11_enumerate_certs(tok, &certs, &cert_count)) {
+ ctx_log(ctx, 0, "Unable to enumerate certificates\n");
+ return NULL;
+ }
+ if (cert_count == 0)
+ return NULL;
+
+ ctx_log(ctx, 1, "Found %u cert%s:\n", cert_count, cert_count <= 1 ? "s" : "");
+ if (obj_id && *obj_id && (obj_id_len != 0 || obj_label)) {
+ for (m = 0; m < cert_count; m++) {
+ PKCS11_CERT *k = certs + m;
+
+ if (obj_label && k->label && strcmp(k->label, obj_label) == 0)
+ selected_cert = k;
+ if (obj_id_len != 0 && k->id_len == obj_id_len &&
+ memcmp(k->id, obj_id, obj_id_len) == 0)
+ selected_cert = k;
+ }
+ } else {
+ for (m = 0; m < cert_count; m++) {
+ PKCS11_CERT *k = certs + m;
+ if (k->id && *k->id) {
+ selected_cert = k; /* Use the first certificate with nonempty id */
+ break;
+ }
+ }
+ if (!selected_cert)
+ selected_cert = certs; /* Use the first certificate */
+ }
+ return selected_cert;
}
static int ctx_ctrl_load_cert(ENGINE_CTX *ctx, void *p)
@@ -606,6 +638,7 @@ static int ctx_ctrl_load_cert(ENGINE_CTX *ctx, void *p)
const char *s_slot_cert_id;
X509 *cert;
} *parms = p;
+ PKCS11_CERT *cert;
if (!parms) {
ENGerr(ENG_F_CTX_CTRL_LOAD_CERT, ERR_R_PASSED_NULL_PARAMETER);
@@ -616,18 +649,14 @@ static int ctx_ctrl_load_cert(ENGINE_CTX *ctx, void *p)
ENGerr(ENG_F_CTX_CTRL_LOAD_CERT, ENG_R_INVALID_PARAMETER);
return 0;
}
- ERR_clear_error();
- if (!ctx->force_login)
- parms->cert = ctx_load_cert(ctx, parms->s_slot_cert_id, 0);
- if (!parms->cert) { /* Try again with login */
- ERR_clear_error();
- parms->cert = ctx_load_cert(ctx, parms->s_slot_cert_id, 1);
- }
- if (!parms->cert) {
+ cert = ctx_load_object(ctx, "certificate", match_cert, parms->s_slot_cert_id,
+ ctx->ui_method, ctx->callback_data);
+ if (!cert) {
if (!ERR_peek_last_error())
ENGerr(ENG_F_CTX_CTRL_LOAD_CERT, ENG_R_OBJECT_NOT_FOUND);
return 0;
}
+ parms->cert = X509_dup(cert->x509);
return 1;
}
@@ -642,322 +664,96 @@ static int ctx_ctrl_load_cert(ENGINE_CTX *ctx, void *p)
/* Private and public key handling */
/******************************************************************************/
-static EVP_PKEY *ctx_load_key(ENGINE_CTX *ctx, const char *s_slot_key_id,
- UI_METHOD *ui_method, void *callback_data,
- const int isPrivate, const int login)
+static void *match_key(ENGINE_CTX *ctx, const char *key_type,
+ PKCS11_KEY *keys, unsigned int key_count,
+ const unsigned char *obj_id, size_t obj_id_len, const char *obj_label)
{
- PKCS11_SLOT *slot;
- PKCS11_SLOT *found_slot = NULL, **matched_slots = NULL;
- PKCS11_TOKEN *tok, *match_tok = NULL;
- PKCS11_KEY *keys, *selected_key = NULL;
- EVP_PKEY *pk = NULL;
- unsigned int key_count, n, m;
- unsigned char key_id[MAX_VALUE_LEN / 2];
- size_t key_id_len = sizeof(key_id);
- char *key_label = NULL;
- int slot_nr = -1;
- char tmp_pin[MAX_PIN_LENGTH+1];
- size_t tmp_pin_len = MAX_PIN_LENGTH;
- char flags[64];
- size_t matched_count = 0;
-
- if (ctx_init_libp11(ctx)) /* Delayed libp11 initialization */
- goto error;
-
- ctx_log(ctx, 1, "Loading %s key \"%s\"\n",
- (char *)(isPrivate ? "private" : "public"),
- s_slot_key_id);
- if (s_slot_key_id && *s_slot_key_id) {
- if (!strncasecmp(s_slot_key_id, "pkcs11:", 7)) {
- n = parse_pkcs11_uri(ctx, s_slot_key_id, &match_tok,
- key_id, &key_id_len,
- tmp_pin, &tmp_pin_len, &key_label);
- if (!n) {
- ctx_log(ctx, 0,
- "The key ID is not a valid PKCS#11 URI\n"
- "The PKCS#11 URI format is defined by RFC7512\n");
- ENGerr(ENG_F_CTX_LOAD_KEY, ENG_R_INVALID_ID);
- goto error;
- }
- if (tmp_pin_len > 0 && tmp_pin[0] != 0) {
- /* If the searched key is public, try without login once even
- * when the PIN is provided */
- if (!login && isPrivate)
- goto error; /* Process on second attempt */
- ctx_destroy_pin(ctx);
- ctx->pin = OPENSSL_malloc(MAX_PIN_LENGTH+1);
- if (ctx->pin) {
- memset(ctx->pin, 0, MAX_PIN_LENGTH+1);
- memcpy(ctx->pin, tmp_pin, tmp_pin_len);
- ctx->pin_length = tmp_pin_len;
- }
- }
- } else {
- n = parse_slot_id_string(ctx, s_slot_key_id, &slot_nr,
- key_id, &key_id_len, &key_label);
- if (!n) {
- ctx_log(ctx, 0,
- "The key ID is not a valid PKCS#11 URI\n"
- "The PKCS#11 URI format is defined by RFC7512\n"
- "The legacy ENGINE_pkcs11 ID format is also "
- "still accepted for now\n");
- ENGerr(ENG_F_CTX_LOAD_KEY, ENG_R_INVALID_ID);
- goto error;
- }
- }
- ctx_log(ctx, 1, "Looking in slot %d for key: ",
- slot_nr);
- if (key_id_len != 0) {
- ctx_log(ctx, 1, "id=");
- dump_hex(ctx, 1, key_id, key_id_len);
- }
- if (key_id_len != 0 && key_label)
- ctx_log(ctx, 1, " ");
- if (key_label)
- ctx_log(ctx, 1, "label=%s", key_label);
- ctx_log(ctx, 1, "\n");
- }
-
- matched_slots = (PKCS11_SLOT **)calloc(ctx->slot_count,
- sizeof(PKCS11_SLOT *));
- if (!matched_slots) {
- ctx_log(ctx, 0, "Could not allocate memory for matched slots\n");
- goto error;
- }
-
- for (n = 0; n < ctx->slot_count; n++) {
- slot = ctx->slot_list + n;
- flags[0] = '\0';
- if (slot->token) {
- if (!slot->token->initialized)
- strcat(flags, "uninitialized, ");
- else if (!slot->token->userPinSet)
- strcat(flags, "no pin, ");
- if (slot->token->loginRequired)
- strcat(flags, "login, ");
- if (slot->token->readOnly)
- strcat(flags, "ro, ");
- } else {
- strcpy(flags, "no token");
- }
- if ((m = strlen(flags)) != 0) {
- flags[m - 2] = '\0';
- }
+ PKCS11_KEY *selected_key = NULL;
+ unsigned int m;
- if (slot_nr != -1 &&
- slot_nr == (int)PKCS11_get_slotid_from_slot(slot)) {
- found_slot = slot;
- }
+ if (key_count == 0)
+ return NULL;
- if (match_tok && slot->token &&
- (!match_tok->label ||
- !strcmp(match_tok->label, slot->token->label)) &&
- (!match_tok->manufacturer ||
- !strcmp(match_tok->manufacturer, slot->token->manufacturer)) &&
- (!match_tok->serialnr ||
- !strcmp(match_tok->serialnr, slot->token->serialnr)) &&
- (!match_tok->model ||
- !strcmp(match_tok->model, slot->token->model))) {
- found_slot = slot;
- }
- ctx_log(ctx, 1, "[%lu] %-25.25s %-16s",
- PKCS11_get_slotid_from_slot(slot),
- slot->description, flags);
- if (slot->token) {
- ctx_log(ctx, 1, " (%s)",
- slot->token->label[0] ?
- slot->token->label : "no label");
- }
- ctx_log(ctx, 1, "\n");
+ ctx_log(ctx, 1, "Found %u %s key%s:\n", key_count, key_type,
+ key_count <= 1 ? "" : "s");
- if (found_slot && found_slot->token && !found_slot->token->initialized)
- ctx_log(ctx, 0, "Found uninitialized token\n");
+ if (obj_id && *obj_id && (obj_id_len != 0 || obj_label)) {
+ for (m = 0; m < key_count; m++) {
+ PKCS11_KEY *k = keys + m;
- /* Ignore slots without tokens or with uninitialized token */
- if (found_slot && found_slot->token && found_slot->token->initialized) {
- matched_slots[matched_count] = found_slot;
- matched_count++;
- }
- found_slot = NULL;
- }
-
- if (matched_count == 0) {
- if (match_tok) {
- ctx_log(ctx, 0, "Specified object not found\n");
- goto error;
- }
-
- /* If the legacy slot ID format was used */
- if (slot_nr != -1) {
- ctx_log(ctx, 0, "Invalid slot number: %d\n", slot_nr);
- goto error;
- } else {
- found_slot = PKCS11_find_token(ctx->pkcs11_ctx,
- ctx->slot_list, ctx->slot_count);
- /* Ignore if the the token is not initialized */
- if (found_slot && found_slot->token &&
- found_slot->token->initialized) {
- matched_slots[matched_count] = found_slot;
- matched_count++;
- } else {
- ctx_log(ctx, 0, "No tokens found\n");
- goto error;
- }
+ ctx_log(ctx, 1, " %2u %c%c id=", m + 1,
+ k->isPrivate ? 'P' : ' ',
+ k->needLogin ? 'L' : ' ');
+ dump_hex(ctx, 1, k->id, k->id_len);
+ ctx_log(ctx, 1, " label=%s\n", k->label ? k->label : "(null)");
+ if (obj_label && k->label && strcmp(k->label, obj_label) == 0)
+ selected_key = k;
+ if (obj_id_len != 0 && k->id_len == obj_id_len
+ && memcmp(k->id, obj_id, obj_id_len) == 0)
+ selected_key = k;
}
+ } else {
+ selected_key = keys; /* Use the first key */
}
+ return selected_key;
+}
- for (n = 0; n < matched_count; n++) {
- slot = matched_slots[n];
- tok = slot->token;
- if (!tok) {
- ctx_log(ctx, 0, "Found empty token\n");
- break;
- }
-
- ctx_log(ctx, 1, "Found slot: %s\n", slot->description);
- ctx_log(ctx, 1, "Found token: %s\n", slot->token->label);
-
- /* Both private and public keys can have the CKA_PRIVATE attribute
- * set and thus require login (even to retrieve attributes!) */
- if (login) {
- /* Try to login only if login is required */
- if (tok->loginRequired) {
- /* Try to login only if a single slot matched to avoiding trying
- * the PIN against all matching slots */
- if (matched_count == 1) {
- if (!ctx_login(ctx, slot, tok, ui_method, callback_data)) {
- ctx_log(ctx, 0, "Login to token failed, returning NULL...\n");
- goto error;
- }
- } else {
- ctx_log(ctx, 0, "Multiple matching slots (%lu); will not try to"
- " login\n", matched_count);
- for (m = 0; m < matched_count; m++){
- slot = matched_slots[m];
- ctx_log(ctx, 1, "[%u] %s: %s\n", m + 1,
- slot->description? slot->description:
- "(no description)",
- (slot->token && slot->token->label)?
- slot->token->label: "no label");
- }
- goto error;
- }
- }
- }
-
- if (isPrivate) {
- /* Make sure there is at least one private key on the token */
- if (PKCS11_enumerate_keys(tok, &keys, &key_count)) {
- ctx_log(ctx, 0, "Unable to enumerate private keys\n");
- continue;
- }
- } else {
- /* Make sure there is at least one public key on the token */
- if (PKCS11_enumerate_public_keys(tok, &keys, &key_count)) {
- ctx_log(ctx, 0, "Unable to enumerate public keys\n");
- continue;
- }
- }
- if (key_count == 0) {
- if (login) /* Only print the error on the second attempt */
- ctx_log(ctx, 0, "No %s keys found.\n",
- (char *)(isPrivate ? "private" : "public"));
- continue;
- }
- ctx_log(ctx, 1, "Found %u %s key%s:\n", key_count,
- (char *)(isPrivate ? "private" : "public"),
- (key_count == 1) ? "" : "s");
-
- if (s_slot_key_id && *s_slot_key_id && (key_id_len != 0 || key_label)) {
- for (m = 0; m < key_count; m++) {
- PKCS11_KEY *k = keys + m;
-
- ctx_log(ctx, 1, " %2u %c%c id=", m + 1,
- k->isPrivate ? 'P' : ' ',
- k->needLogin ? 'L' : ' ');
- dump_hex(ctx, 1, k->id, k->id_len);
- ctx_log(ctx, 1, " label=%s\n", k->label ? k->label : "(null)");
- if (key_label && k->label && strcmp(k->label, key_label) == 0)
- selected_key = k;
- if (key_id_len != 0 && k->id_len == key_id_len
- && memcmp(k->id, key_id, key_id_len) == 0)
- selected_key = k;
- }
- } else {
- selected_key = keys; /* Use the first key */
- }
+static void *match_public_key(ENGINE_CTX *ctx, PKCS11_TOKEN *tok,
+ const unsigned char *obj_id, size_t obj_id_len, const char *obj_label)
+{
+ PKCS11_KEY *keys;
+ unsigned int key_count;
- if (selected_key) {
- break;
- }
+ /* Make sure there is at least one public key on the token */
+ if (PKCS11_enumerate_public_keys(tok, &keys, &key_count)) {
+ ctx_log(ctx, 0, "Unable to enumerate public keys\n");
+ return 0;
}
+ return match_key(ctx, "public", keys, key_count, obj_id, obj_id_len, obj_label);
+}
- if (selected_key) {
- pk = isPrivate ?
- PKCS11_get_private_key(selected_key) :
- PKCS11_get_public_key(selected_key);
- } else {
- if (login) /* Only print the error on the second attempt */
- ctx_log(ctx, 0, "Key not found.\n");
- pk = NULL;
- }
+static void *match_private_key(ENGINE_CTX *ctx, PKCS11_TOKEN *tok,
+ const unsigned char *obj_id, size_t obj_id_len, const char *obj_label)
+{
+ PKCS11_KEY *keys;
+ unsigned int key_count;
-error:
- /* Free the searched token data */
- if (match_tok) {
- OPENSSL_free(match_tok->model);
- OPENSSL_free(match_tok->manufacturer);
- OPENSSL_free(match_tok->serialnr);
- OPENSSL_free(match_tok->label);
- OPENSSL_free(match_tok);
+ /* Make sure there is at least one private key on the token */
+ if (PKCS11_enumerate_keys(tok, &keys, &key_count)) {
+ ctx_log(ctx, 0, "Unable to enumerate private keys\n");
+ return 0;
}
- if (key_label)
- OPENSSL_free(key_label);
- if (matched_slots)
- free(matched_slots);
- return pk;
+ return match_key(ctx, "private", keys, key_count, obj_id, obj_id_len, obj_label);
}
EVP_PKEY *ctx_load_pubkey(ENGINE_CTX *ctx, const char *s_key_id,
UI_METHOD *ui_method, void *callback_data)
{
- EVP_PKEY *pk = NULL;
-
- ERR_clear_error();
+ PKCS11_KEY *key;
- if (!ctx->force_login)
- pk = ctx_load_key(ctx, s_key_id, ui_method, callback_data, 0, 0);
- if (!pk) { /* Try again with login */
- ERR_clear_error();
- pk = ctx_load_key(ctx, s_key_id, ui_method, callback_data, 0, 1);
- }
- if (!pk) {
+ key = ctx_load_object(ctx, "public key", match_public_key, s_key_id,
+ ui_method, callback_data);
+ if (!key) {
ctx_log(ctx, 0, "PKCS11_load_public_key returned NULL\n");
if (!ERR_peek_last_error())
ENGerr(ENG_F_CTX_LOAD_PUBKEY, ENG_R_OBJECT_NOT_FOUND);
return NULL;
}
- return pk;
+ return PKCS11_get_public_key(key);
}
EVP_PKEY *ctx_load_privkey(ENGINE_CTX *ctx, const char *s_key_id,
UI_METHOD *ui_method, void *callback_data)
{
- EVP_PKEY *pk = NULL;
-
- ERR_clear_error();
+ PKCS11_KEY *key;
- if (!ctx->force_login)
- pk = ctx_load_key(ctx, s_key_id, ui_method, callback_data, 1, 0);
- if (!pk) { /* Try again with login */
- ERR_clear_error();
- pk = ctx_load_key(ctx, s_key_id, ui_method, callback_data, 1, 1);
- }
- if (!pk) {
+ key = ctx_load_object(ctx, "private key", match_private_key, s_key_id,
+ ui_method, callback_data);
+ if (!key) {
ctx_log(ctx, 0, "PKCS11_get_private_key returned NULL\n");
if (!ERR_peek_last_error())
ENGerr(ENG_F_CTX_LOAD_PRIVKEY, ENG_R_OBJECT_NOT_FOUND);
return NULL;
}
- return pk;
+ return PKCS11_get_private_key(key);
}
/******************************************************************************/
diff --git a/src/eng_err.h b/src/eng_err.h
index e542a3d8..8151be5f 100644
--- a/src/eng_err.h
+++ b/src/eng_err.h
@@ -31,6 +31,7 @@ void ERR_ENG_error(int function, int reason, char *file, int line);
# define ENG_F_CTX_CTRL_LOAD_CERT 102
# define ENG_F_CTX_CTRL_SET_PIN 106
# define ENG_F_CTX_ENGINE_CTRL 105
+# define ENG_F_CTX_LOAD_OBJECT 107
# define ENG_F_CTX_LOAD_CERT 100
# define ENG_F_CTX_LOAD_KEY 101
# define ENG_F_CTX_LOAD_PRIVKEY 103

View File

@ -1,8 +1,8 @@
Version: 0.4.10
Release: 3%{?dist}
Version: 0.4.11
Release: 9%{?dist}
# Define the directory where the OpenSSL engines are installed
%global enginesdir %{_libdir}/engines-1.1
%global enginesdir %{_libdir}/engines-3
Name: openssl-pkcs11
Summary: A PKCS#11 engine for use with OpenSSL
@ -11,15 +11,29 @@ License: LGPLv2+ and BSD
URL: https://github.com/OpenSC/libp11
Source0: https://github.com/OpenSC/libp11/releases/download/libp11-%{version}/libp11-%{version}.tar.gz
Patch0: openssl-pkcs11-0.4.10-small-bug-fixes.patch
Patch1: openssl-pkcs11-0.4.10-search-objects-in-all-matching-tokens.patch
Patch2: openssl-pkcs11-0.4.10-set-rsa-fips-method-flag.patch
Patch3: openssl-pkcs11-0.4.10-fix-memory-leak.patch
Patch4: openssl-pkcs11-0.4.10-fix-potential-leak-in-rsa-method.patch
# Downstream only for now to make RSA operations working in FIPS mode
Patch4: openssl-pkcs11-0.4.10-set-rsa-fips-method-flag.patch
# Coverity issues
# https://github.com/OpenSC/libp11/pull/400
Patch5: openssl-pkcs11-0.4.10-coverity.patch
# https://github.com/OpenSC/libp11/pull/406
Patch6: openssl-pkcs11-0.4.10-openssl3.patch
# https://github.com/OpenSC/libp11/pull/440
Patch7: openssl-pkcs11-0.4.11-oaep.patch
# https://github.com/OpenSC/libp11/pull/398
Patch8: openssl-pkcs11-0.4.11-re-enumerate.patch
# https://github.com/OpenSC/libp11/commit/b56082faa03ce5d85fbce13583b27a7a563ebeb1
# https://github.com/OpenSC/libp11/pull/409
Patch9: openssl-pkcs11-0.4.11-simplify-objects-loading.patch
# https://github.com/OpenSC/libp11/pull/433
Patch10: openssl-pkcs11-0.4.11-logging-expiry.patch
# https://github.com/OpenSC/libp11/pull/514
Patch11: openssl-pkcs11-0.4.11-coverity.patch
BuildRequires: make
BuildRequires: autoconf automake libtool
BuildRequires: openssl-devel
BuildRequires: openssl >= 1.0.2
BuildRequires: openssl >= 3.0.0
BuildRequires: pkgconfig
BuildRequires: pkgconfig(p11-kit-1)
# Needed for testsuite
@ -30,7 +44,7 @@ BuildRequires: doxygen
%endif
Requires: p11-kit-trust
Requires: openssl >= 1.0.2
Requires: openssl-libs >= 1.0.2
# Package renamed from libp11 to openssl-pkcs11 in release 0.4.7-4
Provides: libp11%{?_isa} = %{version}-%{release}
@ -115,31 +129,80 @@ make check %{?_smp_mflags} || if [ $? -ne 0 ]; then cat tests/*.log; exit 1; fi;
%endif
%changelog
* Mon Jan 09 2023 Clemens Lang <cllang@redhat.com> - 0.4.10-3
- Fix memory leak in PKCS11_pkey_meths (#2097690)
- Fix memory leak in RSA method (#2097690)
* Fri Sep 08 2023 Jakub Jelen <jjelen@redhat.com> - 0.4.11-9
- Fix coverity issues introduced with recent changes
* Thu Nov 28 2019 Anderson Sasaki <ansasaki@redhat.com> - 0.4.10-2
- Set RSA_FLAG_FIPS_METHOD for RSA methods (#1777892)
* Fri Aug 25 2023 Jakub Jelen <jjelen@redhat.com> - 0.4.11-8
- Fix sending parameters for RSA-OAEP operations (#2063378)
- Improve logging and fix selection of expired certificates (#2029834)
* Thu Nov 21 2019 Anderson Sasaki <ansasaki@redhat.com> - 0.4.10-1
- Update to 0.4.10 (#1745082)
- Add BuildRequires for OpenSSL >= 1.0.2, required for testing
- Print tests logs if failed during build
- Small bug fixes such as removal of unused variable
- Search objects in all matching tokens (#1705505)
* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 0.4.11-7
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Wed Jun 16 2021 Mohan Boddu <mboddu@redhat.com> - 0.4.11-6
- Rebuilt for RHEL 9 BETA for openssl 3.0
Related: rhbz#1971065
* Mon May 24 2021 Jakub Jelen <jjelen@redhat.com> - 0.4.11-5
- Support for OpenSSL 3.0 (#1959832)
* Fri Apr 30 2021 Jakub Jelen <jjelen@redhat.com> - 0.4.11-4
- Fix coverity reported issues
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 0.4.11-3
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 0.4.11-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
* Fri Nov 20 2020 Jakub Jelen <jjelen@redhat.com> - 0.4.11-1
- New upstream release (#1887217)
* Tue Jul 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 0.4.10-7
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Mon Apr 27 2020 Anderson Sasaki <ansasaki@redhat.com> - 0.4.10-6
- Set RSA_FLAG_FIPS_METHOD for RSA methods (#1827535)
* Mon Feb 03 2020 James Cassell <cyberpear@fedoraproject.org> - 0.4.10-5
- minimization: depend on openssl-libs rather than openssl
* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 0.4.10-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Fri Oct 11 2019 Anderson Sasaki <ansasaki@redhat.com> - 0.4.10-3
- Added support for "pin-source" within PKCS#11 URI (#1670026)
- Search objects in all matching tokens (#1760751)
- Set flag RSA_FLAG_EXT_PKEY for RSA keys (#1760541)
- Fixed various bugs
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 0.4.10-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Fri Apr 05 2019 Anderson Sasaki <ansasaki@redhat.com> - 0.4.10-1
- Added BuildRequires for openssl >= 1.0.2
* Thu Apr 04 2019 Anderson Sasaki <ansasaki@redhat.com> - 0.4.10-1
- Update to upstream version 0.4.10
* Tue Feb 19 2019 Anderson Sasaki <ansasaki@redhat.com> - 0.4.9-1
- Update to upstream version 0.4.9
* Fri Feb 01 2019 Fedora Release Engineering <releng@fedoraproject.org> - 0.4.8-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Tue Sep 18 2018 Anderson Sasaki <ansasaki@redhat.com> - 0.4.8-2
- Require OpenSSL >= 1.0.2
- Fixed missing declaration of ERR_get_CKR_code()
- Add support to use EC keys and tests (#1625338)
- Add support to use EC keys and tests (#1619184)
- Exposed check_fork() API
- Fixed memory leak of RSA objects in pkcs11_store_key()
- Updated OpenSSL license in eng_front.c
- Fixed build for old C dialects
- Allow engine to use private key without PIN
- Require DEBUG to be defined to print debug messages
- Changed package description
- Changed package description (#1614699)
* Mon Aug 06 2018 Anderson Sasaki <ansasaki@redhat.com> - 0.4.8-1
- Update to 0.4.8-1