static int read_file(sc_pkcs15_card_t * p15card, u8 fid[2], u8 *efbin, size_t *len) { sc_path_t path; int r; sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, 2, 0, 0); /* look this up with our AID */ path.aid = sc_hsm_aid; /* we don't have a pre-known size of the file */ path.count = -1; if (!p15card->opts.use_file_cache || SC_SUCCESS != sc_pkcs15_read_cached_file(p15card, &path, &efbin, len)) { /* avoid re-selection of SC-HSM */ path.aid.len = 0; r = sc_select_file(p15card->card, &path, NULL); LOG_TEST_RET(p15card->card->ctx, r, "Could not select EF"); r = sc_read_binary(p15card->card, 0, efbin, *len, 0); LOG_TEST_RET(p15card->card->ctx, r, "Could not read EF"); *len = r; if (p15card->opts.use_file_cache) { /* save this with our AID */ path.aid = sc_hsm_aid; sc_pkcs15_cache_file(p15card, &path, efbin, *len); } } return SC_SUCCESS; }
int sc_pkcs15_read_file(struct sc_pkcs15_card *p15card, const sc_path_t *in_path, u8 **buf, size_t *buflen, sc_file_t **file_out) { sc_file_t *file = NULL; u8 *data = NULL; size_t len = 0, offset = 0; int r; assert(p15card != NULL && in_path != NULL && buf != NULL); if (p15card->card->ctx->debug >= 1) { char pbuf[SC_MAX_PATH_STRING_SIZE]; r = sc_path_print(pbuf, sizeof(pbuf), in_path); if (r != SC_SUCCESS) pbuf[0] = '\0'; sc_debug(p15card->card->ctx, "called, path=%s, index=%u, count=%d\n", pbuf, in_path->index, in_path->count); } r = -1; /* file state: not in cache */ if (p15card->opts.use_cache) { r = sc_pkcs15_read_cached_file(p15card, in_path, &data, &len); } if (r) { r = sc_lock(p15card->card); SC_TEST_RET(p15card->card->ctx, r, "sc_lock() failed"); r = sc_select_file(p15card->card, in_path, &file); if (r) goto fail_unlock; /* Handle the case where the ASN.1 Path object specified * index and length values */ if (in_path->count < 0) { len = file->size; offset = 0; } else { offset = in_path->index; len = in_path->count; /* Make sure we're within proper bounds */ if (offset >= file->size || offset + len > file->size) { r = SC_ERROR_INVALID_ASN1_OBJECT; goto fail_unlock; } } data = (u8 *) malloc(len); if (data == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto fail_unlock; } if (file->ef_structure == SC_FILE_EF_LINEAR_VARIABLE_TLV) { int i; size_t l, record_len; unsigned char *head; head = data; for (i=1; ; i++) { l = len - (head - data); if (l > 256) { l = 256; } p15card->card->ctx->suppress_errors++; r = sc_read_record(p15card->card, i, head, l, SC_RECORD_BY_REC_NR); p15card->card->ctx->suppress_errors--; if (r == SC_ERROR_RECORD_NOT_FOUND) break; if (r < 0) { free(data); goto fail_unlock; } if (r < 2) break; record_len = head[1]; if (record_len != 0xff) { memmove(head,head+2,r-2); head += (r-2); } else { if (r < 4) break; record_len = head[2] * 256 + head[3]; memmove(head,head+4,r-4); head += (r-4); } } len = head-data; r = len; } else { r = sc_read_binary(p15card->card, offset, data, len, 0); if (r < 0) { free(data); goto fail_unlock; } /* sc_read_binary may return less than requested */ len = r; } sc_unlock(p15card->card); /* Return of release file */ if (file_out != NULL) *file_out = file; else sc_file_free(file); } *buf = data; *buflen = len; return 0; fail_unlock: if (file) sc_file_free(file); sc_unlock(p15card->card); return r; }