diff --git a/src/asn1.c b/src/asn1.c
index b114d7b..a08c3d6 100644
--- a/src/asn1.c
+++ b/src/asn1.c
@@ -15,8 +15,40 @@
* along with this program. If not, see .
*/
+#include "pico_keys.h"
#include "asn1.h"
+int asn1_ctx_init(uint8_t *data, uint16_t len, asn1_ctx_t *ctx) {
+ if (!ctx) {
+ return CCID_ERR_NULL_PARAM;
+ }
+ ctx->data = data;
+ ctx->len = 0;
+ return CCID_OK;
+}
+
+int asn1_ctx_clear(asn1_ctx_t *ctx) {
+ ctx->data = NULL;
+ ctx->len = 0;
+ return CCID_OK;
+}
+
+uint16_t asn1_len(asn1_ctx_t *ctx) {
+ if (ctx->data && ctx->len > 0) {
+ return ctx->len;
+ }
+ return 0;
+}
+
+uint32_t asn1_get_uint(asn1_ctx_t *ctx) {
+ uint32_t d = ctx->data[0];
+ for (uint8_t lt = 1; lt < ctx->len; lt++) {
+ d <<= 8;
+ d |= ctx->data[lt];
+ }
+ return d;
+}
+
uint16_t asn1_len_tag(uint16_t tag, uint16_t len) {
uint16_t ret = 1 + format_tlv_len(len, NULL) + len;
if (tag > 0x00ff) {
@@ -47,8 +79,7 @@ uint8_t format_tlv_len(uint16_t len, uint8_t *out) {
return 3;
}
-int walk_tlv(const uint8_t *cdata,
- uint16_t cdata_len,
+int walk_tlv(const asn1_ctx_t *ctxi,
uint8_t **p,
uint16_t *tag,
uint16_t *tag_len,
@@ -57,9 +88,9 @@ int walk_tlv(const uint8_t *cdata,
return 0;
}
if (!*p) {
- *p = (uint8_t *) cdata;
+ *p = (uint8_t *) ctxi->data;
}
- if (*p - cdata >= cdata_len) {
+ if (*p - ctxi->data >= ctxi->len) {
return 0;
}
uint16_t tg = 0x0;
@@ -90,22 +121,18 @@ int walk_tlv(const uint8_t *cdata,
return 1;
}
-bool asn1_find_tag(const uint8_t *data,
- uint16_t data_len,
+bool asn1_find_tag(const asn1_ctx_t *ctxi,
uint16_t itag,
- uint16_t *tag_len,
- uint8_t **tag_data) {
+ asn1_ctx_t *ctxo) {
uint16_t tag = 0x0;
uint8_t *p = NULL;
uint8_t *tdata = NULL;
uint16_t tlen = 0;
- while (walk_tlv(data, data_len, &p, &tag, &tlen, &tdata)) {
+ while (walk_tlv(ctxi, &p, &tag, &tlen, &tdata)) {
if (itag == tag) {
- if (tag_data != NULL) {
- *tag_data = tdata;
- }
- if (tag_len != NULL) {
- *tag_len = tlen;
+ if (ctxo != NULL) {
+ ctxo->data = tdata;
+ ctxo->len = tlen;
}
return true;
}
diff --git a/src/asn1.h b/src/asn1.h
index 474cb6d..3d4c5e1 100644
--- a/src/asn1.h
+++ b/src/asn1.h
@@ -26,18 +26,25 @@
#include
#endif
-extern int walk_tlv(const uint8_t *cdata,
- uint16_t cdata_len,
+typedef struct asn1_ctx {
+ uint8_t *data;
+ uint16_t len;
+} asn1_ctx_t;
+
+extern int asn1_ctx_init(uint8_t *, uint16_t, asn1_ctx_t *);
+extern int asn1_ctx_clear(asn1_ctx_t *ctx);
+extern uint16_t asn1_len(asn1_ctx_t *ctx);
+extern uint32_t asn1_get_uint(asn1_ctx_t *ctx);
+
+extern int walk_tlv(const asn1_ctx_t *ctxi,
uint8_t **p,
uint16_t *tag,
uint16_t *tag_len,
uint8_t **data);
extern uint8_t format_tlv_len(uint16_t len, uint8_t *out);
-extern bool asn1_find_tag(const uint8_t *data,
- uint16_t data_len,
+extern bool asn1_find_tag(const asn1_ctx_t *ctxi,
uint16_t itag,
- uint16_t *tag_len,
- uint8_t **tag_data);
+ asn1_ctx_t *ctxo);
extern uint16_t asn1_len_tag(uint16_t tag, uint16_t len);
#endif
diff --git a/src/eac.c b/src/eac.c
index 1d0ddf8..77181da 100644
--- a/src/eac.c
+++ b/src/eac.c
@@ -113,7 +113,10 @@ int sm_unwrap() {
uint16_t tag = 0x0;
uint8_t *tag_data = NULL, *p = NULL;
uint16_t tag_len = 0;
- while (walk_tlv(apdu.data, (uint16_t)apdu.nc, &p, &tag, &tag_len, &tag_data)) {
+ asn1_ctx_t ctxi;
+ asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
+ while (walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data))
+ {
if (tag == 0x87 || tag == 0x85) {
body = tag_data;
body_size = tag_len;
@@ -209,7 +212,9 @@ uint16_t sm_get_le() {
uint16_t tag = 0x0;
uint8_t *tag_data = NULL, *p = NULL;
uint16_t tag_len = 0;
- while (walk_tlv(apdu.data, (uint16_t)apdu.nc, &p, &tag, &tag_len, &tag_data)) {
+ asn1_ctx_t ctxi;
+ asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
+ while (walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data)) {
if (tag == 0x97) {
uint16_t le = 0;
for (uint16_t t = 1; t <= tag_len; t++) {
@@ -266,7 +271,9 @@ int sm_verify() {
uint16_t tag = 0x0;
uint8_t *tag_data = NULL, *p = NULL;
uint16_t tag_len = 0;
- while (walk_tlv(apdu.data, (uint16_t)apdu.nc, &p, &tag, &tag_len, &tag_data)) {
+ asn1_ctx_t ctxi;
+ asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
+ while (walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data)) {
if (tag & 0x1) {
input[input_len++] = (uint8_t)tag;
uint8_t tlen = format_tlv_len(tag_len, input + input_len);
diff --git a/src/fs/file.c b/src/fs/file.c
index 93be707..c6fad0c 100644
--- a/src/fs/file.c
+++ b/src/fs/file.c
@@ -358,9 +358,11 @@ uint16_t meta_find(uint16_t fid, uint8_t **out) {
return 0;
}
uint16_t tag = 0x0;
- uint8_t *tag_data = NULL, *p = NULL, *data = file_get_data(ef);
- uint16_t tag_len = 0, data_len = file_get_size(ef);
- while (walk_tlv(data, data_len, &p, &tag, &tag_len, &tag_data)) {
+ uint8_t *tag_data = NULL, *p = NULL;
+ uint16_t tag_len = 0;
+ asn1_ctx_t ctxi;
+ asn1_ctx_init(file_get_data(ef), file_get_size(ef), &ctxi);
+ while (walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data)) {
if (tag_len < 2) {
continue;
}
@@ -380,27 +382,29 @@ int meta_delete(uint16_t fid) {
return CCID_ERR_FILE_NOT_FOUND;
}
uint16_t tag = 0x0;
- uint8_t *tag_data = NULL, *p = NULL, *data = file_get_data(ef);
- uint16_t tag_len = 0, data_len = file_get_size(ef);
+ uint8_t *tag_data = NULL, *p = NULL;
+ uint16_t tag_len = 0;
uint8_t *fdata = NULL;
- while (walk_tlv(data, data_len, &p, &tag, &tag_len, &tag_data)) {
+ asn1_ctx_t ctxi;
+ asn1_ctx_init(file_get_data(ef), file_get_size(ef), &ctxi);
+ while (walk_tlv(&ctxi, &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) {
- uint16_t new_len = data_len - 1 - tag_len - format_tlv_len(tag_len, NULL);
+ uint16_t new_len = ctxi.len - 1 - tag_len - format_tlv_len(tag_len, NULL);
if (new_len == 0) {
flash_clear_file(ef);
}
else {
fdata = (uint8_t *) calloc(1, new_len);
- if (tpos > data) {
- memcpy(fdata, data, tpos - data);
+ if (tpos > ctxi.data) {
+ memcpy(fdata, ctxi.data, tpos - ctxi.data);
}
- if (data + data_len > p) {
- memcpy(fdata + (tpos - data), p, data + data_len - p);
+ if (ctxi.data + ctxi.len > p) {
+ memcpy(fdata + (tpos - ctxi.data), p, ctxi.data + ctxi.len - p);
}
int r = flash_write_data_to_file(ef, fdata, new_len);
free(fdata);
@@ -426,7 +430,9 @@ int meta_add(uint16_t fid, const uint8_t *data, uint16_t len) {
uint16_t tag = 0x0;
uint8_t *tag_data = NULL, *p = NULL;
uint16_t tag_len = 0;
- while (walk_tlv(fdata, ef_size, &p, &tag, &tag_len, &tag_data)) {
+ asn1_ctx_t ctxi;
+ asn1_ctx_init(fdata, ef_size, &ctxi);
+ while (walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data)) {
if (tag_len < 2) {
continue;
}