Add meta functions for manipulating meta data.

Added meta_add(), meta_delete() and meta_find().
It conveys this meta data throught tag A5 of FCP.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos 2022-05-24 14:42:54 +02:00
parent 1a58422cd8
commit 6c90ce3361
No known key found for this signature in database
GPG key ID: C0095B7870A4CCD3
2 changed files with 87 additions and 17 deletions

View file

@ -23,6 +23,7 @@
extern const uintptr_t end_data_pool;
extern const uintptr_t start_data_pool;
extern int flash_write_data_to_file(file_t *file, const uint8_t *data, uint16_t len);
extern int flash_write_data_to_file_offset(file_t *file, const uint8_t *data, uint16_t len, uint16_t offset);
extern int flash_program_halfword (uintptr_t addr, uint16_t data);
extern int flash_program_word (uintptr_t addr, uint32_t data);
extern int flash_program_uintptr (uintptr_t addr, uintptr_t data);
@ -84,6 +85,13 @@ void process_fci(const file_t *pe) {
}
memcpy(res_APDU+res_APDU_size, "\x8A\x01\x05", 3); //life-cycle (5 -> activated)
res_APDU_size += 3;
uint8_t meta_size = meta_find(pe->fid, res_APDU+res_APDU_size+3, 256);
if (meta_size) {
res_APDU[res_APDU_size++] = 0xA5;
res_APDU[res_APDU_size++] = 0x81;
res_APDU[res_APDU_size++] = meta_size;
res_APDU_size += meta_size;
}
res_APDU[1] = res_APDU_size-2;
res_APDU[3] = res_APDU_size-4;
}
@ -184,15 +192,6 @@ bool authenticate_action(const file_t *ef, uint8_t op) {
return false;
}
void initialize_chain(file_chain_t **chain) {
file_chain_t *next;
for (file_chain_t *f = *chain; f; f = next) {
next = f->next;
free(f);
}
*chain = NULL;
}
void initialize_flash(bool hard) {
if (hard) {
const uint8_t empty[8] = { 0 };
@ -300,3 +299,77 @@ file_t *file_new(uint16_t fid) {
//memset((uint8_t *)f->acl, 0x90, sizeof(f->acl));
return f;
}
int meta_find(uint16_t fid, uint8_t *out, size_t out_len) {
file_t *ef = search_by_fid(EF_META, NULL, SPECIFY_EF);
if (!ef)
return CCID_ERR_FILE_NOT_FOUND;
uint8_t tag = 0x0, *tag_data = NULL, *p = NULL, *data = file_get_data(ef);
size_t tag_len = 0, data_len = file_get_size(ef);
while (walk_tlv(data, data_len, &p, &tag, &tag_len, &tag_data)) {
if (tag_len < 2)
continue;
uint16_t cfid = (tag_data[0] << 8 | tag_data[1]);
if (cfid == fid) {
if (out) {
if (out_len < tag_len-2)
return CCID_ERR_NO_MEMORY;
memcpy(out, tag_data+2, tag_len-2);
}
return tag_len-2;
}
}
return 0;
}
int meta_delete(uint16_t fid) {
file_t *ef = search_by_fid(EF_META, NULL, SPECIFY_EF);
if (!ef)
return CCID_ERR_FILE_NOT_FOUND;
uint8_t tag = 0x0, *tag_data = NULL, *p = NULL, *data = file_get_data(ef);
size_t tag_len = 0, data_len = file_get_size(ef);
uint8_t *fdata = NULL;
while (walk_tlv(data, data_len, &p, &tag, &tag_len, &tag_data)) {
uint8_t *tpos = p-tag_len-format_tlv_len(tag_len, NULL)-1;
if (tag_len < 2)
continue;
uint16_t cfid = (tag_data[0] << 8 | tag_data[1]);
if (cfid == fid) {
size_t new_len = data_len-1-tag_len-format_tlv_len(tag_len, NULL);
fdata = (uint8_t *)calloc(1, new_len);
if (tpos > data) {
memcpy(fdata, data, tpos-data);
}
if (data+data_len > p) {
memcpy(fdata+(tpos-data), p, data+data_len-p);
}
int r = flash_write_data_to_file(ef, fdata, new_len);
free(fdata);
if (r != CCID_OK)
return CCID_EXEC_ERROR;
low_flash_available();
break;
}
}
return CCID_OK;
}
int meta_add(uint16_t fid, const uint8_t *data, uint16_t len) {
int r;
file_t *ef = search_by_fid(EF_META, NULL, SPECIFY_EF);
if (!ef)
return CCID_ERR_FILE_NOT_FOUND;
if ((r = meta_delete(fid)) != CCID_OK)
return r;
size_t fdata_len = 1+format_tlv_len(len+2, NULL)+len+2;
uint8_t *fdata = (uint8_t *)calloc(1, fdata_len), *f = fdata;
*f++ = fid & 0xff;
f += format_tlv_len(len, f);
*f++ = fid >> 8;
*f++ = fid & 0xff;
memcpy(f, data, len);
r = flash_write_data_to_file(ef, fdata, fdata_len);
free(fdata);
if (r != CCID_OK)
return CCID_EXEC_ERROR;
low_flash_available();
return CCID_OK;
}

View file

@ -59,6 +59,7 @@
#define EF_AODFS 0x6043
#define EF_DODFS 0x6044
#define EF_SKDFS 0x6045
#define EF_META 0xE010
#define MAX_DEPTH 4
@ -73,12 +74,6 @@ typedef struct file
const uint8_t acl[7];
} __attribute__((packed)) file_t;
typedef struct file_chain
{
file_t *file;
struct file_chain *next;
} file_chain_t;
extern file_t *currentEF;
extern file_t *currentDF;
extern const file_t *selected_applet;
@ -116,9 +111,11 @@ extern file_t dynamic_file[];
extern file_t *search_dynamic_file(uint16_t);
extern int delete_dynamic_file(file_t *f);
extern file_chain_t *add_file_to_chain(file_t *file, file_chain_t **chain);
extern file_t *search_file_chain(uint16_t fid, file_chain_t *chain);
extern bool isUserAuthenticated;
extern int meta_find(uint16_t, uint8_t *out, size_t out_len);
extern int meta_delete(uint16_t fid);
extern int meta_add(uint16_t fid, const uint8_t *data, uint16_t len);
#endif