Merge pull request #1447 from Jakuje/x41sec-merge

Security issues idefnitifed by fuzzing. For more information, see the blog post:

https://www.x41-dsec.de/lab/blog/smartcards/
This commit is contained in:
Frank Morgner 2018-08-20 15:11:51 +02:00 committed by GitHub
commit fcd719d30f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 248 additions and 176 deletions

View File

@ -65,15 +65,17 @@ int sc_asn1_read_tag(const u8 ** buf, size_t buflen, unsigned int *cla_out,
size_t left = buflen, len; size_t left = buflen, len;
unsigned int cla, tag, i; unsigned int cla, tag, i;
if (left < 2)
return SC_ERROR_INVALID_ASN1_OBJECT;
*buf = NULL; *buf = NULL;
if (left == 0)
return SC_ERROR_INVALID_ASN1_OBJECT;
if (*p == 0xff || *p == 0) { if (*p == 0xff || *p == 0) {
/* end of data reached */ /* end of data reached */
*taglen = 0; *taglen = 0;
*tag_out = SC_ASN1_TAG_EOC; *tag_out = SC_ASN1_TAG_EOC;
return SC_SUCCESS; return SC_SUCCESS;
} }
/* parse tag byte(s) /* parse tag byte(s)
* Resulted tag is presented by integer that has not to be * Resulted tag is presented by integer that has not to be
* confused with the 'tag number' part of ASN.1 tag. * confused with the 'tag number' part of ASN.1 tag.
@ -86,30 +88,35 @@ int sc_asn1_read_tag(const u8 ** buf, size_t buflen, unsigned int *cla_out,
/* high tag number */ /* high tag number */
size_t n = SC_ASN1_TAGNUM_SIZE - 1; size_t n = SC_ASN1_TAGNUM_SIZE - 1;
/* search the last tag octet */ /* search the last tag octet */
while (left-- != 0 && n != 0) { do {
if (left == 0 || n == 0)
/* either an invalid tag or it doesn't fit in
* unsigned int */
return SC_ERROR_INVALID_ASN1_OBJECT;
tag <<= 8; tag <<= 8;
tag |= *p; tag |= *p;
if ((*p++ & 0x80) == 0) p++;
break; left--;
n--; n--;
} } while (tag & 0x80);
if (left == 0 || n == 0)
/* either an invalid tag or it doesn't fit in
* unsigned int */
return SC_ERROR_INVALID_ASN1_OBJECT;
} }
/* parse length byte(s) */ /* parse length byte(s) */
len = *p & 0x7f; if (left == 0)
if (*p++ & 0x80) { return SC_ERROR_INVALID_ASN1_OBJECT;
len = *p;
p++;
left--;
if (len & 0x80) {
len &= 0x7f;
unsigned int a = 0; unsigned int a = 0;
if (len > 4 || len > left) if (len > sizeof a || len > left)
return SC_ERROR_INVALID_ASN1_OBJECT; return SC_ERROR_INVALID_ASN1_OBJECT;
left -= len;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
a <<= 8; a <<= 8;
a |= *p; a |= *p;
p++; p++;
left--;
} }
len = a; len = a;
} }

View File

@ -169,7 +169,7 @@ static int asepcos_parse_sec_attr(sc_card_t *card, sc_file_t *file, const u8 *bu
while (len != 0) { while (len != 0) {
unsigned int amode, tlen = 3; unsigned int amode, tlen = 3;
if (len < 5 && p[0] != 0x80 && p[1] != 0x01) { if (len < 5 || p[0] != 0x80 || p[1] != 0x01) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "invalid access mode encoding"); sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "invalid access mode encoding");
return SC_ERROR_INTERNAL; return SC_ERROR_INTERNAL;
} }

View File

@ -560,6 +560,9 @@ authentic_set_current_files(struct sc_card *card, struct sc_path *path,
sc_file_dup(&card->cache.current_df, file); sc_file_dup(&card->cache.current_df, file);
if (cur_df_path.len) { if (cur_df_path.len) {
if (cur_df_path.len + card->cache.current_df->path.len > sizeof card->cache.current_df->path.value
|| cur_df_path.len > sizeof card->cache.current_df->path.value)
LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
memcpy(card->cache.current_df->path.value + cur_df_path.len, memcpy(card->cache.current_df->path.value + cur_df_path.len,
card->cache.current_df->path.value, card->cache.current_df->path.value,
card->cache.current_df->path.len); card->cache.current_df->path.len);
@ -988,7 +991,7 @@ authentic_process_fci(struct sc_card *card, struct sc_file *file,
} }
sc_log_hex(ctx, "ACL data", file->sec_attr, file->sec_attr_len); sc_log_hex(ctx, "ACL data", file->sec_attr, file->sec_attr_len);
for (ii = 0; ii < file->sec_attr_len / 2; ii++) { for (ii = 0; ii < file->sec_attr_len / 2 && ii < sizeof ops_DF; ii++) {
unsigned char op = file->type == SC_FILE_TYPE_DF ? ops_DF[ii] : ops_EF[ii]; unsigned char op = file->type == SC_FILE_TYPE_DF ? ops_DF[ii] : ops_EF[ii];
unsigned char acl = *(file->sec_attr + ii*2); unsigned char acl = *(file->sec_attr + ii*2);
unsigned char cred_id = *(file->sec_attr + ii*2 + 1); unsigned char cred_id = *(file->sec_attr + ii*2 + 1);

View File

@ -637,7 +637,8 @@ static int cac_read_binary(sc_card_t *card, unsigned int idx,
val_len -= len, tlv_len -= len, val_ptr += len, tlv_ptr += len) { val_len -= len, tlv_len -= len, val_ptr += len, tlv_ptr += len) {
/* get the tag and the length */ /* get the tag and the length */
tl_start = tl_ptr; tl_start = tl_ptr;
if (sc_simpletlv_read_tag(&tl_ptr, tl_len, &tag, &len) != SC_SUCCESS) r = sc_simpletlv_read_tag(&tl_ptr, tl_len, &tag, &len);
if (r != SC_SUCCESS && r != SC_ERROR_TLV_END_OF_CONTENTS)
break; break;
tl_head_len = (tl_ptr - tl_start); tl_head_len = (tl_ptr - tl_start);
sc_simpletlv_put_tag(tag, len, tlv_ptr, tlv_len, &tlv_ptr); sc_simpletlv_put_tag(tag, len, tlv_ptr, tlv_len, &tlv_ptr);
@ -646,6 +647,8 @@ static int cac_read_binary(sc_card_t *card, unsigned int idx,
/* don't crash on bad data */ /* don't crash on bad data */
if (val_len < len) { if (val_len < len) {
sc_log(card->ctx, "Received too long value %"SC_FORMAT_LEN_SIZE_T"u, "
"while only %"SC_FORMAT_LEN_SIZE_T"u left. Truncating", len, val_len);
len = val_len; len = val_len;
} }
/* if we run out of return space, truncate */ /* if we run out of return space, truncate */
@ -664,12 +667,21 @@ static int cac_read_binary(sc_card_t *card, unsigned int idx,
cert_len = 0; cert_len = 0;
cert_ptr = NULL; cert_ptr = NULL;
cert_type = 0; cert_type = 0;
for (tl_ptr = tl, val_ptr=val; tl_len >= 2; for (tl_ptr = tl, val_ptr = val; tl_len >= 2;
val_len -= len, val_ptr += len, tl_len -= tl_head_len) { val_len -= len, val_ptr += len, tl_len -= tl_head_len) {
tl_start = tl_ptr; tl_start = tl_ptr;
if (sc_simpletlv_read_tag(&tl_ptr, tl_len, &tag, &len) != SC_SUCCESS) r = sc_simpletlv_read_tag(&tl_ptr, tl_len, &tag, &len);
if (r != SC_SUCCESS && r != SC_ERROR_TLV_END_OF_CONTENTS)
break; break;
tl_head_len = tl_ptr - tl_start; tl_head_len = tl_ptr - tl_start;
/* incomplete value */
if (val_len < len) {
sc_log(card->ctx, "Read incomplete value %"SC_FORMAT_LEN_SIZE_T"u, "
"while only %"SC_FORMAT_LEN_SIZE_T"u left", len, val_len);
break;
}
if (tag == CAC_TAG_CERTIFICATE) { if (tag == CAC_TAG_CERTIFICATE) {
cert_len = len; cert_len = len;
cert_ptr = val_ptr; cert_ptr = val_ptr;
@ -682,9 +694,6 @@ static int cac_read_binary(sc_card_t *card, unsigned int idx,
if (tag == CAC_TAG_MSCUID) { if (tag == CAC_TAG_MSCUID) {
sc_log_hex(card->ctx, "MSCUID", val_ptr, len); sc_log_hex(card->ctx, "MSCUID", val_ptr, len);
} }
if ((val_len < len) || (tl_len < tl_head_len)) {
break;
}
} }
/* if the info byte is 1, then the cert is compressed, decompress it */ /* if the info byte is 1, then the cert is compressed, decompress it */
if ((cert_type & 0x3) == 1) { if ((cert_type & 0x3) == 1) {
@ -789,7 +798,7 @@ static int cac_get_serial_nr_from_CUID(sc_card_t* card, sc_serial_number_t* seri
} }
if (priv->cac_id_len) { if (priv->cac_id_len) {
serial->len = MIN(priv->cac_id_len, SC_MAX_SERIALNR); serial->len = MIN(priv->cac_id_len, SC_MAX_SERIALNR);
memcpy(serial->value, priv->cac_id, priv->cac_id_len); memcpy(serial->value, priv->cac_id, serial->len);
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS);
} }
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_FILE_NOT_FOUND); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_FILE_NOT_FOUND);
@ -1381,9 +1390,9 @@ static int cac_path_from_cardurl(sc_card_t *card, sc_path_t *path, cac_card_url_
} }
sc_mem_clear(path, sizeof(sc_path_t)); sc_mem_clear(path, sizeof(sc_path_t));
memcpy(path->aid.value, &val->rid, sizeof(val->rid)); memcpy(path->aid.value, &val->rid, sizeof(val->rid));
memcpy(&path->aid.value[5], &val->applicationID, sizeof(val->applicationID)); memcpy(&path->aid.value[5], val->applicationID, sizeof(val->applicationID));
path->aid.len = sizeof(val->rid) + sizeof(val->applicationID); path->aid.len = sizeof(val->rid) + sizeof(val->applicationID);
memcpy(path->value, &val->objectID, sizeof(val->objectID)); memcpy(path->value, val->objectID, sizeof(val->objectID));
path->len = sizeof(val->objectID); path->len = sizeof(val->objectID);
path->type = SC_PATH_TYPE_FILE_ID; path->type = SC_PATH_TYPE_FILE_ID;
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
@ -1546,8 +1555,15 @@ static int cac_parse_CCC(sc_card_t *card, cac_private_data_t *priv, u8 *tl,
for (; (tl < tl_end) && (val< val_end); val += len) { for (; (tl < tl_end) && (val< val_end); val += len) {
/* get the tag and the length */ /* get the tag and the length */
u8 tag; u8 tag;
if (sc_simpletlv_read_tag(&tl, tl_end - tl, &tag, &len) != SC_SUCCESS) r = sc_simpletlv_read_tag(&tl, tl_end - tl, &tag, &len);
if (r != SC_SUCCESS && r != SC_ERROR_TLV_END_OF_CONTENTS) {
sc_log(card->ctx, "Failed to parse tag from buffer");
break; break;
}
if (val + len > val_end) {
sc_log(card->ctx, "Invalid length %"SC_FORMAT_LEN_SIZE_T"u", len);
break;
}
switch (tag) { switch (tag) {
case CAC_TAG_CUID: case CAC_TAG_CUID:
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,"TAG:CUID"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,"TAG:CUID");

View File

@ -1129,7 +1129,7 @@ static int coolkey_read_object(sc_card_t *card, unsigned long object_id, size_t
do { do {
ulong2bebytes(&params.offset[0], offset); ulong2bebytes(&params.offset[0], offset);
params.length = MIN(left, COOLKEY_MAX_CHUNK_SIZE); params.length = MIN(left, COOLKEY_MAX_CHUNK_SIZE);
len = left+2; len = left;
r = coolkey_apdu_io(card, COOLKEY_CLASS, COOLKEY_INS_READ_OBJECT, 0, 0, r = coolkey_apdu_io(card, COOLKEY_CLASS, COOLKEY_INS_READ_OBJECT, 0, 0,
(u8 *)&params, sizeof(params), &out_ptr, &len, nonce, nonce_size); (u8 *)&params, sizeof(params), &out_ptr, &len, nonce, nonce_size);
if (r < 0) { if (r < 0) {
@ -1467,7 +1467,7 @@ coolkey_find_attribute(sc_card_t *card, sc_cardctl_coolkey_attribute_t *attribut
for (i=0; i < attribute_count; i++) { for (i=0; i < attribute_count; i++) {
size_t record_len = coolkey_get_attribute_record_len(attr, object_record_type, buf_len); size_t record_len = coolkey_get_attribute_record_len(attr, object_record_type, buf_len);
/* make sure we have the complete record */ /* make sure we have the complete record */
if (buf_len < record_len) { if (buf_len < record_len || record_len < 4) {
return SC_ERROR_CORRUPTED_DATA; return SC_ERROR_CORRUPTED_DATA;
} }
/* does the attribute match the one we are looking for */ /* does the attribute match the one we are looking for */

View File

@ -1408,13 +1408,15 @@ static int entersafe_gen_key(sc_card_t *card, sc_entersafe_gen_key_data *data)
data->modulus = malloc(len); data->modulus = malloc(len);
if (!data->modulus) if (!data->modulus)
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_OUT_OF_MEMORY); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_OUT_OF_MEMORY);
p=rbuf; p=rbuf;
assert(*p=='E'); if (*p!='E')
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
p+=2+p[1]; p+=2+p[1];
/* N */ /* N */
assert(*p=='N'); if (*p!='N')
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
++p; ++p;
if(*p++>0x80) if(*p++>0x80)
{ {

View File

@ -740,11 +740,11 @@ construct_mac_tlv(struct sc_card *card, unsigned char *apdu_buf, size_t data_tlv
memcpy(mac_tlv + 2, &mac[mac_len - 16], 8); memcpy(mac_tlv + 2, &mac[mac_len - 16], 8);
} }
else { else {
unsigned char iv[8] = { 0 }; unsigned char iv[EVP_MAX_IV_LENGTH] = { 0 };
unsigned char tmp[8] = { 0 }; unsigned char tmp[8] = { 0 };
des_encrypt_cbc(exdata->sk_mac, 8, icv, apdu_buf, mac_len, mac); des_encrypt_cbc(exdata->sk_mac, 8, icv, apdu_buf, mac_len, mac);
des_decrypt_cbc(&exdata->sk_mac[8], 8, iv, &mac[mac_len - 8], 8, tmp); des_decrypt_cbc(&exdata->sk_mac[8], 8, iv, &mac[mac_len - 8], 8, tmp);
memset(iv, 0x00, 8); memset(iv, 0x00, sizeof iv);
des_encrypt_cbc(exdata->sk_mac, 8, iv, tmp, 8, mac_tlv + 2); des_encrypt_cbc(exdata->sk_mac, 8, iv, tmp, 8, mac_tlv + 2);
} }
@ -903,9 +903,9 @@ epass2003_sm_wrap_apdu(struct sc_card *card, struct sc_apdu *plain, struct sc_ap
* SW12(TLV)=0x99|0x02|SW1+SW2 * SW12(TLV)=0x99|0x02|SW1+SW2
* MAC(TLV)=0x8e|0x08|MAC */ * MAC(TLV)=0x8e|0x08|MAC */
static int static int
decrypt_response(struct sc_card *card, unsigned char *in, unsigned char *out, size_t * out_len) decrypt_response(struct sc_card *card, unsigned char *in, size_t inlen, unsigned char *out, size_t * out_len)
{ {
size_t in_len; size_t cipher_len;
size_t i; size_t i;
unsigned char iv[16] = { 0 }; unsigned char iv[16] = { 0 };
unsigned char plaintext[4096] = { 0 }; unsigned char plaintext[4096] = { 0 };
@ -922,37 +922,40 @@ decrypt_response(struct sc_card *card, unsigned char *in, unsigned char *out, si
/* parse cipher length */ /* parse cipher length */
if (0x01 == in[2] && 0x82 != in[1]) { if (0x01 == in[2] && 0x82 != in[1]) {
in_len = in[1]; cipher_len = in[1];
i = 3; i = 3;
} }
else if (0x01 == in[3] && 0x81 == in[1]) { else if (0x01 == in[3] && 0x81 == in[1]) {
in_len = in[2]; cipher_len = in[2];
i = 4; i = 4;
} }
else if (0x01 == in[4] && 0x82 == in[1]) { else if (0x01 == in[4] && 0x82 == in[1]) {
in_len = in[2] * 0x100; cipher_len = in[2] * 0x100;
in_len += in[3]; cipher_len += in[3];
i = 5; i = 5;
} }
else { else {
return -1; return -1;
} }
/* decrypt */ if (cipher_len < 2 || i+cipher_len > inlen || cipher_len > sizeof plaintext)
if (KEY_TYPE_AES == exdata->smtype)
aes128_decrypt_cbc(exdata->sk_enc, 16, iv, &in[i], in_len - 1, plaintext);
else
des3_decrypt_cbc(exdata->sk_enc, 16, iv, &in[i], in_len - 1, plaintext);
/* unpadding */
while (0x80 != plaintext[in_len - 2] && (in_len - 2 > 0))
in_len--;
if (2 == in_len)
return -1; return -1;
memcpy(out, plaintext, in_len - 2); /* decrypt */
*out_len = in_len - 2; if (KEY_TYPE_AES == exdata->smtype)
aes128_decrypt_cbc(exdata->sk_enc, 16, iv, &in[i], cipher_len - 1, plaintext);
else
des3_decrypt_cbc(exdata->sk_enc, 16, iv, &in[i], cipher_len - 1, plaintext);
/* unpadding */
while (0x80 != plaintext[cipher_len - 2] && (cipher_len - 2 > 0))
cipher_len--;
if (2 == cipher_len || *out_len < cipher_len - 2)
return -1;
memcpy(out, plaintext, cipher_len - 2);
*out_len = cipher_len - 2;
return 0; return 0;
} }
@ -974,7 +977,8 @@ epass2003_sm_unwrap_apdu(struct sc_card *card, struct sc_apdu *sm, struct sc_apd
r = sc_check_sw(card, sm->sw1, sm->sw2); r = sc_check_sw(card, sm->sw1, sm->sw2);
if (r == SC_SUCCESS) { if (r == SC_SUCCESS) {
if (exdata->sm) { if (exdata->sm) {
if (0 != decrypt_response(card, sm->resp, plain->resp, &len)) len = plain->resplen;
if (0 != decrypt_response(card, sm->resp, sm->resplen, plain->resp, &len))
return SC_ERROR_CARD_CMD_FAILED; return SC_ERROR_CARD_CMD_FAILED;
} }
else { else {

View File

@ -409,6 +409,9 @@ gpk_parse_fileinfo(sc_card_t *card,
if (sp[0] == 0x85) { if (sp[0] == 0x85) {
unsigned int ac[3], n; unsigned int ac[3], n;
if (sp + 11 + 2*3 >= end)
break;
file->id = (sp[4] << 8) | sp[5]; file->id = (sp[4] << 8) | sp[5];
file->size = (sp[8] << 8) | sp[9]; file->size = (sp[8] << 8) | sp[9];
file->record_length = sp[7]; file->record_length = sp[7];

View File

@ -827,16 +827,16 @@ iasecc_select_file(struct sc_card *card, const struct sc_path *path,
sc_log(ctx, "iasecc_select_file() path:%s", sc_print_path(path)); sc_log(ctx, "iasecc_select_file() path:%s", sc_print_path(path));
sc_print_cache(card); sc_print_cache(card);
if (lpath.len >= 2 && lpath.value[0] == 0x3F && lpath.value[1] == 0x00) { if (path->type != SC_PATH_TYPE_DF_NAME
&& lpath.len >= 2
&& lpath.value[0] == 0x3F && lpath.value[1] == 0x00) {
sc_log(ctx, "EF.ATR(aid:'%s')", card->ef_atr ? sc_dump_hex(card->ef_atr->aid.value, card->ef_atr->aid.len) : ""); sc_log(ctx, "EF.ATR(aid:'%s')", card->ef_atr ? sc_dump_hex(card->ef_atr->aid.value, card->ef_atr->aid.len) : "");
rv = iasecc_select_mf(card, file_out); rv = iasecc_select_mf(card, file_out);
LOG_TEST_RET(ctx, rv, "MF selection error"); LOG_TEST_RET(ctx, rv, "MF selection error");
if (lpath.len >= 2 && lpath.value[0] == 0x3F && lpath.value[1] == 0x00) { memmove(&lpath.value[0], &lpath.value[2], lpath.len - 2);
memmove(&lpath.value[0], &lpath.value[2], lpath.len - 2); lpath.len -= 2;
lpath.len -= 2;
}
} }
if (lpath.aid.len) { if (lpath.aid.len) {
@ -2504,6 +2504,12 @@ iasecc_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_le
static int static int
iasecc_get_serialnr(struct sc_card *card, struct sc_serial_number *serial) iasecc_get_serialnr(struct sc_card *card, struct sc_serial_number *serial)
{ {
#if 1
/* the current implementation doesn't perform any bounds check when parsing
* the serial number. Hence, we disable this code until someone has time to
* fix this. */
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
#else
struct sc_context *ctx = card->ctx; struct sc_context *ctx = card->ctx;
struct sc_iin *iin = &card->serialnr.iin; struct sc_iin *iin = &card->serialnr.iin;
struct sc_apdu apdu; struct sc_apdu apdu;
@ -2548,7 +2554,7 @@ iasecc_get_serialnr(struct sc_card *card, struct sc_serial_number *serial)
if (card->type == SC_CARD_TYPE_IASECC_SAGEM) { if (card->type == SC_CARD_TYPE_IASECC_SAGEM) {
/* 5A 0A 92 50 00 20 10 10 25 00 01 3F */ /* 5A 0A 92 50 00 20 10 10 25 00 01 3F */
/* 00 02 01 01 02 50 00 13 */ /* 00 02 01 01 02 50 00 13 */
for (ii=0; ii < rbuf[1] - offs; ii++) for (ii=0; (ii < rbuf[1] - offs) && (ii + offs + 2 < sizeof(rbuf)); ii++)
*(card->serialnr.value + ii) = ((rbuf[ii + offs + 1] & 0x0F) << 4) *(card->serialnr.value + ii) = ((rbuf[ii + offs + 1] & 0x0F) << 4)
+ ((rbuf[ii + offs + 2] & 0xF0) >> 4) ; + ((rbuf[ii + offs + 2] & 0xF0) >> 4) ;
card->serialnr.len = ii; card->serialnr.len = ii;
@ -2573,6 +2579,7 @@ end:
memcpy(serial, &card->serialnr, sizeof(*serial)); memcpy(serial, &card->serialnr, sizeof(*serial));
LOG_FUNC_RETURN(ctx, SC_SUCCESS); LOG_FUNC_RETURN(ctx, SC_SUCCESS);
#endif
} }

View File

@ -149,7 +149,8 @@ static struct df_info_s *get_df_info(sc_card_t * card)
struct mcrd_priv_data *priv = DRVDATA(card); struct mcrd_priv_data *priv = DRVDATA(card);
struct df_info_s *dfi; struct df_info_s *dfi;
assert(!priv->is_ef); if(!(!priv->is_ef))
return NULL;
if (!priv->curpathlen) { if (!priv->curpathlen) {
sc_log(ctx, "no current path to find the df_info\n"); sc_log(ctx, "no current path to find the df_info\n");
@ -202,7 +203,8 @@ static int mcrd_delete_ref_to_authkey(sc_card_t * card)
int r; int r;
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
assert(card != NULL); if(!(card != NULL))
return SC_ERROR_INTERNAL;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xA4); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xA4);
sbuf[0] = 0x83; sbuf[0] = 0x83;
@ -220,7 +222,8 @@ static int mcrd_delete_ref_to_signkey(sc_card_t * card)
sc_apdu_t apdu; sc_apdu_t apdu;
int r; int r;
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
assert(card != NULL); if(!(card != NULL))
return SC_ERROR_INTERNAL;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xB6); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xB6);
@ -242,7 +245,8 @@ static int mcrd_set_decipher_key_ref(sc_card_t * card, int key_reference)
int r; int r;
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
u8 keyref_data[SC_ESTEID_KEYREF_FILE_RECLEN]; u8 keyref_data[SC_ESTEID_KEYREF_FILE_RECLEN];
assert(card != NULL); if(!(card != NULL))
return SC_ERROR_INTERNAL;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xB8); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xB8);
/* track the active keypair */ /* track the active keypair */
@ -956,7 +960,8 @@ select_file_by_path(sc_card_t * card, unsigned short *pathptr,
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
assert(!priv->curpathlen || priv->curpath[0] == MFID); if (!(!priv->curpathlen || priv->curpath[0] == MFID))
return SC_ERROR_INTERNAL;
if (pathlen && *pathptr == 0x3FFF) { if (pathlen && *pathptr == 0x3FFF) {
pathlen--; pathlen--;
@ -997,7 +1002,8 @@ select_file_by_path(sc_card_t * card, unsigned short *pathptr,
/* This EF or DF was already selected, but /* This EF or DF was already selected, but
we need to get the FCI, so we have we need to get the FCI, so we have
to select again. */ to select again. */
assert(priv->curpathlen > 1); if (!(priv->curpathlen > 1))
return SC_ERROR_INTERNAL;
priv->curpathlen--; priv->curpathlen--;
priv->is_ef = 0; priv->is_ef = 0;
r = select_down(card, pathptr + pathlen - 1, 1, r = select_down(card, pathptr + pathlen - 1, 1,
@ -1022,7 +1028,8 @@ select_file_by_path(sc_card_t * card, unsigned short *pathptr,
priv->is_ef = 0; priv->is_ef = 0;
} }
if (priv->is_ef) { if (priv->is_ef) {
assert(priv->curpathlen > 1); if(!(priv->curpathlen > 1))
return SC_ERROR_INTERNAL;
priv->curpathlen--; priv->curpathlen--;
priv->is_ef = 0; priv->is_ef = 0;
} }
@ -1040,7 +1047,8 @@ select_file_by_fid(sc_card_t * card, unsigned short *pathptr,
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
assert(!priv->curpathlen || priv->curpath[0] == MFID); if (!(!priv->curpathlen || priv->curpath[0] == MFID))
return SC_ERROR_INTERNAL;
if (pathlen > 1) if (pathlen > 1)
return SC_ERROR_INVALID_ARGUMENTS; return SC_ERROR_INVALID_ARGUMENTS;
@ -1056,7 +1064,8 @@ select_file_by_fid(sc_card_t * card, unsigned short *pathptr,
/* There is no current file. */ /* There is no current file. */
r = SC_ERROR_INTERNAL; r = SC_ERROR_INTERNAL;
} else { } else {
assert(priv->curpathlen > 1); if (!(priv->curpathlen > 1))
return SC_ERROR_INTERNAL;
priv->curpathlen--; priv->curpathlen--;
priv->is_ef = 0; priv->is_ef = 0;
r = select_down(card, pathptr, 1, 0, file); r = select_down(card, pathptr, 1, 0, file);
@ -1081,7 +1090,8 @@ select_file_by_fid(sc_card_t * card, unsigned short *pathptr,
priv->is_ef = 0; priv->is_ef = 0;
} }
if (priv->is_ef) { if (priv->is_ef) {
assert(priv->curpathlen > 1); if (!(priv->curpathlen > 1))
return SC_ERROR_INTERNAL;
priv->curpathlen--; priv->curpathlen--;
priv->is_ef = 0; priv->is_ef = 0;
} }
@ -1209,7 +1219,8 @@ static int mcrd_set_security_env(sc_card_t * card,
u8 *p; u8 *p;
int r, locked = 0; int r, locked = 0;
assert(card != NULL && env != NULL); if (!(card != NULL && env != NULL))
return SC_ERROR_INTERNAL;
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_NORMAL); SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_NORMAL);
/* special environment handling for esteid, stolen from openpgp */ /* special environment handling for esteid, stolen from openpgp */

View File

@ -518,7 +518,9 @@ static int muscle_list_files(sc_card_t *card, u8 *buf, size_t bufLen)
mscfs_check_cache(priv->fs); mscfs_check_cache(priv->fs);
for(x = 0; x < fs->cache.size; x++) { for(x = 0; x < fs->cache.size; x++) {
u8* oid= fs->cache.array[x].objectId.id; u8* oid = fs->cache.array[x].objectId.id;
if (bufLen < 2)
break;
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
"FILE: %02X%02X%02X%02X\n", "FILE: %02X%02X%02X%02X\n",
oid[0],oid[1],oid[2],oid[3]); oid[0],oid[1],oid[2],oid[3]);
@ -527,7 +529,8 @@ static int muscle_list_files(sc_card_t *card, u8 *buf, size_t bufLen)
buf[1] = oid[3]; buf[1] = oid[3];
if(buf[0] == 0x00 && buf[1] == 0x00) continue; /* No directories/null names outside of root */ if(buf[0] == 0x00 && buf[1] == 0x00) continue; /* No directories/null names outside of root */
buf += 2; buf += 2;
count+=2; count += 2;
bufLen -= 2;
} }
} }
return count; return count;

View File

@ -476,6 +476,9 @@ auth_select_file(struct sc_card *card, const struct sc_path *in_path,
memcpy(&path, in_path, sizeof(struct sc_path)); memcpy(&path, in_path, sizeof(struct sc_path));
if (!auth_current_df)
return SC_ERROR_OBJECT_NOT_FOUND;
sc_log(card->ctx, "in_path; type=%d, path=%s, out %p", sc_log(card->ctx, "in_path; type=%d, path=%s, out %p",
in_path->type, sc_print_path(in_path), file_out); in_path->type, sc_print_path(in_path), file_out);
sc_log(card->ctx, "current path; type=%d, path=%s", sc_log(card->ctx, "current path; type=%d, path=%s",
@ -2113,6 +2116,10 @@ auth_read_binary(struct sc_card *card, unsigned int offset,
bn[1].data = NULL; bn[1].data = NULL;
LOG_FUNC_CALLED(card->ctx); LOG_FUNC_CALLED(card->ctx);
if (!auth_current_ef)
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Invalid auth_current_ef");
sc_log(card->ctx, sc_log(card->ctx,
"offset %i; size %"SC_FORMAT_LEN_SIZE_T"u; flags 0x%lX", "offset %i; size %"SC_FORMAT_LEN_SIZE_T"u; flags 0x%lX",
offset, count, flags); offset, count, flags);

View File

@ -623,13 +623,19 @@ pgp_get_card_features(sc_card_t *card)
/* category indicator 0x00, 0x10 or 0x80 => compact TLV (ISO) */ /* category indicator 0x00, 0x10 or 0x80 => compact TLV (ISO) */
switch (hist_bytes[0]) { switch (hist_bytes[0]) {
case 0x00: case 0x00:
pgp_parse_hist_bytes(card, hist_bytes+1, hist_bytes_len-4); if (hist_bytes_len > 4) {
pgp_parse_hist_bytes(card, hist_bytes+1, hist_bytes_len-4);
}
break; break;
case 0x80: case 0x80:
pgp_parse_hist_bytes(card, hist_bytes+1, hist_bytes_len-1); if (hist_bytes_len > 1) {
pgp_parse_hist_bytes(card, hist_bytes+1, hist_bytes_len-1);
}
break; break;
case 0x10: case 0x10:
pgp_parse_hist_bytes(card, hist_bytes+2, hist_bytes_len-2); if (hist_bytes_len > 2) {
pgp_parse_hist_bytes(card, hist_bytes+2, hist_bytes_len-2);
}
break; break;
} }
} }
@ -642,7 +648,9 @@ pgp_get_card_features(sc_card_t *card)
if ((pgp_get_blob(card, priv->mf, 0x5f52, &blob) >= 0) && if ((pgp_get_blob(card, priv->mf, 0x5f52, &blob) >= 0) &&
(blob->data != NULL) && (blob->data[0] == 0x00)) { (blob->data != NULL) && (blob->data[0] == 0x00)) {
pgp_parse_hist_bytes(card, hist_bytes+1, hist_bytes_len-4); if (hist_bytes_len > 4) {
pgp_parse_hist_bytes(card, hist_bytes+1, hist_bytes_len-4);
}
/* get card status from historical bytes status indicator */ /* get card status from historical bytes status indicator */
if ((blob->data[0] == 0x00) && (blob->len >= 4)) { if ((blob->data[0] == 0x00) && (blob->len >= 4)) {
@ -1061,6 +1069,9 @@ pgp_enumerate_blob(sc_card_t *card, pgp_blob_t *blob)
const u8 *data = in; const u8 *data = in;
pgp_blob_t *new; pgp_blob_t *new;
if (!in)
return SC_ERROR_OBJECT_NOT_VALID;
r = sc_asn1_read_tag(&data, blob->len - (in - blob->data), r = sc_asn1_read_tag(&data, blob->len - (in - blob->data),
&cla, &tag, &len); &cla, &tag, &len);
if (r < 0 || data == NULL) { if (r < 0 || data == NULL) {
@ -1069,6 +1080,9 @@ pgp_enumerate_blob(sc_card_t *card, pgp_blob_t *blob)
return SC_ERROR_OBJECT_NOT_VALID; return SC_ERROR_OBJECT_NOT_VALID;
} }
if (data + len > blob->data + blob->len)
return SC_ERROR_OBJECT_NOT_VALID;
/* undo ASN1's split of tag & class */ /* undo ASN1's split of tag & class */
for (tmptag = tag; tmptag > 0x0FF; tmptag >>= 8) { for (tmptag = tag; tmptag > 0x0FF; tmptag >>= 8) {
cla <<= 8; cla <<= 8;

View File

@ -147,7 +147,6 @@ enum {
}; };
typedef struct piv_private_data { typedef struct piv_private_data {
sc_file_t *aid_file;
int enumtag; int enumtag;
int selected_obj; /* The index into the piv_objects last selected */ int selected_obj; /* The index into the piv_objects last selected */
int return_only_cert; /* return the cert from the object */ int return_only_cert; /* return the cert from the object */
@ -573,7 +572,7 @@ static int piv_general_io(sc_card_t *card, int ins, int p1, int p2,
* the buffer is bigger, so it will not produce "ASN1.tag too long!" */ * the buffer is bigger, so it will not produce "ASN1.tag too long!" */
body = rbuf; body = rbuf;
if (sc_asn1_read_tag(&body, 0xffff, &cla_out, &tag_out, &bodylen) != SC_SUCCESS if (sc_asn1_read_tag(&body, rbuflen, &cla_out, &tag_out, &bodylen) != SC_SUCCESS
|| body == NULL) { || body == NULL) {
/* only early beta cards had this problem */ /* only early beta cards had this problem */
sc_log(card->ctx, "***** received buffer tag MISSING "); sc_log(card->ctx, "***** received buffer tag MISSING ");
@ -758,10 +757,9 @@ static int piv_select_aid(sc_card_t* card, u8* aid, size_t aidlen, u8* response,
/* find the PIV AID on the card. If card->type already filled in, /* find the PIV AID on the card. If card->type already filled in,
* then look for specific AID only * then look for specific AID only
* Assumes that priv may not be present
*/ */
static int piv_find_aid(sc_card_t * card, sc_file_t *aid_file) static int piv_find_aid(sc_card_t * card)
{ {
sc_apdu_t apdu; sc_apdu_t apdu;
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
@ -842,8 +840,6 @@ static int piv_find_aid(sc_card_t * card, sc_file_t *aid_file)
if (apdu.resp[0] != 0x6f || apdu.resp[1] > apdu.resplen - 2 ) if (apdu.resp[0] != 0x6f || apdu.resp[1] > apdu.resplen - 2 )
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NO_CARD_SUPPORT); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NO_CARD_SUPPORT);
card->ops->process_fci(card, aid_file, apdu.resp+2, apdu.resp[1]);
LOG_FUNC_RETURN(card->ctx, i); LOG_FUNC_RETURN(card->ctx, i);
} }
@ -2373,15 +2369,15 @@ static int piv_validate_general_authentication(sc_card_t *card,
r = piv_general_io(card, 0x87, real_alg_id, priv->key_ref, r = piv_general_io(card, 0x87, real_alg_id, priv->key_ref,
sbuf, p - sbuf, &rbuf, &rbuflen); sbuf, p - sbuf, &rbuf, &rbuflen);
if ( r >= 0) { if (r >= 0) {
body = sc_asn1_find_tag(card->ctx, rbuf, rbuflen, 0x7c, &bodylen); body = sc_asn1_find_tag(card->ctx, rbuf, rbuflen, 0x7c, &bodylen);
if (body) { if (body) {
tag = sc_asn1_find_tag(card->ctx, body, bodylen, 0x82, &taglen); tag = sc_asn1_find_tag(card->ctx, body, bodylen, 0x82, &taglen);
if (tag) { if (tag) {
memcpy(out, tag, taglen); memcpy(out, tag, taglen);
r = taglen; r = taglen;
} } else
r = SC_ERROR_INVALID_DATA;
} else } else
r = SC_ERROR_INVALID_DATA; r = SC_ERROR_INVALID_DATA;
} }
@ -2924,7 +2920,6 @@ piv_finish(sc_card_t *card)
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
if (priv) { if (priv) {
sc_file_free(priv->aid_file);
if (priv->w_buf) if (priv->w_buf)
free(priv->w_buf); free(priv->w_buf);
if (priv->offCardCertURL) if (priv->offCardCertURL)
@ -3033,12 +3028,13 @@ static int piv_match_card_continued(sc_card_t *card)
* 73 66 74 65 20 63 64 31 34 34 * 73 66 74 65 20 63 64 31 34 34
* will check for 73 66 74 65 * will check for 73 66 74 65
*/ */
else if (card->reader->atr_info.hist_bytes_len >= 4 && else if (card->reader->atr_info.hist_bytes_len >= 4
!(memcmp(card->reader->atr_info.hist_bytes, "sfte", 4))) { && !(memcmp(card->reader->atr_info.hist_bytes, "sfte", 4))) {
type = SC_CARD_TYPE_PIV_II_GI_DE; type = SC_CARD_TYPE_PIV_II_GI_DE;
} }
else if (card->reader->atr_info.hist_bytes[0] == 0x80u) { /* compact TLV */ else if (card->reader->atr_info.hist_bytes_len > 0
&& card->reader->atr_info.hist_bytes[0] == 0x80u) { /* compact TLV */
size_t datalen; size_t datalen;
const u8 *data = sc_compacttlv_find_tag(card->reader->atr_info.hist_bytes + 1, const u8 *data = sc_compacttlv_find_tag(card->reader->atr_info.hist_bytes + 1,
card->reader->atr_info.hist_bytes_len - 1, card->reader->atr_info.hist_bytes_len - 1,
@ -3072,7 +3068,6 @@ static int piv_match_card_continued(sc_card_t *card)
card->type = type; card->type = type;
card->drv_data = priv; /* will free if no match, or pass on to piv_init */ card->drv_data = priv; /* will free if no match, or pass on to piv_init */
priv->aid_file = sc_file_new();
priv->selected_obj = -1; priv->selected_obj = -1;
priv->pin_preference = 0x80; /* 800-73-3 part 1, table 3 */ priv->pin_preference = 0x80; /* 800-73-3 part 1, table 3 */
priv->logged_in = SC_PIN_STATE_UNKNOWN; priv->logged_in = SC_PIN_STATE_UNKNOWN;
@ -3099,9 +3094,7 @@ static int piv_match_card_continued(sc_card_t *card)
if (i < 0) { if (i < 0) {
/* Detect by selecting applet */ /* Detect by selecting applet */
sc_file_t aidfile; i = piv_find_aid(card);
i = piv_find_aid(card, &aidfile);
} }
if (i >= 0) { if (i >= 0) {
@ -3487,7 +3480,7 @@ piv_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left)
/* if access to applet is know to be reset by other driver we select_aid and try again */ /* if access to applet is know to be reset by other driver we select_aid and try again */
if ( priv->card_issues & CI_OTHER_AID_LOSE_STATE && priv->pin_cmd_verify_sw1 == 0x6DU) { if ( priv->card_issues & CI_OTHER_AID_LOSE_STATE && priv->pin_cmd_verify_sw1 == 0x6DU) {
sc_log(card->ctx, "AID may be lost doing piv_find_aid and retry pin_cmd"); sc_log(card->ctx, "AID may be lost doing piv_find_aid and retry pin_cmd");
piv_find_aid(card, priv->aid_file); /* return not tested */ piv_find_aid(card);
priv->pin_cmd_verify = 1; /* tell piv_check_sw its a verify to save sw1, sw2 */ priv->pin_cmd_verify = 1; /* tell piv_check_sw its a verify to save sw1, sw2 */
r = iso_drv->ops->pin_cmd(card, data, tries_left); r = iso_drv->ops->pin_cmd(card, data, tries_left);

View File

@ -275,7 +275,7 @@ static int rtecp_select_file(sc_card_t *card,
set_acl_from_sec_attr(card, file); set_acl_from_sec_attr(card, file);
else else
r = SC_ERROR_UNKNOWN_DATA_RECEIVED; r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
if (r) if (r && !file_out)
sc_file_free(file); sc_file_free(file);
else else
{ {

View File

@ -788,15 +788,17 @@ static void parse_sec_attr_44(sc_file_t *file, const u8 *buf, size_t len)
/* Check all sub-AC definitions within the total AC */ /* Check all sub-AC definitions within the total AC */
while (len > 1) { /* minimum length = 2 */ while (len > 1) { /* minimum length = 2 */
int iACLen = buf[iOffset] & 0x0F; size_t iACLen = buf[iOffset] & 0x0F;
if (iACLen > len)
break;
iPinCount = -1; /* default no pin required */ iPinCount = -1; /* default no pin required */
iMethod = SC_AC_NONE; /* default no authentication required */ iMethod = SC_AC_NONE; /* default no authentication required */
if (buf[iOffset] & 0X80) { /* AC in adaptive coding */ if (buf[iOffset] & 0X80) { /* AC in adaptive coding */
/* Evaluates only the command-byte, not the optional P1/P2/Option bytes */ /* Evaluates only the command-byte, not the optional P1/P2/Option bytes */
int iParmLen = 1; /* command-byte is always present */ size_t iParmLen = 1; /* command-byte is always present */
int iKeyLen = 0; /* Encryption key is optional */ size_t iKeyLen = 0; /* Encryption key is optional */
if (buf[iOffset] & 0x20) iKeyLen++; if (buf[iOffset] & 0x20) iKeyLen++;
if (buf[iOffset+1] & 0x40) iParmLen++; if (buf[iOffset+1] & 0x40) iParmLen++;
@ -806,7 +808,10 @@ static void parse_sec_attr_44(sc_file_t *file, const u8 *buf, size_t len)
/* Get KeyNumber if available */ /* Get KeyNumber if available */
if(iKeyLen) { if(iKeyLen) {
int iSC = buf[iOffset+iACLen]; int iSC;
if (len < 1+(size_t)iACLen)
break;
iSC = buf[iOffset+iACLen];
switch( (iSC>>5) & 0x03 ){ switch( (iSC>>5) & 0x03 ){
case 0: case 0:
@ -825,11 +830,15 @@ static void parse_sec_attr_44(sc_file_t *file, const u8 *buf, size_t len)
/* Get PinNumber if available */ /* Get PinNumber if available */
if (iACLen > (1+iParmLen+iKeyLen)) { /* check via total length if pin is present */ if (iACLen > (1+iParmLen+iKeyLen)) { /* check via total length if pin is present */
if (len < 1+1+1+(size_t)iParmLen)
break;
iKeyRef = buf[iOffset+1+1+iParmLen]; /* PTL + AM-header + parameter-bytes */ iKeyRef = buf[iOffset+1+1+iParmLen]; /* PTL + AM-header + parameter-bytes */
iMethod = SC_AC_CHV; iMethod = SC_AC_CHV;
} }
/* Convert SETCOS command to OpenSC command group */ /* Convert SETCOS command to OpenSC command group */
if (len < 1+2)
break;
switch(buf[iOffset+2]){ switch(buf[iOffset+2]){
case 0x2A: /* crypto operation */ case 0x2A: /* crypto operation */
iOperation = SC_AC_OP_CRYPTO; iOperation = SC_AC_OP_CRYPTO;
@ -863,7 +872,10 @@ static void parse_sec_attr_44(sc_file_t *file, const u8 *buf, size_t len)
iPinCount = iACLen - 1; iPinCount = iACLen - 1;
if (buf[iOffset] & 0x20) { if (buf[iOffset] & 0x20) {
int iSC = buf[iOffset + iACLen]; int iSC;
if (len < 1 + (size_t)iACLen)
break;
iSC = buf[iOffset + iACLen];
switch( (iSC>>5) & 0x03 ) { switch( (iSC>>5) & 0x03 ) {
case 0: case 0:
@ -884,6 +896,8 @@ static void parse_sec_attr_44(sc_file_t *file, const u8 *buf, size_t len)
/* Pin present ? */ /* Pin present ? */
if ( iPinCount > 0 ) { if ( iPinCount > 0 ) {
if (len < 1 + 2)
break;
iKeyRef = buf[iOffset + 2]; /* pin ref */ iKeyRef = buf[iOffset + 2]; /* pin ref */
iMethod = SC_AC_CHV; iMethod = SC_AC_CHV;
} }

View File

@ -343,7 +343,6 @@ static int tcos_select_file(sc_card_t *card,
sc_apdu_t apdu; sc_apdu_t apdu;
sc_file_t *file=NULL; sc_file_t *file=NULL;
u8 buf[SC_MAX_APDU_BUFFER_SIZE], pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf; u8 buf[SC_MAX_APDU_BUFFER_SIZE], pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf;
unsigned int i;
int r, pathlen; int r, pathlen;
assert(card != NULL && in_path != NULL); assert(card != NULL && in_path != NULL);
@ -407,42 +406,7 @@ static int tcos_select_file(sc_card_t *card,
*file_out = file; *file_out = file;
file->path = *in_path; file->path = *in_path;
for(i=2; i+1<apdu.resplen && i+1+apdu.resp[i+1]<apdu.resplen; i+=2+apdu.resp[i+1]){ iso_ops->process_fci(card, file, apdu.resp, apdu.resplen);
int j, len=apdu.resp[i+1];
unsigned char type=apdu.resp[i], *d=apdu.resp+i+2;
switch (type) {
case 0x80:
case 0x81:
file->size=0;
for(j=0; j<len; ++j) file->size = (file->size<<8) | d[j];
break;
case 0x82:
file->shareable = (d[0] & 0x40) ? 1 : 0;
file->ef_structure = d[0] & 7;
switch ((d[0]>>3) & 7) {
case 0: file->type = SC_FILE_TYPE_WORKING_EF; break;
case 7: file->type = SC_FILE_TYPE_DF; break;
default:
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "invalid file type %02X in file descriptor\n", d[0]);
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_UNKNOWN_DATA_RECEIVED);
}
break;
case 0x83:
file->id = (d[0]<<8) | d[1];
break;
case 0x84:
memcpy(file->name, d, len);
file->namelen = len;
break;
case 0x86:
sc_file_set_sec_attr(file, d, len);
break;
default:
if (len>0) sc_file_set_prop_attr(file, d, len);
}
}
file->magic = SC_FILE_MAGIC;
parse_sec_attr(card, file, file->sec_attr, file->sec_attr_len); parse_sec_attr(card, file, file->sec_attr, file->sec_attr_len);

View File

@ -72,7 +72,7 @@ sc_parse_ef_gdo_content(const unsigned char *gdo, size_t gdo_len,
} }
p += tag_len; p += tag_len;
left -= (p - gdo); left = gdo_len - (p - gdo);
} }
if (!iccsn_found && iccsn_len) if (!iccsn_found && iccsn_len)

View File

@ -104,6 +104,8 @@ const char *sc_strerror(int error)
"Unable to load external module", "Unable to load external module",
"EF offset too large", "EF offset too large",
"Not implemented" "Not implemented"
"Invalid Simple TLV object",
"Premature end of Simple TLV stream",
}; };
const int int_base = -SC_ERROR_INTERNAL; const int int_base = -SC_ERROR_INTERNAL;

View File

@ -95,6 +95,8 @@ extern "C" {
#define SC_ERROR_CANNOT_LOAD_MODULE -1414 #define SC_ERROR_CANNOT_LOAD_MODULE -1414
#define SC_ERROR_OFFSET_TOO_LARGE -1415 #define SC_ERROR_OFFSET_TOO_LARGE -1415
#define SC_ERROR_NOT_IMPLEMENTED -1416 #define SC_ERROR_NOT_IMPLEMENTED -1416
#define SC_ERROR_INVALID_TLV_OBJECT -1417
#define SC_ERROR_TLV_END_OF_CONTENTS -1418
/* Relating to PKCS #15 init stuff */ /* Relating to PKCS #15 init stuff */
#define SC_ERROR_PKCS15INIT -1500 #define SC_ERROR_PKCS15INIT -1500

View File

@ -79,7 +79,7 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card)
/* read the serial (document number) */ /* read the serial (document number) */
r = sc_read_record (card, SC_ESTEID_PD_DOCUMENT_NR, buff, sizeof(buff), SC_RECORD_BY_REC_NR); r = sc_read_record (card, SC_ESTEID_PD_DOCUMENT_NR, buff, sizeof(buff), SC_RECORD_BY_REC_NR);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "read document number failed"); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "read document number failed");
buff[r] = '\0'; buff[MIN((size_t) r, (sizeof buff)-1)] = '\0';
set_string (&p15card->tokeninfo->serial_number, (const char *) buff); set_string (&p15card->tokeninfo->serial_number, (const char *) buff);
p15card->tokeninfo->flags = SC_PKCS15_TOKEN_PRN_GENERATION p15card->tokeninfo->flags = SC_PKCS15_TOKEN_PRN_GENERATION

View File

@ -208,7 +208,7 @@ static int gemsafe_get_cert_len(sc_card_t *card)
* the private key. * the private key.
*/ */
ind = 2; /* skip length */ ind = 2; /* skip length */
while (ibuf[ind] == 0x01) { while (ibuf[ind] == 0x01 && i < gemsafe_cert_max) {
if (ibuf[ind+1] == 0xFE) { if (ibuf[ind+1] == 0xFE) {
gemsafe_prkeys[i].ref = ibuf[ind+4]; gemsafe_prkeys[i].ref = ibuf[ind+4];
sc_log(card->ctx, "Key container %d is allocated and uses key_ref %d", sc_log(card->ctx, "Key container %d is allocated and uses key_ref %d",

View File

@ -550,6 +550,7 @@ static int itacns_add_data_files(sc_pkcs15_card_t *p15card)
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,
"Could not read EF_DatiPersonali: " "Could not read EF_DatiPersonali: "
"keeping generic card name"); "keeping generic card name");
return SC_SUCCESS;
} }
{ {

View File

@ -837,12 +837,14 @@ static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card)
r = read_file(p15card, (u8 *) "\x2F\x02", efbin, &len, 1); r = read_file(p15card, (u8 *) "\x2F\x02", efbin, &len, 1);
LOG_TEST_RET(card->ctx, r, "Skipping optional EF.C_DevAut"); LOG_TEST_RET(card->ctx, r, "Skipping optional EF.C_DevAut");
/* save EF_C_DevAut for further use */ if (len > 0) {
ptr = realloc(priv->EF_C_DevAut, len); /* save EF_C_DevAut for further use */
if (ptr) { ptr = realloc(priv->EF_C_DevAut, len);
memcpy(ptr, efbin, len); if (ptr) {
priv->EF_C_DevAut = ptr; memcpy(ptr, efbin, len);
priv->EF_C_DevAut_len = len; priv->EF_C_DevAut = ptr;
priv->EF_C_DevAut_len = len;
}
} }
ptr = efbin; ptr = efbin;

View File

@ -157,7 +157,8 @@ static int insert_key(
if(buf[i]==0xB8) can_crypt++; if(buf[i]==0xB8) can_crypt++;
} }
} else { } else {
if(sc_select_file(card, &prkey_info.path, &f)!=SC_SUCCESS){ if(sc_select_file(card, &prkey_info.path, &f)!=SC_SUCCESS
|| !f->prop_attr || f->prop_attr_len < 2){
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
"Select(%s) failed\n", "Select(%s) failed\n",
sc_print_path(&prkey_info.path)); sc_print_path(&prkey_info.path));
@ -245,7 +246,8 @@ static int insert_pin(
return 1; return 1;
} }
} else { } else {
if(sc_select_file(card, &pin_info.path, &f)!=SC_SUCCESS){ if(sc_select_file(card, &pin_info.path, &f)!=SC_SUCCESS
|| !f->prop_attr || f->prop_attr_len < 4){
sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"Select(%s) failed\n", path); sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"Select(%s) failed\n", path);
return 1; return 1;
} }

View File

@ -628,7 +628,7 @@ int sc_file_set_sec_attr(sc_file_t *file, const u8 *sec_attr,
return SC_ERROR_INVALID_ARGUMENTS; return SC_ERROR_INVALID_ARGUMENTS;
} }
if (sec_attr == NULL) { if (sec_attr == NULL || sec_attr_len) {
if (file->sec_attr != NULL) if (file->sec_attr != NULL)
free(file->sec_attr); free(file->sec_attr);
file->sec_attr = NULL; file->sec_attr = NULL;

View File

@ -74,27 +74,38 @@ sc_simpletlv_put_tag(u8 tag, size_t datalen, u8 *out, size_t outlen, u8 **ptr)
int int
sc_simpletlv_read_tag(u8 **buf, size_t buflen, u8 *tag_out, size_t *taglen) sc_simpletlv_read_tag(u8 **buf, size_t buflen, u8 *tag_out, size_t *taglen)
{ {
size_t len; u8 tag;
size_t left = buflen, len;
u8 *p = *buf; u8 *p = *buf;
if (buflen < 2) { *buf = NULL;
*buf = p+buflen;
return SC_ERROR_INVALID_ARGUMENTS; if (left < 2) {
} return SC_ERROR_INVALID_TLV_OBJECT;
}
tag = *p;
p++;
len = *p;
p++;
left -= 2;
*tag_out = *p++;
len = *p++;
if (len == 0xff) { if (len == 0xff) {
/* don't crash on bad data */ /* don't crash on bad data */
if (buflen < 4) { if (left < 2) {
*taglen = 0; return SC_ERROR_INVALID_TLV_OBJECT;
return SC_ERROR_INVALID_ARGUMENTS;
} }
/* skip two bytes (the size) */ /* skip two bytes (the size) */
len = lebytes2ushort(p); len = lebytes2ushort(p);
p+=2; p += 2;
left -= 2;
} }
*tag_out = tag;
*taglen = len; *taglen = len;
*buf = p; *buf = p;
if (len > left)
return SC_ERROR_TLV_END_OF_CONTENTS;
return SC_SUCCESS; return SC_SUCCESS;
} }

View File

@ -21,6 +21,7 @@
#include "config.h" #include "config.h"
#include "libopensc/sc-ossl-compat.h" #include "libopensc/sc-ossl-compat.h"
#include "libopensc/internal.h"
#include <openssl/bn.h> #include <openssl/bn.h>
#include <openssl/rsa.h> #include <openssl/rsa.h>
#include <openssl/x509.h> #include <openssl/x509.h>
@ -331,7 +332,7 @@ static int read_public_key(RSA *rsa)
fprintf(stderr, "Unable to select public key file: %s\n", sc_strerror(r)); fprintf(stderr, "Unable to select public key file: %s\n", sc_strerror(r));
return 2; return 2;
} }
bufsize = file->size; bufsize = MIN(file->size, sizeof buf);
sc_file_free(file); sc_file_free(file);
r = sc_read_binary(card, 0, buf, bufsize, 0); r = sc_read_binary(card, 0, buf, bufsize, 0);
if (r < 0) { if (r < 0) {
@ -382,7 +383,7 @@ static int read_private_key(RSA *rsa)
e = sc_file_get_acl_entry(file, SC_AC_OP_READ); e = sc_file_get_acl_entry(file, SC_AC_OP_READ);
if (e == NULL || e->method == SC_AC_NEVER) if (e == NULL || e->method == SC_AC_NEVER)
return 10; return 10;
bufsize = file->size; bufsize = MIN(file->size, sizeof buf);
sc_file_free(file); sc_file_free(file);
r = sc_read_binary(card, 0, buf, bufsize, 0); r = sc_read_binary(card, 0, buf, bufsize, 0);
if (r < 0) { if (r < 0) {

View File

@ -149,7 +149,7 @@ int read_file(struct sc_card *card, char *str_path, unsigned char **data, size_t
goto err; goto err;
} }
len = file ? file->size : 4096; len = file && file->size > 0 ? file->size : 4096;
p = realloc(*data, len); p = realloc(*data, len);
if (!p) { if (!p) {
goto err; goto err;

View File

@ -457,7 +457,7 @@ static int enum_dir(sc_path_t path, int depth)
{ {
sc_file_t *file; sc_file_t *file;
int r, file_type; int r, file_type;
u8 files[SC_MAX_APDU_BUFFER_SIZE]; u8 files[SC_MAX_EXT_APDU_BUFFER_SIZE];
r = sc_lock(card); r = sc_lock(card);
if (r == SC_SUCCESS) if (r == SC_SUCCESS)
@ -483,15 +483,16 @@ static int enum_dir(sc_path_t path, int depth)
} }
if (r == 0) { if (r == 0) {
printf("Empty directory\n"); printf("Empty directory\n");
} else } else {
for (i = 0; i < r/2; i++) { for (i = 0; i < r/2; i++) {
sc_path_t tmppath; sc_path_t tmppath;
memset(&tmppath, 0, sizeof(tmppath)); memset(&tmppath, 0, sizeof(tmppath));
memcpy(&tmppath, &path, sizeof(path)); memcpy(&tmppath, &path, sizeof(path));
memcpy(tmppath.value + tmppath.len, files + 2*i, 2); memcpy(tmppath.value + tmppath.len, files + 2*i, 2);
tmppath.len += 2; tmppath.len += 2;
enum_dir(tmppath, depth + 1); enum_dir(tmppath, depth + 1);
}
} }
} }
return 0; return 0;

View File

@ -31,6 +31,7 @@
#include <ctype.h> #include <ctype.h>
#include "util.h" #include "util.h"
#include "ui/notify.h" #include "ui/notify.h"
#include "common/compat_strlcat.h"
int int
is_string_valid_atr(const char *atr_str) is_string_valid_atr(const char *atr_str)
@ -339,10 +340,11 @@ const char * util_acl_to_str(const sc_acl_entry_t *e)
strcpy(buf, "????"); strcpy(buf, "????");
break; break;
} }
strcat(line, buf); strlcat(line, buf, sizeof line);
strcat(line, " "); strlcat(line, " ", sizeof line);
e = e->next; e = e->next;
} }
line[(sizeof line)-1] = '\0'; /* make sure it's NUL terminated */
line[strlen(line)-1] = 0; /* get rid of trailing space */ line[strlen(line)-1] = 0; /* get rid of trailing space */
return line; return line;
} }