Compare commits

...

11 Commits

Author SHA1 Message Date
openeuler-ci-bot
292be3dd19
!86 [sync] PR-82: 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-08 08:52:05 +00:00
Funda Wang
955439d2aa 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 72ed47eab9c6389435989294e353b2d94615e258)
2024-10-08 16:36:20 +08:00
openeuler-ci-bot
442fd77cf4
!79 backport 1 commit,fix clang build error
From: @yuncang123 
Reviewed-by: @xiezhipeng1 
Signed-off-by: @xiezhipeng1
2024-09-09 12:15:09 +00:00
yuncang123
75204ca35d backport to avoid calling functions without prototype,add -Wno-error 2024-09-04 18:05:57 +08:00
openeuler-ci-bot
564062ac7b
!75 [sync] PR-71: fix CVE-2023-5992
From: @openeuler-sync-bot 
Reviewed-by: @dillon_chen 
Signed-off-by: @dillon_chen
2024-07-02 01:27:57 +00:00
dillon_chen
1d6ca8a1ff fix CVE-2023-5992
(cherry picked from commit 4a65537bcccc749595144eacb116a3112e776ab5)
2024-07-02 09:12:28 +08:00
openeuler-ci-bot
251c7db3f7
!55 三个CVE
From: @dillon_chen 
Reviewed-by: @overweight 
Signed-off-by: @overweight
2023-10-23 01:09:54 +00:00
dillon_chen
e2cd5ca55b CVE-2023-40660, CVE-2023-4535, CVE-2023-40661 2023-10-20 17:34:43 +08:00
openeuler-ci-bot
564a9f86a4
!50 fix CVE-2021-34193
From: @Gzx1999 
Reviewed-by: @dillon_chen 
Signed-off-by: @dillon_chen
2023-09-11 01:53:32 +00:00
Gzx1999
0e0a01c0ab fix CVE-2021-34193 2023-09-09 20:02:47 +08:00
openeuler-ci-bot
983b06c889
!49 fix CVE-2023-2977
From: @Gzx1999 
Reviewed-by: @dillon_chen 
Signed-off-by: @dillon_chen
2023-09-07 07:30:28 +00:00
27 changed files with 3399 additions and 1 deletions

View File

@ -0,0 +1,26 @@
From ae1cf0be90396fb6c0be95829bf0d3eecbd2fd1c Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Thu, 11 Feb 2021 11:22:54 +0100
Subject: [PATCH] iasecc: Prevent stack buffer overflow when empty ACL is
returned
Thanks oss-fuzz
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=30800
---
src/libopensc/card-iasecc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c
index 166bc307bc..0eec63363a 100644
--- a/src/libopensc/card-iasecc.c
+++ b/src/libopensc/card-iasecc.c
@@ -1251,7 +1251,7 @@ iasecc_process_fci(struct sc_card *card, struct sc_file *file,
else
acls = sc_asn1_find_tag(ctx, buf, buflen, IASECC_DOCP_TAG_ACLS_CONTACT, &taglen);
- if (!acls) {
+ if (!acls || taglen < 7) {
sc_log(ctx,
"ACLs not found in data(%"SC_FORMAT_LEN_SIZE_T"u) %s",
buflen, sc_dump_hex(buf, buflen));

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

View File

@ -0,0 +1,54 @@
From cde2e050ec4f2f1b7db38429aa4e9c0f4656308c Mon Sep 17 00:00:00 2001
From: Peter Popovec <popovec.peter@gmail.com>
Date: Wed, 26 Apr 2023 13:22:09 +0200
Subject: [PATCH] NULL pointer fix
Thanks to the clang analyzer:
Null pointer passed to 2nd parameter expecting 'nonnull'
[clang-analyzer-core.NonNullParamChecker]
modified: src/libopensc/card-myeid.c
---
src/libopensc/card-myeid.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c
index 31dd209f3e..951c179f1b 100644
--- a/src/libopensc/card-myeid.c
+++ b/src/libopensc/card-myeid.c
@@ -1973,6 +1973,9 @@ myeid_enc_dec_sym(struct sc_card *card, const u8 *data, size_t datalen,
return_len = block_size - pad_byte;
}
*outlen = return_len;
+ /* application can request buffer size or actual buffer size is too small */
+ if (out == NULL)
+ LOG_FUNC_RETURN(ctx, SC_SUCCESS);
if (return_len > *outlen)
LOG_FUNC_RETURN(ctx, SC_ERROR_BUFFER_TOO_SMALL);
memcpy(out, priv->sym_plain_buffer, return_len);
@@ -2042,10 +2045,11 @@ myeid_enc_dec_sym(struct sc_card *card, const u8 *data, size_t datalen,
priv->sym_crypt_buffer_len = 0;
rest_len = 0;
}
- memcpy(sdata, data, apdu_datalen);
- data += apdu_datalen;
- datalen -= apdu_datalen;
-
+ if (data) {
+ memcpy(sdata, data, apdu_datalen);
+ data += apdu_datalen;
+ datalen -= apdu_datalen;
+ }
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
@@ -2084,7 +2088,8 @@ myeid_enc_dec_sym(struct sc_card *card, const u8 *data, size_t datalen,
/* save rest of data for next run */
priv->sym_crypt_buffer_len = datalen;
sc_log(ctx, "rest data len = %zu", datalen);
- memcpy(priv->sym_crypt_buffer, data, datalen);
+ if (data)
+ memcpy(priv->sym_crypt_buffer, data, datalen);
sc_log(ctx, "return data len = %zu", return_len);
*outlen = return_len;
return SC_SUCCESS;

View File

@ -0,0 +1,39 @@
From f1993dc4e0b33050b8f72a3558ee88b24c4063b2 Mon Sep 17 00:00:00 2001
From: Peter Popovec <popovec.peter@gmail.com>
Date: Tue, 27 Jun 2023 09:50:42 +0200
Subject: [PATCH] myeid: fixed CID 380538 Out-of-bounds read (OVERRUN)
also fixes output buffer size checking
---
src/libopensc/card-myeid.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c
index 4ee4246840..50e78ff1d8 100644
--- a/src/libopensc/card-myeid.c
+++ b/src/libopensc/card-myeid.c
@@ -1986,18 +1986,20 @@ myeid_enc_dec_sym(struct sc_card *card, const u8 *data, size_t datalen,
sc_log(ctx, "Found padding byte %02x", pad_byte);
if (pad_byte == 0 || pad_byte > block_size)
LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING);
- sdata = priv->sym_plain_buffer + block_size - pad_byte;
+ sdata = priv->sym_plain_buffer + block_size;
for (i = 0; i < pad_byte; i++)
- if (sdata[i] != pad_byte)
+ if (*(--sdata) != pad_byte)
LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING);
return_len = block_size - pad_byte;
}
- *outlen = return_len;
/* application can request buffer size or actual buffer size is too small */
- if (out == NULL)
+ if (out == NULL) {
+ *outlen = return_len;
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
+ }
if (return_len > *outlen)
LOG_FUNC_RETURN(ctx, SC_ERROR_BUFFER_TOO_SMALL);
+ *outlen = return_len;
memcpy(out, priv->sym_plain_buffer, return_len);
sc_log(ctx, "C_DecryptFinal %zu bytes", *outlen);
return SC_SUCCESS;

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,546 @@
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;
@@ -386,7 +386,7 @@ static int refresh_attributes(sc_reader_t *reader)
}
LOG_FUNC_RETURN(reader->ctx, SC_SUCCESS);
}
-
+
/* the system could not detect the reader. It means, the prevoiusly attached reader is disconnected. */
if (rv == (LONG)SCARD_E_UNKNOWN_READER
#ifdef SCARD_E_NO_READERS_AVAILABLE
@@ -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");
}
}
}
@@ -1177,7 +1177,7 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle)
priv->modify_ioctl_finish = ntohl(pcsc_tlv->value);
} else if (pcsc_tlv->tag == FEATURE_IFD_PIN_PROPERTIES) {
priv->pin_properties_ioctl = ntohl(pcsc_tlv->value);
- } else if (pcsc_tlv->tag == FEATURE_GET_TLV_PROPERTIES) {
+ } else if (pcsc_tlv->tag == FEATURE_GET_TLV_PROPERTIES) {
priv->get_tlv_properties = ntohl(pcsc_tlv->value);
} else if (pcsc_tlv->tag == FEATURE_EXECUTE_PACE) {
priv->pace_ioctl = ntohl(pcsc_tlv->value);
@@ -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,
@@ -1266,34 +1266,55 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle)
}
}
+ size_t max_send_size = 0;
+ size_t max_recv_size = 0;
if (priv->get_tlv_properties) {
/* Try to set reader max_send_size and max_recv_size based on
* detected max_data */
- int max_data = part10_detect_max_data(reader, card_handle);
-
- if (max_data > 0) {
- sc_log(ctx, "Reader supports transceiving %d bytes of data",
- max_data);
- if (!priv->gpriv->force_max_send_size)
- reader->max_send_size = max_data;
- else
- sc_log(ctx, "Sending is limited to %"SC_FORMAT_LEN_SIZE_T"u bytes of data"
- " in configuration file", reader->max_send_size);
- if (!priv->gpriv->force_max_recv_size)
- reader->max_recv_size = max_data;
- else
- sc_log(ctx, "Receiving is limited to %"SC_FORMAT_LEN_SIZE_T"u bytes of data"
- " in configuration file", reader->max_recv_size);
- } else {
- sc_log(ctx, "Assuming that the reader supports transceiving "
- "short length APDUs only");
- }
+ max_send_size = max_recv_size = part10_detect_max_data(reader, card_handle);
/* debug the product and vendor ID of the reader */
part10_get_vendor_product(reader, card_handle, NULL, NULL);
}
+ else {
+ /* Try to set default limits based on device name */
+ if (!strncmp("REINER SCT cyberJack", reader->name, 20)) {
+ max_send_size = 1014;
+ max_recv_size = 1014;
+ }
+ else if (!strncmp("Secure Flash Card", reader->name, 17)) {
+ max_send_size = 478;
+ max_recv_size = 506;
+ }
+ }
- if(gpriv->SCardGetAttrib != NULL) {
+ if (max_send_size > 0) {
+ sc_log(ctx, "Reader supports sending %"SC_FORMAT_LEN_SIZE_T"u bytes of data",
+ max_send_size);
+ if (!priv->gpriv->force_max_send_size)
+ reader->max_send_size = max_send_size;
+ else
+ sc_log(ctx, "Sending is limited to %"SC_FORMAT_LEN_SIZE_T"u bytes of data"
+ " in configuration file", reader->max_send_size);
+ } else {
+ sc_log(ctx, "Assuming that the reader supports sending "
+ "short length APDUs only");
+ }
+
+ if (max_recv_size > 0) {
+ sc_log(ctx, "Reader supports receiving %"SC_FORMAT_LEN_SIZE_T"u bytes of data",
+ max_recv_size);
+ if (!priv->gpriv->force_max_recv_size)
+ reader->max_recv_size = max_recv_size;
+ else
+ sc_log(ctx, "Receiving is limited to %"SC_FORMAT_LEN_SIZE_T"u bytes of data"
+ " in configuration file", reader->max_recv_size);
+ } else {
+ sc_log(ctx, "Assuming that the reader supports receiving "
+ "short length APDUs only");
+ }
+
+ if (gpriv->SCardGetAttrib != NULL) {
rcount = sizeof(buf);
if (gpriv->SCardGetAttrib(card_handle, SCARD_ATTR_VENDOR_NAME,
buf, &rcount) == SCARD_S_SUCCESS
@@ -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;
@@ -1684,7 +1705,7 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re
state = rsp->dwEventState;
rsp->dwCurrentState = rsp->dwEventState;
if (state & SCARD_STATE_CHANGED) {
- /* check for hotplug events */
+ /* check for hotplug events */
if (!strcmp(rsp->szReader, "\\\\?PnP?\\Notification")) {
sc_log(ctx, "detected hotplug event");
/* Windows sends hotplug event on both, attaching and
@@ -1859,7 +1880,7 @@ static int part10_build_verify_pin_block(struct sc_reader *reader, u8 * buf, siz
u8 tmp;
unsigned int tmp16;
unsigned int off;
- PIN_VERIFY_STRUCTURE *pin_verify = (PIN_VERIFY_STRUCTURE *)buf;
+ PIN_VERIFY_STRUCTURE *pin_verify = (PIN_VERIFY_STRUCTURE *)buf;
/* PIN verification control message */
pin_verify->bTimerOut = SC_CCID_PIN_TIMEOUT;
@@ -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;
@@ -2569,7 +2590,7 @@ int pcsc_use_reader(sc_context_t *ctx, void * pcsc_context_handle, void * pcsc_c
gpriv->attached_reader = NULL;
gpriv->pcsc_ctx = *(SCARDCONTEXT *)pcsc_context_handle;
- card_handle = *(SCARDHANDLE *)pcsc_card_handle;
+ card_handle = *(SCARDHANDLE *)pcsc_card_handle;
if(SCARD_S_SUCCESS == gpriv->SCardGetAttrib(card_handle,
SCARD_ATTR_DEVICE_SYSTEM_NAME_A, (LPBYTE)
diff --git a/src/tests/fuzzing/fuzz_pkcs15_decode.c b/src/tests/fuzzing/fuzz_pkcs15_decode.c
index a83c719cb9..e5758ba4d5 100644
--- a/src/tests/fuzzing/fuzz_pkcs15_decode.c
+++ b/src/tests/fuzzing/fuzz_pkcs15_decode.c
@@ -108,9 +108,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
sc_pkcs15_parse_unusedspace(buf, buf_len, p15card);
- sc_pkcs15_card_free(p15card);
-
err:
+ sc_pkcs15_card_free(p15card);
sc_disconnect_card(card);
sc_release_context(ctx);
return 0;
diff --git a/src/tests/fuzzing/fuzz_pkcs15_encode.c b/src/tests/fuzzing/fuzz_pkcs15_encode.c
index eb3436dae2..a10ecf5645 100644
--- a/src/tests/fuzzing/fuzz_pkcs15_encode.c
+++ b/src/tests/fuzzing/fuzz_pkcs15_encode.c
@@ -80,8 +80,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
sc_pkcs15_encode_unusedspace(ctx, p15card, &unused_space, &unused_space_len);
free(unused_space);
- sc_pkcs15_card_free(p15card);
err:
+ sc_pkcs15_card_free(p15card);
sc_disconnect_card(card);
sc_release_context(ctx);

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,824 @@
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 5153428dce..9ecbffe8fd 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='' --checks='$(TIDY_CHECKS)' -header-filter=.* $(addprefix $(srcdir)/,$(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 7531260c14..2a98f0e966 100644
--- a/src/libopensc/internal.h
+++ b/src/libopensc/internal.h
@@ -175,8 +175,8 @@ int _sc_card_add_xeddsa_alg(struct sc_card *card, size_t key_length,
int sc_pkcs1_strip_01_padding(struct sc_context *ctx, const u8 *in_dat, size_t in_len,
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);
#ifdef ENABLE_OPENSSL
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"
#include "pkcs11/pkcs11.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);
}
#ifdef ENABLE_OPENSSL
diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c
index 3391994abe..5248d9758a 100644
--- a/src/minidriver/minidriver.c
+++ b/src/minidriver/minidriver.c
@@ -4653,9 +4653,9 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData,
"sc_pkcs15_decipher: DECRYPT-INFO dwVersion=%lu\n",
(unsigned long)pInfo->dwVersion);
if (pInfo->dwPaddingType == CARD_PADDING_PKCS1) {
- size_t temp = pInfo->cbData;
+ unsigned int temp = pInfo->cbData;
logprintf(pCardData, 2, "sc_pkcs15_decipher: stripping PKCS1 padding\n");
- r = sc_pkcs1_strip_02_padding(vs->ctx, pbuf2, pInfo->cbData, pbuf2, &temp);
+ r = sc_pkcs1_strip_02_padding_constant_time(vs->ctx, prkey_info->modulus_length / 8, pbuf2, pInfo->cbData, pbuf2, &temp);
pInfo->cbData = (DWORD) temp;
if (r < 0) {
logprintf(pCardData, 2, "Cannot strip PKCS1 padding: %i\n", r);
diff --git a/src/tests/unittests/Makefile.am b/src/tests/unittests/Makefile.am
index 7019ca7ba8..4c73911e48 100644
--- a/src/tests/unittests/Makefile.am
+++ b/src/tests/unittests/Makefile.am
@@ -6,8 +6,10 @@ include $(top_srcdir)/aminclude_static.a
clean-local: code-coverage-clean
distclean-local: code-coverage-dist-clean
-noinst_PROGRAMS = asn1 simpletlv cachedir pkcs15filter openpgp-tool hextobin decode_ecdsa_signature
-TESTS = asn1 simpletlv cachedir pkcs15filter openpgp-tool hextobin decode_ecdsa_signature
+noinst_PROGRAMS = asn1 simpletlv cachedir pkcs15filter openpgp-tool hextobin \
+ decode_ecdsa_signature strip_pkcs1_2_padding
+TESTS = asn1 simpletlv cachedir pkcs15filter openpgp-tool hextobin \
+ decode_ecdsa_signature strip_pkcs1_2_padding
noinst_HEADERS = torture.h
@@ -28,6 +30,7 @@ pkcs15filter_SOURCES = pkcs15-emulator-f
openpgp_tool_SOURCES = openpgp-tool.c $(top_builddir)/src/tools/openpgp-tool-helpers.c
hextobin_SOURCES = hextobin.c
decode_ecdsa_signature_SOURCES = decode_ecdsa_signature.c
+strip_pkcs1_2_paddingSOURCES = strip_pkcs1_2_padding.c
if ENABLE_ZLIB
noinst_PROGRAMS += compression
diff --git a/src/tests/unittests/Makefile.mak b/src/tests/unittests/Makefile.mak
index 2607546f57..6284b51af9 100644
--- a/src/tests/unittests/Makefile.mak
+++ b/src/tests/unittests/Makefile.mak
@@ -1,10 +1,11 @@
TOPDIR = ..\..\..
-TARGETS = asn1 compression pkcs15filter
+TARGETS = asn1 compression pkcs15filter strip_pkcs1_2_padding
OBJECTS = asn1.obj \
compression.obj \
- pkcs15-emulator-filter.obj
+ pkcs15-emulator-filter.obj \
+ strip_pkcs1_2_padding.obj \
$(TOPDIR)\win32\versioninfo.res
all: $(TARGETS)
diff --git a/src/tests/unittests/strip_pkcs1_2_padding.c b/src/tests/unittests/strip_pkcs1_2_padding.c
new file mode 100644
index 0000000000..f9561b936d
--- /dev/null
+++ b/src/tests/unittests/strip_pkcs1_2_padding.c
@@ -0,0 +1,204 @@
+#include "common/compat_strlcpy.c"
+#include "libopensc/log.c"
+#include "libopensc/padding.c"
+#include "torture.h"
+#include <cmocka.h>
+
+static void
+torture_long_output_buffer(void **state)
+{
+ unsigned int n = 14;
+ unsigned int in_len = 14;
+ unsigned char in[] = {0x00, 0x02,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x00,
+ 'm', 's', 'g'};
+ unsigned int out_len = 3;
+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
+ unsigned char result_msg[] = {'m', 's', 'g'};
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+ assert_int_equal(r, 3);
+ assert_memory_equal(out, result_msg, r);
+ free(out);
+}
+
+static void
+torture_short_output_buffer(void **state)
+{
+ unsigned int n = 14;
+ unsigned int in_len = 14;
+ unsigned char in[] = {0x00, 0x02,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x00,
+ 'm', 's', 'g'};
+ unsigned int out_len = 1;
+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+ assert_int_equal(r, SC_ERROR_WRONG_PADDING);
+ free(out);
+}
+
+static void
+torture_short_message_correct_padding(void **state)
+{
+ unsigned int n = 14;
+ unsigned int in_len = 14;
+ unsigned char in[] = {0x00, 0x02,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x00,
+ 'm', 's', 'g'};
+ unsigned int out_len = 3;
+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
+ unsigned char result_msg[] = {'m', 's', 'g'};
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+ assert_int_equal(r, 3);
+ assert_memory_equal(out, result_msg, r);
+ free(out);
+}
+
+static void
+torture_missing_first_zero(void **state)
+{
+ unsigned int n = 13;
+ unsigned int in_len = 13;
+ unsigned char in[] = {0x02,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x00,
+ 'm', 's', 'g'};
+ unsigned int out_len = 10;
+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+ assert_int_equal(r, SC_ERROR_WRONG_PADDING);
+ free(out);
+}
+
+static void
+torture_missing_two(void **state)
+{
+ unsigned int n = 13;
+ unsigned int in_len = 13;
+ unsigned char in[] = {0x00,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x00,
+ 'm', 's', 'g'};
+ unsigned int out_len = 10;
+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+ assert_int_equal(r, SC_ERROR_WRONG_PADDING);
+ free(out);
+}
+
+static void
+torture_short_padding(void **state)
+{
+ unsigned int n = 13;
+ unsigned int in_len = 13;
+ unsigned char in[] = {0x00, 0x02,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x00,
+ 'm', 's', 'g'};
+ unsigned int out_len = 10;
+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+ assert_int_equal(r, SC_ERROR_WRONG_PADDING);
+ free(out);
+}
+
+static void
+torture_missing_second_zero(void **state)
+{
+ unsigned int n = 13;
+ unsigned int in_len = 13;
+ unsigned char in[] = {0x00, 0x02,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 'm', 's', 'g'};
+ unsigned int out_len = 10;
+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+ assert_int_equal(r, SC_ERROR_WRONG_PADDING);
+ free(out);
+}
+
+static void
+torture_missing_message(void **state)
+{
+ unsigned int n = 20;
+ unsigned int in_len = 11;
+ unsigned char in[] = {0x00, 0x02,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x00};
+ unsigned int out_len = 11;
+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+ assert_int_equal(r, SC_ERROR_WRONG_PADDING);
+ free(out);
+}
+
+static void
+torture_one_byte_message(void **state)
+{
+ unsigned int n = 12;
+ unsigned int in_len = 12;
+ unsigned char in[] = {0x00, 0x02,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x00,
+ 'm'};
+ unsigned int out_len = 1;
+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
+ unsigned char result_msg[] = {'m'};
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+ assert_int_equal(r, 1);
+ assert_memory_equal(out, result_msg, r);
+ free(out);
+}
+
+static void
+torture_longer_padding(void **state)
+{
+ unsigned int n = 26;
+ unsigned int in_len = 26;
+ unsigned char in[] = {0x00, 0x02,
+ 0x0e, 0x38, 0x97, 0x18, 0x16, 0x57, 0x9e, 0x30, 0xb6, 0xa5, 0x78, 0x13, 0x20, 0xca, 0x11,
+ 0x00,
+ 0x9d, 0x98, 0x3d, 0xca, 0xa9, 0xa7, 0x11, 0x0a};
+ unsigned int out_len = 8;
+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
+ unsigned char result_msg[] = {0x9d, 0x98, 0x3d, 0xca, 0xa9, 0xa7, 0x11, 0x0a};
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+ assert_int_equal(r, 8);
+ assert_memory_equal(out, result_msg, r);
+ free(out);
+}
+
+static void
+torture_empty_message(void **state)
+{
+ unsigned int n = 18;
+ unsigned int in_len = 18;
+ unsigned char in[] = {0x00, 0x02,
+ 0x0e, 0x38, 0x97, 0x18, 0x16, 0x57, 0x9e, 0x30, 0xb6, 0xa5, 0x78, 0x13, 0x20, 0xca, 0x11,
+ 0x00};
+ unsigned int out_len = 8;
+ unsigned char *out = calloc(out_len, sizeof(unsigned char));
+ int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len);
+ assert_int_equal(r, 0);
+ free(out);
+}
+
+int
+main(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(torture_long_output_buffer),
+ cmocka_unit_test(torture_short_output_buffer),
+ cmocka_unit_test(torture_short_message_correct_padding),
+ cmocka_unit_test(torture_missing_first_zero),
+ cmocka_unit_test(torture_missing_two),
+ cmocka_unit_test(torture_short_padding),
+ cmocka_unit_test(torture_missing_second_zero),
+ cmocka_unit_test(torture_missing_message),
+ cmocka_unit_test(torture_one_byte_message),
+ cmocka_unit_test(torture_longer_padding),
+ cmocka_unit_test(torture_empty_message)};
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
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
@@ -308,9 +308,10 @@ 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 */
}
#ifdef ENABLE_OPENSSL
if (pad_flags & SC_ALGORITHM_RSA_PAD_OAEP)
@@ -332,7 +333,8 @@ int sc_pkcs15_decipher(struct sc_pkcs15_
LOG_TEST_RET(ctx, r, "Invalid OAEP padding");
}
#endif
- 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>
@@ -4395,7 +4396,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;
if (pulDataLen == NULL) {
/* This is call from the C_DecyptInit function */
@@ -4484,27 +4486,53 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_se
rv = sc_pkcs15_decipher(fw_data->p15_card, prkey->prv_p15obj, flags,
pEncryptedData, ulEncryptedDataLen, decrypted, sizeof(decrypted), pMechanism);
- 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), pMechanism);
sc_unlock(p11card->card);
- sc_log(context, "Decryption complete. Result %d.", rv);
+ sc_log(context, "Decryption complete.");
- if (rv < 0)
- return sc_to_cryptoki_error(rv, "C_Decrypt");
+ /* Handle following code in constant-time
+ * 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);
+ /* 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");
- return CKR_OK;
+ /* 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;
@@ -1110,10 +1113,12 @@ sc_pkcs11_decr_update(struct sc_pkcs11_s
rv = op->type->decrypt_update(op, pEncryptedData, ulEncryptedDataLen,
pData, pulDataLen);
- /* terminate session for any error except CKR_BUFFER_TOO_SMALL */
- if (rv != CKR_OK && rv != CKR_BUFFER_TOO_SMALL)
+ /* 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_OK) & ~constant_time_eq_s(rv, CKR_BUFFER_TOO_SMALL))
session_stop_operation(session, SC_PKCS11_OPERATION_DECRYPT);
- LOG_FUNC_RETURN(context, (int)rv);
+ /* do not log error code to prevent side channel attack */
+ return rv;
}
CK_RV
@@ -1530,6 +1535,10 @@ sc_pkcs11_decrypt(sc_pkcs11_operation_t
if (pulDataLen)
*pulDataLen = ulDataLen;
+ /* Skip DecryptFinalize for PKCS#1 v1.5 padding to prevent time side-channel leakage */
+ if (((CK_MECHANISM_PTR)&operation->mechanism)->mechanism == CKM_RSA_PKCS)
+ return rv;
+
if (rv != CKR_OK)
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
@@ -1034,7 +1034,8 @@ C_Decrypt(CK_SESSION_HANDLE hSession, /* the session's handle */
rv = reset_login_state(session->slot, rv);
}
- SC_LOG_RV("C_Decrypt() = %s", rv);
+ /* do not log error code to prevent side channel attack */
+ SC_LOG("C_Decrypt()");
sc_pkcs11_unlock();
return rv;
}
@@ -1058,7 +1059,8 @@ C_DecryptUpdate(CK_SESSION_HANDLE hSession, /* the session's handle */
rv = sc_pkcs11_decr_update(session, pEncryptedPart, ulEncryptedPartLen,
pPart, pulPartLen);
- SC_LOG_RV("C_DecryptUpdate() = %s", rv);
+ /* do not log error code to prevent side channel attack */
+ SC_LOG("C_DecryptUpdate()");
sc_pkcs11_unlock();
return rv;
}
@@ -1086,7 +1088,8 @@ C_DecryptFinal(CK_SESSION_HANDLE hSession, /* the session's handle */
rv = reset_login_state(session->slot, rv);
}
- SC_LOG_RV("C_DecryptFinal() = %s", rv);
+ /* do not log error code to prevent side channel attack */
+ SC_LOG("C_DecryptFinal()");
sc_pkcs11_unlock();
return rv;
}
diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h
index 66dfcdde67..510017ed2a 100644
--- a/src/pkcs11/sc-pkcs11.h
+++ b/src/pkcs11/sc-pkcs11.h
@@ -246,6 +246,11 @@ do {\
}\
} while(0)
+#define SC_LOG(fmt) \
+ do { \
+ sc_log(context, (fmt)); \
+ } while (0)
+
/* Debug virtual slots. S is slot to be highlighted or NULL
* C is a comment format string and args It will be preceded by "VSS " */
#define DEBUG_VSS(S, ...) do { sc_log(context,"VSS " __VA_ARGS__); _debug_virtual_slots(S); } while (0)
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);
}

View File

@ -0,0 +1,60 @@
From 17c6c80de8edd5d08db5bc2f914af6473a6f0f46 Mon Sep 17 00:00:00 2001
From: yuncang123 <1050706328@qq.com>
Date: Sun, 1 Sep 2024 16:08:07 +0800
Subject: [PATCH] backport-pgp-avoid calling functions without prototype
---
src/libopensc/card-openpgp.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
index fad32f0..e4e6cc4 100644
--- a/src/libopensc/card-openpgp.c
+++ b/src/libopensc/card-openpgp.c
@@ -129,7 +129,7 @@ static pgp_ec_curves_t ec_curves_gnuk[] = {
static int pgp_get_card_features(sc_card_t *card);
static int pgp_finish(sc_card_t *card);
-static void pgp_iterate_blobs(pgp_blob_t *, void (*func)());
+static void pgp_free_blobs(pgp_blob_t *);
static int pgp_get_blob(sc_card_t *card, pgp_blob_t *blob,
unsigned int id, pgp_blob_t **ret);
@@ -947,7 +947,7 @@ pgp_finish(sc_card_t *card)
if (priv != NULL) {
/* delete fake file hierarchy */
- pgp_iterate_blobs(priv->mf, pgp_free_blob);
+ pgp_free_blobs(priv->mf);
/* delete private data */
free(priv);
@@ -1147,10 +1147,10 @@ pgp_free_blob(pgp_blob_t *blob)
/**
- * Internal: iterate through the blob tree, calling a function for each blob.
+ * Internal: iterate through the blob tree, calling pgp_free_blob for each blob.
*/
static void
-pgp_iterate_blobs(pgp_blob_t *blob, void (*func)())
+pgp_free_blobs(pgp_blob_t *blob)
{
if (blob) {
pgp_blob_t *child = blob->files;
@@ -1158,10 +1158,10 @@ pgp_iterate_blobs(pgp_blob_t *blob, void (*func)())
while (child != NULL) {
pgp_blob_t *next = child->next;
- pgp_iterate_blobs(child, func);
+ pgp_free_blobs(child);
child = next;
}
- func(blob);
+ pgp_free_blob(blob);
}
}
--
2.43.0

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.23.0/src/libopensc/card-cac.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/card-cac.c
+++ opensc-0.23.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.23.0/src/libopensc/card-piv.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/card-piv.c
+++ opensc-0.23.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.23.0/src/libopensc/pkcs15-cert.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/pkcs15-cert.c
+++ opensc-0.23.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.23.0/src/libopensc/pkcs15-sc-hsm.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/pkcs15-sc-hsm.c
+++ opensc-0.23.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;
const u8 *tbuf;
int r;
Index: opensc-0.23.0/src/pkcs15init/profile.c
===================================================================
--- opensc-0.23.0.orig/src/pkcs15init/profile.c
+++ opensc-0.23.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.23.0/src/libopensc/card-cardos.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/card-cardos.c
+++ opensc-0.23.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.23.0/src/libopensc/card-cac1.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/card-cac1.c
+++ opensc-0.23.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.23.0/src/libopensc/card-oberthur.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/card-oberthur.c
+++ opensc-0.23.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.23.0/src/libopensc/card-gids.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/card-gids.c
+++ opensc-0.23.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.23.0/src/libopensc/card-mcrd.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/card-mcrd.c
+++ opensc-0.23.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.23.0/src/libopensc/asn1.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/asn1.c
+++ opensc-0.23.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.23.0/src/libopensc/card-dnie.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/card-dnie.c
+++ opensc-0.23.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.23.0/src/libopensc/muscle.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/muscle.c
+++ opensc-0.23.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.23.0/src/libopensc/card-entersafe.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/card-entersafe.c
+++ opensc-0.23.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.23.0/src/libopensc/card-cac.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/card-cac.c
+++ opensc-0.23.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.23.0/src/libopensc/card-cardos.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/card-cardos.c
+++ opensc-0.23.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.23.0/src/libopensc/card-jpki.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/card-jpki.c
+++ opensc-0.23.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.23.0/src/libopensc/pkcs15-tcos.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/pkcs15-tcos.c
+++ opensc-0.23.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.23.0/src/libopensc/pkcs15-gemsafeV1.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/pkcs15-gemsafeV1.c
+++ opensc-0.23.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.23.0/src/pkcs15init/pkcs15-setcos.c
===================================================================
--- opensc-0.23.0.orig/src/pkcs15init/pkcs15-setcos.c
+++ opensc-0.23.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.23.0/src/pkcs15init/pkcs15-sc-hsm.c
===================================================================
--- opensc-0.23.0.orig/src/pkcs15init/pkcs15-sc-hsm.c
+++ opensc-0.23.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.23.0/src/libopensc/card-coolkey.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/card-coolkey.c
+++ opensc-0.23.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.23.0/src/pkcs15init/pkcs15-starcos.c
===================================================================
--- opensc-0.23.0.orig/src/pkcs15init/pkcs15-starcos.c
+++ opensc-0.23.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.23.0/src/libopensc/iasecc-sdo.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/iasecc-sdo.c
+++ opensc-0.23.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.23.0/src/libopensc/card-openpgp.c
===================================================================
--- opensc-0.23.0.orig/src/libopensc/card-openpgp.c
+++ opensc-0.23.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,12 +3,44 @@
Name: opensc Name: opensc
Version: 0.23.0 Version: 0.23.0
Release: 2 Release: 7
License: LGPL-2.1-or-later License: LGPL-2.1-or-later
Summary: Smart card library and applications Summary: Smart card library and applications
URL: https://github.com/OpenSC/OpenSC/wiki URL: https://github.com/OpenSC/OpenSC/wiki
Source0: https://github.com/OpenSC/OpenSC/releases/download/%{version}/%{name}-%{version}.tar.gz Source0: https://github.com/OpenSC/OpenSC/releases/download/%{version}/%{name}-%{version}.tar.gz
Patch0: 0001-correct_left_length_calculation_to_fix_buffer.patch Patch0: 0001-correct_left_length_calculation_to_fix_buffer.patch
Patch1: 0002-Prevent_stack_buffer_overflow_when_empty_ACL_is_returned.patch
# PATCH-FIX-UPSTREAM: CVE-2023-40660: PIN bypass when card tracks its own login state
Patch2: 0003-opensc-CVE-2023-40660-1of2.patch
Patch3: 0004-opensc-CVE-2023-40660-2of2.patch
# PATCH-FIX-UPSTREAM: CVE-2023-4535: out-of-bounds read in MyEID driver handling encryption using symmetric keys
Patch4: 0005-opensc-NULL_pointer_fix.patch
Patch5: 0006-opensc-CVE-2023-4535.patch
# PATCH-FIX-UPSTREAM: CVE-2023-40661: multiple memory issues with pkcs15-init (enrollment tool)
Patch6: 0007-opensc-CVE-2023-40661-1of12.patch
Patch7: 0008-opensc-CVE-2023-40661-2of12.patch
Patch8: 0009-opensc-CVE-2023-40661-3of12.patch
Patch9: 0010-opensc-CVE-2023-40661-4of12.patch
Patch10: 0011-opensc-CVE-2023-40661-5of12.patch
Patch11: 0012-opensc-CVE-2023-40661-6of12.patch
Patch12: 0013-opensc-CVE-2023-40661-7of12.patch
Patch13: 0014-opensc-CVE-2023-40661-8of12.patch
Patch14: 0015-opensc-CVE-2023-40661-9of12.patch
Patch15: 0016-opensc-CVE-2023-40661-10of12.patch
Patch16: 0017-opensc-CVE-2023-40661-11of12.patch
Patch17: 0018-opensc-CVE-2023-40661-12of12.patch
#CVE-2023-5992 constant-time-pkcs1.5.patch
# https://github.com/OpenSC/OpenSC/pull/2948
# https://github.com/OpenSC/OpenSC/pull/3016
Patch18: 0019-opensc-CVE-2023-5992.patch
Patch19: 0020-backport-avoid-calling-functions-without-prototype.patch
Patch20: opensc-CVE-2024-45615.patch
Patch21: opensc-CVE-2024-45616.patch
Patch22: opensc-CVE-2024-45617.patch
Patch23: opensc-CVE-2024-45618.patch
Patch24: opensc-CVE-2024-45619.patch
Patch25: opensc-CVE-2024-45620.patch
Patch26: opensc-CVE-2024-8443.patch
BuildRequires: openssl-devel pcsc-lite-devel bash-completion docbook-style-xsl readline-devel BuildRequires: openssl-devel pcsc-lite-devel bash-completion docbook-style-xsl readline-devel
BuildRequires: desktop-file-utils /usr/bin/xsltproc autoconf automake libtool gcc BuildRequires: desktop-file-utils /usr/bin/xsltproc autoconf automake libtool gcc
@ -40,6 +72,9 @@ cp -p src/pkcs15init/README ./README.pkcs15init
cp -p src/scconf/README.scconf . cp -p src/scconf/README.scconf .
%build %build
%if "%toolchain" == "clang"
CFLAGS="$CFLAGS -Wno-error=unused-command-line-argument -Wno-error=unused-but-set-variable"
%endif
autoreconf -fvi autoreconf -fvi
sed -i -e 's/opensc.conf/opensc-%{_arch}.conf/g' src/libopensc/Makefile.in sed -i -e 's/opensc.conf/opensc-%{_arch}.conf/g' src/libopensc/Makefile.in
sed -i -e 's|"/lib /usr/lib\b|"/%{_lib} %{_libdir}|' configure # lib64 rpaths sed -i -e 's|"/lib /usr/lib\b|"/%{_lib} %{_libdir}|' configure # lib64 rpaths
@ -139,6 +174,22 @@ make check
%{_datadir}/opensc/ %{_datadir}/opensc/
%changelog %changelog
* Mon Oct 07 2024 Funda Wang <fundawang@yeah.net> - 0.23.0-7
- fix CVE-2024-8443, CVE-2024-45615, CVE-2024-45616,
CVE-2024-45617, CVE-2024-45618, CVE-2024-45619, CVE-2024-45620
* Sun Sep 1 2024 yuanchao <1050706328@qq.com> - 0.23.0-6
- backport:avoid calling functions without prototype,and add compiler flags to support clang build
* Fri Jun 28 2024 dillon chen <dillon.chen@gmail.com> - 0.23.0-5
- fix CVE-2023-5992
* Fri Oct 20 2023 dillon chen <dillon.chen@gmail.com> - 0.23.0-4
- fix CVE-2023-40660 CVE-2023-4535 CVE-2023-40661
* Wed Sep 6 2023 Zhengxin Guo <guozhengxin@kylinos.cn> - 0.23.0-3
- fix CVE-2021-34193
* Tue Sep 5 2023 Zhengxin Guo <guozhengxin@kylinos.cn> - 0.23.0-2 * Tue Sep 5 2023 Zhengxin Guo <guozhengxin@kylinos.cn> - 0.23.0-2
- fix CVE-2023-2977 - fix CVE-2023-2977