891c12
From 592a641cb9f8eb17d4d1b1c9a96a1581f61e169b Mon Sep 17 00:00:00 2001
891c12
From: Doug Engert <deengert@gmail.com>
891c12
Date: Sun, 29 Mar 2020 05:56:21 -0500
891c12
Subject: [PATCH 2/6] pkcs11-tool - use valid data for decription tests
891c12
891c12
In tests, make sute test data is either padded, or "zero" padded
891c12
so size if data <=  modlen - 11. The smallest pad in 11 bytes,
891c12
00 | NN | PS | 00. PS is at least 8 bytes.
891c12
"zero" padding has N = 00, PS >= 8 byte of 00.
891c12
891c12
 On branch cardos-5.3
891c12
 Changes to be committed:
891c12
	modified:   tools/pkcs11-tool.c
891c12
---
891c12
 src/tools/pkcs11-tool.c | 4 ++--
891c12
 1 file changed, 2 insertions(+), 2 deletions(-)
891c12
891c12
diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c
891c12
index 3ad9289033..b1674a76cf 100644
891c12
--- a/src/tools/pkcs11-tool.c
891c12
+++ b/src/tools/pkcs11-tool.c
891c12
@@ -5044,8 +5044,8 @@ static int test_signature(CK_SESSION_HANDLE sess)
891c12
 	}
891c12
 
891c12
 	if (firstMechType == CKM_RSA_X_509) {
891c12
-		/* make sure our data is smaller than the modulus */
891c12
-		data[0] = 0x00;
891c12
+		/* make sure our data is smaller than the modulus - 11 */
891c12
+		memset(data, 0, 11); /* in effect is zero padding */ 
891c12
 	}
891c12
 
891c12
 	ck_mech.mechanism = firstMechType;
891c12
891c12
From 3043f5b8a15c7cff90adcd2d31095afa734e663c Mon Sep 17 00:00:00 2001
891c12
From: Doug Engert <deengert@gmail.com>
891c12
Date: Sun, 5 Apr 2020 11:04:42 -0500
891c12
Subject: [PATCH 3/6] Increase SC_MAX_SUPPORTED_ALGORITHMS from 8 to 16
891c12
891c12
CardOS cards may have more then 8 supported_algo_info entries in tokenInfo.
891c12
We may bemissing some. We have seen 8 in some pkcs15-tool -i -v output.
891c12
891c12
Simple fix is to incrase the limit. More appropriate fix is to remove the limit,
891c12
much like is done with sc_algorithm_info. and use realloc of the array.
891c12
891c12
 On branch cardos-5.3
891c12
 Changes to be committed:
891c12
	modified:   src/libopensc/pkcs15-prkey.c
891c12
	modified:   src/libopensc/pkcs15-skey.c
891c12
	modified:   src/libopensc/pkcs15.c
891c12
	modified:   src/libopensc/types.h
891c12
---
891c12
 src/libopensc/pkcs15-prkey.c | 10 +++++++++-
891c12
 src/libopensc/pkcs15-skey.c  | 10 +++++++++-
891c12
 src/libopensc/pkcs15.c       | 10 +++++++++-
891c12
 src/libopensc/types.h        |  6 ++++--
891c12
 4 files changed, 31 insertions(+), 5 deletions(-)
891c12
891c12
diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c
891c12
index ed008ede14..a6c05415ec 100644
891c12
--- a/src/libopensc/pkcs15-prkey.c
891c12
+++ b/src/libopensc/pkcs15-prkey.c
891c12
@@ -48,10 +48,18 @@
891c12
 #include "aux-data.h"
891c12
 
891c12
 /*
891c12
- * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS  defined as 8
891c12
+ * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS  defined as 16
891c12
  */
891c12
 #define C_ASN1_SUPPORTED_ALGORITHMS_SIZE (SC_MAX_SUPPORTED_ALGORITHMS + 1)
891c12
 static const struct sc_asn1_entry c_asn1_supported_algorithms[C_ASN1_SUPPORTED_ALGORITHMS_SIZE] = {
891c12
+	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
 	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
 	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
 	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
diff --git a/src/libopensc/pkcs15-skey.c b/src/libopensc/pkcs15-skey.c
891c12
index b22e619723..4e58355ad7 100644
891c12
--- a/src/libopensc/pkcs15-skey.c
891c12
+++ b/src/libopensc/pkcs15-skey.c
891c12
@@ -28,10 +28,18 @@
891c12
 #include <assert.h>
891c12
 
891c12
 /*
891c12
- * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS  defined as 8
891c12
+ * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS  defined as 16
891c12
  */
891c12
 #define C_ASN1_SUPPORTED_ALGORITHMS_SIZE (SC_MAX_SUPPORTED_ALGORITHMS + 1)
891c12
 static const struct sc_asn1_entry c_asn1_supported_algorithms[C_ASN1_SUPPORTED_ALGORITHMS_SIZE] = {
891c12
+	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
 	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
 	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
 	{ "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c
891c12
index ba04f531ef..d4a4496980 100644
891c12
--- a/src/libopensc/pkcs15.c
891c12
+++ b/src/libopensc/pkcs15.c
891c12
@@ -64,9 +64,17 @@ static const struct sc_asn1_entry c_asn1_algorithm_info_parameters[3] = {
891c12
 };
891c12
 
891c12
 /*
891c12
- * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS  defined as 8
891c12
+ * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS  defined as 16
891c12
  */
891c12
 static const struct sc_asn1_entry c_asn1_supported_algorithms[SC_MAX_SUPPORTED_ALGORITHMS + 1] = {
891c12
+	{ "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
+	{ "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
 	{ "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
 	{ "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
 	{ "algorithmInfo", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
891c12
diff --git a/src/libopensc/types.h b/src/libopensc/types.h
891c12
index 76cf4c1a71..17035b5505 100644
891c12
--- a/src/libopensc/types.h
891c12
+++ b/src/libopensc/types.h
891c12
@@ -52,9 +52,11 @@ typedef unsigned char u8;
891c12
 
891c12
 /* When changing this value, pay attention to the initialization of the ASN1
891c12
  * static variables that use this macro, like, for example,
891c12
- * 'c_asn1_supported_algorithms' in src/libopensc/pkcs15.c
891c12
+ * 'c_asn1_supported_algorithms' in src/libopensc/pkcs15.c,
891c12
+ * src/libopensc/pkcs15-prkey.c and src/libopensc/pkcs15-skey.c
891c12
+ * `grep "src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS  defined as"'
891c12
  */
891c12
-#define SC_MAX_SUPPORTED_ALGORITHMS	8
891c12
+#define SC_MAX_SUPPORTED_ALGORITHMS	16
891c12
 
891c12
 struct sc_lv_data {
891c12
 	unsigned char *value;
891c12
891c12
From 8292ff57ad581995eca8209764813725594dd34f Mon Sep 17 00:00:00 2001
891c12
From: Doug Engert <deengert@gmail.com>
891c12
Date: Fri, 17 Apr 2020 12:26:14 -0500
891c12
Subject: [PATCH 4/6] sc_supported_algo_info - Put ECDSA OID as inline
891c12
891c12
    Mismatch of ASN1 parsing of tokeninfo.supported_algos[n].paramters
891c12
    in one place parameter was treated as a pointer to sc_object_id
891c12
    and in another as inline structure. This caused segfaults
891c12
    in pkcs15-tool when it tried to print the OID.
891c12
891c12
 Changes to be committed:
891c12
	modified:   src/libopensc/opensc.h
891c12
	modified:   src/libopensc/pkcs15.c
891c12
---
891c12
 src/libopensc/opensc.h | 2 +-
891c12
 src/libopensc/pkcs15.c | 2 +-
891c12
 2 files changed, 2 insertions(+), 2 deletions(-)
891c12
891c12
diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h
891c12
index 9e764665b2..0c3c73e229 100644
891c12
--- a/src/libopensc/opensc.h
891c12
+++ b/src/libopensc/opensc.h
891c12
@@ -223,7 +223,7 @@ extern "C" {
891c12
 struct sc_supported_algo_info {
891c12
 	unsigned int reference;
891c12
 	unsigned int mechanism;
891c12
-	struct sc_object_id *parameters; /* OID for ECC, NULL for RSA */
891c12
+	struct sc_object_id parameters; /* OID for ECC */
891c12
 	unsigned int operations;
891c12
 	struct sc_object_id algo_id;
891c12
 	unsigned int algo_ref;
891c12
diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c
891c12
index d4a4496980..c58c34fd13 100644
891c12
--- a/src/libopensc/pkcs15.c
891c12
+++ b/src/libopensc/pkcs15.c
891c12
@@ -318,7 +318,7 @@ sc_pkcs15_encode_tokeninfo(sc_context_t *ctx, sc_pkcs15_tokeninfo_t *ti,
891c12
 		sc_format_asn1_entry(asn1_algo_infos[ii] + 1, &ti->supported_algos[ii].mechanism, &mechanism_len, 1);
891c12
 		sc_format_asn1_entry(asn1_algo_infos[ii] + 2,
891c12
 			asn1_algo_infos_parameters[ii], NULL, 1);
891c12
-		if (!ti->supported_algos[ii].parameters)	{
891c12
+		if (!sc_valid_oid(&ti->supported_algos[ii].parameters)) {
891c12
 			sc_format_asn1_entry(asn1_algo_infos_parameters[ii] + 0,
891c12
 				NULL, NULL, 1);
891c12
 		}
891c12
891c12
From f9665e4d46ed278b6cf1188e0e7adb5b6e119ac9 Mon Sep 17 00:00:00 2001
891c12
From: Doug Engert <deengert@gmail.com>
891c12
Date: Thu, 26 Mar 2020 13:51:33 -0500
891c12
Subject: [PATCH 5/6] pkcs15-tool.c - print Supported_algorithms from tokenInfo
891c12
891c12
Some cards can provide supported algorithms in tokenInfo
891c12
which contain ECDSA OID, and PKCS11 mechanism
891c12
891c12
Don't know how many Algo_refs were actually read,
891c12
and a ref of 0 may be valid. print at least one Algo_refs.
891c12
891c12
Print the mechanism from PKCS11, and print operations
891c12
Use the $(top_srcdir)/src/pkcs11/pkcs11-display.c  on Unix
891c12
Use the $(TOPDIR)\src\pkcs11\pkcs11-display.obj on Windows
891c12
891c12
pkcs15.tool.c treat ECDSA OID as inline
891c12
891c12
pkcs15-tool prints PKCS11 mechanisms using pkcs11-display.c
891c12
Automake now warns that the default will change, in the future
891c12
so "[subdir-objects]" is added to configure.ac
891c12
891c12
 Changes to be committed:
891c12
	modified:   configure.ac
891c12
	modified:   src/tools/Makefile.am
891c12
	modified:   src/tools/Makefile.mak
891c12
	modified:   src/tools/pkcs15-tool.c
891c12
---
891c12
 configure.ac            |  2 +-
891c12
 src/tools/Makefile.am   |  2 +-
891c12
 src/tools/Makefile.mak  |  5 ++++
891c12
 src/tools/pkcs15-tool.c | 57 +++++++++++++++++++++++++++++++++++++++++
891c12
 4 files changed, 64 insertions(+), 2 deletions(-)
891c12
891c12
diff --git a/configure.ac b/configure.ac
891c12
index 705bc027f1..f54093b0aa 100644
891c12
--- a/configure.ac
891c12
+++ b/configure.ac
891c12
@@ -27,7 +27,7 @@ AC_INIT([PRODUCT_NAME],[PACKAGE_VERSION_MAJOR.PACKAGE_VERSION_MINOR.PACKAGE_VERS
891c12
 AC_CONFIG_AUX_DIR([.])
891c12
 AC_CONFIG_HEADERS([config.h])
891c12
 AC_CONFIG_MACRO_DIR([m4])
891c12
-AM_INIT_AUTOMAKE(foreign 1.10)
891c12
+AM_INIT_AUTOMAKE(foreign 1.10 [subdir-objects])
891c12
 
891c12
 OPENSC_VERSION_MAJOR="PACKAGE_VERSION_MAJOR"
891c12
 OPENSC_VERSION_MINOR="PACKAGE_VERSION_MINOR"
891c12
diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am
891c12
index 5ee5edfb29..55beb631d5 100644
891c12
--- a/src/tools/Makefile.am
891c12
+++ b/src/tools/Makefile.am
891c12
@@ -52,7 +52,7 @@ piv_tool_SOURCES = piv-tool.c util.c
891c12
 piv_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS)
891c12
 opensc_explorer_SOURCES = opensc-explorer.c util.c
891c12
 opensc_explorer_LDADD = $(OPTIONAL_READLINE_LIBS)
891c12
-pkcs15_tool_SOURCES = pkcs15-tool.c util.c
891c12
+pkcs15_tool_SOURCES = pkcs15-tool.c util.c ../pkcs11/pkcs11-display.c ../pkcs11/pkcs11-display.h
891c12
 pkcs15_tool_LDADD = $(OPTIONAL_OPENSSL_LIBS)
891c12
 pkcs11_tool_SOURCES = pkcs11-tool.c util.c
891c12
 pkcs11_tool_LDADD = \
891c12
diff --git a/src/tools/Makefile.mak b/src/tools/Makefile.mak
891c12
index 4637a44dc6..38e5ba4e7e 100644
891c12
--- a/src/tools/Makefile.mak
891c12
+++ b/src/tools/Makefile.mak
891c12
@@ -52,6 +52,11 @@ pkcs11-register.exe: pkcs11-register-cmdline.obj fread_to_eof.obj $(LIBS)
891c12
 	link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj pkcs11-register-cmdline.obj fread_to_eof.obj versioninfo-tools.res $(LIBS) gdi32.lib shell32.lib User32.lib ws2_32.lib
891c12
 	mt -manifest exe.manifest -outputresource:$@;1
891c12
 
891c12
+pkcs15-tool.exe: pkcs15-tool.obj $(TOPDIR)\src\pkcs11\pkcs11-display.obj
891c12
+	cl $(COPTS) /c $*.c
891c12
+	link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj $(TOPDIR)\src\pkcs11\pkcs11-display.obj $(OBJECTS) $(LIBS) $(OPENSSL_LIB) gdi32.lib shell32.lib User32.lib ws2_32.lib
891c12
+	mt -manifest exe.manifest -outputresource:$@;1
891c12
+
891c12
 .c.exe:
891c12
 	cl $(COPTS) /c $<
891c12
 	link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj $(OBJECTS) $(LIBS) $(OPENSSL_LIB) gdi32.lib shell32.lib User32.lib ws2_32.lib
891c12
diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c
891c12
index e901e17d0d..363bfb8272 100644
891c12
--- a/src/tools/pkcs15-tool.c
891c12
+++ b/src/tools/pkcs15-tool.c
891c12
@@ -57,6 +57,7 @@ typedef unsigned __int32 uint32_t;
891c12
 #include "libopensc/pkcs15.h"
891c12
 #include "libopensc/asn1.h"
891c12
 #include "util.h"
891c12
+#include "pkcs11/pkcs11-display.h"
891c12
 
891c12
 static const char *app_name = "pkcs15-tool";
891c12
 
891c12
@@ -607,6 +608,8 @@ static void print_prkey_info(const struct sc_pkcs15_object *obj)
891c12
 	struct sc_pkcs15_prkey_info *prkey = (struct sc_pkcs15_prkey_info *) obj->data;
891c12
 	unsigned char guid[40];
891c12
 	size_t guid_len;
891c12
+	int i;
891c12
+	int last_algo_refs = 0;
891c12
 
891c12
 	if (compact) {
891c12
 		printf("\t%-3s", key_types[7 & obj->type]);
891c12
@@ -635,6 +638,16 @@ static void print_prkey_info(const struct sc_pkcs15_object *obj)
891c12
 	printf("\tAccess Flags   : [0x%02X]", prkey->access_flags);
891c12
 	print_key_access_flags(prkey->access_flags);
891c12
 	printf("\n");
891c12
+	printf("\tAlgo_refs      : ");
891c12
+	/* zero may be valid and don't know how many were read  print at least 1*/
891c12
+	for (i = 0; i< SC_MAX_SUPPORTED_ALGORITHMS; i++) {
891c12
+		if (prkey->algo_refs[i] != 0)
891c12
+			last_algo_refs = i;
891c12
+	}
891c12
+	for (i = 0; i< last_algo_refs + 1; i++) {
891c12
+		printf("%s%u", (i == 0) ? "" : ", ", prkey->algo_refs[i]);
891c12
+	}
891c12
+	printf("\n");
891c12
 
891c12
 	print_access_rules(obj->access_rules, SC_PKCS15_MAX_ACCESS_RULES);
891c12
 
891c12
@@ -1645,6 +1658,21 @@ static int list_apps(FILE *fout)
891c12
 	return 0;
891c12
 }
891c12
 
891c12
+
891c12
+static void print_supported_algo_info_operations(unsigned int operation)
891c12
+
891c12
+{
891c12
+	size_t i;
891c12
+	const char *operations[] = {
891c12
+		"compute_checksum", "compute_signature", "verify_checksum", "verify_signature",
891c12
+		"encipher", "decipher", "hash", "generate/derive_key"
891c12
+	};
891c12
+	const size_t operations_count = NELEMENTS(operations);
891c12
+	for (i = 0; i < operations_count; i++)
891c12
+		if (operation & (1 << i))
891c12
+			printf(", %s", operations[i]);
891c12
+}
891c12
+
891c12
 static void list_info(void)
891c12
 {
891c12
 	const char *flags[] = {
891c12
@@ -1655,6 +1683,7 @@ static void list_info(void)
891c12
 	};
891c12
 	char *last_update = sc_pkcs15_get_lastupdate(p15card);
891c12
 	int i, count = 0;
891c12
+	int idx;
891c12
 
891c12
 	printf("PKCS#15 Card [%s]:\n", p15card->tokeninfo->label);
891c12
 	printf("\tVersion        : %d\n", p15card->tokeninfo->version);
891c12
@@ -1675,6 +1704,34 @@ static void list_info(void)
891c12
 			count++;
891c12
 		}
891c12
 	}
891c12
+	printf("\n");
891c12
+	for (i = 0; i < SC_MAX_SUPPORTED_ALGORITHMS; i++) {
891c12
+		struct sc_supported_algo_info * sa = &p15card->tokeninfo->supported_algos[i];
891c12
+
891c12
+		if (sa->reference == 0 && sa->reference == 0 && sa->mechanism == 0
891c12
+				&& sa->operations == 0 && sa->algo_ref == 0)
891c12
+					break;
891c12
+		printf("\t\t sc_supported_algo_info[%d]:\n", i);
891c12
+		printf("\t\t\t reference  : %u (0x%02x)\n", sa->reference, sa->reference);
891c12
+		printf("\t\t\t mechanism  : [0x%02x] %s\n", sa->mechanism, lookup_enum(MEC_T, sa->mechanism));
891c12
+		if (sc_valid_oid(&sa->parameters)) {
891c12
+			printf("\t\t\t parameters:  %i", sa->parameters.value[0]);
891c12
+			for (idx = 1; idx < SC_MAX_OBJECT_ID_OCTETS && sa->parameters.value[idx] != -1 ; idx++)
891c12
+				printf(".%i", sa->parameters.value[idx]);
891c12
+			printf("\n");
891c12
+		}
891c12
+		printf("\t\t\t operations : [0x%2.2x]",sa->operations);
891c12
+		print_supported_algo_info_operations(sa->operations);
891c12
+		printf("\n");
891c12
+		if (sc_valid_oid((const struct sc_object_id*)&sa->algo_id)) {
891c12
+			printf("\t\t\t algo_id    : %i", sa->algo_id.value[0]);
891c12
+			for (idx = 1; idx < SC_MAX_OBJECT_ID_OCTETS && sa->algo_id.value[idx] != -1 ; idx++)
891c12
+				printf(".%i", sa->algo_id.value[idx]);
891c12
+			printf("\n");
891c12
+		}
891c12
+		printf("\t\t\t algo_ref   : [0x%02x]\n",sa->algo_ref);
891c12
+	}
891c12
+
891c12
 	printf((compact) ? "\n" : "\n\n");
891c12
 }
891c12
 
891c12
891c12
From f472f0ec213adc096508997bf7e1786ffb557d52 Mon Sep 17 00:00:00 2001
891c12
From: Doug Engert <deengert@gmail.com>
891c12
Date: Fri, 17 Apr 2020 11:36:48 -0500
891c12
Subject: [PATCH 6/6] Various CardOS V5_* improvements
891c12
MIME-Version: 1.0
891c12
Content-Type: text/plain; charset=UTF-8
891c12
Content-Transfer-Encoding: 8bit
891c12
891c12
Treat CardOS V5_0 and V5_3 cards differently then older versions:
891c12
891c12
Use card->dvr_data as a pointer to cardos_data_t to store private driver
891c12
data to pass internally, especially between set security environment
891c12
and the crypto operations. Sc_get_encoding_flags sets sec_flags from
891c12
algo_info->flags in pkcs15-sec.c and it passed to decipher.
891c12
891c12
Some cards when doing a decipher may drop leading 00 byte when
891c12
returning data from RSA_RAW decipher. Add leading byte(s) as needed.
891c12
891c12
Get Cryptographic Mechanism Reference from Key Reference:
891c12
891c12
Key reference byte appears to be a 4 bit Cryptographic Mechanism Reference
891c12
and a 4 bit key reference.
891c12
891c12
This is only done if key reference & 0xF0 != 0  i.e. default Cryptographic
891c12
mechanism reference is 0. which appears to be the case for RSA RAW.
891c12
PKCS1 appears to be 0x10 and ECDSA 0x30
891c12
891c12
    See iso 7816-4 table 55 for DST:
891c12
      84 Reference of a private key
891c12
      95 Usage qualifier byte - Table 57 - 40 looks OK
891c12
      80 Cryptographic mechanism reference and referes to section 9.2
891c12
891c12
The 4 bit key reference limits card to 16 keys. In future this may not work,
891c12
but we can derive a Cryptographic Mechanism Reference from what OpenSC
891c12
thinks the card needs to do. Only know RSA RAW, PKCS1 and ECDSA.
891c12
891c12
ECDSA code has not been tested, but expected to work.
891c12
891c12
Allow setting CardOS type and flags from opensc.conf using card_atr stanza
891c12
This is a fallback if newer cards are added or older cards have problems
891c12
giving us time to make need changes in next release.
891c12
891c12
It will help in identifying what flags are needed for each card.
891c12
As user can report what combination of flags work for them. They do this by
891c12
adding to opensc.conf with something like this. (Change the ATR to your card's ATR):
891c12
891c12
        card_atr 3b:d2:18:00:81:31:fe:58:c9:03:16 {
891c12
                driver = "cardos";
891c12
                # type is decimal from cards.h:
891c12
                # SC_CARD_TYPE_CARDOS_V5_0 is 1009
891c12
                # SC_CARD_TYPE_CARDOS_V5_3 is 1010
891c12
                type = 1010;
891c12
891c12
                # flags is hex from opensc.h:
891c12
                #define SC_ALGORITHM_ONBOARD_KEY_GEN    0x80000000
891c12
                #define SC_ALGORITHM_NEED_USAGE         0x40000000
891c12
891c12
                #define SC_ALGORITHM_RSA_RAW            0x00000001 /* RSA_RAW is PAD_NONE */
891c12
                #define SC_ALGORITHM_RSA_PAD_NONE       0x00000001
891c12
                #define SC_ALGORITHM_RSA_PAD_PKCS1      0x00000002 /* PKCS#1 v1.5 padding */
891c12
                #define SC_ALGORITHM_RSA_PAD_ANSI       0x00000004
891c12
                #define SC_ALGORITHM_RSA_PAD_ISO9796    0x00000008
891c12
                #define SC_ALGORITHM_RSA_PAD_PSS        0x00000010 /* PKCS#1 v2.0 PSS */
891c12
                #define SC_ALGORITHM_RSA_PAD_OAEP       0x00000020 /* PKCS#1 v2.0 OAEP */
891c12
                #define SC_ALGORITHM_RSA_HASH_NONE      0x00000100 /* only applies to PKCS1 padding */
891c12
                # example: SC_ALGORITHM_ONBOARD_KEY_GEN | SC_ALGORITHM_RSA_HASH_NONE |  SC_ALGORITHM_RSA_RAW
891c12
                flags = 80000101;
891c12
                #example: SC_ALGORITHM_ONBOARD_KEY_GEN | SC_ALGORITHM_RSA_PAD_PKCS1
891c12
                flags = 80000002;
891c12
        }
891c12
891c12
For V5_0 and v5_3 cards, use sc_get_max_send_size and sc_get_max_recv_size
891c12
which takes care or reader sizes even on Windows where SCardControl can not get PART_10 sizes.
891c12
891c12
(commit eddea6f3c2d3dafc2c09eba6695c745a61b5186f on Windows forces reader sizes to 255, 256
891c12
in reader-pcsc.c if not already set. It should not do this, but leave that up to card drivers.)
891c12
891c12
pkcs15-cardos.c added:
891c12
891c12
New file, pkcs15-cardos.c, added as emulation only for CardOS
891c12
V5_0 and V5_3 cards.
891c12
891c12
sc_pkcs15_bind_internal is called to get tokenInfo as CardOS
891c12
cards are substantially PKCS15 cards. But some V5_* cards have
891c12
errors in the tokenInfo, Which are corrected.
891c12
891c12
For older CardOS cards, card-cardos.c will create all the
891c12
card->algorithms.
891c12
891c12
Pkcs15-cardos.c will check for card->algorithms and if there
891c12
are none, it will do the following:
891c12
891c12
SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS is called twice. First to get
891c12
the flags as set by user via opensc.conf card_atr or default
891c12
flags set by the card driver.  Then after determining from the
891c12
tokenInfo what algorithms the card can support, the new flags
891c12
are passed to card_cardos.c to create card->algorithms.
891c12
891c12
https://atos.net/wp-content/uploads/2018/11/CT_181026_LPM_CardOS_V5-3_Multifunctionality_FS_en3_web.pdf
891c12
says card supports: "“Command chaining” in accordance with ISO/IEC 7816-4"
891c12
891c12
To take advantage of this with older readers, max_send_size and max_recv_size
891c12
is now based on minimum of reader limits and  "data_field_length" from card.
891c12
This should allow card to work in older readers not capable of extended APDU.
891c12
So far current cards we have seen do no appear to support “Command chaining”.
891c12
891c12
 Changes to be committed:
891c12
	modified:   src/libopensc/Makefile.am
891c12
	modified:   src/libopensc/Makefile.mak
891c12
	modified:   src/libopensc/card-cardos.c
891c12
	modified:   src/libopensc/cardctl.h
891c12
	modified:   src/libopensc/cards.h
891c12
	new file:   src/libopensc/pkcs15-cardos.c
891c12
	modified:   src/libopensc/pkcs15-syn.c
891c12
	modified:   src/libopensc/pkcs15-syn.h
891c12
---
891c12
 src/libopensc/Makefile.am     |   4 +-
891c12
 src/libopensc/Makefile.mak    |   2 +-
891c12
 src/libopensc/card-cardos.c   | 336 +++++++++++++++++++++++++++++-----
891c12
 src/libopensc/cardctl.h       |  18 ++
891c12
 src/libopensc/cards.h         |   1 +
891c12
 src/libopensc/pkcs15-cardos.c | 177 ++++++++++++++++++
891c12
 src/libopensc/pkcs15-syn.c    |   3 +
891c12
 src/libopensc/pkcs15-syn.h    |   1 +
891c12
 8 files changed, 492 insertions(+), 50 deletions(-)
891c12
 create mode 100644 src/libopensc/pkcs15-cardos.c
891c12
891c12
diff --git a/src/libopensc/Makefile.am b/src/libopensc/Makefile.am
891c12
index 140665c8a6..9f0dda5ecb 100644
891c12
--- a/src/libopensc/Makefile.am
891c12
+++ b/src/libopensc/Makefile.am
891c12
@@ -51,7 +51,7 @@ libopensc_la_SOURCES_BASE = \
891c12
 	ctbcs.c reader-ctapi.c reader-pcsc.c reader-openct.c reader-tr03119.c \
891c12
 	\
891c12
 	card-setcos.c card-miocos.c card-flex.c card-gpk.c \
891c12
-	card-cardos.c card-tcos.c card-default.c \
891c12
+	card-cardos.c card-tcos.c pkcs15-cardos.c card-default.c \
891c12
 	card-mcrd.c card-starcos.c card-openpgp.c card-jcop.c \
891c12
 	card-oberthur.c card-belpic.c card-atrust-acos.c \
891c12
 	card-entersafe.c card-epass2003.c card-coolkey.c card-incrypto34.c \
891c12
@@ -134,7 +134,7 @@ TIDY_FILES = \
891c12
 	card-npa.c card-esteid2018.c card-idprime.c \
891c12
 	\
891c12
 	pkcs15-openpgp.c \
891c12
-	pkcs15-tcos.c pkcs15-esteid.c \
891c12
+	pkcs15-tcos.c pkcs15-esteid.c pkcs15-cardos.c \
891c12
 	pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c \
891c12
 	pkcs15-cac.c pkcs15-esinit.c pkcs15-westcos.c pkcs15-pteid.c \
891c12
 	pkcs15-oberthur.c pkcs15-itacns.c pkcs15-sc-hsm.c \
891c12
diff --git a/src/libopensc/Makefile.mak b/src/libopensc/Makefile.mak
891c12
index 2e3c30c22b..1b0ff45c9b 100644
891c12
--- a/src/libopensc/Makefile.mak
891c12
+++ b/src/libopensc/Makefile.mak
891c12
@@ -29,7 +29,7 @@ OBJECTS			= \
891c12
 	card-masktech.obj card-gids.obj card-jpki.obj \
891c12
 	card-npa.obj card-esteid2018.obj card-idprime.obj \
891c12
 	\
891c12
-	pkcs15-openpgp.obj pkcs15-starcert.obj \
891c12
+	pkcs15-openpgp.obj pkcs15-starcert.obj pkcs15-cardos.obj \
891c12
 	pkcs15-tcos.obj pkcs15-esteid.obj pkcs15-gemsafeGPK.obj \
891c12
 	pkcs15-actalis.obj pkcs15-atrust-acos.obj pkcs15-tccardos.obj pkcs15-piv.obj \
891c12
 	pkcs15-cac.obj pkcs15-esinit.obj pkcs15-westcos.obj pkcs15-pteid.obj pkcs15-din-66291.obj \
891c12
diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c
891c12
index 306822b974..4ef6ead0d2 100644
891c12
--- a/src/libopensc/card-cardos.c
891c12
+++ b/src/libopensc/card-cardos.c
891c12
@@ -53,13 +53,42 @@ static const struct sc_atr_table cardos_atrs[] = {
891c12
 	/* CardOS v5.0 */
891c12
 	{ "3b:d2:18:00:81:31:fe:58:c9:01:14", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_0, 0, NULL},
891c12
 	/* CardOS v5.3 */
891c12
-	{ "3b:d2:18:00:81:31:fe:58:c9:02:17", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_0, 0, NULL},
891c12
-	{ "3b:d2:18:00:81:31:fe:58:c9:03:16", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_0, 0, NULL},
891c12
+	{ "3b:d2:18:00:81:31:fe:58:c9:02:17", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_3, 0, NULL},
891c12
+	{ "3b:d2:18:00:81:31:fe:58:c9:03:16", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_3, 0, NULL},
891c12
 	{ NULL, NULL, NULL, 0, 0, NULL }
891c12
 };
891c12
 
891c12
-static unsigned int algorithm_ids_in_tokeninfo[SC_MAX_SUPPORTED_ALGORITHMS];
891c12
-static unsigned int algorithm_ids_in_tokeninfo_count=0;
891c12
+/* private data for cardos driver */
891c12
+typedef struct cardos_data {
891c12
+	/* constructed internally */
891c12
+	unsigned int algorithm_ids_in_tokeninfo[SC_MAX_SUPPORTED_ALGORITHMS];
891c12
+	unsigned int algorithm_ids_in_tokeninfo_count;
891c12
+	unsigned long flags; /* flags used by init to create sc_algorithms */
891c12
+	unsigned long ec_flags;
891c12
+	unsigned long ext_flags;
891c12
+	int rsa_2048;
891c12
+	const sc_security_env_t * sec_env;
891c12
+} cardos_data_t;
891c12
+
891c12
+/* copied from iso7816.c */
891c12
+static void fixup_transceive_length(const struct sc_card *card,
891c12
+		struct sc_apdu *apdu)
891c12
+{
891c12
+	if (card == NULL || apdu == NULL) {
891c12
+		return;
891c12
+	}
891c12
+
891c12
+	if (apdu->lc > sc_get_max_send_size(card)) {
891c12
+		/* The lower layers will automatically do chaining */
891c12
+		apdu->flags |= SC_APDU_FLAGS_CHAINING;
891c12
+	}
891c12
+
891c12
+	if (apdu->le > sc_get_max_recv_size(card)) {
891c12
+		/* The lower layers will automatically do a GET RESPONSE, if possible.
891c12
+		 * All other workarounds must be carried out by the upper layers. */
891c12
+		apdu->le = sc_get_max_recv_size(card);
891c12
+	}
891c12
+}
891c12
 
891c12
 static int cardos_match_card(sc_card_t *card)
891c12
 {
891c12
@@ -79,6 +108,8 @@ static int cardos_match_card(sc_card_t *card)
891c12
 		return 1;
891c12
 	if (card->type == SC_CARD_TYPE_CARDOS_V5_0)
891c12
 		return 1;
891c12
+	if (card->type == SC_CARD_TYPE_CARDOS_V5_3)
891c12
+		return 1;
891c12
 	if (card->type == SC_CARD_TYPE_CARDOS_M4_2) {
891c12
 		int rv;
891c12
 		sc_apdu_t apdu;
891c12
@@ -159,42 +190,102 @@ static int cardos_have_2048bit_package(sc_card_t *card)
891c12
 	return 0;
891c12
 }
891c12
 
891c12
+
891c12
+/* Called from cardos_init for old cards, from cardos_cardctl_parsed_token_info for new cards */
891c12
+/* TODO see if works from old cards too */
891c12
+static int cardos_add_algs(sc_card_t *card, unsigned long flags, unsigned long ec_flags, unsigned long ext_flags)
891c12
+{
891c12
+
891c12
+	cardos_data_t * priv = (cardos_data_t *)card->drv_data;
891c12
+
891c12
+	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
891c12
+
891c12
+	_sc_card_add_rsa_alg(card,  512, flags, 0);
891c12
+	_sc_card_add_rsa_alg(card,  768, flags, 0);
891c12
+	_sc_card_add_rsa_alg(card, 1024, flags, 0);
891c12
+	if (priv->rsa_2048 == 1) {
891c12
+		_sc_card_add_rsa_alg(card, 1280, flags, 0);
891c12
+		_sc_card_add_rsa_alg(card, 1536, flags, 0);
891c12
+		_sc_card_add_rsa_alg(card, 1792, flags, 0);
891c12
+		_sc_card_add_rsa_alg(card, 2048, flags, 0);
891c12
+	}
891c12
+
891c12
+	if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) {
891c12
+		/* Starting with CardOS 5, the card supports PIN query commands */
891c12
+		card->caps |= SC_CARD_CAP_ISO7816_PIN_INFO;
891c12
+		_sc_card_add_rsa_alg(card, 3072, flags, 0);
891c12
+		_sc_card_add_rsa_alg(card, 4096, flags, 0);
891c12
+	}
891c12
+
891c12
+	/* TODO need to get sizes from supported_algos too */
891c12
+	if (ec_flags != 0) {
891c12
+		 _sc_card_add_ec_alg(card, 256, ec_flags, priv->ext_flags, NULL);
891c12
+		 _sc_card_add_ec_alg(card, 384, ec_flags, priv->ext_flags, NULL);
891c12
+	}
891c12
+
891c12
+	return 0;
891c12
+}
891c12
+
891c12
 static int cardos_init(sc_card_t *card)
891c12
 {
891c12
-	unsigned long flags = 0, rsa_2048 = 0;
891c12
+	cardos_data_t * priv = NULL;
891c12
+	unsigned long flags = 0;
891c12
 	size_t data_field_length;
891c12
 	sc_apdu_t apdu;
891c12
 	u8 rbuf[2];
891c12
 	int r;
891c12
 
891c12
+	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
891c12
+
891c12
+	priv = calloc(1, sizeof(cardos_data_t));
891c12
+	if (!priv)
891c12
+		LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
891c12
+	card->drv_data = priv;
891c12
+
891c12
 	card->name = "Atos CardOS";
891c12
 	card->cla = 0x00;
891c12
 
891c12
-	/* Set up algorithm info. */
891c12
-	flags = 0;
891c12
-	if (card->type == SC_CARD_TYPE_CARDOS_V5_0) {
891c12
-		flags |= SC_ALGORITHM_RSA_PAD_PKCS1;
891c12
+	/* let user override flags and type from opensc.conf */
891c12
+	/* user can override card->type too.*/
891c12
+	if (card->flags) {
891c12
+	    flags = card->flags;
891c12
 	} else {
891c12
-		flags |= SC_ALGORITHM_RSA_RAW
891c12
-			| SC_ALGORITHM_RSA_HASH_NONE
891c12
-			| SC_ALGORITHM_NEED_USAGE
891c12
-			| SC_ALGORITHM_ONBOARD_KEY_GEN;
891c12
+
891c12
+		/* Set up algorithm info. */
891c12
+		flags = 0;
891c12
+		if (card->type == SC_CARD_TYPE_CARDOS_V5_0) {
891c12
+			flags |= SC_ALGORITHM_RSA_PAD_PKCS1;
891c12
+		} else if(card->type == SC_CARD_TYPE_CARDOS_V5_3) {
891c12
+			flags |= SC_ALGORITHM_RSA_RAW
891c12
+				| SC_ALGORITHM_RSA_HASH_NONE
891c12
+				| SC_ALGORITHM_ONBOARD_KEY_GEN;
891c12
+		} else {
891c12
+			flags |= SC_ALGORITHM_RSA_RAW
891c12
+				| SC_ALGORITHM_RSA_HASH_NONE
891c12
+				| SC_ALGORITHM_NEED_USAGE
891c12
+				| SC_ALGORITHM_ONBOARD_KEY_GEN;
891c12
+		}
891c12
 	}
891c12
 
891c12
+	priv->flags = flags;
891c12
+
891c12
 	if (card->type == SC_CARD_TYPE_CARDOS_M4_2) {
891c12
 		r = cardos_have_2048bit_package(card);
891c12
 		if (r < 0)
891c12
 			return SC_ERROR_INVALID_CARD;
891c12
 		if (r == 1)
891c12
-			rsa_2048 = 1;
891c12
+			priv->rsa_2048 = 1;
891c12
 		card->caps |= SC_CARD_CAP_APDU_EXT;
891c12
-	} else if (card->type == SC_CARD_TYPE_CARDOS_M4_3 
891c12
+	} else if (card->type == SC_CARD_TYPE_CARDOS_M4_3
891c12
 		|| card->type == SC_CARD_TYPE_CARDOS_M4_2B
891c12
 		|| card->type == SC_CARD_TYPE_CARDOS_M4_2C
891c12
 		|| card->type == SC_CARD_TYPE_CARDOS_M4_4
891c12
-		|| card->type == SC_CARD_TYPE_CARDOS_V5_0) {
891c12
-		rsa_2048 = 1;
891c12
+		|| card->type == SC_CARD_TYPE_CARDOS_V5_0
891c12
+		|| card->type == SC_CARD_TYPE_CARDOS_V5_3) {
891c12
+		priv->rsa_2048 = 1;
891c12
 		card->caps |= SC_CARD_CAP_APDU_EXT;
891c12
+		/* TODO check this. EC only if in supported_algo */
891c12
+		priv->ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES;
891c12
 	}
891c12
 
891c12
 	/* probe DATA FIELD LENGTH with GET DATA */
891c12
@@ -202,6 +293,7 @@ static int cardos_init(sc_card_t *card)
891c12
 	apdu.le = sizeof rbuf;
891c12
 	apdu.resp = rbuf;
891c12
 	apdu.resplen = sizeof(rbuf);
891c12
+
891c12
 	r = sc_transmit_apdu(card, &apdu);
891c12
 	if (r < 0)
891c12
 		LOG_TEST_RET(card->ctx,
891c12
@@ -216,34 +308,99 @@ static int cardos_init(sc_card_t *card)
891c12
 		return SC_ERROR_INVALID_CARD;
891c12
 	data_field_length = ((rbuf[0] << 8) | rbuf[1]);
891c12
 
891c12
-	/* strip the length of possible Lc and Le bytes */
891c12
-	if (card->caps & SC_CARD_CAP_APDU_EXT)
891c12
-		card->max_send_size = data_field_length - 6;
891c12
-	else
891c12
-		card->max_send_size = data_field_length - 3;
891c12
-	/* strip the length of SW bytes */
891c12
-	card->max_recv_size = data_field_length - 2;
891c12
+	/* TODO is this really needed? strip the length of possible Lc and Le bytes */
891c12
+
891c12
+	/* Use Min card sizes and reader too. for V5_3 at least*/
891c12
+
891c12
+	if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) {
891c12
+		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "data_field_length:%"SC_FORMAT_LEN_SIZE_T"u "
891c12
+				"card->reader->max_send_size:%"SC_FORMAT_LEN_SIZE_T"u "
891c12
+				"card->reader->max_recv_size:%"SC_FORMAT_LEN_SIZE_T"u %s",
891c12
+				data_field_length, card->reader->max_send_size, card->reader->max_recv_size,
891c12
+				(card->caps & SC_CARD_CAP_APDU_EXT) ? "SC_CARD_CAP_APDU_EXT" : " ");
891c12
+
891c12
+		if (card->caps & SC_CARD_CAP_APDU_EXT) {
891c12
+			card->max_send_size  = data_field_length - 6;
891c12
+#ifdef _WIN32
891c12
+			/* Windows does not support PCSC PART_10 and may have forced reader to 255/256
891c12
+			 * https://github.com/OpenSC/OpenSC/commit/eddea6f3c2d3dafc2c09eba6695c745a61b5186f
891c12
+			 * may have reset this. if so, will override and force extended 
891c12
+			 * Most, if not all, cardos cards do extended, but not chaining 
891c12
+			 */
891c12
+			if (card->reader->max_send_size == 255 && card->reader->max_recv_size == 256) {
891c12
+				sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "reseting reader to use data_field_length");
891c12
+				card->reader->max_send_size = data_field_length - 6;
891c12
+				card->reader->max_recv_size = data_field_length - 3;
891c12
+			}
891c12
+#endif
891c12
+		} else
891c12
+			card->max_send_size = data_field_length - 3;
891c12
 
891c12
-	_sc_card_add_rsa_alg(card,  512, flags, 0);
891c12
-	_sc_card_add_rsa_alg(card,  768, flags, 0);
891c12
-	_sc_card_add_rsa_alg(card, 1024, flags, 0);
891c12
-	if (rsa_2048 == 1) {
891c12
-		_sc_card_add_rsa_alg(card, 1280, flags, 0);
891c12
-		_sc_card_add_rsa_alg(card, 1536, flags, 0);
891c12
-		_sc_card_add_rsa_alg(card, 1792, flags, 0);
891c12
-		_sc_card_add_rsa_alg(card, 2048, flags, 0);
891c12
+		card->max_send_size = sc_get_max_send_size(card); /* include reader sizes and protocol */
891c12
+		card->max_recv_size = data_field_length - 2;
891c12
+		card->max_recv_size = sc_get_max_recv_size(card);
891c12
+	} else {
891c12
+		/* old way, disregards reader capabilities */
891c12
+		if (card->caps & SC_CARD_CAP_APDU_EXT)
891c12
+			card->max_send_size = data_field_length - 6;
891c12
+		else
891c12
+			card->max_send_size = data_field_length - 3;
891c12
+		/* strip the length of SW bytes */
891c12
+		card->max_recv_size = data_field_length - 2;
891c12
 	}
891c12
 
891c12
-	if (card->type == SC_CARD_TYPE_CARDOS_V5_0) {
891c12
-		/* Starting with CardOS 5, the card supports PIN query commands */
891c12
-		card->caps |= SC_CARD_CAP_ISO7816_PIN_INFO;
891c12
-		_sc_card_add_rsa_alg(card, 3072, flags, 0);
891c12
-		_sc_card_add_rsa_alg(card, 4096, flags, 0);
891c12
+	/*for new cards, wait till after sc_pkcs15_bind_internal reads tokeninfo */
891c12
+	if (card->type != SC_CARD_TYPE_CARDOS_V5_0 && card->type != SC_CARD_TYPE_CARDOS_V5_3) {
891c12
+		r = cardos_add_algs(card, flags, 0, 0);
891c12
 	}
891c12
 
891c12
 	return 0;
891c12
 }
891c12
 
891c12
+static int cardos_pass_algo_flags(sc_card_t *card, struct sc_cardctl_cardos_pass_algo_flags * ptr)
891c12
+{
891c12
+	cardos_data_t * priv = (cardos_data_t *)card->drv_data;
891c12
+	int r = 0;
891c12
+
891c12
+	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
891c12
+	switch (ptr->pass) {
891c12
+		case 1:
891c12
+			ptr->card_flags = card->flags;
891c12
+			ptr->used_flags = priv->flags;
891c12
+			ptr->ec_flags = priv->ec_flags;
891c12
+			ptr->ext_flags = priv->ext_flags;
891c12
+			break;
891c12
+		case 2:
891c12
+			r = cardos_add_algs(card,ptr->new_flags, ptr->ec_flags, ptr->ext_flags);
891c12
+			break;
891c12
+		default:
891c12
+			sc_log(card->ctx, "ptr->pass: %ul invalid", ptr->pass);
891c12
+			r = SC_ERROR_INTERNAL;
891c12
+	}
891c12
+	LOG_FUNC_RETURN(card->ctx, r);
891c12
+}
891c12
+
891c12
+
891c12
+static int cardos_finish(sc_card_t *card)
891c12
+{
891c12
+	int r = 0;
891c12
+
891c12
+	if (card)
891c12
+		return 0;
891c12
+
891c12
+	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
891c12
+
891c12
+	/* free priv data */
891c12
+	if (card->drv_data) { /* priv */
891c12
+		free(card->drv_data);
891c12
+		card->drv_data = NULL;
891c12
+	}
891c12
+
891c12
+	SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
891c12
+}
891c12
+
891c12
+
891c12
+
891c12
 static const struct sc_card_error cardos_errors[] = {
891c12
 /* some error inside the card */
891c12
 /* i.e. nothing you can do */
891c12
@@ -772,8 +929,9 @@ cardos_set_security_env(sc_card_t *card,
891c12
 			    const sc_security_env_t *env,
891c12
 			    int se_num)
891c12
 {
891c12
+	cardos_data_t* priv = (cardos_data_t*)card->drv_data;
891c12
 	sc_apdu_t apdu;
891c12
-	u8	data[6];
891c12
+	u8	data[9];
891c12
 	int	key_id, r;
891c12
 
891c12
 	assert(card != NULL && env != NULL);
891c12
@@ -782,6 +940,15 @@ cardos_set_security_env(sc_card_t *card,
891c12
 		sc_log(card->ctx, "No or invalid key reference\n");
891c12
 		return SC_ERROR_INVALID_ARGUMENTS;
891c12
 	}
891c12
+	priv->sec_env = env; /* pass on to crypto routines */
891c12
+
891c12
+	/* key_ref includes card mechanism and key number
891c12
+	 * But newer cards appear to get this some other way,
891c12
+	 * We can use flags passed to know what OpenSC expects from the card
891c12
+	 * and have derived what these machanisums are. 
891c12
+	 * Newer cards may change how this is done
891c12
+	 */
891c12
+
891c12
 	key_id = env->key_ref[0];
891c12
 
891c12
 	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0);
891c12
@@ -802,16 +969,39 @@ cardos_set_security_env(sc_card_t *card,
891c12
 		return SC_ERROR_INVALID_ARGUMENTS;
891c12
 	}
891c12
 
891c12
-	if (card->type == SC_CARD_TYPE_CARDOS_V5_0) {
891c12
+	if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) {
891c12
+		/* some cards appear to have key_id be both Cryptographic mechanism reference 4 bits
891c12
+		 * and key_ref 4 bits. But this limits card to 16 keys.
891c12
+		 * TODO may need to be looked at at a later time
891c12
+		 */
891c12
 		/* Private key reference */
891c12
 		data[0] = 0x84;
891c12
 		data[1] = 0x01;
891c12
-		data[2] = key_id;
891c12
+		data[2] = key_id & 0x0F;
891c12
 		/* Usage qualifier byte */
891c12
 		data[3] = 0x95;
891c12
 		data[4] = 0x01;
891c12
 		data[5] = 0x40;
891c12
 		apdu.lc = apdu.datalen = 6;
891c12
+		if (key_id & 0xF0) {
891c12
+			/* Cryptographic mechanism reference */
891c12
+			data[6] = 0x80;
891c12
+			data[7] = 0x01;
891c12
+			data[8] = key_id & 0xF0;
891c12
+			apdu.lc = apdu.datalen = 9;
891c12
+		} else if (priv->sec_env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
891c12
+			/* TODO this may only apply to c903 cards */
891c12
+			/* TODO or only for cards without any supported_algos or EIDComplient only */
891c12
+			data[6] = 0x80;
891c12
+			data[7] = 0x01;
891c12
+			data[8] = 0x10;
891c12
+			apdu.lc = apdu.datalen = 9;
891c12
+		} else if (priv->sec_env->algorithm_flags & SC_ALGORITHM_ECDSA_RAW) {
891c12
+			data[6] = 0x80;
891c12
+			data[7] = 0x01;
891c12
+			data[8] = 0x30;
891c12
+			apdu.lc = apdu.datalen = 9;
891c12
+		}
891c12
 	} else {
891c12
 		data[0] = 0x83;
891c12
 		data[1] = 0x01;
891c12
@@ -839,12 +1029,12 @@ cardos_set_security_env(sc_card_t *card,
891c12
 
891c12
 				sc_log(card->ctx, "is signature");
891c12
 				sc_log(card->ctx, "Adding ID %d at index %d", algorithm_id, algorithm_id_count);
891c12
-				algorithm_ids_in_tokeninfo[algorithm_id_count++] = algorithm_id;
891c12
+				priv->algorithm_ids_in_tokeninfo[algorithm_id_count++] = algorithm_id;
891c12
 			}
891c12
 			sc_log(card->ctx, "reference=%d, mechanism=%d, operations=%d, algo_ref=%d",
891c12
 					alg.reference, alg.mechanism, alg.operations, alg.algo_ref);
891c12
 		}
891c12
-		algorithm_ids_in_tokeninfo_count = algorithm_id_count;
891c12
+		priv -> algorithm_ids_in_tokeninfo_count = algorithm_id_count;
891c12
 	} while (0);
891c12
 
891c12
 	LOG_FUNC_RETURN(card->ctx, r);
891c12
@@ -859,6 +1049,7 @@ static int
891c12
 do_compute_signature(sc_card_t *card, const u8 *data, size_t datalen,
891c12
 		     u8 *out, size_t outlen)
891c12
 {
891c12
+	/* cardos_data_t* priv = (cardos_data_t*)card->drv_dataa */;
891c12
 	int r;
891c12
 	sc_apdu_t apdu;
891c12
 
891c12
@@ -873,6 +1064,7 @@ do_compute_signature(sc_card_t *card, const u8 *data, size_t datalen,
891c12
 	apdu.data    = data;
891c12
 	apdu.lc      = datalen;
891c12
 	apdu.datalen = datalen;
891c12
+	fixup_transceive_length(card, &apdu);
891c12
 	r = sc_transmit_apdu(card, &apdu);
891c12
 	LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
891c12
 
891c12
@@ -886,6 +1078,7 @@ static int
891c12
 cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen,
891c12
 			 u8 *out, size_t outlen)
891c12
 {
891c12
+	cardos_data_t* priv;
891c12
 	int    r;
891c12
 	sc_context_t *ctx;
891c12
 	int do_rsa_pure_sig = 0;
891c12
@@ -895,8 +1088,21 @@ cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen,
891c12
 
891c12
 	assert(card != NULL && data != NULL && out != NULL);
891c12
 	ctx = card->ctx;
891c12
+	priv = (cardos_data_t*)card->drv_data;
891c12
 	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
891c12
 
891c12
+	/* sec_env has algorithm_flags set from sc_get_encoding_flags sec_flags
891c12
+	 * If flags are set correctly we don't need to test anything 
891c12
+	 * TODO this assumes RSA is  PSS, PKCS1 or RAW and we are passing 
891c12
+	 * the correct data. Should work for ECDSA too.    
891c12
+	 * use for V5 cards and TODO should for older cards too
891c12
+	 */
891c12
+	if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) {
891c12
+
891c12
+		r = do_compute_signature(card, data, datalen, out, outlen);
891c12
+		LOG_FUNC_RETURN(ctx, r);
891c12
+	}
891c12
+
891c12
 	/* There are two ways to create a signature, depending on the way,
891c12
 	 * the key was created: RSA_SIG and RSA_PURE_SIG.
891c12
 	 * We can use the following reasoning, to determine the correct operation:
891c12
@@ -913,8 +1119,8 @@ cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen,
891c12
 	 */
891c12
 
891c12
 	/* check the the algorithmIDs from the AlgorithmInfo */
891c12
-	for (i = 0; i < algorithm_ids_in_tokeninfo_count; ++i) {
891c12
-		unsigned int id = algorithm_ids_in_tokeninfo[i];
891c12
+	for (i = 0; i < priv->algorithm_ids_in_tokeninfo_count; ++i) {
891c12
+		unsigned int id = priv->algorithm_ids_in_tokeninfo[i];
891c12
 		if (id == 0x86 || id == 0x88) {
891c12
 			do_rsa_sig = 1;
891c12
 		} else if (id == 0x8C || id == 0x8A) {
891c12
@@ -985,10 +1191,41 @@ cardos_decipher(struct sc_card *card,
891c12
 		const u8 * crgram, size_t crgram_len,
891c12
 		u8 * out, size_t outlen)
891c12
 {
891c12
+	cardos_data_t* priv = (cardos_data_t*)card->drv_data;
891c12
 	int r;
891c12
 	size_t card_max_send_size = card->max_send_size;
891c12
 	size_t reader_max_send_size = card->reader->max_send_size;
891c12
 
891c12
+	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
891c12
+
891c12
+	/* 5.3 supports command chaining. Others may also
891c12
+	 * card_max_send_size for 5.3 is already based on reader max_send_size */
891c12
+
891c12
+	if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) {
891c12
+
891c12
+		r = iso_ops->decipher(card, crgram, crgram_len, out, outlen);
891c12
+		/*
891c12
+		 * 5.3 supports RAW as well as PKCS1 and PSS
891c12
+		 * decription may strip padding if card supports it
891c12
+		 * with cards that support RAW, it always appears to 
891c12
+		 * drop first 00 that is start of padding.
891c12
+		 */
891c12
+
891c12
+		if (r > 0 && priv->sec_env->algorithm_flags & SC_ALGORITHM_RSA_RAW) {
891c12
+			size_t rsize = r;
891c12
+			/* RSA RAW crgram_len == modlen */
891c12
+			/* removed padding is always > 1 byte */
891c12
+			/* add back missing leading zero if card dropped it */
891c12
+			if (rsize == crgram_len - 1 && rsize < outlen) {
891c12
+				memmove(out+1, out, rsize);
891c12
+				out[0] =0x00;
891c12
+				r++;
891c12
+			}
891c12
+		}
891c12
+
891c12
+		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
891c12
+	}
891c12
+
891c12
 	if (sc_get_max_send_size(card) < crgram_len + 1) {
891c12
 		/* CardOS doesn't support chaining for PSO:DEC, so we just _hope_
891c12
 		 * that both, the reader and the card are able to send enough data.
891c12
@@ -1003,7 +1240,7 @@ cardos_decipher(struct sc_card *card,
891c12
 	card->max_send_size = card_max_send_size;
891c12
 	card->reader->max_send_size = reader_max_send_size;
891c12
 
891c12
-	return r;
891c12
+	SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
891c12
 }
891c12
 
891c12
 static int
891c12
@@ -1188,7 +1425,7 @@ static int cardos_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
891c12
 	LOG_TEST_RET(card->ctx, r,  "APDU transmit failed");
891c12
 	if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
891c12
 		return SC_ERROR_INTERNAL;
891c12
-	if ((apdu.resplen == 8) && (card->type == SC_CARD_TYPE_CARDOS_V5_0)) {
891c12
+	if ((apdu.resplen == 8) && (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3)) {
891c12
 		/* cache serial number */
891c12
 		memcpy(card->serialnr.value, rbuf, 8);
891c12
 		card->serialnr.len = 8;
891c12
@@ -1223,6 +1460,9 @@ cardos_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
891c12
 	case SC_CARDCTL_CARDOS_GENERATE_KEY:
891c12
 		return cardos_generate_key(card,
891c12
 			(struct sc_cardctl_cardos_genkey_info *) ptr);
891c12
+	case  SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS:
891c12
+		return cardos_pass_algo_flags(card,
891c12
+			(struct sc_cardctl_cardos_pass_algo_flags *) ptr);
891c12
 	case SC_CARDCTL_LIFECYCLE_GET:
891c12
 		return cardos_lifecycle_get(card, (int *) ptr);
891c12
 	case SC_CARDCTL_LIFECYCLE_SET:
891c12
@@ -1279,7 +1519,8 @@ cardos_logout(sc_card_t *card)
891c12
 		   	|| card->type == SC_CARD_TYPE_CARDOS_M4_2C
891c12
 		   	|| card->type == SC_CARD_TYPE_CARDOS_M4_3
891c12
 		   	|| card->type == SC_CARD_TYPE_CARDOS_M4_4
891c12
-			|| card->type == SC_CARD_TYPE_CARDOS_V5_0) {
891c12
+			|| card->type == SC_CARD_TYPE_CARDOS_V5_0
891c12
+			|| card->type == SC_CARD_TYPE_CARDOS_V5_3) {
891c12
 		sc_apdu_t apdu;
891c12
 		int       r;
891c12
 		sc_path_t path;
891c12
@@ -1309,6 +1550,7 @@ static struct sc_card_driver * sc_get_driver(void)
891c12
 	cardos_ops = *iso_ops;
891c12
 	cardos_ops.match_card = cardos_match_card;
891c12
 	cardos_ops.init = cardos_init;
891c12
+	cardos_ops.finish = cardos_finish;
891c12
 	cardos_ops.select_file = cardos_select_file;
891c12
 	cardos_ops.create_file = cardos_create_file;
891c12
 	cardos_ops.set_security_env = cardos_set_security_env;
891c12
diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h
891c12
index 0c68c4c625..10ddfa0545 100644
891c12
--- a/src/libopensc/cardctl.h
891c12
+++ b/src/libopensc/cardctl.h
891c12
@@ -83,6 +83,7 @@ enum {
891c12
 	SC_CARDCTL_CARDOS_PUT_DATA_OCI,
891c12
 	SC_CARDCTL_CARDOS_PUT_DATA_SECI,
891c12
 	SC_CARDCTL_CARDOS_GENERATE_KEY,
891c12
+	SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS,
891c12
 
891c12
 	/*
891c12
 	 * Starcos SPK 2.3 specific calls
891c12
@@ -350,6 +351,14 @@ typedef struct sc_cardctl_pkcs11_init_pin {
891c12
 	size_t			pin_len;
891c12
 } sc_cardctl_pkcs11_init_pin_t;
891c12
 
891c12
+/*
891c12
+ * Generic cardctl - card driver can examine token info
891c12
+ */
891c12
+struct sc_cardctl_parsed_token_info {
891c12
+	unsigned int flags;
891c12
+	struct sc_pkcs15_tokeninfo * tokeninfo;
891c12
+};
891c12
+
891c12
 /*
891c12
  * GPK lock file.
891c12
  * Parent DF of file must be selected.
891c12
@@ -419,6 +428,15 @@ struct sc_cardctl_cardos_genkey_info {
891c12
 	unsigned short	fid;
891c12
 };
891c12
 
891c12
+struct sc_cardctl_cardos_pass_algo_flags {
891c12
+	unsigned int pass;
891c12
+	unsigned long card_flags; /* from card->flags i.e. user set */
891c12
+	unsigned long used_flags; /* as set by default */
891c12
+	unsigned long new_flags; /* set in pkcs15-cardos.c */
891c12
+	unsigned long ec_flags; /* for EC keys */
891c12
+	unsigned long ext_flags; /* for EC keys */
891c12
+};
891c12
+
891c12
 /*
891c12
  * Incrypto34 PIN info
891c12
  */
891c12
diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h
891c12
index cb0501c3aa..8d58fb9368 100644
891c12
--- a/src/libopensc/cards.h
891c12
+++ b/src/libopensc/cards.h
891c12
@@ -47,6 +47,7 @@ enum {
891c12
 	SC_CARD_TYPE_CARDOS_CIE_V1, /* Italian CIE (eID) v1 */
891c12
 	SC_CARD_TYPE_CARDOS_M4_4,
891c12
 	SC_CARD_TYPE_CARDOS_V5_0,
891c12
+	SC_CARD_TYPE_CARDOS_V5_3,
891c12
 
891c12
 	/* flex/cyberflex drivers */
891c12
 	SC_CARD_TYPE_FLEX_BASE = 2000,
891c12
diff --git a/src/libopensc/pkcs15-cardos.c b/src/libopensc/pkcs15-cardos.c
891c12
new file mode 100644
891c12
index 0000000000..752631ce88
891c12
--- /dev/null
891c12
+++ b/src/libopensc/pkcs15-cardos.c
891c12
@@ -0,0 +1,177 @@
891c12
+/*
891c12
+ * PKCS15 emulation layer for CardOS cards
891c12
+ * Adapted from PKCS15 emulation layer for IAS/ECC card.
891c12
+ *
891c12
+ * Copyright (C) 2020, Douglas E. Engert <DEEngert@gmail.com>
891c12
+ * Copyright (C) 2016, Viktor Tarasov <viktor.tarasov@gmail.com>
891c12
+ * Copyright (C) 2004, Bud P. Bruegger <bud@comune.grosseto.it>
891c12
+ * Copyright (C) 2004, Antonino Iacono <ant_iacono@tin.it>
891c12
+ * Copyright (C) 2003, Olaf Kirch <okir@suse.de>
891c12
+ *
891c12
+ * This library is free software; you can redistribute it and/or
891c12
+ * modify it under the terms of the GNU Lesser General Public
891c12
+ * License as published by the Free Software Foundation; either
891c12
+ * version 2.1 of the License, or (at your option) any later version.
891c12
+ *
891c12
+ * This library is distributed in the hope that it will be useful,
891c12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
891c12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
891c12
+ * Lesser General Public License for more details.
891c12
+ *
891c12
+ * You should have received a copy of the GNU Lesser General Public
891c12
+ * License along with this library; if not, write to the Free Software
891c12
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
891c12
+ */
891c12
+
891c12
+#if HAVE_CONFIG_H
891c12
+#include "config.h"
891c12
+#endif
891c12
+
891c12
+#include <stdlib.h>
891c12
+#include <string.h>
891c12
+#include <stdio.h>
891c12
+
891c12
+#include "internal.h"
891c12
+#include "pkcs15.h"
891c12
+
891c12
+
891c12
+/*
891c12
+ * Called after sc_pkcs15_bind_internal
891c12
+ * Create new flags based on supported_algos.
891c12
+ */
891c12
+static int cardos_fix_token_info(sc_pkcs15_card_t *p15card)
891c12
+{
891c12
+	sc_card_t *card;
891c12
+	struct sc_supported_algo_info (*saa)[SC_MAX_SUPPORTED_ALGORITHMS];
891c12
+	struct sc_supported_algo_info *sa;
891c12
+	struct sc_cardctl_cardos_pass_algo_flags *passed = NULL;
891c12
+	int r = 0;
891c12
+	int i;
891c12
+
891c12
+	card = p15card->card;
891c12
+
891c12
+	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
891c12
+
891c12
+	passed = calloc(1, sizeof(struct sc_cardctl_cardos_pass_algo_flags));
891c12
+	if (!passed)
891c12
+		LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY);
891c12
+
891c12
+	passed->pass = 1; /* get used_flags and card_flags from card */
891c12
+	r = sc_card_ctl(p15card->card, SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS, passed);
891c12
+	if (r < 0) {
891c12
+		free(passed);
891c12
+		LOG_FUNC_RETURN(card->ctx, r);
891c12
+	}
891c12
+
891c12
+	saa = &(p15card->tokeninfo->supported_algos);
891c12
+
891c12
+	sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Original Flags: 0x%8.8lx card->flags:0x%8.8lx", passed->used_flags, passed->card_flags);
891c12
+
891c12
+	if (passed->card_flags) { /* user forced the flags, use them */
891c12
+		passed->new_flags = passed->card_flags; /* from card_atr flags */
891c12
+	} else {
891c12
+
891c12
+		for (i = 0, sa = saa[0]; i < SC_MAX_SUPPORTED_ALGORITHMS; i++, sa++) {
891c12
+
891c12
+			if (sa->reference == 0 && sa->reference == 0 && sa->mechanism == 0
891c12
+					&& sa->operations == 0 && sa->algo_ref == 0)
891c12
+				break;
891c12
+
891c12
+			sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "supported_algos[%d] mechamism:0x%8.8x", i, sa->mechanism);
891c12
+			switch(sa->mechanism) {
891c12
+			case 0x01 :
891c12
+				/*
891c12
+				 * Card appears to use lower 4 bits of reference as key, and upper
891c12
+				 * 4 bits as mech for card.
891c12
+				 * Also has a bug if mechanism = 1 (CKM_RSA_PKCS1) and reference 0x10 
891c12
+				 * bit is set mechanism should be 3 (CKM_RSA_X_509) 
891c12
+				 * correct the mechanism in tokenInfo
891c12
+				 */
891c12
+				if (sa->reference & 0x10) {
891c12
+					sc_log(card->ctx, "Changeing mechanism to CKM_RSA_X_509 based on reference");
891c12
+					passed->new_flags |= SC_ALGORITHM_RSA_RAW
891c12
+						| SC_ALGORITHM_RSA_PAD_NONE;
891c12
+					sa->mechanism = 0x03;
891c12
+				} else
891c12
+				passed->new_flags |= SC_ALGORITHM_RSA_PAD_PKCS1;
891c12
+				break;
891c12
+			case 0x03 :
891c12
+				passed->new_flags |= SC_ALGORITHM_RSA_RAW
891c12
+					| SC_ALGORITHM_RSA_PAD_NONE;
891c12
+				break;
891c12
+			case 0x06 :
891c12
+				passed->new_flags |= SC_ALGORITHM_RSA_HASH_SHA1;
891c12
+				break;
891c12
+			case 0x1041:
891c12
+				passed->ec_flags |= SC_ALGORITHM_ECDSA_RAW;
891c12
+				/* no old_ec_flags */
891c12
+				/* TODO turn on sizes from  ec curves OIDS */
891c12
+				break;
891c12
+			default:
891c12
+				sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "UNKNOWN MECH: 0x%8.8x", sa->mechanism);
891c12
+			}
891c12
+
891c12
+			sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "New_flags 0x%8.8lx New_ec_flags: 0x%8.8lx",
891c12
+				passed->new_flags, passed->ec_flags);
891c12
+		}
891c12
+
891c12
+		if (passed->new_flags == 0) {
891c12
+			if (p15card->tokeninfo && p15card->tokeninfo->flags & SC_PKCS15_TOKEN_EID_COMPLIANT) {
891c12
+				sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "EID_COMPLIANT flag found");
891c12
+				passed->new_flags = (passed->used_flags & ~SC_ALGORITHM_SPECIFIC_FLAGS) | SC_ALGORITHM_RSA_PAD_PKCS1;
891c12
+			} else
891c12
+				passed->new_flags = passed->used_flags; /* from default cardos_init */
891c12
+		}
891c12
+	}
891c12
+
891c12
+	sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"Final New_flags 0x%8.8lx New_ec_flags: 0x%8.8lx", passed->new_flags, passed->ec_flags);
891c12
+
891c12
+	passed->pass = 2; /* tell card driver to use the new flags */
891c12
+	r = sc_card_ctl(p15card->card, SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS, passed);
891c12
+
891c12
+	free(passed);
891c12
+	LOG_FUNC_RETURN(card->ctx, r);
891c12
+}
891c12
+
891c12
+static int
891c12
+cardos_pkcs15emu_detect_card(sc_pkcs15_card_t *p15card)
891c12
+{
891c12
+	if (p15card->card->type <  SC_CARD_TYPE_CARDOS_BASE)
891c12
+		return SC_ERROR_WRONG_CARD;
891c12
+
891c12
+	if (p15card->card->type >= SC_CARD_TYPE_CARDOS_BASE + 1000)
891c12
+		return SC_ERROR_WRONG_CARD;
891c12
+
891c12
+	return SC_SUCCESS;
891c12
+}
891c12
+
891c12
+
891c12
+static int
891c12
+sc_pkcs15emu_cardos_init(struct sc_pkcs15_card *p15card, struct sc_aid *aid)
891c12
+{
891c12
+	sc_card_t *card = p15card->card;
891c12
+	int r;
891c12
+
891c12
+	LOG_FUNC_CALLED(card->ctx);
891c12
+
891c12
+	r = sc_pkcs15_bind_internal(p15card, aid);
891c12
+	LOG_TEST_RET(card->ctx, r, "sc_pkcs15_bind_internal failed");
891c12
+
891c12
+	/* If card has created algorithms, return  */
891c12
+	sc_log(card->ctx, " card->algorithms:%p card->algorithm_count:%d", card->algorithms, card->algorithm_count);
891c12
+	if (!card->algorithms && card->algorithm_count == 0) {
891c12
+		r = cardos_fix_token_info(p15card);
891c12
+	}
891c12
+
891c12
+	LOG_FUNC_RETURN(card->ctx, r);
891c12
+}
891c12
+
891c12
+
891c12
+int
891c12
+sc_pkcs15emu_cardos_init_ex(struct sc_pkcs15_card *p15card, struct sc_aid *aid)
891c12
+{
891c12
+	if (cardos_pkcs15emu_detect_card(p15card))
891c12
+		return SC_ERROR_WRONG_CARD;
891c12
+
891c12
+	return sc_pkcs15emu_cardos_init(p15card, aid);
891c12
+}
891c12
diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c
891c12
index aba6f52c0e..ecd06b13c6 100644
891c12
--- a/src/libopensc/pkcs15-syn.c
891c12
+++ b/src/libopensc/pkcs15-syn.c
891c12
@@ -60,6 +60,7 @@ struct sc_pkcs15_emulator_handler builtin_emulators[] = {
891c12
 	{ "coolkey",    sc_pkcs15emu_coolkey_init_ex	},
891c12
 	{ "din66291",   sc_pkcs15emu_din_66291_init_ex	},
891c12
 	{ "esteid2018", sc_pkcs15emu_esteid2018_init_ex	},
891c12
+	{ "cardos",     sc_pkcs15emu_cardos_init_ex	},
891c12
 
891c12
 	{ NULL, NULL }
891c12
 };
891c12
@@ -95,6 +96,8 @@ int sc_pkcs15_is_emulation_only(sc_card_t *card)
891c12
 		case SC_CARD_TYPE_PIV_II_NEO:
891c12
 		case SC_CARD_TYPE_PIV_II_YUBIKEY4:
891c12
 		case SC_CARD_TYPE_ESTEID_2018:
891c12
+		case SC_CARD_TYPE_CARDOS_V5_0:
891c12
+		case SC_CARD_TYPE_CARDOS_V5_3:
891c12
 
891c12
 			return 1;
891c12
 		default:
891c12
diff --git a/src/libopensc/pkcs15-syn.h b/src/libopensc/pkcs15-syn.h
891c12
index ccaf693ca4..a15e0d95cf 100644
891c12
--- a/src/libopensc/pkcs15-syn.h
891c12
+++ b/src/libopensc/pkcs15-syn.h
891c12
@@ -54,6 +54,7 @@ int sc_pkcs15emu_jpki_init_ex(sc_pkcs15_card_t *,	struct sc_aid *);
891c12
 int sc_pkcs15emu_coolkey_init_ex(sc_pkcs15_card_t *p15card,	struct sc_aid *);
891c12
 int sc_pkcs15emu_din_66291_init_ex(sc_pkcs15_card_t *p15card,	struct sc_aid *);
891c12
 int sc_pkcs15emu_idprime_init_ex(sc_pkcs15_card_t *p15card,	struct sc_aid *);
891c12
+int sc_pkcs15emu_cardos_init_ex(sc_pkcs15_card_t *p15card,	struct sc_aid *);
891c12
 
891c12
 struct sc_pkcs15_emulator_handler {
891c12
 	const char *name;
891c12