opensc/opensc-CVE-2023-40660-2of2.patch
Otto Hollmann 58d3215b4a Accepting request 1116477 from home:ohollmann:branches:security:chipcard
- 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
2023-10-10 12:49:01 +00:00

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;
}