static int iso7816_process_fci(struct sc_card *card, struct sc_file *file, const unsigned char *buf, size_t buflen) { struct sc_context *ctx = card->ctx; size_t taglen, len = buflen; int i; const unsigned char *tag = NULL, *p = buf; sc_log(ctx, "processing FCI bytes"); tag = sc_asn1_find_tag(ctx, p, len, 0x83, &taglen); if (tag != NULL && taglen == 2) { file->id = (tag[0] << 8) | tag[1]; sc_log(ctx, " file identifier: 0x%02X%02X", tag[0], tag[1]); } /* determine the file size */ /* try the tag 0x80 then the tag 0x81 */ file->size = 0; for (i = 0x80; i <= 0x81; i++) { int size = 0; len = buflen; tag = sc_asn1_find_tag(ctx, p, len, i, &taglen); if (tag == NULL) continue; if (taglen == 0) continue; if (sc_asn1_decode_integer(tag, taglen, &size) < 0) continue; if (size <0) continue; file->size = size; sc_log(ctx, " bytes in file: %d", file->size); break; } tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen); if (tag != NULL) { if (taglen > 0) { unsigned char byte = tag[0]; const char *type; file->shareable = byte & 0x40 ? 1 : 0; sc_log(ctx, " shareable: %s", (byte & 0x40) ? "yes" : "no"); file->ef_structure = byte & 0x07; switch ((byte >> 3) & 7) { case 0: type = "working EF"; file->type = SC_FILE_TYPE_WORKING_EF; break; case 1: type = "internal EF"; file->type = SC_FILE_TYPE_INTERNAL_EF; break; case 7: type = "DF"; file->type = SC_FILE_TYPE_DF; break; default: type = "unknown"; break; } sc_log(ctx, " type: %s", type); sc_log(ctx, " EF structure: %d", byte & 0x07); } }
static int iso7816_process_fci(struct sc_card *card, struct sc_file *file, const unsigned char *buf, size_t buflen) { struct sc_context *ctx = card->ctx; const unsigned char *p, *end; unsigned int cla = 0, tag = 0; size_t length; int size; for (p = buf, length = buflen, end = buf + buflen; p < end; p += length, length = end - p) { if (SC_SUCCESS != sc_asn1_read_tag(&p, length, &cla, &tag, &length) || p == NULL) { break; } switch (cla | tag) { case 0x81: if (file->size != 0) { /* don't overwrite existing file size excluding structural information */ break; } /* fall through */ case 0x80: /* determine the file size */ if (sc_asn1_decode_integer(p, length, &size) == 0 && size >= 0) { file->size = size; sc_log(ctx, " bytes in file: %"SC_FORMAT_LEN_SIZE_T"u", file->size); } break; case 0x82: if (length > 0) { unsigned char byte = p[0]; const char *type; file->shareable = byte & 0x40 ? 1 : 0; sc_log(ctx, " shareable: %s", (byte & 0x40) ? "yes" : "no"); file->ef_structure = byte & 0x07; switch ((byte >> 3) & 7) { case 0: type = "working EF"; file->type = SC_FILE_TYPE_WORKING_EF; break; case 1: type = "internal EF"; file->type = SC_FILE_TYPE_INTERNAL_EF; break; case 7: type = "DF"; file->type = SC_FILE_TYPE_DF; break; default: type = "unknown"; break; } sc_log(ctx, " type: %s", type); sc_log(ctx, " EF structure: %d", byte & 0x07); sc_log(ctx, " tag 0x82: 0x%02x", byte); if (SC_SUCCESS != sc_file_set_type_attr(file, &byte, 1)) sc_log(ctx, "Warning: Could not set file attributes"); } break; case 0x83: if (length == 2) { file->id = (p[0] << 8) | p[1]; sc_log(ctx, " file identifier: 0x%02X%02X", p[0], p[1]); } break; case 0x84: if (length > 0 && length <= 16) { memcpy(file->name, p, length); file->namelen = length; sc_log_hex(ctx, " File name:", file->name, file->namelen); if (!file->type) file->type = SC_FILE_TYPE_DF; } break; case 0x85: case 0xA5: if (SC_SUCCESS != sc_file_set_prop_attr(file, p, length)) { sc_log(ctx, "Warning: Could not set proprietary file properties"); } break; case 0x86: if (SC_SUCCESS != sc_file_set_sec_attr(file, p, length)) { sc_log(ctx, "Warning: Could not set file security properties"); } break; case 0x88: if (length == 1) { file->sid = *p; sc_log(ctx, " short file identifier: 0x%02X", *p); } break; case 0x8A: if (length == 1) { if (p[0] == 0x01) file->status = SC_FILE_STATUS_CREATION; else if (p[0] == 0x07 || p[0] == 0x05) file->status = SC_FILE_STATUS_ACTIVATED; else if (p[0] == 0x06 || p[0] == 0x04) file->status = SC_FILE_STATUS_INVALIDATED; } break; case 0x62: case 0x64: case 0x6F: /* allow nested FCP/FMD/FCI templates */ iso7816_process_fci(card, file, p, length); } }