Merge pull request #1924 from frankmorgner/recursion
avoid calling sc_*_binary recursively
This commit is contained in:
commit
d8734baf83
|
@ -515,9 +515,8 @@ authentic_erase_binary(struct sc_card *card, unsigned int offs, size_t count, un
|
|||
|
||||
rv = sc_update_binary(card, offs, buf_zero, count, flags);
|
||||
free(buf_zero);
|
||||
LOG_TEST_RET(ctx, rv, "'ERASE BINARY' failed");
|
||||
|
||||
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||
LOG_FUNC_RETURN(ctx, rv);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -624,15 +624,6 @@ done:
|
|||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
|
||||
/* CAC driver is read only */
|
||||
static int cac_write_binary(sc_card_t *card, unsigned int idx,
|
||||
const u8 *buf, size_t count, unsigned long flags)
|
||||
{
|
||||
|
||||
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
/* initialize getting a list and return the number of elements in the list */
|
||||
static int cac_get_init_and_get_count(list_t *list, cac_object_t **entry, int *countp)
|
||||
{
|
||||
|
@ -1916,7 +1907,8 @@ static struct sc_card_driver * sc_get_driver(void)
|
|||
cac_ops.select_file = cac_select_file; /* need to record object type */
|
||||
cac_ops.get_challenge = cac_get_challenge;
|
||||
cac_ops.read_binary = cac_read_binary;
|
||||
cac_ops.write_binary = cac_write_binary;
|
||||
/* CAC driver is read only */
|
||||
cac_ops.write_binary = NULL;
|
||||
cac_ops.set_security_env = cac_set_security_env;
|
||||
cac_ops.restore_security_env = cac_restore_security_env;
|
||||
cac_ops.compute_signature = cac_compute_signature;
|
||||
|
|
|
@ -706,7 +706,7 @@ iasecc_erase_binary(struct sc_card *card, unsigned int offs, size_t count, unsig
|
|||
|
||||
rv = sc_update_binary(card, offs, tmp, count, flags);
|
||||
free(tmp);
|
||||
LOG_TEST_RET(ctx, rv, "iasecc_erase_binary() update binary error");
|
||||
|
||||
LOG_FUNC_RETURN(ctx, rv);
|
||||
}
|
||||
|
||||
|
|
|
@ -206,20 +206,6 @@ jpki_select_file(struct sc_card *card,
|
|||
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
|
||||
}
|
||||
|
||||
static int
|
||||
jpki_read_binary(sc_card_t * card, unsigned int idx,
|
||||
u8 * buf, size_t count, unsigned long flags)
|
||||
{
|
||||
struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
|
||||
const struct sc_card_operations *iso_ops = iso_drv->ops;
|
||||
int rc;
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
|
||||
rc = iso_ops->read_binary(card, idx, buf, count, flags);
|
||||
LOG_FUNC_RETURN(card->ctx, rc);
|
||||
}
|
||||
|
||||
static int
|
||||
jpki_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left)
|
||||
{
|
||||
|
@ -385,7 +371,6 @@ sc_get_driver(void)
|
|||
jpki_ops.init = jpki_init;
|
||||
jpki_ops.finish = jpki_finish;
|
||||
jpki_ops.select_file = jpki_select_file;
|
||||
jpki_ops.read_binary = jpki_read_binary;
|
||||
jpki_ops.pin_cmd = jpki_pin_cmd;
|
||||
jpki_ops.set_security_env = jpki_set_security_env;
|
||||
jpki_ops.compute_signature = jpki_compute_signature;
|
||||
|
|
|
@ -1480,17 +1480,6 @@ pgp_read_binary(sc_card_t *card, unsigned int idx,
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* ABI: ISO 7816-4 WRITE BINARY - write data to currently selected EF.
|
||||
*/
|
||||
static int
|
||||
pgp_write_binary(sc_card_t *card, unsigned int idx,
|
||||
const u8 *buf, size_t count, unsigned long flags)
|
||||
{
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Internal: get public key from card - as DF + sub-wEFs.
|
||||
*/
|
||||
|
@ -3482,7 +3471,7 @@ sc_get_openpgp_driver(void)
|
|||
pgp_ops.list_files = pgp_list_files;
|
||||
pgp_ops.get_challenge = pgp_get_challenge;
|
||||
pgp_ops.read_binary = pgp_read_binary;
|
||||
pgp_ops.write_binary = pgp_write_binary;
|
||||
pgp_ops.write_binary = NULL;
|
||||
pgp_ops.pin_cmd = pgp_pin_cmd;
|
||||
pgp_ops.logout = pgp_logout;
|
||||
pgp_ops.get_data = pgp_get_data;
|
||||
|
|
|
@ -620,6 +620,7 @@ int sc_read_binary(sc_card_t *card, unsigned int idx,
|
|||
unsigned char *buf, size_t count, unsigned long flags)
|
||||
{
|
||||
size_t max_le = sc_get_max_recv_size(card);
|
||||
size_t todo = count;
|
||||
int r;
|
||||
|
||||
if (card == NULL || card->ops == NULL || buf == NULL) {
|
||||
|
@ -628,7 +629,7 @@ int sc_read_binary(sc_card_t *card, unsigned int idx,
|
|||
sc_log(card->ctx, "called; %"SC_FORMAT_LEN_SIZE_T"u bytes at index %d",
|
||||
count, idx);
|
||||
if (count == 0)
|
||||
return 0;
|
||||
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
|
||||
|
||||
#ifdef ENABLE_SM
|
||||
if (card->sm_ctx.ops.read_binary) {
|
||||
|
@ -637,47 +638,45 @@ int sc_read_binary(sc_card_t *card, unsigned int idx,
|
|||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (card->ops->read_binary == NULL)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
|
||||
if (count > max_le) {
|
||||
int bytes_read = 0;
|
||||
unsigned char *p = buf;
|
||||
/* lock the card now to avoid deselection of the file */
|
||||
r = sc_lock(card);
|
||||
LOG_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||
|
||||
r = sc_lock(card);
|
||||
LOG_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||
while (count > 0) {
|
||||
size_t n = count > max_le ? max_le : count;
|
||||
r = sc_read_binary(card, idx, p, n, flags);
|
||||
if (r < 0) {
|
||||
sc_unlock(card);
|
||||
LOG_TEST_RET(card->ctx, r, "sc_read_binary() failed");
|
||||
}
|
||||
p += r;
|
||||
if ((bytes_read > INT_MAX - r) || idx > UINT_MAX - r) {
|
||||
/* `bytes_read + r` or `idx + r` would overflow */
|
||||
sc_unlock(card);
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OFFSET_TOO_LARGE);
|
||||
}
|
||||
idx += r;
|
||||
bytes_read += r;
|
||||
count -= r;
|
||||
if (r == 0) {
|
||||
sc_unlock(card);
|
||||
LOG_FUNC_RETURN(card->ctx, bytes_read);
|
||||
}
|
||||
while (todo > 0) {
|
||||
size_t chunk = todo > max_le ? max_le : todo;
|
||||
|
||||
r = card->ops->read_binary(card, idx, buf, chunk, flags);
|
||||
if (r == 0 || r == SC_ERROR_FILE_END_REACHED)
|
||||
break;
|
||||
if ((idx > SIZE_MAX - (size_t) r)
|
||||
|| (size_t) r > todo) {
|
||||
/* `idx + r` or `todo - r` would overflow */
|
||||
r = SC_ERROR_OFFSET_TOO_LARGE;
|
||||
}
|
||||
sc_unlock(card);
|
||||
LOG_FUNC_RETURN(card->ctx, bytes_read);
|
||||
if (r < 0) {
|
||||
sc_unlock(card);
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
|
||||
todo -= (size_t) r;
|
||||
buf += (size_t) r;
|
||||
idx += (size_t) r;
|
||||
}
|
||||
r = card->ops->read_binary(card, idx, buf, count, flags);
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
|
||||
sc_unlock(card);
|
||||
|
||||
LOG_FUNC_RETURN(card->ctx, count - todo);
|
||||
}
|
||||
|
||||
int sc_write_binary(sc_card_t *card, unsigned int idx,
|
||||
const u8 *buf, size_t count, unsigned long flags)
|
||||
{
|
||||
size_t max_lc = sc_get_max_send_size(card);
|
||||
size_t todo = count;
|
||||
int r;
|
||||
|
||||
if (card == NULL || card->ops == NULL || buf == NULL) {
|
||||
|
@ -686,44 +685,46 @@ int sc_write_binary(sc_card_t *card, unsigned int idx,
|
|||
sc_log(card->ctx, "called; %"SC_FORMAT_LEN_SIZE_T"u bytes at index %d",
|
||||
count, idx);
|
||||
if (count == 0)
|
||||
LOG_FUNC_RETURN(card->ctx, 0);
|
||||
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
|
||||
|
||||
if (card->ops->write_binary == NULL)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
|
||||
if (count > max_lc) {
|
||||
int bytes_written = 0;
|
||||
const u8 *p = buf;
|
||||
/* lock the card now to avoid deselection of the file */
|
||||
r = sc_lock(card);
|
||||
LOG_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||
|
||||
r = sc_lock(card);
|
||||
LOG_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||
while (count > 0) {
|
||||
size_t n = count > max_lc? max_lc : count;
|
||||
r = sc_write_binary(card, idx, p, n, flags);
|
||||
if (r < 0) {
|
||||
sc_unlock(card);
|
||||
LOG_TEST_RET(card->ctx, r, "sc_write_binary() failed");
|
||||
}
|
||||
p += r;
|
||||
idx += r;
|
||||
bytes_written += r;
|
||||
count -= r;
|
||||
if (r == 0) {
|
||||
sc_unlock(card);
|
||||
LOG_FUNC_RETURN(card->ctx, bytes_written);
|
||||
}
|
||||
while (todo > 0) {
|
||||
size_t chunk = todo > max_lc ? max_lc : todo;
|
||||
|
||||
r = card->ops->write_binary(card, idx, buf, chunk, flags);
|
||||
if (r == 0 || r == SC_ERROR_FILE_END_REACHED)
|
||||
break;
|
||||
if ((idx > SIZE_MAX - (size_t) r)
|
||||
|| (size_t) r > todo) {
|
||||
/* `idx + r` or `todo - r` would overflow */
|
||||
r = SC_ERROR_OFFSET_TOO_LARGE;
|
||||
}
|
||||
sc_unlock(card);
|
||||
LOG_FUNC_RETURN(card->ctx, bytes_written);
|
||||
if (r < 0) {
|
||||
sc_unlock(card);
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
|
||||
todo -= (size_t) r;
|
||||
buf += (size_t) r;
|
||||
idx += (size_t) r;
|
||||
}
|
||||
|
||||
r = card->ops->write_binary(card, idx, buf, count, flags);
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
sc_unlock(card);
|
||||
|
||||
LOG_FUNC_RETURN(card->ctx, count - todo);
|
||||
}
|
||||
|
||||
int sc_update_binary(sc_card_t *card, unsigned int idx,
|
||||
const u8 *buf, size_t count, unsigned long flags)
|
||||
{
|
||||
size_t max_lc = sc_get_max_send_size(card);
|
||||
size_t todo = count;
|
||||
int r;
|
||||
|
||||
if (card == NULL || card->ops == NULL || buf == NULL) {
|
||||
|
@ -732,7 +733,7 @@ int sc_update_binary(sc_card_t *card, unsigned int idx,
|
|||
sc_log(card->ctx, "called; %"SC_FORMAT_LEN_SIZE_T"u bytes at index %d",
|
||||
count, idx);
|
||||
if (count == 0)
|
||||
return 0;
|
||||
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
|
||||
|
||||
#ifdef ENABLE_SM
|
||||
if (card->sm_ctx.ops.update_binary) {
|
||||
|
@ -745,53 +746,79 @@ int sc_update_binary(sc_card_t *card, unsigned int idx,
|
|||
if (card->ops->update_binary == NULL)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
|
||||
if (count > max_lc) {
|
||||
int bytes_written = 0;
|
||||
const u8 *p = buf;
|
||||
/* lock the card now to avoid deselection of the file */
|
||||
r = sc_lock(card);
|
||||
LOG_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||
|
||||
r = sc_lock(card);
|
||||
LOG_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||
while (count > 0) {
|
||||
size_t n = count > max_lc? max_lc : count;
|
||||
r = sc_update_binary(card, idx, p, n, flags);
|
||||
if (r < 0) {
|
||||
sc_unlock(card);
|
||||
LOG_TEST_RET(card->ctx, r, "sc_update_binary() failed");
|
||||
}
|
||||
p += r;
|
||||
idx += r;
|
||||
bytes_written += r;
|
||||
count -= r;
|
||||
if (r == 0) {
|
||||
sc_unlock(card);
|
||||
LOG_FUNC_RETURN(card->ctx, bytes_written);
|
||||
}
|
||||
while (todo > 0) {
|
||||
size_t chunk = todo > max_lc ? max_lc : todo;
|
||||
|
||||
r = card->ops->update_binary(card, idx, buf, chunk, flags);
|
||||
if (r == 0 || r == SC_ERROR_FILE_END_REACHED)
|
||||
break;
|
||||
if ((idx > SIZE_MAX - (size_t) r)
|
||||
|| (size_t) r > todo) {
|
||||
/* `idx + r` or `todo - r` would overflow */
|
||||
r = SC_ERROR_OFFSET_TOO_LARGE;
|
||||
}
|
||||
sc_unlock(card);
|
||||
LOG_FUNC_RETURN(card->ctx, bytes_written);
|
||||
if (r < 0) {
|
||||
sc_unlock(card);
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
|
||||
todo -= (size_t) r;
|
||||
buf += (size_t) r;
|
||||
idx += (size_t) r;
|
||||
}
|
||||
|
||||
r = card->ops->update_binary(card, idx, buf, count, flags);
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
sc_unlock(card);
|
||||
|
||||
LOG_FUNC_RETURN(card->ctx, count - todo);
|
||||
}
|
||||
|
||||
|
||||
int sc_erase_binary(struct sc_card *card, unsigned int offs, size_t count, unsigned long flags)
|
||||
int sc_erase_binary(struct sc_card *card, unsigned int idx, size_t count, unsigned long flags)
|
||||
{
|
||||
int r;
|
||||
size_t todo = count;
|
||||
|
||||
if (card == NULL || card->ops == NULL) {
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
sc_log(card->ctx,
|
||||
"called; erase %"SC_FORMAT_LEN_SIZE_T"u bytes from offset %d",
|
||||
count, offs);
|
||||
count, idx);
|
||||
if (count == 0)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
|
||||
|
||||
if (card->ops->erase_binary == NULL)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
|
||||
r = card->ops->erase_binary(card, offs, count, flags);
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
/* lock the card now to avoid deselection of the file */
|
||||
r = sc_lock(card);
|
||||
LOG_TEST_RET(card->ctx, r, "sc_lock() failed");
|
||||
|
||||
while (todo > 0) {
|
||||
r = card->ops->erase_binary(card, idx, todo, flags);
|
||||
if (r == 0 || r == SC_ERROR_FILE_END_REACHED)
|
||||
break;
|
||||
if ((idx > SIZE_MAX - (size_t) r)
|
||||
|| (size_t) r > todo) {
|
||||
/* `idx + r` or `todo - r` would overflow */
|
||||
r = SC_ERROR_OFFSET_TOO_LARGE;
|
||||
}
|
||||
if (r < 0) {
|
||||
sc_unlock(card);
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
|
||||
todo -= (size_t) r;
|
||||
idx += (size_t) r;
|
||||
}
|
||||
|
||||
sc_unlock(card);
|
||||
|
||||
LOG_FUNC_RETURN(card->ctx, count - todo);
|
||||
}
|
||||
|
||||
|
||||
|
@ -881,7 +908,6 @@ int sc_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t len)
|
|||
int sc_get_challenge(sc_card_t *card, u8 *rnd, size_t len)
|
||||
{
|
||||
int r;
|
||||
size_t retry = 10;
|
||||
|
||||
if (len == 0)
|
||||
return SC_SUCCESS;
|
||||
|
@ -899,19 +925,17 @@ int sc_get_challenge(sc_card_t *card, u8 *rnd, size_t len)
|
|||
if (r != SC_SUCCESS)
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
|
||||
while (len > 0 && retry > 0) {
|
||||
while (len > 0) {
|
||||
r = card->ops->get_challenge(card, rnd, len);
|
||||
if (r == 0)
|
||||
r = SC_ERROR_INVALID_DATA;
|
||||
if (r < 0) {
|
||||
sc_unlock(card);
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
|
||||
if (r > 0) {
|
||||
rnd += (size_t) r;
|
||||
len -= (size_t) r;
|
||||
} else {
|
||||
retry--;
|
||||
}
|
||||
rnd += (size_t) r;
|
||||
len -= (size_t) r;
|
||||
}
|
||||
|
||||
sc_unlock(card);
|
||||
|
@ -931,7 +955,11 @@ int sc_read_record(sc_card_t *card, unsigned int rec_nr, u8 *buf,
|
|||
|
||||
if (card->ops->read_record == NULL)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
|
||||
r = card->ops->read_record(card, rec_nr, buf, count, flags);
|
||||
if (r == SC_SUCCESS) {
|
||||
r = count;
|
||||
}
|
||||
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
|
@ -948,7 +976,11 @@ int sc_write_record(sc_card_t *card, unsigned int rec_nr, const u8 * buf,
|
|||
|
||||
if (card->ops->write_record == NULL)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
|
||||
r = card->ops->write_record(card, rec_nr, buf, count, flags);
|
||||
if (r == SC_SUCCESS) {
|
||||
r = count;
|
||||
}
|
||||
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
|
@ -965,7 +997,11 @@ int sc_append_record(sc_card_t *card, const u8 * buf, size_t count,
|
|||
|
||||
if (card->ops->append_record == NULL)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
|
||||
r = card->ops->append_record(card, buf, count, flags);
|
||||
if (r == SC_SUCCESS) {
|
||||
r = count;
|
||||
}
|
||||
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
|
@ -982,7 +1018,11 @@ int sc_update_record(sc_card_t *card, unsigned int rec_nr, const u8 * buf,
|
|||
|
||||
if (card->ops->update_record == NULL)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
|
||||
r = card->ops->update_record(card, rec_nr, buf, count, flags);
|
||||
if (r == SC_SUCCESS) {
|
||||
r = count;
|
||||
}
|
||||
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
}
|
||||
|
@ -998,6 +1038,7 @@ int sc_delete_record(sc_card_t *card, unsigned int rec_nr)
|
|||
|
||||
if (card->ops->delete_record == NULL)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
|
||||
|
||||
r = card->ops->delete_record(card, rec_nr);
|
||||
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
|
|
|
@ -142,7 +142,7 @@ iso7816_read_binary(struct sc_card *card, unsigned int idx, u8 *buf, size_t coun
|
|||
struct sc_apdu apdu;
|
||||
int r;
|
||||
|
||||
if (idx > 0x7fff) {
|
||||
if (idx > 0x7FFF) {
|
||||
sc_log(ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
|
||||
return SC_ERROR_OFFSET_TOO_LARGE;
|
||||
}
|
||||
|
@ -161,15 +161,6 @@ iso7816_read_binary(struct sc_card *card, unsigned int idx, u8 *buf, size_t coun
|
|||
LOG_FUNC_RETURN(ctx, apdu.resplen);
|
||||
LOG_TEST_RET(ctx, r, "Check SW error");
|
||||
|
||||
if (apdu.resplen > 0 && apdu.resplen < count) {
|
||||
r = iso7816_read_binary(card, idx + apdu.resplen, buf + apdu.resplen, count - apdu.resplen, flags);
|
||||
/* Ignore all but 'corrupted data' errors */
|
||||
if (r == SC_ERROR_CORRUPTED_DATA)
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_CORRUPTED_DATA);
|
||||
else if (r > 0)
|
||||
apdu.resplen += r;
|
||||
}
|
||||
|
||||
LOG_FUNC_RETURN(ctx, apdu.resplen);
|
||||
}
|
||||
|
||||
|
@ -182,13 +173,12 @@ iso7816_read_record(struct sc_card *card,
|
|||
int r;
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0xB2, rec_nr, 0);
|
||||
apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
|
||||
if (flags & SC_RECORD_BY_REC_NR)
|
||||
apdu.p2 |= 0x04;
|
||||
|
||||
apdu.le = count;
|
||||
apdu.resplen = count;
|
||||
apdu.resp = buf;
|
||||
apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
|
||||
if (flags & SC_RECORD_BY_REC_NR)
|
||||
apdu.p2 |= 0x04;
|
||||
|
||||
fixup_transceive_length(card, &apdu);
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
|
@ -208,13 +198,12 @@ iso7816_write_record(struct sc_card *card, unsigned int rec_nr,
|
|||
int r;
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xD2, rec_nr, 0);
|
||||
apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
|
||||
if (flags & SC_RECORD_BY_REC_NR)
|
||||
apdu.p2 |= 0x04;
|
||||
|
||||
apdu.lc = count;
|
||||
apdu.datalen = count;
|
||||
apdu.data = buf;
|
||||
apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
|
||||
if (flags & SC_RECORD_BY_REC_NR)
|
||||
apdu.p2 |= 0x04;
|
||||
|
||||
fixup_transceive_length(card, &apdu);
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
|
@ -234,11 +223,10 @@ iso7816_append_record(struct sc_card *card,
|
|||
int r;
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xE2, 0, 0);
|
||||
apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
|
||||
|
||||
apdu.lc = count;
|
||||
apdu.datalen = count;
|
||||
apdu.data = buf;
|
||||
apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
|
||||
|
||||
fixup_transceive_length(card, &apdu);
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
|
@ -258,13 +246,12 @@ iso7816_update_record(struct sc_card *card, unsigned int rec_nr,
|
|||
int r;
|
||||
|
||||
sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xDC, rec_nr, 0);
|
||||
apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
|
||||
if (flags & SC_RECORD_BY_REC_NR)
|
||||
apdu.p2 |= 0x04;
|
||||
|
||||
apdu.lc = count;
|
||||
apdu.datalen = count;
|
||||
apdu.data = buf;
|
||||
apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
|
||||
if (flags & SC_RECORD_BY_REC_NR)
|
||||
apdu.p2 |= 0x04;
|
||||
|
||||
fixup_transceive_length(card, &apdu);
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
|
@ -1358,6 +1345,8 @@ int iso7816_read_binary_sfid(sc_card_t *card, unsigned char sfid,
|
|||
*ef_len += r;
|
||||
break;
|
||||
}
|
||||
if (r == 0 || r == SC_ERROR_FILE_END_REACHED)
|
||||
break;
|
||||
if (r < 0) {
|
||||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not read EF.");
|
||||
goto err;
|
||||
|
@ -1375,7 +1364,7 @@ int iso7816_read_binary_sfid(sc_card_t *card, unsigned char sfid,
|
|||
*ef + *ef_len, read, 0);
|
||||
}
|
||||
|
||||
r = SC_SUCCESS;
|
||||
r = *ef_len;
|
||||
|
||||
err:
|
||||
return r;
|
||||
|
@ -1435,6 +1424,8 @@ int iso7816_write_binary_sfid(sc_card_t *card, unsigned char sfid,
|
|||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not write EF.");
|
||||
goto err;
|
||||
}
|
||||
if (r == 0 || r == SC_ERROR_FILE_END_REACHED)
|
||||
break;
|
||||
wrote += r;
|
||||
apdu.data += r;
|
||||
if (wrote >= ef_len)
|
||||
|
@ -1443,7 +1434,7 @@ int iso7816_write_binary_sfid(sc_card_t *card, unsigned char sfid,
|
|||
r = sc_write_binary(card, wrote, ef, write, 0);
|
||||
}
|
||||
|
||||
r = SC_SUCCESS;
|
||||
r = wrote;
|
||||
|
||||
err:
|
||||
return r;
|
||||
|
@ -1503,6 +1494,8 @@ int iso7816_update_binary_sfid(sc_card_t *card, unsigned char sfid,
|
|||
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not update EF.");
|
||||
goto err;
|
||||
}
|
||||
if (r == 0 || r == SC_ERROR_FILE_END_REACHED)
|
||||
break;
|
||||
wrote += r;
|
||||
apdu.data += r;
|
||||
if (wrote >= ef_len)
|
||||
|
@ -1511,7 +1504,7 @@ int iso7816_update_binary_sfid(sc_card_t *card, unsigned char sfid,
|
|||
r = sc_update_binary(card, wrote, ef, write, 0);
|
||||
}
|
||||
|
||||
r = SC_SUCCESS;
|
||||
r = wrote;
|
||||
|
||||
err:
|
||||
return r;
|
||||
|
|
|
@ -605,28 +605,90 @@ typedef struct sc_card {
|
|||
} sc_card_t;
|
||||
|
||||
struct sc_card_operations {
|
||||
/* Called in sc_connect_card(). Must return 1, if the current
|
||||
/** @brief Match a card with the given card driver.
|
||||
*
|
||||
* Called in sc_connect_card(). Must return 1, if the current
|
||||
* card can be handled with this driver, or 0 otherwise. ATR
|
||||
* field of the sc_card struct is filled in before calling
|
||||
* this function. */
|
||||
* this function. It is recommended not to modify `card` during this call.
|
||||
* */
|
||||
int (*match_card)(struct sc_card *card);
|
||||
|
||||
/* Called when ATR of the inserted card matches an entry in ATR
|
||||
/** @brief Initialize a card.
|
||||
*
|
||||
* Called when ATR of the inserted card matches an entry in ATR
|
||||
* table. May return SC_ERROR_INVALID_CARD to indicate that
|
||||
* the card cannot be handled with this driver. */
|
||||
* the card cannot be handled with this driver. drv_data may be used to
|
||||
* store card driver's (allocated) private data. */
|
||||
int (*init)(struct sc_card *card);
|
||||
/* Called when the card object is being freed. finish() has to
|
||||
/** @brief Deinitialize a card.
|
||||
*
|
||||
* Called when the `card` object is being freed. finish() has to
|
||||
* deallocate all possible private data. */
|
||||
int (*finish)(struct sc_card *card);
|
||||
|
||||
/* ISO 7816-4 functions */
|
||||
|
||||
/**
|
||||
* @brief Read data from a binary EF with a single command
|
||||
*
|
||||
* Implementation of this call back is optional and may be NULL.
|
||||
*
|
||||
* @param card struct sc_card object on which to issue the command
|
||||
* @param idx index within the file with the data to read
|
||||
* @param buf buffer to the read data
|
||||
* @param count number of bytes to read
|
||||
* @param flags flags for the READ BINARY command (currently not used)
|
||||
* @return number of bytes read or an error code
|
||||
*
|
||||
* @see sc_read_binary()
|
||||
*/
|
||||
int (*read_binary)(struct sc_card *card, unsigned int idx,
|
||||
u8 * buf, size_t count, unsigned long flags);
|
||||
/**
|
||||
* @brief Write data to a binary EF with a single command
|
||||
*
|
||||
* Implementation of this call back is optional and may be NULL.
|
||||
*
|
||||
* @param card struct sc_card object on which to issue the command
|
||||
* @param idx index within the file for the data to be written
|
||||
* @param buf buffer with the data
|
||||
* @param count number of bytes to write
|
||||
* @param flags flags for the WRITE BINARY command (currently not used)
|
||||
* @return number of bytes written or an error code
|
||||
*
|
||||
* @see sc_write_binary()
|
||||
*/
|
||||
int (*write_binary)(struct sc_card *card, unsigned int idx,
|
||||
const u8 * buf, size_t count, unsigned long flags);
|
||||
/** @brief Updates the content of a binary EF
|
||||
*
|
||||
* Implementation of this call back is optional and may be NULL.
|
||||
*
|
||||
* @param card struct sc_card object on which to issue the command
|
||||
* @param idx index within the file for the data to be updated
|
||||
* @param buf buffer with the new data
|
||||
* @param count number of bytes to update
|
||||
* @param flags flags for the UPDATE BINARY command (currently not used)
|
||||
* @return number of bytes written or an error code
|
||||
*
|
||||
* @see sc_update_binary()
|
||||
*/
|
||||
int (*update_binary)(struct sc_card *card, unsigned int idx,
|
||||
const u8 * buf, size_t count, unsigned long flags);
|
||||
/**
|
||||
* @brief Sets (part of) the content fo an EF to its logical erased state
|
||||
*
|
||||
* Implementation of this call back is optional and may be NULL.
|
||||
*
|
||||
* @param card struct sc_card object on which to issue the command
|
||||
* @param idx index within the file for the data to be erased
|
||||
* @param count number of bytes to erase
|
||||
* @param flags flags for the ERASE BINARY command (currently not used)
|
||||
* @return number of bytes erased or an error code
|
||||
*
|
||||
* @see sc_erase_binary()
|
||||
*/
|
||||
int (*erase_binary)(struct sc_card *card, unsigned int idx,
|
||||
size_t count, unsigned long flags);
|
||||
|
||||
|
@ -1130,7 +1192,10 @@ int sc_select_file(struct sc_card *card, const sc_path_t *path,
|
|||
*/
|
||||
int sc_list_files(struct sc_card *card, u8 *buf, size_t buflen);
|
||||
/**
|
||||
* Read data from a binary EF
|
||||
* @brief Read data from a binary EF
|
||||
*
|
||||
* If `count` exceeds the card's transmission limits, multiple commands are issued.
|
||||
*
|
||||
* @param card struct sc_card object on which to issue the command
|
||||
* @param idx index within the file with the data to read
|
||||
* @param buf buffer to the read data
|
||||
|
@ -1141,7 +1206,10 @@ int sc_list_files(struct sc_card *card, u8 *buf, size_t buflen);
|
|||
int sc_read_binary(struct sc_card *card, unsigned int idx, u8 * buf,
|
||||
size_t count, unsigned long flags);
|
||||
/**
|
||||
* Write data to a binary EF
|
||||
* @brief Write data to a binary EF
|
||||
*
|
||||
* If `count` exceeds the card's transmission limits, multiple commands are issued.
|
||||
*
|
||||
* @param card struct sc_card object on which to issue the command
|
||||
* @param idx index within the file for the data to be written
|
||||
* @param buf buffer with the data
|
||||
|
@ -1152,7 +1220,10 @@ int sc_read_binary(struct sc_card *card, unsigned int idx, u8 * buf,
|
|||
int sc_write_binary(struct sc_card *card, unsigned int idx, const u8 * buf,
|
||||
size_t count, unsigned long flags);
|
||||
/**
|
||||
* Updates the content of a binary EF
|
||||
* @brief Updates the content of a binary EF
|
||||
*
|
||||
* If `count` exceeds the card's transmission limits, multiple commands are issued.
|
||||
*
|
||||
* @param card struct sc_card object on which to issue the command
|
||||
* @param idx index within the file for the data to be updated
|
||||
* @param buf buffer with the new data
|
||||
|
@ -1169,7 +1240,7 @@ int sc_update_binary(struct sc_card *card, unsigned int idx, const u8 * buf,
|
|||
* @param idx index within the file for the data to be erased
|
||||
* @param count number of bytes to erase
|
||||
* @param flags flags for the ERASE BINARY command (currently not used)
|
||||
* @return number of bytes written or an error code
|
||||
* @return number of bytes erased or an error code
|
||||
*/
|
||||
int sc_erase_binary(struct sc_card *card, unsigned int idx,
|
||||
size_t count, unsigned long flags);
|
||||
|
|
Loading…
Reference in New Issue