commit 1d3b410e06d33cfc4c70e8a25386e456cfbd7bd1
Author: Veronika Hanulíková <vhanulik@redhat.com>
Date:   Thu Jul 11 15:27:19 2024 +0200

    cardos: Fix uninitialized values
    
    Thanks Matteo Marini for report
    https://github.com/OpenSC/OpenSC/security/advisories/GHSA-p3mx-7472-h3j8
    
    fuzz_card/2

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