225 lines
7.9 KiB
Diff
225 lines
7.9 KiB
Diff
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.24.0/src/libopensc/card-cardos.c
|
|
===================================================================
|
|
--- opensc-0.24.0.orig/src/libopensc/card-cardos.c
|
|
+++ opensc-0.24.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.24.0/src/libopensc/card-cac1.c
|
|
===================================================================
|
|
--- opensc-0.24.0.orig/src/libopensc/card-cac1.c
|
|
+++ opensc-0.24.0/src/libopensc/card-cac1.c
|
|
@@ -92,12 +92,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.24.0/src/libopensc/card-oberthur.c
|
|
===================================================================
|
|
--- opensc-0.24.0.orig/src/libopensc/card-oberthur.c
|
|
+++ opensc-0.24.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.24.0/src/libopensc/card-gids.c
|
|
===================================================================
|
|
--- opensc-0.24.0.orig/src/libopensc/card-gids.c
|
|
+++ opensc-0.24.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.24.0/src/libopensc/asn1.c
|
|
===================================================================
|
|
--- opensc-0.24.0.orig/src/libopensc/asn1.c
|
|
+++ opensc-0.24.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.24.0/src/libopensc/card-dnie.c
|
|
===================================================================
|
|
--- opensc-0.24.0.orig/src/libopensc/card-dnie.c
|
|
+++ opensc-0.24.0/src/libopensc/card-dnie.c
|
|
@@ -1171,12 +1171,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);
|
|
}
|
|
@@ -1934,7 +1938,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.24.0/src/libopensc/muscle.c
|
|
===================================================================
|
|
--- opensc-0.24.0.orig/src/libopensc/muscle.c
|
|
+++ opensc-0.24.0/src/libopensc/muscle.c
|
|
@@ -112,13 +112,15 @@ int msc_partial_read_object(sc_card_t *c
|
|
|
|
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;
|
|
}
|
|
@@ -171,7 +173,7 @@ int msc_create_object(sc_card_t *card, m
|
|
apdu.sw1, apdu.sw2);
|
|
}
|
|
msc_zero_object(card, objectId, objectSize);
|
|
- return objectSize;
|
|
+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_UNKNOWN_DATA_RECEIVED);
|
|
}
|
|
|
|
/* Update up to MSC_MAX_READ - 9 bytes */
|
|
Index: opensc-0.24.0/src/libopensc/card-entersafe.c
|
|
===================================================================
|
|
--- opensc-0.24.0.orig/src/libopensc/card-entersafe.c
|
|
+++ opensc-0.24.0/src/libopensc/card-entersafe.c
|
|
@@ -1482,7 +1482,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);
|