diff --git a/SOURCES/openssl-pkcs11-0.4.11-coverity.patch b/SOURCES/openssl-pkcs11-0.4.11-coverity.patch new file mode 100644 index 0000000..ba62d89 --- /dev/null +++ b/SOURCES/openssl-pkcs11-0.4.11-coverity.patch @@ -0,0 +1,64 @@ +From 1441c57837b71bf861081c33bb9270c65cdb5e5c Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +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 +--- + 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 +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 +--- + 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 + diff --git a/SOURCES/openssl-pkcs11-0.4.11-logging-expiry.patch b/SOURCES/openssl-pkcs11-0.4.11-logging-expiry.patch new file mode 100644 index 0000000..56248c9 --- /dev/null +++ b/SOURCES/openssl-pkcs11-0.4.11-logging-expiry.patch @@ -0,0 +1,497 @@ +From b56082faa03ce5d85fbce13583b27a7a563ebeb1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Trojnara?= +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 +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 +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 +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 +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"; + diff --git a/SOURCES/openssl-pkcs11-0.4.11-oaep.patch b/SOURCES/openssl-pkcs11-0.4.11-oaep.patch new file mode 100644 index 0000000..2b7e4f1 --- /dev/null +++ b/SOURCES/openssl-pkcs11-0.4.11-oaep.patch @@ -0,0 +1,25 @@ +From 668b2bd03942f3d371f0553fc252ea6c64253a19 Mon Sep 17 00:00:00 2001 +From: S-P Chan +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; + } diff --git a/SOURCES/openssl-pkcs11-0.4.11-re-enumerate.patch b/SOURCES/openssl-pkcs11-0.4.11-re-enumerate.patch new file mode 100644 index 0000000..d079b54 --- /dev/null +++ b/SOURCES/openssl-pkcs11-0.4.11-re-enumerate.patch @@ -0,0 +1,155 @@ +From 7275c4b8f681846cc5d9acc4ae9e6b186f8267bf Mon Sep 17 00:00:00 2001 +From: Markus Koetter +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 +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. + + + + diff --git a/SOURCES/openssl-pkcs11-0.4.11-simplify-objects-loading.patch b/SOURCES/openssl-pkcs11-0.4.11-simplify-objects-loading.patch new file mode 100644 index 0000000..89d069a --- /dev/null +++ b/SOURCES/openssl-pkcs11-0.4.11-simplify-objects-loading.patch @@ -0,0 +1,746 @@ +From 2b593a224d38e68f562deaa2a887e2ee155374ea Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Timo=20Ter=C3=A4s?= +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 + diff --git a/SPECS/openssl-pkcs11.spec b/SPECS/openssl-pkcs11.spec index eb0a9e3..bb2fe8a 100644 --- a/SPECS/openssl-pkcs11.spec +++ b/SPECS/openssl-pkcs11.spec @@ -1,5 +1,5 @@ Version: 0.4.11 -Release: 7%{?dist} +Release: 9%{?dist} # Define the directory where the OpenSSL engines are installed %global enginesdir %{_libdir}/engines-3 @@ -18,6 +18,17 @@ Patch4: openssl-pkcs11-0.4.10-set-rsa-fips-method-flag.patch 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 @@ -118,6 +129,13 @@ make check %{?_smp_mflags} || if [ $? -ne 0 ]; then cat tests/*.log; exit 1; fi; %endif %changelog +* Fri Sep 08 2023 Jakub Jelen - 0.4.11-9 +- Fix coverity issues introduced with recent changes + +* Fri Aug 25 2023 Jakub Jelen - 0.4.11-8 +- Fix sending parameters for RSA-OAEP operations (#2063378) +- Improve logging and fix selection of expired certificates (#2029834) + * Mon Aug 09 2021 Mohan Boddu - 0.4.11-7 - Rebuilt for IMA sigs, glibc 2.34, aarch64 flags Related: rhbz#1991688