From cccdfc46b10184d1eea62d07fe2b06240b7fafbc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Veronika=20Hanul=C3=ADkov=C3=A1?= <vhanulik@redhat.com>
Date: Fri, 12 Jul 2024 13:16:56 +0200
Subject: [PATCH] card-dnie: Check APDU response length and ASN1 lengths

Thanks Matteo Marini for report
https://github.com/OpenSC/OpenSC/security/advisories/GHSA-p3mx-7472-h3j8

fuzz_pkcs15_decode/10, fuzz_pkcs15_encode/12

CVE: CVE-2024-45616
Upstream-Status: Backport [https://github.com/OpenSC/OpenSC/commit/cccdfc46b10184d1eea62d07fe2b06240b7fafbc]

Signed-off-by: Zhang Peng <peng.zhang1.cn@windriver.com>
---
 src/libopensc/asn1.c      | 4 +++-
 src/libopensc/card-dnie.c | 8 ++++++--
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/src/libopensc/asn1.c b/src/libopensc/asn1.c
index 08ef56149c..548263a2da 100644
--- a/src/libopensc/asn1.c
+++ b/src/libopensc/asn1.c
@@ -68,7 +68,7 @@ int sc_asn1_read_tag(const u8 ** buf, size_t buflen, unsigned int *cla_out,
 
 	*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, size_t buflen, unsigned int *cla_out,
 	 */
 	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) {
diff --git a/src/libopensc/card-dnie.c b/src/libopensc/card-dnie.c
index 2c36ddf5c..25c15b2b7 100644
--- a/src/libopensc/card-dnie.c
+++ b/src/libopensc/card-dnie.c
@@ -1185,12 +1185,16 @@ static int dnie_compose_and_send_apdu(sc_card_t *card, const u8 *path, size_t pa
 
 	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);
 }
@@ -1948,7 +1952,7 @@ static int dnie_process_fci(struct sc_card *card,
 	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);
--
2.34.1
