From d2a36c88fd2d02fe20037b736bdc9bfe78dbefb3 Mon Sep 17 00:00:00 2001 From: jey Date: Thu, 21 Feb 2002 19:23:21 +0000 Subject: [PATCH] - added sc_update_binary(), sc_append_binary() and sc_write_binary() with their corresponding ISO 7816-4 reference functions git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@216 c6295689-39f2-0310-b995-f0e70906c6a9 --- src/libopensc/card.c | 39 +++++++++++++++++++ src/libopensc/iso7816.c | 86 ++++++++++++++++++++++++++++++++++++++++- src/libopensc/opensc.h | 24 +++++++++--- 3 files changed, 142 insertions(+), 7 deletions(-) diff --git a/src/libopensc/card.c b/src/libopensc/card.c index 42047883..77f68c3d 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -761,6 +761,45 @@ int sc_read_record(struct sc_card *card, unsigned int rec_nr, u8 *buf, SC_FUNC_RETURN(card->ctx, 2, r); } +int sc_write_record(struct sc_card *card, unsigned int rec_nr, const u8 * buf, + size_t count, unsigned long flags) +{ + int r; + + assert(card != NULL); + SC_FUNC_CALLED(card->ctx, 2); + if (card->ops->write_record == NULL) + SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_NOT_SUPPORTED); + r = card->ops->write_record(card, rec_nr, buf, count, flags); + SC_FUNC_RETURN(card->ctx, 2, r); +} + +int sc_append_record(struct sc_card *card, const u8 * buf, size_t count, + unsigned long flags) +{ + int r; + + assert(card != NULL); + SC_FUNC_CALLED(card->ctx, 2); + if (card->ops->append_record == NULL) + SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_NOT_SUPPORTED); + r = card->ops->append_record(card, buf, count, flags); + SC_FUNC_RETURN(card->ctx, 2, r); +} + +int sc_update_record(struct sc_card *card, unsigned int rec_nr, const u8 * buf, + size_t count, unsigned long flags) +{ + int r; + + assert(card != NULL); + SC_FUNC_CALLED(card->ctx, 2); + if (card->ops->update_record == NULL) + SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_NOT_SUPPORTED); + r = card->ops->update_record(card, rec_nr, buf, count, flags); + SC_FUNC_RETURN(card->ctx, 2, r); +} + inline int sc_card_valid(const struct sc_card *card) { #ifndef NDEBUG assert(card != NULL); diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index e5c65b12..143d6a93 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -123,8 +123,8 @@ static int iso7816_read_record(struct sc_card *card, int r; sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xB2, rec_nr, 0); - apdu.p2 = (flags & SC_READ_RECORD_EF_ID_MASK) << 3; - if (flags & SC_READ_RECORD_BY_REC_NR) + apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3; + if (flags & SC_RECORD_BY_REC_NR) apdu.p2 |= 0x04; apdu.le = count; @@ -140,6 +140,85 @@ static int iso7816_read_record(struct sc_card *card, SC_FUNC_RETURN(card->ctx, 3, apdu.resplen); } +static int iso7816_write_record(struct sc_card *card, unsigned int rec_nr, + const u8 *buf, size_t count, + unsigned long flags) +{ + struct sc_apdu apdu; + int r; + + if (count > 256) { + error(card->ctx, "Trying to send too many bytes\n"); + return SC_ERROR_INVALID_ARGUMENTS; + } + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 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; + + r = sc_transmit_apdu(card, &apdu); + SC_TEST_RET(card->ctx, r, "APDU transmit failed"); + SC_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), + "Card returned error"); + SC_FUNC_RETURN(card->ctx, 3, count); +} + +static int iso7816_append_record(struct sc_card *card, + const u8 *buf, size_t count, + unsigned long flags) +{ + struct sc_apdu apdu; + int r; + + if (count > 256) { + error(card->ctx, "Trying to send too many bytes\n"); + return SC_ERROR_INVALID_ARGUMENTS; + } + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE2, 0, 0); + apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3; + + apdu.lc = count; + apdu.datalen = count; + apdu.data = buf; + + r = sc_transmit_apdu(card, &apdu); + SC_TEST_RET(card->ctx, r, "APDU transmit failed"); + SC_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), + "Card returned error"); + SC_FUNC_RETURN(card->ctx, 3, count); +} + +static int iso7816_update_record(struct sc_card *card, unsigned int rec_nr, + const u8 *buf, size_t count, + unsigned long flags) +{ + struct sc_apdu apdu; + int r; + + if (count > 256) { + error(card->ctx, "Trying to send too many bytes\n"); + return SC_ERROR_INVALID_ARGUMENTS; + } + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 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; + + r = sc_transmit_apdu(card, &apdu); + SC_TEST_RET(card->ctx, r, "APDU transmit failed"); + SC_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), + "Card returned error"); + SC_FUNC_RETURN(card->ctx, 3, count); +} + static int iso7816_write_binary(struct sc_card *card, unsigned int idx, const u8 *buf, size_t count, unsigned long flags) @@ -766,6 +845,9 @@ const struct sc_card_driver * sc_get_iso7816_driver(void) iso_ops.match_card = no_match; iso_ops.read_binary = iso7816_read_binary; iso_ops.read_record = iso7816_read_record; + iso_ops.write_record = iso7816_write_record; + iso_ops.append_record = iso7816_append_record; + iso_ops.update_record = iso7816_update_record; iso_ops.write_binary = iso7816_write_binary; iso_ops.update_binary = iso7816_update_binary; iso_ops.select_file = iso7816_select_file; diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 3dfec4fb..703c84e6 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -138,11 +138,11 @@ extern "C" { #define SC_MAX_AC_OPS 7 -/* sc_read_record() flags */ -#define SC_READ_RECORD_EF_ID_MASK 0x0001F -#define SC_READ_RECORD_BY_REC_ID 0x00000 -#define SC_READ_RECORD_BY_REC_NR 0x00100 -#define SC_READ_RECORD_CURRENT 0 +/* sc_*_record() flags */ +#define SC_RECORD_EF_ID_MASK 0x0001F +#define SC_RECORD_BY_REC_ID 0x00000 +#define SC_RECORD_BY_REC_NR 0x00100 +#define SC_RECORD_CURRENT 0 /* various maximum values */ #define SC_MAX_CARD_DRIVERS 16 @@ -327,8 +327,15 @@ struct sc_card_operations { const u8 * buf, size_t count, unsigned long flags); int (*erase_binary)(struct sc_card *card, unsigned int idx, size_t count, unsigned long flags); + int (*read_record)(struct sc_card *card, unsigned int rec_nr, u8 * buf, size_t count, unsigned long flags); + int (*write_record)(struct sc_card *card, unsigned int rec_nr, + const u8 * buf, size_t count, unsigned long flags); + int (*append_record)(struct sc_card *card, const u8 * buf, + size_t count, unsigned long flags); + int (*update_record)(struct sc_card *card, unsigned int rec_nr, + const u8 * buf, size_t count, unsigned long flags); /* select_file: Does the equivalent of SELECT FILE command specified * in ISO7816-4. Stores information about the selected file to @@ -545,6 +552,13 @@ int sc_update_binary(struct sc_card *card, unsigned int idx, const u8 * buf, */ int sc_read_record(struct sc_card *card, unsigned int rec_nr, u8 * buf, size_t count, unsigned long flags); +int sc_write_record(struct sc_card *card, unsigned int rec_nr, const u8 * buf, + size_t count, unsigned long flags); +int sc_append_record(struct sc_card *card, const u8 * buf, size_t count, + unsigned long flags); +int sc_update_record(struct sc_card *card, unsigned int rec_nr, const u8 * buf, + size_t count, unsigned long flags); + int sc_get_challenge(struct sc_card *card, u8 * rndout, size_t len); /* ISO 7816-8 related functions */