From 6b07ff64f6082ae44df9544129962a40a46fd548 Mon Sep 17 00:00:00 2001 From: jey Date: Sun, 3 Mar 2002 00:32:28 +0000 Subject: [PATCH] - Reworked PKCS #15 structure a bit (MANY THINGS WILL BREAK) - Added support for public key DFs (not tested yet) git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@251 c6295689-39f2-0310-b995-f0e70906c6a9 --- src/libopensc/Makefile.am | 4 +- src/libopensc/asn1.c | 34 ++--- src/libopensc/asn1.h | 2 +- src/libopensc/opensc-pkcs15.h | 100 +++++++------- src/libopensc/pkcs15-cert.c | 87 ++---------- src/libopensc/pkcs15-pin.c | 115 +--------------- src/libopensc/pkcs15-prkey.c | 107 +-------------- src/libopensc/pkcs15-pubkey.c | 154 +++++++++++++++++++++ src/libopensc/pkcs15.c | 159 +++++++++++++++++++++- src/libopensc/pkcs15.h | 100 +++++++------- src/libopensc/sc-asn1.h | 2 +- src/libopensc/sc.c | 2 +- src/tools/Makefile.am | 2 +- src/tools/cryptoflex-tool.c | 5 +- src/tools/pkcs15-crypt.c | 24 ++-- src/tools/pkcs15-tool.c | 244 ++++++++++++++++++++++++++++------ 16 files changed, 684 insertions(+), 457 deletions(-) create mode 100644 src/libopensc/pkcs15-pubkey.c diff --git a/src/libopensc/Makefile.am b/src/libopensc/Makefile.am index 3cb42348..508f4c50 100644 --- a/src/libopensc/Makefile.am +++ b/src/libopensc/Makefile.am @@ -19,8 +19,8 @@ bin_SCRIPTS = opensc-config lib_LTLIBRARIES = libopensc.la libopensc_la_SOURCES = asn1.c base64.c sec.c log.c sc.c card.c iso7816.c \ dir.c pkcs15.c pkcs15-cert.c pkcs15-pin.c \ - pkcs15-prkey.c pkcs15-sec.c pkcs15-cache.c \ - $(PCSC_SRC) \ + pkcs15-prkey.c pkcs15-pubkey.c pkcs15-sec.c \ + pkcs15-cache.c $(PCSC_SRC) \ card-setcos.c card-miocos.c card-flex.c card-gpk.c \ card-tcos.c card-emv.c card-default.c libopensc_la_LDFLAGS = -version-info 0:6:0 diff --git a/src/libopensc/asn1.c b/src/libopensc/asn1.c index 89d7181d..cdb40760 100644 --- a/src/libopensc/asn1.c +++ b/src/libopensc/asn1.c @@ -707,17 +707,17 @@ static int asn1_decode_p15_object(struct sc_context *ctx, const u8 *in, int depth) { int r; - struct sc_pkcs15_common_obj_attr *com_attr = obj->com_attr; + struct sc_pkcs15_object *p15_obj = obj->p15_obj; struct sc_asn1_entry asn1_c_attr[6], asn1_p15_obj[5]; - size_t flags_len = sizeof(com_attr->flags); - size_t label_len = sizeof(com_attr->label); + size_t flags_len = sizeof(p15_obj->flags); + size_t label_len = sizeof(p15_obj->label); sc_copy_asn1_entry(c_asn1_com_obj_attr, asn1_c_attr); sc_copy_asn1_entry(c_asn1_p15_obj, asn1_p15_obj); - sc_format_asn1_entry(asn1_c_attr + 0, com_attr->label, &label_len, 0); - sc_format_asn1_entry(asn1_c_attr + 1, &com_attr->flags, &flags_len, 0); - sc_format_asn1_entry(asn1_c_attr + 2, &com_attr->auth_id, NULL, 0); - sc_format_asn1_entry(asn1_c_attr + 3, &com_attr->user_consent, NULL, 0); + sc_format_asn1_entry(asn1_c_attr + 0, p15_obj->label, &label_len, 0); + sc_format_asn1_entry(asn1_c_attr + 1, &p15_obj->flags, &flags_len, 0); + sc_format_asn1_entry(asn1_c_attr + 2, &p15_obj->auth_id, NULL, 0); + sc_format_asn1_entry(asn1_c_attr + 3, &p15_obj->user_consent, NULL, 0); /* FIXME: encode accessControlRules */ sc_format_asn1_entry(asn1_c_attr + 4, NULL, NULL, 0); sc_format_asn1_entry(asn1_p15_obj + 0, asn1_c_attr, NULL, 0); @@ -733,23 +733,23 @@ static int asn1_encode_p15_object(struct sc_context *ctx, const struct sc_asn1_p u8 **buf, size_t *bufsize, int depth) { int r; - const struct sc_pkcs15_common_obj_attr *com_attr = obj->com_attr; + const struct sc_pkcs15_object *p15_obj = obj->p15_obj; struct sc_asn1_entry asn1_c_attr[6], asn1_p15_obj[5]; size_t flags_len; - size_t label_len = strlen(com_attr->label); + size_t label_len = strlen(p15_obj->label); sc_copy_asn1_entry(c_asn1_com_obj_attr, asn1_c_attr); sc_copy_asn1_entry(c_asn1_p15_obj, asn1_p15_obj); if (label_len != 0) - sc_format_asn1_entry(asn1_c_attr + 0, (void *) com_attr->label, &label_len, 1); - if (com_attr->flags) { - flags_len = _sc_count_bit_string_size(&com_attr->flags, sizeof(com_attr->flags)); - sc_format_asn1_entry(asn1_c_attr + 1, (void *) &com_attr->flags, &flags_len, 1); + sc_format_asn1_entry(asn1_c_attr + 0, (void *) p15_obj->label, &label_len, 1); + if (p15_obj->flags) { + flags_len = _sc_count_bit_string_size(&p15_obj->flags, sizeof(p15_obj->flags)); + sc_format_asn1_entry(asn1_c_attr + 1, (void *) &p15_obj->flags, &flags_len, 1); } - if (com_attr->auth_id.len) - sc_format_asn1_entry(asn1_c_attr + 2, (void *) &com_attr->auth_id, NULL, 1); - if (com_attr->user_consent) - sc_format_asn1_entry(asn1_c_attr + 3, (void *) &com_attr->user_consent, NULL, 1); + if (p15_obj->auth_id.len) + sc_format_asn1_entry(asn1_c_attr + 2, (void *) &p15_obj->auth_id, NULL, 1); + if (p15_obj->user_consent) + sc_format_asn1_entry(asn1_c_attr + 3, (void *) &p15_obj->user_consent, NULL, 1); /* FIXME: decode accessControlRules */ sc_format_asn1_entry(asn1_p15_obj + 0, asn1_c_attr, NULL, 1); sc_format_asn1_entry(asn1_p15_obj + 1, obj->asn1_class_attr, NULL, 1); diff --git a/src/libopensc/asn1.h b/src/libopensc/asn1.h index 77cbcb38..6dd9218e 100644 --- a/src/libopensc/asn1.h +++ b/src/libopensc/asn1.h @@ -34,7 +34,7 @@ struct sc_asn1_entry { }; struct sc_asn1_pkcs15_object { - struct sc_pkcs15_common_obj_attr *com_attr; + struct sc_pkcs15_object *p15_obj; struct sc_asn1_entry *asn1_class_attr; struct sc_asn1_entry *asn1_subclass_attr; struct sc_asn1_entry *asn1_type_attr; diff --git a/src/libopensc/opensc-pkcs15.h b/src/libopensc/opensc-pkcs15.h index 8bcf2110..e6adaf46 100644 --- a/src/libopensc/opensc-pkcs15.h +++ b/src/libopensc/opensc-pkcs15.h @@ -46,15 +46,6 @@ struct sc_pkcs15_id { #define SC_PKCS15_CO_FLAG_MODIFIABLE 0x00000002 #define SC_PKCS15_CO_FLAG_OBJECT_SEEN 0x80000000 /* for PKCS #11 module */ -struct sc_pkcs15_common_obj_attr { - char label[SC_PKCS15_MAX_LABEL_SIZE]; /* zero terminated */ - int flags; - struct sc_pkcs15_id auth_id; - - int user_consent; - /* FIXME: add accessControlRules */ -}; - #define SC_PKCS15_PIN_FLAG_CASE_SENSITIVE 0x0001 #define SC_PKCS15_PIN_FLAG_LOCAL 0x0002 #define SC_PKCS15_PIN_FLAG_CHANGE_DISABLED 0x0004 @@ -73,8 +64,6 @@ struct sc_pkcs15_common_obj_attr { #define SC_PKCS15_PIN_TYPE_UTF8 2 struct sc_pkcs15_pin_info { - struct sc_pkcs15_common_obj_attr com_attr; - struct sc_pkcs15_id auth_id; int reference; int flags, type; @@ -100,11 +89,11 @@ struct sc_pkcs15_algorithm_info { int algorithm, supported_operations; }; -struct sc_pkcs15_rsa_pubkey { +struct sc_pkcs15_pubkey_rsa { u8 *modulus; int modulus_len; unsigned int exponent; - + u8 *data; /* DER encoded raw key */ int data_len; }; @@ -113,15 +102,13 @@ struct sc_pkcs15_cert { int version; unsigned long serial; - struct sc_pkcs15_rsa_pubkey key; + struct sc_pkcs15_pubkey_rsa key; u8 *data; /* DER encoded raw cert */ int data_len; }; struct sc_pkcs15_cert_info { - struct sc_pkcs15_common_obj_attr com_attr; - - struct sc_pkcs15_id id; /* correlates to private RSA key id */ + struct sc_pkcs15_id id; /* correlates to private key id */ int authority; /* boolean */ /* identifiers [2] SEQUENCE OF CredentialIdentifier{{KeyIdentifiers}} */ struct sc_path path; @@ -145,8 +132,6 @@ struct sc_pkcs15_cert_info { #define SC_PKCS15_PRKEY_ACCESS_LOCAL 0x10 struct sc_pkcs15_prkey_info { - struct sc_pkcs15_common_obj_attr com_attr; - struct sc_pkcs15_id id; /* correlates to public certificate id */ unsigned int usage, access_flags; int native, key_reference; @@ -155,19 +140,44 @@ struct sc_pkcs15_prkey_info { struct sc_path path; }; -#define SC_PKCS15_TYPE_PRKEY_RSA 0x100 -#define SC_PKCS15_TYPE_PUBKEY_RSA 0x200 -#define SC_PKCS15_TYPE_CERT_X509 0x400 +struct sc_pkcs15_pubkey_info { + struct sc_pkcs15_id id; /* correlates to private key id */ + unsigned int usage, access_flags; + int native, key_reference; + int modulus_length; + + struct sc_path path; +}; + +#define SC_PKCS15_TYPE_CLASS_MASK 0xF00 + +#define SC_PKCS15_TYPE_PRKEY 0x100 +#define SC_PKCS15_TYPE_PRKEY_RSA 0x101 + +#define SC_PKCS15_TYPE_PUBKEY 0x200 +#define SC_PKCS15_TYPE_PUBKEY_RSA 0x201 + +#define SC_PKCS15_TYPE_CERT 0x400 +#define SC_PKCS15_TYPE_CERT_X509 0x401 #define SC_PKCS15_TYPE_CERT_SPKI 0x402 + #define SC_PKCS15_TYPE_DATA_OBJECT 0x500 -#define SC_PKCS15_TYPE_AUTH_PIN 0x600 +#define SC_PKCS15_TYPE_AUTH 0x600 +#define SC_PKCS15_TYPE_AUTH_PIN 0x601 struct sc_pkcs15_object { int type; + /* CommonObjectAttributes */ + char label[SC_PKCS15_MAX_LABEL_SIZE]; /* zero terminated */ + int flags; + struct sc_pkcs15_id auth_id; + + int user_consent; + + /* Object type specific data */ void *data; - - /* For linked list purposes */ - struct sc_pkcs15_object *next; + + struct sc_pkcs15_object *next; /* used only internally */ }; #define SC_PKCS15_PRKDF 0 @@ -187,6 +197,7 @@ struct sc_pkcs15_df { struct sc_file *file[SC_PKCS15_MAX_DFS]; struct sc_pkcs15_object *obj[SC_PKCS15_MAX_DFS]; int count, record_length, type; + int enumerated; }; #define SC_PKCS15_CARD_MAGIC 0x10203040 @@ -199,14 +210,6 @@ struct sc_pkcs15_card { char *serial_number, *manufacturer_id; unsigned long flags; struct sc_pkcs15_algorithm_info alg_info[1]; - /* FIXME: this could be done better with some C pre-processor - * magic */ - struct sc_pkcs15_cert_info cert_info[SC_PKCS15_MAX_CERTS]; - int cert_count; - struct sc_pkcs15_prkey_info prkey_info[SC_PKCS15_MAX_PRKEYS]; - int prkey_count; - struct sc_pkcs15_pin_info pin_info[SC_PKCS15_MAX_PINS]; - int pin_count; struct sc_file *file_app; struct sc_file *file_tokeninfo, *file_odf; @@ -223,7 +226,7 @@ struct sc_pkcs15_card { #define SC_PKCS15_CARD_FLAG_EID_COMPLIANT 0x08 /* sc_pkcs15_bind: Binds a card object to a PKCS #15 card object - * and initializes a new PKCS#15 card object. Will return + * and initializes a new PKCS #15 card object. Will return * SC_ERROR_PKCS15_APP_NOT_FOUND, if the card hasn't got a * valid PKCS #15 file structure. */ int sc_pkcs15_bind(struct sc_card *card, @@ -232,6 +235,13 @@ int sc_pkcs15_bind(struct sc_card *card, * memory allocations done on the card object. */ int sc_pkcs15_unbind(struct sc_pkcs15_card *card); +int sc_pkcs15_get_objects(struct sc_pkcs15_card *card, int type, + struct sc_pkcs15_object **ret, int ret_count); +int sc_pkcs15_get_objects_cond(struct sc_pkcs15_card *card, int type, + int (* func)(struct sc_pkcs15_object *, void *), + void *func_arg, + struct sc_pkcs15_object **ret, int ret_count); + struct sc_pkcs15_card * sc_pkcs15_card_new(); void sc_pkcs15_card_free(struct sc_pkcs15_card *p15card); @@ -250,14 +260,13 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card, void sc_pkcs15_print_card(const struct sc_pkcs15_card *card); void sc_pkcs15_print_cert_info(const struct sc_pkcs15_cert_info *cert); -int sc_pkcs15_enum_certificates(struct sc_pkcs15_card *card); int sc_pkcs15_read_certificate(struct sc_pkcs15_card *card, const struct sc_pkcs15_cert_info *info, struct sc_pkcs15_cert **cert); void sc_pkcs15_free_certificate(struct sc_pkcs15_cert *cert); int sc_pkcs15_find_cert_by_id(struct sc_pkcs15_card *card, const struct sc_pkcs15_id *id, - struct sc_pkcs15_cert_info **out); + struct sc_pkcs15_object **out); /* sc_pkcs15_create_cdf: Creates a new certificate DF on a card pointed * by . Information about the file, such as the file ID, is read * from . has to be NULL-terminated. */ @@ -267,23 +276,21 @@ int sc_pkcs15_create_cdf(struct sc_pkcs15_card *card, int sc_pkcs15_create(struct sc_pkcs15_card *p15card, struct sc_card *card); void sc_pkcs15_print_prkey_info(const struct sc_pkcs15_prkey_info *prkey); -int sc_pkcs15_enum_private_keys(struct sc_pkcs15_card *card); int sc_pkcs15_find_prkey_by_id(struct sc_pkcs15_card *card, const struct sc_pkcs15_id *id, - struct sc_pkcs15_prkey_info **out); + struct sc_pkcs15_object **out); -void sc_pkcs15_print_pin_info(const struct sc_pkcs15_pin_info *pin); -int sc_pkcs15_enum_pins(struct sc_pkcs15_card *card); +void sc_pkcs15_print_pin_info(const struct sc_pkcs15_pin_info *auth); int sc_pkcs15_verify_pin(struct sc_pkcs15_card *card, struct sc_pkcs15_pin_info *pin, - const u8 *pincode, int pinlen); + const u8 *pincode, size_t pinlen); int sc_pkcs15_change_pin(struct sc_pkcs15_card *card, struct sc_pkcs15_pin_info *pin, - const u8 *oldpincode, int oldpinlen, - const u8 *newpincode, int newpinlen); + const u8 *oldpincode, size_t oldpinlen, + const u8 *newpincode, size_t newpinlen); int sc_pkcs15_find_pin_by_auth_id(struct sc_pkcs15_card *card, const struct sc_pkcs15_id *id, - struct sc_pkcs15_pin_info **out); + struct sc_pkcs15_object **out); int sc_pkcs15_encode_dir(struct sc_context *ctx, struct sc_pkcs15_card *card, @@ -303,6 +310,9 @@ int sc_pkcs15_encode_cdf_entry(struct sc_context *ctx, int sc_pkcs15_encode_prkdf_entry(struct sc_context *ctx, const struct sc_pkcs15_object *obj, u8 **buf, size_t *bufsize); +int sc_pkcs15_encode_pukdf_entry(struct sc_context *ctx, + const struct sc_pkcs15_object *obj, u8 **buf, + size_t *bufsize); int sc_pkcs15_encode_aodf_entry(struct sc_context *ctx, const struct sc_pkcs15_object *obj, u8 **buf, size_t *bufsize); diff --git a/src/libopensc/pkcs15-cert.c b/src/libopensc/pkcs15-cert.c index f1c38405..09ce6fc0 100644 --- a/src/libopensc/pkcs15-cert.c +++ b/src/libopensc/pkcs15-cert.c @@ -29,9 +29,9 @@ #include #include -static int parse_rsa_pubkey(struct sc_context *ctx, struct sc_pkcs15_rsa_pubkey *key) +static int parse_pubkey_rsa(struct sc_context *ctx, struct sc_pkcs15_pubkey_rsa *key) { - struct sc_asn1_entry asn1_rsa_pubkey[] = { + struct sc_asn1_entry asn1_pubkey_rsa[] = { { "modulus", SC_ASN1_OCTET_STRING, ASN1_INTEGER, SC_ASN1_ALLOC, &key->modulus, &key->modulus_len }, { "publicExponent", SC_ASN1_INTEGER, ASN1_INTEGER, 0, &key->exponent }, { NULL } @@ -46,7 +46,7 @@ static int parse_rsa_pubkey(struct sc_context *ctx, struct sc_pkcs15_rsa_pubkey error(ctx, "RSA public key not found\n"); return SC_ERROR_INVALID_ASN1_OBJECT; } - r = sc_asn1_decode(ctx, asn1_rsa_pubkey, obj, objlen, NULL, NULL); + r = sc_asn1_decode(ctx, asn1_pubkey_rsa, obj, objlen, NULL, NULL); SC_TEST_RET(ctx, r, "ASN.1 parsing failed"); return 0; @@ -76,7 +76,7 @@ static int parse_algorithm_id(struct sc_context *ctx, void *arg, const u8 *obj, static int parse_x509_cert(struct sc_context *ctx, const u8 *buf, size_t buflen, struct sc_pkcs15_cert *cert) { int r; - struct sc_pkcs15_rsa_pubkey *key = &cert->key; + struct sc_pkcs15_pubkey_rsa *key = &cert->key; struct asn1_algorithm_id pk_alg, sig_alg; u8 *pk = NULL; size_t pklen = 0; @@ -123,7 +123,7 @@ static int parse_x509_cert(struct sc_context *ctx, const u8 *buf, size_t buflen, key->data = pk; key->data_len = pklen; /* FIXME: ignore the object id for now, and presume it's RSA */ - r = parse_rsa_pubkey(ctx, key); + r = parse_pubkey_rsa(ctx, key); if (r) { free(key->data); return SC_ERROR_INVALID_ASN1_OBJECT; @@ -219,7 +219,7 @@ int sc_pkcs15_decode_cdf_entry(struct sc_pkcs15_card *p15card, struct sc_asn1_entry asn1_cred_ident[3], asn1_com_cert_attr[4], asn1_x509_cert_attr[2], asn1_type_cert_attr[2], asn1_cert[2]; - struct sc_asn1_pkcs15_object cert_obj = { &info.com_attr, asn1_com_cert_attr, NULL, + struct sc_asn1_pkcs15_object cert_obj = { obj, asn1_com_cert_attr, NULL, asn1_type_cert_attr }; u8 id_value[128]; int id_type, id_value_len = sizeof(id_value); @@ -254,12 +254,6 @@ int sc_pkcs15_decode_cdf_entry(struct sc_pkcs15_card *p15card, SC_FUNC_RETURN(ctx, 0, SC_ERROR_OUT_OF_MEMORY); memcpy(obj->data, &info, sizeof(info)); - /* Legacy code */ - if (p15card->cert_count >= SC_PKCS15_MAX_CERTS) - return SC_ERROR_TOO_MANY_OBJECTS; - p15card->cert_info[p15card->cert_count] = info; - p15card->cert_count++; - return 0; } @@ -272,8 +266,9 @@ int sc_pkcs15_encode_cdf_entry(struct sc_context *ctx, asn1_cert[2]; struct sc_pkcs15_cert_info *infop = (struct sc_pkcs15_cert_info *) obj->data; - const struct sc_asn1_pkcs15_object cert_obj = { &infop->com_attr, asn1_com_cert_attr, NULL, - asn1_type_cert_attr }; + const struct sc_asn1_pkcs15_object cert_obj = { (struct sc_pkcs15_object *) obj, + asn1_com_cert_attr, NULL, + asn1_type_cert_attr }; int r; sc_copy_asn1_entry(c_asn1_cred_ident, asn1_cred_ident); @@ -294,51 +289,6 @@ int sc_pkcs15_encode_cdf_entry(struct sc_context *ctx, return r; } -void sc_pkcs15_print_cert_info(const struct sc_pkcs15_cert_info *cert) -{ - int i; - printf("X.509 Certificate [%s]\n", cert->com_attr.label); - printf("\tFlags : %d\n", cert->com_attr.flags); - printf("\tAuthority: %s\n", cert->authority ? "yes" : "no"); - printf("\tPath : "); - for (i = 0; i < cert->path.len; i++) - printf("%02X", cert->path.value[i]); - printf("\n"); - printf("\tID : "); - sc_pkcs15_print_id(&cert->id); - printf("\n"); -} - -int sc_pkcs15_enum_certificates(struct sc_pkcs15_card *p15card) -{ - int r = 0, i, j; - const int df_types[] = { - SC_PKCS15_CDF, SC_PKCS15_CDF_TRUSTED, SC_PKCS15_CDF_USEFUL - }; - const int nr_types = sizeof(df_types)/sizeof(df_types[0]); - - assert(p15card != NULL); - - if (p15card->cert_count) - return p15card->cert_count; /* already enumerated */ - r = sc_lock(p15card->card); - SC_TEST_RET(p15card->card->ctx, r, "sc_lock() failed"); - for (j = 0; j < nr_types; j++) { - int type = df_types[j]; - for (i = 0; i < p15card->df[type].count; i++) { - r = sc_pkcs15_parse_df(p15card, &p15card->df[type], i); - if (r != 0) - break; - } - if (r != 0) - break; - } - sc_unlock(p15card->card); - if (r != 0) - return r; - return p15card->cert_count; -} - void sc_pkcs15_free_certificate(struct sc_pkcs15_cert *cert) { assert(cert != NULL); @@ -348,22 +298,3 @@ void sc_pkcs15_free_certificate(struct sc_pkcs15_cert *cert) free(cert->data); free(cert); } - -int sc_pkcs15_find_cert_by_id(struct sc_pkcs15_card *card, - const struct sc_pkcs15_id *id, - struct sc_pkcs15_cert_info **cert_out) -{ - int r, i; - - r = sc_pkcs15_enum_certificates(card); - if (r < 0) - return r; - for (i = 0; i < card->cert_count; i++) { - struct sc_pkcs15_cert_info *cert = &card->cert_info[i]; - if (sc_pkcs15_compare_id(&cert->id, id) == 1) { - *cert_out = cert; - return 0; - } - } - return SC_ERROR_OBJECT_NOT_FOUND; -} diff --git a/src/libopensc/pkcs15-pin.c b/src/libopensc/pkcs15-pin.c index e81f478b..bc908959 100644 --- a/src/libopensc/pkcs15-pin.c +++ b/src/libopensc/pkcs15-pin.c @@ -63,8 +63,7 @@ int sc_pkcs15_decode_aodf_entry(struct sc_pkcs15_card *p15card, int padchar_len = 1; struct sc_asn1_entry asn1_com_ao_attr[2], asn1_pin_attr[10], asn1_type_pin_attr[2]; struct sc_asn1_entry asn1_pin[2]; - struct sc_asn1_pkcs15_object pin_obj = { &info.com_attr, asn1_com_ao_attr, NULL, - asn1_type_pin_attr }; + struct sc_asn1_pkcs15_object pin_obj = { obj, asn1_com_ao_attr, NULL, asn1_type_pin_attr }; sc_copy_asn1_entry(c_asn1_pin, asn1_pin); sc_copy_asn1_entry(c_asn1_type_pin_attr, asn1_type_pin_attr); sc_copy_asn1_entry(c_asn1_pin_attr, asn1_pin_attr); @@ -99,12 +98,6 @@ int sc_pkcs15_decode_aodf_entry(struct sc_pkcs15_card *p15card, SC_FUNC_RETURN(ctx, 0, SC_ERROR_OUT_OF_MEMORY); memcpy(obj->data, &info, sizeof(info)); - /* Legacy code */ - if (p15card->pin_count >= SC_PKCS15_MAX_PINS) - return SC_ERROR_TOO_MANY_OBJECTS; - p15card->pin_info[p15card->pin_count] = info; - p15card->pin_count++; - return 0; } @@ -116,8 +109,9 @@ int sc_pkcs15_encode_aodf_entry(struct sc_context *ctx, struct sc_asn1_entry asn1_pin[2]; struct sc_pkcs15_pin_info *pin = (struct sc_pkcs15_pin_info *) obj->data; - struct sc_asn1_pkcs15_object pin_obj = { &pin->com_attr, asn1_com_ao_attr, NULL, - asn1_type_pin_attr }; + struct sc_asn1_pkcs15_object pin_obj = { (struct sc_pkcs15_object *) obj, + asn1_com_ao_attr, NULL, + asn1_type_pin_attr }; int r; int flags_len = sizeof(pin->flags); int padchar_len = 1; @@ -149,85 +143,9 @@ int sc_pkcs15_encode_aodf_entry(struct sc_context *ctx, return r; } -void sc_pkcs15_print_pin_info(const struct sc_pkcs15_pin_info *pin) -{ - const char *pin_flags[] = { - "case-sensitive", "local", "change-disabled", - "unblock-disabled", "initialized", "needs-padding", - "unblockingPin", "soPin", "disable_allowed", - "integrity-protected", "confidentiality-protected", - "exchangeRefData" - }; - const int pf_count = sizeof(pin_flags)/sizeof(pin_flags[0]); - char path[SC_MAX_PATH_SIZE * 2 + 1]; - int i; - char *p; - - p = path; - *p = 0; - for (i = 0; i < pin->path.len; i++) { - sprintf(p, "%02X", pin->path.value[i]); - p += 2; - } - printf("PIN [%s]\n", pin->com_attr.label); - printf("\tCom. Flags: 0x%X\n", pin->com_attr.flags); - printf("\tAuth ID : "); - sc_pkcs15_print_id(&pin->auth_id); - printf("\n"); - printf("\tFlags : [0x%02X]", pin->flags); - for (i = 0; i < pf_count; i++) - if (pin->flags & (1 << i)) { - printf(", %s", pin_flags[i]); - } - printf("\n"); - printf("\tLength : %d..%d\n", pin->min_length, pin->stored_length); - printf("\tPad char : 0x%02X\n", pin->pad_char); - printf("\tReference : %d\n", pin->reference); - printf("\tType : %d\n", pin->type); - printf("\tPath : %s\n", path); -} - -int sc_pkcs15_enum_pins(struct sc_pkcs15_card *p15card) -{ - int r, i, j; - const int df_types[] = { - SC_PKCS15_AODF - }; - const int nr_types = sizeof(df_types)/sizeof(df_types[0]); - - assert(p15card != NULL); - SC_FUNC_CALLED(p15card->card->ctx, 1); - if (p15card->pin_count) { - for (i = 0; i < p15card->pin_count; i++) { - if (p15card->pin_info[i].magic != SC_PKCS15_PIN_MAGIC) - break; - } - if (i == p15card->pin_count) - return i; /* Already enumerated */ - } - p15card->pin_count = 0; - r = sc_lock(p15card->card); - SC_TEST_RET(p15card->card->ctx, r, "sc_lock() failed"); - for (j = 0; r == 0 && j < nr_types; j++) { - int type = df_types[j]; - - for (i = 0; r == 0 && i < p15card->df[type].count; i++) { - r = sc_pkcs15_parse_df(p15card, &p15card->df[type], i); - if (r != 0) - break; - } - if (r != 0) - break; - } - sc_unlock(p15card->card); - if (r != 0) - return r; - return p15card->pin_count; -} - int sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_pin_info *pin, - const u8 *pincode, int pinlen) + const u8 *pincode, size_t pinlen) { int r; struct sc_card *card; @@ -260,8 +178,8 @@ int sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card, int sc_pkcs15_change_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_pin_info *pin, - const u8 *oldpin, int oldpinlen, - const u8 *newpin, int newpinlen) + const u8 *oldpin, size_t oldpinlen, + const u8 *newpin, size_t newpinlen) { int r; struct sc_card *card; @@ -293,22 +211,3 @@ int sc_pkcs15_change_pin(struct sc_pkcs15_card *p15card, sc_unlock(card); return r; } - -int sc_pkcs15_find_pin_by_auth_id(struct sc_pkcs15_card *card, - const struct sc_pkcs15_id *id, - struct sc_pkcs15_pin_info **pin_out) -{ - int r, i; - - r = sc_pkcs15_enum_pins(card); - if (r < 0) - return r; - for (i = 0; i < card->pin_count; i++) { - struct sc_pkcs15_pin_info *pin = &card->pin_info[i]; - if (sc_pkcs15_compare_id(&pin->auth_id, id) == 1) { - *pin_out = pin; - return 0; - } - } - return SC_ERROR_OBJECT_NOT_FOUND; -} diff --git a/src/libopensc/pkcs15-prkey.c b/src/libopensc/pkcs15-prkey.c index 948314ee..a813ce1a 100644 --- a/src/libopensc/pkcs15-prkey.c +++ b/src/libopensc/pkcs15-prkey.c @@ -27,50 +27,6 @@ #include #include -void sc_pkcs15_print_prkey_info(const struct sc_pkcs15_prkey_info *prkey) -{ - int i; - const char *usages[] = { - "encrypt", "decrypt", "sign", "signRecover", - "wrap", "unwrap", "verify", "verifyRecover", - "derive", "nonRepudiation" - }; - const int usage_count = sizeof(usages)/sizeof(usages[0]); - const char *access_flags[] = { - "sensitive", "extract", "alwaysSensitive", - "neverExtract", "local" - }; - const int af_count = sizeof(access_flags)/sizeof(access_flags[0]); - - printf("Private RSA Key [%s]\n", prkey->com_attr.label); - printf("\tCom. Flags : %X\n", prkey->com_attr.flags); - printf("\tUsage : [0x%X]", prkey->usage); - for (i = 0; i < usage_count; i++) - if (prkey->usage & (1 << i)) { - printf(", %s", usages[i]); - } - printf("\n"); - printf("\tAccess Flags: [0x%X]", prkey->access_flags); - for (i = 0; i < af_count; i++) - if (prkey->access_flags & (1 << i)) { - printf(", %s", access_flags[i]); - } - printf("\n"); - printf("\tModLength : %d\n", prkey->modulus_length); - printf("\tKey ref : %d\n", prkey->key_reference); - printf("\tNative : %s\n", prkey->native ? "yes" : "no"); - printf("\tPath : "); - for (i = 0; i < prkey->path.len; i++) - printf("%02X", prkey->path.value[i]); - printf("\n"); - printf("\tAuth ID : "); - sc_pkcs15_print_id(&prkey->com_attr.auth_id); - printf("\n"); - printf("\tID : "); - sc_pkcs15_print_id(&prkey->id); - printf("\n"); -} - static const struct sc_asn1_entry c_asn1_com_key_attr[] = { { "iD", SC_ASN1_PKCS15_ID, ASN1_OCTET_STRING, 0, NULL }, { "usage", SC_ASN1_BIT_STRING, ASN1_BIT_STRING, 0, NULL }, @@ -114,8 +70,8 @@ int sc_pkcs15_decode_prkdf_entry(struct sc_pkcs15_card *p15card, struct sc_asn1_entry asn1_com_key_attr[6], asn1_com_prkey_attr[1]; struct sc_asn1_entry asn1_rsakey_attr[4], asn1_type_attr[2]; struct sc_asn1_entry asn1_prkey[2]; - struct sc_asn1_pkcs15_object prkey_obj = { &info.com_attr, asn1_com_key_attr, - asn1_com_prkey_attr, asn1_type_attr }; + struct sc_asn1_pkcs15_object prkey_obj = { obj, asn1_com_key_attr, + asn1_com_prkey_attr, asn1_type_attr }; sc_copy_asn1_entry(c_asn1_prkey, asn1_prkey); sc_copy_asn1_entry(c_asn1_type_attr, asn1_type_attr); @@ -151,12 +107,6 @@ int sc_pkcs15_decode_prkdf_entry(struct sc_pkcs15_card *p15card, SC_FUNC_RETURN(ctx, 0, SC_ERROR_OUT_OF_MEMORY); memcpy(obj->data, &info, sizeof(info)); - /* Legacy code */ - if (p15card->prkey_count >= SC_PKCS15_MAX_PRKEYS) - return SC_ERROR_TOO_MANY_OBJECTS; - p15card->prkey_info[p15card->prkey_count] = info; - p15card->prkey_count++; - return 0; } int sc_pkcs15_encode_prkdf_entry(struct sc_context *ctx, @@ -168,7 +118,8 @@ int sc_pkcs15_encode_prkdf_entry(struct sc_context *ctx, struct sc_asn1_entry asn1_prkey[2]; struct sc_pkcs15_prkey_info *prkey = (struct sc_pkcs15_prkey_info *) obj->data; - struct sc_asn1_pkcs15_object prkey_obj = { &prkey->com_attr, asn1_com_key_attr, + struct sc_asn1_pkcs15_object prkey_obj = { (struct sc_pkcs15_object *) obj, + asn1_com_key_attr, asn1_com_prkey_attr, asn1_type_attr }; int r; int af_len, usage_len; @@ -201,53 +152,3 @@ int sc_pkcs15_encode_prkdf_entry(struct sc_context *ctx, return r; } - -int sc_pkcs15_enum_private_keys(struct sc_pkcs15_card *p15card) -{ - int r, i, j; - const int df_types[] = { - SC_PKCS15_PRKDF - }; - const int nr_types = sizeof(df_types)/sizeof(df_types[0]); - - assert(p15card != NULL); - SC_FUNC_CALLED(p15card->card->ctx, 1); - if (p15card->prkey_count) - return p15card->prkey_count; /* already enumerated */ - r = sc_lock(p15card->card); - SC_TEST_RET(p15card->card->ctx, r, "sc_lock() failed"); - for (j = 0; r == 0 && j < nr_types; j++) { - int type = df_types[j]; - - for (i = 0; r == 0 && i < p15card->df[type].count; i++) { - r = sc_pkcs15_parse_df(p15card, &p15card->df[type], i); - if (r != 0) - break; - } - if (r != 0) - break; - } - sc_unlock(p15card->card); - if (r != 0) - return r; - return p15card->prkey_count; -} - -int sc_pkcs15_find_prkey_by_id(struct sc_pkcs15_card *card, - const struct sc_pkcs15_id *id, - struct sc_pkcs15_prkey_info **key_out) -{ - int r, i; - - r = sc_pkcs15_enum_private_keys(card); - if (r < 0) - return r; - for (i = 0; i < card->prkey_count; i++) { - struct sc_pkcs15_prkey_info *key = &card->prkey_info[i]; - if (sc_pkcs15_compare_id(&key->id, id) == 1) { - *key_out = key; - return 0; - } - } - return SC_ERROR_OBJECT_NOT_FOUND; -} diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c new file mode 100644 index 00000000..20f80250 --- /dev/null +++ b/src/libopensc/pkcs15-pubkey.c @@ -0,0 +1,154 @@ +/* + * pkcs15-pubkey.c: PKCS #15 public key functions + * + * Copyright (C) 2002 Juha Yrjölä + * + * 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 + */ + +#include "sc-internal.h" +#include "opensc-pkcs15.h" +#include "sc-asn1.h" +#include "sc-log.h" +#include +#include +#include +#include + +static const struct sc_asn1_entry c_asn1_com_key_attr[] = { + { "iD", SC_ASN1_PKCS15_ID, ASN1_OCTET_STRING, 0, NULL }, + { "usage", SC_ASN1_BIT_STRING, ASN1_BIT_STRING, 0, NULL }, + { "native", SC_ASN1_BOOLEAN, ASN1_BOOLEAN, SC_ASN1_OPTIONAL, NULL }, + { "accessFlags", SC_ASN1_BIT_STRING, ASN1_BIT_STRING, SC_ASN1_OPTIONAL, NULL }, + { "keyReference",SC_ASN1_INTEGER, ASN1_INTEGER, SC_ASN1_OPTIONAL, NULL }, + { NULL } +}; + +static const struct sc_asn1_entry c_asn1_com_pubkey_attr[] = { + /* FIXME */ + { NULL } +}; + +static const struct sc_asn1_entry c_asn1_rsakey_attr[] = { + { "value", SC_ASN1_PATH, ASN1_SEQUENCE | SC_ASN1_CONS, 0, NULL }, + { "modulusLength", SC_ASN1_INTEGER, ASN1_INTEGER, 0, NULL }, + { "keyInfo", SC_ASN1_INTEGER, ASN1_INTEGER, SC_ASN1_OPTIONAL, NULL }, + { NULL } +}; + +static const struct sc_asn1_entry c_asn1_type_attr[] = { + { "privateRSAKeyAttributes", SC_ASN1_STRUCT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, NULL }, + { NULL } +}; + +static const struct sc_asn1_entry c_asn1_pubkey[] = { + { "publicRSAKey", SC_ASN1_PKCS15_OBJECT, ASN1_SEQUENCE | SC_ASN1_CONS, 0, NULL }, + { NULL } +}; + +int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card, + struct sc_pkcs15_object *obj, + const u8 ** buf, size_t *buflen) +{ + struct sc_context *ctx = p15card->card->ctx; + struct sc_pkcs15_pubkey_info info; + int r; + int usage_len = sizeof(info.usage); + int af_len = sizeof(info.access_flags); + struct sc_asn1_entry asn1_com_key_attr[6], asn1_com_pubkey_attr[1]; + struct sc_asn1_entry asn1_rsakey_attr[4], asn1_type_attr[2]; + struct sc_asn1_entry asn1_pubkey[2]; + struct sc_asn1_pkcs15_object pubkey_obj = { obj, asn1_com_key_attr, + asn1_com_pubkey_attr, asn1_type_attr }; + + sc_copy_asn1_entry(c_asn1_pubkey, asn1_pubkey); + sc_copy_asn1_entry(c_asn1_type_attr, asn1_type_attr); + sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr); + sc_copy_asn1_entry(c_asn1_com_pubkey_attr, asn1_com_pubkey_attr); + sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr); + + sc_format_asn1_entry(asn1_pubkey + 0, &pubkey_obj, NULL, 0); + + sc_format_asn1_entry(asn1_type_attr + 0, asn1_rsakey_attr, NULL, 0); + + sc_format_asn1_entry(asn1_rsakey_attr + 0, &info.path, NULL, 0); + sc_format_asn1_entry(asn1_rsakey_attr + 1, &info.modulus_length, NULL, 0); + + sc_format_asn1_entry(asn1_com_key_attr + 0, &info.id, NULL, 0); + sc_format_asn1_entry(asn1_com_key_attr + 1, &info.usage, &usage_len, 0); + sc_format_asn1_entry(asn1_com_key_attr + 2, &info.native, NULL, 0); + sc_format_asn1_entry(asn1_com_key_attr + 3, &info.access_flags, &af_len, 0); + sc_format_asn1_entry(asn1_com_key_attr + 4, &info.key_reference, NULL, 0); + + /* Fill in defaults */ + memset(&info, 0, sizeof(info)); + info.key_reference = -1; + info.native = 1; + + r = sc_asn1_decode(ctx, asn1_pubkey, *buf, *buflen, buf, buflen); + if (r == SC_ERROR_ASN1_END_OF_CONTENTS) + return r; + SC_TEST_RET(ctx, r, "ASN.1 decoding failed"); + obj->type = SC_PKCS15_TYPE_PUBKEY_RSA; + obj->data = malloc(sizeof(info)); + if (obj->data == NULL) + SC_FUNC_RETURN(ctx, 0, SC_ERROR_OUT_OF_MEMORY); + memcpy(obj->data, &info, sizeof(info)); + + return 0; +} +int sc_pkcs15_encode_pukdf_entry(struct sc_context *ctx, + const struct sc_pkcs15_object *obj, + u8 **buf, size_t *buflen) +{ + struct sc_asn1_entry asn1_com_key_attr[6], asn1_com_pubkey_attr[1]; + struct sc_asn1_entry asn1_rsakey_attr[4], asn1_type_attr[2]; + struct sc_asn1_entry asn1_pubkey[2]; + struct sc_pkcs15_pubkey_info *pubkey = + (struct sc_pkcs15_pubkey_info *) obj->data; + struct sc_asn1_pkcs15_object pubkey_obj = { (struct sc_pkcs15_object *) obj, + asn1_com_key_attr, + asn1_com_pubkey_attr, asn1_type_attr }; + int r; + int af_len, usage_len; + + sc_copy_asn1_entry(c_asn1_pubkey, asn1_pubkey); + sc_copy_asn1_entry(c_asn1_type_attr, asn1_type_attr); + sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr); + sc_copy_asn1_entry(c_asn1_com_pubkey_attr, asn1_com_pubkey_attr); + sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr); + + sc_format_asn1_entry(asn1_pubkey + 0, &pubkey_obj, NULL, 1); + + sc_format_asn1_entry(asn1_type_attr + 0, asn1_rsakey_attr, NULL, 1); + + sc_format_asn1_entry(asn1_rsakey_attr + 0, &pubkey->path, NULL, 1); + sc_format_asn1_entry(asn1_rsakey_attr + 1, &pubkey->modulus_length, NULL, 1); + + sc_format_asn1_entry(asn1_com_key_attr + 0, &pubkey->id, NULL, 1); + usage_len = _sc_count_bit_string_size(&pubkey->usage, sizeof(pubkey->usage)); + sc_format_asn1_entry(asn1_com_key_attr + 1, &pubkey->usage, &usage_len, 1); + if (pubkey->native == 0) + sc_format_asn1_entry(asn1_com_key_attr + 2, &pubkey->native, NULL, 1); + if (pubkey->access_flags) { + af_len = _sc_count_bit_string_size(&pubkey->access_flags, sizeof(pubkey->access_flags)); + sc_format_asn1_entry(asn1_com_key_attr + 3, &pubkey->access_flags, &af_len, 1); + } + if (pubkey->key_reference >= 0) + sc_format_asn1_entry(asn1_com_key_attr + 4, &pubkey->key_reference, NULL, 1); + r = sc_asn1_encode(ctx, asn1_pubkey, buf, buflen); + + return r; +} diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index 8621bcc6..a93780c6 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -305,8 +305,11 @@ int sc_pkcs15_create_dir(struct sc_pkcs15_card *p15card, struct sc_card *card) static const struct sc_asn1_entry c_asn1_odf[] = { { "privateKeys", SC_ASN1_STRUCT, SC_ASN1_CTX | 0 | SC_ASN1_CONS, 0, NULL }, + { "publicKeys", SC_ASN1_STRUCT, SC_ASN1_CTX | 1 | SC_ASN1_CONS, 0, NULL }, + { "trustedPublicKeys", SC_ASN1_STRUCT, SC_ASN1_CTX | 2 | SC_ASN1_CONS, 0, NULL }, { "certificates", SC_ASN1_STRUCT, SC_ASN1_CTX | 4 | SC_ASN1_CONS, 0, NULL }, { "trustedCertificates", SC_ASN1_STRUCT, SC_ASN1_CTX | 5 | SC_ASN1_CONS, 0, NULL }, + { "usefulCertificates", SC_ASN1_STRUCT, SC_ASN1_CTX | 6 | SC_ASN1_CONS, 0, NULL }, { "dataObjects", SC_ASN1_STRUCT, SC_ASN1_CTX | 7 | SC_ASN1_CONS, 0, NULL }, { "authObjects", SC_ASN1_STRUCT, SC_ASN1_CTX | 8 | SC_ASN1_CONS, 0, NULL }, { NULL } @@ -314,8 +317,11 @@ static const struct sc_asn1_entry c_asn1_odf[] = { static const int odf_indexes[] = { SC_PKCS15_PRKDF, + SC_PKCS15_PUKDF, + SC_PKCS15_PUKDF_TRUSTED, SC_PKCS15_CDF, SC_PKCS15_CDF_TRUSTED, + SC_PKCS15_CDF_USEFUL, SC_PKCS15_DODF, SC_PKCS15_AODF, }; @@ -330,7 +336,7 @@ static int parse_odf(const u8 * buf, int buflen, struct sc_pkcs15_card *card) { "path", SC_ASN1_PATH, SC_ASN1_CONS | SC_ASN1_SEQUENCE, 0, &path }, { NULL } }; - struct sc_asn1_entry asn1_odf[6]; + struct sc_asn1_entry asn1_odf[9]; sc_copy_asn1_entry(c_asn1_odf, asn1_odf); for (i = 0; asn1_odf[i].name != NULL; i++) @@ -593,6 +599,148 @@ int sc_pkcs15_unbind(struct sc_pkcs15_card *p15card) return 0; } +int sc_pkcs15_get_objects_cond(struct sc_pkcs15_card *p15card, int type, + int (* func)(struct sc_pkcs15_object *, void *), + void *func_arg, + struct sc_pkcs15_object **ret, int ret_size) +{ + const int prkey_df[] = { SC_PKCS15_PRKDF, -1 }; + const int pubkey_df[] = { SC_PKCS15_PUKDF, SC_PKCS15_PUKDF_TRUSTED, -1 }; + const int cert_df[] = { SC_PKCS15_CDF, SC_PKCS15_CDF_TRUSTED, SC_PKCS15_CDF_USEFUL, -1 }; + const int auth_df[] = { SC_PKCS15_AODF, -1 }; + const int *dfs; + int count = 0, i, r; + + switch (type & SC_PKCS15_TYPE_CLASS_MASK) { + case SC_PKCS15_TYPE_PRKEY: + dfs = prkey_df; + break; + case SC_PKCS15_TYPE_PUBKEY: + dfs = pubkey_df; + break; + case SC_PKCS15_TYPE_CERT: + dfs = cert_df; + break; + case SC_PKCS15_TYPE_AUTH: + dfs = auth_df; + break; + default: + return SC_ERROR_INVALID_ARGUMENTS; + } + for (i = 0; dfs[i] != -1; i++) { + int j; + struct sc_pkcs15_df *df = &p15card->df[dfs[i]]; + + if (!df->enumerated) { + r = sc_lock(p15card->card); + SC_TEST_RET(p15card->card->ctx, r, "sc_lock() failed"); + for (j = 0; j < df->count; j++) { + r = sc_pkcs15_parse_df(p15card, df, j); + if (r < 0) + break; + } + sc_unlock(p15card->card); + SC_TEST_RET(p15card->card->ctx, r, "DF parsing failed"); + df->enumerated = 1; + } + for (j = 0; j < df->count; j++) { + struct sc_pkcs15_object *obj = df->obj[j]; + + for (; obj != NULL; obj = obj->next) { + if (obj->type != type) + continue; + if (func != NULL && func(obj, func_arg) <= 0) + continue; + count++; + } + } + } + if (count == 0) + return 0; + if (ret_size <= 0) + return count; + count = 0; + for (i = 0; dfs[i] != -1; i++) { + int j; + struct sc_pkcs15_df *df = &p15card->df[dfs[i]]; + + for (j = 0; j < df->count && count < ret_size; j++) { + struct sc_pkcs15_object *obj = df->obj[j]; + + for (; obj != NULL; obj = obj->next) { + if (count >= ret_size) + break; + if (obj->type != type) + continue; + if (func != NULL && func(obj, func_arg) <= 0) + continue; + ret[count] = obj; + count++; + } + } + } + return count; +} + +int sc_pkcs15_get_objects(struct sc_pkcs15_card *p15card, int type, + struct sc_pkcs15_object **ret, int ret_size) +{ + return sc_pkcs15_get_objects_cond(p15card, type, NULL, NULL, ret, ret_size); +} + +static int compare_obj_id(struct sc_pkcs15_object *obj, void *arg) +{ + void *data = obj->data; + const struct sc_pkcs15_id *id = arg; + + switch (obj->type) { + case SC_PKCS15_TYPE_CERT_X509: + return sc_pkcs15_compare_id(&((struct sc_pkcs15_cert_info *) data)->id, id); + case SC_PKCS15_TYPE_PRKEY_RSA: + return sc_pkcs15_compare_id(&((struct sc_pkcs15_prkey_info *) data)->id, id); + case SC_PKCS15_TYPE_PUBKEY_RSA: + return sc_pkcs15_compare_id(&((struct sc_pkcs15_pubkey_info *) data)->id, id); + case SC_PKCS15_TYPE_AUTH_PIN: + return sc_pkcs15_compare_id(&((struct sc_pkcs15_pin_info *) data)->auth_id, id); + } + return 0; +} + +static int find_by_id(struct sc_pkcs15_card *p15card, + int type, const struct sc_pkcs15_id *id, + struct sc_pkcs15_object **out) +{ + int r; + + r = sc_pkcs15_get_objects_cond(p15card, type, compare_obj_id, (void *) id, out, 1); + if (r < 0) + return r; + if (r == 0) + return SC_ERROR_OBJECT_NOT_FOUND; + return 0; +} + +int sc_pkcs15_find_cert_by_id(struct sc_pkcs15_card *p15card, + const struct sc_pkcs15_id *id, + struct sc_pkcs15_object **out) +{ + return find_by_id(p15card, SC_PKCS15_TYPE_CERT_X509, id, out); +} + +int sc_pkcs15_find_prkey_by_id(struct sc_pkcs15_card *p15card, + const struct sc_pkcs15_id *id, + struct sc_pkcs15_object **out) +{ + return find_by_id(p15card, SC_PKCS15_TYPE_PRKEY_RSA, id, out); +} + +int sc_pkcs15_find_pin_by_auth_id(struct sc_pkcs15_card *p15card, + const struct sc_pkcs15_id *id, + struct sc_pkcs15_object **out) +{ + return find_by_id(p15card, SC_PKCS15_TYPE_AUTH_PIN, id, out); +} + int sc_pkcs15_add_object(struct sc_pkcs15_card *p15card, struct sc_pkcs15_df *df, int file_nr, struct sc_pkcs15_object *obj) { @@ -625,6 +773,10 @@ int sc_pkcs15_encode_df(struct sc_context *ctx, case SC_PKCS15_PRKDF: func = sc_pkcs15_encode_prkdf_entry; break; + case SC_PKCS15_PUKDF: + case SC_PKCS15_PUKDF_TRUSTED: + func = sc_pkcs15_encode_pukdf_entry; + break; case SC_PKCS15_CDF: case SC_PKCS15_CDF_TRUSTED: case SC_PKCS15_CDF_USEFUL: @@ -854,18 +1006,23 @@ int sc_pkcs15_parse_df(struct sc_pkcs15_card *p15card, struct sc_file *file = NULL; size_t file_size; + r = sc_lock(p15card->card); + SC_TEST_RET(ctx, r, "sc_lock() failed"); r = sc_select_file(p15card->card, &path, &file); if (r) { sc_perror(ctx, r, "sc_select_file() failed"); + sc_unlock(p15card->card); return r; } file_size = file->size; sc_file_free(file); if (file_size > sizeof(buf)) { error(ctx, "Buffer too small to handle DF contents\n"); + sc_unlock(p15card->card); return SC_ERROR_INTERNAL; } r = sc_read_binary(p15card->card, 0, buf, file_size, 0); + sc_unlock(p15card->card); if (r < 0) return r; bufsize = file_size; diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h index 8bcf2110..e6adaf46 100644 --- a/src/libopensc/pkcs15.h +++ b/src/libopensc/pkcs15.h @@ -46,15 +46,6 @@ struct sc_pkcs15_id { #define SC_PKCS15_CO_FLAG_MODIFIABLE 0x00000002 #define SC_PKCS15_CO_FLAG_OBJECT_SEEN 0x80000000 /* for PKCS #11 module */ -struct sc_pkcs15_common_obj_attr { - char label[SC_PKCS15_MAX_LABEL_SIZE]; /* zero terminated */ - int flags; - struct sc_pkcs15_id auth_id; - - int user_consent; - /* FIXME: add accessControlRules */ -}; - #define SC_PKCS15_PIN_FLAG_CASE_SENSITIVE 0x0001 #define SC_PKCS15_PIN_FLAG_LOCAL 0x0002 #define SC_PKCS15_PIN_FLAG_CHANGE_DISABLED 0x0004 @@ -73,8 +64,6 @@ struct sc_pkcs15_common_obj_attr { #define SC_PKCS15_PIN_TYPE_UTF8 2 struct sc_pkcs15_pin_info { - struct sc_pkcs15_common_obj_attr com_attr; - struct sc_pkcs15_id auth_id; int reference; int flags, type; @@ -100,11 +89,11 @@ struct sc_pkcs15_algorithm_info { int algorithm, supported_operations; }; -struct sc_pkcs15_rsa_pubkey { +struct sc_pkcs15_pubkey_rsa { u8 *modulus; int modulus_len; unsigned int exponent; - + u8 *data; /* DER encoded raw key */ int data_len; }; @@ -113,15 +102,13 @@ struct sc_pkcs15_cert { int version; unsigned long serial; - struct sc_pkcs15_rsa_pubkey key; + struct sc_pkcs15_pubkey_rsa key; u8 *data; /* DER encoded raw cert */ int data_len; }; struct sc_pkcs15_cert_info { - struct sc_pkcs15_common_obj_attr com_attr; - - struct sc_pkcs15_id id; /* correlates to private RSA key id */ + struct sc_pkcs15_id id; /* correlates to private key id */ int authority; /* boolean */ /* identifiers [2] SEQUENCE OF CredentialIdentifier{{KeyIdentifiers}} */ struct sc_path path; @@ -145,8 +132,6 @@ struct sc_pkcs15_cert_info { #define SC_PKCS15_PRKEY_ACCESS_LOCAL 0x10 struct sc_pkcs15_prkey_info { - struct sc_pkcs15_common_obj_attr com_attr; - struct sc_pkcs15_id id; /* correlates to public certificate id */ unsigned int usage, access_flags; int native, key_reference; @@ -155,19 +140,44 @@ struct sc_pkcs15_prkey_info { struct sc_path path; }; -#define SC_PKCS15_TYPE_PRKEY_RSA 0x100 -#define SC_PKCS15_TYPE_PUBKEY_RSA 0x200 -#define SC_PKCS15_TYPE_CERT_X509 0x400 +struct sc_pkcs15_pubkey_info { + struct sc_pkcs15_id id; /* correlates to private key id */ + unsigned int usage, access_flags; + int native, key_reference; + int modulus_length; + + struct sc_path path; +}; + +#define SC_PKCS15_TYPE_CLASS_MASK 0xF00 + +#define SC_PKCS15_TYPE_PRKEY 0x100 +#define SC_PKCS15_TYPE_PRKEY_RSA 0x101 + +#define SC_PKCS15_TYPE_PUBKEY 0x200 +#define SC_PKCS15_TYPE_PUBKEY_RSA 0x201 + +#define SC_PKCS15_TYPE_CERT 0x400 +#define SC_PKCS15_TYPE_CERT_X509 0x401 #define SC_PKCS15_TYPE_CERT_SPKI 0x402 + #define SC_PKCS15_TYPE_DATA_OBJECT 0x500 -#define SC_PKCS15_TYPE_AUTH_PIN 0x600 +#define SC_PKCS15_TYPE_AUTH 0x600 +#define SC_PKCS15_TYPE_AUTH_PIN 0x601 struct sc_pkcs15_object { int type; + /* CommonObjectAttributes */ + char label[SC_PKCS15_MAX_LABEL_SIZE]; /* zero terminated */ + int flags; + struct sc_pkcs15_id auth_id; + + int user_consent; + + /* Object type specific data */ void *data; - - /* For linked list purposes */ - struct sc_pkcs15_object *next; + + struct sc_pkcs15_object *next; /* used only internally */ }; #define SC_PKCS15_PRKDF 0 @@ -187,6 +197,7 @@ struct sc_pkcs15_df { struct sc_file *file[SC_PKCS15_MAX_DFS]; struct sc_pkcs15_object *obj[SC_PKCS15_MAX_DFS]; int count, record_length, type; + int enumerated; }; #define SC_PKCS15_CARD_MAGIC 0x10203040 @@ -199,14 +210,6 @@ struct sc_pkcs15_card { char *serial_number, *manufacturer_id; unsigned long flags; struct sc_pkcs15_algorithm_info alg_info[1]; - /* FIXME: this could be done better with some C pre-processor - * magic */ - struct sc_pkcs15_cert_info cert_info[SC_PKCS15_MAX_CERTS]; - int cert_count; - struct sc_pkcs15_prkey_info prkey_info[SC_PKCS15_MAX_PRKEYS]; - int prkey_count; - struct sc_pkcs15_pin_info pin_info[SC_PKCS15_MAX_PINS]; - int pin_count; struct sc_file *file_app; struct sc_file *file_tokeninfo, *file_odf; @@ -223,7 +226,7 @@ struct sc_pkcs15_card { #define SC_PKCS15_CARD_FLAG_EID_COMPLIANT 0x08 /* sc_pkcs15_bind: Binds a card object to a PKCS #15 card object - * and initializes a new PKCS#15 card object. Will return + * and initializes a new PKCS #15 card object. Will return * SC_ERROR_PKCS15_APP_NOT_FOUND, if the card hasn't got a * valid PKCS #15 file structure. */ int sc_pkcs15_bind(struct sc_card *card, @@ -232,6 +235,13 @@ int sc_pkcs15_bind(struct sc_card *card, * memory allocations done on the card object. */ int sc_pkcs15_unbind(struct sc_pkcs15_card *card); +int sc_pkcs15_get_objects(struct sc_pkcs15_card *card, int type, + struct sc_pkcs15_object **ret, int ret_count); +int sc_pkcs15_get_objects_cond(struct sc_pkcs15_card *card, int type, + int (* func)(struct sc_pkcs15_object *, void *), + void *func_arg, + struct sc_pkcs15_object **ret, int ret_count); + struct sc_pkcs15_card * sc_pkcs15_card_new(); void sc_pkcs15_card_free(struct sc_pkcs15_card *p15card); @@ -250,14 +260,13 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card, void sc_pkcs15_print_card(const struct sc_pkcs15_card *card); void sc_pkcs15_print_cert_info(const struct sc_pkcs15_cert_info *cert); -int sc_pkcs15_enum_certificates(struct sc_pkcs15_card *card); int sc_pkcs15_read_certificate(struct sc_pkcs15_card *card, const struct sc_pkcs15_cert_info *info, struct sc_pkcs15_cert **cert); void sc_pkcs15_free_certificate(struct sc_pkcs15_cert *cert); int sc_pkcs15_find_cert_by_id(struct sc_pkcs15_card *card, const struct sc_pkcs15_id *id, - struct sc_pkcs15_cert_info **out); + struct sc_pkcs15_object **out); /* sc_pkcs15_create_cdf: Creates a new certificate DF on a card pointed * by . Information about the file, such as the file ID, is read * from . has to be NULL-terminated. */ @@ -267,23 +276,21 @@ int sc_pkcs15_create_cdf(struct sc_pkcs15_card *card, int sc_pkcs15_create(struct sc_pkcs15_card *p15card, struct sc_card *card); void sc_pkcs15_print_prkey_info(const struct sc_pkcs15_prkey_info *prkey); -int sc_pkcs15_enum_private_keys(struct sc_pkcs15_card *card); int sc_pkcs15_find_prkey_by_id(struct sc_pkcs15_card *card, const struct sc_pkcs15_id *id, - struct sc_pkcs15_prkey_info **out); + struct sc_pkcs15_object **out); -void sc_pkcs15_print_pin_info(const struct sc_pkcs15_pin_info *pin); -int sc_pkcs15_enum_pins(struct sc_pkcs15_card *card); +void sc_pkcs15_print_pin_info(const struct sc_pkcs15_pin_info *auth); int sc_pkcs15_verify_pin(struct sc_pkcs15_card *card, struct sc_pkcs15_pin_info *pin, - const u8 *pincode, int pinlen); + const u8 *pincode, size_t pinlen); int sc_pkcs15_change_pin(struct sc_pkcs15_card *card, struct sc_pkcs15_pin_info *pin, - const u8 *oldpincode, int oldpinlen, - const u8 *newpincode, int newpinlen); + const u8 *oldpincode, size_t oldpinlen, + const u8 *newpincode, size_t newpinlen); int sc_pkcs15_find_pin_by_auth_id(struct sc_pkcs15_card *card, const struct sc_pkcs15_id *id, - struct sc_pkcs15_pin_info **out); + struct sc_pkcs15_object **out); int sc_pkcs15_encode_dir(struct sc_context *ctx, struct sc_pkcs15_card *card, @@ -303,6 +310,9 @@ int sc_pkcs15_encode_cdf_entry(struct sc_context *ctx, int sc_pkcs15_encode_prkdf_entry(struct sc_context *ctx, const struct sc_pkcs15_object *obj, u8 **buf, size_t *bufsize); +int sc_pkcs15_encode_pukdf_entry(struct sc_context *ctx, + const struct sc_pkcs15_object *obj, u8 **buf, + size_t *bufsize); int sc_pkcs15_encode_aodf_entry(struct sc_context *ctx, const struct sc_pkcs15_object *obj, u8 **buf, size_t *bufsize); diff --git a/src/libopensc/sc-asn1.h b/src/libopensc/sc-asn1.h index 77cbcb38..6dd9218e 100644 --- a/src/libopensc/sc-asn1.h +++ b/src/libopensc/sc-asn1.h @@ -34,7 +34,7 @@ struct sc_asn1_entry { }; struct sc_asn1_pkcs15_object { - struct sc_pkcs15_common_obj_attr *com_attr; + struct sc_pkcs15_object *p15_obj; struct sc_asn1_entry *asn1_class_attr; struct sc_asn1_entry *asn1_subclass_attr; struct sc_asn1_entry *asn1_type_attr; diff --git a/src/libopensc/sc.c b/src/libopensc/sc.c index 2c4f5c84..01880b7f 100644 --- a/src/libopensc/sc.c +++ b/src/libopensc/sc.c @@ -159,7 +159,7 @@ int sc_establish_context(struct sc_context **ctx_out) for (i = 0; i < SC_MAX_READER_DRIVERS+1; i++) ctx->reader_drivers[i] = NULL; i = 0; -#if 1 +#if 1 && defined(HAVE_LIBPCSCLITE) ctx->reader_drivers[i++] = sc_get_pcsc_driver(); #endif i = 0; diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am index 5cee3596..cba663b7 100644 --- a/src/tools/Makefile.am +++ b/src/tools/Makefile.am @@ -7,7 +7,7 @@ if HAVE_SSL PROGRAMS_SSL = cryptoflex-tool pkcs15-init endif -bin_PROGRAMS = opensc-tool opensc-explorer pkcs15-crypt pkcs15-tool \ +bin_PROGRAMS = opensc-tool opensc-explorer pkcs15-tool pkcs15-crypt \ $(PROGRAMS_SSL) opensc_tool_SOURCES = opensc-tool.c util.c diff --git a/src/tools/cryptoflex-tool.c b/src/tools/cryptoflex-tool.c index 6c8020f4..4e5e8a20 100644 --- a/src/tools/cryptoflex-tool.c +++ b/src/tools/cryptoflex-tool.c @@ -1087,9 +1087,11 @@ int add_object(struct sc_pkcs15_card *p15card, int create_pkcs15() { +#if 0 struct sc_pkcs15_card *p15card; struct sc_file *file; - struct sc_path path; + struct sc_path path; + struct sc_pkcs15_object obj; struct sc_pkcs15_cert_info cert; struct sc_pkcs15_pin_info pin; struct sc_pkcs15_prkey_info prkey; @@ -1223,6 +1225,7 @@ int create_pkcs15() fprintf(stderr, "PKCS #15 structure creation failed: %s\n", sc_strerror(r)); return 1; } +#endif return 0; } diff --git a/src/tools/pkcs15-crypt.c b/src/tools/pkcs15-crypt.c index aada1762..d31bbcec 100644 --- a/src/tools/pkcs15-crypt.c +++ b/src/tools/pkcs15-crypt.c @@ -73,14 +73,15 @@ struct sc_context *ctx = NULL; struct sc_card *card = NULL; struct sc_pkcs15_card *p15card = NULL; -char * get_pin(struct sc_pkcs15_pin_info *pinfo) +char * get_pin(struct sc_pkcs15_object *obj) { char buf[80]; char *pincode; + struct sc_pkcs15_pin_info *pinfo = obj->data; if (opt_pincode != NULL) return strdup(opt_pincode); - sprintf(buf, "Enter PIN [%s]: ", pinfo->com_attr.label); + sprintf(buf, "Enter PIN [%s]: ", obj->label); while (1) { pincode = getpass(buf); if (strlen(pincode) == 0) @@ -192,8 +193,7 @@ int main(int argc, char * const argv[]) int do_decipher = 0; int do_sign = 0; int action_count = 0; - struct sc_pkcs15_prkey_info *key; - struct sc_pkcs15_pin_info *pin; + struct sc_pkcs15_object *key, *pin, *objs[32]; struct sc_pkcs15_id id; char *pincode; @@ -280,17 +280,17 @@ int main(int argc, char * const argv[]) #endif if (!quiet) - fprintf(stderr, "Trying to find a PKCS#15 compatible card...\n"); + fprintf(stderr, "Trying to find a PKCS #15 compatible card...\n"); r = sc_pkcs15_bind(card, &p15card); if (r) { - fprintf(stderr, "PKCS#15 initialization failed: %s\n", sc_strerror(r)); + fprintf(stderr, "PKCS #15 initialization failed: %s\n", sc_strerror(r)); err = 1; goto end; } if (!quiet) fprintf(stderr, "Found %s!\n", p15card->label); - r = sc_pkcs15_enum_private_keys(p15card); + r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY_RSA, objs, 32); if (r <= 0) { if (r == 0) r = SC_ERROR_OBJECT_NOT_FOUND; @@ -308,8 +308,8 @@ int main(int argc, char * const argv[]) goto end; } } else - key = &p15card->prkey_info[0]; - r = sc_pkcs15_find_pin_by_auth_id(p15card, &key->com_attr.auth_id, &pin); + key = objs[0]; + r = sc_pkcs15_find_pin_by_auth_id(p15card, &key->auth_id, &pin); if (r) { fprintf(stderr, "Unable to find PIN code for private key: %s\n", sc_strerror(r)); @@ -321,7 +321,7 @@ int main(int argc, char * const argv[]) err = 5; goto end; } - r = sc_pkcs15_verify_pin(p15card, pin, (const u8 *) pincode, strlen(pincode)); + r = sc_pkcs15_verify_pin(p15card, pin->data, (const u8 *) pincode, strlen(pincode)); if (r) { fprintf(stderr, "PIN code verification failed: %s\n", sc_strerror(r)); err = 5; @@ -331,12 +331,12 @@ int main(int argc, char * const argv[]) if (!quiet) fprintf(stderr, "PIN code correct.\n"); if (do_decipher) { - if ((err = decipher(key))) + if ((err = decipher(key->data))) goto end; action_count--; } if (do_sign) { - if ((err = sign(key))) + if ((err = sign(key->data))) goto end; action_count--; } diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index e3047334..68714266 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -74,20 +74,38 @@ struct sc_context *ctx = NULL; struct sc_card *card = NULL; struct sc_pkcs15_card *p15card = NULL; +void print_cert_info(const struct sc_pkcs15_object *obj) +{ + int i; + struct sc_pkcs15_cert_info *cert = (struct sc_pkcs15_cert_info *) obj->data; + + printf("X.509 Certificate [%s]\n", obj->label); + printf("\tFlags : %d\n", obj->flags); + printf("\tAuthority: %s\n", cert->authority ? "yes" : "no"); + printf("\tPath : "); + for (i = 0; i < cert->path.len; i++) + printf("%02X", cert->path.value[i]); + printf("\n"); + printf("\tID : "); + sc_pkcs15_print_id(&cert->id); + printf("\n"); +} + + int list_certificates(void) { int r, i; + struct sc_pkcs15_object *objs[32]; - r = sc_pkcs15_enum_certificates(p15card); + r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_CERT_X509, objs, 32); if (r < 0) { fprintf(stderr, "Certificate enumeration failed: %s\n", sc_strerror(r)); return 1; } if (!quiet) - printf("Card has %d certificate(s).\n\n", p15card->cert_count); - for (i = 0; i < p15card->cert_count; i++) { - struct sc_pkcs15_cert_info *cinfo = &p15card->cert_info[i]; - sc_pkcs15_print_cert_info(cinfo); + printf("Card has %d certificate(s).\n\n", r); + for (i = 0; i < r; i++) { + print_cert_info(objs[i]); printf("\n"); } return 0; @@ -123,20 +141,21 @@ int print_pem_certificate(struct sc_pkcs15_cert *cert) int read_certificate(void) { - int r, i; + int r, i, count; struct sc_pkcs15_id id; + struct sc_pkcs15_object *objs[32]; id.len = SC_PKCS15_MAX_ID_SIZE; sc_pkcs15_hex_string_to_id(opt_cert, &id); - - r = sc_pkcs15_enum_certificates(p15card); + + r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_CERT_X509, objs, 32); if (r < 0) { fprintf(stderr, "Certificate enumeration failed: %s\n", sc_strerror(r)); return 1; } - - for (i = 0; i < p15card->cert_count; i++) { - struct sc_pkcs15_cert_info *cinfo = &p15card->cert_info[i]; + count = r; + for (i = 0; i < count; i++) { + struct sc_pkcs15_cert_info *cinfo = objs[i]->data; struct sc_pkcs15_cert *cert; if (sc_pkcs15_compare_id(&id, &cinfo->id) != 1) @@ -157,37 +176,131 @@ int read_certificate(void) return 2; } +void print_prkey_info(const struct sc_pkcs15_object *obj) +{ + int i; + struct sc_pkcs15_prkey_info *prkey = (struct sc_pkcs15_prkey_info *) obj->data; + const char *usages[] = { + "encrypt", "decrypt", "sign", "signRecover", + "wrap", "unwrap", "verify", "verifyRecover", + "derive", "nonRepudiation" + }; + const int usage_count = sizeof(usages)/sizeof(usages[0]); + const char *access_flags[] = { + "sensitive", "extract", "alwaysSensitive", + "neverExtract", "local" + }; + const int af_count = sizeof(access_flags)/sizeof(access_flags[0]); + + printf("Private RSA Key [%s]\n", obj->label); + printf("\tCom. Flags : %X\n", obj->flags); + printf("\tUsage : [0x%X]", prkey->usage); + for (i = 0; i < usage_count; i++) + if (prkey->usage & (1 << i)) { + printf(", %s", usages[i]); + } + printf("\n"); + printf("\tAccess Flags: [0x%X]", prkey->access_flags); + for (i = 0; i < af_count; i++) + if (prkey->access_flags & (1 << i)) { + printf(", %s", access_flags[i]); + } + printf("\n"); + printf("\tModLength : %d\n", prkey->modulus_length); + printf("\tKey ref : %d\n", prkey->key_reference); + printf("\tNative : %s\n", prkey->native ? "yes" : "no"); + printf("\tPath : "); + for (i = 0; i < prkey->path.len; i++) + printf("%02X", prkey->path.value[i]); + printf("\n"); + printf("\tAuth ID : "); + sc_pkcs15_print_id(&obj->auth_id); + printf("\n"); + printf("\tID : "); + sc_pkcs15_print_id(&prkey->id); + printf("\n"); +} + + int list_private_keys(void) { int r, i; + struct sc_pkcs15_object *objs[32]; - r = sc_pkcs15_enum_private_keys(p15card); + r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY_RSA, objs, 32); if (r < 0) { fprintf(stderr, "Private key enumeration failed: %s\n", sc_strerror(r)); return 1; } if (!quiet) - printf("Card has %d private key(s).\n\n", p15card->prkey_count); - for (i = 0; i < p15card->prkey_count; i++) { - struct sc_pkcs15_prkey_info *pinfo = &p15card->prkey_info[i]; - sc_pkcs15_print_prkey_info(pinfo); + printf("Card has %d private key(s).\n\n", r); + for (i = 0; i < r; i++) { + print_prkey_info(objs[i]); printf("\n"); } return 0; } +void print_pubkey_info(const struct sc_pkcs15_object *obj) +{ + int i; + const struct sc_pkcs15_pubkey_info *pubkey = (const struct sc_pkcs15_pubkey_info *) obj->data; + const char *usages[] = { + "encrypt", "decrypt", "sign", "signRecover", + "wrap", "unwrap", "verify", "verifyRecover", + "derive", "nonRepudiation" + }; + const int usage_count = sizeof(usages)/sizeof(usages[0]); + const char *access_flags[] = { + "sensitive", "extract", "alwaysSensitive", + "neverExtract", "local" + }; + const int af_count = sizeof(access_flags)/sizeof(access_flags[0]); + + printf("Public RSA Key [%s]\n", obj->label); + printf("\tCom. Flags : %X\n", obj->flags); + printf("\tUsage : [0x%X]", pubkey->usage); + for (i = 0; i < usage_count; i++) + if (pubkey->usage & (1 << i)) { + printf(", %s", usages[i]); + } + printf("\n"); + printf("\tAccess Flags: [0x%X]", pubkey->access_flags); + for (i = 0; i < af_count; i++) + if (pubkey->access_flags & (1 << i)) { + printf(", %s", access_flags[i]); + } + printf("\n"); + printf("\tModLength : %d\n", pubkey->modulus_length); + printf("\tKey ref : %d\n", pubkey->key_reference); + printf("\tNative : %s\n", pubkey->native ? "yes" : "no"); + printf("\tPath : "); + for (i = 0; i < pubkey->path.len; i++) + printf("%02X", pubkey->path.value[i]); + printf("\n"); + printf("\tAuth ID : "); + sc_pkcs15_print_id(&obj->auth_id); + printf("\n"); + printf("\tID : "); + sc_pkcs15_print_id(&pubkey->id); + printf("\n"); +} + + + u8 * get_pin(const char *prompt, struct sc_pkcs15_pin_info **pin_out) { int r; char buf[80]; char *pincode; - struct sc_pkcs15_pin_info *pinfo; + struct sc_pkcs15_object *objs[32], *obj; + struct sc_pkcs15_pin_info *pinfo = NULL; if (pin_out != NULL) pinfo = *pin_out; - + if (pinfo == NULL && opt_pin_id == NULL) { - r = sc_pkcs15_enum_pins(p15card); + r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, 32); if (r < 0) { fprintf(stderr, "PIN code enumeration failed: %s\n", sc_strerror(r)); return NULL; @@ -196,22 +309,24 @@ u8 * get_pin(const char *prompt, struct sc_pkcs15_pin_info **pin_out) fprintf(stderr, "No PIN codes found.\n"); return NULL; } - pinfo = &p15card->pin_info[0]; + obj = objs[0]; + pinfo = obj->data; } else if (pinfo == NULL) { struct sc_pkcs15_id pin_id; sc_pkcs15_hex_string_to_id(opt_pin_id, &pin_id); - r = sc_pkcs15_find_pin_by_auth_id(p15card, &pin_id, &pinfo); + r = sc_pkcs15_find_pin_by_auth_id(p15card, &pin_id, &obj); if (r) { fprintf(stderr, "Unable to find PIN code: %s\n", sc_strerror(r)); return NULL; } + pinfo = obj->data; } if (pin_out != NULL) *pin_out = pinfo; - - sprintf(buf, "%s [%s]: ", prompt, pinfo->com_attr.label); + + sprintf(buf, "%s [%s]: ", prompt, obj->label); while (1) { pincode = getpass(buf); if (strlen(pincode) == 0) @@ -228,20 +343,59 @@ u8 * get_pin(const char *prompt, struct sc_pkcs15_pin_info **pin_out) } } +void print_pin_info(const struct sc_pkcs15_object *obj) +{ + const char *pin_flags[] = { + "case-sensitive", "local", "change-disabled", + "unblock-disabled", "initialized", "needs-padding", + "unblockingPin", "soPin", "disable_allowed", + "integrity-protected", "confidentiality-protected", + "exchangeRefData" + }; + const struct sc_pkcs15_pin_info *pin = (const struct sc_pkcs15_pin_info *) obj->data; + const int pf_count = sizeof(pin_flags)/sizeof(pin_flags[0]); + char path[SC_MAX_PATH_SIZE * 2 + 1]; + int i; + char *p; + + p = path; + *p = 0; + for (i = 0; i < pin->path.len; i++) { + sprintf(p, "%02X", pin->path.value[i]); + p += 2; + } + printf("PIN [%s]\n", obj->label); + printf("\tCom. Flags: 0x%X\n", obj->flags); + printf("\tAuth ID : "); + sc_pkcs15_print_id(&pin->auth_id); + printf("\n"); + printf("\tFlags : [0x%02X]", pin->flags); + for (i = 0; i < pf_count; i++) + if (pin->flags & (1 << i)) { + printf(", %s", pin_flags[i]); + } + printf("\n"); + printf("\tLength : %d..%d\n", pin->min_length, pin->stored_length); + printf("\tPad char : 0x%02X\n", pin->pad_char); + printf("\tReference : %d\n", pin->reference); + printf("\tType : %d\n", pin->type); + printf("\tPath : %s\n", path); +} + int list_pins(void) { int r, i; - - r = sc_pkcs15_enum_pins(p15card); + struct sc_pkcs15_object *objs[32]; + + r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, 32); if (r < 0) { - fprintf(stderr, "PIN code enumeration failed: %s\n", sc_strerror(r)); + fprintf(stderr, "Private key enumeration failed: %s\n", sc_strerror(r)); return 1; } if (!quiet) - printf("Card has %d PIN code(s).\n\n", p15card->pin_count); - for (i = 0; i < p15card->pin_count; i++) { - struct sc_pkcs15_pin_info *pinfo = &p15card->pin_info[i]; - sc_pkcs15_print_pin_info(pinfo); + printf("Card has %d PIN code(s).\n\n", r); + for (i = 0; i < r; i++) { + print_pin_info(objs[i]); printf("\n"); } return 0; @@ -332,8 +486,9 @@ int learn_card(void) { struct stat stbuf; char dir[120]; - int r, i; - + int r, i, cert_count; + struct sc_pkcs15_object *certs[32]; + r = sc_get_cache_dir(ctx, dir, sizeof(dir)); if (r) { fprintf(stderr, "Unable to find cache directory: %s\n", sc_strerror(r)); @@ -349,19 +504,20 @@ int learn_card(void) } } printf("Using cache directory '%s'.\n", dir); - r = sc_pkcs15_enum_certificates(p15card); + r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_CERT_X509, certs, 32); if (r < 0) { fprintf(stderr, "Certificate enumeration failed: %s\n", sc_strerror(r)); return 1; } - r = sc_pkcs15_enum_private_keys(p15card); + cert_count = r; + r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY_RSA, NULL, 0); if (r < 0) { - fprintf(stderr, "Certificate enumeration failed: %s\n", sc_strerror(r)); + fprintf(stderr, "Private key enumeration failed: %s\n", sc_strerror(r)); return 1; } - r = sc_pkcs15_enum_pins(p15card); + r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, NULL, 0); if (r < 0) { - fprintf(stderr, "Certificate enumeration failed: %s\n", sc_strerror(r)); + fprintf(stderr, "PIN code enumeration failed: %s\n", sc_strerror(r)); return 1; } for (i = 0; i < SC_PKCS15_DF_TYPE_COUNT; i++) { @@ -375,10 +531,10 @@ int learn_card(void) } } printf("Caching %d certificate(s)...\n", r); - for (i = 0; i < p15card->cert_count; i++) { - struct sc_pkcs15_cert_info *cinfo = &p15card->cert_info[i]; + for (i = 0; i < cert_count; i++) { + struct sc_pkcs15_cert_info *cinfo = certs[i]->data; - printf("[%s]\n", cinfo->com_attr.label); + printf("[%s]\n", certs[i]->label); read_and_cache_file(&cinfo->path); } @@ -458,6 +614,11 @@ int main(int argc, char * const argv[]) ctx->error_file = stderr; ctx->debug_file = stdout; ctx->debug = opt_debug; + if (ctx->reader_count == 0) { + fprintf(stderr, "No readers configured.\n"); + err = 1; + goto end; + } if (opt_reader >= ctx->reader_count || opt_reader < 0) { fprintf(stderr, "Illegal reader number. Only %d reader(s) configured.\n", ctx->reader_count); err = 1; @@ -465,7 +626,8 @@ int main(int argc, char * const argv[]) } if (sc_detect_card_presence(ctx->reader[opt_reader], 0) != 1) { fprintf(stderr, "Card not present.\n"); - return 3; + err = 3; + goto end; } if (!quiet) fprintf(stderr, "Connecting to card in reader %s...\n", ctx->reader[opt_reader]->name);