CVE-2023-40660

(cherry picked from commit c13ddb45d7e7820b9e595c6294af33f3bfb215e9)
This commit is contained in:
dillon_chen 2023-10-23 16:06:24 +08:00 committed by openeuler-sync-bot
parent bd009f2437
commit 66666248bf
3 changed files with 546 additions and 1 deletions

View File

@ -0,0 +1,50 @@
From 74ddc3636db18ae78de62922a74bfdefae015c76 Mon Sep 17 00:00:00 2001
From: Frank Morgner <frankmorgner@gmail.com>
Date: Wed, 21 Jun 2023 12:27:23 +0200
Subject: [PATCH] Fixed PIN authentication bypass
If two processes are accessing a token, then one process may leave the
card usable with an authenticated PIN so that a key may sign/decrypt any
data. This is especially the case if the token does not support a way of
resetting the authentication status (logout).
We have some tracking of the authentication status in software via
PKCS#11, Minidriver (os-wise) and CryptoTokenKit, which is why a
PIN-prompt will appear even though the card may technically be unlocked
as described in the above example. However, before this change, an empty
PIN was not verified (likely yielding an error during PIN-verification),
but it was just checked whether the PIN is authenticated. This defeats
the purpose of the PIN verification, because an empty PIN is not the
correct one. Especially during OS Logon, we don't want that kind of
shortcut, but we want the user to verify the correct PIN (even though
the token was left unattended and authentication at the computer).
This essentially reverts commit e6f7373ef066cfab6e3162e8b5f692683db23864.
---
src/libopensc/pkcs15-pin.c | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/src/libopensc/pkcs15-pin.c b/src/libopensc/pkcs15-pin.c
index 48e16fdc1c..2402675316 100644
--- a/src/libopensc/pkcs15-pin.c
+++ b/src/libopensc/pkcs15-pin.c
@@ -307,19 +307,6 @@ sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *pi
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_PIN_REFERENCE);
auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data;
- /*
- * if pin cache is disabled, we can get here with no PIN data.
- * in this case, to avoid error or unnecessary pin prompting on pinpad,
- * check if the PIN has been already verified and the access condition
- * is still open on card.
- */
- if (pinlen == 0) {
- r = sc_pkcs15_get_pin_info(p15card, pin_obj);
-
- if (r == SC_SUCCESS && auth_info->logged_in == SC_PIN_STATE_LOGGED_IN)
- LOG_FUNC_RETURN(ctx, r);
- }
-
r = _validate_pin(p15card, auth_info, pinlen);
if (r)

View File

@ -0,0 +1,490 @@
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-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-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;
}

View File

@ -3,7 +3,7 @@
Name: opensc
Version: 0.21.0
Release: 7
Release: 8
License: LGPLv2.1+
Summary: Smart card library and applications
URL: https://github.com/OpenSC/OpenSC/wiki
@ -38,6 +38,8 @@ Patch17: backport-0003-CVE-2021-42782-cardos-Correctly-calculate-the-left.patch
Patch18: backport-0004-CVE-2021-42782-iasecc-Prevent-stack-buffer.patch
Patch19: backport-0005-CVE-2021-42782-PIV-Improved-parsing.patch
Patch20: backport-0006-CVE-2023-2977-correct_left_length_calculation_to_fix_buffer.patch
Patch21: 0003-opensc-CVE-2023-40660-1of2.patch
Patch22: 0004-opensc-CVE-2023-40660-2of2.patch
%description
OpenSC provides a set of libraries and utilities to work with smart cards.
@ -156,6 +158,9 @@ make check
%{_datadir}/opensc/
%changelog
* Mon Oct 23 2023 dillon chen <dillon.chen@gmail.com> - 0.21.0-8
- fix CVE-2023-40660
* Mon Sep 18 2023 dillon chen <dillon.chen@gmail.com> - 0.21.0-7
- fix CVE-2023-2977