Removal of cache, fixing a compiler warning and removing recursive functions.
This commit is contained in:
parent
fce847bf25
commit
1408e25e4b
|
@ -464,6 +464,14 @@ static int dnie_get_serialnr(sc_card_t * card, sc_serial_number_t * serial)
|
||||||
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
|
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the binary data in the cache.
|
||||||
|
*
|
||||||
|
* It frees memory if allocated and resets pointer and length.
|
||||||
|
* It only touches the private binary cache variables, not the sc_card information.
|
||||||
|
*
|
||||||
|
* @param data pointer to dnie private data
|
||||||
|
*/
|
||||||
static void dnie_clear_cache(dnie_private_data_t * data)
|
static void dnie_clear_cache(dnie_private_data_t * data)
|
||||||
{
|
{
|
||||||
if (data == NULL) return;
|
if (data == NULL) return;
|
||||||
|
@ -473,6 +481,13 @@ static void dnie_clear_cache(dnie_private_data_t * data)
|
||||||
data->cachelen = 0;
|
data->cachelen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set sc_card flags according to DNIe requirements.
|
||||||
|
*
|
||||||
|
* Used in card initialization.
|
||||||
|
*
|
||||||
|
* @param card pointer to card data
|
||||||
|
*/
|
||||||
static inline void init_flags(struct sc_card *card)
|
static inline void init_flags(struct sc_card *card)
|
||||||
{
|
{
|
||||||
unsigned long algoflags;
|
unsigned long algoflags;
|
||||||
|
@ -814,10 +829,8 @@ static int dnie_read_binary(struct sc_card *card,
|
||||||
/* on first block or no cache, try to fill */
|
/* on first block or no cache, try to fill */
|
||||||
res = dnie_fill_cache(card);
|
res = dnie_fill_cache(card);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
sc_log(ctx,
|
sc_log(ctx, "Cannot fill cache. using iso_read_binary()");
|
||||||
"Cannot fill cache. using iso_read_binary()");
|
return iso_ops->read_binary(card, idx, buf, count, flags);
|
||||||
return iso_ops->read_binary(card, idx, buf, count,
|
|
||||||
flags);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (idx >= GET_DNIE_PRIV_DATA(card)->cachelen)
|
if (idx >= GET_DNIE_PRIV_DATA(card)->cachelen)
|
||||||
|
@ -829,82 +842,72 @@ static int dnie_read_binary(struct sc_card *card,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invalidate pathfile cache.
|
* Send apdu to the card
|
||||||
*
|
*
|
||||||
* Marks cache path invalid, so next select_file() will traverse
|
* @param card pointer to sc_card_t structure
|
||||||
* the entire card filesystem
|
* @param path
|
||||||
*
|
* @param pathlen
|
||||||
* @param card pointer to card structure
|
* @param p1
|
||||||
|
* @param file_out
|
||||||
|
* @return result
|
||||||
*/
|
*/
|
||||||
static inline void dnie_invalidate_path(sc_card_t *card) {
|
static int dnie_compose_and_send_apdu(sc_card_t *card, const u8 *path, size_t pathlen,
|
||||||
memset(&card->cache, 0, sizeof(card->cache));
|
u8 p1, sc_file_t **file_out)
|
||||||
card->cache.valid = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tracks current path to avoid extra filesystem operation.
|
|
||||||
*
|
|
||||||
* Tracks selected DF's to let card know their current working directory
|
|
||||||
*
|
|
||||||
* TODO: use common opensc file cache structure and functions
|
|
||||||
*
|
|
||||||
* @param card card pointer structure
|
|
||||||
* @param file current DF to be cached
|
|
||||||
*/
|
|
||||||
static int dnie_cache_path(sc_card_t *card, struct sc_file *file)
|
|
||||||
{
|
{
|
||||||
u8 path[] = {0x00,0x00};
|
int res = 0;
|
||||||
LOG_FUNC_CALLED(card->ctx);
|
sc_apdu_t apdu;
|
||||||
path[0]=(u8) (0xff & (file->id >>8));
|
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||||
path[1]=(u8) (0xff & (file->id >>0));
|
sc_file_t *file = NULL;
|
||||||
if (path[0]==0x3F && path[1]==0x00) {
|
|
||||||
/* if absolute path, just copy data */
|
sc_context_t *ctx = NULL;
|
||||||
dnie_invalidate_path(card);
|
|
||||||
card->cache.current_path.value[0]=path[0];
|
if (!card || !card->ctx)
|
||||||
card->cache.current_path.value[1]=path[1];
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
card->cache.current_path.len=2;
|
ctx = card->ctx;
|
||||||
} else {
|
|
||||||
/* if relative path add to current */
|
LOG_FUNC_CALLED(ctx);
|
||||||
size_t curlen=card->cache.current_path.len;
|
|
||||||
card->cache.current_path.value[curlen+0] =path[0];
|
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "called, p1=%u, path=%s\n", p1, sc_dump_hex(path, pathlen));
|
||||||
card->cache.current_path.value[curlen+1] =path[1];
|
|
||||||
card->cache.current_path.len += 2;
|
/* Arriving here means need to compose and send apdu */
|
||||||
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, p1, 0);
|
||||||
|
apdu.resp = rbuf;
|
||||||
|
apdu.resplen = sizeof(rbuf);
|
||||||
|
apdu.lc = pathlen;
|
||||||
|
apdu.data = path;
|
||||||
|
apdu.datalen = pathlen;
|
||||||
|
apdu.le = card->max_recv_size > 0 ? card->max_recv_size : 256;
|
||||||
|
if (p1 == 3)
|
||||||
|
apdu.cse= SC_APDU_CASE_1;
|
||||||
|
|
||||||
|
if (file_out == NULL) {
|
||||||
|
apdu.cse = (apdu.lc == 0) ? SC_APDU_CASE_1 : SC_APDU_CASE_3_SHORT;
|
||||||
|
apdu.le = 0;
|
||||||
|
}
|
||||||
|
res = dnie_transmit_apdu(card, &apdu);
|
||||||
|
LOG_TEST_RET(ctx, res, "SelectFile() APDU transmit failed");
|
||||||
|
if (file_out == NULL) {
|
||||||
|
if (apdu.sw1 == 0x61)
|
||||||
|
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, 0);
|
||||||
|
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE,
|
||||||
|
sc_check_sw(card, apdu.sw1, apdu.sw2));
|
||||||
}
|
}
|
||||||
card->cache.current_path.type=SC_PATH_TYPE_PATH;
|
|
||||||
card->cache.valid=1;
|
|
||||||
LOG_FUNC_RETURN(card->ctx,SC_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/* analyze response. if FCI, try to parse */
|
||||||
* Check proposed path against current (cached) one.
|
res = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||||
*
|
LOG_TEST_RET(ctx, res, "SelectFile() check_sw failed");
|
||||||
* This code compares proposed path to stored one, evaluating required path
|
if (apdu.resplen < 2)
|
||||||
* ID to be selected if finally select_file() is required,
|
LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
|
||||||
*
|
if (apdu.resp[0] == 0x00) /* proprietary coding */
|
||||||
* @param card card pointer structure
|
LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
|
||||||
* @param pathptr pointer to proposed path
|
|
||||||
* @param pathlen len of proposed path
|
/* finally process FCI response */
|
||||||
* @param need_info set if process_fci is needed
|
file = sc_file_new();
|
||||||
* @return 1 on match; 0 on fail
|
if (file == NULL)
|
||||||
*/
|
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||||
static int dnie_check_path(sc_card_t *card, u8 **pathptr, size_t *pathlen,
|
res = card->ops->process_fci(card, file, apdu.resp + 2, apdu.resp[1]);
|
||||||
int need_info)
|
*file_out = file;
|
||||||
{
|
LOG_FUNC_RETURN(ctx, res);
|
||||||
u8 *cacheptr = card->cache.current_path.value;
|
|
||||||
size_t cachelen = card->cache.current_path.len;
|
|
||||||
size_t len = *pathlen;
|
|
||||||
u8 *ptr = *pathptr;
|
|
||||||
int hit=1;
|
|
||||||
if (card->cache.valid==0) hit = 0; /* no valid cache */
|
|
||||||
if (cachelen < 2) hit = 0; /* no data cached */
|
|
||||||
if (len < 2) hit = 0; /* no proposed path */
|
|
||||||
if (len<cachelen) hit = 0; /* length missmatch */
|
|
||||||
if (memcmp(ptr,cacheptr,cachelen)!=0 ) hit = 0; /* path missmatch */
|
|
||||||
if (!hit) return 0;
|
|
||||||
*pathptr = ptr + cachelen;
|
|
||||||
*pathlen = len - cachelen;
|
|
||||||
if (need_info) return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -938,18 +941,10 @@ static int dnie_select_file(struct sc_card *card,
|
||||||
const struct sc_path *in_path,
|
const struct sc_path *in_path,
|
||||||
struct sc_file **file_out)
|
struct sc_file **file_out)
|
||||||
{
|
{
|
||||||
|
|
||||||
u8 buf[SC_MAX_APDU_BUFFER_SIZE];
|
|
||||||
u8 pathbuf[SC_MAX_PATH_SIZE];
|
|
||||||
char pbuf[SC_MAX_PATH_STRING_SIZE];
|
|
||||||
u8 *path = pathbuf;
|
|
||||||
size_t pathlen;
|
|
||||||
int cached=0;
|
|
||||||
|
|
||||||
sc_file_t *file = NULL;
|
|
||||||
int res = SC_SUCCESS;
|
int res = SC_SUCCESS;
|
||||||
sc_apdu_t apdu;
|
|
||||||
sc_context_t *ctx = NULL;
|
sc_context_t *ctx = NULL;
|
||||||
|
unsigned char tmp_path[sizeof(DNIE_MF_NAME)];
|
||||||
|
int reminder = 0;
|
||||||
|
|
||||||
if (!card || !card->ctx || !in_path)
|
if (!card || !card->ctx || !in_path)
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
@ -957,11 +952,6 @@ static int dnie_select_file(struct sc_card *card,
|
||||||
|
|
||||||
LOG_FUNC_CALLED(ctx);
|
LOG_FUNC_CALLED(ctx);
|
||||||
|
|
||||||
memcpy(path, in_path->value, in_path->len);
|
|
||||||
pathlen = in_path->len;
|
|
||||||
|
|
||||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0, 0);
|
|
||||||
|
|
||||||
switch (in_path->type) {
|
switch (in_path->type) {
|
||||||
case SC_PATH_TYPE_FILE_ID:
|
case SC_PATH_TYPE_FILE_ID:
|
||||||
/* pathlen must be of len=2 */
|
/* pathlen must be of len=2 */
|
||||||
|
@ -973,132 +963,71 @@ static int dnie_select_file(struct sc_card *card,
|
||||||
* According iso7816-4 sect 7.1.1 pathlen==0 implies
|
* According iso7816-4 sect 7.1.1 pathlen==0 implies
|
||||||
* select MF, but this case is not supported by DNIe
|
* select MF, but this case is not supported by DNIe
|
||||||
*/
|
*/
|
||||||
if (pathlen != 2)
|
if (in_path->len != 2)
|
||||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
sc_log(ctx, "select_file(ID): %s", sc_dump_hex(path, pathlen));
|
sc_log(ctx, "select_file(ID): %s", sc_dump_hex(in_path->value, in_path->len));
|
||||||
apdu.p1 = 0;
|
res = dnie_compose_and_send_apdu(card, in_path->value, in_path->len, 0, file_out);
|
||||||
break;
|
break;
|
||||||
case SC_PATH_TYPE_DF_NAME:
|
case SC_PATH_TYPE_DF_NAME:
|
||||||
sc_log(ctx, "select_file(NAME): %s",
|
sc_log(ctx, "select_file(NAME): %s", sc_dump_hex(in_path->value, in_path->len));
|
||||||
sc_dump_hex(path, pathlen));
|
res = dnie_compose_and_send_apdu(card, in_path->value, in_path->len, 4, file_out);
|
||||||
apdu.p1 = 4;
|
|
||||||
break;
|
break;
|
||||||
case SC_PATH_TYPE_PATH:
|
case SC_PATH_TYPE_PATH:
|
||||||
if ((pathlen & 1) != 0) /* not divisible by 2 */
|
if ((in_path->len == 0) || ((in_path->len & 1) != 0)) /* not divisible by 2 */
|
||||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
|
|
||||||
/* evaluate current patch from cache */
|
sc_log(ctx, "select_file(PATH): requested:%s ", sc_dump_hex(in_path->value, in_path->len));
|
||||||
res = sc_path_print(pbuf, sizeof(pbuf), &card->cache.current_path);
|
|
||||||
if (res != SC_SUCCESS) pbuf[0] = '\0';
|
|
||||||
sc_log(ctx, "select_file(PATH): requested:%s cached:%s",
|
|
||||||
sc_dump_hex(path, pathlen),pbuf);
|
|
||||||
|
|
||||||
/* check pathfile cache
|
|
||||||
* cached returns true if:
|
|
||||||
* - path matches cache
|
|
||||||
* - path starts with cache
|
|
||||||
* remember that only DF's are cached
|
|
||||||
*/
|
|
||||||
cached = dnie_check_path(card, &path, &pathlen, file_out != NULL);
|
|
||||||
if (pathlen == 0) {
|
|
||||||
/* request to select_file on current df */
|
|
||||||
sc_log(ctx,"Cache hit: already on cached DF");
|
|
||||||
LOG_FUNC_RETURN(ctx,SC_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* convert to SC_PATH_TYPE_FILE_ID */
|
/* convert to SC_PATH_TYPE_FILE_ID */
|
||||||
res = sc_lock(card); /* lock to ensure path traversal */
|
res = sc_lock(card); /* lock to ensure path traversal */
|
||||||
LOG_TEST_RET(ctx, res, "sc_lock() failed");
|
LOG_TEST_RET(ctx, res, "sc_lock() failed");
|
||||||
while (pathlen > 0) {
|
if (memcmp(in_path->value, "\x3F\x00", 2) == 0) {
|
||||||
sc_path_t tmpp;
|
/* if MF, use the name as path */
|
||||||
if ( memcmp(path, "\x3F\x00", 2) == 0) {
|
strcpy((char *)tmp_path, DNIE_MF_NAME);
|
||||||
/* if MF, use their name as path */
|
sc_log(ctx, "select_file(NAME): requested:%s ", sc_dump_hex(tmp_path, sizeof(DNIE_MF_NAME) - 1));
|
||||||
tmpp.type = SC_PATH_TYPE_DF_NAME;
|
res = dnie_compose_and_send_apdu(card, tmp_path, sizeof(DNIE_MF_NAME) - 1, 4, file_out);
|
||||||
strcpy((char *)tmpp.value, DNIE_MF_NAME);
|
|
||||||
tmpp.len = sizeof(DNIE_MF_NAME) - 1;
|
|
||||||
} else {
|
|
||||||
/* else use 2-byte file id */
|
|
||||||
tmpp.type = SC_PATH_TYPE_FILE_ID;
|
|
||||||
tmpp.value[0] = path[0];
|
|
||||||
tmpp.value[1] = path[1];
|
|
||||||
tmpp.len = 2;
|
|
||||||
}
|
|
||||||
/* recursively call to select_file */
|
|
||||||
res = card->ops->select_file(card, &tmpp, file_out);
|
|
||||||
if (res != SC_SUCCESS) {
|
if (res != SC_SUCCESS) {
|
||||||
sc_unlock(card);
|
sc_unlock(card);
|
||||||
sc_log(ctx,"select_file(PATH) failed");
|
LOG_TEST_RET(ctx, res, "select_file(NAME) failed");
|
||||||
LOG_FUNC_RETURN(ctx,res);
|
|
||||||
}
|
}
|
||||||
pathlen -= 2;
|
tmp_path[2] = 0;
|
||||||
path += 2;
|
reminder = in_path->len - 2;
|
||||||
|
} else {
|
||||||
|
tmp_path[2] = 0;
|
||||||
|
reminder = in_path->len;
|
||||||
|
}
|
||||||
|
while (reminder > 0) {
|
||||||
|
tmp_path[0] = in_path->value[in_path->len - reminder];
|
||||||
|
tmp_path[1] = in_path->value[1 + in_path->len - reminder];
|
||||||
|
sc_log(ctx, "select_file(PATH): requested:%s ", sc_dump_hex(tmp_path, 2));
|
||||||
|
res = dnie_compose_and_send_apdu(card, tmp_path, 2, 0, file_out);
|
||||||
|
if (res != SC_SUCCESS) {
|
||||||
|
sc_unlock(card);
|
||||||
|
LOG_TEST_RET(ctx, res, "select_file(PATH) failed");
|
||||||
|
}
|
||||||
|
reminder -= 2;
|
||||||
}
|
}
|
||||||
sc_unlock(card);
|
sc_unlock(card);
|
||||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
|
||||||
break;
|
break;
|
||||||
case SC_PATH_TYPE_FROM_CURRENT:
|
case SC_PATH_TYPE_FROM_CURRENT:
|
||||||
LOG_FUNC_RETURN(ctx, SC_ERROR_NO_CARD_SUPPORT);
|
LOG_FUNC_RETURN(ctx, SC_ERROR_NO_CARD_SUPPORT);
|
||||||
|
break;
|
||||||
case SC_PATH_TYPE_PARENT:
|
case SC_PATH_TYPE_PARENT:
|
||||||
/* Hey!! Manual doesn't says anything on this, but
|
/* Hey!! Manual doesn't says anything on this, but
|
||||||
* gscriptor shows that this type is supported
|
* gscriptor shows that this type is supported
|
||||||
*/
|
*/
|
||||||
sc_log(ctx, "select_file(PARENT)");
|
sc_log(ctx, "select_file(PARENT)");
|
||||||
/* according iso7816-4 sect 7.1.1 shouldn't have any parameters */
|
/* according iso7816-4 sect 7.1.1 shouldn't have any parameters */
|
||||||
if (pathlen != 0)
|
if (in_path->len != 0)
|
||||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
apdu.cse= SC_APDU_CASE_1;
|
res = dnie_compose_and_send_apdu(card, NULL, 0, 3, file_out);
|
||||||
apdu.p1 = 3;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Arriving here means need to compose and send apdu */
|
|
||||||
apdu.p2 = 0; /* first record, return FCI */
|
|
||||||
apdu.lc = pathlen;
|
|
||||||
apdu.data = path;
|
|
||||||
apdu.datalen = pathlen;
|
|
||||||
|
|
||||||
if (file_out != NULL) {
|
|
||||||
apdu.resp = buf;
|
|
||||||
apdu.resplen = sizeof(buf);
|
|
||||||
apdu.le = card->max_recv_size > 0 ? card->max_recv_size : 256;
|
|
||||||
} else {
|
|
||||||
apdu.cse =
|
|
||||||
(apdu.lc == 0) ? SC_APDU_CASE_1 : SC_APDU_CASE_3_SHORT;
|
|
||||||
}
|
|
||||||
res = dnie_transmit_apdu(card, &apdu);
|
|
||||||
if (res!=SC_SUCCESS)
|
|
||||||
dnie_invalidate_path(card); /* failed: invalidate cache */
|
|
||||||
LOG_TEST_RET(ctx, res, "SelectFile() APDU transmit failed");
|
|
||||||
if (file_out == NULL) {
|
|
||||||
if (apdu.sw1 == 0x61)
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, 0);
|
|
||||||
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE,
|
|
||||||
sc_check_sw(card, apdu.sw1, apdu.sw2));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* analyze response. if FCI, try to parse */
|
|
||||||
res = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
|
||||||
LOG_TEST_RET(ctx, res, "SelectFile() check_sw failed");
|
|
||||||
if (apdu.resplen < 2)
|
|
||||||
LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
|
|
||||||
if (apdu.resp[0] == 0x00) /* proprietary coding */
|
|
||||||
LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
|
|
||||||
|
|
||||||
/* finally process FCI response */
|
|
||||||
file = sc_file_new();
|
|
||||||
if (file == NULL)
|
|
||||||
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
|
|
||||||
if (!card->ops->process_fci) { /* hey! DNIe MUST have process_fci */
|
|
||||||
if (file)
|
|
||||||
sc_file_free(file);
|
|
||||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
|
|
||||||
}
|
|
||||||
res = card->ops->process_fci(card, file, apdu.resp + 2, apdu.resp[1]);
|
|
||||||
*file_out = file;
|
|
||||||
/* if file is a DF, store it into DF cache */
|
|
||||||
if (file->type==SC_FILE_TYPE_DF) dnie_cache_path(card,file);
|
|
||||||
/* as last step clear data cache and return */
|
/* as last step clear data cache and return */
|
||||||
dnie_clear_cache(GET_DNIE_PRIV_DATA(card));
|
dnie_clear_cache(GET_DNIE_PRIV_DATA(card));
|
||||||
LOG_FUNC_RETURN(ctx, res);
|
LOG_FUNC_RETURN(ctx, res);
|
||||||
|
@ -1824,8 +1753,7 @@ static int dnie_process_fci(struct sc_card *card,
|
||||||
}
|
}
|
||||||
/* FCI response for Keys EF returns 3 additional bytes */
|
/* FCI response for Keys EF returns 3 additional bytes */
|
||||||
if (file->prop_attr_len < 13) {
|
if (file->prop_attr_len < 13) {
|
||||||
sc_log(ctx,
|
sc_log(ctx, "FCI response len for Keys EF should be 13 bytes");
|
||||||
"FCI response len for Keys EF should be 13 bytes");
|
|
||||||
res = SC_ERROR_WRONG_LENGTH;
|
res = SC_ERROR_WRONG_LENGTH;
|
||||||
goto dnie_process_fci_end;
|
goto dnie_process_fci_end;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue