From 947ac4bf32ae2e9e006a98e33bc41aedf460c624 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 4 Oct 2023 14:46:08 +0200 Subject: [PATCH] Fixes for CVE-2023-40661 Resolves: RHEL-17086 --- opensc-0.23.0-pkcs15init.patch | 855 +++++++++++++++++++++++++++++++++ opensc.spec | 19 + 2 files changed, 874 insertions(+) create mode 100644 opensc-0.23.0-pkcs15init.patch diff --git a/opensc-0.23.0-pkcs15init.patch b/opensc-0.23.0-pkcs15init.patch new file mode 100644 index 0000000..b715d04 --- /dev/null +++ b/opensc-0.23.0-pkcs15init.patch @@ -0,0 +1,855 @@ +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 | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c +index eb7fc6afc..4215b733a 100644 +--- a/src/libopensc/pkcs15.c ++++ b/src/libopensc/pkcs15.c +@@ -532,7 +532,7 @@ sc_pkcs15_get_lastupdate(struct sc_pkcs15_card *p15card) + 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; +@@ -569,9 +569,11 @@ sc_pkcs15_get_lastupdate(struct sc_pkcs15_card *p15card) + 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; +2.41.0 + +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(+) + +diff --git a/src/pkcs15init/pkcs15-setcos.c b/src/pkcs15init/pkcs15-setcos.c +index 1b56afe6d..1907b47f9 100644 +--- a/src/pkcs15init/pkcs15-setcos.c ++++ b/src/pkcs15init/pkcs15-setcos.c +@@ -349,6 +349,10 @@ setcos_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, + + /* 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]; + +-- +2.41.0 + +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 ad2cabd53..c441ab1e7 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. */ +-- +2.41.0 + + +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 4a0ddffbe..7107c47cb 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); +-- +2.41.0 + +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 7107c47cb..49b514968 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); +-- +2.41.0 +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 d06568073..ce1d48e62 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) +-- +2.41.0 + +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 2b793b028..3bad1e853 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)); + +-- +2.41.0 + +From e7f81d86dcdc751f4737f4b29a99bfc54d29c5c9 Mon Sep 17 00:00:00 2001 +From: Frank Morgner +Date: Thu, 8 Dec 2022 00:45:31 +0100 +Subject: [PATCH] muscle: prevent out of bounds write + +fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=53631 +--- + src/libopensc/muscle.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/libopensc/muscle.c b/src/libopensc/muscle.c +index 7af279a0a..61a4ec24d 100644 +--- a/src/libopensc/muscle.c ++++ b/src/libopensc/muscle.c +@@ -127,7 +127,7 @@ int msc_zero_object(sc_card_t *card, msc_id objectId, size_t dataLength) + { + u8 zeroBuffer[MSC_MAX_APDU]; + size_t i; +- size_t max_write_unit = MSC_MAX_SEND - 9; /* - 9 for object ID+length */ ++ size_t max_write_unit = MIN(MSC_MAX_APDU, MSC_MAX_SEND - 9); /* - 9 for object ID+length */ + + memset(zeroBuffer, 0, max_write_unit); + for(i = 0; i < dataLength; i += max_write_unit) { +-- +2.41.0 + +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 61a4ec24d..9d01e0c11 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) +-- +2.41.0 + +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 91cee3731..3df03c6e1 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--) { +-- +2.41.0 + +From 4013a807492568bf9907cfb3df41f130ac83c7b9 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Wed, 15 Nov 2023 10:53:46 +0100 +Subject: [PATCH] setcos: Avoid writing behind the path buffer end + +The path->value buffer is fixed to 16 bytes so it is not always possible +to append 2 more bytes. Doing so overruns the buffer, writing into the +ACL block, crashing during the cleanup. + +Thanks oss-fuzz + +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=64181 +--- + src/pkcs15init/pkcs15-setcos.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/pkcs15init/pkcs15-setcos.c b/src/pkcs15init/pkcs15-setcos.c +index 70a28048b..1eeeda064 100644 +--- a/src/pkcs15init/pkcs15-setcos.c ++++ b/src/pkcs15init/pkcs15-setcos.c +@@ -287,6 +287,10 @@ setcos_new_file(sc_profile_t *profile, sc_card_t *card, + file->id += num; + p = &file->path; + *p = profile->df_info->file->path; ++ if (p->len + 2 > SC_MAX_PATH_SIZE) { ++ sc_file_free(file); ++ return SC_ERROR_INVALID_DATA; ++ } + p->value[p->len++] = (u8) (file->id / 256); + p->value[p->len++] = (u8) (file->id % 256); + +-- +2.42.0 + +From 8fc2c20c3f895569eeb58328bb882aec07325d3b Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 7 Nov 2023 17:48:27 +0100 +Subject: [PATCH] iasecc: Avoid another buffer overflow + +thanks oss-fuzz + +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=63949 +--- + src/libopensc/iasecc-sdo.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/src/libopensc/iasecc-sdo.c b/src/libopensc/iasecc-sdo.c +index a41c3c2d3..86032f5a8 100644 +--- a/src/libopensc/iasecc-sdo.c ++++ b/src/libopensc/iasecc-sdo.c +@@ -44,7 +44,8 @@ iasecc_parse_acls(struct sc_card *card, struct iasecc_sdo_docp *docp, int flags) + { + struct sc_context *ctx = card->ctx; + struct iasecc_extended_tlv *acls = &docp->acls_contact; +- int ii, offs; ++ int ii; ++ size_t offs; + unsigned char mask = 0x40; + + if (flags) +@@ -56,8 +57,12 @@ iasecc_parse_acls(struct sc_card *card, struct iasecc_sdo_docp *docp, int flags) + docp->amb = *(acls->value + 0); + memset(docp->scbs, 0xFF, sizeof(docp->scbs)); + for (ii=0, offs = 1; ii<7; ii++, mask >>= 1) +- if (mask & docp->amb) ++ if (mask & docp->amb) { ++ if (offs >= acls->size) { ++ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); ++ } + docp->scbs[ii] = *(acls->value + offs++); ++ } + + sc_log(ctx, "iasecc_parse_docp() SCBs %02X:%02X:%02X:%02X:%02X:%02X:%02X", + docp->scbs[0],docp->scbs[1],docp->scbs[2],docp->scbs[3], +-- +2.42.0 + +From 83b9129bd3cfc6ac57d5554e015c3df85f5076dc Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Wed, 11 Oct 2023 08:57:45 +0200 +Subject: [PATCH] iassecc: Verify buffer lengths before use + +Thanks oss-fuzz + +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=63163 +--- + src/libopensc/iasecc-sdo.c | 55 +++++++++++++++++++++----------------- + 1 file changed, 31 insertions(+), 24 deletions(-) + +diff --git a/src/libopensc/iasecc-sdo.c b/src/libopensc/iasecc-sdo.c +index 3eeb03b91..a6e6c2677 100644 +--- a/src/libopensc/iasecc-sdo.c ++++ b/src/libopensc/iasecc-sdo.c +@@ -36,7 +36,7 @@ + #include "iasecc.h" + #include "iasecc-sdo.h" + +-static int iasecc_parse_size(unsigned char *data, size_t *out); ++static int iasecc_parse_size(unsigned char *data, size_t data_len, size_t *out); + + + static int +@@ -330,7 +330,7 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru + LOG_FUNC_CALLED(ctx); + + if (*data == IASECC_SDO_TEMPLATE_TAG) { +- size_size = iasecc_parse_size(data + 1, &size); ++ size_size = iasecc_parse_size(data + 1, data_len - 1, &size); + LOG_TEST_RET(ctx, size_size, "parse error: invalid size data of IASECC_SDO_TEMPLATE"); + + data += size_size + 1; +@@ -345,7 +345,7 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru + if ((*(data + 1) & 0x7F) != IASECC_SDO_CLASS_SE) + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); + +- size_size = iasecc_parse_size(data + 3, &size); ++ size_size = iasecc_parse_size(data + 3, data_len - 3, &size); + LOG_TEST_RET(ctx, size_size, "parse error: invalid SDO SE data size"); + + if (data_len != size + size_size + 3) +@@ -365,7 +365,7 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru + LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); + } + +- size_size = iasecc_parse_size(data + 1, &size); ++ size_size = iasecc_parse_size(data + 1, data_len - 1, &size); + LOG_TEST_RET(ctx, size_size, "parse error: invalid size data"); + + if (data_len != size + size_size + 1) +@@ -387,17 +387,17 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru + + + static int +-iasecc_parse_size(unsigned char *data, size_t *out) ++iasecc_parse_size(unsigned char *data, size_t data_len, size_t *out) + { +- if (*data < 0x80) { ++ if (*data < 0x80 && data_len > 0) { + *out = *data; + return 1; + } +- else if (*data == 0x81) { ++ else if (*data == 0x81 && data_len > 1) { + *out = *(data + 1); + return 2; + } +- else if (*data == 0x82) { ++ else if (*data == 0x82 && data_len > 2) { + *out = *(data + 1) * 0x100 + *(data + 2); + return 3; + } +@@ -407,14 +407,18 @@ iasecc_parse_size(unsigned char *data, size_t *out) + + + static int +-iasecc_parse_get_tlv(struct sc_card *card, unsigned char *data, struct iasecc_extended_tlv *tlv) ++iasecc_parse_get_tlv(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_extended_tlv *tlv) + { + struct sc_context *ctx = card->ctx; + size_t size_len, tag_len; + + memset(tlv, 0, sizeof(*tlv)); + sc_log(ctx, "iasecc_parse_get_tlv() called for tag 0x%X", *data); ++ if (data_len < 1) ++ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); + if ((*data == 0x7F) || (*data == 0x5F)) { ++ if (data_len < 2) ++ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); + tlv->tag = *data * 0x100 + *(data + 1); + tag_len = 2; + } +@@ -424,8 +428,11 @@ iasecc_parse_get_tlv(struct sc_card *card, unsigned char *data, struct iasecc_ex + } + + sc_log(ctx, "iasecc_parse_get_tlv() tlv->tag 0x%X", tlv->tag); +- size_len = iasecc_parse_size(data + tag_len, &tlv->size); ++ size_len = iasecc_parse_size(data + tag_len, data_len - tag_len, &tlv->size); + LOG_TEST_RET(ctx, size_len, "parse error: invalid size data"); ++ if (tag_len + size_len + tlv->size > data_len) { ++ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); ++ } + + tlv->value = calloc(1, tlv->size); + if (!tlv->value) +@@ -452,7 +459,7 @@ iasecc_parse_chv(struct sc_card *card, unsigned char *data, size_t data_len, str + while(offs < data_len) { + struct iasecc_extended_tlv tlv; + +- rv = iasecc_parse_get_tlv(card, data + offs, &tlv); ++ rv = iasecc_parse_get_tlv(card, data + offs, data_len - offs, &tlv); + LOG_TEST_RET(ctx, rv, "iasecc_parse_chv() get and parse TLV error"); + + sc_log(ctx, +@@ -486,7 +493,7 @@ iasecc_parse_prvkey(struct sc_card *card, unsigned char *data, size_t data_len, + while(offs < data_len) { + struct iasecc_extended_tlv tlv; + +- rv = iasecc_parse_get_tlv(card, data + offs, &tlv); ++ rv = iasecc_parse_get_tlv(card, data + offs, data_len - offs, &tlv); + LOG_TEST_RET(ctx, rv, "iasecc_parse_prvkey() get and parse TLV error"); + + sc_log(ctx, +@@ -516,7 +523,7 @@ iasecc_parse_pubkey(struct sc_card *card, unsigned char *data, size_t data_len, + while(offs < data_len) { + struct iasecc_extended_tlv tlv; + +- rv = iasecc_parse_get_tlv(card, data + offs, &tlv); ++ rv = iasecc_parse_get_tlv(card, data + offs, data_len - offs, &tlv); + LOG_TEST_RET(ctx, rv, "iasecc_parse_pubkey() get and parse TLV error"); + + sc_log(ctx, +@@ -554,7 +561,7 @@ iasecc_parse_keyset(struct sc_card *card, unsigned char *data, size_t data_len, + while(offs < data_len) { + struct iasecc_extended_tlv tlv; + +- rv = iasecc_parse_get_tlv(card, data + offs, &tlv); ++ rv = iasecc_parse_get_tlv(card, data + offs, data_len - offs, &tlv); + LOG_TEST_RET(ctx, rv, "iasecc_parse_keyset() get and parse TLV error"); + + sc_log(ctx, +@@ -586,7 +593,7 @@ iasecc_parse_docp(struct sc_card *card, unsigned char *data, size_t data_len, st + while(offs < data_len) { + struct iasecc_extended_tlv tlv; + +- rv = iasecc_parse_get_tlv(card, data + offs, &tlv); ++ rv = iasecc_parse_get_tlv(card, data + offs, data_len - offs, &tlv); + LOG_TEST_RET(ctx, rv, "iasecc_parse_get_tlv() get and parse TLV error"); + + sc_log(ctx, +@@ -641,7 +648,7 @@ iasecc_parse_docp(struct sc_card *card, unsigned char *data, size_t data_len, st + + + static int +-iasecc_sdo_parse_data(struct sc_card *card, unsigned char *data, struct iasecc_sdo *sdo) ++iasecc_sdo_parse_data(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_sdo *sdo) + { + struct sc_context *ctx = card->ctx; + struct iasecc_extended_tlv tlv; +@@ -650,7 +657,7 @@ iasecc_sdo_parse_data(struct sc_card *card, unsigned char *data, struct iasecc_s + LOG_FUNC_CALLED(ctx); + sc_log(ctx, "iasecc_sdo_parse_data() class %X; ref %X", sdo->sdo_class, sdo->sdo_ref); + +- tlv_size = iasecc_parse_get_tlv(card, data, &tlv); ++ tlv_size = iasecc_parse_get_tlv(card, data, data_len, &tlv); + LOG_TEST_RET(ctx, tlv_size, "parse error: get TLV"); + + sc_log(ctx, "iasecc_sdo_parse_data() tlv.tag 0x%X", tlv.tag); +@@ -735,7 +742,7 @@ iasecc_sdo_parse(struct sc_card *card, unsigned char *data, size_t data_len, str + LOG_FUNC_CALLED(ctx); + + if (*data == IASECC_SDO_TEMPLATE_TAG) { +- size_size = iasecc_parse_size(data + 1, &size); ++ size_size = iasecc_parse_size(data + 1, data_len - 1, &size); + LOG_TEST_RET(ctx, size_size, "parse error: invalid size data of IASECC_SDO_TEMPLATE"); + + data += size_size + 1; +@@ -754,7 +761,7 @@ iasecc_sdo_parse(struct sc_card *card, unsigned char *data, size_t data_len, str + if (sdo->sdo_ref != (*(data + 2) & 0x3F)) + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); + +- size_size = iasecc_parse_size(data + 3, &size); ++ size_size = iasecc_parse_size(data + 3, data_len - 3, &size); + LOG_TEST_RET(ctx, size_size, "parse error: invalid size data"); + + if (data_len != size + size_size + 3) +@@ -766,7 +773,7 @@ iasecc_sdo_parse(struct sc_card *card, unsigned char *data, size_t data_len, str + + offs = 3 + size_size; + for (; offs < data_len;) { +- rv = iasecc_sdo_parse_data(card, data + offs, sdo); ++ rv = iasecc_sdo_parse_data(card, data + offs, data_len - offs, sdo); + LOG_TEST_RET(ctx, rv, "parse error: invalid SDO data"); + + offs += rv; +@@ -812,7 +819,7 @@ iasecc_sdo_allocate_and_parse(struct sc_card *card, unsigned char *data, size_t + if (data_len == 3) + LOG_FUNC_RETURN(ctx, SC_SUCCESS); + +- size_size = iasecc_parse_size(data + 3, &size); ++ size_size = iasecc_parse_size(data + 3, data_len - 3, &size); + LOG_TEST_RET(ctx, size_size, "parse error: invalid size data"); + + if (data_len != size + size_size + 3) +@@ -824,7 +831,7 @@ iasecc_sdo_allocate_and_parse(struct sc_card *card, unsigned char *data, size_t + + offs = 3 + size_size; + for (; offs < data_len;) { +- rv = iasecc_sdo_parse_data(card, data + offs, sdo); ++ rv = iasecc_sdo_parse_data(card, data + offs, data_len - offs, sdo); + LOG_TEST_RET(ctx, rv, "parse error: invalid SDO data"); + + offs += rv; +@@ -1222,7 +1229,7 @@ iasecc_sdo_parse_card_answer(struct sc_context *ctx, unsigned char *data, size_t + + memset(out, 0, sizeof(*out)); + for (offs=0; offs sizeof(out->data)) +@@ -1293,7 +1300,7 @@ iasecc_docp_copy(struct sc_context *ctx, struct iasecc_sdo_docp *in, struct iase + int rv; + + LOG_FUNC_CALLED(ctx); +- if (!in || !out) ++ if (!in || !out) + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); + + memset(out, 0, sizeof(struct iasecc_sdo_docp)); +-- +2.42.0 + +From fbda61d0d276dc98b9d1d1e6810bbd21d19e3859 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 27 Oct 2023 13:23:18 +0200 +Subject: [PATCH] iasecc: Avoid buffer overflow with invalid data + +Thanks oss-fuzz + +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=63587 +--- + src/libopensc/iasecc-sdo.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/libopensc/iasecc-sdo.c b/src/libopensc/iasecc-sdo.c +index 1e01c0df5..479b3c23b 100644 +--- a/src/libopensc/iasecc-sdo.c ++++ b/src/libopensc/iasecc-sdo.c +@@ -371,15 +371,15 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru + static int + iasecc_parse_size(unsigned char *data, size_t data_len, size_t *out) + { +- if (*data < 0x80 && data_len > 0) { ++ if (data_len > 0 && *data < 0x80) { + *out = *data; + return 1; + } +- else if (*data == 0x81 && data_len > 1) { ++ else if (data_len > 1 && *data == 0x81) { + *out = *(data + 1); + return 2; + } +- else if (*data == 0x82 && data_len > 2) { ++ else if (data_len > 2 && *data == 0x82) { + *out = *(data + 1) * 0x100 + *(data + 2); + return 3; + } +-- +2.42.0 + +From 2a4921ab23fd0853f327517636c50de947548161 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= +Date: Tue, 29 Aug 2023 14:40:21 +0200 +Subject: [PATCH] iasecc: Check length of data when parsing crt + +Thanks OSS-Fuzz +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=61797 +--- + src/libopensc/iasecc-sdo.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/src/libopensc/iasecc-sdo.c b/src/libopensc/iasecc-sdo.c +index b3e567dd5..3eeb03b91 100644 +--- a/src/libopensc/iasecc-sdo.c ++++ b/src/libopensc/iasecc-sdo.c +@@ -204,7 +204,7 @@ iasecc_sdo_free(struct sc_card *card, struct iasecc_sdo *sdo) + + + static int +-iasecc_crt_parse(struct sc_card *card, unsigned char *data, struct iasecc_se_info *se) ++iasecc_crt_parse(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_se_info *se) + { + struct sc_context *ctx = card->ctx; + struct sc_crt crt; +@@ -212,11 +212,16 @@ iasecc_crt_parse(struct sc_card *card, unsigned char *data, struct iasecc_se_inf + + sc_log(ctx, "iasecc_crt_parse(0x%X) called", *data); + ++ if (data_len < 2) ++ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); ++ + memset(&crt, 0, sizeof(crt)); + crt.tag = *(data + 0); + len = *(data + 1); + + for(offs = 2; offs < len + 2; offs += 3) { ++ if ((size_t) offs + 2 >= data_len) ++ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); + sc_log(ctx, "iasecc_crt_parse(0x%X) CRT %X -> %X", *data, *(data + offs), *(data + offs + 2)); + if (*(data + offs) == IASECC_CRT_TAG_USAGE) { + crt.usage = *(data + offs + 2); +@@ -368,7 +373,7 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru + + offs = 1 + size_size; + for (; offs < data_len;) { +- rv = iasecc_crt_parse(card, data + offs, se); ++ rv = iasecc_crt_parse(card, data + offs, data_len - offs, se); + LOG_TEST_RET(ctx, rv, "parse error: invalid SE data"); + + offs += rv; +-- +2.42.0 + +From 6085994384a7171c5c68f6718d9db10ed77c5af1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= +Date: Thu, 10 Aug 2023 13:56:24 +0200 +Subject: [PATCH] card-entersafe.c: Free modulus buffer in case of error + +Thanks OSS-Fuzz +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=60680 +--- + src/libopensc/card-entersafe.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/src/libopensc/card-entersafe.c b/src/libopensc/card-entersafe.c +index eb31f7146..168894abd 100644 +--- a/src/libopensc/card-entersafe.c ++++ b/src/libopensc/card-entersafe.c +@@ -1423,12 +1423,18 @@ static int entersafe_gen_key(sc_card_t *card, sc_entersafe_gen_key_data *data) + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_OUT_OF_MEMORY); + + p=rbuf; +- if (*p!='E') ++ if (*p!='E') { ++ free(data->modulus); ++ data->modulus = NULL; + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA); ++ } + p+=2+p[1]; + /* N */ +- if (*p!='N') ++ if (*p!='N') { ++ free(data->modulus); ++ data->modulus = NULL; + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA); ++ } + ++p; + if(*p++>0x80) + { +-- +2.42.0 + +From 50f0985f6343eeac4044661d56807ee9286db42c Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Sun, 8 Oct 2023 19:08:39 +0200 +Subject: [PATCH] entersafe: Avoid buffer overflow during keygen + +Thanks oss-fuzz + +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=63104 +--- + src/libopensc/card-entersafe.c | 54 ++++++++++++++++++++-------------- + 1 file changed, 32 insertions(+), 22 deletions(-) + +diff --git a/src/libopensc/card-entersafe.c b/src/libopensc/card-entersafe.c +index 168894abd..feb9ebe18 100644 +--- a/src/libopensc/card-entersafe.c ++++ b/src/libopensc/card-entersafe.c +@@ -1374,8 +1374,9 @@ static int entersafe_gen_key(sc_card_t *card, sc_entersafe_gen_key_data *data) + int r; + size_t len = data->key_length >> 3; + sc_apdu_t apdu; +- u8 rbuf[300]; ++ u8 rbuf[300] = {0}; + u8 sbuf[4],*p; ++ size_t plen = 0; + + SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); + +@@ -1418,40 +1419,49 @@ static int entersafe_gen_key(sc_card_t *card, sc_entersafe_gen_key_data *data) + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + LOG_TEST_RET(card->ctx, sc_check_sw(card,apdu.sw1,apdu.sw2),"EnterSafe get pukey failed"); + +- data->modulus = malloc(len); +- if (!data->modulus) +- SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_OUT_OF_MEMORY); +- +- p=rbuf; +- if (*p!='E') { +- free(data->modulus); +- data->modulus = NULL; ++ p = rbuf; ++ plen = apdu.resplen; ++ if (*p != 'E') { + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA); + } +- p+=2+p[1]; ++ if ((size_t)(p - rbuf) + 2 + p[1] >= plen) { ++ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA); ++ } ++ p += 2 + p[1]; + /* N */ +- if (*p!='N') { +- free(data->modulus); +- data->modulus = NULL; ++ if (*p != 'N') { ++ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA); ++ } ++ if ((size_t)(p - rbuf) + 2 >= plen) { + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA); + } + ++p; +- if(*p++>0x80) ++ if (*p++ > 0x80) + { +- u8 len_bytes=(*(p-1))&0x0f; +- size_t module_len=0; +- while(len_bytes!=0) ++ u8 len_bytes = (*(p - 1)) & 0x0f; ++ size_t module_len = 0; ++ if ((size_t)(p - rbuf) + len_bytes >= plen) { ++ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA); ++ } ++ while (len_bytes != 0) + { +- module_len=module_len<<8; +- module_len+=*p++; ++ module_len = module_len << 8; ++ module_len += *p++; + --len_bytes; + } + } + +- entersafe_reverse_buffer(p,len); +- memcpy(data->modulus,p,len); ++ if ((p - rbuf) + len >= plen) { ++ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA); ++ } + +- SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_SUCCESS); ++ data->modulus = malloc(len); ++ if (!data->modulus) ++ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_OUT_OF_MEMORY); ++ entersafe_reverse_buffer(p, len); ++ memcpy(data->modulus, p, len); ++ ++ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS); + } + + static int entersafe_get_serialnr(sc_card_t *card, sc_serial_number_t *serial) +-- +2.42.0 + diff --git a/opensc.spec b/opensc.spec index e8bf6d6..e112ce7 100644 --- a/opensc.spec +++ b/opensc.spec @@ -60,6 +60,24 @@ Patch20: %{name}-0.23.0-cache-offsets.patch # https://github.com/OpenSC/OpenSC/commit/868f76fb31255fd3fdacfc3e476452efeb61c3e7 # https://github.com/OpenSC/OpenSC/commit/80cc5d30635f0d2c92b5099c0f9dc680d0ffce2f Patch21: %{name}-0.23.0-pin-bypass.patch +# https://github.com/OpenSC/OpenSC/commit/245efe608d083fd4e4ec96793fdefd218e26fde7 +# https://github.com/OpenSC/OpenSC/commit/440ca666eff10cc7011901252d20f3fc4ea23651 +# https://github.com/OpenSC/OpenSC/commit/41d61da8481582e12710b5858f8b635e0a71ab5e +# https://github.com/OpenSC/OpenSC/commit/88880db0307a07e33cf2e1592bb029e9c170dfea +# https://github.com/OpenSC/OpenSC/commit/638a5007a5d240d6fa901aa822cfeef94fe36e85 +# https://github.com/OpenSC/OpenSC/commit/c449a181a6988cc1e8dc8764d23574e48cdc3fa6 +# https://github.com/OpenSC/OpenSC/commit/5631e9843c832a99769def85b7b9b68b4e3e3959 +# https://github.com/OpenSC/OpenSC/commit/e7f81d86dcdc751f4737f4b29a99bfc54d29c5c9 +# https://github.com/OpenSC/OpenSC/commit/df5a176bfdf8c52ba89c7fef1f82f6f3b9312bc1 +# https://github.com/OpenSC/OpenSC/commit/578aed8391ef117ca64a9e0cba8e5c264368a0ec +# https://github.com/OpenSC/OpenSC/commit/013a807492568bf9907cfb3df41f130ac83c7b9 +# https://github.com/OpenSC/OpenSC/commit/fc2c20c3f895569eeb58328bb882aec07325d3b +# https://github.com/OpenSC/OpenSC/commit/3b9129bd3cfc6ac57d5554e015c3df85f5076dc +# https://github.com/OpenSC/OpenSC/commit/bda61d0d276dc98b9d1d1e6810bbd21d19e3859 +# https://github.com/OpenSC/OpenSC/commit/a4921ab23fd0853f327517636c50de947548161 +# https://github.com/OpenSC/OpenSC/commit/085994384a7171c5c68f6718d9db10ed77c5af1 +# https://github.com/OpenSC/OpenSC/commit/0f0985f6343eeac4044661d56807ee9286db42c +Patch22: %{name}-0.23.0-pkcs15init.patch BuildRequires: pcsc-lite-devel BuildRequires: readline-devel @@ -103,6 +121,7 @@ every software/card that does so, too. %patch19 -p1 -b .reader-removal %patch20 -p1 -b .cache-offsets %patch21 -p1 -b .pin-bypass +%patch22 -p1 -b .pkcs15init cp -p src/pkcs15init/README ./README.pkcs15init cp -p src/scconf/README.scconf .