Compare commits

...

10 Commits

Author SHA1 Message Date
openeuler-ci-bot
c1233c731f
!88 [sync] PR-83: fix CVE-2024-8443, CVE-2024-45615, CVE-2024-45616, CVE-2024-45617, CVE-2024-45618, CVE-2024-45619, CVE-2024-45620
From: @openeuler-sync-bot 
Reviewed-by: @dillon_chen 
Signed-off-by: @dillon_chen
2024-10-09 00:56:58 +00:00
Funda Wang
fc2191d583 fix CVE-2024-8443, CVE-2024-45615, CVE-2024-45616, CVE-2024-45617, CVE-2024-45618, CVE-2024-45619, CVE-2024-45620
(cherry picked from commit 0f4d609fb73dc7d87793031f6ea3dd142dc6ff8b)
2024-10-08 16:37:40 +08:00
openeuler-ci-bot
c73b3eb46d
!73 fix CVE-2023-5992
From: @dillon_chen 
Reviewed-by: @overweight 
Signed-off-by: @overweight
2024-07-02 01:01:02 +00:00
dillon_chen
9738770d9c fix CVE-2023-5992.patch 2024-07-01 16:18:34 +08:00
openeuler-ci-bot
a90d4fc2ae
!69 [sync] PR-63: [sync] PR-61: fix CVE-2023-40661
From: @openeuler-sync-bot 
Reviewed-by: @dillon_chen 
Signed-off-by: @dillon_chen
2023-11-21 06:57:37 +00:00
dillon_chen
26f384cd78 fix CVE-2023-40661
(cherry picked from commit d12aec18ec9df597ac79a4ce38d8438a1144e0b3)
(cherry picked from commit 255765d8527bfca0b947c048e822095113aee2af)
2023-11-21 14:43:22 +08:00
openeuler-ci-bot
423ce97c26
!59 [sync] PR-57: CVE-2023-40660
From: @openeuler-sync-bot 
Reviewed-by: @dillon_chen 
Signed-off-by: @dillon_chen
2023-10-25 03:43:58 +00:00
dillon_chen
66666248bf CVE-2023-40660
(cherry picked from commit c13ddb45d7e7820b9e595c6294af33f3bfb215e9)
2023-10-24 17:18:22 +08:00
openeuler-ci-bot
bd009f2437
!53 [sync] PR-52: CVE-2023-2977
From: @openeuler-sync-bot 
Reviewed-by: @dillon_chen 
Signed-off-by: @dillon_chen
2023-09-18 09:44:53 +00:00
dillon_chen
fdbb13931c CVE-2023-2977
(cherry picked from commit 3611e52982ea35f1552bf36f0e960cbbd621be57)
2023-09-18 17:35:19 +08:00
24 changed files with 2747 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

@ -0,0 +1,23 @@
From 578aed8391ef117ca64a9e0cba8e5c264368a0ec Mon Sep 17 00:00:00 2001
From: Frank Morgner <frankmorgner@gmail.com>
Date: Thu, 8 Dec 2022 00:27:18 +0100
Subject: [PATCH] sc_pkcs15init_rmdir: prevent out of bounds write
fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=53927
---
src/pkcs15init/pkcs15-lib.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c
index 91cee37310..3df03c6e1f 100644
--- a/src/pkcs15init/pkcs15-lib.c
+++ b/src/pkcs15init/pkcs15-lib.c
@@ -685,6 +685,8 @@ sc_pkcs15init_rmdir(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
path = df->path;
path.len += 2;
+ if (path.len > SC_MAX_PATH_SIZE)
+ return SC_ERROR_INTERNAL;
nfids = r / 2;
while (r >= 0 && nfids--) {

View File

@ -0,0 +1,25 @@
From df5a176bfdf8c52ba89c7fef1f82f6f3b9312bc1 Mon Sep 17 00:00:00 2001
From: Veronika Hanulikova <xhanulik@fi.muni.cz>
Date: Fri, 10 Feb 2023 11:47:34 +0100
Subject: [PATCH] Check array bounds
Thanks OSS-Fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=54312
---
src/libopensc/muscle.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/libopensc/muscle.c b/src/libopensc/muscle.c
index 61a4ec24d8..9d01e0c113 100644
--- a/src/libopensc/muscle.c
+++ b/src/libopensc/muscle.c
@@ -181,6 +181,9 @@ int msc_partial_update_object(sc_card_t *card, msc_id objectId, int offset, cons
sc_apdu_t apdu;
int r;
+ if (dataLength + 9 > MSC_MAX_APDU)
+ return SC_ERROR_INVALID_ARGUMENTS;
+
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x54, 0x00, 0x00);
apdu.lc = dataLength + 9;
if (card->ctx->debug >= 2)

View File

@ -0,0 +1,37 @@
From 5631e9843c832a99769def85b7b9b68b4e3e3959 Mon Sep 17 00:00:00 2001
From: Veronika Hanulikova <xhanulik@fi.muni.cz>
Date: Fri, 3 Mar 2023 16:07:38 +0100
Subject: [PATCH] Check length of string before making copy
Thanks OSS-Fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=55851
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=55998
---
src/pkcs15init/profile.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/pkcs15init/profile.c b/src/pkcs15init/profile.c
index 2b793b0282..3bad1e8536 100644
--- a/src/pkcs15init/profile.c
+++ b/src/pkcs15init/profile.c
@@ -1575,7 +1575,10 @@ do_acl(struct state *cur, int argc, char **argv)
while (argc--) {
unsigned int op, method, id;
+ if (strlen(*argv) >= sizeof(oper))
+ goto bad;
strlcpy(oper, *argv++, sizeof(oper));
+
if ((what = strchr(oper, '=')) == NULL)
goto bad;
*what++ = '\0';
@@ -2288,6 +2291,9 @@ get_authid(struct state *cur, const char *value,
return get_uint(cur, value, type);
}
+ if (strlen(value) >= sizeof(temp))
+ return 1;
+
n = strcspn(value, "0123456789x");
strlcpy(temp, value, (sizeof(temp) > n) ? n + 1 : sizeof(temp));

View File

@ -0,0 +1,396 @@
From aadd82bb071e574fc57263a103e3bf06ebbd8de7 Mon Sep 17 00:00:00 2001
From: "Ingo Struck (git commits)" <gitlab@ingostruck.de>
Date: Sat, 21 Jan 2023 22:15:10 +0100
Subject: [PATCH] Handle reader limits for SC Card unwrap operations
Fixes #2514
---
src/libopensc/card-sc-hsm.c | 181 ++++++++++++++-----------
src/libopensc/reader-pcsc.c | 91 ++++++++-----
src/tests/fuzzing/fuzz_pkcs15_decode.c | 3 +-
src/tests/fuzzing/fuzz_pkcs15_encode.c | 2 +-
4 files changed, 159 insertions(+), 118 deletions(-)
diff --git a/src/libopensc/card-sc-hsm.c b/src/libopensc/card-sc-hsm.c
index 60d5895127..1b707f08df 100644
--- a/src/libopensc/card-sc-hsm.c
+++ b/src/libopensc/card-sc-hsm.c
@@ -145,9 +145,7 @@ static int sc_hsm_select_file_ex(sc_card_t *card,
if (file_out == NULL) { // Versions before 0.16 of the SmartCard-HSM do not support P2='0C'
rv = sc_hsm_select_file_ex(card, in_path, forceselect, &file);
- if (file != NULL) {
- sc_file_free(file);
- }
+ sc_file_free(file);
return rv;
}
@@ -181,9 +179,7 @@ static int sc_hsm_select_file_ex(sc_card_t *card,
LOG_TEST_RET(card->ctx, rv, "Could not select SmartCard-HSM application");
if (priv) {
- if (priv->dffcp != NULL) {
- sc_file_free(priv->dffcp);
- }
+ sc_file_free(priv->dffcp);
// Cache the FCP returned when selecting the applet
sc_file_dup(&priv->dffcp, *file_out);
}
@@ -730,12 +726,12 @@ static int sc_hsm_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
u8 recvbuf[SC_MAX_APDU_BUFFER_SIZE];
#ifdef ENABLE_SM
if (card->sm_ctx.sm_mode != SM_MODE_TRANSMIT) {
- sc_log(card->ctx,
+ sc_log(card->ctx,
"Session PIN generation only supported in SM");
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
#else
- sc_log(card->ctx,
+ sc_log(card->ctx,
"Session PIN generation only supported in SM");
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
#endif
@@ -746,7 +742,7 @@ static int sc_hsm_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
apdu.le = 0;
if (sc_transmit_apdu(card, &apdu) != SC_SUCCESS
|| sc_check_sw(card, apdu.sw1, apdu.sw2) != SC_SUCCESS) {
- sc_log(card->ctx,
+ sc_log(card->ctx,
"Generating session PIN failed");
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
@@ -756,12 +752,12 @@ static int sc_hsm_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
apdu.resplen);
data->pin2.len = apdu.resplen;
} else {
- sc_log(card->ctx,
+ sc_log(card->ctx,
"Buffer too small for session PIN");
}
}
} else {
- sc_log(card->ctx,
+ sc_log(card->ctx,
"Session PIN not supported for this PIN (0x%02X)",
data->pin_reference);
}
@@ -848,47 +844,61 @@ static int sc_hsm_write_ef(sc_card_t *card,
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
}
- p = cmdbuff;
- *p++ = 0x54;
- *p++ = 0x02;
- *p++ = (idx >> 8) & 0xFF;
- *p++ = idx & 0xFF;
- *p++ = 0x53;
- if (count < 128) {
- *p++ = (u8) count;
- len = 6;
- } else if (count < 256) {
- *p++ = 0x81;
- *p++ = (u8) count;
- len = 7;
- } else {
- *p++ = 0x82;
- *p++ = (count >> 8) & 0xFF;
- *p++ = count & 0xFF;
- len = 8;
- }
+ size_t bytes_left = count;
+ // 8 bytes are required for T54(4) and T53(4)
+ size_t blk_size = card->max_send_size - 8;
+ size_t to_send = 0;
+ size_t offset = (size_t) idx;
+ do {
+ len = 0;
+ to_send = bytes_left >= blk_size ? blk_size : bytes_left;
+ p = cmdbuff;
+ // ASN1 0x54 offset
+ *p++ = 0x54;
+ *p++ = 0x02;
+ *p++ = (offset >> 8) & 0xFF;
+ *p++ = offset & 0xFF;
+ // ASN1 0x53 to_send
+ *p++ = 0x53;
+ if (to_send < 128) {
+ *p++ = (u8)to_send;
+ len = 6;
+ } else if (to_send < 256) {
+ *p++ = 0x81;
+ *p++ = (u8)to_send;
+ len = 7;
+ } else {
+ *p++ = 0x82;
+ *p++ = (to_send >> 8) & 0xFF;
+ *p++ = to_send & 0xFF;
+ len = 8;
+ }
- if (buf != NULL)
- memcpy(p, buf, count);
- len += count;
+ if (buf != NULL)
+ memcpy(p, buf+offset, to_send);
+ len += to_send;
- sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xD7, fid >> 8, fid & 0xFF);
- apdu.data = cmdbuff;
- apdu.datalen = len;
- apdu.lc = len;
+ sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xD7, fid >> 8, fid & 0xFF);
+ apdu.data = cmdbuff;
+ apdu.datalen = len;
+ apdu.lc = len;
- r = sc_transmit_apdu(card, &apdu);
- free(cmdbuff);
- LOG_TEST_RET(ctx, r, "APDU transmit failed");
+ r = sc_transmit_apdu(card, &apdu);
+ LOG_TEST_GOTO_ERR(ctx, r, "APDU transmit failed");
+ r = sc_check_sw(card, apdu.sw1, apdu.sw2);
+ LOG_TEST_GOTO_ERR(ctx, r, "Check SW error");
- r = sc_check_sw(card, apdu.sw1, apdu.sw2);
- LOG_TEST_RET(ctx, r, "Check SW error");
+ bytes_left -= to_send;
+ offset += to_send;
+ } while (0 < bytes_left);
+
+err:
+ free(cmdbuff);
LOG_FUNC_RETURN(ctx, count);
}
-
static int sc_hsm_update_binary(sc_card_t *card,
unsigned int idx, const u8 *buf, size_t count,
unsigned long flags)
@@ -1227,7 +1237,7 @@ static int sc_hsm_initialize(sc_card_t *card, sc_cardctl_sc_hsm_init_param_t *pa
return SC_ERROR_INVALID_ARGUMENTS;
}
*p++ = 0x81; // User PIN
- *p++ = (u8) params->user_pin_len;
+ *p++ = (u8)params->user_pin_len;
memcpy(p, params->user_pin, params->user_pin_len);
p += params->user_pin_len;
@@ -1400,12 +1410,11 @@ static int sc_hsm_unwrap_key(sc_card_t *card, sc_cardctl_sc_hsm_wrapped_key_t *p
LOG_FUNC_CALLED(card->ctx);
- sc_format_apdu(card, &apdu, SC_APDU_CASE_3_EXT, 0x74, params->key_id, 0x93);
- apdu.cla = 0x80;
- apdu.lc = params->wrapped_key_length;
- apdu.data = params->wrapped_key;
- apdu.datalen = params->wrapped_key_length;
+ r = sc_hsm_write_ef(card, 0x2F10, 0, params->wrapped_key, params->wrapped_key_length);
+ LOG_TEST_RET(card->ctx, r, "Create EF failed");
+ sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x74, params->key_id, 0x93);
+ apdu.cla = 0x80;
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(ctx, r, "APDU transmit failed");
@@ -1765,17 +1774,10 @@ static int sc_hsm_init(struct sc_card *card)
int flags,ext_flags;
sc_file_t *file = NULL;
sc_path_t path;
- sc_hsm_private_data_t *priv = card->drv_data;
+ sc_hsm_private_data_t *priv = NULL;
LOG_FUNC_CALLED(card->ctx);
- if (!priv) {
- priv = calloc(1, sizeof(sc_hsm_private_data_t));
- if (!priv)
- LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
- card->drv_data = priv;
- }
-
flags = SC_ALGORITHM_RSA_RAW|SC_ALGORITHM_RSA_PAD_PSS|SC_ALGORITHM_ONBOARD_KEY_GEN;
_sc_card_add_rsa_alg(card, 1024, flags, 0);
@@ -1807,6 +1809,46 @@ static int sc_hsm_init(struct sc_card *card)
card->caps |= SC_CARD_CAP_RNG|SC_CARD_CAP_APDU_EXT|SC_CARD_CAP_ISO7816_PIN_INFO;
+ // APDU Buffer limits
+ // JCOP 2.4.1r3 1462
+ // JCOP 2.4.2r3 1454
+ // JCOP 3 1232
+ // MicroSD with JCOP 3 478 / 506 - handled in reader-pcsc.c
+ // Reiner SCT 1014 - handled in reader-pcsc.c
+
+ // Use JCOP 3 card limits for sending
+ card->max_send_size = 1232;
+ // Assume that card supports sending with extended length APDU and without limit
+ card->max_recv_size = 0;
+
+ if (card->type == SC_CARD_TYPE_SC_HSM_SOC
+ || card->type == SC_CARD_TYPE_SC_HSM_GOID) {
+ card->max_recv_size = 0x0630; // SoC Proxy forces this limit
+ } else {
+ // Adjust to the limits set by the reader
+ if (card->reader->max_send_size < card->max_send_size) {
+ if (18 >= card->reader->max_send_size)
+ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INCONSISTENT_CONFIGURATION);
+
+ // 17 byte header and TLV because of odd ins in UPDATE BINARY
+ card->max_send_size = card->reader->max_send_size - 17;
+ }
+
+ if (0 < card->reader->max_recv_size) {
+ if (3 >= card->reader->max_recv_size)
+ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INCONSISTENT_CONFIGURATION);
+ card->max_recv_size = card->reader->max_recv_size - 2;
+ }
+ }
+
+ priv = card->drv_data;
+ if (!priv) {
+ priv = calloc(1, sizeof(sc_hsm_private_data_t));
+ if (!priv)
+ LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
+ card->drv_data = priv;
+ }
+
sc_path_set(&path, SC_PATH_TYPE_DF_NAME, sc_hsm_aid.value, sc_hsm_aid.len, 0, 0);
if (sc_hsm_select_file_ex(card, &path, 0, &file) == SC_SUCCESS
&& file && file->prop_attr && file->prop_attr_len >= 2) {
@@ -1839,25 +1881,6 @@ static int sc_hsm_init(struct sc_card *card)
}
sc_file_free(file);
- // APDU Buffer limits
- // JCOP 2.4.1r3 1462
- // JCOP 2.4.2r3 1454
- // JCOP 3 1232
- // MicroSD with JCOP 3 478 / 506
- // Reiner SCT 1014
-
- card->max_send_size = 1232 - 17; // 1232 buffer size - 17 byte header and TLV because of odd ins in UPDATE BINARY
-
- if (!strncmp("Secure Flash Card", card->reader->name, 17)) {
- card->max_send_size = 478 - 17;
- card->max_recv_size = 506 - 2;
- } else if (card->type == SC_CARD_TYPE_SC_HSM_SOC
- || card->type == SC_CARD_TYPE_SC_HSM_GOID) {
- card->max_recv_size = 0x0630; // SoC Proxy forces this limit
- } else {
- card->max_recv_size = 0; // Card supports sending with extended length APDU and without limit
- }
-
priv->EF_C_DevAut = NULL;
priv->EF_C_DevAut_len = 0;
@@ -1883,13 +1906,11 @@ static int sc_hsm_finish(sc_card_t * card)
#ifdef ENABLE_SM
sc_sm_stop(card);
#endif
- if (priv->serialno) {
+ if (priv) {
free(priv->serialno);
- }
- if (priv->dffcp) {
sc_file_free(priv->dffcp);
+ free(priv->EF_C_DevAut);
}
- free(priv->EF_C_DevAut);
free(priv);
return SC_SUCCESS;
diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c
index 40bfd293d3..04d5ac8fdd 100644
--- a/src/libopensc/reader-pcsc.c
+++ b/src/libopensc/reader-pcsc.c
@@ -311,7 +311,7 @@ static int pcsc_transmit(sc_reader_t *reader, sc_apdu_t *apdu)
* The buffer for the returned data needs to be at least 2 bytes
* larger than the expected data length to store SW1 and SW2. */
rsize = rbuflen = apdu->resplen <= 256 ? 258 : apdu->resplen + 2;
- rbuf = malloc(rbuflen);
+ rbuf = malloc(rbuflen);
if (rbuf == NULL) {
r = SC_ERROR_OUT_OF_MEMORY;
goto out;
@@ -424,7 +424,7 @@ static int refresh_attributes(sc_reader_t *reader)
if (priv->reader_state.cbAtr > SC_MAX_ATR_SIZE)
return SC_ERROR_INTERNAL;
- /* Some cards have a different cold (after a powerup) and warm (after a reset) ATR */
+ /* Some cards have a different cold (after a powerup) and warm (after a reset) ATR */
if (memcmp(priv->reader_state.rgbAtr, reader->atr.value, priv->reader_state.cbAtr) != 0) {
reader->atr.len = priv->reader_state.cbAtr;
memcpy(reader->atr.value, priv->reader_state.rgbAtr, reader->atr.len);
@@ -556,7 +556,7 @@ static int pcsc_reconnect(sc_reader_t * reader, DWORD action)
priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
protocol, action, &active_proto);
-
+
PCSC_TRACE(reader, "SCardReconnect returned", rv);
if (rv != SCARD_S_SUCCESS) {
PCSC_TRACE(reader, "SCardReconnect failed", rv);
@@ -593,7 +593,7 @@ static void initialize_uid(sc_reader_t *reader)
sc_log_hex(reader->ctx, "UID",
reader->uid.value, reader->uid.len);
} else {
- sc_log(reader->ctx, "unable to get UID");
+ sc_log(reader->ctx, "unable to get UID");
}
}
}
@@ -1240,11 +1240,11 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle)
sc_log(ctx, "Reader has a display: %04X", caps->wLcdLayout);
reader->capabilities |= SC_READER_CAP_DISPLAY;
}
- else {
+ else {
sc_log(ctx, "Reader does not have a display.");
}
}
- else {
+ else {
sc_log(ctx,
"Returned PIN properties structure has bad length (%lu/%"SC_FORMAT_LEN_SIZE_T"u)",
(unsigned long)rcount,
@@ -1304,7 +1325,7 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle)
}
rcount = sizeof i;
- if(gpriv->SCardGetAttrib(card_handle, SCARD_ATTR_VENDOR_IFD_VERSION,
+ if (gpriv->SCardGetAttrib(card_handle, SCARD_ATTR_VENDOR_IFD_VERSION,
(u8 *) &i, &rcount) == SCARD_S_SUCCESS
&& rcount == sizeof i) {
reader->version_major = (i >> 24) & 0xFF;
@@ -1314,7 +1335,7 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle)
}
int pcsc_add_reader(sc_context_t *ctx,
- char *reader_name, size_t reader_name_len,
+ char *reader_name, size_t reader_name_len,
sc_reader_t **out_reader)
{
int ret = SC_ERROR_INTERNAL;
@@ -1574,7 +1595,7 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
LOG_FUNC_CALLED(ctx);
- if (!event_reader && !event && reader_states) {
+ if (!event_reader && !event && reader_states) {
sc_log(ctx, "free allocated reader states");
free(*reader_states);
*reader_states = NULL;
@@ -1958,7 +1979,7 @@ static int part10_build_modify_pin_block(struct sc_reader *reader, u8 * buf, siz
sc_apdu_t *apdu = data->apdu;
u8 tmp;
unsigned int tmp16;
- PIN_MODIFY_STRUCTURE *pin_modify = (PIN_MODIFY_STRUCTURE *)buf;
+ PIN_MODIFY_STRUCTURE *pin_modify = (PIN_MODIFY_STRUCTURE *)buf;
struct sc_pin_cmd_pin *pin_ref =
data->flags & SC_PIN_CMD_IMPLICIT_CHANGE ?
&data->pin2 : &data->pin1;

View File

@ -0,0 +1,61 @@
From dd138d0600a1acd7991989127f36827e5836b24e Mon Sep 17 00:00:00 2001
From: "Ingo Struck (git commits)" <gitlab@ingostruck.de>
Date: Thu, 16 Mar 2023 22:12:49 +0100
Subject: [PATCH] Fixed loop in sc_hsm_write_ef, handle offset into buf and
into EF separately
---
src/libopensc/card-sc-hsm.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/src/libopensc/card-sc-hsm.c b/src/libopensc/card-sc-hsm.c
index 1b707f08df..c100a87c2a 100644
--- a/src/libopensc/card-sc-hsm.c
+++ b/src/libopensc/card-sc-hsm.c
@@ -782,7 +782,7 @@ static int sc_hsm_logout(sc_card_t * card)
}
-
+/* NOTE: idx is an offset into the card's file, not into buf */
static int sc_hsm_read_binary(sc_card_t *card,
unsigned int idx, u8 *buf, size_t count,
unsigned long flags)
@@ -823,7 +823,7 @@ static int sc_hsm_read_binary(sc_card_t *card,
}
-
+/* NOTE: idx is an offset into the card's file, not into buf */
static int sc_hsm_write_ef(sc_card_t *card,
int fid,
unsigned int idx, const u8 *buf, size_t count)
@@ -848,7 +848,8 @@ static int sc_hsm_write_ef(sc_card_t *card,
// 8 bytes are required for T54(4) and T53(4)
size_t blk_size = card->max_send_size - 8;
size_t to_send = 0;
- size_t offset = (size_t) idx;
+ size_t file_offset = (size_t) idx;
+ size_t offset = 0;
do {
len = 0;
to_send = bytes_left >= blk_size ? blk_size : bytes_left;
@@ -856,8 +857,8 @@ static int sc_hsm_write_ef(sc_card_t *card,
// ASN1 0x54 offset
*p++ = 0x54;
*p++ = 0x02;
- *p++ = (offset >> 8) & 0xFF;
- *p++ = offset & 0xFF;
+ *p++ = (file_offset >> 8) & 0xFF;
+ *p++ = file_offset & 0xFF;
// ASN1 0x53 to_send
*p++ = 0x53;
if (to_send < 128) {
@@ -890,6 +891,7 @@ static int sc_hsm_write_ef(sc_card_t *card,
bytes_left -= to_send;
offset += to_send;
+ file_offset += to_send;
} while (0 < bytes_left);
err:

View File

@ -0,0 +1,25 @@
From c449a181a6988cc1e8dc8764d23574e48cdc3fa6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
Date: Mon, 19 Jun 2023 16:14:51 +0200
Subject: [PATCH] pkcs15-cflex: check path length to prevent underflow
Thanks OSS-Fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=58932
---
src/pkcs15init/pkcs15-cflex.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/pkcs15init/pkcs15-cflex.c b/src/pkcs15init/pkcs15-cflex.c
index d06568073d..ce1d48e62c 100644
--- a/src/pkcs15init/pkcs15-cflex.c
+++ b/src/pkcs15init/pkcs15-cflex.c
@@ -56,6 +56,9 @@ cflex_delete_file(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *d
int r = 0;
/* Select the parent DF */
path = df->path;
+ if (path.len < 2) {
+ return SC_ERROR_INVALID_ARGUMENTS;
+ }
path.len -= 2;
r = sc_select_file(p15card->card, &path, &parent);
if (r < 0)

View File

@ -0,0 +1,27 @@
From 88880db0307a07e33cf2e1592bb029e9c170dfea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
Date: Wed, 21 Jun 2023 15:48:27 +0200
Subject: [PATCH] pkcs15-pubkey: free DER value when parsing public key fails
The der value might be allocated in asn1_decode_entry()
but it is not released when errror occurs.
Thanks OSS-Fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=59615
---
src/libopensc/pkcs15-pubkey.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c
index 4a0ddffbeb..7107c47cbc 100644
--- a/src/libopensc/pkcs15-pubkey.c
+++ b/src/libopensc/pkcs15-pubkey.c
@@ -351,6 +351,8 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card,
err:
if (r < 0) {
sc_pkcs15_free_pubkey_info(info);
+ if (der->len)
+ free(der->value);
}
LOG_FUNC_RETURN(ctx, r);

View File

@ -0,0 +1,29 @@
From 638a5007a5d240d6fa901aa822cfeef94fe36e85 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
Date: Thu, 10 Aug 2023 12:20:33 +0200
Subject: [PATCH] pkcs15-pubkey.c: Avoid double-free
Thanks OSS-Fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=60616
---
src/libopensc/pkcs15-pubkey.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/libopensc/pkcs15-pubkey.c b/src/libopensc/pkcs15-pubkey.c
index 7107c47cbc..49b514968b 100644
--- a/src/libopensc/pkcs15-pubkey.c
+++ b/src/libopensc/pkcs15-pubkey.c
@@ -351,8 +351,12 @@ int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card,
err:
if (r < 0) {
sc_pkcs15_free_pubkey_info(info);
- if (der->len)
+ if (der->len) {
free(der->value);
+ /* der points to obj->content */
+ obj->content.value = NULL;
+ obj->content.len = 0;
+ }
}
LOG_FUNC_RETURN(ctx, r);

View File

@ -0,0 +1,27 @@
From ce7fcdaa35196706a83fe982900228e15464f928 Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Thu, 17 Aug 2023 11:55:06 +0200
Subject: [PATCH] oberthur: Avoid heap buffer overflow
Thanks oss-fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=60650
---
src/pkcs15init/pkcs15-oberthur.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/pkcs15init/pkcs15-oberthur.c b/src/pkcs15init/pkcs15-oberthur.c
index 377e28948e..b20bd6e6c4 100644
--- a/src/pkcs15init/pkcs15-oberthur.c
+++ b/src/pkcs15init/pkcs15-oberthur.c
@@ -531,7 +531,9 @@ cosm_new_file(struct sc_profile *profile, struct sc_card *card,
}
file->id |= (num & 0xFF);
- file->path.value[file->path.len-1] |= (num & 0xFF);
+ if (file->path.len) {
+ file->path.value[file->path.len - 1] |= (num & 0xFF);
+ }
if (file->type == SC_FILE_TYPE_INTERNAL_EF) {
file->ef_structure = structure;
}

View File

@ -0,0 +1,25 @@
From 440ca666eff10cc7011901252d20f3fc4ea23651 Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Thu, 17 Aug 2023 13:41:36 +0200
Subject: [PATCH] setcos: Avoid buffer underflow
Thanks oss-fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=60672
---
src/pkcs15init/pkcs15-setcos.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/src/pkcs15init/pkcs15-setcos.c
+++ b/src/pkcs15init/pkcs15-setcos.c
@@ -349,6 +349,10 @@ setcos_create_key(sc_profile_t *profile,
/* Replace the path of instantiated key template by the path from the object data. */
memcpy(&file->path, &key_info->path, sizeof(file->path));
+ if (file->path.len < 2) {
+ sc_file_free(file);
+ LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Invalid path");
+ }
file->id = file->path.value[file->path.len - 2] * 0x100
+ file->path.value[file->path.len - 1];

View File

@ -0,0 +1,38 @@
From 245efe608d083fd4e4ec96793fdefd218e26fde7 Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Thu, 17 Aug 2023 13:54:42 +0200
Subject: [PATCH] pkcs15: Avoid buffer overflow when getting last update
Thanks oss-fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=60769
---
src/libopensc/pkcs15.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
--- a/src/libopensc/pkcs15.c
+++ b/src/libopensc/pkcs15.c
@@ -528,7 +528,7 @@ sc_pkcs15_get_lastupdate(struct sc_pkcs1
struct sc_context *ctx = p15card->card->ctx;
struct sc_file *file = NULL;
struct sc_asn1_entry asn1_last_update[C_ASN1_LAST_UPDATE_SIZE];
- unsigned char *content, last_update[32];
+ unsigned char *content, last_update[32] = {0};
size_t lupdate_len = sizeof(last_update) - 1;
int r, content_len;
size_t size;
@@ -564,9 +564,11 @@ sc_pkcs15_get_lastupdate(struct sc_pkcs1
if (r < 0)
return NULL;
- p15card->tokeninfo->last_update.gtime = strdup((char *)last_update);
- if (!p15card->tokeninfo->last_update.gtime)
- return NULL;
+ if (asn1_last_update[0].flags & SC_ASN1_PRESENT) {
+ p15card->tokeninfo->last_update.gtime = strdup((char *)last_update);
+ if (!p15card->tokeninfo->last_update.gtime)
+ return NULL;
+ }
done:
sc_log(ctx, "lastUpdate.gtime '%s'", p15card->tokeninfo->last_update.gtime);
return p15card->tokeninfo->last_update.gtime;

View File

@ -0,0 +1,26 @@
From 41d61da8481582e12710b5858f8b635e0a71ab5e Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Wed, 20 Sep 2023 10:13:57 +0200
Subject: [PATCH] oberthur: Avoid buffer overflow
Thanks oss-fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=60650
---
src/pkcs15init/pkcs15-oberthur.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/pkcs15init/pkcs15-oberthur.c b/src/pkcs15init/pkcs15-oberthur.c
index ad2cabd530..c441ab1e76 100644
--- a/src/pkcs15init/pkcs15-oberthur.c
+++ b/src/pkcs15init/pkcs15-oberthur.c
@@ -715,6 +715,9 @@ cosm_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
if (object->type != SC_PKCS15_TYPE_PRKEY_RSA)
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Create key failed: RSA only supported");
+ if (key_info->path.len < 2)
+ LOG_TEST_RET(ctx, SC_ERROR_OBJECT_NOT_VALID, "The path needs to be at least to bytes long");
+
sc_log(ctx, "create private key ID:%s", sc_pkcs15_print_id(&key_info->id));
/* Here, the path of private key file should be defined.
* Nevertheless, we need to instantiate private key to get the ACLs. */

View File

@ -0,0 +1,49 @@
From 3bf3ab2f9091f984cda6dd910654ccbbe3f06a40 Mon Sep 17 00:00:00 2001
From: fullwaywang <fullwaywang@tencent.com>
Date: Mon, 29 May 2023 10:38:48 +0800
Subject: [PATCH] pkcs15init: correct left length calculation to fix buffer
overrun bug. Fixes #2785
---
src/pkcs15init/pkcs15-cardos.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/pkcs15init/pkcs15-cardos.c b/src/pkcs15init/pkcs15-cardos.c
index 9715cf390f..f41f73c349 100644
--- a/src/pkcs15init/pkcs15-cardos.c
+++ b/src/pkcs15init/pkcs15-cardos.c
@@ -872,7 +872,7 @@ static int cardos_have_verifyrc_package(sc_card_t *card)
sc_apdu_t apdu;
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
int r;
- const u8 *p = rbuf, *q;
+ const u8 *p = rbuf, *q, *pp;
size_t len, tlen = 0, ilen = 0;
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x88);
@@ -888,13 +888,13 @@ static int cardos_have_verifyrc_package(sc_card_t *card)
return 0;
while (len != 0) {
- p = sc_asn1_find_tag(card->ctx, p, len, 0xe1, &tlen);
- if (p == NULL)
+ pp = sc_asn1_find_tag(card->ctx, p, len, 0xe1, &tlen);
+ if (pp == NULL)
return 0;
if (card->type == SC_CARD_TYPE_CARDOS_M4_3) {
/* the verifyRC package on CardOS 4.3B use Manufacturer ID 0x01 */
/* and Package Number 0x07 */
- q = sc_asn1_find_tag(card->ctx, p, tlen, 0x01, &ilen);
+ q = sc_asn1_find_tag(card->ctx, pp, tlen, 0x01, &ilen);
if (q == NULL || ilen != 4)
return 0;
if (q[0] == 0x07)
@@ -902,7 +902,7 @@ static int cardos_have_verifyrc_package(sc_card_t *card)
} else if (card->type == SC_CARD_TYPE_CARDOS_M4_4) {
/* the verifyRC package on CardOS 4.4 use Manufacturer ID 0x03 */
/* and Package Number 0x02 */
- q = sc_asn1_find_tag(card->ctx, p, tlen, 0x03, &ilen);
+ q = sc_asn1_find_tag(card->ctx, pp, tlen, 0x03, &ilen);
if (q == NULL || ilen != 4)
return 0;
if (q[0] == 0x02)

View File

@ -0,0 +1,485 @@
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 5153428dc..9ecbffe8f 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -8,7 +8,8 @@ dist_noinst_DATA = \
LICENSE.compat_getopt compat_getopt.txt \
compat_getopt_main.c \
README.compat_strlcpy compat_strlcpy.3
-noinst_HEADERS = compat_strlcat.h compat_strlcpy.h compat_strnlen.h compat_getpass.h compat_getopt.h simclist.h libpkcs11.h libscdl.h
+noinst_HEADERS = compat_strlcat.h compat_strlcpy.h compat_strnlen.h compat_getpass.h \
+ compat_getopt.h simclist.h libpkcs11.h libscdl.h constant-time.h
AM_CPPFLAGS = -I$(top_srcdir)/src
@@ -43,7 +44,8 @@ TIDY_FILES = \
compat_report_rangecheckfailure.c \
compat___iob_func.c \
simclist.c simclist.h \
- libpkcs11.c libscdl.c
+ libpkcs11.c libscdl.c \
+ constant-time.h
check-local:
if [ -x "$(CLANGTIDY)" ]; then clang-tidy -config='' -header-filter=.* $(TIDY_FILES) -- $(TIDY_FLAGS); fi
diff --git a/src/common/constant-time.h b/src/common/constant-time.h
new file mode 100644
index 0000000000..40c3e500c2
--- /dev/null
+++ b/src/common/constant-time.h
@@ -0,0 +1,134 @@
+/* Original source: https://github.com/openssl/openssl/blob/9890cc42daff5e2d0cad01ac4bf78c391f599a6e/include/internal/constant_time.h */
+
+#ifndef CONSTANT_TIME_H
+#define CONSTANT_TIME_H
+
+#include <stdlib.h>
+#include <string.h>
+
+#if !defined(inline)
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define constant_inline inline
+#elif defined(__GNUC__) && __GNUC__ >= 2
+#elif defined(__GNUC__) && __GNUC__ >= 2
+#elif defined(_MSC_VER)
+#define constant_inline __inline
+#else
+#define constant_inline
+#endif
+#else /* use what caller wants as inline may be from config.h */
+#define constant_inline inline /* inline */
+#endif
+
+/*-
+ * The boolean methods return a bitmask of all ones (0xff...f) for true
+ * and 0 for false. For example,
+ * if (a < b) {
+ * c = a;
+ * } else {
+ * c = b;
+ * }
+ * can be written as
+ * unsigned int lt = constant_time_lt(a, b);
+ * c = constant_time_select(lt, a, b);
+ */
+
+static constant_inline unsigned int
+value_barrier(unsigned int a)
+{
+ volatile unsigned int r = a;
+ return r;
+}
+
+static constant_inline size_t
+value_barrier_s(size_t a)
+{
+ volatile size_t r = a;
+ return r;
+}
+
+/* MSB */
+static constant_inline size_t
+constant_time_msb_s(size_t a)
+{
+ return 0 - (a >> (sizeof(a) * 8 - 1));
+}
+
+static constant_inline unsigned int
+constant_time_msb(unsigned int a)
+{
+ return 0 - (a >> (sizeof(a) * 8 - 1));
+}
+
+/* Select */
+static constant_inline unsigned int
+constant_time_select(unsigned int mask, unsigned int a, unsigned int b)
+{
+ return (value_barrier(mask) & a) | (value_barrier(~mask) & b);
+}
+
+static constant_inline unsigned char
+constant_time_select_8(unsigned char mask, unsigned char a, unsigned char b)
+{
+ return (unsigned char)constant_time_select(mask, a, b);
+}
+
+static constant_inline size_t
+constant_time_select_s(size_t mask, size_t a, size_t b)
+{
+ return (value_barrier_s(mask) & a) | (value_barrier_s(~mask) & b);
+}
+
+/* Zero */
+static constant_inline unsigned int
+constant_time_is_zero(unsigned int a)
+{
+ return constant_time_msb(~a & (a - 1));
+}
+
+static constant_inline size_t
+constant_time_is_zero_s(size_t a)
+{
+ return constant_time_msb_s(~a & (a - 1));
+}
+
+/* Comparison*/
+static constant_inline size_t
+constant_time_lt_s(size_t a, size_t b)
+{
+ return constant_time_msb_s(a ^ ((a ^ b) | ((a - b) ^ b)));
+}
+
+static constant_inline unsigned int
+constant_time_lt(unsigned int a, unsigned int b)
+{
+ return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b)));
+}
+
+static constant_inline unsigned int
+constant_time_ge(unsigned int a, unsigned int b)
+{
+ return ~constant_time_lt(a, b);
+}
+
+/* Equality*/
+
+static constant_inline unsigned int
+constant_time_eq(unsigned int a, unsigned int b)
+{
+ return constant_time_is_zero(a ^ b);
+}
+
+static constant_inline size_t
+constant_time_eq_s(size_t a, size_t b)
+{
+ return constant_time_is_zero_s(a ^ b);
+}
+
+static constant_inline unsigned int
+constant_time_eq_i(int a, int b)
+{
+ return constant_time_eq((unsigned int)a, (unsigned int)b);
+}
+
+#endif /* CONSTANT_TIME_H */
diff --git a/src/libopensc/internal.h b/src/libopensc/internal.h
index 74014235a..13eccfa1a 100644
--- a/src/libopensc/internal.h
+++ b/src/libopensc/internal.h
@@ -168,6 +168,8 @@ int sc_pkcs1_strip_01_padding(struct sc_context *ctx, const u8 *in_dat, size_t i
u8 *out_dat, size_t *out_len);
int sc_pkcs1_strip_02_padding(struct sc_context *ctx, const u8 *data, size_t len,
u8 *out_dat, size_t *out_len);
+int sc_pkcs1_strip_02_padding_constant_time(sc_context_t *ctx, unsigned int n, const u8 *data,
+ unsigned int data_len, u8 *out, unsigned int *out_len);
int sc_pkcs1_strip_digest_info_prefix(unsigned int *algorithm,
const u8 *in_dat, size_t in_len, u8 *out_dat, size_t *out_len);
diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c
index ca47733a4e..ddb3061134 100644
--- a/src/libopensc/padding.c
+++ b/src/libopensc/padding.c
@@ -32,10 +32,13 @@
#include <string.h>
#include <stdlib.h>
+#include "common/constant-time.h"
#include "internal.h"
/* TODO doxygen comments */
+#define SC_PKCS1_PADDING_MIN_SIZE 11
+
/*
* Prefixes for pkcs-v1 signatures
*/
@@ -144,44 +147,82 @@ sc_pkcs1_strip_01_padding(struct sc_cont
}
-/* remove pkcs1 BT02 padding (adding BT02 padding is currently not
- * needed/implemented) */
+/* Remove pkcs1 BT02 padding (adding BT02 padding is currently not
+ * needed/implemented) in constant-time.
+ * Original source: https://github.com/openssl/openssl/blob/9890cc42daff5e2d0cad01ac4bf78c391f599a6e/crypto/rsa/rsa_pk1.c#L171 */
int
-sc_pkcs1_strip_02_padding(sc_context_t *ctx, const u8 *data, size_t len, u8 *out, size_t *out_len)
+sc_pkcs1_strip_02_padding_constant_time(sc_context_t *ctx, unsigned int n, const u8 *data, unsigned int data_len, u8 *out, unsigned int *out_len)
{
- unsigned int n = 0;
-
+ unsigned int i = 0;
+ u8 *msg, *msg_orig = NULL;
+ unsigned int good, found_zero_byte, mask;
+ unsigned int zero_index = 0, msg_index, mlen = -1, len = 0;
LOG_FUNC_CALLED(ctx);
- if (data == NULL || len < 3)
+
+ if (data == NULL || data_len <= 0 || data_len > n || n < SC_PKCS1_PADDING_MIN_SIZE)
LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
- /* skip leading zero byte */
- if (*data == 0) {
- data++;
- len--;
+ msg = msg_orig = calloc(n, sizeof(u8));
+ if (msg == NULL)
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
+
+ /*
+ * We can not check length of input data straight away and still we need to read
+ * from input even when the input is not as long as needed to keep the time constant.
+ * If data has wrong size, it is padded by zeroes from left and the following checks
+ * do not pass.
+ */
+ len = data_len;
+ for (data += len, msg += n, i = 0; i < n; i++) {
+ mask = ~constant_time_is_zero(len);
+ len -= 1 & mask;
+ data -= 1 & mask;
+ *--msg = *data & mask;
+ }
+ // check first byte to be 0x00
+ good = constant_time_is_zero(msg[0]);
+ // check second byte to be 0x02
+ good &= constant_time_eq(msg[1], 2);
+
+ // find zero byte after random data in padding
+ found_zero_byte = 0;
+ for (i = 2; i < n; i++) {
+ unsigned int equals0 = constant_time_is_zero(msg[i]);
+ zero_index = constant_time_select(~found_zero_byte & equals0, i, zero_index);
+ found_zero_byte |= equals0;
}
- if (data[0] != 0x02)
- LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING);
- /* skip over padding bytes */
- for (n = 1; n < len && data[n]; n++)
- ;
- /* Must be at least 8 pad bytes */
- if (n >= len || n < 9)
- LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING);
- n++;
- if (out == NULL)
- /* just check the padding */
- LOG_FUNC_RETURN(ctx, SC_SUCCESS);
- /* Now move decrypted contents to head of buffer */
- if (*out_len < len - n)
- LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
- *out_len = len - n;
- memmove(out, data + n, *out_len);
+ // zero_index stands for index of last found zero
+ good &= constant_time_ge(zero_index, 2 + 8);
+
+ // start of the actual message in data
+ msg_index = zero_index + 1;
+
+ // length of message
+ mlen = data_len - msg_index;
+
+ // check that message fits into out buffer
+ good &= constant_time_ge(*out_len, mlen);
+
+ // move the result in-place by |num|-SC_PKCS1_PADDING_MIN_SIZE-|mlen| bytes to the left.
+ *out_len = constant_time_select(constant_time_lt(n - SC_PKCS1_PADDING_MIN_SIZE, *out_len),
+ n - SC_PKCS1_PADDING_MIN_SIZE, *out_len);
+ for (msg_index = 1; msg_index < n - SC_PKCS1_PADDING_MIN_SIZE; msg_index <<= 1) {
+ mask = ~constant_time_eq(msg_index & (n - SC_PKCS1_PADDING_MIN_SIZE - mlen), 0);
+ for (i = SC_PKCS1_PADDING_MIN_SIZE; i < n - msg_index; i++)
+ msg[i] = constant_time_select_8(mask, msg[i + msg_index], msg[i]);
+ }
+ // move message into out buffer, if good
+ for (i = 0; i < *out_len; i++) {
+ unsigned int msg_index;
+ // when out is longer than message in data, use some bogus index in msg
+ mask = good & constant_time_lt(i, mlen);
+ msg_index = constant_time_select(mask, i + SC_PKCS1_PADDING_MIN_SIZE, 0); // to now overflow msg buffer
+ out[i] = constant_time_select_8(mask, msg[msg_index], out[i]);
+ }
- sc_log(ctx, "stripped output(%"SC_FORMAT_LEN_SIZE_T"u): %s", len - n,
- sc_dump_hex(out, len - n));
- LOG_FUNC_RETURN(ctx, len - n);
+ free(msg_orig);
+ return constant_time_select(good, mlen, SC_ERROR_WRONG_PADDING);
}
/* add/remove DigestInfo prefix */
diff --git a/src/libopensc/pkcs15-sec.c b/src/libopensc/pkcs15-sec.c
index a019af460f..f7ee819d65 100644
--- a/src/libopensc/pkcs15-sec.c
+++ b/src/libopensc/pkcs15-sec.c
@@ -286,12 +286,14 @@ int sc_pkcs15_decipher(struct sc_pkcs15_
/* Strip any padding */
if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
- size_t s = r;
- r = sc_pkcs1_strip_02_padding(ctx, out, s, out, &s);
- LOG_TEST_RET(ctx, r, "Invalid PKCS#1 padding");
+ unsigned int s = r;
+ unsigned int key_size = (unsigned int)alg_info->key_length;
+ r = sc_pkcs1_strip_02_padding_constant_time(ctx, key_size / 8, out, s, out, &s);
+ /* for keeping PKCS#1 v1.5 depadding constant-time, do not log error here */
}
- LOG_FUNC_RETURN(ctx, r);
+ /* do not log error code to prevent side channel attack */
+ return r;
}
/* derive one key from another. RSA can use decipher, so this is for only ECDH
diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c
index f75a3dbaec..632681df63 100644
--- a/src/pkcs11/framework-pkcs15.c
+++ b/src/pkcs11/framework-pkcs15.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include "common/constant-time.h"
#include "config.h"
#include <stdlib.h>
#include <string.h>
@@ -4174,7 +4175,8 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_se
struct pkcs15_fw_data *fw_data = NULL;
struct pkcs15_prkey_object *prkey;
unsigned char decrypted[512]; /* FIXME: Will not work for keys above 4096 bits */
- int buff_too_small, rv, flags = 0, prkey_has_path = 0;
+ int rv, flags = 0, prkey_has_path = 0;
+ CK_ULONG mask, good, rv_pkcs11;
sc_log(context, "Initiating decryption.");
@@ -4246,27 +4248,54 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_se
rv = sc_pkcs15_decipher(fw_data->p15_card, prkey->prv_p15obj, flags,
pEncryptedData, ulEncryptedDataLen, decrypted, sizeof(decrypted));
- if (rv < 0 && !sc_pkcs11_conf.lock_login && !prkey_has_path)
+ /* skip for PKCS#1 v1.5 padding prevent side channel attack */
+ if (!(flags & SC_ALGORITHM_RSA_PAD_PKCS1) &&
+ rv < 0 && !sc_pkcs11_conf.lock_login && !prkey_has_path)
if (reselect_app_df(fw_data->p15_card) == SC_SUCCESS)
rv = sc_pkcs15_decipher(fw_data->p15_card, prkey->prv_p15obj, flags,
pEncryptedData, ulEncryptedDataLen, decrypted, sizeof(decrypted));
sc_unlock(p11card->card);
- sc_log(context, "Decryption complete. Result %d.", rv);
+ sc_log(context, "Decryption complete.");
- if (rv < 0)
+ /* Handle following code in constant-time
return sc_to_cryptoki_error(rv, "C_Decrypt");
+ * to prevent Marvin attack for PKCS#1 v1.5 padding. */
- buff_too_small = (*pulDataLen < (CK_ULONG)rv);
- *pulDataLen = rv;
- if (pData == NULL_PTR)
- return CKR_OK;
- if (buff_too_small)
- return CKR_BUFFER_TOO_SMALL;
- memcpy(pData, decrypted, *pulDataLen);
-
- return CKR_OK;
+ /* only padding error must be handled in constant-time way,
+ * other error can be returned straight away */
+ if ((~constant_time_eq_i(rv, SC_ERROR_WRONG_PADDING) & constant_time_lt_s(sizeof(decrypted), (size_t)rv)))
+ return sc_to_cryptoki_error(rv, "C_Decrypt");
+
+ /* check rv for padding error */
+ good = ~constant_time_eq_i(rv, SC_ERROR_WRONG_PADDING);
+ rv_pkcs11 = sc_to_cryptoki_error(SC_ERROR_WRONG_PADDING, "C_Decrypt");
+ rv_pkcs11 = constant_time_select_s(good, CKR_OK, rv_pkcs11);
+
+ if (pData == NULL_PTR) {
+ /* set length only if no error */
+ *pulDataLen = constant_time_select_s(good, rv, *pulDataLen);
+ /* return error only if original rv < 0 */
+ return rv_pkcs11;
+ }
+
+ /* check whether *pulDataLen < rv and set return value for small output buffer */
+ mask = good & constant_time_lt_s(*pulDataLen, rv);
+ rv_pkcs11 = constant_time_select_s(mask, CKR_BUFFER_TOO_SMALL, rv_pkcs11);
+ good &= ~mask;
+
+ /* move everything from decrypted into out buffer constant-time, if rv is ok */
+ for (CK_ULONG i = 0; i < *pulDataLen; i++) { /* iterate over whole pData to not disclose real depadded length */
+ CK_ULONG msg_index;
+ mask = good & constant_time_lt_s(i, sizeof(decrypted)); /* i should be in the bounds of decrypted */
+ mask &= constant_time_lt_s(i, constant_time_select_s(good, rv, 0)); /* check that is in bounds of depadded message */
+ msg_index = constant_time_select_s(mask, i, 0);
+ pData[i] = constant_time_select_8(mask, decrypted[msg_index], pData[i]);
+ }
+ *pulDataLen = constant_time_select_s(good, rv, *pulDataLen);
+ /* do not log error code to prevent side channel attack */
+ return rv_pkcs11;
}
diff --git a/src/pkcs11/mechanism.c b/src/pkcs11/mechanism.c
index 03495265a4..d3f0434231 100644
--- a/src/pkcs11/mechanism.c
+++ b/src/pkcs11/mechanism.c
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <string.h>
+#include "common/constant-time.h"
#include "sc-pkcs11.h"
/* Also used for verification data */
@@ -1089,7 +1090,9 @@ sc_pkcs11_decr(struct sc_pkcs11_session
rv = op->type->decrypt(op, pEncryptedData, ulEncryptedDataLen,
pData, pulDataLen);
- if (rv != CKR_BUFFER_TOO_SMALL && pData != NULL)
+ /* terminate session for any return value except CKR_BUFFER_TOO_SMALL,
+ * perform check in time side-channel free way to prevent Marvin attack */
+ if (!constant_time_eq_s(rv, CKR_BUFFER_TOO_SMALL) && pData != NULL)
session_stop_operation(session, SC_PKCS11_OPERATION_DECRYPT);
return rv;
diff --git a/src/pkcs11/pkcs11-object.c b/src/pkcs11/pkcs11-object.c
index f04c0b4c56..b023911213 100644
--- a/src/pkcs11/pkcs11-object.c
+++ b/src/pkcs11/pkcs11-object.c
@@ -926,7 +926,8 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSessi
rv = reset_login_state(session->slot, rv);
}
- sc_log(context, "C_Decrypt() = %s", lookup_enum ( RV_T, rv ));
+ /* do not log error code to prevent side channel attack */
+ sc_log(context, "C_Decrypt() finished");
sc_pkcs11_unlock();
return rv;
}
diff --git a/src/pkcs11/misc.c b/src/pkcs11/misc.c
index 5ca1176b1d..1d893d6181 100644
--- a/src/pkcs11/misc.c
+++ b/src/pkcs11/misc.c
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <string.h>
+#include "common/constant-time.h"
#include "sc-pkcs11.h"
#define DUMP_TEMPLATE_MAX 32
@@ -174,7 +175,7 @@ CK_RV reset_login_state(struct sc_pkcs11_slot *slot, CK_RV rv)
slot->p11card->framework->logout(slot);
}
- if (rv == CKR_USER_NOT_LOGGED_IN) {
+ if (constant_time_eq_s(rv, CKR_USER_NOT_LOGGED_IN)) {
slot->login_user = -1;
pop_all_login_states(slot);
}

111
opensc-CVE-2024-45615.patch Normal file
View File

@ -0,0 +1,111 @@
commit 5e4f26b510b04624386c54816bf26aacea0fe4a1
Author: Veronika Hanulíková <vhanulik@redhat.com>
Date: Thu Jul 11 14:58:25 2024 +0200
cac: Fix uninitialized values
Thanks Matteo Marini for report
https://github.com/OpenSC/OpenSC/security/advisories/GHSA-p3mx-7472-h3j8
fuzz_card/1,fuzz_pkcs11/6
Index: opensc-0.21.0/src/libopensc/card-cac.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/card-cac.c
+++ opensc-0.21.0/src/libopensc/card-cac.c
@@ -255,7 +255,7 @@ static int cac_apdu_io(sc_card_t *card,
size_t * recvbuflen)
{
int r;
- sc_apdu_t apdu;
+ sc_apdu_t apdu = {0};
u8 rbufinitbuf[CAC_MAX_SIZE];
u8 *rbuf;
size_t rbuflen;
@@ -392,13 +392,13 @@ fail:
static int cac_read_file(sc_card_t *card, int file_type, u8 **out_buf, size_t *out_len)
{
u8 params[2];
- u8 count[2];
+ u8 count[2] = {0};
u8 *out = NULL;
- u8 *out_ptr;
+ u8 *out_ptr = NULL;
size_t offset = 0;
size_t size = 0;
size_t left = 0;
- size_t len;
+ size_t len = 0;
int r;
params[0] = file_type;
@@ -461,7 +461,7 @@ static int cac_read_binary(sc_card_t *ca
const u8 *tl_ptr, *val_ptr, *tl_start;
u8 *tlv_ptr;
const u8 *cert_ptr;
- size_t tl_len, val_len, tlv_len;
+ size_t tl_len = 0, val_len = 0, tlv_len;
size_t len, tl_head_len, cert_len;
u8 cert_type, tag;
@@ -1528,7 +1528,7 @@ static int cac_parse_CCC(sc_card_t *card
static int cac_process_CCC(sc_card_t *card, cac_private_data_t *priv, int depth)
{
u8 *tl = NULL, *val = NULL;
- size_t tl_len, val_len;
+ size_t tl_len = 0, val_len = 0;
int r;
if (depth > CAC_MAX_CCC_DEPTH) {
Index: opensc-0.21.0/src/libopensc/card-piv.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/card-piv.c
+++ opensc-0.21.0/src/libopensc/card-piv.c
@@ -2202,7 +2202,7 @@ static int piv_get_challenge(sc_card_t *
const u8 *p;
size_t out_len = 0;
int r;
- unsigned int tag, cla;
+ unsigned int tag = 0, cla = 0;
piv_private_data_t * priv = PIV_DATA(card);
LOG_FUNC_CALLED(card->ctx);
Index: opensc-0.21.0/src/libopensc/pkcs15-cert.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/pkcs15-cert.c
+++ opensc-0.21.0/src/libopensc/pkcs15-cert.c
@@ -169,7 +169,7 @@ sc_pkcs15_get_name_from_dn(struct sc_con
for (next_ava = rdn, next_ava_len = rdn_len; next_ava_len; ) {
const u8 *ava, *dummy, *oidp;
struct sc_object_id oid;
- size_t ava_len, dummy_len, oid_len;
+ size_t ava_len = 0, dummy_len, oid_len = 0;
/* unwrap the set and point to the next ava */
ava = sc_asn1_skip_tag(ctx, &next_ava, &next_ava_len, SC_ASN1_TAG_SET | SC_ASN1_CONS, &ava_len);
Index: opensc-0.21.0/src/libopensc/pkcs15-sc-hsm.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/pkcs15-sc-hsm.c
+++ opensc-0.21.0/src/libopensc/pkcs15-sc-hsm.c
@@ -277,7 +277,7 @@ int sc_pkcs15emu_sc_hsm_decode_cvc(sc_pk
struct sc_asn1_entry asn1_cvcert[C_ASN1_CVCERT_SIZE];
struct sc_asn1_entry asn1_cvc_body[C_ASN1_CVC_BODY_SIZE];
struct sc_asn1_entry asn1_cvc_pubkey[C_ASN1_CVC_PUBKEY_SIZE];
- unsigned int cla,tag;
+ unsigned int cla = 0, tag = 0;
size_t taglen;
size_t lenchr = sizeof(cvc->chr);
size_t lencar = sizeof(cvc->car);
Index: opensc-0.21.0/src/pkcs15init/profile.c
===================================================================
--- opensc-0.21.0.orig/src/pkcs15init/profile.c
+++ opensc-0.21.0/src/pkcs15init/profile.c
@@ -1695,7 +1695,7 @@ do_pin_storedlength(struct state *cur, i
static int
do_pin_flags(struct state *cur, int argc, char **argv)
{
- unsigned int flags;
+ unsigned int flags = 0;
int i, r;
if (cur->pin->pin.auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)

287
opensc-CVE-2024-45616.patch Normal file
View File

@ -0,0 +1,287 @@
commit 1d3b410e06d33cfc4c70e8a25386e456cfbd7bd1
Author: Veronika Hanulíková <vhanulik@redhat.com>
Date: Thu Jul 11 15:27:19 2024 +0200
cardos: Fix uninitialized values
Thanks Matteo Marini for report
https://github.com/OpenSC/OpenSC/security/advisories/GHSA-p3mx-7472-h3j8
fuzz_card/2
Index: opensc-0.21.0/src/libopensc/card-cardos.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/card-cardos.c
+++ opensc-0.21.0/src/libopensc/card-cardos.c
@@ -94,14 +94,14 @@ static void fixup_transceive_length(cons
static int cardos_match_card(sc_card_t *card)
{
- unsigned char atr[SC_MAX_ATR_SIZE];
+ unsigned char atr[SC_MAX_ATR_SIZE] = {0};
int i;
i = _sc_match_atr(card, cardos_atrs, &card->type);
if (i < 0)
return 0;
- memcpy(atr, card->atr.value, sizeof(atr));
+ memcpy(atr, card->atr.value, card->atr.len);
/* Do not change card type for CIE! */
if (card->type == SC_CARD_TYPE_CARDOS_CIE_V1)
@@ -114,8 +114,8 @@ static int cardos_match_card(sc_card_t *
return 1;
if (card->type == SC_CARD_TYPE_CARDOS_M4_2) {
int rv;
- sc_apdu_t apdu;
- u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
+ sc_apdu_t apdu = {0};
+ u8 rbuf[SC_MAX_APDU_BUFFER_SIZE] = {0};
/* first check some additional ATR bytes */
if ((atr[4] != 0xff && atr[4] != 0x02) ||
(atr[6] != 0x10 && atr[6] != 0x0a) ||
@@ -131,7 +131,7 @@ static int cardos_match_card(sc_card_t *
apdu.lc = 0;
rv = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, rv, "APDU transmit failed");
- if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
+ if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00 || apdu.resplen < 2)
return 0;
if (apdu.resp[0] != atr[10] ||
apdu.resp[1] != atr[11])
Index: opensc-0.21.0/src/libopensc/card-cac1.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/card-cac1.c
+++ opensc-0.21.0/src/libopensc/card-cac1.c
@@ -95,12 +95,12 @@ static int cac_cac1_get_certificate(sc_c
if (apdu.sw1 != 0x63 || apdu.sw2 < 1) {
/* we've either finished reading, or hit an error, break */
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
- left -= len;
+ left -= apdu.resplen;
break;
}
/* Adjust the lengths */
- left -= len;
- out_ptr += len;
+ left -= apdu.resplen;
+ out_ptr += apdu.resplen;
len = MIN(left, apdu.sw2);
}
if (r < 0) {
Index: opensc-0.21.0/src/libopensc/card-oberthur.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/card-oberthur.c
+++ opensc-0.21.0/src/libopensc/card-oberthur.c
@@ -148,7 +148,7 @@ auth_select_aid(struct sc_card *card)
{
struct sc_apdu apdu;
unsigned char apdu_resp[SC_MAX_APDU_BUFFER_SIZE];
- struct auth_private_data *data = (struct auth_private_data *) card->drv_data;
+ struct auth_private_data *data = (struct auth_private_data *)card->drv_data;
int rv, ii;
struct sc_path tmp_path;
@@ -165,6 +165,9 @@ auth_select_aid(struct sc_card *card)
rv = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, rv, "APDU transmit failed");
+ if (apdu.resplen < 20) {
+ LOG_TEST_RET(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Serial number has incorrect length");
+ }
card->serialnr.len = 4;
memcpy(card->serialnr.value, apdu.resp+15, 4);
Index: opensc-0.21.0/src/libopensc/card-gids.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/card-gids.c
+++ opensc-0.21.0/src/libopensc/card-gids.c
@@ -231,6 +231,7 @@ static int gids_get_DO(sc_card_t* card,
size_t datasize = 0;
const u8* p;
u8 buffer[MAX_GIDS_FILE_SIZE];
+ size_t buffer_len = sizeof(buffer);
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
sc_log(card->ctx,
@@ -244,14 +245,15 @@ static int gids_get_DO(sc_card_t* card,
apdu.data = data;
apdu.datalen = 04;
apdu.resp = buffer;
- apdu.resplen = sizeof(buffer);
+ apdu.resplen = buffer_len;
apdu.le = 256;
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "gids get data failed");
LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "invalid return");
+ buffer_len = apdu.resplen;
- p = sc_asn1_find_tag(card->ctx, buffer, sizeof(buffer), dataObjectIdentifier, &datasize);
+ p = sc_asn1_find_tag(card->ctx, buffer, buffer_len, dataObjectIdentifier, &datasize);
if (!p) {
LOG_FUNC_RETURN(card->ctx, SC_ERROR_FILE_NOT_FOUND);
}
Index: opensc-0.21.0/src/libopensc/card-mcrd.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/card-mcrd.c
+++ opensc-0.21.0/src/libopensc/card-mcrd.c
@@ -634,23 +634,25 @@ do_select(sc_card_t * card, u8 kind,
}
}
- if (p2 == 0x04 && apdu.resp[0] == 0x62) {
- *file = sc_file_new();
- if (!*file)
- LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
- /* EstEID v3.0 cards are buggy and sometimes return a double 0x62 tag */
- if (card->type == SC_CARD_TYPE_MCRD_ESTEID_V30 && apdu.resp[2] == 0x62)
- process_fcp(card, *file, apdu.resp + 4, apdu.resp[3]);
- else
- process_fcp(card, *file, apdu.resp + 2, apdu.resp[1]);
- return SC_SUCCESS;
- }
+ if (p2 == 0x04 && apdu.resplen > 2 && apdu.resp[0] == 0x62) {
+ *file = sc_file_new();
+ if (!*file)
+ LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
+ if (apdu.resp[1] > apdu.resplen - 2)
+ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA);
+ /* EstEID v3.0 cards are buggy and sometimes return a double 0x62 tag */
+ if (card->type == SC_CARD_TYPE_MCRD_ESTEID_V30 && apdu.resp[2] == 0x62)
+ process_fcp(card, *file, apdu.resp + 4, apdu.resp[3]);
+ else
+ process_fcp(card, *file, apdu.resp + 2, apdu.resp[1]);
+ return SC_SUCCESS;
+ }
- if (p2 != 0x0C && apdu.resp[0] == 0x6F) {
+ if (p2 != 0x0C && apdu.resplen > 2 && apdu.resp[0] == 0x6F) {
*file = sc_file_new();
if (!*file)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
- if (apdu.resp[1] <= apdu.resplen)
+ if (apdu.resp[1] > apdu.resplen - 2)
process_fcp(card, *file, apdu.resp + 2, apdu.resp[1]);
return SC_SUCCESS;
}
Index: opensc-0.21.0/src/libopensc/asn1.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/asn1.c
+++ opensc-0.21.0/src/libopensc/asn1.c
@@ -68,7 +68,7 @@ int sc_asn1_read_tag(const u8 ** buf, si
*buf = NULL;
- if (left == 0 || !p)
+ if (left == 0 || !p || buflen == 0)
return SC_ERROR_INVALID_ASN1_OBJECT;
if (*p == 0xff || *p == 0) {
/* end of data reached */
@@ -83,6 +83,8 @@ int sc_asn1_read_tag(const u8 ** buf, si
*/
cla = (*p & SC_ASN1_TAG_CLASS) | (*p & SC_ASN1_TAG_CONSTRUCTED);
tag = *p & SC_ASN1_TAG_PRIMITIVE;
+ if (left < 1)
+ return SC_ERROR_INVALID_ASN1_OBJECT;
p++;
left--;
if (tag == SC_ASN1_TAG_PRIMITIVE) {
Index: opensc-0.21.0/src/libopensc/card-dnie.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/card-dnie.c
+++ opensc-0.21.0/src/libopensc/card-dnie.c
@@ -1185,12 +1185,16 @@ static int dnie_compose_and_send_apdu(sc
if (file_out) {
/* finally process FCI response */
+ size_t len = apdu.resp[1];
sc_file_free(*file_out);
*file_out = sc_file_new();
if (*file_out == NULL) {
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
}
- res = card->ops->process_fci(card, *file_out, apdu.resp + 2, apdu.resp[1]);
+ if (apdu.resplen - 2 < len || len < 1) {
+ LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
+ }
+ res = card->ops->process_fci(card, *file_out, apdu.resp + 2, len);
}
LOG_FUNC_RETURN(ctx, res);
}
@@ -1949,7 +1953,7 @@ static int dnie_process_fci(struct sc_ca
int *op = df_acl;
int n = 0;
sc_context_t *ctx = NULL;
- if ((card == NULL) || (card->ctx == NULL) || (file == NULL))
+ if ((card == NULL) || (card->ctx == NULL) || (file == NULL) || buflen == 0)
return SC_ERROR_INVALID_ARGUMENTS;
ctx = card->ctx;
LOG_FUNC_CALLED(ctx);
Index: opensc-0.21.0/src/libopensc/muscle.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/muscle.c
+++ opensc-0.21.0/src/libopensc/muscle.c
@@ -94,33 +94,35 @@ int msc_partial_read_object(sc_card_t *c
apdu.resp = data;
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
- if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
- return dataLength;
- if(apdu.sw1 == 0x9C) {
- if(apdu.sw2 == 0x07) {
+ if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00 && dataLength <= apdu.resplen)
+ return dataLength;
+ if (apdu.sw1 == 0x9C) {
+ if (apdu.sw2 == 0x07) {
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_FILE_NOT_FOUND);
- } else if(apdu.sw2 == 0x06) {
+ } else if (apdu.sw2 == 0x06) {
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_ALLOWED);
- } else if(apdu.sw2 == 0x0F) {
+ } else if (apdu.sw2 == 0x0F) {
/* GUESSED */
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
}
}
sc_log(card->ctx,
"got strange SWs: 0x%02X 0x%02X\n", apdu.sw1, apdu.sw2);
- return dataLength;
-
-}
+
+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_UNKNOWN_DATA_RECEIVED);
+ }
int msc_read_object(sc_card_t *card, msc_id objectId, int offset, u8 *data, size_t dataLength)
{
- int r;
+ int r = 0;
size_t i;
size_t max_read_unit = MSC_MAX_READ;
- for(i = 0; i < dataLength; i += max_read_unit) {
+ for(i = 0; i < dataLength; i += r) {
r = msc_partial_read_object(card, objectId, offset + i, data + i, MIN(dataLength - i, max_read_unit));
LOG_TEST_RET(card->ctx, r, "Error in partial object read");
+ if (r==0)
+ break;
}
return dataLength;
}
Index: opensc-0.21.0/src/libopensc/card-entersafe.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/card-entersafe.c
+++ opensc-0.21.0/src/libopensc/card-entersafe.c
@@ -1453,7 +1453,9 @@ static int entersafe_get_serialnr(sc_car
r=entersafe_transmit_apdu(card, &apdu,0,0,0,0);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
LOG_TEST_RET(card->ctx, sc_check_sw(card,apdu.sw1,apdu.sw2),"EnterSafe get SN failed");
-
+ if (apdu.resplen != 8)
+ LOG_TEST_RET(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid length of SN");
+
card->serialnr.len=serial->len=8;
memcpy(card->serialnr.value,rbuf,8);
memcpy(serial->value,rbuf,8);

View File

@ -0,0 +1,55 @@
commit fdb9e903eb124b6b18a5a9350a26eceb775585bc
Author: Veronika Hanulíková <vhanulik@redhat.com>
Date: Tue Jul 16 14:05:36 2024 +0200
cac: Check return value when selecting AID
Thanks Matteo Marini for report
https://github.com/OpenSC/OpenSC/security/advisories/GHSA-p3mx-7472-h3j8
fuzz_pkcs11/14
Index: opensc-0.21.0/src/libopensc/card-cac.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/card-cac.c
+++ opensc-0.21.0/src/libopensc/card-cac.c
@@ -1302,10 +1302,10 @@ static int cac_parse_aid(sc_card_t *card
/* Call without OID set will just select the AID without subsequent
* OID selection, which we need to figure out just now
*/
- cac_select_file_by_type(card, &new_object.path, NULL);
+ r = cac_select_file_by_type(card, &new_object.path, NULL);
+ LOG_TEST_RET(card->ctx, r, "Cannot select AID");
r = cac_get_properties(card, &prop);
- if (r < 0)
- return SC_ERROR_INTERNAL;
+ LOG_TEST_RET(card->ctx, r, "Cannot get CAC properties");
for (i = 0; i < prop.num_objects; i++) {
/* don't fail just because we have more certs than we can support */
Index: opensc-0.21.0/src/libopensc/card-cardos.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/card-cardos.c
+++ opensc-0.21.0/src/libopensc/card-cardos.c
@@ -1277,7 +1277,7 @@ cardos_lifecycle_get(sc_card_t *card, in
LOG_TEST_RET(card->ctx, r, "Card returned error");
if (apdu.resplen < 1) {
- LOG_TEST_RET(card->ctx, r, "Lifecycle byte not in response");
+ LOG_TEST_RET(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Lifecycle byte not in response");
}
r = SC_SUCCESS;
Index: opensc-0.21.0/src/libopensc/card-jpki.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/card-jpki.c
+++ opensc-0.21.0/src/libopensc/card-jpki.c
@@ -195,6 +195,8 @@ jpki_select_file(struct sc_card *card,
u8 buf[4];
rc = sc_read_binary(card, 0, buf, 4, 0);
LOG_TEST_RET(card->ctx, rc, "SW Check failed");
+ if (rc < 4)
+ LOG_TEST_RET(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Received data too short");
file = sc_file_new();
if (!file) {
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);

View File

@ -0,0 +1,67 @@
commit 8632ec172beda894581d67eaa991e519a7874f7d
Author: Veronika Hanulíková <vhanulik@redhat.com>
Date: Wed Jul 17 11:18:52 2024 +0200
pkcs15-tcos: Check return value of serial num conversion
Thanks Matteo Marini for report
https://github.com/OpenSC/OpenSC/security/advisories/GHSA-p3mx-7472-h3j8
fuzz_pkcs15_encode/21
diff --git a/src/libopensc/pkcs15-tcos.c b/src/libopensc/pkcs15-tcos.c
index 4d02a98ee..2bd275c4f 100644
--- a/src/libopensc/pkcs15-tcos.c
+++ b/src/libopensc/pkcs15-tcos.c
@@ -531,10 +531,15 @@ int sc_pkcs15emu_tcos_init_ex(
/* get the card serial number */
r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serialnr);
if (r < 0) {
- sc_log(ctx, "unable to get ICCSN\n");
+ sc_log(ctx, "unable to get ICCSN");
return SC_ERROR_WRONG_CARD;
}
- sc_bin_to_hex(serialnr.value, serialnr.len , serial, sizeof(serial), 0);
+ r = sc_bin_to_hex(serialnr.value, serialnr.len, serial, sizeof(serial), 0);
+ if (r != SC_SUCCESS) {
+ sc_log(ctx, "serial number invalid");
+ return SC_ERROR_INTERNAL;
+ }
+
serial[19] = '\0';
set_string(&p15card->tokeninfo->serial_number, serial);
commit f9d68660f032ad4d7803431d5fc7577ea8792ac3
Author: Veronika Hanulíková <vhanulik@redhat.com>
Date: Wed Jul 17 14:56:22 2024 +0200
pkcs15-lib: Report transport key error
Thanks Matteo Marini for report
https://github.com/OpenSC/OpenSC/security/advisories/GHSA-p3mx-7472-h3j8
fuzz_pkcs15init/17, fuzz_pkcs15init/18
diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c
index 6574e8025..943d53e98 100644
--- a/src/pkcs15init/pkcs15-lib.c
+++ b/src/pkcs15init/pkcs15-lib.c
@@ -3831,13 +3831,15 @@ sc_pkcs15init_get_transport_key(struct sc_profile *profile, struct sc_pkcs15_car
if (callbacks.get_key) {
rv = callbacks.get_key(profile, type, reference, defbuf, defsize, pinbuf, pinsize);
LOG_TEST_RET(ctx, rv, "Cannot get key");
- }
- else if (rv >= 0) {
+ } else if (rv >= 0) {
if (*pinsize < defsize)
LOG_TEST_RET(ctx, SC_ERROR_BUFFER_TOO_SMALL, "Get transport key error");
memcpy(pinbuf, data.key_data, data.len);
*pinsize = data.len;
+ } else {
+ /* pinbuf and pinsize were not filled */
+ LOG_TEST_RET(ctx, SC_ERROR_INTERNAL, "Get transport key error");
}
memset(&auth_info, 0, sizeof(auth_info));

221
opensc-CVE-2024-45619.patch Normal file
View File

@ -0,0 +1,221 @@
commit f01bfbd19b9c8243a40f7f17d554fe0eb9e89d0d
Author: Veronika Hanulíková <vhanulik@redhat.com>
Date: Tue Jul 16 14:22:02 2024 +0200
pkcs15-tcos: Check number of read bytes for cert
Thanks Matteo Marini for report
https://github.com/OpenSC/OpenSC/security/advisories/GHSA-p3mx-7472-h3j8
fuzz_pkcs11/15
Index: opensc-0.21.0/src/libopensc/pkcs15-tcos.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/pkcs15-tcos.c
+++ opensc-0.21.0/src/libopensc/pkcs15-tcos.c
@@ -45,6 +45,7 @@ static int insert_cert(
struct sc_pkcs15_cert_info cert_info;
struct sc_pkcs15_object cert_obj;
unsigned char cert[20];
+ size_t cert_len = 0;
int r;
memset(&cert_info, 0, sizeof(cert_info));
@@ -57,24 +58,31 @@ static int insert_cert(
strlcpy(cert_obj.label, label, sizeof(cert_obj.label));
cert_obj.flags = writable ? SC_PKCS15_CO_FLAG_MODIFIABLE : 0;
- if(sc_select_file(card, &cert_info.path, NULL)!=SC_SUCCESS){
- sc_log(ctx,
- "Select(%s) failed\n", path);
+ if (sc_select_file(card, &cert_info.path, NULL) != SC_SUCCESS) {
+ sc_log(ctx, "Select(%s) failed", path);
return 1;
}
- if(sc_read_binary(card, 0, cert, sizeof(cert), 0)<0){
- sc_log(ctx,
- "ReadBinary(%s) failed\n", path);
+ r = sc_read_binary(card, 0, cert, sizeof(cert), 0);
+ if (r <= 0) {
+ sc_log(ctx, "ReadBinary(%s) failed\n", path);
return 2;
}
- if(cert[0]!=0x30 || cert[1]!=0x82){
- sc_log(ctx,
- "Invalid Cert: %02X:%02X:...\n", cert[0], cert[1]);
+ cert_len = r; /* actual number of read bytes */
+ if (cert_len < 7 || (size_t)(7 + cert[5]) > cert_len) {
+ sc_log(ctx, "Invalid certificate length");
+ return 3;
+ }
+ if (cert[0] != 0x30 || cert[1] != 0x82) {
+ sc_log(ctx, "Invalid Cert: %02X:%02X:...\n", cert[0], cert[1]);
return 3;
}
/* some certificates are prefixed by an OID */
- if(cert[4]==0x06 && cert[5]<10 && cert[6+cert[5]]==0x30 && cert[7+cert[5]]==0x82){
+ if (cert[4] == 0x06 && cert[5] < 10 && cert[6 + cert[5]] == 0x30 && cert[7 + cert[5]] == 0x82) {
+ if ((size_t)(9 + cert[5]) > cert_len) {
+ sc_log(ctx, "Invalid certificate length");
+ return 3;
+ }
cert_info.path.index=6+cert[5];
cert_info.path.count=(cert[8+cert[5]]<<8) + cert[9+cert[5]] + 4;
} else {
@@ -82,12 +90,12 @@ static int insert_cert(
cert_info.path.count=(cert[2]<<8) + cert[3] + 4;
}
- r=sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
- if(r!=SC_SUCCESS){
- sc_log(ctx, "sc_pkcs15emu_add_x509_cert(%s) failed\n", path);
+ r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
+ if (r != SC_SUCCESS) {
+ sc_log(ctx, "sc_pkcs15emu_add_x509_cert(%s) failed", path);
return 4;
}
- sc_log(ctx, "%s: OK, Index=%d, Count=%d\n", path, cert_info.path.index, cert_info.path.count);
+ sc_log(ctx, "%s: OK, Index=%d, Count=%d", path, cert_info.path.index, cert_info.path.count);
return 0;
}
Index: opensc-0.21.0/src/libopensc/pkcs15-gemsafeV1.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/pkcs15-gemsafeV1.c
+++ opensc-0.21.0/src/libopensc/pkcs15-gemsafeV1.c
@@ -168,6 +168,7 @@ static int gemsafe_get_cert_len(sc_card_
struct sc_file *file;
size_t objlen, certlen;
unsigned int ind, i=0;
+ int read_len;
sc_format_path(GEMSAFE_PATH, &path);
r = sc_select_file(card, &path, &file);
@@ -176,9 +177,11 @@ static int gemsafe_get_cert_len(sc_card_
sc_file_free(file);
/* Initial read */
- r = sc_read_binary(card, 0, ibuf, GEMSAFE_READ_QUANTUM, 0);
- if (r < 0)
+ read_len = sc_read_binary(card, 0, ibuf, GEMSAFE_READ_QUANTUM, 0);
+ if (read_len <= 2) {
+ sc_log(card->ctx, "Invalid size of object data: %d", read_len);
return SC_ERROR_INTERNAL;
+ }
/* Actual stored object size is encoded in first 2 bytes
* (allocated EF space is much greater!)
@@ -207,7 +210,7 @@ static int gemsafe_get_cert_len(sc_card_
* the private key.
*/
ind = 2; /* skip length */
- while (ibuf[ind] == 0x01 && i < gemsafe_cert_max) {
+ while (ind + 1 < (size_t)read_len && ibuf[ind] == 0x01 && i < gemsafe_cert_max) {
if (ibuf[ind+1] == 0xFE) {
gemsafe_prkeys[i].ref = ibuf[ind+4];
sc_log(card->ctx, "Key container %d is allocated and uses key_ref %d",
@@ -234,7 +237,7 @@ static int gemsafe_get_cert_len(sc_card_
/* Read entire file, then dissect in memory.
* Gemalto ClassicClient seems to do it the same way.
*/
- iptr = ibuf + GEMSAFE_READ_QUANTUM;
+ iptr = ibuf + read_len;
while ((size_t)(iptr - ibuf) < objlen) {
r = sc_read_binary(card, iptr - ibuf, iptr,
MIN(GEMSAFE_READ_QUANTUM, objlen - (iptr - ibuf)), 0);
@@ -242,7 +245,14 @@ static int gemsafe_get_cert_len(sc_card_
sc_log(card->ctx, "Could not read cert object");
return SC_ERROR_INTERNAL;
}
- iptr += GEMSAFE_READ_QUANTUM;
+ if (r == 0)
+ break;
+ read_len += r;
+ iptr += r;
+ }
+ if ((size_t)read_len < objlen) {
+ sc_log(card->ctx, "Could not read cert object");
+ return SC_ERROR_INTERNAL;
}
/* Search buffer for certificates, they start with 0x3082. */
Index: opensc-0.21.0/src/pkcs15init/pkcs15-setcos.c
===================================================================
--- opensc-0.21.0.orig/src/pkcs15init/pkcs15-setcos.c
+++ opensc-0.21.0/src/pkcs15init/pkcs15-setcos.c
@@ -488,6 +488,9 @@ setcos_generate_key(struct sc_profile *p
r = sc_card_ctl(p15card->card, SC_CARDCTL_SETCOS_GETDATA, &data_obj);
LOG_TEST_RET(ctx, r, "Cannot get key modulus: 'SETCOS_GETDATA' failed");
+ if (data_obj.DataLen < 3 || data_obj.DataLen < pubkey->u.rsa.modulus.len)
+ LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Cannot get key modulus: wrong length of raw key");
+
keybits = ((raw_pubkey[0] * 256) + raw_pubkey[1]); /* modulus bit length */
if (keybits != key_info->modulus_length) {
sc_log(ctx,
@@ -495,7 +498,7 @@ setcos_generate_key(struct sc_profile *p
keybits, key_info->modulus_length);
LOG_TEST_RET(ctx, SC_ERROR_PKCS15INIT, "Failed to generate key");
}
- memcpy (pubkey->u.rsa.modulus.data, &raw_pubkey[2], pubkey->u.rsa.modulus.len);
+ memcpy(pubkey->u.rsa.modulus.data, &raw_pubkey[2], pubkey->u.rsa.modulus.len);
}
sc_file_free(file);
Index: opensc-0.21.0/src/pkcs15init/pkcs15-sc-hsm.c
===================================================================
--- opensc-0.21.0.orig/src/pkcs15init/pkcs15-sc-hsm.c
+++ opensc-0.21.0/src/pkcs15init/pkcs15-sc-hsm.c
@@ -140,7 +140,7 @@ static int sc_hsm_determine_free_id(stru
LOG_TEST_RET(card->ctx, filelistlength, "Could not enumerate file and key identifier");
for (j = 0; j < 256; j++) {
- for (i = 0; i < filelistlength; i += 2) {
+ for (i = 0; i + 1 < filelistlength; i += 2) {
if ((filelist[i] == range) && (filelist[i + 1] == j)) {
break;
}
Index: opensc-0.21.0/src/libopensc/card-coolkey.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/card-coolkey.c
+++ opensc-0.21.0/src/libopensc/card-coolkey.c
@@ -1684,6 +1684,7 @@ static int coolkey_rsa_op(sc_card_t *car
u8 key_number;
size_t params_len;
u8 buf[MAX_COMPUTE_BUF + 2];
+ size_t buf_len;
u8 *buf_out;
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
@@ -1724,8 +1725,6 @@ static int coolkey_rsa_op(sc_card_t *car
ushort2bebytes(params.init.buf_len, 0);
} else {
/* The data fits in APDU. Copy it to the params object */
- size_t buf_len;
-
params.init.location = COOLKEY_CRYPT_LOCATION_APDU;
params_len = sizeof(params.init) + datalen;
@@ -1745,6 +1744,7 @@ static int coolkey_rsa_op(sc_card_t *car
if (r < 0) {
goto done;
}
+ buf_len = crypt_out_len_p;
if (datalen > MAX_COMPUTE_BUF) {
u8 len_buf[2];
@@ -1763,7 +1763,12 @@ static int coolkey_rsa_op(sc_card_t *car
priv->nonce, sizeof(priv->nonce));
} else {
- size_t out_length = bebytes2ushort(buf);
+ size_t out_length;
+ if (buf_len < 2) {
+ r = SC_ERROR_WRONG_LENGTH;
+ goto done;
+ }
+ out_length = bebytes2ushort(buf);
if (out_length > sizeof buf - 2) {
r = SC_ERROR_WRONG_LENGTH;
goto done;

View File

@ -0,0 +1,73 @@
commit a1bcc6516f43d570899820d259b71c53f8049168
Author: Veronika Hanulíková <vhanulik@redhat.com>
Date: Thu Jul 18 09:23:20 2024 +0200
pkcs15-starcos: Check length of file to be non-zero
Thanks Matteo Marini for report
https://github.com/OpenSC/OpenSC/security/advisories/GHSA-p3mx-7472-h3j8
fuzz_pkcs15init/20
Index: opensc-0.21.0/src/pkcs15init/pkcs15-starcos.c
===================================================================
--- opensc-0.21.0.orig/src/pkcs15init/pkcs15-starcos.c
+++ opensc-0.21.0/src/pkcs15init/pkcs15-starcos.c
@@ -670,6 +670,8 @@ static int starcos_write_pukey(sc_profil
return r;
len = tfile->size;
sc_file_free(tfile);
+ if (len == 0)
+ return SC_ERROR_INTERNAL;
buf = malloc(len);
if (!buf)
return SC_ERROR_OUT_OF_MEMORY;
@@ -682,7 +684,7 @@ static int starcos_write_pukey(sc_profil
if (num_keys == 0xff)
num_keys = 0;
/* encode public key */
- keylen = starcos_encode_pukey(rsa, NULL, kinfo);
+ keylen = starcos_encode_pukey(rsa, NULL, kinfo);
if (!keylen) {
free(buf);
return SC_ERROR_INTERNAL;
Index: opensc-0.21.0/src/libopensc/iasecc-sdo.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/iasecc-sdo.c
+++ opensc-0.21.0/src/libopensc/iasecc-sdo.c
@@ -324,16 +324,25 @@ iasecc_se_parse(struct sc_card *card, un
LOG_FUNC_CALLED(ctx);
+ if (data_len < 1)
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
+
if (*data == IASECC_SDO_TEMPLATE_TAG) {
size_size = iasecc_parse_size(data + 1, &size);
LOG_TEST_RET(ctx, size_size, "parse error: invalid size data of IASECC_SDO_TEMPLATE");
+ if (data_len - 1 < size)
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
+
data += size_size + 1;
data_len = size;
sc_log(ctx,
"IASECC_SDO_TEMPLATE: size %"SC_FORMAT_LEN_SIZE_T"u, size_size %"SC_FORMAT_LEN_SIZE_T"u",
size, size_size);
+ if (data_len < 3)
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
+
if (*data != IASECC_SDO_TAG_HEADER)
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
@@ -728,6 +737,8 @@ iasecc_sdo_parse(struct sc_card *card, u
int rv;
LOG_FUNC_CALLED(ctx);
+ if (data == NULL || data_len < 2)
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
if (*data == IASECC_SDO_TEMPLATE_TAG) {
size_size = iasecc_parse_size(data + 1, &size);

View File

@ -0,0 +1,78 @@
commit b28a3cef416fcfb92fbb9ea7fd3c71df52c6c9fc
Author: Jakub Jelen <jjelen@redhat.com>
Date: Mon Aug 12 19:02:14 2024 +0200
openpgp: Do not accept non-matching key responses
When generating RSA key pair using PKCS#15 init, the driver could accept
responses relevant to ECC keys, which made further processing in the
pkcs15-init failing/accessing invalid parts of structures.
Thanks oss-fuzz!
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=71010
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Index: opensc-0.21.0/src/libopensc/card-openpgp.c
===================================================================
--- opensc-0.21.0.orig/src/libopensc/card-openpgp.c
+++ opensc-0.21.0/src/libopensc/card-openpgp.c
@@ -2657,14 +2657,21 @@ pgp_calculate_and_store_fingerprint(sc_c
/* update the blob containing fingerprints (00C5) */
sc_log(card->ctx, "Updating fingerprint blob 00C5.");
fpseq_blob = pgp_find_blob(card, 0x00C5);
- if (fpseq_blob == NULL)
- LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot find blob 00C5");
+ if (fpseq_blob == NULL) {
+ r = SC_ERROR_OUT_OF_MEMORY;
+ LOG_TEST_GOTO_ERR(card->ctx, r, "Cannot find blob 00C5");
+ }
+ if (20 * key_info->key_id > fpseq_blob->len) {
+ r = SC_ERROR_OBJECT_NOT_VALID;
+ LOG_TEST_GOTO_ERR(card->ctx, r, "The 00C5 blob is not large enough");
+ }
/* save the fingerprints sequence */
newdata = malloc(fpseq_blob->len);
- if (newdata == NULL)
- LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_OUT_OF_MEMORY,
- "Not enough memory to update fingerprint blob 00C5");
+ if (newdata == NULL) {
+ r = SC_ERROR_OUT_OF_MEMORY;
+ LOG_TEST_GOTO_ERR(card->ctx, r, "Not enough memory to update fingerprint blob 00C5");
+ }
memcpy(newdata, fpseq_blob->data, fpseq_blob->len);
/* move p to the portion holding the fingerprint of the current key */
@@ -2778,6 +2785,9 @@ pgp_parse_and_set_pubkey_output(sc_card_
/* RSA modulus */
if (tag == 0x0081) {
+ if (key_info->algorithm != SC_OPENPGP_KEYALGO_RSA) {
+ LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
+ }
if ((BYTES4BITS(key_info->u.rsa.modulus_len) < len) /* modulus_len is in bits */
|| key_info->u.rsa.modulus == NULL) {
@@ -2793,6 +2803,9 @@ pgp_parse_and_set_pubkey_output(sc_card_
}
/* RSA public exponent */
else if (tag == 0x0082) {
+ if (key_info->algorithm != SC_OPENPGP_KEYALGO_RSA) {
+ LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
+ }
if ((BYTES4BITS(key_info->u.rsa.exponent_len) < len) /* exponent_len is in bits */
|| key_info->u.rsa.exponent == NULL) {
@@ -2808,6 +2821,10 @@ pgp_parse_and_set_pubkey_output(sc_card_
}
/* ECC public key */
else if (tag == 0x0086) {
+ if (key_info->algorithm != SC_OPENPGP_KEYALGO_ECDSA &&
+ key_info->algorithm != SC_OPENPGP_KEYALGO_ECDH) {
+ LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
+ }
/* set the output data */
/* len is ecpoint length + format byte
* see section 7.2.14 of 3.3.1 specs */

View File

@ -3,7 +3,7 @@
Name: opensc
Version: 0.21.0
Release: 6
Release: 11
License: LGPLv2.1+
Summary: Smart card library and applications
URL: https://github.com/OpenSC/OpenSC/wiki
@ -37,6 +37,31 @@ Patch16: backport-0002-CVE-2021-42782-coolkey-Initialize-potentially.patch
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
Patch23: 0007-opensc-CVE-2023-40661-1of12.patch
Patch24: 0008-opensc-CVE-2023-40661-2of12.patch
Patch25: 0009-opensc-CVE-2023-40661-3of12.patch
Patch26: 0010-opensc-CVE-2023-40661-4of12.patch
Patch27: 0011-opensc-CVE-2023-40661-5of12.patch
Patch28: 0012-opensc-CVE-2023-40661-6of12.patch
Patch29: 0013-opensc-CVE-2023-40661-7of12.patch
Patch30: 0014-opensc-CVE-2023-40661-8of12.patch
Patch31: 0015-opensc-CVE-2023-40661-9of12.patch
Patch32: 0016-opensc-CVE-2023-40661-10of12.patch
Patch33: 0017-opensc-CVE-2023-40661-11of12.patch
Patch34: 0018-opensc-CVE-2023-40661-12of12.patch
# https://github.com/OpenSC/OpenSC/pull/2948
# https://github.com/OpenSC/OpenSC/pull/3016
Patch35: backport-opensc-CVE-2023-5992.patch
Patch36: opensc-CVE-2024-45615.patch
Patch38: opensc-CVE-2024-45616.patch
Patch39: opensc-CVE-2024-45617.patch
Patch40: opensc-CVE-2024-45618.patch
Patch41: opensc-CVE-2024-45619.patch
Patch42: opensc-CVE-2024-45620.patch
Patch43: opensc-CVE-2024-8443.patch
%description
OpenSC provides a set of libraries and utilities to work with smart cards.
@ -155,6 +180,22 @@ make check
%{_datadir}/opensc/
%changelog
* Mon Oct 07 2024 Funda Wang <fundawang@yeah.net> - 0.21.0-11
- fix CVE-2024-8443, CVE-2024-45615, CVE-2024-45616,
CVE-2024-45617, CVE-2024-45618, CVE-2024-45619, CVE-2024-45620
* Mon Jul 1 2024 dillon chen <dillon.chen@gmail.com> - 0.21.0-10
- fix CVE-2023-5992
* Wed Nov 8 2023 dillon chen <dillon.chen@gmail.com> - 0.21.0-9
- fix CVE-2023-40661
* 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
* Mon May 9 2022 Hugel <gengqihu1@h-partners.com> - 0.21.0-6
- fix CVE-2021-42782