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}"