From 5113a5ed02da3d16d2a683f08663ae9a9ecb4b41 Mon Sep 17 00:00:00 2001 From: Dave Pate Date: Tue, 22 Jan 2019 08:17:45 -0800 Subject: [PATCH] lib: tlv length buffer checks --- lib/internal.h | 1 + lib/ykpiv.c | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/lib/internal.h b/lib/internal.h index 4f0dac7..83d1b91 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -193,6 +193,7 @@ ykpiv_rc _ykpiv_ensure_application_selected(ykpiv_state *state); ykpiv_rc _ykpiv_select_application(ykpiv_state *state); unsigned int _ykpiv_set_length(unsigned char *buffer, size_t length); unsigned int _ykpiv_get_length(const unsigned char *buffer, size_t *len); +bool _ykpiv_has_valid_length(const unsigned char* buffer, size_t len); void* _ykpiv_alloc(ykpiv_state *state, size_t size); void* _ykpiv_realloc(ykpiv_state *state, void *address, size_t size); diff --git a/lib/ykpiv.c b/lib/ykpiv.c index 258fa0a..700ccc3 100644 --- a/lib/ykpiv.c +++ b/lib/ykpiv.c @@ -186,6 +186,19 @@ unsigned int _ykpiv_get_length(const unsigned char *buffer, size_t *len) { return 0; } +bool _ykpiv_has_valid_length(const unsigned char* buffer, size_t len) { + if ((buffer[0] < 0x81) && (len > 0)) { + return true; + } + else if (((*buffer & 0x7f) == 1) && (len > 1)) { + return true; + } + else if (((*buffer & 0x7f) == 2) && (len > 2)) { + return true; + } + return false; +} + static unsigned char *set_object(int object_id, unsigned char *buffer) { *buffer++ = 0x5c; if(object_id == YKPIV_OBJ_DISCOVERY) { @@ -1514,8 +1527,14 @@ ykpiv_rc _ykpiv_fetch_object(ykpiv_state *state, int object_id, } if(sw == SW_SUCCESS) { - size_t outlen; - unsigned int offs = _ykpiv_get_length(data + 1, &outlen); + size_t outlen = 0; + unsigned int offs = 0; + + if ((*len < 2) || !_ykpiv_has_valid_length(data + 1, *len - 1)) { + return YKPIV_SIZE_ERROR; + } + + offs = _ykpiv_get_length(data + 1, &outlen); if(offs == 0) { return YKPIV_SIZE_ERROR; }