Changed ASN1 calls for easier calls.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos 2024-03-13 17:16:35 +01:00
parent caddf87c23
commit f88e786c04
No known key found for this signature in database
GPG key ID: C0095B7870A4CCD3
4 changed files with 82 additions and 35 deletions

View file

@ -15,8 +15,40 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#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;
}

View file

@ -26,18 +26,25 @@
#include <stdbool.h>
#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

View file

@ -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);

View file

@ -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;
}