Blame SOURCES/opensc-0.20.0-cardos.patch

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