diff --git a/src/libopensc/pkcs15-cache.c b/src/libopensc/pkcs15-cache.c index 490434c8..30f6a4a8 100644 --- a/src/libopensc/pkcs15-cache.c +++ b/src/libopensc/pkcs15-cache.c @@ -67,9 +67,9 @@ int sc_pkcs15_read_cached_file(struct sc_pkcs15_card *p15card, u8 **buf, size_t *bufsize) { char fname[160]; - int r; + int r, got; FILE *f; - size_t c; + size_t count, offset; struct stat stbuf; u8 *data = NULL; @@ -79,13 +79,22 @@ int sc_pkcs15_read_cached_file(struct sc_pkcs15_card *p15card, r = stat(fname, &stbuf); if (r) return SC_ERROR_FILE_NOT_FOUND; - c = stbuf.st_size; + if (path->count < 0) { + count = stbuf.st_size; + offset = 0; + } else { + count = path->count; + offset = path->index; + if (offset >= stbuf.st_size + || offset + count >= stbuf.st_size) + return SC_ERROR_FILE_NOT_FOUND; /* cache file bad? */ + } if (*buf == NULL) { data = (u8 *) malloc(stbuf.st_size); if (data == NULL) return SC_ERROR_OUT_OF_MEMORY; } else - if (c > *bufsize) + if (count > *bufsize) return SC_ERROR_BUFFER_TOO_SMALL; f = fopen(fname, "r"); if (f == NULL) { @@ -93,16 +102,18 @@ int sc_pkcs15_read_cached_file(struct sc_pkcs15_card *p15card, free(data); return SC_ERROR_FILE_NOT_FOUND; } + if (offset) + fseek(f, offset, SEEK_SET); if (data) *buf = data; - c = fread(*buf, 1, c, f); + got = fread(*buf, 1, count, f); fclose(f); - if (c != stbuf.st_size) { + if (got != count) { if (data) free(data); return SC_ERROR_BUFFER_TOO_SMALL; } - *bufsize = c; + *bufsize = count; if (data) *buf = data; return 0; diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index 61bd2fde..f9c9f0df 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -948,11 +948,12 @@ int sc_pkcs15_read_file(struct sc_pkcs15_card *p15card, { struct sc_file *file; u8 *data = NULL; - size_t len = 0; + size_t len = 0, offset = 0; int r = -1; assert(p15card != NULL && path != NULL && buf != NULL); SC_FUNC_CALLED(p15card->card->ctx, 1); + if (p15card->opts.use_cache) { r = sc_pkcs15_read_cached_file(p15card, path, &data, &len); } @@ -964,7 +965,21 @@ int sc_pkcs15_read_file(struct sc_pkcs15_card *p15card, sc_unlock(p15card->card); return r; } - len = file->size; + /* Handle the case where the ASN.1 Path object specified + * index and length values */ + if (path->count < 0) { + len = file->size; + offset = 0; + } else { + offset = path->index; + len = path->count; + /* Make sure we're within proper bounds */ + if (offset >= file->size + || offset + len >= file->size) { + sc_unlock(p15card->card); + return SC_ERROR_INVALID_ASN1_OBJECT; + } + } if (file_out != NULL) *file_out = file; else @@ -974,7 +989,7 @@ int sc_pkcs15_read_file(struct sc_pkcs15_card *p15card, sc_unlock(p15card->card); return SC_ERROR_OUT_OF_MEMORY; } - r = sc_read_binary(p15card->card, 0, data, len, 0); + r = sc_read_binary(p15card->card, offset, data, len, 0); if (r < 0) { sc_unlock(p15card->card); free(data);