diff --git a/SOURCES/opensc-0.23.0-generic-genkey.patch b/SOURCES/opensc-0.23.0-generic-genkey.patch new file mode 100644 index 0000000..2b20b19 --- /dev/null +++ b/SOURCES/opensc-0.23.0-generic-genkey.patch @@ -0,0 +1,29 @@ +From 6a1ff88d5c45e0b927922928cd947a95caccd4ed Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Thu, 18 May 2023 14:25:56 +0200 +Subject: [PATCH] tests: Fix the secret key test that never worked + +--- + tests/common.sh | 6 +++++- + tests/test-pkcs11-tool-sign-verify.sh | 6 ++++-- + 2 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/tests/common.sh b/tests/common.sh +index 9466c8fd6d..ba7b797826 100644 +--- a/tests/common.sh ++++ b/tests/common.sh +@@ -78,8 +78,12 @@ function card_setup() { + # Generate 521b ECC Key pair + generate_key "EC:secp521r1" "04" "ECC521" + # Generate an HMAC:SHA256 key +- $PKCS11_TOOL --keypairgen --key-type="GENERIC:64" --login --pin=$PIN \ ++ $PKCS11_TOOL --keygen --key-type="GENERIC:64" --login --pin=$PIN \ + --module="$P11LIB" --label="HMAC-SHA256" ++ if [[ "$?" -ne "0" ]]; then ++ echo "Couldn't generate GENERIC key" ++ return 1 ++ fi + } + + function softhsm_cleanup() { + diff --git a/SOURCES/opensc-0.23.0-pkcs11-read-object.patch b/SOURCES/opensc-0.23.0-pkcs11-read-object.patch new file mode 100644 index 0000000..1e1c337 --- /dev/null +++ b/SOURCES/opensc-0.23.0-pkcs11-read-object.patch @@ -0,0 +1,32 @@ +From 63d4bd3d3900682c8d2511e259abec63ce904895 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Mon, 22 May 2023 14:58:40 +0200 +Subject: [PATCH] pkcs11-tool: Avoid dereferencing freed members when reading + public keys + +--- + src/tools/pkcs11-tool.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c +index 85c500e223..1e9bf4bff5 100644 +--- a/src/tools/pkcs11-tool.c ++++ b/src/tools/pkcs11-tool.c +@@ -5739,8 +5739,6 @@ static int read_object(CK_SESSION_HANDLE session) + util_fatal("cannot set OSSL_PARAM"); + } + OSSL_PARAM_BLD_free(bld); +- OSSL_PARAM_free(old); +- OSSL_PARAM_free(new); + if (success) + ASN1_STRING_free(os); + free(value); +@@ -5758,6 +5756,8 @@ static int read_object(CK_SESSION_HANDLE session) + EVP_PKEY_CTX_free(ctx); + util_fatal("cannot create EVP_PKEY"); + } ++ OSSL_PARAM_free(old); ++ OSSL_PARAM_free(new); + + #endif + if (!i2d_PUBKEY_bio(pout, pkey)) diff --git a/SOURCES/opensc-0.23.0-pkcs11-uri.patch b/SOURCES/opensc-0.23.0-pkcs11-uri.patch new file mode 100644 index 0000000..c6881ac --- /dev/null +++ b/SOURCES/opensc-0.23.0-pkcs11-uri.patch @@ -0,0 +1,446 @@ +From 700b6e767391fdec3e9ed3865780f6bf7828ac85 Mon Sep 17 00:00:00 2001 +From: Sergio Arroutbi +Date: Fri, 19 Apr 2024 16:02:13 +0200 +Subject: [PATCH 1/2] Include uri in pkcs11-tool -L option + +Fixes: #3123 + +Signed-off-by: Sergio Arroutbi +--- + src/tools/pkcs11-tool.c | 66 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 66 insertions(+) + +diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c +index 5b2abf590c..c165945872 100644 +--- a/src/tools/pkcs11-tool.c ++++ b/src/tools/pkcs11-tool.c +@@ -621,6 +621,7 @@ static void generate_random(CK_SESSION_HANDLE session); + static CK_RV find_object_with_attributes(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *out, + CK_ATTRIBUTE *attrs, CK_ULONG attrsLen, CK_ULONG obj_index); + static CK_ULONG get_private_key_length(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE prkey); ++static const char *percent_encode(CK_UTF8CHAR *, size_t); + + /* win32 needs this in open(2) */ + #ifndef O_BINARY +@@ -1681,6 +1682,15 @@ static void show_token(CK_SLOT_ID slot) + printf(" serial num : %s\n", p11_utf8_to_local(info.serialNumber, + sizeof(info.serialNumber))); + printf(" pin min/max : %lu/%lu\n", info.ulMinPinLen, info.ulMaxPinLen); ++ printf(" uri : pkcs11:model="); ++ printf("%s", percent_encode(info.model, sizeof(info.model))); ++ printf(";manufacturer="); ++ printf("%s", percent_encode(info.manufacturerID, sizeof(info.manufacturerID))); ++ printf(";serial="); ++ printf("%s", percent_encode(info.serialNumber, sizeof(info.serialNumber))); ++ printf(";token="); ++ printf("%s", percent_encode(info.label, sizeof(info.label))); ++ printf("\n"); + } + + static void list_mechs(CK_SLOT_ID slot) +@@ -8293,6 +8303,62 @@ static const char *p11_utf8_to_local(CK_UTF8CHAR *string, size_t len) + return buffer; + } + ++static CK_BBOOL ++p11_is_percent_format_reserved_char(CK_UTF8CHAR c) ++{ ++ switch (c) { ++ case ' ': ++ case '!': ++ case '"': ++ case '#': ++ case '$': ++ case '%': ++ case '&': ++ case '\'': ++ case '(': ++ case ')': ++ case '*': ++ case '+': ++ case ',': ++ case '/': ++ case ':': ++ case ';': ++ case '=': ++ case '?': ++ case '@': ++ case '[': ++ case ']': ++ return CK_TRUE; ++ } ++ return CK_FALSE; ++} ++ ++static const char * ++percent_encode(CK_UTF8CHAR *string, size_t len) ++{ ++ static char buffer[1024]; ++ size_t output_index, input_index; ++ ++ while (len && string[len - 1] == ' ') ++ len--; ++ ++ for (output_index = input_index = 0; output_index < sizeof(buffer) - 3; ++ output_index++) { ++ if (input_index >= len) { ++ break; ++ } ++ if (p11_is_percent_format_reserved_char(string[input_index])) { ++ snprintf(&buffer[output_index], 4, "%%%x", string[input_index]); ++ output_index += 2; ++ } else { ++ buffer[output_index] = string[input_index]; ++ } ++ input_index++; ++ } ++ buffer[output_index] = '\0'; ++ return buffer; ++} ++ + static void p11_fatal(const char *func, CK_RV rv) + { + if (p11) + +From d9119d0695ea207dca50d651f78ec5fd0a9023ba Mon Sep 17 00:00:00 2001 +From: Sergio Arroutbi +Date: Thu, 25 Apr 2024 13:42:14 +0200 +Subject: [PATCH 2/2] Update src/tools/pkcs11-tool.c + +Co-authored-by: Jakub Jelen +--- + src/tools/pkcs11-tool.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c +index c165945872..46f8b735e5 100644 +--- a/src/tools/pkcs11-tool.c ++++ b/src/tools/pkcs11-tool.c +@@ -1682,8 +1682,8 @@ static void show_token(CK_SLOT_ID slot) + printf(" serial num : %s\n", p11_utf8_to_local(info.serialNumber, + sizeof(info.serialNumber))); + printf(" pin min/max : %lu/%lu\n", info.ulMinPinLen, info.ulMaxPinLen); +- printf(" uri : pkcs11:model="); +- printf("%s", percent_encode(info.model, sizeof(info.model))); ++ printf(" uri : pkcs11:"); ++ printf("model=%s", percent_encode(info.model, sizeof(info.model))); + printf(";manufacturer="); + printf("%s", percent_encode(info.manufacturerID, sizeof(info.manufacturerID))); + printf(";serial="); + +From 5289269d4a57563bdcd604ec091e6eda0f0547fd Mon Sep 17 00:00:00 2001 +From: Sergio Arroutbi +Date: Tue, 30 Apr 2024 18:30:16 +0200 +Subject: [PATCH] Include URIs for PKCS#11 objects + +Fixes: #3129 + +Signed-off-by: Sergio Arroutbi +--- + src/tests/fuzzing/fuzz_pkcs15init.c | 7 +- + src/tools/pkcs11-tool.c | 119 ++++++++++++++++++++++------ + tests/test-pkcs11-tool-test.sh | 20 ++++- + 3 files changed, 116 insertions(+), 30 deletions(-) + +diff --git a/src/tests/fuzzing/fuzz_pkcs15init.c b/src/tests/fuzzing/fuzz_pkcs15init.c +index e44e3aae35..85810ded77 100644 +--- a/src/tests/fuzzing/fuzz_pkcs15init.c ++++ b/src/tests/fuzzing/fuzz_pkcs15init.c +@@ -109,7 +109,7 @@ int fuzz_get_reader_data(const uint8_t *from, size_t from_size, const uint8_t ** + size_t i = 0; + while(i < from_size - 1 && from[i] != '\0') + i++; +- ++ + if (from[i] != '\0') + return 0; + +@@ -126,6 +126,7 @@ void do_init_app(struct sc_profile *profile, struct sc_pkcs15_card *p15card, sc_ + int so_puk_disabled = 0; + + memset(&init_args, 0, sizeof(init_args)); ++ memset(&info, 0, sizeof(info)); + sc_pkcs15init_get_pin_info(profile, SC_PKCS15INIT_SO_PIN, &info); + if ((info.attrs.pin.flags & SC_PKCS15_PIN_FLAG_UNBLOCK_DISABLED) && + (info.attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN)) +@@ -150,7 +151,7 @@ void do_store_pin(struct sc_profile *profile, struct sc_pkcs15_card *p15card, sc + struct sc_pkcs15init_pinargs pin_args; + char pin_id[SC_PKCS15_MAX_ID_SIZE] = "1\0"; + sc_pkcs15init_set_p15card(profile, p15card); +- ++ + memcpy(pin, "1234555678\0", 11); /* Set new pin */ + memset(&pin_args, 0, sizeof(pin_args)); + +@@ -363,6 +364,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) + if (card) + sc_disconnect_card(card); + sc_release_context(ctx); +- ++ + return 0; + } +diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c +index 46f8b735e5..4e1668290f 100644 +--- a/src/tools/pkcs11-tool.c ++++ b/src/tools/pkcs11-tool.c +@@ -1648,6 +1648,43 @@ static void list_slots(int tokens, int refresh, int print) + } + } + ++static const char * ++copy_key_value_to_uri(const char *key, const char *value, CK_BBOOL last) ++{ ++ static char URI[1024]; ++ static size_t shift = 0; ++ if (key && (shift + strlen(key) < sizeof(URI))) { ++ strcpy(&URI[shift], key); ++ shift += strlen(key); ++ } ++ if (value && (shift + strlen(value) < sizeof(URI))) { ++ strcpy(&URI[shift], value); ++ shift += strlen(value); ++ } ++ if (key && value && !last && shift < sizeof(URI)) { ++ URI[shift++] = ';'; ++ } ++ if (last && shift < sizeof(URI)) { ++ URI[shift] = '\0'; ++ shift = 0; ++ } ++ return URI; ++} ++ ++static const char * ++get_uri(CK_TOKEN_INFO_PTR info) ++{ ++ copy_key_value_to_uri("pkcs11:", NULL, CK_FALSE); ++ const char *model = percent_encode(info->model, sizeof(info->model)); ++ copy_key_value_to_uri("model=", model, CK_FALSE); ++ const char *manufacturer = percent_encode(info->manufacturerID, sizeof(info->manufacturerID)); ++ copy_key_value_to_uri("manufacturer=", manufacturer, CK_FALSE); ++ const char *serial = percent_encode(info->serialNumber, sizeof(info->serialNumber)); ++ copy_key_value_to_uri("serial=", serial, CK_FALSE); ++ const char *token = percent_encode(info->label, sizeof(info->label)); ++ return copy_key_value_to_uri("token=", token, CK_TRUE); ++} ++ + static void show_token(CK_SLOT_ID slot) + { + CK_TOKEN_INFO info; +@@ -1682,14 +1719,7 @@ static void show_token(CK_SLOT_ID slot) + printf(" serial num : %s\n", p11_utf8_to_local(info.serialNumber, + sizeof(info.serialNumber))); + printf(" pin min/max : %lu/%lu\n", info.ulMinPinLen, info.ulMaxPinLen); +- printf(" uri : pkcs11:"); +- printf("model=%s", percent_encode(info.model, sizeof(info.model))); +- printf(";manufacturer="); +- printf("%s", percent_encode(info.manufacturerID, sizeof(info.manufacturerID))); +- printf(";serial="); +- printf("%s", percent_encode(info.serialNumber, sizeof(info.serialNumber))); +- printf(";token="); +- printf("%s", percent_encode(info.label, sizeof(info.label))); ++ printf(" uri : %s", get_uri(&info)); + printf("\n"); + } + +@@ -5045,13 +5075,14 @@ show_key(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) + { + CK_MECHANISM_TYPE_PTR mechs = NULL; + CK_KEY_TYPE key_type = getKEY_TYPE(sess, obj); +- CK_ULONG size = 0; ++ CK_ULONG size, idsize = 0; + unsigned char *id, *oid, *value; + const char *sepa; + char *label; + char *unique_id; + int pub = 1; + int sec = 0; ++ CK_TOKEN_INFO info; + + switch(getCLASS(sess, obj)) { + case CKO_PRIVATE_KEY: +@@ -5243,17 +5274,15 @@ show_key(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) + + if ((label = getLABEL(sess, obj, NULL)) != NULL) { + printf(" label: %s\n", label); +- free(label); + } + +- if ((id = getID(sess, obj, &size)) != NULL && size) { ++ if ((id = getID(sess, obj, &idsize)) != NULL && idsize) { + unsigned int n; + + printf(" ID: "); +- for (n = 0; n < size; n++) ++ for (n = 0; n < idsize; n++) + printf("%02x", id[n]); + printf("\n"); +- free(id); + } + + printf(" Usage: "); +@@ -5355,7 +5384,26 @@ show_key(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) + printf(" Unique ID: %s\n", unique_id); + free(unique_id); + } +- ++ get_token_info(opt_slot, &info); ++ printf(" uri: %s", get_uri(&info)); ++ if (id != NULL && idsize) { ++ printf(";id=%%"); ++ for (unsigned int n = 0; n < idsize; n++) ++ printf("%02x", id[n]); ++ free(id); ++ } ++ if (label != NULL) { ++ const char *pelabel = percent_encode((unsigned char *)label, strlen(label)); ++ printf(";object=%s", pelabel); ++ free(label); ++ } ++ if (sec) { ++ printf(";type=secret-key\n"); ++ } else if (pub) { ++ printf(";type=public\n"); ++ } else { ++ printf(";type=private\n"); ++ } + suppress_warn = 0; + } + +@@ -5363,6 +5411,7 @@ static void show_cert(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) + { + CK_CERTIFICATE_TYPE cert_type = getCERTIFICATE_TYPE(sess, obj); + CK_ULONG size; ++ CK_TOKEN_INFO info; + unsigned char *id; + char *label; + char *unique_id; +@@ -5389,7 +5438,6 @@ static void show_cert(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) + + if ((label = getLABEL(sess, obj, NULL)) != NULL) { + printf(" label: %s\n", label); +- free(label); + } + + #if defined(ENABLE_OPENSSL) +@@ -5433,37 +5481,49 @@ static void show_cert(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) + for (n = 0; n < size; n++) + printf("%02x", id[n]); + printf("\n"); +- free(id); + } + if ((unique_id = getUNIQUE_ID(sess, obj, NULL)) != NULL) { + printf(" Unique ID: %s\n", unique_id); + free(unique_id); + } ++ get_token_info(opt_slot, &info); ++ printf(" uri: %s", get_uri(&info)); ++ if (id != NULL && size) { ++ printf(";id=%%"); ++ for (unsigned int n = 0; n < size; n++) ++ printf("%02x", id[n]); ++ free(id); ++ } ++ if (label != NULL) { ++ const char *pelabel = percent_encode((unsigned char *)label, strlen(label)); ++ printf(";object=%s", pelabel); ++ free(label); ++ } ++ printf(";type=cert\n"); + } + + static void show_dobj(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) + { + unsigned char *oid_buf; + char *label; ++ char *application; + CK_ULONG size = 0; ++ CK_TOKEN_INFO info; + + suppress_warn = 1; + printf("Data object %u\n", (unsigned int) obj); + printf(" label: "); + if ((label = getLABEL(sess, obj, NULL)) != NULL) { + printf("'%s'\n", label); +- free(label); +- } +- else { ++ } else { + printf("\n"); + } + + printf(" application: "); +- if ((label = getAPPLICATION(sess, obj, NULL)) != NULL) { +- printf("'%s'\n", label); +- free(label); +- } +- else { ++ if ((application = getAPPLICATION(sess, obj, NULL)) != NULL) { ++ printf("'%s'\n", application); ++ free(application); ++ } else { + printf("\n"); + } + +@@ -5494,8 +5554,16 @@ static void show_dobj(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) + printf(" private"); + if (!getMODIFIABLE(sess, obj) && !getPRIVATE(sess, obj)) + printf(""); ++ printf("\n"); + +- printf ("\n"); ++ get_token_info(opt_slot, &info); ++ printf(" uri: %s", get_uri(&info)); ++ if (label != NULL) { ++ const char *pelabel = percent_encode((unsigned char *)label, strlen(label)); ++ printf(";object=%s", pelabel); ++ free(label); ++ } ++ printf(";type=data\n"); + suppress_warn = 0; + } + +@@ -8337,6 +8405,7 @@ static const char * + percent_encode(CK_UTF8CHAR *string, size_t len) + { + static char buffer[1024]; ++ memset(buffer, 0, 1024); + size_t output_index, input_index; + + while (len && string[len - 1] == ' ') +diff --git a/tests/test-pkcs11-tool-test.sh b/tests/test-pkcs11-tool-test.sh +index 2a1f43b8bc..1a96cbd754 100755 +--- a/tests/test-pkcs11-tool-test.sh ++++ b/tests/test-pkcs11-tool-test.sh +@@ -20,12 +20,28 @@ assert $? "Failed to set up card" + echo "=======================================================" + echo "Test" + echo "=======================================================" +-$PKCS11_TOOL --test -p $PIN --module $P11LIB ++$PKCS11_TOOL --test -p "${PIN}" --module "${P11LIB}" + assert $? "Failed running tests" + ++echo "=======================================================" ++echo "Test objects URI" ++echo "=======================================================" ++$PKCS11_TOOL -O 2>/dev/null | grep 'uri:' 2>/dev/null >/dev/null ++assert $? "Failed running objects URI tests" ++$PKCS11_TOOL -O 2>/dev/null | grep 'uri:' | awk -F 'uri:' '{print $2}' | tr -d ' ' | grep ^"pkcs11:" 2>/dev/null >/dev/null ++assert $? "Failed running objects URI tests" ++ ++echo "=======================================================" ++echo "Test slots URI" ++echo "=======================================================" ++$PKCS11_TOOL -L 2>/dev/null | grep 'uri' 2>/dev/null >/dev/null ++assert $? "Failed running slots URI tests" ++$PKCS11_TOOL -O 2>/dev/null | grep 'uri' | awk -F 'uri*:' '{print $2}' | tr -d ' ' | grep ^"pkcs11:" 2>/dev/null >/dev/null ++assert $? "Failed running slots URI tests" ++ + echo "=======================================================" + echo "Cleanup" + echo "=======================================================" + card_cleanup + +-exit $ERRORS ++exit "${ERRORS}" diff --git a/SPECS/opensc.spec b/SPECS/opensc.spec index 0c3dfc3..f8b1959 100644 --- a/SPECS/opensc.spec +++ b/SPECS/opensc.spec @@ -3,7 +3,7 @@ Name: opensc Version: 0.23.0 -Release: 4%{?dist} +Release: 6%{?dist} Summary: Smart card library and applications License: LGPLv2+ @@ -56,6 +56,12 @@ Patch16: %{name}-0.23.0-myeid-sym.patch # https://github.com/OpenSC/OpenSC/pull/2948 # https://github.com/OpenSC/OpenSC/pull/3016 Patch17: %{name}-0.23.0-constant-time-pkcs1.5.patch +# https://github.com/OpenSC/OpenSC/pull/3125 +# https://github.com/OpenSC/OpenSC/pull/3130 +Patch18: %{name}-0.23.0-pkcs11-uri.patch +# https://github.com/OpenSC/OpenSC/pull/2756 +Patch19: %{name}-0.23.0-pkcs11-read-object.patch +Patch20: %{name}-0.23.0-generic-genkey.patch BuildRequires: make BuildRequires: pcsc-lite-devel @@ -104,6 +110,9 @@ every software/card that does so, too. %patch15 -p1 -b .pkcs15init %patch16 -p1 -b .myeid-sym %patch17 -p1 -b .constant-time-pkcs1 +%patch18 -p1 -b .pkcs11-uri +%patch19 -p1 -b .pkcs11-read-object +%patch20 -p1 -b .generic-genkey cp -p src/pkcs15init/README ./README.pkcs15init cp -p src/scconf/README.scconf . @@ -245,6 +254,12 @@ rm %{buildroot}%{_mandir}/man1/opensc-notify.1* %changelog +* Thu Jul 21 2025 Veronika Hanulikova - 0.23.0-6 +- Fix free before dereference when reading public key (RHEL-96029) + +* Thu Oct 24 2024 Veronika Hanulikova - 0.23.0-5 +- Add URI in PKCS#11 objects and pkcs11-tool (RHEL-53115) + * Thu Feb 08 2024 Veronika Hanulikova - 0.23.0-4 - Fix CVE-2023-5992: Side-channel leaks while stripping encryption PKCS#1.5 padding