File opensc-0_19_0-CVE-2021-42782.patch of Package opensc.26104

diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c
index 4862592..84f9b81 100644
--- a/src/libopensc/card-cardos.c
+++ b/src/libopensc/card-cardos.c
@@ -134,7 +134,7 @@ static int cardos_have_2048bit_package(sc_card_t *card)
 	sc_apdu_t apdu;
         u8        rbuf[SC_MAX_APDU_BUFFER_SIZE];
         int       r;
-	const u8  *p = rbuf, *q;
+	const u8  *p = rbuf, *q, *pp;
 	size_t    len, tlen = 0, ilen = 0;
 
 	sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x88);
@@ -150,10 +150,10 @@ static int cardos_have_2048bit_package(sc_card_t *card)
 		return 0;
 
 	while (len != 0) {
-		p = sc_asn1_find_tag(card->ctx, p, len, 0xe1, &tlen);
-		if (p == NULL)
+		pp = sc_asn1_find_tag(card->ctx, p, len, 0xe1, &tlen);
+		if (pp == NULL)
 			return 0;
-		q = sc_asn1_find_tag(card->ctx, p, tlen, 0x01, &ilen);
+		q = sc_asn1_find_tag(card->ctx, pp, tlen, 0x01, &ilen);
 		if (q == NULL || ilen != 4)
 			return 0;
 		if (q[0] == 0x1c)
diff --git a/src/libopensc/card-iasecc.c b/src/libopensc/card-iasecc.c
index dcd4a83..6829171 100644
--- a/src/libopensc/card-iasecc.c
+++ b/src/libopensc/card-iasecc.c
@@ -1109,7 +1109,7 @@ iasecc_process_fci(struct sc_card *card, struct sc_file *file,
 	else
 		acls = sc_asn1_find_tag(ctx, buf, buflen, IASECC_DOCP_TAG_ACLS_CONTACT, &taglen);
 
-	if (!acls)   {
+	if (!acls || taglen < 7)   {
 		sc_log(ctx,
 		       "ACLs not found in data(%"SC_FORMAT_LEN_SIZE_T"u) %s",
 		       buflen, sc_dump_hex(buf, buflen));
diff --git a/src/libopensc/card-piv.c b/src/libopensc/card-piv.c
index 61acedc..a97e6ff 100644
--- a/src/libopensc/card-piv.c
+++ b/src/libopensc/card-piv.c
@@ -669,14 +669,12 @@ static int piv_generate_key(sc_card_t *card,
 		const u8 *cp;
 		keydata->exponent = 0;
 
-		/* expected tag is 7f49.  */
-		/* we will whatever tag is present */
-
 		cp = rbuf;
 		in_len = rbuflen;
 
+		/* expected tag is 0x7f49,returned as cla_out == 0x60 and tag_out = 0x1F49 */
 		r = sc_asn1_read_tag(&cp, rbuflen, &cla_out, &tag_out, &in_len);
-		if (cp == NULL) {
+		if (cp == NULL || in_len == 0 || cla_out != 0x60 || tag_out != 0x1f49) {
 			r = SC_ERROR_ASN1_OBJECT_NOT_FOUND;
 		}
 		if (r != SC_SUCCESS) {
@@ -1090,7 +1088,7 @@ piv_cache_internal_data(sc_card_t *card, int enumtag)
 			priv->obj_cache[enumtag].obj_len,
 			0x53, &bodylen);
 
-	if (body == NULL)
+	if (body == NULL || priv->obj_cache[enumtag].obj_data[0] != 0x53)
 		LOG_FUNC_RETURN(card->ctx, SC_ERROR_OBJECT_NOT_VALID);
 
 	/* get the certificate out */
@@ -1660,7 +1658,7 @@ static int piv_general_mutual_authenticate(sc_card_t *card,
 	/* Remove the encompassing outer TLV of 0x7C and get the data */
 	body = sc_asn1_find_tag(card->ctx, rbuf,
 		r, 0x7C, &body_len);
-	if (!body) {
+	if (!body || rbuf[0] != 0x7C) {
 		sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Invalid Witness Data response of NULL\n");
 		r =  SC_ERROR_INVALID_DATA;
 		goto err;
@@ -1784,7 +1782,7 @@ static int piv_general_mutual_authenticate(sc_card_t *card,
 	/* Remove the encompassing outer TLV of 0x7C and get the data */
 	body = sc_asn1_find_tag(card->ctx, rbuf,
 		r, 0x7C, &body_len);
-	if(!body) {
+	if(!body || rbuf[0] != 0x7C) {
 		sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not find outer tag 0x7C in response");
 		r =  SC_ERROR_INVALID_DATA;
 		goto err;
@@ -1948,7 +1946,7 @@ static int piv_general_external_authenticate(sc_card_t *card,
 	/* Remove the encompassing outer TLV of 0x7C and get the data */
 	body = sc_asn1_find_tag(card->ctx, rbuf,
 		r, 0x7C, &body_len);
-	if (!body) {
+	if (!body || rbuf[0] != 0x7C) {
 		sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Invalid Challenge Data response of NULL\n");
 		r =  SC_ERROR_INVALID_DATA;
 		goto err;
@@ -2108,7 +2106,7 @@ piv_get_serial_nr_from_CHUI(sc_card_t* card, sc_serial_number_t* serial)
 	r = SC_ERROR_INTERNAL;
 	if (rbuflen != 0) {
 		body = sc_asn1_find_tag(card->ctx, rbuf, rbuflen, 0x53, &bodylen); /* Pass the outer wrapper asn1 */
-		if (body != NULL && bodylen != 0) {
+		if (body != NULL && bodylen != 0 && rbuf[0] == 0x53) {
 			fascn = sc_asn1_find_tag(card->ctx, body, bodylen, 0x30, &fascnlen); /* Find the FASC-N data */
 			guid = sc_asn1_find_tag(card->ctx, body, bodylen, 0x34, &guidlen);
 
@@ -2323,10 +2321,10 @@ static int piv_validate_general_authentication(sc_card_t *card,
 	piv_private_data_t * priv = PIV_DATA(card);
 	int r;
 	u8 *p;
-	const u8 *tag;
+	const unsigned char *p2;
 	size_t taglen;
-	const u8 *body;
 	size_t bodylen;
+	unsigned int cla, tag;
 	unsigned int real_alg_id;
 
 	u8 sbuf[4096]; /* needs work. for 3072 keys, needs 384+10 or so */
@@ -2369,20 +2367,28 @@ static int piv_validate_general_authentication(sc_card_t *card,
 
 	r = piv_general_io(card, 0x87, real_alg_id, priv->key_ref,
 			sbuf, p - sbuf, &rbuf, &rbuflen);
+       if (r < 0)
+               goto err;
 
-	if (r >= 0) {
-		body = sc_asn1_find_tag(card->ctx, rbuf, rbuflen, 0x7c, &bodylen);
-		if (body) {
-			tag = sc_asn1_find_tag(card->ctx, body,  bodylen, 0x82, &taglen);
-			if (tag) {
-				memcpy(out, tag, taglen);
-				r = taglen;
-			} else
-				r = SC_ERROR_INVALID_DATA;
-		} else
-			r = SC_ERROR_INVALID_DATA;
+       p2= rbuf;
+       r= sc_asn1_read_tag(&p2, r, &cla, &tag, &bodylen);
+       if (p2 == NULL || r < 0 || bodylen == 0 || (cla|tag) != 0x7C) {
+               LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA, "Can't find 0x7C");
+        }
+
+       r = sc_asn1_read_tag(&p2, bodylen, &cla, &tag, &taglen);
+       if (p2 == NULL || r < 0 || taglen == 0 || (cla|tag) != 0x82) {
+               LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA, "Can't find 0x82");
 	}
 
+       if (taglen > outlen) {
+               LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA, "data read longer then buffer");
+       }
+
+       memcpy(out, p2, taglen);
+       r = taglen;
+
+err:
 	if (rbuf)
 		free(rbuf);
 
@@ -2400,19 +2406,19 @@ piv_compute_signature(sc_card_t *card, const u8 * data, size_t datalen,
 	size_t nLen;
 	u8 rbuf[128]; /* For EC conversions  384 will fit */
 	size_t rbuflen = sizeof(rbuf);
-	const u8 * body;
-	size_t bodylen;
-	const u8 * tag;
-	size_t taglen;
+       const unsigned char *pseq, *pint, *ptemp, *pend;
+       unsigned int cla, tag;
+       size_t seqlen;
+       size_t intlen;
+       size_t templen;
 
 	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
 
 	/* The PIV returns a DER SEQUENCE{INTEGER, INTEGER}
-	 * Which may have leading 00 to force positive
-	 * TODO: -DEE should check if PKCS15 want the same
-	 * But PKCS11 just wants 2* filed_length in bytes
+	 * Which may have leading 00 to force apositive integer
+	 * But PKCS11 just wants 2* field_length in bytes
 	 * So we have to strip out the integers
-	 * if present and pad on left if too short.
+	 * and pad on left if too short.
 	 */
 
 	if (priv->alg_id == 0x11 || priv->alg_id == 0x14 ) {
@@ -2431,32 +2437,34 @@ piv_compute_signature(sc_card_t *card, const u8 * data, size_t datalen,
 			goto err;
 
 		if ( r >= 0) {
-			body = sc_asn1_find_tag(card->ctx, rbuf, rbuflen, 0x30, &bodylen);
-
-			for (i = 0; i<2; i++) {
-				if (body) {
-					tag = sc_asn1_find_tag(card->ctx, body,  bodylen, 0x02, &taglen);
-					if (tag) {
-						bodylen -= taglen - (tag - body);
-						body = tag + taglen;
-
-						if (taglen > nLen) { /* drop leading 00 if present */
-							if (*tag != 0x00) {
-								r = SC_ERROR_INVALID_DATA;
-								goto err;
-							}
-							tag++;
-							taglen--;
-						}
-						memcpy(out + nLen*i + nLen - taglen , tag, taglen);
-					} else {
+               pseq = rbuf;
+               r = sc_asn1_read_tag(&pseq, r, &cla, &tag, &seqlen);
+               if (pseq == NULL || r < 0 || seqlen == 0 || (cla|tag) != 0x30)
+                       LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA, "Can't find 0x30");
+
+               pint = pseq;
+               pend = pseq + seqlen;
+              for (i = 0; i < 2; i++) {
+                       r = sc_asn1_read_tag(&pint, (pend - pint), &cla, &tag, &intlen);
+                       if (pint == NULL || r < 0 || intlen == 0 || (cla|tag) != 0x02)
+                               LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA, "Can't find 0x02");
+                       if (intlen> nLen + 1)
+                               LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_DATA,"Signature too long");
+
+                      ptemp= pint;
+                       templen = intlen;
+                      if (intlen> nLen) { /* drop leading 00 if present */
+                               if (*ptemp!= 0x00) {
+                                       LOG_TEST_GOTO_ERR(card->ctx,SC_ERROR_INVALID_DATA,"Signaturetoolong");
 						r = SC_ERROR_INVALID_DATA;
 						goto err;
 					}
-				} else  {
-					r = SC_ERROR_INVALID_DATA;
-					goto err;
+                               ptemp++;
+                               templen--;
 				}
+                       memcpy(out + nLen*i + nLen - templen , ptemp, templen);
+                       pint += intlen; /* next integer */
+
 			}
 			r = 2 * nLen;
 		}
diff --git a/src/libopensc/pkcs15-coolkey.c b/src/libopensc/pkcs15-coolkey.c
index 09618fe..3005785 100644
--- a/src/libopensc/pkcs15-coolkey.c
+++ b/src/libopensc/pkcs15-coolkey.c
@@ -428,7 +428,8 @@ coolkey_get_public_key_from_certificate(sc_pkcs15_card_t *p15card, sc_cardctl_co
 	sc_pkcs15_pubkey_t *key = NULL;
 	int r;
 
-	cert_info.value.value = NULL;
+	memset(&cert_info, 0, sizeof(cert_info));
+
 	r = coolkey_get_certificate(p15card->card, obj, &cert_info.value);
 	if (r < 0) {
 		goto fail;
diff --git a/src/libopensc/pkcs15-tcos.c b/src/libopensc/pkcs15-tcos.c
index 547de12..642c2b5 100644
--- a/src/libopensc/pkcs15-tcos.c
+++ b/src/libopensc/pkcs15-tcos.c
@@ -152,7 +152,7 @@ static int insert_key(
 			sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"No EF_KEYD-Record found\n");
 			return 1;
 		}
-		for(i=0;i<r;i+=2+buf[i+1]){
+		for(i=0;i+1<r;i+=2+buf[i+1]){
 			if(buf[i]==0xB6) can_sign++;
 			if(buf[i]==0xB8) can_crypt++;
 		}
openSUSE Build Service is sponsored by