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:
commit
fcd719d30f
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -1129,7 +1129,7 @@ static int coolkey_read_object(sc_card_t *card, unsigned long object_id, size_t
|
||||||
do {
|
do {
|
||||||
ulong2bebytes(¶ms.offset[0], offset);
|
ulong2bebytes(¶ms.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 *)¶ms, sizeof(params), &out_ptr, &len, nonce, nonce_size);
|
(u8 *)¶ms, 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 */
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue