From 1dc943b5a93cca630297833b7579574cd06f0ee7 Mon Sep 17 00:00:00 2001 From: Funda Wang Date: Mon, 7 Oct 2024 16:33:42 +0800 Subject: [PATCH] fix CVE-2024-8443, CVE-2024-45615, CVE-2024-45616, CVE-2024-45617, CVE-2024-45618, CVE-2024-45619, CVE-2024-45620 --- 0003-opensc-CVE-2023-40660-1of2.patch | 50 +++ 0004-opensc-CVE-2023-40660-2of2.patch | 490 ++++++++++++++++++++++++ 0007-opensc-CVE-2023-40661-1of12.patch | 23 ++ 0008-opensc-CVE-2023-40661-2of12.patch | 25 ++ 0009-opensc-CVE-2023-40661-3of12.patch | 37 ++ 0010-opensc-CVE-2023-40661-4of12.patch | 396 +++++++++++++++++++ 0011-opensc-CVE-2023-40661-5of12.patch | 61 +++ 0012-opensc-CVE-2023-40661-6of12.patch | 25 ++ 0013-opensc-CVE-2023-40661-7of12.patch | 27 ++ 0014-opensc-CVE-2023-40661-8of12.patch | 29 ++ 0015-opensc-CVE-2023-40661-9of12.patch | 27 ++ 0016-opensc-CVE-2023-40661-10of12.patch | 25 ++ 0017-opensc-CVE-2023-40661-11of12.patch | 38 ++ 0018-opensc-CVE-2023-40661-12of12.patch | 26 ++ backport-opensc-CVE-2023-5992.patch | 485 +++++++++++++++++++++++ opensc-CVE-2024-45615.patch | 111 ++++++ opensc-CVE-2024-45616.patch | 287 ++++++++++++++ opensc-CVE-2024-45617.patch | 55 +++ opensc-CVE-2024-45618.patch | 67 ++++ opensc-CVE-2024-45619.patch | 221 +++++++++++ opensc-CVE-2024-45620.patch | 73 ++++ opensc-CVE-2024-8443.patch | 78 ++++ opensc.spec | 41 +- 23 files changed, 2695 insertions(+), 2 deletions(-) create mode 100644 0003-opensc-CVE-2023-40660-1of2.patch create mode 100644 0004-opensc-CVE-2023-40660-2of2.patch create mode 100644 0007-opensc-CVE-2023-40661-1of12.patch create mode 100644 0008-opensc-CVE-2023-40661-2of12.patch create mode 100644 0009-opensc-CVE-2023-40661-3of12.patch create mode 100644 0010-opensc-CVE-2023-40661-4of12.patch create mode 100644 0011-opensc-CVE-2023-40661-5of12.patch create mode 100644 0012-opensc-CVE-2023-40661-6of12.patch create mode 100644 0013-opensc-CVE-2023-40661-7of12.patch create mode 100644 0014-opensc-CVE-2023-40661-8of12.patch create mode 100644 0015-opensc-CVE-2023-40661-9of12.patch create mode 100644 0016-opensc-CVE-2023-40661-10of12.patch create mode 100644 0017-opensc-CVE-2023-40661-11of12.patch create mode 100644 0018-opensc-CVE-2023-40661-12of12.patch create mode 100644 backport-opensc-CVE-2023-5992.patch create mode 100644 opensc-CVE-2024-45615.patch create mode 100644 opensc-CVE-2024-45616.patch create mode 100644 opensc-CVE-2024-45617.patch create mode 100644 opensc-CVE-2024-45618.patch create mode 100644 opensc-CVE-2024-45619.patch create mode 100644 opensc-CVE-2024-45620.patch create mode 100644 opensc-CVE-2024-8443.patch diff --git a/0003-opensc-CVE-2023-40660-1of2.patch b/0003-opensc-CVE-2023-40660-1of2.patch new file mode 100644 index 0000000..b7a77d5 --- /dev/null +++ b/0003-opensc-CVE-2023-40660-1of2.patch @@ -0,0 +1,50 @@ +From 74ddc3636db18ae78de62922a74bfdefae015c76 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +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) diff --git a/0004-opensc-CVE-2023-40660-2of2.patch b/0004-opensc-CVE-2023-40660-2of2.patch new file mode 100644 index 0000000..c9a4ca7 --- /dev/null +++ b/0004-opensc-CVE-2023-40660-2of2.patch @@ -0,0 +1,490 @@ +From d7fadae950f6d33b32f979759c06ab78a3475c22 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Wed, 21 Jun 2023 13:49:40 +0200 +Subject: [PATCH 01/15] PIV: implemented logout + +--- + src/libopensc/card-asepcos.c | 15 +++++++++++++ + src/libopensc/card-authentic.c | 11 ++++++++++ + src/libopensc/card-cac.c | 10 ++++++--- + src/libopensc/card-cac1.c | 10 ++++++--- + src/libopensc/card-coolkey.c | 3 -- + src/libopensc/card-edo.c | 7 ++++++ + src/libopensc/card-epass2003.c | 18 ++++++++++++++++ + src/libopensc/card-esteid2018.c | 5 ++++ + src/libopensc/card-gemsafeV1.c | 8 +++++++ + src/libopensc/card-isoApplet.c | 8 +++++++ + src/libopensc/card-jpki.c | 6 +++++ + src/libopensc/card-mcrd.c | 10 +++++++++ + src/libopensc/card-muscle.c | 18 ++++++++++++---- + src/libopensc/card-piv.c | 20 ++++++++++-------- + src/libopensc/card-westcos.c | 44 ++++++++++++++++++++++++---------------- + 16 files changed, 155 insertions(+), 49 deletions(-) + +--- a/src/libopensc/card-asepcos.c ++++ b/src/libopensc/card-asepcos.c +@@ -1050,6 +1050,20 @@ static int asepcos_card_reader_lock_obta + LOG_FUNC_RETURN(card->ctx, r); + } + ++static int asepcos_logout(sc_card_t *card) ++{ ++ int r = SC_ERROR_NOT_SUPPORTED; ++ ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ ++ if (card->type == SC_CARD_TYPE_ASEPCOS_JAVA) { ++ /* in case of a Java card try to select the ASEPCOS applet */ ++ r = asepcos_select_asepcos_applet(card); ++ } ++ ++ LOG_FUNC_RETURN(card->ctx, r); ++} ++ + static struct sc_card_driver * sc_get_driver(void) + { + if (iso_ops == NULL) +@@ -1066,6 +1080,7 @@ static struct sc_card_driver * sc_get_dr + asepcos_ops.list_files = asepcos_list_files; + asepcos_ops.card_ctl = asepcos_card_ctl; + asepcos_ops.pin_cmd = asepcos_pin_cmd; ++ asepcos_ops.logout = asepcos_logout; + asepcos_ops.card_reader_lock_obtained = asepcos_card_reader_lock_obtained; + + return &asepcos_drv; +--- a/src/libopensc/card-authentic.c ++++ b/src/libopensc/card-authentic.c +@@ -2311,6 +2311,17 @@ authentic_sm_get_wrapped_apdu(struct sc_ + } + #endif + ++int authentic_logout(sc_card_t *card) ++{ ++ int r = SC_ERROR_NOT_SUPPORTED; ++ ++ if (card->type == SC_CARD_TYPE_OBERTHUR_AUTHENTIC_3_2) { ++ r = authentic_select_aid(card, aid_AuthentIC_3_2, sizeof(aid_AuthentIC_3_2), NULL, NULL); ++ } ++ ++ return r; ++} ++ + static struct sc_card_driver * + sc_get_driver(void) + { +--- a/src/libopensc/card-cac.c ++++ b/src/libopensc/card-cac.c +@@ -1831,9 +1831,6 @@ static int cac_match_card(sc_card_t *car + { + int r; + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); +- /* Since we send an APDU, the card's logout function may be called... +- * however it may be in dirty memory */ +- card->ops->logout = NULL; + + r = cac_find_and_initialize(card, 0); + return (r == SC_SUCCESS); /* never match */ +@@ -1862,6 +1859,12 @@ static int cac_init(sc_card_t *card) + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); + } + ++static int cac_logout(sc_card_t *card) ++{ ++ int index; ++ return cac_find_first_pki_applet(card, &index); ++} ++ + static int cac_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left) + { + /* CAC, like PIV needs Extra validation of (new) PIN during +@@ -1933,6 +1936,7 @@ static struct sc_card_driver * sc_get_dr + cac_ops.decipher = cac_decipher; + cac_ops.card_ctl = cac_card_ctl; + cac_ops.pin_cmd = cac_pin_cmd; ++ cac_ops.logout = cac_logout; + + return &cac_drv; + } +--- a/src/libopensc/card-cac1.c ++++ b/src/libopensc/card-cac1.c +@@ -498,9 +498,6 @@ static int cac_match_card(sc_card_t *car + { + int r; + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); +- /* Since we send an APDU, the card's logout function may be called... +- * however it may be in dirty memory */ +- card->ops->logout = NULL; + + r = cac_find_and_initialize(card, 0); + return (r == SC_SUCCESS); /* never match */ +@@ -529,6 +526,12 @@ static int cac_init(sc_card_t *card) + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); + } + ++static int cac_logout(sc_card_t *card) ++{ ++ int index; ++ return cac_find_first_pki_applet(card, &index); ++} ++ + static struct sc_card_operations cac_ops; + + static struct sc_card_driver cac1_drv = { +@@ -550,6 +553,7 @@ static struct sc_card_driver * sc_get_dr + + cac_ops.select_file = cac_select_file; /* need to record object type */ + cac_ops.read_binary = cac_read_binary; ++ cac_ops.logout = cac_logout; + + return &cac1_drv; + } +--- a/src/libopensc/card-coolkey.c ++++ b/src/libopensc/card-coolkey.c +@@ -2264,9 +2264,6 @@ static int coolkey_match_card(sc_card_t + int r; + + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); +- /* Since we send an APDU, the card's logout function may be called... +- * however it may be in dirty memory */ +- card->ops->logout = NULL; + + r = coolkey_select_applet(card); + if (r == SC_SUCCESS) { +--- a/src/libopensc/card-edo.c ++++ b/src/libopensc/card-edo.c +@@ -302,6 +302,12 @@ static int edo_init(sc_card_t* card) { + } + + ++static int edo_logout(sc_card_t* card) { ++ sc_sm_stop(card); ++ return edo_unlock(card); ++} ++ ++ + struct sc_card_driver* sc_get_edo_driver(void) { + edo_ops = *sc_get_iso7816_driver()->ops; + edo_ops.match_card = edo_match_card; +@@ -309,6 +315,7 @@ struct sc_card_driver* sc_get_edo_driver + edo_ops.select_file = edo_select_file; + edo_ops.set_security_env = edo_set_security_env; + edo_ops.compute_signature = edo_compute_signature; ++ edo_ops.logout = edo_logout; + + return &edo_drv; + } +--- a/src/libopensc/card-epass2003.c ++++ b/src/libopensc/card-epass2003.c +@@ -3278,6 +3278,23 @@ epass2003_pin_cmd(struct sc_card *card, + return r; + } + ++static int ++epass2003_logout(struct sc_card *card) ++{ ++ epass2003_exdata *exdata = NULL; ++ ++ if (!card->drv_data) ++ return SC_ERROR_INVALID_ARGUMENTS; ++ ++ exdata = (epass2003_exdata *)card->drv_data; ++ if (exdata->sm) { ++ sc_sm_stop(card); ++ return epass2003_refresh(card); ++ } ++ ++ return SC_ERROR_NOT_SUPPORTED; ++} ++ + static struct sc_card_driver *sc_get_driver(void) + { + struct sc_card_driver *iso_drv = sc_get_iso7816_driver(); +@@ -3307,6 +3324,7 @@ static struct sc_card_driver *sc_get_dri + epass2003_ops.pin_cmd = epass2003_pin_cmd; + epass2003_ops.check_sw = epass2003_check_sw; + epass2003_ops.get_challenge = epass2003_get_challenge; ++ epass2003_ops.logout = epass2003_logout; + return &epass2003_drv; + } + +--- a/src/libopensc/card-esteid2018.c ++++ b/src/libopensc/card-esteid2018.c +@@ -306,6 +306,10 @@ static int esteid_finish(sc_card_t *card + return 0; + } + ++static int esteid_logout(sc_card_t *card) { ++ return gp_select_aid(card, &IASECC_AID); ++} ++ + struct sc_card_driver *sc_get_esteid2018_driver(void) { + struct sc_card_driver *iso_drv = sc_get_iso7816_driver(); + +@@ -323,6 +327,7 @@ struct sc_card_driver *sc_get_esteid2018 + esteid_ops.set_security_env = esteid_set_security_env; + esteid_ops.compute_signature = esteid_compute_signature; + esteid_ops.pin_cmd = esteid_pin_cmd; ++ esteid_ops.logout = esteid_logout; + + return &esteid2018_driver; + } +--- a/src/libopensc/card-gemsafeV1.c ++++ b/src/libopensc/card-gemsafeV1.c +@@ -582,6 +582,13 @@ static int gemsafe_card_reader_lock_obta + LOG_FUNC_RETURN(card->ctx, r); + } + ++static int gemsafe_logout(sc_card_t *card) ++{ ++ gemsafe_exdata *exdata = (gemsafe_exdata *)card->drv_data; ++ ++ return gp_select_applet(card, exdata->aid, exdata->aid_len); ++} ++ + static struct sc_card_driver *sc_get_driver(void) + { + struct sc_card_driver *iso_drv = sc_get_iso7816_driver(); +@@ -602,6 +609,7 @@ static struct sc_card_driver *sc_get_dri + gemsafe_ops.process_fci = gemsafe_process_fci; + gemsafe_ops.pin_cmd = iso_ops->pin_cmd; + gemsafe_ops.card_reader_lock_obtained = gemsafe_card_reader_lock_obtained; ++ gemsafe_ops.logout = gemsafe_logout; + + return &gemsafe_drv; + } +--- a/src/libopensc/card-isoApplet.c ++++ b/src/libopensc/card-isoApplet.c +@@ -1244,6 +1244,13 @@ static int isoApplet_card_reader_lock_ob + LOG_FUNC_RETURN(card->ctx, r); + } + ++static int isoApplet_logout(sc_card_t *card) ++{ ++ size_t rlen = SC_MAX_APDU_BUFFER_SIZE; ++ u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; ++ return isoApplet_select_applet(card, isoApplet_aid, sizeof(isoApplet_aid), rbuf, &rlen); ++} ++ + static struct sc_card_driver *sc_get_driver(void) + { + sc_card_driver_t *iso_drv = sc_get_iso7816_driver(); +@@ -1267,6 +1274,7 @@ static struct sc_card_driver *sc_get_dri + isoApplet_ops.compute_signature = isoApplet_compute_signature; + isoApplet_ops.get_challenge = isoApplet_get_challenge; + isoApplet_ops.card_reader_lock_obtained = isoApplet_card_reader_lock_obtained; ++ isoApplet_ops.logout = isoApplet_logout; + + /* unsupported functions */ + isoApplet_ops.write_binary = NULL; +--- a/src/libopensc/card-jpki.c ++++ b/src/libopensc/card-jpki.c +@@ -361,6 +361,11 @@ static int jpki_card_reader_lock_obtaine + LOG_FUNC_RETURN(card->ctx, r); + } + ++static int jpki_logout(sc_card_t *card) ++{ ++ return jpki_select_ap(card); ++} ++ + static struct sc_card_driver * + sc_get_driver(void) + { +@@ -375,6 +380,7 @@ sc_get_driver(void) + jpki_ops.set_security_env = jpki_set_security_env; + jpki_ops.compute_signature = jpki_compute_signature; + jpki_ops.card_reader_lock_obtained = jpki_card_reader_lock_obtained; ++ jpki_ops.logout = jpki_logout; + + return &jpki_drv; + } +--- a/src/libopensc/card-mcrd.c ++++ b/src/libopensc/card-mcrd.c +@@ -1174,6 +1174,15 @@ static int mcrd_pin_cmd(sc_card_t * card + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, iso_ops->pin_cmd(card, data, tries_left)); + } + ++static int mcrd_logout(sc_card_t * card) ++{ ++ if (card->type == SC_CARD_TYPE_MCRD_ESTEID_V30) { ++ return gp_select_aid(card, &EstEID_v35_AID); ++ } else { ++ return SC_ERROR_NOT_SUPPORTED; ++ } ++} ++ + /* Driver binding */ + static struct sc_card_driver *sc_get_driver(void) + { +@@ -1190,6 +1199,7 @@ static struct sc_card_driver *sc_get_dri + mcrd_ops.compute_signature = mcrd_compute_signature; + mcrd_ops.decipher = mcrd_decipher; + mcrd_ops.pin_cmd = mcrd_pin_cmd; ++ mcrd_ops.logout = mcrd_logout; + + return &mcrd_drv; + } +--- a/src/libopensc/card-muscle.c ++++ b/src/libopensc/card-muscle.c +@@ -81,10 +81,6 @@ static int muscle_match_card(sc_card_t * + u8 response[64]; + int r; + +- /* Since we send an APDU, the card's logout function may be called... +- * however it's not always properly nulled out... */ +- card->ops->logout = NULL; +- + if (msc_select_applet(card, muscleAppletId, sizeof muscleAppletId) == 1) { + /* Muscle applet is present, check the protocol version to be sure */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x3C, 0x00, 0x00); +@@ -853,6 +849,19 @@ static int muscle_card_reader_lock_obtai + LOG_FUNC_RETURN(card->ctx, r); + } + ++static int muscle_logout(sc_card_t *card) ++{ ++ int r = SC_ERROR_NOT_SUPPORTED; ++ ++ SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); ++ ++ if (msc_select_applet(card, muscleAppletId, sizeof muscleAppletId) == 1) { ++ r = SC_SUCCESS; ++ } ++ ++ LOG_FUNC_RETURN(card->ctx, r); ++} ++ + + static struct sc_card_driver * sc_get_driver(void) + { +@@ -881,6 +890,7 @@ static struct sc_card_driver * sc_get_dr + muscle_ops.delete_file = muscle_delete_file; + muscle_ops.list_files = muscle_list_files; + muscle_ops.card_reader_lock_obtained = muscle_card_reader_lock_obtained; ++ muscle_ops.logout = muscle_logout; + + return &muscle_drv; + } +--- a/src/libopensc/card-piv.c ++++ b/src/libopensc/card-piv.c +@@ -2183,11 +2183,11 @@ static int piv_is_object_present(sc_card + * or the global pin for the card 0x00. Look at Discovery object to get this. + * called by pkcs15-piv.c via cardctl when setting up the pins. + */ +-static int piv_get_pin_preference(sc_card_t *card, int *ptr) ++static int piv_get_pin_preference(sc_card_t *card, int *pin_ref) + { + piv_private_data_t * priv = PIV_DATA(card); + +- *ptr = priv->pin_preference; ++ *pin_ref = priv->pin_preference; + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); + } + +@@ -3082,10 +3082,6 @@ static int piv_match_card_continued(sc_c + piv_private_data_t *priv = NULL; + int saved_type = card->type; + +- /* Since we send an APDU, the card's logout function may be called... +- * however it may be in dirty memory */ +- card->ops->logout = NULL; +- + /* piv_match_card may be called with card->type, set by opensc.conf */ + /* user provide card type must be one we know */ + switch (card->type) { +@@ -3747,12 +3743,18 @@ piv_pin_cmd(sc_card_t *card, struct sc_p + + static int piv_logout(sc_card_t *card) + { +- int r = SC_ERROR_NOT_SUPPORTED; /* TODO Some PIV cards may support a logout */ +- /* piv_private_data_t * priv = PIV_DATA(card); */ ++ int r = SC_ERROR_NOT_SUPPORTED; ++ piv_private_data_t * priv = PIV_DATA(card); + + LOG_FUNC_CALLED(card->ctx); + +- /* TODO 800-73-3 does not define a logout, 800-73-4 does */ ++ if (priv) { ++ /* logout defined since 800-73-4 */ ++ r = iso7816_logout(card, priv->pin_preference); ++ if (r == SC_SUCCESS) { ++ priv->logged_in = SC_PIN_STATE_LOGGED_OUT; ++ } ++ } + + LOG_FUNC_RETURN(card->ctx, r); + } +--- a/src/libopensc/card-westcos.c ++++ b/src/libopensc/card-westcos.c +@@ -166,6 +166,26 @@ static int westcos_finish(sc_card_t * ca + return 0; + } + ++static int select_westcos_applet(sc_card_t *card) ++{ ++ int r; ++ sc_apdu_t apdu; ++ u8 aid[] = { ++ 0xA0, 0x00, 0xCE, 0x00, 0x07, 0x01 ++ }; ++ sc_format_apdu(card, &apdu, ++ SC_APDU_CASE_3_SHORT, 0xA4, 0x04, ++ 0); ++ apdu.cla = 0x00; ++ apdu.lc = sizeof(aid); ++ apdu.datalen = sizeof(aid); ++ apdu.data = aid; ++ r = sc_transmit_apdu(card, &apdu); ++ if (r) ++ return r; ++ return sc_check_sw(card, apdu.sw1, apdu.sw2); ++} ++ + static int westcos_match_card(sc_card_t * card) + { + int i; +@@ -176,23 +196,7 @@ static int westcos_match_card(sc_card_t + + /* JAVACARD, look for westcos applet */ + if (i == 1) { +- int r; +- sc_apdu_t apdu; +- u8 aid[] = { +- 0xA0, 0x00, 0xCE, 0x00, 0x07, 0x01 +- }; +- sc_format_apdu(card, &apdu, +- SC_APDU_CASE_3_SHORT, 0xA4, 0x04, +- 0); +- apdu.cla = 0x00; +- apdu.lc = sizeof(aid); +- apdu.datalen = sizeof(aid); +- apdu.data = aid; +- r = sc_transmit_apdu(card, &apdu); +- if (r) +- return 0; +- r = sc_check_sw(card, apdu.sw1, apdu.sw2); +- if (r) ++ if (select_westcos_applet(card)) + return 0; + } + +@@ -1257,6 +1261,11 @@ static int westcos_decipher(sc_card_t *c + return westcos_sign_decipher(1, card, crgram, crgram_len, out, outlen); + } + ++static int westcos_logout(sc_card_t *card) ++{ ++ return select_westcos_applet(card); ++} ++ + struct sc_card_driver *sc_get_westcos_driver(void) + { + if (iso_ops == NULL) +@@ -1288,6 +1297,7 @@ struct sc_card_driver *sc_get_westcos_dr + westcos_ops.process_fci = westcos_process_fci; + westcos_ops.construct_fci = NULL; + westcos_ops.pin_cmd = westcos_pin_cmd; ++ westcos_ops.logout = westcos_logout; + + return &westcos_drv; + } diff --git a/0007-opensc-CVE-2023-40661-1of12.patch b/0007-opensc-CVE-2023-40661-1of12.patch new file mode 100644 index 0000000..57ea030 --- /dev/null +++ b/0007-opensc-CVE-2023-40661-1of12.patch @@ -0,0 +1,23 @@ +From 578aed8391ef117ca64a9e0cba8e5c264368a0ec Mon Sep 17 00:00:00 2001 +From: Frank Morgner +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--) { diff --git a/0008-opensc-CVE-2023-40661-2of12.patch b/0008-opensc-CVE-2023-40661-2of12.patch new file mode 100644 index 0000000..f28efba --- /dev/null +++ b/0008-opensc-CVE-2023-40661-2of12.patch @@ -0,0 +1,25 @@ +From df5a176bfdf8c52ba89c7fef1f82f6f3b9312bc1 Mon Sep 17 00:00:00 2001 +From: Veronika Hanulikova +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) diff --git a/0009-opensc-CVE-2023-40661-3of12.patch b/0009-opensc-CVE-2023-40661-3of12.patch new file mode 100644 index 0000000..e0e4e1f --- /dev/null +++ b/0009-opensc-CVE-2023-40661-3of12.patch @@ -0,0 +1,37 @@ +From 5631e9843c832a99769def85b7b9b68b4e3e3959 Mon Sep 17 00:00:00 2001 +From: Veronika Hanulikova +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)); + diff --git a/0010-opensc-CVE-2023-40661-4of12.patch b/0010-opensc-CVE-2023-40661-4of12.patch new file mode 100644 index 0000000..31ad565 --- /dev/null +++ b/0010-opensc-CVE-2023-40661-4of12.patch @@ -0,0 +1,396 @@ +From aadd82bb071e574fc57263a103e3bf06ebbd8de7 Mon Sep 17 00:00:00 2001 +From: "Ingo Struck (git commits)" +Date: Sat, 21 Jan 2023 22:15:10 +0100 +Subject: [PATCH] Handle reader limits for SC Card unwrap operations + +Fixes #2514 +--- + src/libopensc/card-sc-hsm.c | 181 ++++++++++++++----------- + src/libopensc/reader-pcsc.c | 91 ++++++++----- + src/tests/fuzzing/fuzz_pkcs15_decode.c | 3 +- + src/tests/fuzzing/fuzz_pkcs15_encode.c | 2 +- + 4 files changed, 159 insertions(+), 118 deletions(-) + +diff --git a/src/libopensc/card-sc-hsm.c b/src/libopensc/card-sc-hsm.c +index 60d5895127..1b707f08df 100644 +--- a/src/libopensc/card-sc-hsm.c ++++ b/src/libopensc/card-sc-hsm.c +@@ -145,9 +145,7 @@ static int sc_hsm_select_file_ex(sc_card_t *card, + + if (file_out == NULL) { // Versions before 0.16 of the SmartCard-HSM do not support P2='0C' + rv = sc_hsm_select_file_ex(card, in_path, forceselect, &file); +- if (file != NULL) { +- sc_file_free(file); +- } ++ sc_file_free(file); + return rv; + } + +@@ -181,9 +179,7 @@ static int sc_hsm_select_file_ex(sc_card_t *card, + LOG_TEST_RET(card->ctx, rv, "Could not select SmartCard-HSM application"); + + if (priv) { +- if (priv->dffcp != NULL) { +- sc_file_free(priv->dffcp); +- } ++ sc_file_free(priv->dffcp); + // Cache the FCP returned when selecting the applet + sc_file_dup(&priv->dffcp, *file_out); + } +@@ -730,12 +726,12 @@ static int sc_hsm_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, + u8 recvbuf[SC_MAX_APDU_BUFFER_SIZE]; + #ifdef ENABLE_SM + if (card->sm_ctx.sm_mode != SM_MODE_TRANSMIT) { +- sc_log(card->ctx, ++ sc_log(card->ctx, + "Session PIN generation only supported in SM"); + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); + } + #else +- sc_log(card->ctx, ++ sc_log(card->ctx, + "Session PIN generation only supported in SM"); + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); + #endif +@@ -746,7 +742,7 @@ static int sc_hsm_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, + apdu.le = 0; + if (sc_transmit_apdu(card, &apdu) != SC_SUCCESS + || sc_check_sw(card, apdu.sw1, apdu.sw2) != SC_SUCCESS) { +- sc_log(card->ctx, ++ sc_log(card->ctx, + "Generating session PIN failed"); + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); + } +@@ -756,12 +752,12 @@ static int sc_hsm_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, + apdu.resplen); + data->pin2.len = apdu.resplen; + } else { +- sc_log(card->ctx, ++ sc_log(card->ctx, + "Buffer too small for session PIN"); + } + } + } else { +- sc_log(card->ctx, ++ sc_log(card->ctx, + "Session PIN not supported for this PIN (0x%02X)", + data->pin_reference); + } +@@ -848,47 +844,61 @@ static int sc_hsm_write_ef(sc_card_t *card, + LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); + } + +- p = cmdbuff; +- *p++ = 0x54; +- *p++ = 0x02; +- *p++ = (idx >> 8) & 0xFF; +- *p++ = idx & 0xFF; +- *p++ = 0x53; +- if (count < 128) { +- *p++ = (u8) count; +- len = 6; +- } else if (count < 256) { +- *p++ = 0x81; +- *p++ = (u8) count; +- len = 7; +- } else { +- *p++ = 0x82; +- *p++ = (count >> 8) & 0xFF; +- *p++ = count & 0xFF; +- len = 8; +- } ++ size_t bytes_left = count; ++ // 8 bytes are required for T54(4) and T53(4) ++ size_t blk_size = card->max_send_size - 8; ++ size_t to_send = 0; ++ size_t offset = (size_t) idx; ++ do { ++ len = 0; ++ to_send = bytes_left >= blk_size ? blk_size : bytes_left; ++ p = cmdbuff; ++ // ASN1 0x54 offset ++ *p++ = 0x54; ++ *p++ = 0x02; ++ *p++ = (offset >> 8) & 0xFF; ++ *p++ = offset & 0xFF; ++ // ASN1 0x53 to_send ++ *p++ = 0x53; ++ if (to_send < 128) { ++ *p++ = (u8)to_send; ++ len = 6; ++ } else if (to_send < 256) { ++ *p++ = 0x81; ++ *p++ = (u8)to_send; ++ len = 7; ++ } else { ++ *p++ = 0x82; ++ *p++ = (to_send >> 8) & 0xFF; ++ *p++ = to_send & 0xFF; ++ len = 8; ++ } + +- if (buf != NULL) +- memcpy(p, buf, count); +- len += count; ++ if (buf != NULL) ++ memcpy(p, buf+offset, to_send); ++ len += to_send; + +- sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xD7, fid >> 8, fid & 0xFF); +- apdu.data = cmdbuff; +- apdu.datalen = len; +- apdu.lc = len; ++ sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xD7, fid >> 8, fid & 0xFF); ++ apdu.data = cmdbuff; ++ apdu.datalen = len; ++ apdu.lc = len; + +- r = sc_transmit_apdu(card, &apdu); +- free(cmdbuff); +- LOG_TEST_RET(ctx, r, "APDU transmit failed"); ++ r = sc_transmit_apdu(card, &apdu); ++ LOG_TEST_GOTO_ERR(ctx, r, "APDU transmit failed"); ++ r = sc_check_sw(card, apdu.sw1, apdu.sw2); ++ LOG_TEST_GOTO_ERR(ctx, r, "Check SW error"); + +- r = sc_check_sw(card, apdu.sw1, apdu.sw2); +- LOG_TEST_RET(ctx, r, "Check SW error"); ++ bytes_left -= to_send; ++ offset += to_send; ++ } while (0 < bytes_left); ++ ++err: ++ free(cmdbuff); + + LOG_FUNC_RETURN(ctx, count); + } + + +- + static int sc_hsm_update_binary(sc_card_t *card, + unsigned int idx, const u8 *buf, size_t count, + unsigned long flags) +@@ -1227,7 +1237,7 @@ static int sc_hsm_initialize(sc_card_t *card, sc_cardctl_sc_hsm_init_param_t *pa + return SC_ERROR_INVALID_ARGUMENTS; + } + *p++ = 0x81; // User PIN +- *p++ = (u8) params->user_pin_len; ++ *p++ = (u8)params->user_pin_len; + memcpy(p, params->user_pin, params->user_pin_len); + p += params->user_pin_len; + +@@ -1400,12 +1410,11 @@ static int sc_hsm_unwrap_key(sc_card_t *card, sc_cardctl_sc_hsm_wrapped_key_t *p + + LOG_FUNC_CALLED(card->ctx); + +- sc_format_apdu(card, &apdu, SC_APDU_CASE_3_EXT, 0x74, params->key_id, 0x93); +- apdu.cla = 0x80; +- apdu.lc = params->wrapped_key_length; +- apdu.data = params->wrapped_key; +- apdu.datalen = params->wrapped_key_length; ++ r = sc_hsm_write_ef(card, 0x2F10, 0, params->wrapped_key, params->wrapped_key_length); ++ LOG_TEST_RET(card->ctx, r, "Create EF failed"); + ++ sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x74, params->key_id, 0x93); ++ apdu.cla = 0x80; + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(ctx, r, "APDU transmit failed"); + +@@ -1765,17 +1774,10 @@ static int sc_hsm_init(struct sc_card *card) + int flags,ext_flags; + sc_file_t *file = NULL; + sc_path_t path; +- sc_hsm_private_data_t *priv = card->drv_data; ++ sc_hsm_private_data_t *priv = NULL; + + LOG_FUNC_CALLED(card->ctx); + +- if (!priv) { +- priv = calloc(1, sizeof(sc_hsm_private_data_t)); +- if (!priv) +- LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); +- card->drv_data = priv; +- } +- + flags = SC_ALGORITHM_RSA_RAW|SC_ALGORITHM_RSA_PAD_PSS|SC_ALGORITHM_ONBOARD_KEY_GEN; + + _sc_card_add_rsa_alg(card, 1024, flags, 0); +@@ -1807,6 +1809,46 @@ static int sc_hsm_init(struct sc_card *card) + + card->caps |= SC_CARD_CAP_RNG|SC_CARD_CAP_APDU_EXT|SC_CARD_CAP_ISO7816_PIN_INFO; + ++ // APDU Buffer limits ++ // JCOP 2.4.1r3 1462 ++ // JCOP 2.4.2r3 1454 ++ // JCOP 3 1232 ++ // MicroSD with JCOP 3 478 / 506 - handled in reader-pcsc.c ++ // Reiner SCT 1014 - handled in reader-pcsc.c ++ ++ // Use JCOP 3 card limits for sending ++ card->max_send_size = 1232; ++ // Assume that card supports sending with extended length APDU and without limit ++ card->max_recv_size = 0; ++ ++ if (card->type == SC_CARD_TYPE_SC_HSM_SOC ++ || card->type == SC_CARD_TYPE_SC_HSM_GOID) { ++ card->max_recv_size = 0x0630; // SoC Proxy forces this limit ++ } else { ++ // Adjust to the limits set by the reader ++ if (card->reader->max_send_size < card->max_send_size) { ++ if (18 >= card->reader->max_send_size) ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INCONSISTENT_CONFIGURATION); ++ ++ // 17 byte header and TLV because of odd ins in UPDATE BINARY ++ card->max_send_size = card->reader->max_send_size - 17; ++ } ++ ++ if (0 < card->reader->max_recv_size) { ++ if (3 >= card->reader->max_recv_size) ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INCONSISTENT_CONFIGURATION); ++ card->max_recv_size = card->reader->max_recv_size - 2; ++ } ++ } ++ ++ priv = card->drv_data; ++ if (!priv) { ++ priv = calloc(1, sizeof(sc_hsm_private_data_t)); ++ if (!priv) ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); ++ card->drv_data = priv; ++ } ++ + sc_path_set(&path, SC_PATH_TYPE_DF_NAME, sc_hsm_aid.value, sc_hsm_aid.len, 0, 0); + if (sc_hsm_select_file_ex(card, &path, 0, &file) == SC_SUCCESS + && file && file->prop_attr && file->prop_attr_len >= 2) { +@@ -1839,25 +1881,6 @@ static int sc_hsm_init(struct sc_card *card) + } + sc_file_free(file); + +- // APDU Buffer limits +- // JCOP 2.4.1r3 1462 +- // JCOP 2.4.2r3 1454 +- // JCOP 3 1232 +- // MicroSD with JCOP 3 478 / 506 +- // Reiner SCT 1014 +- +- card->max_send_size = 1232 - 17; // 1232 buffer size - 17 byte header and TLV because of odd ins in UPDATE BINARY +- +- if (!strncmp("Secure Flash Card", card->reader->name, 17)) { +- card->max_send_size = 478 - 17; +- card->max_recv_size = 506 - 2; +- } else if (card->type == SC_CARD_TYPE_SC_HSM_SOC +- || card->type == SC_CARD_TYPE_SC_HSM_GOID) { +- card->max_recv_size = 0x0630; // SoC Proxy forces this limit +- } else { +- card->max_recv_size = 0; // Card supports sending with extended length APDU and without limit +- } +- + priv->EF_C_DevAut = NULL; + priv->EF_C_DevAut_len = 0; + +@@ -1883,13 +1906,11 @@ static int sc_hsm_finish(sc_card_t * card) + #ifdef ENABLE_SM + sc_sm_stop(card); + #endif +- if (priv->serialno) { ++ if (priv) { + free(priv->serialno); +- } +- if (priv->dffcp) { + sc_file_free(priv->dffcp); ++ free(priv->EF_C_DevAut); + } +- free(priv->EF_C_DevAut); + free(priv); + + return SC_SUCCESS; +diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c +index 40bfd293d3..04d5ac8fdd 100644 +--- a/src/libopensc/reader-pcsc.c ++++ b/src/libopensc/reader-pcsc.c +@@ -311,7 +311,7 @@ static int pcsc_transmit(sc_reader_t *reader, sc_apdu_t *apdu) + * The buffer for the returned data needs to be at least 2 bytes + * larger than the expected data length to store SW1 and SW2. */ + rsize = rbuflen = apdu->resplen <= 256 ? 258 : apdu->resplen + 2; +- rbuf = malloc(rbuflen); ++ rbuf = malloc(rbuflen); + if (rbuf == NULL) { + r = SC_ERROR_OUT_OF_MEMORY; + goto out; +@@ -424,7 +424,7 @@ static int refresh_attributes(sc_reader_t *reader) + if (priv->reader_state.cbAtr > SC_MAX_ATR_SIZE) + return SC_ERROR_INTERNAL; + +- /* Some cards have a different cold (after a powerup) and warm (after a reset) ATR */ ++ /* Some cards have a different cold (after a powerup) and warm (after a reset) ATR */ + if (memcmp(priv->reader_state.rgbAtr, reader->atr.value, priv->reader_state.cbAtr) != 0) { + reader->atr.len = priv->reader_state.cbAtr; + memcpy(reader->atr.value, priv->reader_state.rgbAtr, reader->atr.len); +@@ -556,7 +556,7 @@ static int pcsc_reconnect(sc_reader_t * reader, DWORD action) + priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED, + protocol, action, &active_proto); + +- ++ + PCSC_TRACE(reader, "SCardReconnect returned", rv); + if (rv != SCARD_S_SUCCESS) { + PCSC_TRACE(reader, "SCardReconnect failed", rv); +@@ -593,7 +593,7 @@ static void initialize_uid(sc_reader_t *reader) + sc_log_hex(reader->ctx, "UID", + reader->uid.value, reader->uid.len); + } else { +- sc_log(reader->ctx, "unable to get UID"); ++ sc_log(reader->ctx, "unable to get UID"); + } + } + } +@@ -1240,11 +1240,11 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) + sc_log(ctx, "Reader has a display: %04X", caps->wLcdLayout); + reader->capabilities |= SC_READER_CAP_DISPLAY; + } +- else { ++ else { + sc_log(ctx, "Reader does not have a display."); + } + } +- else { ++ else { + sc_log(ctx, + "Returned PIN properties structure has bad length (%lu/%"SC_FORMAT_LEN_SIZE_T"u)", + (unsigned long)rcount, +@@ -1304,7 +1325,7 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) + } + + rcount = sizeof i; +- if(gpriv->SCardGetAttrib(card_handle, SCARD_ATTR_VENDOR_IFD_VERSION, ++ if (gpriv->SCardGetAttrib(card_handle, SCARD_ATTR_VENDOR_IFD_VERSION, + (u8 *) &i, &rcount) == SCARD_S_SUCCESS + && rcount == sizeof i) { + reader->version_major = (i >> 24) & 0xFF; +@@ -1314,7 +1335,7 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) + } + + int pcsc_add_reader(sc_context_t *ctx, +- char *reader_name, size_t reader_name_len, ++ char *reader_name, size_t reader_name_len, + sc_reader_t **out_reader) + { + int ret = SC_ERROR_INTERNAL; +@@ -1574,7 +1595,7 @@ static int pcsc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_re + + LOG_FUNC_CALLED(ctx); + +- if (!event_reader && !event && reader_states) { ++ if (!event_reader && !event && reader_states) { + sc_log(ctx, "free allocated reader states"); + free(*reader_states); + *reader_states = NULL; +@@ -1958,7 +1979,7 @@ static int part10_build_modify_pin_block(struct sc_reader *reader, u8 * buf, siz + sc_apdu_t *apdu = data->apdu; + u8 tmp; + unsigned int tmp16; +- PIN_MODIFY_STRUCTURE *pin_modify = (PIN_MODIFY_STRUCTURE *)buf; ++ PIN_MODIFY_STRUCTURE *pin_modify = (PIN_MODIFY_STRUCTURE *)buf; + struct sc_pin_cmd_pin *pin_ref = + data->flags & SC_PIN_CMD_IMPLICIT_CHANGE ? + &data->pin2 : &data->pin1; diff --git a/0011-opensc-CVE-2023-40661-5of12.patch b/0011-opensc-CVE-2023-40661-5of12.patch new file mode 100644 index 0000000..6fe9d34 --- /dev/null +++ b/0011-opensc-CVE-2023-40661-5of12.patch @@ -0,0 +1,61 @@ +From dd138d0600a1acd7991989127f36827e5836b24e Mon Sep 17 00:00:00 2001 +From: "Ingo Struck (git commits)" +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: diff --git a/0012-opensc-CVE-2023-40661-6of12.patch b/0012-opensc-CVE-2023-40661-6of12.patch new file mode 100644 index 0000000..1323602 --- /dev/null +++ b/0012-opensc-CVE-2023-40661-6of12.patch @@ -0,0 +1,25 @@ +From c449a181a6988cc1e8dc8764d23574e48cdc3fa6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= +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) diff --git a/0013-opensc-CVE-2023-40661-7of12.patch b/0013-opensc-CVE-2023-40661-7of12.patch new file mode 100644 index 0000000..35c4326 --- /dev/null +++ b/0013-opensc-CVE-2023-40661-7of12.patch @@ -0,0 +1,27 @@ +From 88880db0307a07e33cf2e1592bb029e9c170dfea Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= +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); diff --git a/0014-opensc-CVE-2023-40661-8of12.patch b/0014-opensc-CVE-2023-40661-8of12.patch new file mode 100644 index 0000000..6b40c74 --- /dev/null +++ b/0014-opensc-CVE-2023-40661-8of12.patch @@ -0,0 +1,29 @@ +From 638a5007a5d240d6fa901aa822cfeef94fe36e85 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= +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); diff --git a/0015-opensc-CVE-2023-40661-9of12.patch b/0015-opensc-CVE-2023-40661-9of12.patch new file mode 100644 index 0000000..cedde52 --- /dev/null +++ b/0015-opensc-CVE-2023-40661-9of12.patch @@ -0,0 +1,27 @@ +From ce7fcdaa35196706a83fe982900228e15464f928 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +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; + } diff --git a/0016-opensc-CVE-2023-40661-10of12.patch b/0016-opensc-CVE-2023-40661-10of12.patch new file mode 100644 index 0000000..6300e70 --- /dev/null +++ b/0016-opensc-CVE-2023-40661-10of12.patch @@ -0,0 +1,25 @@ +From 440ca666eff10cc7011901252d20f3fc4ea23651 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +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]; + diff --git a/0017-opensc-CVE-2023-40661-11of12.patch b/0017-opensc-CVE-2023-40661-11of12.patch new file mode 100644 index 0000000..e4649a8 --- /dev/null +++ b/0017-opensc-CVE-2023-40661-11of12.patch @@ -0,0 +1,38 @@ +From 245efe608d083fd4e4ec96793fdefd218e26fde7 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +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; diff --git a/0018-opensc-CVE-2023-40661-12of12.patch b/0018-opensc-CVE-2023-40661-12of12.patch new file mode 100644 index 0000000..724d6fc --- /dev/null +++ b/0018-opensc-CVE-2023-40661-12of12.patch @@ -0,0 +1,26 @@ +From 41d61da8481582e12710b5858f8b635e0a71ab5e Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +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. */ diff --git a/backport-opensc-CVE-2023-5992.patch b/backport-opensc-CVE-2023-5992.patch new file mode 100644 index 0000000..42fd9f1 --- /dev/null +++ b/backport-opensc-CVE-2023-5992.patch @@ -0,0 +1,485 @@ +diff --git a/src/common/Makefile.am b/src/common/Makefile.am +index 5153428dc..9ecbffe8f 100644 +--- a/src/common/Makefile.am ++++ b/src/common/Makefile.am +@@ -8,7 +8,8 @@ dist_noinst_DATA = \ + LICENSE.compat_getopt compat_getopt.txt \ + compat_getopt_main.c \ + README.compat_strlcpy compat_strlcpy.3 +-noinst_HEADERS = compat_strlcat.h compat_strlcpy.h compat_strnlen.h compat_getpass.h compat_getopt.h simclist.h libpkcs11.h libscdl.h ++noinst_HEADERS = compat_strlcat.h compat_strlcpy.h compat_strnlen.h compat_getpass.h \ ++ compat_getopt.h simclist.h libpkcs11.h libscdl.h constant-time.h + + AM_CPPFLAGS = -I$(top_srcdir)/src + +@@ -43,7 +44,8 @@ TIDY_FILES = \ + compat_report_rangecheckfailure.c \ + compat___iob_func.c \ + simclist.c simclist.h \ +- libpkcs11.c libscdl.c ++ libpkcs11.c libscdl.c \ ++ constant-time.h + + check-local: + if [ -x "$(CLANGTIDY)" ]; then clang-tidy -config='' -header-filter=.* $(TIDY_FILES) -- $(TIDY_FLAGS); fi +diff --git a/src/common/constant-time.h b/src/common/constant-time.h +new file mode 100644 +index 0000000000..40c3e500c2 +--- /dev/null ++++ b/src/common/constant-time.h +@@ -0,0 +1,134 @@ ++/* Original source: https://github.com/openssl/openssl/blob/9890cc42daff5e2d0cad01ac4bf78c391f599a6e/include/internal/constant_time.h */ ++ ++#ifndef CONSTANT_TIME_H ++#define CONSTANT_TIME_H ++ ++#include ++#include ++ ++#if !defined(inline) ++#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L ++#define constant_inline inline ++#elif defined(__GNUC__) && __GNUC__ >= 2 ++#elif defined(__GNUC__) && __GNUC__ >= 2 ++#elif defined(_MSC_VER) ++#define constant_inline __inline ++#else ++#define constant_inline ++#endif ++#else /* use what caller wants as inline may be from config.h */ ++#define constant_inline inline /* inline */ ++#endif ++ ++/*- ++ * The boolean methods return a bitmask of all ones (0xff...f) for true ++ * and 0 for false. For example, ++ * if (a < b) { ++ * c = a; ++ * } else { ++ * c = b; ++ * } ++ * can be written as ++ * unsigned int lt = constant_time_lt(a, b); ++ * c = constant_time_select(lt, a, b); ++ */ ++ ++static constant_inline unsigned int ++value_barrier(unsigned int a) ++{ ++ volatile unsigned int r = a; ++ return r; ++} ++ ++static constant_inline size_t ++value_barrier_s(size_t a) ++{ ++ volatile size_t r = a; ++ return r; ++} ++ ++/* MSB */ ++static constant_inline size_t ++constant_time_msb_s(size_t a) ++{ ++ return 0 - (a >> (sizeof(a) * 8 - 1)); ++} ++ ++static constant_inline unsigned int ++constant_time_msb(unsigned int a) ++{ ++ return 0 - (a >> (sizeof(a) * 8 - 1)); ++} ++ ++/* Select */ ++static constant_inline unsigned int ++constant_time_select(unsigned int mask, unsigned int a, unsigned int b) ++{ ++ return (value_barrier(mask) & a) | (value_barrier(~mask) & b); ++} ++ ++static constant_inline unsigned char ++constant_time_select_8(unsigned char mask, unsigned char a, unsigned char b) ++{ ++ return (unsigned char)constant_time_select(mask, a, b); ++} ++ ++static constant_inline size_t ++constant_time_select_s(size_t mask, size_t a, size_t b) ++{ ++ return (value_barrier_s(mask) & a) | (value_barrier_s(~mask) & b); ++} ++ ++/* Zero */ ++static constant_inline unsigned int ++constant_time_is_zero(unsigned int a) ++{ ++ return constant_time_msb(~a & (a - 1)); ++} ++ ++static constant_inline size_t ++constant_time_is_zero_s(size_t a) ++{ ++ return constant_time_msb_s(~a & (a - 1)); ++} ++ ++/* Comparison*/ ++static constant_inline size_t ++constant_time_lt_s(size_t a, size_t b) ++{ ++ return constant_time_msb_s(a ^ ((a ^ b) | ((a - b) ^ b))); ++} ++ ++static constant_inline unsigned int ++constant_time_lt(unsigned int a, unsigned int b) ++{ ++ return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b))); ++} ++ ++static constant_inline unsigned int ++constant_time_ge(unsigned int a, unsigned int b) ++{ ++ return ~constant_time_lt(a, b); ++} ++ ++/* Equality*/ ++ ++static constant_inline unsigned int ++constant_time_eq(unsigned int a, unsigned int b) ++{ ++ return constant_time_is_zero(a ^ b); ++} ++ ++static constant_inline size_t ++constant_time_eq_s(size_t a, size_t b) ++{ ++ return constant_time_is_zero_s(a ^ b); ++} ++ ++static constant_inline unsigned int ++constant_time_eq_i(int a, int b) ++{ ++ return constant_time_eq((unsigned int)a, (unsigned int)b); ++} ++ ++#endif /* CONSTANT_TIME_H */ +diff --git a/src/libopensc/internal.h b/src/libopensc/internal.h +index 74014235a..13eccfa1a 100644 +--- a/src/libopensc/internal.h ++++ b/src/libopensc/internal.h +@@ -168,6 +168,8 @@ int sc_pkcs1_strip_01_padding(struct sc_context *ctx, const u8 *in_dat, size_t i + u8 *out_dat, size_t *out_len); + int sc_pkcs1_strip_02_padding(struct sc_context *ctx, const u8 *data, size_t len, + u8 *out_dat, size_t *out_len); ++int sc_pkcs1_strip_02_padding_constant_time(sc_context_t *ctx, unsigned int n, const u8 *data, ++ unsigned int data_len, u8 *out, unsigned int *out_len); + int sc_pkcs1_strip_digest_info_prefix(unsigned int *algorithm, + const u8 *in_dat, size_t in_len, u8 *out_dat, size_t *out_len); + +diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c +index ca47733a4e..ddb3061134 100644 +--- a/src/libopensc/padding.c ++++ b/src/libopensc/padding.c +@@ -32,10 +32,13 @@ + #include + #include + ++#include "common/constant-time.h" + #include "internal.h" + + /* TODO doxygen comments */ + ++#define SC_PKCS1_PADDING_MIN_SIZE 11 ++ + /* + * Prefixes for pkcs-v1 signatures + */ +@@ -144,44 +147,82 @@ sc_pkcs1_strip_01_padding(struct sc_cont + } + + +-/* remove pkcs1 BT02 padding (adding BT02 padding is currently not +- * needed/implemented) */ ++/* Remove pkcs1 BT02 padding (adding BT02 padding is currently not ++ * needed/implemented) in constant-time. ++ * Original source: https://github.com/openssl/openssl/blob/9890cc42daff5e2d0cad01ac4bf78c391f599a6e/crypto/rsa/rsa_pk1.c#L171 */ + int +-sc_pkcs1_strip_02_padding(sc_context_t *ctx, const u8 *data, size_t len, u8 *out, size_t *out_len) ++sc_pkcs1_strip_02_padding_constant_time(sc_context_t *ctx, unsigned int n, const u8 *data, unsigned int data_len, u8 *out, unsigned int *out_len) + { +- unsigned int n = 0; +- ++ unsigned int i = 0; ++ u8 *msg, *msg_orig = NULL; ++ unsigned int good, found_zero_byte, mask; ++ unsigned int zero_index = 0, msg_index, mlen = -1, len = 0; + LOG_FUNC_CALLED(ctx); +- if (data == NULL || len < 3) ++ ++ if (data == NULL || data_len <= 0 || data_len > n || n < SC_PKCS1_PADDING_MIN_SIZE) + LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); + +- /* skip leading zero byte */ +- if (*data == 0) { +- data++; +- len--; ++ msg = msg_orig = calloc(n, sizeof(u8)); ++ if (msg == NULL) ++ LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); ++ ++ /* ++ * We can not check length of input data straight away and still we need to read ++ * from input even when the input is not as long as needed to keep the time constant. ++ * If data has wrong size, it is padded by zeroes from left and the following checks ++ * do not pass. ++ */ ++ len = data_len; ++ for (data += len, msg += n, i = 0; i < n; i++) { ++ mask = ~constant_time_is_zero(len); ++ len -= 1 & mask; ++ data -= 1 & mask; ++ *--msg = *data & mask; ++ } ++ // check first byte to be 0x00 ++ good = constant_time_is_zero(msg[0]); ++ // check second byte to be 0x02 ++ good &= constant_time_eq(msg[1], 2); ++ ++ // find zero byte after random data in padding ++ found_zero_byte = 0; ++ for (i = 2; i < n; i++) { ++ unsigned int equals0 = constant_time_is_zero(msg[i]); ++ zero_index = constant_time_select(~found_zero_byte & equals0, i, zero_index); ++ found_zero_byte |= equals0; + } +- if (data[0] != 0x02) +- LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING); +- /* skip over padding bytes */ +- for (n = 1; n < len && data[n]; n++) +- ; +- /* Must be at least 8 pad bytes */ +- if (n >= len || n < 9) +- LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING); +- n++; +- if (out == NULL) +- /* just check the padding */ +- LOG_FUNC_RETURN(ctx, SC_SUCCESS); + +- /* Now move decrypted contents to head of buffer */ +- if (*out_len < len - n) +- LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); +- *out_len = len - n; +- memmove(out, data + n, *out_len); ++ // zero_index stands for index of last found zero ++ good &= constant_time_ge(zero_index, 2 + 8); ++ ++ // start of the actual message in data ++ msg_index = zero_index + 1; ++ ++ // length of message ++ mlen = data_len - msg_index; ++ ++ // check that message fits into out buffer ++ good &= constant_time_ge(*out_len, mlen); ++ ++ // move the result in-place by |num|-SC_PKCS1_PADDING_MIN_SIZE-|mlen| bytes to the left. ++ *out_len = constant_time_select(constant_time_lt(n - SC_PKCS1_PADDING_MIN_SIZE, *out_len), ++ n - SC_PKCS1_PADDING_MIN_SIZE, *out_len); ++ for (msg_index = 1; msg_index < n - SC_PKCS1_PADDING_MIN_SIZE; msg_index <<= 1) { ++ mask = ~constant_time_eq(msg_index & (n - SC_PKCS1_PADDING_MIN_SIZE - mlen), 0); ++ for (i = SC_PKCS1_PADDING_MIN_SIZE; i < n - msg_index; i++) ++ msg[i] = constant_time_select_8(mask, msg[i + msg_index], msg[i]); ++ } ++ // move message into out buffer, if good ++ for (i = 0; i < *out_len; i++) { ++ unsigned int msg_index; ++ // when out is longer than message in data, use some bogus index in msg ++ mask = good & constant_time_lt(i, mlen); ++ msg_index = constant_time_select(mask, i + SC_PKCS1_PADDING_MIN_SIZE, 0); // to now overflow msg buffer ++ out[i] = constant_time_select_8(mask, msg[msg_index], out[i]); ++ } + +- sc_log(ctx, "stripped output(%"SC_FORMAT_LEN_SIZE_T"u): %s", len - n, +- sc_dump_hex(out, len - n)); +- LOG_FUNC_RETURN(ctx, len - n); ++ free(msg_orig); ++ return constant_time_select(good, mlen, SC_ERROR_WRONG_PADDING); + } + + /* add/remove DigestInfo prefix */ + +diff --git a/src/libopensc/pkcs15-sec.c b/src/libopensc/pkcs15-sec.c +index a019af460f..f7ee819d65 100644 +--- a/src/libopensc/pkcs15-sec.c ++++ b/src/libopensc/pkcs15-sec.c +@@ -286,12 +286,14 @@ int sc_pkcs15_decipher(struct sc_pkcs15_ + + /* Strip any padding */ + if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) { +- size_t s = r; +- r = sc_pkcs1_strip_02_padding(ctx, out, s, out, &s); +- LOG_TEST_RET(ctx, r, "Invalid PKCS#1 padding"); ++ unsigned int s = r; ++ unsigned int key_size = (unsigned int)alg_info->key_length; ++ r = sc_pkcs1_strip_02_padding_constant_time(ctx, key_size / 8, out, s, out, &s); ++ /* for keeping PKCS#1 v1.5 depadding constant-time, do not log error here */ + } + +- LOG_FUNC_RETURN(ctx, r); ++ /* do not log error code to prevent side channel attack */ ++ return r; + } + + /* derive one key from another. RSA can use decipher, so this is for only ECDH + +diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c +index f75a3dbaec..632681df63 100644 +--- a/src/pkcs11/framework-pkcs15.c ++++ b/src/pkcs11/framework-pkcs15.c +@@ -18,6 +18,7 @@ + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + ++#include "common/constant-time.h" + #include "config.h" + #include + #include +@@ -4174,7 +4175,8 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_se + struct pkcs15_fw_data *fw_data = NULL; + struct pkcs15_prkey_object *prkey; + unsigned char decrypted[512]; /* FIXME: Will not work for keys above 4096 bits */ +- int buff_too_small, rv, flags = 0, prkey_has_path = 0; ++ int rv, flags = 0, prkey_has_path = 0; ++ CK_ULONG mask, good, rv_pkcs11; + + sc_log(context, "Initiating decryption."); + +@@ -4246,27 +4248,54 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_se + rv = sc_pkcs15_decipher(fw_data->p15_card, prkey->prv_p15obj, flags, + pEncryptedData, ulEncryptedDataLen, decrypted, sizeof(decrypted)); + +- if (rv < 0 && !sc_pkcs11_conf.lock_login && !prkey_has_path) ++ /* skip for PKCS#1 v1.5 padding prevent side channel attack */ ++ if (!(flags & SC_ALGORITHM_RSA_PAD_PKCS1) && ++ rv < 0 && !sc_pkcs11_conf.lock_login && !prkey_has_path) + if (reselect_app_df(fw_data->p15_card) == SC_SUCCESS) + rv = sc_pkcs15_decipher(fw_data->p15_card, prkey->prv_p15obj, flags, + pEncryptedData, ulEncryptedDataLen, decrypted, sizeof(decrypted)); + + sc_unlock(p11card->card); + +- sc_log(context, "Decryption complete. Result %d.", rv); ++ sc_log(context, "Decryption complete."); + +- if (rv < 0) ++ /* Handle following code in constant-time + return sc_to_cryptoki_error(rv, "C_Decrypt"); ++ * to prevent Marvin attack for PKCS#1 v1.5 padding. */ + +- buff_too_small = (*pulDataLen < (CK_ULONG)rv); +- *pulDataLen = rv; +- if (pData == NULL_PTR) +- return CKR_OK; +- if (buff_too_small) +- return CKR_BUFFER_TOO_SMALL; +- memcpy(pData, decrypted, *pulDataLen); +- +- return CKR_OK; ++ /* only padding error must be handled in constant-time way, ++ * other error can be returned straight away */ ++ if ((~constant_time_eq_i(rv, SC_ERROR_WRONG_PADDING) & constant_time_lt_s(sizeof(decrypted), (size_t)rv))) ++ return sc_to_cryptoki_error(rv, "C_Decrypt"); ++ ++ /* check rv for padding error */ ++ good = ~constant_time_eq_i(rv, SC_ERROR_WRONG_PADDING); ++ rv_pkcs11 = sc_to_cryptoki_error(SC_ERROR_WRONG_PADDING, "C_Decrypt"); ++ rv_pkcs11 = constant_time_select_s(good, CKR_OK, rv_pkcs11); ++ ++ if (pData == NULL_PTR) { ++ /* set length only if no error */ ++ *pulDataLen = constant_time_select_s(good, rv, *pulDataLen); ++ /* return error only if original rv < 0 */ ++ return rv_pkcs11; ++ } ++ ++ /* check whether *pulDataLen < rv and set return value for small output buffer */ ++ mask = good & constant_time_lt_s(*pulDataLen, rv); ++ rv_pkcs11 = constant_time_select_s(mask, CKR_BUFFER_TOO_SMALL, rv_pkcs11); ++ good &= ~mask; ++ ++ /* move everything from decrypted into out buffer constant-time, if rv is ok */ ++ for (CK_ULONG i = 0; i < *pulDataLen; i++) { /* iterate over whole pData to not disclose real depadded length */ ++ CK_ULONG msg_index; ++ mask = good & constant_time_lt_s(i, sizeof(decrypted)); /* i should be in the bounds of decrypted */ ++ mask &= constant_time_lt_s(i, constant_time_select_s(good, rv, 0)); /* check that is in bounds of depadded message */ ++ msg_index = constant_time_select_s(mask, i, 0); ++ pData[i] = constant_time_select_8(mask, decrypted[msg_index], pData[i]); ++ } ++ *pulDataLen = constant_time_select_s(good, rv, *pulDataLen); ++ /* do not log error code to prevent side channel attack */ ++ return rv_pkcs11; + } + + +diff --git a/src/pkcs11/mechanism.c b/src/pkcs11/mechanism.c +index 03495265a4..d3f0434231 100644 +--- a/src/pkcs11/mechanism.c ++++ b/src/pkcs11/mechanism.c +@@ -23,6 +23,7 @@ + #include + #include + ++#include "common/constant-time.h" + #include "sc-pkcs11.h" + + /* Also used for verification data */ +@@ -1089,7 +1090,9 @@ sc_pkcs11_decr(struct sc_pkcs11_session + rv = op->type->decrypt(op, pEncryptedData, ulEncryptedDataLen, + pData, pulDataLen); + +- if (rv != CKR_BUFFER_TOO_SMALL && pData != NULL) ++ /* terminate session for any return value except CKR_BUFFER_TOO_SMALL, ++ * perform check in time side-channel free way to prevent Marvin attack */ ++ if (!constant_time_eq_s(rv, CKR_BUFFER_TOO_SMALL) && pData != NULL) + session_stop_operation(session, SC_PKCS11_OPERATION_DECRYPT); + + return rv; + + + +diff --git a/src/pkcs11/pkcs11-object.c b/src/pkcs11/pkcs11-object.c +index f04c0b4c56..b023911213 100644 +--- a/src/pkcs11/pkcs11-object.c ++++ b/src/pkcs11/pkcs11-object.c +@@ -926,7 +926,8 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSessi + rv = reset_login_state(session->slot, rv); + } + +- sc_log(context, "C_Decrypt() = %s", lookup_enum ( RV_T, rv )); ++ /* do not log error code to prevent side channel attack */ ++ sc_log(context, "C_Decrypt() finished"); + sc_pkcs11_unlock(); + return rv; + } + +diff --git a/src/pkcs11/misc.c b/src/pkcs11/misc.c +index 5ca1176b1d..1d893d6181 100644 +--- a/src/pkcs11/misc.c ++++ b/src/pkcs11/misc.c +@@ -23,6 +23,7 @@ + #include + #include + ++#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); + } + diff --git a/opensc-CVE-2024-45615.patch b/opensc-CVE-2024-45615.patch new file mode 100644 index 0000000..d9ad5ed --- /dev/null +++ b/opensc-CVE-2024-45615.patch @@ -0,0 +1,111 @@ +commit 5e4f26b510b04624386c54816bf26aacea0fe4a1 +Author: Veronika Hanulíková +Date: Thu Jul 11 14:58:25 2024 +0200 + + cac: Fix uninitialized values + + Thanks Matteo Marini for report + https://github.com/OpenSC/OpenSC/security/advisories/GHSA-p3mx-7472-h3j8 + + fuzz_card/1,fuzz_pkcs11/6 + +Index: opensc-0.21.0/src/libopensc/card-cac.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/card-cac.c ++++ opensc-0.21.0/src/libopensc/card-cac.c +@@ -255,7 +255,7 @@ static int cac_apdu_io(sc_card_t *card, + size_t * recvbuflen) + { + int r; +- sc_apdu_t apdu; ++ sc_apdu_t apdu = {0}; + u8 rbufinitbuf[CAC_MAX_SIZE]; + u8 *rbuf; + size_t rbuflen; +@@ -392,13 +392,13 @@ fail: + static int cac_read_file(sc_card_t *card, int file_type, u8 **out_buf, size_t *out_len) + { + u8 params[2]; +- u8 count[2]; ++ u8 count[2] = {0}; + u8 *out = NULL; +- u8 *out_ptr; ++ u8 *out_ptr = NULL; + size_t offset = 0; + size_t size = 0; + size_t left = 0; +- size_t len; ++ size_t len = 0; + int r; + + params[0] = file_type; +@@ -461,7 +461,7 @@ static int cac_read_binary(sc_card_t *ca + const u8 *tl_ptr, *val_ptr, *tl_start; + u8 *tlv_ptr; + const u8 *cert_ptr; +- size_t tl_len, val_len, tlv_len; ++ size_t tl_len = 0, val_len = 0, tlv_len; + size_t len, tl_head_len, cert_len; + u8 cert_type, tag; + +@@ -1528,7 +1528,7 @@ static int cac_parse_CCC(sc_card_t *card + static int cac_process_CCC(sc_card_t *card, cac_private_data_t *priv, int depth) + { + u8 *tl = NULL, *val = NULL; +- size_t tl_len, val_len; ++ size_t tl_len = 0, val_len = 0; + int r; + + if (depth > CAC_MAX_CCC_DEPTH) { +Index: opensc-0.21.0/src/libopensc/card-piv.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/card-piv.c ++++ opensc-0.21.0/src/libopensc/card-piv.c +@@ -2202,7 +2202,7 @@ static int piv_get_challenge(sc_card_t * + const u8 *p; + size_t out_len = 0; + int r; +- unsigned int tag, cla; ++ unsigned int tag = 0, cla = 0; + piv_private_data_t * priv = PIV_DATA(card); + + LOG_FUNC_CALLED(card->ctx); +Index: opensc-0.21.0/src/libopensc/pkcs15-cert.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/pkcs15-cert.c ++++ opensc-0.21.0/src/libopensc/pkcs15-cert.c +@@ -169,7 +169,7 @@ sc_pkcs15_get_name_from_dn(struct sc_con + for (next_ava = rdn, next_ava_len = rdn_len; next_ava_len; ) { + const u8 *ava, *dummy, *oidp; + struct sc_object_id oid; +- size_t ava_len, dummy_len, oid_len; ++ size_t ava_len = 0, dummy_len, oid_len = 0; + + /* unwrap the set and point to the next ava */ + ava = sc_asn1_skip_tag(ctx, &next_ava, &next_ava_len, SC_ASN1_TAG_SET | SC_ASN1_CONS, &ava_len); +Index: opensc-0.21.0/src/libopensc/pkcs15-sc-hsm.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/pkcs15-sc-hsm.c ++++ opensc-0.21.0/src/libopensc/pkcs15-sc-hsm.c +@@ -277,7 +277,7 @@ int sc_pkcs15emu_sc_hsm_decode_cvc(sc_pk + struct sc_asn1_entry asn1_cvcert[C_ASN1_CVCERT_SIZE]; + struct sc_asn1_entry asn1_cvc_body[C_ASN1_CVC_BODY_SIZE]; + struct sc_asn1_entry asn1_cvc_pubkey[C_ASN1_CVC_PUBKEY_SIZE]; +- unsigned int cla,tag; ++ unsigned int cla = 0, tag = 0; + size_t taglen; + size_t lenchr = sizeof(cvc->chr); + size_t lencar = sizeof(cvc->car); +Index: opensc-0.21.0/src/pkcs15init/profile.c +=================================================================== +--- opensc-0.21.0.orig/src/pkcs15init/profile.c ++++ opensc-0.21.0/src/pkcs15init/profile.c +@@ -1695,7 +1695,7 @@ do_pin_storedlength(struct state *cur, i + static int + do_pin_flags(struct state *cur, int argc, char **argv) + { +- unsigned int flags; ++ unsigned int flags = 0; + int i, r; + + if (cur->pin->pin.auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) diff --git a/opensc-CVE-2024-45616.patch b/opensc-CVE-2024-45616.patch new file mode 100644 index 0000000..0c9852e --- /dev/null +++ b/opensc-CVE-2024-45616.patch @@ -0,0 +1,287 @@ +commit 1d3b410e06d33cfc4c70e8a25386e456cfbd7bd1 +Author: Veronika Hanulíková +Date: Thu Jul 11 15:27:19 2024 +0200 + + cardos: Fix uninitialized values + + Thanks Matteo Marini for report + https://github.com/OpenSC/OpenSC/security/advisories/GHSA-p3mx-7472-h3j8 + + fuzz_card/2 + +Index: opensc-0.21.0/src/libopensc/card-cardos.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/card-cardos.c ++++ opensc-0.21.0/src/libopensc/card-cardos.c +@@ -94,14 +94,14 @@ static void fixup_transceive_length(cons + + static int cardos_match_card(sc_card_t *card) + { +- unsigned char atr[SC_MAX_ATR_SIZE]; ++ unsigned char atr[SC_MAX_ATR_SIZE] = {0}; + int i; + + i = _sc_match_atr(card, cardos_atrs, &card->type); + if (i < 0) + return 0; + +- memcpy(atr, card->atr.value, sizeof(atr)); ++ memcpy(atr, card->atr.value, card->atr.len); + + /* Do not change card type for CIE! */ + if (card->type == SC_CARD_TYPE_CARDOS_CIE_V1) +@@ -114,8 +114,8 @@ static int cardos_match_card(sc_card_t * + return 1; + if (card->type == SC_CARD_TYPE_CARDOS_M4_2) { + int rv; +- sc_apdu_t apdu; +- u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; ++ sc_apdu_t apdu = {0}; ++ u8 rbuf[SC_MAX_APDU_BUFFER_SIZE] = {0}; + /* first check some additional ATR bytes */ + if ((atr[4] != 0xff && atr[4] != 0x02) || + (atr[6] != 0x10 && atr[6] != 0x0a) || +@@ -131,7 +131,7 @@ static int cardos_match_card(sc_card_t * + apdu.lc = 0; + rv = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, rv, "APDU transmit failed"); +- if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) ++ if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00 || apdu.resplen < 2) + return 0; + if (apdu.resp[0] != atr[10] || + apdu.resp[1] != atr[11]) +Index: opensc-0.21.0/src/libopensc/card-cac1.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/card-cac1.c ++++ opensc-0.21.0/src/libopensc/card-cac1.c +@@ -95,12 +95,12 @@ static int cac_cac1_get_certificate(sc_c + if (apdu.sw1 != 0x63 || apdu.sw2 < 1) { + /* we've either finished reading, or hit an error, break */ + r = sc_check_sw(card, apdu.sw1, apdu.sw2); +- left -= len; ++ left -= apdu.resplen; + break; + } + /* Adjust the lengths */ +- left -= len; +- out_ptr += len; ++ left -= apdu.resplen; ++ out_ptr += apdu.resplen; + len = MIN(left, apdu.sw2); + } + if (r < 0) { +Index: opensc-0.21.0/src/libopensc/card-oberthur.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/card-oberthur.c ++++ opensc-0.21.0/src/libopensc/card-oberthur.c +@@ -148,7 +148,7 @@ auth_select_aid(struct sc_card *card) + { + struct sc_apdu apdu; + unsigned char apdu_resp[SC_MAX_APDU_BUFFER_SIZE]; +- struct auth_private_data *data = (struct auth_private_data *) card->drv_data; ++ struct auth_private_data *data = (struct auth_private_data *)card->drv_data; + int rv, ii; + struct sc_path tmp_path; + +@@ -165,6 +165,9 @@ auth_select_aid(struct sc_card *card) + + rv = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, rv, "APDU transmit failed"); ++ if (apdu.resplen < 20) { ++ LOG_TEST_RET(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Serial number has incorrect length"); ++ } + card->serialnr.len = 4; + memcpy(card->serialnr.value, apdu.resp+15, 4); + +Index: opensc-0.21.0/src/libopensc/card-gids.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/card-gids.c ++++ opensc-0.21.0/src/libopensc/card-gids.c +@@ -231,6 +231,7 @@ static int gids_get_DO(sc_card_t* card, + size_t datasize = 0; + const u8* p; + u8 buffer[MAX_GIDS_FILE_SIZE]; ++ size_t buffer_len = sizeof(buffer); + + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + sc_log(card->ctx, +@@ -244,14 +245,15 @@ static int gids_get_DO(sc_card_t* card, + apdu.data = data; + apdu.datalen = 04; + apdu.resp = buffer; +- apdu.resplen = sizeof(buffer); ++ apdu.resplen = buffer_len; + apdu.le = 256; + + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "gids get data failed"); + LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "invalid return"); ++ buffer_len = apdu.resplen; + +- p = sc_asn1_find_tag(card->ctx, buffer, sizeof(buffer), dataObjectIdentifier, &datasize); ++ p = sc_asn1_find_tag(card->ctx, buffer, buffer_len, dataObjectIdentifier, &datasize); + if (!p) { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_FILE_NOT_FOUND); + } +Index: opensc-0.21.0/src/libopensc/card-mcrd.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/card-mcrd.c ++++ opensc-0.21.0/src/libopensc/card-mcrd.c +@@ -634,23 +634,25 @@ do_select(sc_card_t * card, u8 kind, + } + } + +- if (p2 == 0x04 && apdu.resp[0] == 0x62) { +- *file = sc_file_new(); +- if (!*file) +- LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); +- /* EstEID v3.0 cards are buggy and sometimes return a double 0x62 tag */ +- if (card->type == SC_CARD_TYPE_MCRD_ESTEID_V30 && apdu.resp[2] == 0x62) +- process_fcp(card, *file, apdu.resp + 4, apdu.resp[3]); +- else +- process_fcp(card, *file, apdu.resp + 2, apdu.resp[1]); +- return SC_SUCCESS; +- } ++ if (p2 == 0x04 && apdu.resplen > 2 && apdu.resp[0] == 0x62) { ++ *file = sc_file_new(); ++ if (!*file) ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); ++ if (apdu.resp[1] > apdu.resplen - 2) ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA); ++ /* EstEID v3.0 cards are buggy and sometimes return a double 0x62 tag */ ++ if (card->type == SC_CARD_TYPE_MCRD_ESTEID_V30 && apdu.resp[2] == 0x62) ++ process_fcp(card, *file, apdu.resp + 4, apdu.resp[3]); ++ else ++ process_fcp(card, *file, apdu.resp + 2, apdu.resp[1]); ++ return SC_SUCCESS; ++ } + +- if (p2 != 0x0C && apdu.resp[0] == 0x6F) { ++ if (p2 != 0x0C && apdu.resplen > 2 && apdu.resp[0] == 0x6F) { + *file = sc_file_new(); + if (!*file) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); +- if (apdu.resp[1] <= apdu.resplen) ++ if (apdu.resp[1] > apdu.resplen - 2) + process_fcp(card, *file, apdu.resp + 2, apdu.resp[1]); + return SC_SUCCESS; + } +Index: opensc-0.21.0/src/libopensc/asn1.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/asn1.c ++++ opensc-0.21.0/src/libopensc/asn1.c +@@ -68,7 +68,7 @@ int sc_asn1_read_tag(const u8 ** buf, si + + *buf = NULL; + +- if (left == 0 || !p) ++ if (left == 0 || !p || buflen == 0) + return SC_ERROR_INVALID_ASN1_OBJECT; + if (*p == 0xff || *p == 0) { + /* end of data reached */ +@@ -83,6 +83,8 @@ int sc_asn1_read_tag(const u8 ** buf, si + */ + cla = (*p & SC_ASN1_TAG_CLASS) | (*p & SC_ASN1_TAG_CONSTRUCTED); + tag = *p & SC_ASN1_TAG_PRIMITIVE; ++ if (left < 1) ++ return SC_ERROR_INVALID_ASN1_OBJECT; + p++; + left--; + if (tag == SC_ASN1_TAG_PRIMITIVE) { +Index: opensc-0.21.0/src/libopensc/card-dnie.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/card-dnie.c ++++ opensc-0.21.0/src/libopensc/card-dnie.c +@@ -1185,12 +1185,16 @@ static int dnie_compose_and_send_apdu(sc + + if (file_out) { + /* finally process FCI response */ ++ size_t len = apdu.resp[1]; + sc_file_free(*file_out); + *file_out = sc_file_new(); + if (*file_out == NULL) { + LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); + } +- res = card->ops->process_fci(card, *file_out, apdu.resp + 2, apdu.resp[1]); ++ if (apdu.resplen - 2 < len || len < 1) { ++ LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); ++ } ++ res = card->ops->process_fci(card, *file_out, apdu.resp + 2, len); + } + LOG_FUNC_RETURN(ctx, res); + } +@@ -1949,7 +1953,7 @@ static int dnie_process_fci(struct sc_ca + int *op = df_acl; + int n = 0; + sc_context_t *ctx = NULL; +- if ((card == NULL) || (card->ctx == NULL) || (file == NULL)) ++ if ((card == NULL) || (card->ctx == NULL) || (file == NULL) || buflen == 0) + return SC_ERROR_INVALID_ARGUMENTS; + ctx = card->ctx; + LOG_FUNC_CALLED(ctx); +Index: opensc-0.21.0/src/libopensc/muscle.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/muscle.c ++++ opensc-0.21.0/src/libopensc/muscle.c +@@ -94,33 +94,35 @@ int msc_partial_read_object(sc_card_t *c + apdu.resp = data; + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); +- if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) +- return dataLength; +- if(apdu.sw1 == 0x9C) { +- if(apdu.sw2 == 0x07) { ++ if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00 && dataLength <= apdu.resplen) ++ return dataLength; ++ if (apdu.sw1 == 0x9C) { ++ if (apdu.sw2 == 0x07) { + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_FILE_NOT_FOUND); +- } else if(apdu.sw2 == 0x06) { ++ } else if (apdu.sw2 == 0x06) { + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_ALLOWED); +- } else if(apdu.sw2 == 0x0F) { ++ } else if (apdu.sw2 == 0x0F) { + /* GUESSED */ + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS); + } + } + sc_log(card->ctx, + "got strange SWs: 0x%02X 0x%02X\n", apdu.sw1, apdu.sw2); +- return dataLength; +- +-} ++ ++ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_UNKNOWN_DATA_RECEIVED); ++ } + + int msc_read_object(sc_card_t *card, msc_id objectId, int offset, u8 *data, size_t dataLength) + { +- int r; ++ int r = 0; + size_t i; + size_t max_read_unit = MSC_MAX_READ; + +- for(i = 0; i < dataLength; i += max_read_unit) { ++ for(i = 0; i < dataLength; i += r) { + r = msc_partial_read_object(card, objectId, offset + i, data + i, MIN(dataLength - i, max_read_unit)); + LOG_TEST_RET(card->ctx, r, "Error in partial object read"); ++ if (r==0) ++ break; + } + return dataLength; + } +Index: opensc-0.21.0/src/libopensc/card-entersafe.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/card-entersafe.c ++++ opensc-0.21.0/src/libopensc/card-entersafe.c +@@ -1453,7 +1453,9 @@ static int entersafe_get_serialnr(sc_car + r=entersafe_transmit_apdu(card, &apdu,0,0,0,0); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + LOG_TEST_RET(card->ctx, sc_check_sw(card,apdu.sw1,apdu.sw2),"EnterSafe get SN failed"); +- ++ if (apdu.resplen != 8) ++ LOG_TEST_RET(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid length of SN"); ++ + card->serialnr.len=serial->len=8; + memcpy(card->serialnr.value,rbuf,8); + memcpy(serial->value,rbuf,8); diff --git a/opensc-CVE-2024-45617.patch b/opensc-CVE-2024-45617.patch new file mode 100644 index 0000000..52fa9e3 --- /dev/null +++ b/opensc-CVE-2024-45617.patch @@ -0,0 +1,55 @@ +commit fdb9e903eb124b6b18a5a9350a26eceb775585bc +Author: Veronika Hanulíková +Date: Tue Jul 16 14:05:36 2024 +0200 + + cac: Check return value when selecting AID + + Thanks Matteo Marini for report + https://github.com/OpenSC/OpenSC/security/advisories/GHSA-p3mx-7472-h3j8 + + fuzz_pkcs11/14 + +Index: opensc-0.21.0/src/libopensc/card-cac.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/card-cac.c ++++ opensc-0.21.0/src/libopensc/card-cac.c +@@ -1302,10 +1302,10 @@ static int cac_parse_aid(sc_card_t *card + /* Call without OID set will just select the AID without subsequent + * OID selection, which we need to figure out just now + */ +- cac_select_file_by_type(card, &new_object.path, NULL); ++ r = cac_select_file_by_type(card, &new_object.path, NULL); ++ LOG_TEST_RET(card->ctx, r, "Cannot select AID"); + r = cac_get_properties(card, &prop); +- if (r < 0) +- return SC_ERROR_INTERNAL; ++ LOG_TEST_RET(card->ctx, r, "Cannot get CAC properties"); + + for (i = 0; i < prop.num_objects; i++) { + /* don't fail just because we have more certs than we can support */ +Index: opensc-0.21.0/src/libopensc/card-cardos.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/card-cardos.c ++++ opensc-0.21.0/src/libopensc/card-cardos.c +@@ -1277,7 +1277,7 @@ cardos_lifecycle_get(sc_card_t *card, in + LOG_TEST_RET(card->ctx, r, "Card returned error"); + + if (apdu.resplen < 1) { +- LOG_TEST_RET(card->ctx, r, "Lifecycle byte not in response"); ++ LOG_TEST_RET(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Lifecycle byte not in response"); + } + + r = SC_SUCCESS; +Index: opensc-0.21.0/src/libopensc/card-jpki.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/card-jpki.c ++++ opensc-0.21.0/src/libopensc/card-jpki.c +@@ -195,6 +195,8 @@ jpki_select_file(struct sc_card *card, + u8 buf[4]; + rc = sc_read_binary(card, 0, buf, 4, 0); + LOG_TEST_RET(card->ctx, rc, "SW Check failed"); ++ if (rc < 4) ++ LOG_TEST_RET(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Received data too short"); + file = sc_file_new(); + if (!file) { + LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); diff --git a/opensc-CVE-2024-45618.patch b/opensc-CVE-2024-45618.patch new file mode 100644 index 0000000..3b40c93 --- /dev/null +++ b/opensc-CVE-2024-45618.patch @@ -0,0 +1,67 @@ +commit 8632ec172beda894581d67eaa991e519a7874f7d +Author: Veronika Hanulíková +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á +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)); diff --git a/opensc-CVE-2024-45619.patch b/opensc-CVE-2024-45619.patch new file mode 100644 index 0000000..b7800b0 --- /dev/null +++ b/opensc-CVE-2024-45619.patch @@ -0,0 +1,221 @@ +commit f01bfbd19b9c8243a40f7f17d554fe0eb9e89d0d +Author: Veronika Hanulíková +Date: Tue Jul 16 14:22:02 2024 +0200 + + pkcs15-tcos: Check number of read bytes for cert + + Thanks Matteo Marini for report + https://github.com/OpenSC/OpenSC/security/advisories/GHSA-p3mx-7472-h3j8 + + fuzz_pkcs11/15 + +Index: opensc-0.21.0/src/libopensc/pkcs15-tcos.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/pkcs15-tcos.c ++++ opensc-0.21.0/src/libopensc/pkcs15-tcos.c +@@ -45,6 +45,7 @@ static int insert_cert( + struct sc_pkcs15_cert_info cert_info; + struct sc_pkcs15_object cert_obj; + unsigned char cert[20]; ++ size_t cert_len = 0; + int r; + + memset(&cert_info, 0, sizeof(cert_info)); +@@ -57,24 +58,31 @@ static int insert_cert( + strlcpy(cert_obj.label, label, sizeof(cert_obj.label)); + cert_obj.flags = writable ? SC_PKCS15_CO_FLAG_MODIFIABLE : 0; + +- if(sc_select_file(card, &cert_info.path, NULL)!=SC_SUCCESS){ +- sc_log(ctx, +- "Select(%s) failed\n", path); ++ if (sc_select_file(card, &cert_info.path, NULL) != SC_SUCCESS) { ++ sc_log(ctx, "Select(%s) failed", path); + return 1; + } +- if(sc_read_binary(card, 0, cert, sizeof(cert), 0)<0){ +- sc_log(ctx, +- "ReadBinary(%s) failed\n", path); ++ r = sc_read_binary(card, 0, cert, sizeof(cert), 0); ++ if (r <= 0) { ++ sc_log(ctx, "ReadBinary(%s) failed\n", path); + return 2; + } +- if(cert[0]!=0x30 || cert[1]!=0x82){ +- sc_log(ctx, +- "Invalid Cert: %02X:%02X:...\n", cert[0], cert[1]); ++ cert_len = r; /* actual number of read bytes */ ++ if (cert_len < 7 || (size_t)(7 + cert[5]) > cert_len) { ++ sc_log(ctx, "Invalid certificate length"); ++ return 3; ++ } ++ if (cert[0] != 0x30 || cert[1] != 0x82) { ++ sc_log(ctx, "Invalid Cert: %02X:%02X:...\n", cert[0], cert[1]); + return 3; + } + + /* some certificates are prefixed by an OID */ +- if(cert[4]==0x06 && cert[5]<10 && cert[6+cert[5]]==0x30 && cert[7+cert[5]]==0x82){ ++ if (cert[4] == 0x06 && cert[5] < 10 && cert[6 + cert[5]] == 0x30 && cert[7 + cert[5]] == 0x82) { ++ if ((size_t)(9 + cert[5]) > cert_len) { ++ sc_log(ctx, "Invalid certificate length"); ++ return 3; ++ } + cert_info.path.index=6+cert[5]; + cert_info.path.count=(cert[8+cert[5]]<<8) + cert[9+cert[5]] + 4; + } else { +@@ -82,12 +90,12 @@ static int insert_cert( + cert_info.path.count=(cert[2]<<8) + cert[3] + 4; + } + +- r=sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); +- if(r!=SC_SUCCESS){ +- sc_log(ctx, "sc_pkcs15emu_add_x509_cert(%s) failed\n", path); ++ r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); ++ if (r != SC_SUCCESS) { ++ sc_log(ctx, "sc_pkcs15emu_add_x509_cert(%s) failed", path); + return 4; + } +- sc_log(ctx, "%s: OK, Index=%d, Count=%d\n", path, cert_info.path.index, cert_info.path.count); ++ sc_log(ctx, "%s: OK, Index=%d, Count=%d", path, cert_info.path.index, cert_info.path.count); + return 0; + } + +Index: opensc-0.21.0/src/libopensc/pkcs15-gemsafeV1.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/pkcs15-gemsafeV1.c ++++ opensc-0.21.0/src/libopensc/pkcs15-gemsafeV1.c +@@ -168,6 +168,7 @@ static int gemsafe_get_cert_len(sc_card_ + struct sc_file *file; + size_t objlen, certlen; + unsigned int ind, i=0; ++ int read_len; + + sc_format_path(GEMSAFE_PATH, &path); + r = sc_select_file(card, &path, &file); +@@ -176,9 +177,11 @@ static int gemsafe_get_cert_len(sc_card_ + sc_file_free(file); + + /* Initial read */ +- r = sc_read_binary(card, 0, ibuf, GEMSAFE_READ_QUANTUM, 0); +- if (r < 0) ++ read_len = sc_read_binary(card, 0, ibuf, GEMSAFE_READ_QUANTUM, 0); ++ if (read_len <= 2) { ++ sc_log(card->ctx, "Invalid size of object data: %d", read_len); + return SC_ERROR_INTERNAL; ++ } + + /* Actual stored object size is encoded in first 2 bytes + * (allocated EF space is much greater!) +@@ -207,7 +210,7 @@ static int gemsafe_get_cert_len(sc_card_ + * the private key. + */ + ind = 2; /* skip length */ +- while (ibuf[ind] == 0x01 && i < gemsafe_cert_max) { ++ while (ind + 1 < (size_t)read_len && ibuf[ind] == 0x01 && i < gemsafe_cert_max) { + if (ibuf[ind+1] == 0xFE) { + gemsafe_prkeys[i].ref = ibuf[ind+4]; + sc_log(card->ctx, "Key container %d is allocated and uses key_ref %d", +@@ -234,7 +237,7 @@ static int gemsafe_get_cert_len(sc_card_ + /* Read entire file, then dissect in memory. + * Gemalto ClassicClient seems to do it the same way. + */ +- iptr = ibuf + GEMSAFE_READ_QUANTUM; ++ iptr = ibuf + read_len; + while ((size_t)(iptr - ibuf) < objlen) { + r = sc_read_binary(card, iptr - ibuf, iptr, + MIN(GEMSAFE_READ_QUANTUM, objlen - (iptr - ibuf)), 0); +@@ -242,7 +245,14 @@ static int gemsafe_get_cert_len(sc_card_ + sc_log(card->ctx, "Could not read cert object"); + return SC_ERROR_INTERNAL; + } +- iptr += GEMSAFE_READ_QUANTUM; ++ if (r == 0) ++ break; ++ read_len += r; ++ iptr += r; ++ } ++ if ((size_t)read_len < objlen) { ++ sc_log(card->ctx, "Could not read cert object"); ++ return SC_ERROR_INTERNAL; + } + + /* Search buffer for certificates, they start with 0x3082. */ +Index: opensc-0.21.0/src/pkcs15init/pkcs15-setcos.c +=================================================================== +--- opensc-0.21.0.orig/src/pkcs15init/pkcs15-setcos.c ++++ opensc-0.21.0/src/pkcs15init/pkcs15-setcos.c +@@ -488,6 +488,9 @@ setcos_generate_key(struct sc_profile *p + r = sc_card_ctl(p15card->card, SC_CARDCTL_SETCOS_GETDATA, &data_obj); + LOG_TEST_RET(ctx, r, "Cannot get key modulus: 'SETCOS_GETDATA' failed"); + ++ if (data_obj.DataLen < 3 || data_obj.DataLen < pubkey->u.rsa.modulus.len) ++ LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Cannot get key modulus: wrong length of raw key"); ++ + keybits = ((raw_pubkey[0] * 256) + raw_pubkey[1]); /* modulus bit length */ + if (keybits != key_info->modulus_length) { + sc_log(ctx, +@@ -495,7 +498,7 @@ setcos_generate_key(struct sc_profile *p + keybits, key_info->modulus_length); + LOG_TEST_RET(ctx, SC_ERROR_PKCS15INIT, "Failed to generate key"); + } +- memcpy (pubkey->u.rsa.modulus.data, &raw_pubkey[2], pubkey->u.rsa.modulus.len); ++ memcpy(pubkey->u.rsa.modulus.data, &raw_pubkey[2], pubkey->u.rsa.modulus.len); + } + + sc_file_free(file); +Index: opensc-0.21.0/src/pkcs15init/pkcs15-sc-hsm.c +=================================================================== +--- opensc-0.21.0.orig/src/pkcs15init/pkcs15-sc-hsm.c ++++ opensc-0.21.0/src/pkcs15init/pkcs15-sc-hsm.c +@@ -140,7 +140,7 @@ static int sc_hsm_determine_free_id(stru + LOG_TEST_RET(card->ctx, filelistlength, "Could not enumerate file and key identifier"); + + for (j = 0; j < 256; j++) { +- for (i = 0; i < filelistlength; i += 2) { ++ for (i = 0; i + 1 < filelistlength; i += 2) { + if ((filelist[i] == range) && (filelist[i + 1] == j)) { + break; + } +Index: opensc-0.21.0/src/libopensc/card-coolkey.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/card-coolkey.c ++++ opensc-0.21.0/src/libopensc/card-coolkey.c +@@ -1684,6 +1684,7 @@ static int coolkey_rsa_op(sc_card_t *car + u8 key_number; + size_t params_len; + u8 buf[MAX_COMPUTE_BUF + 2]; ++ size_t buf_len; + u8 *buf_out; + + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); +@@ -1724,8 +1725,6 @@ static int coolkey_rsa_op(sc_card_t *car + ushort2bebytes(params.init.buf_len, 0); + } else { + /* The data fits in APDU. Copy it to the params object */ +- size_t buf_len; +- + params.init.location = COOLKEY_CRYPT_LOCATION_APDU; + + params_len = sizeof(params.init) + datalen; +@@ -1745,6 +1744,7 @@ static int coolkey_rsa_op(sc_card_t *car + if (r < 0) { + goto done; + } ++ buf_len = crypt_out_len_p; + + if (datalen > MAX_COMPUTE_BUF) { + u8 len_buf[2]; +@@ -1763,7 +1763,12 @@ static int coolkey_rsa_op(sc_card_t *car + priv->nonce, sizeof(priv->nonce)); + + } else { +- size_t out_length = bebytes2ushort(buf); ++ size_t out_length; ++ if (buf_len < 2) { ++ r = SC_ERROR_WRONG_LENGTH; ++ goto done; ++ } ++ out_length = bebytes2ushort(buf); + if (out_length > sizeof buf - 2) { + r = SC_ERROR_WRONG_LENGTH; + goto done; diff --git a/opensc-CVE-2024-45620.patch b/opensc-CVE-2024-45620.patch new file mode 100644 index 0000000..00c5c3a --- /dev/null +++ b/opensc-CVE-2024-45620.patch @@ -0,0 +1,73 @@ +commit a1bcc6516f43d570899820d259b71c53f8049168 +Author: Veronika Hanulíková +Date: Thu Jul 18 09:23:20 2024 +0200 + + pkcs15-starcos: Check length of file to be non-zero + + Thanks Matteo Marini for report + https://github.com/OpenSC/OpenSC/security/advisories/GHSA-p3mx-7472-h3j8 + + fuzz_pkcs15init/20 + +Index: opensc-0.21.0/src/pkcs15init/pkcs15-starcos.c +=================================================================== +--- opensc-0.21.0.orig/src/pkcs15init/pkcs15-starcos.c ++++ opensc-0.21.0/src/pkcs15init/pkcs15-starcos.c +@@ -670,6 +670,8 @@ static int starcos_write_pukey(sc_profil + return r; + len = tfile->size; + sc_file_free(tfile); ++ if (len == 0) ++ return SC_ERROR_INTERNAL; + buf = malloc(len); + if (!buf) + return SC_ERROR_OUT_OF_MEMORY; +@@ -682,7 +684,7 @@ static int starcos_write_pukey(sc_profil + if (num_keys == 0xff) + num_keys = 0; + /* encode public key */ +- keylen = starcos_encode_pukey(rsa, NULL, kinfo); ++ keylen = starcos_encode_pukey(rsa, NULL, kinfo); + if (!keylen) { + free(buf); + return SC_ERROR_INTERNAL; +Index: opensc-0.21.0/src/libopensc/iasecc-sdo.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/iasecc-sdo.c ++++ opensc-0.21.0/src/libopensc/iasecc-sdo.c +@@ -324,16 +324,25 @@ iasecc_se_parse(struct sc_card *card, un + + LOG_FUNC_CALLED(ctx); + ++ if (data_len < 1) ++ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); ++ + if (*data == IASECC_SDO_TEMPLATE_TAG) { + size_size = iasecc_parse_size(data + 1, &size); + LOG_TEST_RET(ctx, size_size, "parse error: invalid size data of IASECC_SDO_TEMPLATE"); + ++ if (data_len - 1 < size) ++ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); ++ + data += size_size + 1; + data_len = size; + sc_log(ctx, + "IASECC_SDO_TEMPLATE: size %"SC_FORMAT_LEN_SIZE_T"u, size_size %"SC_FORMAT_LEN_SIZE_T"u", + size, size_size); + ++ if (data_len < 3) ++ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); ++ + if (*data != IASECC_SDO_TAG_HEADER) + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); + +@@ -728,6 +737,8 @@ iasecc_sdo_parse(struct sc_card *card, u + int rv; + + LOG_FUNC_CALLED(ctx); ++ if (data == NULL || data_len < 2) ++ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); + + if (*data == IASECC_SDO_TEMPLATE_TAG) { + size_size = iasecc_parse_size(data + 1, &size); + diff --git a/opensc-CVE-2024-8443.patch b/opensc-CVE-2024-8443.patch new file mode 100644 index 0000000..c766499 --- /dev/null +++ b/opensc-CVE-2024-8443.patch @@ -0,0 +1,78 @@ +commit b28a3cef416fcfb92fbb9ea7fd3c71df52c6c9fc +Author: Jakub Jelen +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 + +Index: opensc-0.21.0/src/libopensc/card-openpgp.c +=================================================================== +--- opensc-0.21.0.orig/src/libopensc/card-openpgp.c ++++ opensc-0.21.0/src/libopensc/card-openpgp.c +@@ -2657,14 +2657,21 @@ pgp_calculate_and_store_fingerprint(sc_c + /* update the blob containing fingerprints (00C5) */ + sc_log(card->ctx, "Updating fingerprint blob 00C5."); + fpseq_blob = pgp_find_blob(card, 0x00C5); +- if (fpseq_blob == NULL) +- LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot find blob 00C5"); ++ if (fpseq_blob == NULL) { ++ r = SC_ERROR_OUT_OF_MEMORY; ++ LOG_TEST_GOTO_ERR(card->ctx, r, "Cannot find blob 00C5"); ++ } ++ if (20 * key_info->key_id > fpseq_blob->len) { ++ r = SC_ERROR_OBJECT_NOT_VALID; ++ LOG_TEST_GOTO_ERR(card->ctx, r, "The 00C5 blob is not large enough"); ++ } + + /* save the fingerprints sequence */ + newdata = malloc(fpseq_blob->len); +- if (newdata == NULL) +- LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_OUT_OF_MEMORY, +- "Not enough memory to update fingerprint blob 00C5"); ++ if (newdata == NULL) { ++ r = SC_ERROR_OUT_OF_MEMORY; ++ LOG_TEST_GOTO_ERR(card->ctx, r, "Not enough memory to update fingerprint blob 00C5"); ++ } + + memcpy(newdata, fpseq_blob->data, fpseq_blob->len); + /* move p to the portion holding the fingerprint of the current key */ +@@ -2778,6 +2785,9 @@ pgp_parse_and_set_pubkey_output(sc_card_ + + /* RSA modulus */ + if (tag == 0x0081) { ++ if (key_info->algorithm != SC_OPENPGP_KEYALGO_RSA) { ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); ++ } + if ((BYTES4BITS(key_info->u.rsa.modulus_len) < len) /* modulus_len is in bits */ + || key_info->u.rsa.modulus == NULL) { + +@@ -2793,6 +2803,9 @@ pgp_parse_and_set_pubkey_output(sc_card_ + } + /* RSA public exponent */ + else if (tag == 0x0082) { ++ if (key_info->algorithm != SC_OPENPGP_KEYALGO_RSA) { ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); ++ } + if ((BYTES4BITS(key_info->u.rsa.exponent_len) < len) /* exponent_len is in bits */ + || key_info->u.rsa.exponent == NULL) { + +@@ -2808,6 +2821,10 @@ pgp_parse_and_set_pubkey_output(sc_card_ + } + /* ECC public key */ + else if (tag == 0x0086) { ++ if (key_info->algorithm != SC_OPENPGP_KEYALGO_ECDSA && ++ key_info->algorithm != SC_OPENPGP_KEYALGO_ECDH) { ++ LOG_FUNC_RETURN(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); ++ } + /* set the output data */ + /* len is ecpoint length + format byte + * see section 7.2.14 of 3.3.1 specs */ diff --git a/opensc.spec b/opensc.spec index 281ac68..abe31ff 100644 --- a/opensc.spec +++ b/opensc.spec @@ -3,7 +3,7 @@ Name: opensc Version: 0.21.0 -Release: 7 +Release: 11 License: LGPLv2.1+ Summary: Smart card library and applications URL: https://github.com/OpenSC/OpenSC/wiki @@ -38,6 +38,30 @@ Patch17: backport-0003-CVE-2021-42782-cardos-Correctly-calculate-the-left.patch Patch18: backport-0004-CVE-2021-42782-iasecc-Prevent-stack-buffer.patch Patch19: backport-0005-CVE-2021-42782-PIV-Improved-parsing.patch Patch20: backport-0006-CVE-2023-2977-correct_left_length_calculation_to_fix_buffer.patch +Patch21: 0003-opensc-CVE-2023-40660-1of2.patch +Patch22: 0004-opensc-CVE-2023-40660-2of2.patch +Patch23: 0007-opensc-CVE-2023-40661-1of12.patch +Patch24: 0008-opensc-CVE-2023-40661-2of12.patch +Patch25: 0009-opensc-CVE-2023-40661-3of12.patch +Patch26: 0010-opensc-CVE-2023-40661-4of12.patch +Patch27: 0011-opensc-CVE-2023-40661-5of12.patch +Patch28: 0012-opensc-CVE-2023-40661-6of12.patch +Patch29: 0013-opensc-CVE-2023-40661-7of12.patch +Patch30: 0014-opensc-CVE-2023-40661-8of12.patch +Patch31: 0015-opensc-CVE-2023-40661-9of12.patch +Patch32: 0016-opensc-CVE-2023-40661-10of12.patch +Patch33: 0017-opensc-CVE-2023-40661-11of12.patch +Patch34: 0018-opensc-CVE-2023-40661-12of12.patch +# https://github.com/OpenSC/OpenSC/pull/2948 +# https://github.com/OpenSC/OpenSC/pull/3016 +Patch35: backport-opensc-CVE-2023-5992.patch +Patch36: opensc-CVE-2024-45615.patch +Patch38: opensc-CVE-2024-45616.patch +Patch39: opensc-CVE-2024-45617.patch +Patch40: opensc-CVE-2024-45618.patch +Patch41: opensc-CVE-2024-45619.patch +Patch42: opensc-CVE-2024-45620.patch +Patch43: opensc-CVE-2024-8443.patch %description OpenSC provides a set of libraries and utilities to work with smart cards. @@ -156,7 +180,20 @@ make check %{_datadir}/opensc/ %changelog -* Mon Nov 20 2023 liningjie - 0.21.0-7 +* Mon Oct 07 2024 Funda Wang - 0.21.0-11 +- fix CVE-2024-8443, CVE-2024-45615, CVE-2024-45616, + CVE-2024-45617, CVE-2024-45618, CVE-2024-45619, CVE-2024-45620 + +* Mon Jul 1 2024 dillon chen - 0.21.0-10 +- fix CVE-2023-5992 + +* Wed Nov 8 2023 dillon chen - 0.21.0-9 +- fix CVE-2023-40661 + +* Mon Oct 23 2023 dillon chen - 0.21.0-8 +- fix CVE-2023-40660 + +* Mon Sep 18 2023 dillon chen - 0.21.0-7 - fix CVE-2023-2977 * Mon May 9 2022 Hugel - 0.21.0-6 -- Gitee