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++;
}