58d3215b4a
- Security Fix: [CVE-2023-40661, bsc#1215761] * opensc: multiple memory issues with pkcs15-init (enrollment tool) * Add patches: - opensc-CVE-2023-40661-1of12.patch - opensc-CVE-2023-40661-2of12.patch - opensc-CVE-2023-40661-3of12.patch - opensc-CVE-2023-40661-4of12.patch - opensc-CVE-2023-40661-5of12.patch - opensc-CVE-2023-40661-6of12.patch - opensc-CVE-2023-40661-7of12.patch - opensc-CVE-2023-40661-8of12.patch - opensc-CVE-2023-40661-9of12.patch - opensc-CVE-2023-40661-10of12.patch - opensc-CVE-2023-40661-11of12.patch - opensc-CVE-2023-40661-12of12.patch - Security Fix: [CVE-2023-4535, bsc#1215763] * Add patches: - opensc-CVE-2023-4535.patch - opensc-NULL_pointer_fix.patch - Security Fix: [CVE-2023-40660, bsc#1215762] * opensc: PIN bypass when card tracks its own login state * Add patches: - opensc-CVE-2023-40660-1of2.patch - opensc-CVE-2023-40660-2of2.patch OBS-URL: https://build.opensuse.org/request/show/1116477 OBS-URL: https://build.opensuse.org/package/show/security:chipcard/opensc?expand=0&rev=75
514 lines
15 KiB
Diff
514 lines
15 KiB
Diff
From d7fadae950f6d33b32f979759c06ab78a3475c22 Mon Sep 17 00:00:00 2001
|
|
From: Frank Morgner <frankmorgner@gmail.com>
|
|
Date: Wed, 21 Jun 2023 13:49:40 +0200
|
|
Subject: [PATCH 01/15] PIV: implemented logout
|
|
|
|
---
|
|
src/libopensc/card-asepcos.c | 15 +++++++++++++
|
|
src/libopensc/card-authentic.c | 11 ++++++++++
|
|
src/libopensc/card-cac.c | 10 ++++++---
|
|
src/libopensc/card-cac1.c | 10 ++++++---
|
|
src/libopensc/card-coolkey.c | 3 --
|
|
src/libopensc/card-edo.c | 7 ++++++
|
|
src/libopensc/card-epass2003.c | 18 ++++++++++++++++
|
|
src/libopensc/card-esteid2018.c | 5 ++++
|
|
src/libopensc/card-gemsafeV1.c | 8 +++++++
|
|
src/libopensc/card-isoApplet.c | 8 +++++++
|
|
src/libopensc/card-jpki.c | 6 +++++
|
|
src/libopensc/card-mcrd.c | 10 +++++++++
|
|
src/libopensc/card-muscle.c | 18 ++++++++++++----
|
|
src/libopensc/card-piv.c | 20 ++++++++++--------
|
|
src/libopensc/card-starcos.c | 11 ----------
|
|
src/libopensc/card-westcos.c | 44 ++++++++++++++++++++++++----------------
|
|
16 files changed, 155 insertions(+), 49 deletions(-)
|
|
|
|
--- a/src/libopensc/card-asepcos.c
|
|
+++ b/src/libopensc/card-asepcos.c
|
|
@@ -1050,6 +1050,20 @@ static int asepcos_card_reader_lock_obta
|
|
LOG_FUNC_RETURN(card->ctx, r);
|
|
}
|
|
|
|
+static int asepcos_logout(sc_card_t *card)
|
|
+{
|
|
+ int r = SC_ERROR_NOT_SUPPORTED;
|
|
+
|
|
+ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
|
|
+
|
|
+ if (card->type == SC_CARD_TYPE_ASEPCOS_JAVA) {
|
|
+ /* in case of a Java card try to select the ASEPCOS applet */
|
|
+ r = asepcos_select_asepcos_applet(card);
|
|
+ }
|
|
+
|
|
+ LOG_FUNC_RETURN(card->ctx, r);
|
|
+}
|
|
+
|
|
static struct sc_card_driver * sc_get_driver(void)
|
|
{
|
|
if (iso_ops == NULL)
|
|
@@ -1066,6 +1080,7 @@ static struct sc_card_driver * sc_get_dr
|
|
asepcos_ops.list_files = asepcos_list_files;
|
|
asepcos_ops.card_ctl = asepcos_card_ctl;
|
|
asepcos_ops.pin_cmd = asepcos_pin_cmd;
|
|
+ asepcos_ops.logout = asepcos_logout;
|
|
asepcos_ops.card_reader_lock_obtained = asepcos_card_reader_lock_obtained;
|
|
|
|
return &asepcos_drv;
|
|
--- a/src/libopensc/card-authentic.c
|
|
+++ b/src/libopensc/card-authentic.c
|
|
@@ -2311,6 +2311,17 @@ authentic_sm_get_wrapped_apdu(struct sc_
|
|
}
|
|
#endif
|
|
|
|
+int authentic_logout(sc_card_t *card)
|
|
+{
|
|
+ int r = SC_ERROR_NOT_SUPPORTED;
|
|
+
|
|
+ if (card->type == SC_CARD_TYPE_OBERTHUR_AUTHENTIC_3_2) {
|
|
+ r = authentic_select_aid(card, aid_AuthentIC_3_2, sizeof(aid_AuthentIC_3_2), NULL, NULL);
|
|
+ }
|
|
+
|
|
+ return r;
|
|
+}
|
|
+
|
|
static struct sc_card_driver *
|
|
sc_get_driver(void)
|
|
{
|
|
--- a/src/libopensc/card-cac.c
|
|
+++ b/src/libopensc/card-cac.c
|
|
@@ -1831,9 +1831,6 @@ static int cac_match_card(sc_card_t *car
|
|
{
|
|
int r;
|
|
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
|
|
- /* Since we send an APDU, the card's logout function may be called...
|
|
- * however it may be in dirty memory */
|
|
- card->ops->logout = NULL;
|
|
|
|
r = cac_find_and_initialize(card, 0);
|
|
return (r == SC_SUCCESS); /* never match */
|
|
@@ -1862,6 +1859,12 @@ static int cac_init(sc_card_t *card)
|
|
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
|
|
}
|
|
|
|
+static int cac_logout(sc_card_t *card)
|
|
+{
|
|
+ int index;
|
|
+ return cac_find_first_pki_applet(card, &index);
|
|
+}
|
|
+
|
|
static int cac_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left)
|
|
{
|
|
/* CAC, like PIV needs Extra validation of (new) PIN during
|
|
@@ -1933,6 +1936,7 @@ static struct sc_card_driver * sc_get_dr
|
|
cac_ops.decipher = cac_decipher;
|
|
cac_ops.card_ctl = cac_card_ctl;
|
|
cac_ops.pin_cmd = cac_pin_cmd;
|
|
+ cac_ops.logout = cac_logout;
|
|
|
|
return &cac_drv;
|
|
}
|
|
--- a/src/libopensc/card-cac1.c
|
|
+++ b/src/libopensc/card-cac1.c
|
|
@@ -498,9 +498,6 @@ static int cac_match_card(sc_card_t *car
|
|
{
|
|
int r;
|
|
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
|
|
- /* Since we send an APDU, the card's logout function may be called...
|
|
- * however it may be in dirty memory */
|
|
- card->ops->logout = NULL;
|
|
|
|
r = cac_find_and_initialize(card, 0);
|
|
return (r == SC_SUCCESS); /* never match */
|
|
@@ -529,6 +526,12 @@ static int cac_init(sc_card_t *card)
|
|
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
|
|
}
|
|
|
|
+static int cac_logout(sc_card_t *card)
|
|
+{
|
|
+ int index;
|
|
+ return cac_find_first_pki_applet(card, &index);
|
|
+}
|
|
+
|
|
static struct sc_card_operations cac_ops;
|
|
|
|
static struct sc_card_driver cac1_drv = {
|
|
@@ -550,6 +553,7 @@ static struct sc_card_driver * sc_get_dr
|
|
|
|
cac_ops.select_file = cac_select_file; /* need to record object type */
|
|
cac_ops.read_binary = cac_read_binary;
|
|
+ cac_ops.logout = cac_logout;
|
|
|
|
return &cac1_drv;
|
|
}
|
|
--- a/src/libopensc/card-coolkey.c
|
|
+++ b/src/libopensc/card-coolkey.c
|
|
@@ -2264,9 +2264,6 @@ static int coolkey_match_card(sc_card_t
|
|
int r;
|
|
|
|
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
|
|
- /* Since we send an APDU, the card's logout function may be called...
|
|
- * however it may be in dirty memory */
|
|
- card->ops->logout = NULL;
|
|
|
|
r = coolkey_select_applet(card);
|
|
if (r == SC_SUCCESS) {
|
|
--- a/src/libopensc/card-edo.c
|
|
+++ b/src/libopensc/card-edo.c
|
|
@@ -302,6 +302,12 @@ static int edo_init(sc_card_t* card) {
|
|
}
|
|
|
|
|
|
+static int edo_logout(sc_card_t* card) {
|
|
+ sc_sm_stop(card);
|
|
+ return edo_unlock(card);
|
|
+}
|
|
+
|
|
+
|
|
struct sc_card_driver* sc_get_edo_driver(void) {
|
|
edo_ops = *sc_get_iso7816_driver()->ops;
|
|
edo_ops.match_card = edo_match_card;
|
|
@@ -309,6 +315,7 @@ struct sc_card_driver* sc_get_edo_driver
|
|
edo_ops.select_file = edo_select_file;
|
|
edo_ops.set_security_env = edo_set_security_env;
|
|
edo_ops.compute_signature = edo_compute_signature;
|
|
+ edo_ops.logout = edo_logout;
|
|
|
|
return &edo_drv;
|
|
}
|
|
--- a/src/libopensc/card-epass2003.c
|
|
+++ b/src/libopensc/card-epass2003.c
|
|
@@ -3278,6 +3278,23 @@ epass2003_pin_cmd(struct sc_card *card,
|
|
return r;
|
|
}
|
|
|
|
+static int
|
|
+epass2003_logout(struct sc_card *card)
|
|
+{
|
|
+ epass2003_exdata *exdata = NULL;
|
|
+
|
|
+ if (!card->drv_data)
|
|
+ return SC_ERROR_INVALID_ARGUMENTS;
|
|
+
|
|
+ exdata = (epass2003_exdata *)card->drv_data;
|
|
+ if (exdata->sm) {
|
|
+ sc_sm_stop(card);
|
|
+ return epass2003_refresh(card);
|
|
+ }
|
|
+
|
|
+ return SC_ERROR_NOT_SUPPORTED;
|
|
+}
|
|
+
|
|
static struct sc_card_driver *sc_get_driver(void)
|
|
{
|
|
struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
|
|
@@ -3307,6 +3324,7 @@ static struct sc_card_driver *sc_get_dri
|
|
epass2003_ops.pin_cmd = epass2003_pin_cmd;
|
|
epass2003_ops.check_sw = epass2003_check_sw;
|
|
epass2003_ops.get_challenge = epass2003_get_challenge;
|
|
+ epass2003_ops.logout = epass2003_logout;
|
|
return &epass2003_drv;
|
|
}
|
|
|
|
--- a/src/libopensc/card-esteid2018.c
|
|
+++ b/src/libopensc/card-esteid2018.c
|
|
@@ -306,6 +306,10 @@ static int esteid_finish(sc_card_t *card
|
|
return 0;
|
|
}
|
|
|
|
+static int esteid_logout(sc_card_t *card) {
|
|
+ return gp_select_aid(card, &IASECC_AID);
|
|
+}
|
|
+
|
|
struct sc_card_driver *sc_get_esteid2018_driver(void) {
|
|
struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
|
|
|
|
@@ -323,6 +327,7 @@ struct sc_card_driver *sc_get_esteid2018
|
|
esteid_ops.set_security_env = esteid_set_security_env;
|
|
esteid_ops.compute_signature = esteid_compute_signature;
|
|
esteid_ops.pin_cmd = esteid_pin_cmd;
|
|
+ esteid_ops.logout = esteid_logout;
|
|
|
|
return &esteid2018_driver;
|
|
}
|
|
--- a/src/libopensc/card-gemsafeV1.c
|
|
+++ b/src/libopensc/card-gemsafeV1.c
|
|
@@ -582,6 +582,13 @@ static int gemsafe_card_reader_lock_obta
|
|
LOG_FUNC_RETURN(card->ctx, r);
|
|
}
|
|
|
|
+static int gemsafe_logout(sc_card_t *card)
|
|
+{
|
|
+ gemsafe_exdata *exdata = (gemsafe_exdata *)card->drv_data;
|
|
+
|
|
+ return gp_select_applet(card, exdata->aid, exdata->aid_len);
|
|
+}
|
|
+
|
|
static struct sc_card_driver *sc_get_driver(void)
|
|
{
|
|
struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
|
|
@@ -602,6 +609,7 @@ static struct sc_card_driver *sc_get_dri
|
|
gemsafe_ops.process_fci = gemsafe_process_fci;
|
|
gemsafe_ops.pin_cmd = iso_ops->pin_cmd;
|
|
gemsafe_ops.card_reader_lock_obtained = gemsafe_card_reader_lock_obtained;
|
|
+ gemsafe_ops.logout = gemsafe_logout;
|
|
|
|
return &gemsafe_drv;
|
|
}
|
|
--- a/src/libopensc/card-isoApplet.c
|
|
+++ b/src/libopensc/card-isoApplet.c
|
|
@@ -1244,6 +1244,13 @@ static int isoApplet_card_reader_lock_ob
|
|
LOG_FUNC_RETURN(card->ctx, r);
|
|
}
|
|
|
|
+static int isoApplet_logout(sc_card_t *card)
|
|
+{
|
|
+ size_t rlen = SC_MAX_APDU_BUFFER_SIZE;
|
|
+ u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
|
+ return isoApplet_select_applet(card, isoApplet_aid, sizeof(isoApplet_aid), rbuf, &rlen);
|
|
+}
|
|
+
|
|
static struct sc_card_driver *sc_get_driver(void)
|
|
{
|
|
sc_card_driver_t *iso_drv = sc_get_iso7816_driver();
|
|
@@ -1267,6 +1274,7 @@ static struct sc_card_driver *sc_get_dri
|
|
isoApplet_ops.compute_signature = isoApplet_compute_signature;
|
|
isoApplet_ops.get_challenge = isoApplet_get_challenge;
|
|
isoApplet_ops.card_reader_lock_obtained = isoApplet_card_reader_lock_obtained;
|
|
+ isoApplet_ops.logout = isoApplet_logout;
|
|
|
|
/* unsupported functions */
|
|
isoApplet_ops.write_binary = NULL;
|
|
--- a/src/libopensc/card-jpki.c
|
|
+++ b/src/libopensc/card-jpki.c
|
|
@@ -361,6 +361,11 @@ static int jpki_card_reader_lock_obtaine
|
|
LOG_FUNC_RETURN(card->ctx, r);
|
|
}
|
|
|
|
+static int jpki_logout(sc_card_t *card)
|
|
+{
|
|
+ return jpki_select_ap(card);
|
|
+}
|
|
+
|
|
static struct sc_card_driver *
|
|
sc_get_driver(void)
|
|
{
|
|
@@ -375,6 +380,7 @@ sc_get_driver(void)
|
|
jpki_ops.set_security_env = jpki_set_security_env;
|
|
jpki_ops.compute_signature = jpki_compute_signature;
|
|
jpki_ops.card_reader_lock_obtained = jpki_card_reader_lock_obtained;
|
|
+ jpki_ops.logout = jpki_logout;
|
|
|
|
return &jpki_drv;
|
|
}
|
|
--- a/src/libopensc/card-mcrd.c
|
|
+++ b/src/libopensc/card-mcrd.c
|
|
@@ -1174,6 +1174,15 @@ static int mcrd_pin_cmd(sc_card_t * card
|
|
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, iso_ops->pin_cmd(card, data, tries_left));
|
|
}
|
|
|
|
+static int mcrd_logout(sc_card_t * card)
|
|
+{
|
|
+ if (card->type == SC_CARD_TYPE_MCRD_ESTEID_V30) {
|
|
+ return gp_select_aid(card, &EstEID_v35_AID);
|
|
+ } else {
|
|
+ return SC_ERROR_NOT_SUPPORTED;
|
|
+ }
|
|
+}
|
|
+
|
|
/* Driver binding */
|
|
static struct sc_card_driver *sc_get_driver(void)
|
|
{
|
|
@@ -1190,6 +1199,7 @@ static struct sc_card_driver *sc_get_dri
|
|
mcrd_ops.compute_signature = mcrd_compute_signature;
|
|
mcrd_ops.decipher = mcrd_decipher;
|
|
mcrd_ops.pin_cmd = mcrd_pin_cmd;
|
|
+ mcrd_ops.logout = mcrd_logout;
|
|
|
|
return &mcrd_drv;
|
|
}
|
|
--- a/src/libopensc/card-muscle.c
|
|
+++ b/src/libopensc/card-muscle.c
|
|
@@ -81,10 +81,6 @@ static int muscle_match_card(sc_card_t *
|
|
u8 response[64];
|
|
int r;
|
|
|
|
- /* Since we send an APDU, the card's logout function may be called...
|
|
- * however it's not always properly nulled out... */
|
|
- card->ops->logout = NULL;
|
|
-
|
|
if (msc_select_applet(card, muscleAppletId, sizeof muscleAppletId) == 1) {
|
|
/* Muscle applet is present, check the protocol version to be sure */
|
|
sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x3C, 0x00, 0x00);
|
|
@@ -853,6 +849,19 @@ static int muscle_card_reader_lock_obtai
|
|
LOG_FUNC_RETURN(card->ctx, r);
|
|
}
|
|
|
|
+static int muscle_logout(sc_card_t *card)
|
|
+{
|
|
+ int r = SC_ERROR_NOT_SUPPORTED;
|
|
+
|
|
+ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
|
|
+
|
|
+ if (msc_select_applet(card, muscleAppletId, sizeof muscleAppletId) == 1) {
|
|
+ r = SC_SUCCESS;
|
|
+ }
|
|
+
|
|
+ LOG_FUNC_RETURN(card->ctx, r);
|
|
+}
|
|
+
|
|
|
|
static struct sc_card_driver * sc_get_driver(void)
|
|
{
|
|
@@ -881,6 +890,7 @@ static struct sc_card_driver * sc_get_dr
|
|
muscle_ops.delete_file = muscle_delete_file;
|
|
muscle_ops.list_files = muscle_list_files;
|
|
muscle_ops.card_reader_lock_obtained = muscle_card_reader_lock_obtained;
|
|
+ muscle_ops.logout = muscle_logout;
|
|
|
|
return &muscle_drv;
|
|
}
|
|
--- a/src/libopensc/card-piv.c
|
|
+++ b/src/libopensc/card-piv.c
|
|
@@ -2183,11 +2183,11 @@ static int piv_is_object_present(sc_card
|
|
* or the global pin for the card 0x00. Look at Discovery object to get this.
|
|
* called by pkcs15-piv.c via cardctl when setting up the pins.
|
|
*/
|
|
-static int piv_get_pin_preference(sc_card_t *card, int *ptr)
|
|
+static int piv_get_pin_preference(sc_card_t *card, int *pin_ref)
|
|
{
|
|
piv_private_data_t * priv = PIV_DATA(card);
|
|
|
|
- *ptr = priv->pin_preference;
|
|
+ *pin_ref = priv->pin_preference;
|
|
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
|
|
}
|
|
|
|
@@ -3082,10 +3082,6 @@ static int piv_match_card_continued(sc_c
|
|
piv_private_data_t *priv = NULL;
|
|
int saved_type = card->type;
|
|
|
|
- /* Since we send an APDU, the card's logout function may be called...
|
|
- * however it may be in dirty memory */
|
|
- card->ops->logout = NULL;
|
|
-
|
|
/* piv_match_card may be called with card->type, set by opensc.conf */
|
|
/* user provide card type must be one we know */
|
|
switch (card->type) {
|
|
@@ -3747,12 +3743,18 @@ piv_pin_cmd(sc_card_t *card, struct sc_p
|
|
|
|
static int piv_logout(sc_card_t *card)
|
|
{
|
|
- int r = SC_ERROR_NOT_SUPPORTED; /* TODO Some PIV cards may support a logout */
|
|
- /* piv_private_data_t * priv = PIV_DATA(card); */
|
|
+ int r = SC_ERROR_NOT_SUPPORTED;
|
|
+ piv_private_data_t * priv = PIV_DATA(card);
|
|
|
|
LOG_FUNC_CALLED(card->ctx);
|
|
|
|
- /* TODO 800-73-3 does not define a logout, 800-73-4 does */
|
|
+ if (priv) {
|
|
+ /* logout defined since 800-73-4 */
|
|
+ r = iso7816_logout(card, priv->pin_preference);
|
|
+ if (r == SC_SUCCESS) {
|
|
+ priv->logged_in = SC_PIN_STATE_LOGGED_OUT;
|
|
+ }
|
|
+ }
|
|
|
|
LOG_FUNC_RETURN(card->ctx, r);
|
|
}
|
|
--- a/src/libopensc/card-starcos.c
|
|
+++ b/src/libopensc/card-starcos.c
|
|
@@ -2150,18 +2150,9 @@ static int starcos_card_ctl(sc_card_t *c
|
|
}
|
|
}
|
|
|
|
-/**
|
|
- * starcos_logout_v3_x()
|
|
- * StarCOS 3.x cards will not clear the security status by selecting MF.
|
|
- * Returning NOT_SUPPORTED would cause card reset, effectively invalidating
|
|
- * the security status.
|
|
- */
|
|
static int starcos_logout_v3_x(sc_card_t *card)
|
|
{
|
|
- int r = SC_ERROR_NOT_SUPPORTED;
|
|
- SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_NORMAL);
|
|
-
|
|
- SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
|
|
+ return SC_ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
static int starcos_logout(sc_card_t *card)
|
|
--- a/src/libopensc/card-westcos.c
|
|
+++ b/src/libopensc/card-westcos.c
|
|
@@ -166,6 +166,26 @@ static int westcos_finish(sc_card_t * ca
|
|
return 0;
|
|
}
|
|
|
|
+static int select_westcos_applet(sc_card_t *card)
|
|
+{
|
|
+ int r;
|
|
+ sc_apdu_t apdu;
|
|
+ u8 aid[] = {
|
|
+ 0xA0, 0x00, 0xCE, 0x00, 0x07, 0x01
|
|
+ };
|
|
+ sc_format_apdu(card, &apdu,
|
|
+ SC_APDU_CASE_3_SHORT, 0xA4, 0x04,
|
|
+ 0);
|
|
+ apdu.cla = 0x00;
|
|
+ apdu.lc = sizeof(aid);
|
|
+ apdu.datalen = sizeof(aid);
|
|
+ apdu.data = aid;
|
|
+ r = sc_transmit_apdu(card, &apdu);
|
|
+ if (r)
|
|
+ return r;
|
|
+ return sc_check_sw(card, apdu.sw1, apdu.sw2);
|
|
+}
|
|
+
|
|
static int westcos_match_card(sc_card_t * card)
|
|
{
|
|
int i;
|
|
@@ -176,23 +196,7 @@ static int westcos_match_card(sc_card_t
|
|
|
|
/* JAVACARD, look for westcos applet */
|
|
if (i == 1) {
|
|
- int r;
|
|
- sc_apdu_t apdu;
|
|
- u8 aid[] = {
|
|
- 0xA0, 0x00, 0xCE, 0x00, 0x07, 0x01
|
|
- };
|
|
- sc_format_apdu(card, &apdu,
|
|
- SC_APDU_CASE_3_SHORT, 0xA4, 0x04,
|
|
- 0);
|
|
- apdu.cla = 0x00;
|
|
- apdu.lc = sizeof(aid);
|
|
- apdu.datalen = sizeof(aid);
|
|
- apdu.data = aid;
|
|
- r = sc_transmit_apdu(card, &apdu);
|
|
- if (r)
|
|
- return 0;
|
|
- r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
|
- if (r)
|
|
+ if (select_westcos_applet(card))
|
|
return 0;
|
|
}
|
|
|
|
@@ -1257,6 +1261,11 @@ static int westcos_decipher(sc_card_t *c
|
|
return westcos_sign_decipher(1, card, crgram, crgram_len, out, outlen);
|
|
}
|
|
|
|
+static int westcos_logout(sc_card_t *card)
|
|
+{
|
|
+ return select_westcos_applet(card);
|
|
+}
|
|
+
|
|
struct sc_card_driver *sc_get_westcos_driver(void)
|
|
{
|
|
if (iso_ops == NULL)
|
|
@@ -1288,6 +1297,7 @@ struct sc_card_driver *sc_get_westcos_dr
|
|
westcos_ops.process_fci = westcos_process_fci;
|
|
westcos_ops.construct_fci = NULL;
|
|
westcos_ops.pin_cmd = westcos_pin_cmd;
|
|
+ westcos_ops.logout = westcos_logout;
|
|
|
|
return &westcos_drv;
|
|
}
|