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 :
8e75d971cb (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
This commit is contained in:
Viktor Tarasov 2012-09-02 00:12:57 +02:00
parent d5ee8a80b5
commit 58b4304957
15 changed files with 297 additions and 222 deletions

View File

@ -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;i<SC_MAX_OBJECT_ID_OCTETS;i++)
si.owner.value[i] = -1;
sc_init_oid(&si.owner);
ses[idx] = calloc(1, sizeof(sc_pkcs15_sec_env_info_t));
if (ses[idx] == NULL) {
@ -996,6 +1001,7 @@ static int asn1_decode_se_info(sc_context_t *ctx, const u8 *obj, size_t objlen,
ret = SC_SUCCESS;
err:
if (ret != SC_SUCCESS) {
int i;
for (i = 0; i < idx; i++)
if (ses[i])
free(ses[i]);
@ -1022,7 +1028,7 @@ static int asn1_encode_se_info(sc_context_t *ctx,
sc_copy_asn1_entry(c_asn1_se_info, asn1_se_info);
sc_format_asn1_entry(asn1_se_info + 0, &se[idx]->se, 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);

View File

@ -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) {

View File

@ -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

View File

@ -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,

View File

@ -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)

View File

@ -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);

View File

@ -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");
}

View File

@ -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;

View File

@ -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; ii<SC_MAX_OBJECT_ID_OCTETS; ii++)
oid->value[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; ii<SC_MAX_OBJECT_ID_OCTETS; ii++)
oid->value[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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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("<empty>\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;
}

View File

@ -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);

View File

@ -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;