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