File opensc-CVE-2024-45619.patch of Package opensc.35665
commit f01bfbd19b9c8243a40f7f17d554fe0eb9e89d0d
Author: Veronika HanulĂková <vhanulik@redhat.com>
Date: Tue Jul 16 14:22:02 2024 +0200
pkcs15-tcos: Check number of read bytes for cert
Thanks Matteo Marini for report
https://github.com/OpenSC/OpenSC/security/advisories/GHSA-p3mx-7472-h3j8
fuzz_pkcs11/15
Index: opensc-0.13.0/src/libopensc/pkcs15-tcos.c
===================================================================
--- opensc-0.13.0.orig/src/libopensc/pkcs15-tcos.c
+++ opensc-0.13.0/src/libopensc/pkcs15-tcos.c
@@ -46,6 +46,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));
@@ -63,11 +64,17 @@ static int insert_cert(
"Select(%s) failed\n", path);
return 1;
}
- if(sc_read_binary(card, 0, cert, sizeof(cert), 0)<0){
+ r = sc_read_binary(card, 0, cert, sizeof(cert), 0);
+ if (r < 0) {
sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
"ReadBinary(%s) failed\n", path);
return 2;
}
+ 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_debug(ctx, SC_LOG_DEBUG_NORMAL,
"Invalid Cert: %02X:%02X:...\n", cert[0], cert[1]);
@@ -76,6 +83,10 @@ static int insert_cert(
/* 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 ((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 {
Index: opensc-0.13.0/src/libopensc/pkcs15-gemsafeV1.c
===================================================================
--- opensc-0.13.0.orig/src/libopensc/pkcs15-gemsafeV1.c
+++ opensc-0.13.0/src/libopensc/pkcs15-gemsafeV1.c
@@ -131,6 +131,7 @@ static int gemsafe_get_cert_len(sc_card_
unsigned int block=0;
int found = 0;
unsigned int offset=0, index_local, i=0;
+ int read_len;
r = sc_select_file(card, path, &file);
if (r < 0)
@@ -138,9 +139,11 @@ static int gemsafe_get_cert_len(sc_card_
/* Apparently, the Applet max read "quanta" is 248 bytes */
/* Initial read */
- r = sc_read_binary(card, offset, ibuf, 248, 0);
- if (r < 0)
- return 0;
+ read_len = sc_read_binary(card, offset, ibuf, 248, 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!)
@@ -163,7 +166,7 @@ static int gemsafe_get_cert_len(sc_card_
* the key_ref in the opensc.conf with flag = n.
*/
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) {
*key_ref = ibuf[ind+4];
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Using key_ref %d found at offset %d\n",
@@ -192,9 +195,16 @@ static int gemsafe_get_cert_len(sc_card_
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "%s: Could not read cert object\n", fn_name);
return 0;
}
+ if (r == 0)
+ break;
+ read_len += r;
}
}
+ if ((size_t)read_len < objlen) {
+ sc_log(card->ctx, "Could not read cert object");
+ return SC_ERROR_INTERNAL;
+ }
index_local = block*248 + i;
Index: opensc-0.13.0/src/pkcs15init/pkcs15-setcos.c
===================================================================
--- opensc-0.13.0.orig/src/pkcs15init/pkcs15-setcos.c
+++ opensc-0.13.0/src/pkcs15init/pkcs15-setcos.c
@@ -486,13 +486,16 @@ setcos_generate_key(struct sc_profile *p
r = sc_card_ctl(p15card->card, SC_CARDCTL_SETCOS_GETDATA, &data_obj);
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, 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_debug(ctx, SC_LOG_DEBUG_NORMAL, "key-size from card[%i] does not match[%i]\n",
keybits, key_info->modulus_length);
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, 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.13.0/src/pkcs15init/pkcs15-sc-hsm.c
===================================================================
--- opensc-0.13.0.orig/src/pkcs15init/pkcs15-sc-hsm.c
+++ opensc-0.13.0/src/pkcs15init/pkcs15-sc-hsm.c
@@ -211,7 +211,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;
}