Improve logging, fix selection of expired certificates

Resolves: rhbz#2029834
This commit is contained in:
Jakub Jelen 2023-08-25 14:13:16 +02:00
parent e954d309c9
commit 224a8361fb
4 changed files with 1405 additions and 0 deletions

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,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

@ -20,6 +20,13 @@ Patch5: openssl-pkcs11-0.4.10-coverity.patch
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
BuildRequires: make
BuildRequires: autoconf automake libtool