From 58b43049576088dff48b01b20fbfedde20249054 Mon Sep 17 00:00:00 2001 From: Viktor Tarasov Date: Sun, 2 Sep 2012 00:12:57 +0200 Subject: [PATCH] libopensc: 'init', 'format', 'compare', 'is-valid' OID procedures In a reason of number of bugs(*) that concern the OID management, the general usage OID procedures 'init', 'format', 'compare', 'is-valid' are introduced. These procedures should be used by all actors: libopensc, pkcs15, pkcs11, tools, .... (*) This bug reported by Andreas Schwier : https://github.com/OpenSC/OpenSC/commit/8e75d971cb7eadfef9b5b50adb3cb6d18e641ed2#commitcomment-1792477 In pkcs15-algo sc_asn1_get_algorithm_info() can return the OID without ending '-1's: https://github.com/OpenSC/OpenSC/blob/staging/src/libopensc/pkcs15-algo.c#L452 https://github.com/OpenSC/OpenSC/blob/staging/src/libopensc/pkcs15-algo.c#L459 --- src/libopensc/asn1.c | 70 ++++++++++--------- src/libopensc/ef-atr.c | 11 ++- src/libopensc/libopensc.exports | 3 + src/libopensc/opensc.h | 13 +++- src/libopensc/pkcs15-algo.c | 116 +++++++++++++++----------------- src/libopensc/pkcs15-data.c | 16 ++--- src/libopensc/pkcs15-pubkey.c | 4 +- src/libopensc/pkcs15.c | 8 +-- src/libopensc/sc.c | 69 +++++++++++++------ src/libopensc/types.h | 6 +- src/pkcs11/framework-pkcs15.c | 80 ++++++++++++---------- src/pkcs15init/pkcs15-iasecc.c | 4 +- src/tools/pkcs11-tool.c | 73 ++++++++++++++------ src/tools/pkcs15-init.c | 3 +- src/tools/pkcs15-tool.c | 43 +++++------- 15 files changed, 297 insertions(+), 222 deletions(-) diff --git a/src/libopensc/asn1.c b/src/libopensc/asn1.c index c944593c..447045a0 100644 --- a/src/libopensc/asn1.c +++ b/src/libopensc/asn1.c @@ -207,23 +207,23 @@ static void sc_asn1_print_bit_string(const u8 * buf, size_t buflen) static void sc_asn1_print_object_id(const u8 * buf, size_t buflen) { - int i = 0; struct sc_object_id oid; + int i = 0; char sbuf[256]; if (sc_asn1_decode_object_id(buf, buflen, &oid)) { printf("decode error"); return; } + sbuf[0] = 0; - while (oid.value[i] >= 0) { + for (i = 0; (i < SC_MAX_OBJECT_ID_OCTETS) && (oid.value[i] != -1); i++) { char tmp[12]; if (i) strcat(sbuf, "."); sprintf(tmp, "%d", oid.value[i]); strcat(sbuf, tmp); - i++; } printf("%s", sbuf); } @@ -636,18 +636,19 @@ static int asn1_encode_integer(int in, u8 ** obj, size_t * objsize) return 0; } -int sc_asn1_decode_object_id(const u8 * inbuf, size_t inlen, - struct sc_object_id *id) +int +sc_asn1_decode_object_id(const u8 *inbuf, size_t inlen, struct sc_object_id *id) { - int i, a; + int a; const u8 *p = inbuf; int *octet; if (inlen == 0 || inbuf == NULL || id == NULL) return SC_ERROR_INVALID_ARGUMENTS; + + sc_init_oid(id); octet = id->value; - for (i = 0; i < SC_MAX_OBJECT_ID_OCTETS; i++) - id->value[i] = -1; + a = *p; *octet++ = a / 40; *octet++ = a % 40; @@ -664,31 +665,35 @@ int sc_asn1_decode_object_id(const u8 * inbuf, size_t inlen, inlen--; } *octet++ = a; - if (octet - id->value >= SC_MAX_OBJECT_ID_OCTETS-1) + if (octet - id->value >= SC_MAX_OBJECT_ID_OCTETS) { + sc_init_oid(id); return SC_ERROR_INVALID_ASN1_OBJECT; + } }; return 0; } -int sc_asn1_encode_object_id(u8 **buf, size_t *buflen, - const struct sc_object_id *id) +int +sc_asn1_encode_object_id(u8 **buf, size_t *buflen, const struct sc_object_id *id) { u8 temp[SC_MAX_OBJECT_ID_OCTETS*5], *p = temp; - size_t count = 0; int i; - int value[SC_MAX_OBJECT_ID_OCTETS]; - /* set the unused ID part to '-1' */ - memcpy(value, &id->value[0], sizeof(value)); - for (i = SC_MAX_OBJECT_ID_OCTETS - 1; i>=0; i--) - if (!value[i]) - value[i] = -1; + if (!buflen || !id) + return SC_ERROR_INVALID_ARGUMENTS; - for (i = 0; i < SC_MAX_OBJECT_ID_OCTETS && value[i] >= 0; i++) { + /* an OID must have at least two components */ + if (id->value[0] == -1 || id->value[1] == -1) + return SC_ERROR_INVALID_ARGUMENTS; + + for (i = 0; i < SC_MAX_OBJECT_ID_OCTETS; i++) { unsigned int k, shift; - k = value[i]; + if (id->value[i] == -1) + break; + + k = id->value[i]; switch (i) { case 0: if (k > 2) @@ -712,14 +717,15 @@ int sc_asn1_encode_object_id(u8 **buf, size_t *buflen, break; } } - if (i == 1) - /* an OID must have at least two components */ - return SC_ERROR_INVALID_ARGUMENTS; - *buflen = count = p - temp; - *buf = malloc(count); - if (!*buf) - return SC_ERROR_OUT_OF_MEMORY; - memcpy(*buf, temp, count); + + *buflen = p - temp; + + if (buf) { + *buf = malloc(*buflen); + if (!*buf) + return SC_ERROR_OUT_OF_MEMORY; + memcpy(*buf, temp, *buflen); + } return 0; } @@ -953,7 +959,7 @@ static int asn1_decode_se_info(sc_context_t *ctx, const u8 *obj, size_t objlen, { struct sc_pkcs15_sec_env_info **ses; const unsigned char *ptr = obj; - size_t i, idx, ptrlen = objlen; + size_t idx, ptrlen = objlen; int ret; ses = calloc(SC_MAX_SE_NUM, sizeof(sc_pkcs15_sec_env_info_t *)); @@ -978,8 +984,7 @@ static int asn1_decode_se_info(sc_context_t *ctx, const u8 *obj, size_t objlen, if (ret != SC_SUCCESS) goto err; if (!(asn1_se_info[1].flags & SC_ASN1_PRESENT)) - for (i=0;ise, NULL, 1); - if (se[idx]->owner.value[0] != -1) + if (sc_valid_oid(&se[idx]->owner)) sc_format_asn1_entry(asn1_se_info + 1, &se[idx]->owner, NULL, 1); if (se[idx]->aid.len) sc_format_asn1_entry(asn1_se_info + 2, &se[idx]->aid.value, &se[idx]->aid.len, 1); diff --git a/src/libopensc/ef-atr.c b/src/libopensc/ef-atr.c index 4b72eee3..1318db12 100644 --- a/src/libopensc/ef-atr.c +++ b/src/libopensc/ef-atr.c @@ -95,9 +95,14 @@ sc_parse_ef_atr_content(struct sc_card *card, unsigned char *buf, size_t buflen) } tag = sc_asn1_find_tag(ctx, buf, buflen, ISO7816_TAG_II_ALLOCATION_SCHEME, &taglen); - if (tag && taglen < sizeof(ef_atr.allocation_oid)) { - sc_log(ctx, "EF.ATR: OID %s", sc_dump_hex(tag, sizeof(taglen))); - memcpy(ef_atr.allocation_oid.value, tag, taglen); + if (tag) { + sc_log(ctx, "EF.ATR: DER encoded OID %s", sc_dump_hex(tag, taglen)); + tag = sc_asn1_find_tag(ctx, tag, taglen, SC_ASN1_TAG_OBJECT, &taglen); + if (tag) { + sc_log(ctx, "EF.ATR: OID %s", sc_dump_hex(tag, taglen)); + if(sc_asn1_decode_object_id(tag, taglen, &ef_atr.allocation_oid)) + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ASN1_OBJECT); + } } if (category == ISO7816_II_CATEGORY_TLV) { diff --git a/src/libopensc/libopensc.exports b/src/libopensc/libopensc.exports index 4d3de66d..0f161745 100644 --- a/src/libopensc/libopensc.exports +++ b/src/libopensc/libopensc.exports @@ -101,6 +101,9 @@ sc_format_apdu sc_bytes2apdu sc_format_asn1_entry sc_format_oid +sc_init_oid +sc_compare_oid +sc_valid_oid sc_format_path sc_free_apps sc_free_ef_atr diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 878f8210..381b67a8 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -174,7 +174,7 @@ typedef struct sc_security_env { struct sc_algorithm_id { unsigned int algorithm; - struct sc_object_id obj_id; + struct sc_object_id oid; void *params; }; @@ -1216,6 +1216,12 @@ const sc_path_t *sc_get_mf_path(void); int sc_hex_to_bin(const char *in, u8 *out, size_t *outlen); int sc_bin_to_hex(const u8 *, size_t, char *, size_t, int separator); scconf_block *sc_get_conf_block(sc_context_t *ctx, const char *name1, const char *name2, int priority); + +/** + * Initializes a given OID + * @param oid sc_object_id object to be initialized + */ +void sc_init_oid(struct sc_object_id *oid); /** * Converts a given OID in ascii form to a internal sc_object_id object * @param oid OUT sc_object_id object for the result @@ -1230,6 +1236,11 @@ int sc_format_oid(struct sc_object_id *oid, const char *in); * @return 1 if the oids are equal and a non-zero value otherwise */ int sc_compare_oid(const struct sc_object_id *oid1, const struct sc_object_id *oid2); +/** + * Validates a given OID + * @param oid sc_object_id object to be validated + */ +int sc_valid_oid(const struct sc_object_id *oid); /* Base64 encoding/decoding functions */ int sc_base64_encode(const u8 *in, size_t inlen, u8 *out, size_t outlen, diff --git a/src/libopensc/pkcs15-algo.c b/src/libopensc/pkcs15-algo.c index 256878da..f2c22350 100644 --- a/src/libopensc/pkcs15-algo.c +++ b/src/libopensc/pkcs15-algo.c @@ -335,131 +335,122 @@ asn1_free_ec_params(void *params) static struct sc_asn1_pkcs15_algorithm_info algorithm_table[] = { #ifdef SC_ALGORITHM_SHA1 /* hmacWithSHA1 */ - { SC_ALGORITHM_SHA1, {{ 1, 2, 840, 113549, 2, 7 }}, NULL, NULL, NULL }, - { SC_ALGORITHM_SHA1, {{ 1, 3, 6, 1, 5, 5, 8, 1, 2 }}, NULL, NULL, NULL }, + { SC_ALGORITHM_SHA1, {{ 1, 2, 840, 113549, 2, 7, -1}}, NULL, NULL, NULL }, + { SC_ALGORITHM_SHA1, {{ 1, 3, 6, 1, 5, 5, 8, 1, 2, -1}}, NULL, NULL, NULL }, /* SHA1 */ - { SC_ALGORITHM_SHA1, {{ 1, 3, 14, 3, 2, 26, }}, NULL, NULL, NULL }, + { SC_ALGORITHM_SHA1, {{ 1, 3, 14, 3, 2, 26, -1}}, NULL, NULL, NULL }, #endif #ifdef SC_ALGORITHM_MD5 - { SC_ALGORITHM_MD5, {{ 1, 2, 840, 113549, 2, 5, }}, NULL, NULL, NULL }, + { SC_ALGORITHM_MD5, {{ 1, 2, 840, 113549, 2, 5, -1}}, NULL, NULL, NULL }, #endif #ifdef SC_ALGORITHM_DSA - { SC_ALGORITHM_DSA, {{ 1, 2, 840, 10040, 4, 3 }}, NULL, NULL, NULL }, + { SC_ALGORITHM_DSA, {{ 1, 2, 840, 10040, 4, 3, -1}}, NULL, NULL, NULL }, #endif #ifdef SC_ALGORITHM_RSA /* really rsaEncryption */ - { SC_ALGORITHM_RSA, {{ 1, 2, 840, 113549, 1, 1, 1 }}, NULL, NULL, NULL }, + { SC_ALGORITHM_RSA, {{ 1, 2, 840, 113549, 1, 1, 1, -1}}, NULL, NULL, NULL }, #endif #ifdef SC_ALGORITHM_DH - { SC_ALGORITHM_DH, {{ 1, 2, 840, 10046, 2, 1 }}, NULL, NULL, NULL }, + { SC_ALGORITHM_DH, {{ 1, 2, 840, 10046, 2, 1, -1}}, NULL, NULL, NULL }, #endif #ifdef SC_ALGORITHM_RC2_WRAP /* from CMS */ - { SC_ALGORITHM_RC2_WRAP, {{ 1, 2, 840, 113549, 1, 9, 16, 3, 7 }}, NULL, NULL, NULL }, + { SC_ALGORITHM_RC2_WRAP, {{ 1, 2, 840, 113549, 1, 9, 16, 3, 7, -1}}, NULL, NULL, NULL }, #endif #ifdef SC_ALGORITHM_RC2 /* CBC mode */ - { SC_ALGORITHM_RC2, {{ 1, 2, 840, 113549, 3, 2 }}, + { SC_ALGORITHM_RC2, {{ 1, 2, 840, 113549, 3, 2, -1}}, asn1_decode_rc2_params, asn1_encode_rc2_params }, #endif #ifdef SC_ALGORITHM_DES /* CBC mode */ - { SC_ALGORITHM_DES, {{ 1, 3, 14, 3, 2, 7 }}, + { SC_ALGORITHM_DES, {{ 1, 3, 14, 3, 2, 7, -1}}, asn1_decode_des_params, asn1_encode_des_params, free }, #endif #ifdef SC_ALGORITHM_3DES_WRAP /* from CMS */ - { SC_ALGORITHM_3DES_WRAP, {{ 1, 2, 840, 113549, 1, 9, 16, 3, 6 }}, NULL, NULL, NULL }, + { SC_ALGORITHM_3DES_WRAP, {{ 1, 2, 840, 113549, 1, 9, 16, 3, 6, -1}}, NULL, NULL, NULL }, #endif #ifdef SC_ALGORITHM_3DES /* EDE CBC mode */ - { SC_ALGORITHM_3DES, {{ 1, 2, 840, 113549, 3, 7 }}, + { SC_ALGORITHM_3DES, {{ 1, 2, 840, 113549, 3, 7, -1}}, asn1_decode_des_params, asn1_encode_des_params, free }, #endif #ifdef SC_ALGORITHM_GOST /* EDE CBC mode */ - { SC_ALGORITHM_GOST, {{ 1, 2, 4434, 66565, 3, 7 }}, - NULL, - NULL, - NULL }, + { SC_ALGORITHM_GOST, {{ 1, 2, 4434, 66565, 3, 7, -1}}, NULL, NULL, NULL }, #endif #ifdef SC_ALGORITHM_GOSTR3410 - { SC_ALGORITHM_GOSTR3410, {{ 1, 2, 643, 2, 2, 19 }}, + { SC_ALGORITHM_GOSTR3410, {{ 1, 2, 643, 2, 2, 19, -1}}, asn1_decode_gostr3410_params, asn1_encode_gostr3410_params, NULL }, #endif /* We do not support PBES1 because the encryption is weak */ #ifdef SC_ALGORITHM_PBKDF2 - { SC_ALGORITHM_PBKDF2, {{ 1, 2, 840, 113549, 1, 5, 12 }}, + { SC_ALGORITHM_PBKDF2, {{ 1, 2, 840, 113549, 1, 5, 12, -1}}, asn1_decode_pbkdf2_params, asn1_encode_pbkdf2_params, free }, #endif #ifdef SC_ALGORITHM_PBES2 - { SC_ALGORITHM_PBES2, {{ 1, 2, 840, 113549, 1, 5, 13 }}, + { SC_ALGORITHM_PBES2, {{ 1, 2, 840, 113549, 1, 5, 13, -1}}, asn1_decode_pbes2_params, asn1_encode_pbes2_params, asn1_free_pbes2_params }, #endif #ifdef SC_ALGORITHM_EC - { SC_ALGORITHM_EC, {{ 1, 2, 840, 10045, 2, 1 }}, - asn1_decode_ec_params, asn1_encode_ec_params, asn1_free_ec_params }, + { SC_ALGORITHM_EC, {{ 1, 2, 840, 10045, 2, 1, -1}}, + asn1_decode_ec_params, + asn1_encode_ec_params, + asn1_free_ec_params }, #endif /* TODO: -DEE Not clear of we need the next five or not */ #ifdef SC_ALGORITHM_ECDSA_SHA1 /* Note RFC 3279 says no ecParameters */ - { SC_ALGORITHM_ECDSA_SHA1, {{ 1, 2, 840, 10045, 4, 1 }}, NULL, NULL, NULL}, + { SC_ALGORITHM_ECDSA_SHA1, {{ 1, 2, 840, 10045, 4, 1, -1}}, NULL, NULL, NULL}, #endif #ifdef SC_ALGORITHM_ECDSA_SHA224 /* These next 4 are defined in RFC 5758 */ - { SC_ALGORITHM_ECDSA_SHA224, {{ 1, 2, 840, 10045, 4, 3, 1 }}, - asn1_decode_ec_params, asn1_encode_ec_params, asn1_free_ec_params }, + { SC_ALGORITHM_ECDSA_SHA224, {{ 1, 2, 840, 10045, 4, 3, 1, -1}}, + asn1_decode_ec_params, + asn1_encode_ec_params, + asn1_free_ec_params }, #endif #ifdef SC_ALGORITHM_ECDSA_SHA256 - { SC_ALGORITHM_ECDSA_SHA256, {{ 1, 2, 840, 10045, 4, 3, 2 }}, - asn1_decode_ec_params, asn1_encode_ec_params, asn1_free_ec_params }, + { SC_ALGORITHM_ECDSA_SHA256, {{ 1, 2, 840, 10045, 4, 3, 2, -1}}, + asn1_decode_ec_params, + asn1_encode_ec_params, + asn1_free_ec_params }, #endif #ifdef SC_ALGORITHM_ECDSA_SHA384 - { SC_ALGORITHM_ECDSA_SHA384, {{ 1, 2, 840, 10045, 4, 3, 3 }}, - asn1_decode_ec_params, asn1_encode_ec_params, asn1_free_ec_params }, + { SC_ALGORITHM_ECDSA_SHA384, {{ 1, 2, 840, 10045, 4, 3, 3, -1}}, + asn1_decode_ec_params, + asn1_encode_ec_params, + asn1_free_ec_params }, #endif #ifdef SC_ALGORITHM_ECDSA_SHA512 - { SC_ALGORITHM_ECDSA_SHA512, {{ 1, 2, 840, 10045, 4, 3, 4 }}, - asn1_decode_ec_params, asn1_encode_ec_params, asn1_free_ec_params }, + { SC_ALGORITHM_ECDSA_SHA512, {{ 1, 2, 840, 10045, 4, 3, 4, -1}}, + asn1_decode_ec_params, + asn1_encode_ec_params, + asn1_free_ec_params }, #endif { -1, {{ -1 }}, NULL, NULL, NULL } }; + static struct sc_asn1_pkcs15_algorithm_info * sc_asn1_get_algorithm_info(const struct sc_algorithm_id *id) { - struct sc_asn1_pkcs15_algorithm_info *aip; + struct sc_asn1_pkcs15_algorithm_info *aip = NULL; - aip = algorithm_table; - if ((int) id->algorithm < 0) { - while (aip->id >= 0) { - const int *oid1, *oid2; - int m; - - oid1 = aip->oid.value; - oid2 = id->obj_id.value; - for (m = 0; m < SC_MAX_OBJECT_ID_OCTETS; m++) { - if (oid1[m] == oid2[m]) - continue; - if (oid1[m] > 0 || oid2[m] > 0) - break; - /* We have a match */ - return aip; - } - aip++; - } - } else { - while (aip->id >= 0) { - if (aip->id == (int)id->algorithm) - return aip; - aip++; - } + for (aip = algorithm_table; aip->id >= 0; aip++) { + if ((int) id->algorithm < 0 && sc_compare_oid(&id->oid, &aip->oid)) + return aip; + + if (aip->id == (int)id->algorithm) + return aip; } + return NULL; } @@ -479,7 +470,7 @@ sc_asn1_decode_algorithm_id(sc_context_t *ctx, const u8 *in, int r; sc_copy_asn1_entry(c_asn1_alg_id, asn1_alg_id); - sc_format_asn1_entry(asn1_alg_id + 0, &id->obj_id, NULL, 0); + sc_format_asn1_entry(asn1_alg_id + 0, &id->oid, NULL, 0); memset(id, 0, sizeof(*id)); r = _sc_asn1_decode(ctx, asn1_alg_id, in, len, &in, &len, 0, depth + 1); @@ -492,8 +483,8 @@ sc_asn1_decode_algorithm_id(sc_context_t *ctx, const u8 *in, if ((alg_info = sc_asn1_get_algorithm_info(id)) != NULL) { id->algorithm = alg_info->id; if (alg_info->decode) { -/* TODO: -DEE why the test for SC_ASN1_PRESENT? - * If it looking for SC_ASN1_NULL, thats valid for EC, in some cases +/* TODO: -DEE why the test for SC_ASN1_PRESENT? + * If it looking for SC_ASN1_NULL, thats valid for EC, in some cases */ if (asn1_alg_id[1].flags & SC_ASN1_PRESENT) { sc_debug( ctx,SC_LOG_DEBUG_NORMAL,"SC_ASN1_PRESENT was set, so invalid"); @@ -522,20 +513,19 @@ sc_asn1_encode_algorithm_id(sc_context_t *ctx, alg_info = sc_asn1_get_algorithm_info(id); if (alg_info == NULL) { - sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Cannot encode unknown algorithm %u.\n", - id->algorithm); + sc_log(ctx, "Cannot encode unknown algorithm %u", id->algorithm); return SC_ERROR_INVALID_ARGUMENTS; } /* Set the oid if not yet given */ - if (id->obj_id.value[0] <= 0) { + if (!sc_valid_oid(&id->oid)) { temp_id = *id; - temp_id.obj_id = alg_info->oid; + temp_id.oid = alg_info->oid; id = &temp_id; } sc_copy_asn1_entry(c_asn1_alg_id, asn1_alg_id); - sc_format_asn1_entry(asn1_alg_id + 0, (void *) &id->obj_id, NULL, 1); + sc_format_asn1_entry(asn1_alg_id + 0, (void *) &id->oid, NULL, 1); /* no parameters, write NULL tag */ if (!id->params || !alg_info->encode) diff --git a/src/libopensc/pkcs15-data.c b/src/libopensc/pkcs15-data.c index 8391a73e..e366b817 100644 --- a/src/libopensc/pkcs15-data.c +++ b/src/libopensc/pkcs15-data.c @@ -107,7 +107,7 @@ int sc_pkcs15_decode_dodf_entry(struct sc_pkcs15_card *p15card, /* Fill in defaults */ memset(&info, 0, sizeof(info)); - info.app_oid.value[0] = -1; + sc_init_oid(&info.app_oid); r = sc_asn1_decode(ctx, asn1_data, *buf, *buflen, buf, buflen); if (r == SC_ERROR_ASN1_END_OF_CONTENTS) @@ -152,14 +152,12 @@ int sc_pkcs15_encode_dodf_entry(sc_context_t *ctx, sc_copy_asn1_entry(c_asn1_type_data_attr, asn1_type_data_attr); sc_copy_asn1_entry(c_asn1_data, asn1_data); - if (label_len) { - sc_format_asn1_entry(asn1_com_data_attr + 0, - &info->app_label, &label_len, 1); - } - if (info->app_oid.value[0] != -1) { - sc_format_asn1_entry(asn1_com_data_attr + 1, - &info->app_oid, NULL, 1); - } + if (label_len) + sc_format_asn1_entry(asn1_com_data_attr + 0, &info->app_label, &label_len, 1); + + if (sc_valid_oid(&info->app_oid)) + sc_format_asn1_entry(asn1_com_data_attr + 1, &info->app_oid, NULL, 1); + sc_format_asn1_entry(asn1_type_data_attr + 0, &info->path, NULL, 1); sc_format_asn1_entry(asn1_data + 0, &data_obj, NULL, 1); diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c index de2a0c88..c4ff0654 100644 --- a/src/libopensc/pkcs15-pubkey.c +++ b/src/libopensc/pkcs15-pubkey.c @@ -1055,7 +1055,7 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_pkcs15_ec_paramete sc_log(ctx, "Curve name: '%s'", ecparams->named_curve); } - if (ecparams->id.value[0] <=0 || ecparams->id.value[1] <=0) + if (!sc_valid_oid(&ecparams->id)) sc_format_oid(&ecparams->id, ec_curve_infos[ii].oid_str); ecparams->field_length = ec_curve_infos[ii].size; @@ -1081,7 +1081,7 @@ sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_pkcs15_ec_paramete LOG_TEST_RET(ctx, rv, "Cannot encode object ID"); } } - else if (ecparams->id.value[0] > 0 && ecparams->id.value[1] > 0) { + else if (sc_valid_oid(&ecparams->id)) { LOG_TEST_RET(ctx, SC_ERROR_NOT_IMPLEMENTED, "EC parameters has to be presented as a named curve or explicit data"); } diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index b6d5b4a9..8445d017 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -354,13 +354,13 @@ sc_pkcs15_encode_tokeninfo(sc_context_t *ctx, sc_pkcs15_tokeninfo_t *ti, } sc_format_asn1_entry(asn1_toki_attrs + 12, NULL, NULL, 0); - if (ti->profile_indication.oid.value[0] > 0) { - sc_format_asn1_entry(asn1_profile_indication + 0, &ti->profile_indication.oid, NULL, 1); + if (sc_valid_oid(&ti->profile_indication.oid)) { + sc_format_asn1_entry(asn1_profile_indication + 0, &ti->profile_indication.oid, NULL, 1); sc_format_asn1_entry(asn1_toki_attrs + 13, asn1_profile_indication, NULL, 1); } else if (ti->profile_indication.name) { pi_len = strlen(ti->profile_indication.name); - sc_format_asn1_entry(asn1_profile_indication + 1, ti->profile_indication.name, &pi_len, 1); + sc_format_asn1_entry(asn1_profile_indication + 1, ti->profile_indication.name, &pi_len, 1); sc_format_asn1_entry(asn1_toki_attrs + 13, asn1_profile_indication, NULL, 1); } else { @@ -713,7 +713,7 @@ struct sc_pkcs15_card * sc_pkcs15_card_new(void) return NULL; } - p15card->tokeninfo->profile_indication.oid.value[0] = -1; + sc_init_oid(&p15card->tokeninfo->profile_indication.oid); p15card->magic = SC_PKCS15_CARD_MAGIC; return p15card; diff --git a/src/libopensc/sc.c b/src/libopensc/sc.c index 8f7d3f8d..9e29d7ac 100644 --- a/src/libopensc/sc.c +++ b/src/libopensc/sc.c @@ -145,59 +145,88 @@ unsigned short bebytes2ushort(const u8 *buf) return (unsigned short) (buf[0] << 8 | buf[1]); } +void sc_init_oid(struct sc_object_id *oid) +{ + int ii; + + if (!oid) + return; + for (ii=0; iivalue[ii] = -1; +} + int sc_format_oid(struct sc_object_id *oid, const char *in) { - int ii; + int ii, ret = SC_ERROR_INVALID_ARGUMENTS; const char *p; char *q; if (oid == NULL || in == NULL) return SC_ERROR_INVALID_ARGUMENTS; - /* init oid */ - for (ii=0; iivalue[ii] = -1; + + sc_init_oid(oid); p = in; - for (ii=0; ii < SC_MAX_OBJECT_ID_OCTETS; ii++) { oid->value[ii] = strtol(p, &q, 10); if (!*q) break; - if (!(q[0] == '.' && isdigit(q[1]))) { - return SC_ERROR_INVALID_ARGUMENTS; - } + + if (!(q[0] == '.' && isdigit(q[1]))) + goto out; + p = q + 1; } - if (ii == 1) - /* reject too short OIDs */ - return SC_ERROR_INVALID_ARGUMENTS; + if (!sc_valid_oid(oid)) + goto out; - return SC_SUCCESS; + ret = SC_SUCCESS; +out: + if (ret) + sc_init_oid(oid); + + return ret; } int sc_compare_oid(const struct sc_object_id *oid1, const struct sc_object_id *oid2) { int i; + assert(oid1 != NULL && oid2 != NULL); - for (i = 0; i < SC_MAX_OBJECT_ID_OCTETS; i++) { + + for (i = 0; i < SC_MAX_OBJECT_ID_OCTETS; i++) { if (oid1->value[i] != oid2->value[i]) return 0; - if (oid1->value[i] < 0) - return 1; + if (oid1->value[i] == -1) + break; } + return 1; } + +int sc_valid_oid(const struct sc_object_id *oid) +{ + if (!oid) + return 0; + if (oid->value[0] == -1 || oid->value[1] == -1) + return 0; + if (oid->value[0] > 2 || oid->value[1] > 39) + return 0; + return 1; +} + + int sc_detect_card_presence(sc_reader_t *reader) { int r; - SC_FUNC_CALLED(reader->ctx, SC_LOG_DEBUG_VERBOSE); + LOG_FUNC_CALLED(reader->ctx); if (reader->ops->detect_card_presence == NULL) - SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED); + LOG_FUNC_RETURN(reader->ctx, SC_ERROR_NOT_SUPPORTED); r = reader->ops->detect_card_presence(reader); - SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_NORMAL, r); + LOG_FUNC_RETURN(reader->ctx, r); } int sc_path_set(sc_path_t *path, int type, const u8 *id, size_t id_len, @@ -643,12 +672,12 @@ int _sc_parse_atr(sc_reader_t *reader) reader->atr_info.hist_bytes = NULL; if (atr_len == 0) { - sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "empty ATR - card not present?\n"); + sc_log(reader->ctx, "empty ATR - card not present?\n"); return SC_ERROR_INTERNAL; } if (p[0] != 0x3B && p[0] != 0x3F) { - sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "invalid sync byte in ATR: 0x%02X\n", p[0]); + sc_log(reader->ctx, "invalid sync byte in ATR: 0x%02X\n", p[0]); return SC_ERROR_INTERNAL; } n_hist = p[1] & 0x0F; diff --git a/src/libopensc/types.h b/src/libopensc/types.h index 2676e80d..31ca4545 100644 --- a/src/libopensc/types.h +++ b/src/libopensc/types.h @@ -45,9 +45,9 @@ typedef unsigned char u8; #define SC_MAX_CRTS_IN_SE 12 #define SC_MAX_SE_NUM 8 -/* 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 +/* 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 */ #define SC_MAX_SUPPORTED_ALGORITHMS 8 diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index f57012f0..1cf93c84 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -2260,7 +2260,7 @@ pkcs15_create_data(struct sc_pkcs11_slot *slot, struct sc_profile *profile, char label[SC_PKCS15_MAX_LABEL_SIZE]; memset(&args, 0, sizeof(args)); - args.app_oid.value[0] = -1; + sc_init_oid(&args.app_oid); fw_data = (struct pkcs15_fw_data *) p11card->fws_data[slot->fw_data_idx]; if (!fw_data) @@ -2298,9 +2298,10 @@ pkcs15_create_data(struct sc_pkcs11_slot *slot, struct sc_profile *profile, args.app_label = (char *) attr->pValue; break; case CKA_OBJECT_ID: - rv = attr_extract(attr, args.app_oid.value, NULL); - if (rv != CKR_OK) + if (sc_asn1_decode_object_id(attr->pValue, attr->ulValueLen, &args.app_oid)) { + rv = CKR_ATTRIBUTE_VALUE_INVALID; goto out; + } break; case CKA_VALUE: args.der_encoded.len = attr->ulValueLen; @@ -2907,10 +2908,9 @@ pkcs15_cert_release(void *obj) struct pkcs15_cert_object *cert = (struct pkcs15_cert_object *) obj; struct sc_pkcs15_cert *cert_data = cert->cert_data; - if (__pkcs15_release_object((struct pkcs15_any_object *) obj) == 0) { + if (__pkcs15_release_object((struct pkcs15_any_object *) obj) == 0) if (cert_data) /* may never have been read */ sc_pkcs15_free_certificate(cert_data); - } } @@ -2945,8 +2945,7 @@ pkcs15_cert_get_attribute(struct sc_pkcs11_session *session, void *object, CK_AT break; case CKA_PRIVATE: check_attribute_buffer(attr, sizeof(CK_BBOOL)); - *(CK_BBOOL*)attr->pValue = - (cert->base.p15_object->flags & SC_PKCS15_CO_FLAG_PRIVATE) != 0; + *(CK_BBOOL*)attr->pValue = (cert->base.p15_object->flags & SC_PKCS15_CO_FLAG_PRIVATE) != 0; break; case CKA_MODIFIABLE: check_attribute_buffer(attr, sizeof(CK_BBOOL)); @@ -2962,11 +2961,11 @@ pkcs15_cert_get_attribute(struct sc_pkcs11_session *session, void *object, CK_AT *(CK_CERTIFICATE_TYPE*)attr->pValue = CKC_X_509; break; case CKA_ID: - if (cert->cert_info->authority - && sc_pkcs11_conf.zero_ckaid_for_ca_certs) { + if (cert->cert_info->authority && sc_pkcs11_conf.zero_ckaid_for_ca_certs) { check_attribute_buffer(attr, 1); *(unsigned char*)attr->pValue = 0; - } else { + } + else { check_attribute_buffer(attr, cert->cert_info->id.len); memcpy(attr->pValue, cert->cert_info->id.value, cert->cert_info->id.len); } @@ -2996,15 +2995,13 @@ pkcs15_cert_get_attribute(struct sc_pkcs11_session *session, void *object, CK_AT attr->ulValueLen = 0; return CKR_OK; } - return asn1_sequence_wrapper(cert->cert_data->subject, - cert->cert_data->subject_len, attr); + return asn1_sequence_wrapper(cert->cert_data->subject, cert->cert_data->subject_len, attr); case CKA_ISSUER: if (check_cert_data_read(fw_data, cert) != 0) { attr->ulValueLen = 0; return CKR_OK; } - return asn1_sequence_wrapper(cert->cert_data->issuer, - cert->cert_data->issuer_len, attr); + return asn1_sequence_wrapper(cert->cert_data->issuer, cert->cert_data->issuer_len, attr); default: return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -3863,7 +3860,11 @@ static CK_RV pkcs15_dobj_get_attribute(struct sc_pkcs11_session *session, void *object, CK_ATTRIBUTE_PTR attr) { struct pkcs15_data_object *dobj = (struct pkcs15_data_object*) object; + struct sc_pkcs15_data *data = NULL; + CK_RV rv; size_t len; + int r; + unsigned char *buf = NULL; switch (attr->type) { case CKA_CLASS: @@ -3876,13 +3877,11 @@ pkcs15_dobj_get_attribute(struct sc_pkcs11_session *session, void *object, CK_AT break; case CKA_PRIVATE: check_attribute_buffer(attr, sizeof(CK_BBOOL)); - *(CK_BBOOL*)attr->pValue = - (dobj->base.p15_object->flags & SC_PKCS15_CO_FLAG_PRIVATE) != 0; + *(CK_BBOOL*)attr->pValue = (dobj->base.p15_object->flags & SC_PKCS15_CO_FLAG_PRIVATE) != 0; break; case CKA_MODIFIABLE: check_attribute_buffer(attr, sizeof(CK_BBOOL)); - *(CK_BBOOL*)attr->pValue = - (dobj->base.p15_object->flags & 0x02) != 0; + *(CK_BBOOL*)attr->pValue = (dobj->base.p15_object->flags & 0x02) != 0; break; case CKA_LABEL: len = strlen(dobj->base.p15_object->label); @@ -3901,28 +3900,37 @@ pkcs15_dobj_get_attribute(struct sc_pkcs11_session *session, void *object, CK_AT break; #endif case CKA_OBJECT_ID: - { - len = sizeof(dobj->info->app_oid); - - check_attribute_buffer(attr, len); - memcpy(attr->pValue, dobj->info->app_oid.value, len); + if (!sc_valid_oid(&dobj->info->app_oid)) { + attr->ulValueLen = -1; + return CKR_ATTRIBUTE_TYPE_INVALID; } + r = sc_asn1_encode_object_id(NULL, &len, &dobj->info->app_oid); + if (r) { + sc_log(context, "data_get_attr(): encode OID error %i", r); + return CKR_FUNCTION_FAILED; + } + + check_attribute_buffer(attr, len); + + r = sc_asn1_encode_object_id(&buf, &len, &dobj->info->app_oid); + if (r) { + sc_log(context, "data_get_attr(): encode OID error %i", r); + return CKR_FUNCTION_FAILED; + } + + memcpy(attr->pValue, buf, len); + free(buf); break; case CKA_VALUE: - { - CK_RV rv; - struct sc_pkcs15_data *data = NULL; - - rv = pkcs15_dobj_get_value(session, dobj, &data); - if (rv == CKR_OK) - rv = data_value_to_attr(attr, data); - if (data) { - free(data->data); - free(data); - } - if (rv != CKR_OK) - return rv; + rv = pkcs15_dobj_get_value(session, dobj, &data); + if (rv == CKR_OK) + rv = data_value_to_attr(attr, data); + if (data) { + free(data->data); + free(data); } + if (rv != CKR_OK) + return rv; break; default: return CKR_ATTRIBUTE_TYPE_INVALID; diff --git a/src/pkcs15init/pkcs15-iasecc.c b/src/pkcs15init/pkcs15-iasecc.c index c1cdc60f..f238d642 100644 --- a/src/pkcs15init/pkcs15-iasecc.c +++ b/src/pkcs15init/pkcs15-iasecc.c @@ -1384,7 +1384,7 @@ iasecc_md_gemalto_set_default(struct sc_pkcs15_card *p15card, struct sc_profile if (!data_obj) { memset(&data_args, 0, sizeof(data_args)); - data_args.app_oid.value[0] = -1; + sc_init_oid(&data_args.app_oid); data_args.label = "Default Key Container"; data_args.app_label = "CSP"; data_args.der_encoded.value = (unsigned char *)guid; @@ -1493,7 +1493,7 @@ iasecc_md_gemalto_new_prvkey(struct sc_pkcs15_card *p15card, struct sc_profile * data[offs++] = 0x01; memset(&data_args, 0, sizeof(data_args)); - data_args.app_oid.value[0] = -1; + sc_init_oid(&data_args.app_oid); data_args.label = guid; data_args.app_label = "CSP"; data_args.der_encoded.value = data; diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 26f4b599..178f46c2 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -46,6 +46,7 @@ #include "pkcs11/pkcs11.h" #include "pkcs11/pkcs11-opensc.h" +#include "libopensc/asn1.h" #include "util.h" extern void *C_LoadModule(const char *name, CK_FUNCTION_LIST_PTR_PTR); @@ -1762,6 +1763,7 @@ static int write_object(CK_SESSION_HANDLE session) struct sc_object_id oid; CK_RV rv; int need_to_parse_certdata = 0; + unsigned char *oid_buf = NULL; #ifdef ENABLE_OPENSSL struct x509cert_info cert; struct rsakey_info rsa; @@ -2002,9 +2004,15 @@ static int write_object(CK_SESSION_HANDLE session) } if (opt_application_id != NULL) { - sc_format_oid(&oid, opt_application_id); - FILL_ATTR(data_templ[n_data_attr], CKA_OBJECT_ID, - (unsigned char *)oid.value, sizeof(oid.value)); + size_t len; + + if (sc_format_oid(&oid, opt_application_id)) + util_fatal("Invalid OID \"%s\"\n", opt_application_id); + + if (sc_asn1_encode_object_id(&oid_buf, &len, &oid)) + util_fatal("Cannot encode OID \"%s\"\n", opt_application_id); + + FILL_ATTR(data_templ[n_data_attr], CKA_OBJECT_ID, oid_buf, len); n_data_attr++; } @@ -2053,6 +2061,8 @@ static int write_object(CK_SESSION_HANDLE session) show_object(session, privkey_obj); } + if (oid_buf) + free(oid_buf); return 1; } @@ -2702,8 +2712,8 @@ static void show_cert(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) static void show_dobj(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) { - int *app_oid; - char *label; + unsigned char *oid_buf; + char *label; CK_ULONG size = 0; printf("Data object %u\n", (unsigned int) obj); @@ -2726,18 +2736,20 @@ static void show_dobj(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) } printf(" app_id: "); - app_oid = (int *)getOBJECT_ID(sess, obj, &size); - if (app_oid != NULL && size) { + oid_buf = getOBJECT_ID(sess, obj, &size); + if (oid_buf != NULL && size) { unsigned int n; + struct sc_object_id oid; - size /= sizeof(int); - printf("%i", app_oid[0]); - if (app_oid[0] >= 0) - for (n = 1; (n < size) && (app_oid[n] >= 0); n++) - printf(".%i", app_oid[n]); - + sc_init_oid(&oid); + sc_asn1_decode_object_id(oid_buf, size, &oid); + printf("%i", oid.value[0]); + if (oid.value[0] >= 0) + for (n = 1; (n < SC_MAX_OBJECT_ID_OCTETS) && (oid.value[n] >= 0); n++) + printf(".%i", oid.value[n]); printf("\n"); - free(app_oid); + + free(oid_buf); } else { printf("\n"); @@ -2805,7 +2817,7 @@ static int read_object(CK_SESSION_HANDLE session) CK_OBJECT_CLASS clazz = opt_object_class; CK_OBJECT_HANDLE obj = CK_INVALID_HANDLE; int nn_attrs = 0; - unsigned char *value = NULL; + unsigned char *value = NULL, *oid_buf = NULL; CK_ULONG len = 0; FILE *out; struct sc_object_id oid; @@ -2836,9 +2848,15 @@ static int read_object(CK_SESSION_HANDLE session) } if (opt_application_id != NULL) { - sc_format_oid(&oid, opt_application_id); - FILL_ATTR(attrs[nn_attrs], CKA_OBJECT_ID, - (unsigned char *)oid.value, sizeof(oid.value)); + size_t oid_buf_len; + + if (sc_format_oid(&oid, opt_application_id)) + util_fatal("Invalid OID \"%s\"\n", opt_application_id); + + if (sc_asn1_encode_object_id(&oid_buf, &oid_buf_len, &oid)) + util_fatal("Cannot encode OID \"%s\"\n", opt_application_id); + + FILL_ATTR(attrs[nn_attrs], CKA_OBJECT_ID, oid_buf, oid_buf_len); nn_attrs++; } @@ -2886,6 +2904,9 @@ static int read_object(CK_SESSION_HANDLE session) util_fatal("cannot write to '%s'\n", opt_output); if (opt_output) fclose(out); + + if (oid_buf) + free(oid_buf); return 1; } @@ -2900,6 +2921,7 @@ static int delete_object(CK_SESSION_HANDLE session) CK_OBJECT_HANDLE obj = CK_INVALID_HANDLE; int nn_attrs = 0; struct sc_object_id oid; + unsigned char *oid_buf = NULL; if (opt_object_class_str != NULL) { FILL_ATTR(attrs[nn_attrs], CKA_CLASS, @@ -2926,9 +2948,15 @@ static int delete_object(CK_SESSION_HANDLE session) } if (opt_application_id != NULL) { - sc_format_oid(&oid, opt_application_id); - FILL_ATTR(attrs[nn_attrs], CKA_OBJECT_ID, - (unsigned char *)oid.value, sizeof(oid.value)); + size_t oid_buf_len; + + if (sc_format_oid(&oid, opt_application_id)) + util_fatal("Invalid OID '%s'\n", opt_application_id); + + if (sc_asn1_encode_object_id(&oid_buf, &oid_buf_len, &oid)) + util_fatal("Cannot encode OID \"%s\"\n", opt_application_id); + + FILL_ATTR(attrs[nn_attrs], CKA_OBJECT_ID, oid_buf, oid_buf_len); nn_attrs++; } @@ -2941,6 +2969,9 @@ static int delete_object(CK_SESSION_HANDLE session) if (rv != CKR_OK) p11_fatal("C_DestroyObject()", rv); + if (oid_buf) + free(oid_buf); + return 1; } diff --git a/src/tools/pkcs15-init.c b/src/tools/pkcs15-init.c index bd6df253..eb71c5d7 100644 --- a/src/tools/pkcs15-init.c +++ b/src/tools/pkcs15-init.c @@ -63,6 +63,7 @@ #include "libopensc/pkcs15.h" #include "libopensc/log.h" #include "libopensc/cards.h" +#include "libopensc/asn1.h" #include "pkcs15init/pkcs15-init.h" #include "pkcs15init/profile.h" #include "util.h" @@ -1189,7 +1190,7 @@ do_store_data_object(struct sc_profile *profile) int r=0; memset(&args, 0, sizeof(args)); - args.app_oid.value[0] = -1; + sc_init_oid(&args.app_oid); if (opt_objectid) sc_pkcs15_format_id(opt_objectid, &args.id); diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index 67881df8..f3385f2c 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -236,7 +236,6 @@ static void print_cert_info(const struct sc_pkcs15_object *obj) if (rv >= 0 && cert_parsed) { printf("\tEncoded serial : %02X %02X ", *(cert_parsed->serial), *(cert_parsed->serial + 1)); util_hex_dump(stdout, cert_parsed->serial + 2, cert_parsed->serial_len - 2, ""); - printf("\n"); sc_pkcs15_free_certificate(cert_parsed); } } @@ -399,9 +398,9 @@ static int read_certificate(void) static int read_data_object(void) { - int r, i, count, oid_len = 0; + int r, i, count; struct sc_pkcs15_object *objs[32]; - struct sc_object_id oid; + struct sc_object_id oid; r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_DATA_OBJECT, objs, 32); if (r < 0) { @@ -410,19 +409,15 @@ static int read_data_object(void) } count = r; - r = sc_format_oid(&oid, opt_data); - if (r == SC_SUCCESS) { - while (oid.value[oid_len] >= 0) oid_len++; - } - for (i = 0; i < count; i++) { struct sc_pkcs15_data_info *cinfo = (struct sc_pkcs15_data_info *) objs[i]->data; struct sc_pkcs15_data *data_object; - if (oid_len) { - if (memcmp(oid.value, cinfo->app_oid.value, sizeof(int) * oid_len)) + if (!sc_format_oid(&oid, opt_data)) { + if (!sc_compare_oid(&oid, &cinfo->app_oid)) continue; - } else { + } + else { if (strcmp(opt_data, cinfo->app_label) && strcmp(opt_data, objs[i]->label)) continue; } @@ -465,20 +460,18 @@ static int list_data_objects(void) int idx; struct sc_pkcs15_data_info *cinfo = (struct sc_pkcs15_data_info *) objs[i]->data; - printf("Reading data object <%i>\n", i); - printf("applicationName: %s\n", cinfo->app_label); - printf("Label: %s\n", objs[i]->label); - if (cinfo->app_oid.value[0] >= 0) { - printf("applicationOID: %i", cinfo->app_oid.value[0]); - idx = 1; - while (idx < SC_MAX_OBJECT_ID_OCTETS) { - if (cinfo->app_oid.value[idx] < 0) - break; - printf(".%i", cinfo->app_oid.value[idx++]); - } + if (objs[i]->label) + printf("Data object '%s'\n", objs[i]->label); + else + printf("Data object <%i>\n", i); + printf("\tapplicationName: %s\n", cinfo->app_label); + if (sc_valid_oid(&cinfo->app_oid)) { + printf("\tapplicationOID: %i", cinfo->app_oid.value[0]); + for (idx = 1; idx < SC_MAX_OBJECT_ID_OCTETS && cinfo->app_oid.value[idx] != -1 ; idx++) + printf(".%i", cinfo->app_oid.value[idx]); printf("\n"); } - printf("Path: %s\n", sc_print_path(&cinfo->path)); + printf("\tPath: %s\n", sc_print_path(&cinfo->path)); if (objs[i]->auth_id.len == 0) { struct sc_pkcs15_data *data_object; r = sc_pkcs15_read_data_object(p15card, cinfo, &data_object); @@ -488,11 +481,11 @@ static int list_data_objects(void) continue; /* DEE emulation may say there is a file */ return 1; } - r = list_data_object("Data Object", data_object->data, data_object->data_len); + r = list_data_object("\tData", data_object->data, data_object->data_len); sc_pkcs15_free_data_object(data_object); } else { - printf("Auth ID: %s\n", sc_pkcs15_print_id(&objs[i]->auth_id)); + printf("\tAuth ID: %s\n", sc_pkcs15_print_id(&objs[i]->auth_id)); } } return 0;