From 6c90ce3361bc54fa091739728db116e6c69412f1 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 24 May 2022 14:42:54 +0200 Subject: [PATCH] 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 --- src/fs/file.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++----- src/fs/file.h | 13 +++----- 2 files changed, 87 insertions(+), 17 deletions(-) diff --git a/src/fs/file.c b/src/fs/file.c index 135278a..53d1a99 100644 --- a/src/fs/file.c +++ b/src/fs/file.c @@ -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; +} + diff --git a/src/fs/file.h b/src/fs/file.h index 89f96bf..4486eab 100644 --- a/src/fs/file.h +++ b/src/fs/file.h @@ -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