File opensc-fixed-out-of-bounds-reads.patch of Package opensc
From 8fe377e93b4b56060e5bbfb6f3142ceaeca744fa Mon Sep 17 00:00:00 2001
From: Frank Morgner <frankmorgner@gmail.com>
Date: Fri, 25 May 2018 14:54:47 +0200
Subject: [PATCH] fixed out of bounds reads
Thanks to Eric Sesterhenn from X41 D-SEC GmbH
for reporting and suggesting security fixes.
---
src/libopensc/asn1.c | 1 +
src/libopensc/card-asepcos.c | 2 +-
src/libopensc/card-authentic.c | 5 ++++-
src/libopensc/card-cac.c | 9 +++++++--
src/libopensc/card-coolkey.c | 2 +-
src/libopensc/card-entersafe.c | 8 +++++---
src/libopensc/card-epass2003.c | 35 ++++++++++++++++++----------------
src/libopensc/card-gpk.c | 3 +++
src/libopensc/card-iasecc.c | 2 +-
src/libopensc/card-oberthur.c | 7 +++++++
src/libopensc/card-openpgp.c | 6 ++++++
src/libopensc/card-piv.c | 9 +++++----
src/libopensc/card-rtecp.c | 2 +-
src/libopensc/card-setcos.c | 18 +++++++++++++++--
src/libopensc/ef-gdo.c | 2 +-
src/libopensc/pkcs15-itacns.c | 1 +
src/libopensc/pkcs15-tcos.c | 8 +++++---
src/tools/opensc-tool.c | 21 ++++++++++----------
18 files changed, 95 insertions(+), 46 deletions(-)
Index: opensc-0.13.0/src/libopensc/asn1.c
===================================================================
--- opensc-0.13.0.orig/src/libopensc/asn1.c
+++ opensc-0.13.0/src/libopensc/asn1.c
@@ -96,6 +96,7 @@ int sc_asn1_read_tag(const u8 ** buf, si
len = *p & 0x7f;
if (*p++ & 0x80) {
unsigned int a = 0;
+ left--;
if (len > 4 || len > left)
return SC_ERROR_INVALID_ASN1_OBJECT;
left -= len;
Index: opensc-0.13.0/src/libopensc/card-asepcos.c
===================================================================
--- opensc-0.13.0.orig/src/libopensc/card-asepcos.c
+++ opensc-0.13.0/src/libopensc/card-asepcos.c
@@ -167,7 +167,7 @@ static int asepcos_parse_sec_attr(sc_car
while (len != 0) {
unsigned int amode, tlen = 3;
- if (len < 5 && p[0] != 0x80 && p[1] != 0x01) {
+ if (len < 5 || p[0] != 0x80 || p[1] != 0x01) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "invalid access mode encoding");
return SC_ERROR_INTERNAL;
}
Index: opensc-0.13.0/src/libopensc/card-authentic.c
===================================================================
--- opensc-0.13.0.orig/src/libopensc/card-authentic.c
+++ opensc-0.13.0/src/libopensc/card-authentic.c
@@ -593,6 +593,9 @@ authentic_set_current_files(struct sc_ca
sc_file_dup(&card->cache.current_df, file);
if (cur_df_path.len) {
+ if (cur_df_path.len + card->cache.current_df->path.len > sizeof card->cache.current_df->path.value
+ || cur_df_path.len > sizeof card->cache.current_df->path.value)
+ LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
memcpy(card->cache.current_df->path.value + cur_df_path.len,
card->cache.current_df->path.value,
card->cache.current_df->path.len);
@@ -1086,7 +1089,7 @@ authentic_process_fci(struct sc_card *ca
}
sc_log(ctx, "ACL data(%i):%s", file->sec_attr_len, sc_dump_hex(file->sec_attr, file->sec_attr_len));
- for (ii = 0; ii < file->sec_attr_len / 2; ii++) {
+ for (ii = 0; ii < file->sec_attr_len / 2 && ii < sizeof ops_DF; ii++) {
unsigned char op = file->type == SC_FILE_TYPE_DF ? ops_DF[ii] : ops_EF[ii];
unsigned char acl = *(file->sec_attr + ii*2);
unsigned char cred_id = *(file->sec_attr + ii*2 + 1);
Index: opensc-0.13.0/src/libopensc/card-entersafe.c
===================================================================
--- opensc-0.13.0.orig/src/libopensc/card-entersafe.c
+++ opensc-0.13.0/src/libopensc/card-entersafe.c
@@ -1322,13 +1322,15 @@ static int entersafe_gen_key(sc_card_t *
data->modulus = malloc(len);
if (!data->modulus)
- SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_OUT_OF_MEMORY);
+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_OUT_OF_MEMORY);
p=rbuf;
- assert(*p=='E');
+ if (*p!='E')
+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
p+=2+p[1];
/* N */
- assert(*p=='N');
+ if (*p!='N')
+ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
++p;
if(*p++>0x80)
{
Index: opensc-0.13.0/src/libopensc/card-gpk.c
===================================================================
--- opensc-0.13.0.orig/src/libopensc/card-gpk.c
+++ opensc-0.13.0/src/libopensc/card-gpk.c
@@ -448,6 +448,9 @@ gpk_parse_fileinfo(sc_card_t *card,
if (sp[0] == 0x85) {
unsigned int ac[3], n;
+ if (sp + 11 + 2*3 >= end)
+ break;
+
file->id = (sp[4] << 8) | sp[5];
file->size = (sp[8] << 8) | sp[9];
file->record_length = sp[7];
Index: opensc-0.13.0/src/libopensc/card-iasecc.c
===================================================================
--- opensc-0.13.0.orig/src/libopensc/card-iasecc.c
+++ opensc-0.13.0/src/libopensc/card-iasecc.c
@@ -2474,7 +2474,7 @@ iasecc_get_serialnr(struct sc_card *card
if (card->type == SC_CARD_TYPE_IASECC_SAGEM) {
/* 5A 0A 92 50 00 20 10 10 25 00 01 3F */
/* 00 02 01 01 02 50 00 13 */
- for (ii=0; ii < rbuf[1] - offs; ii++)
+ for (ii=0; (ii < rbuf[1] - offs) && (ii + offs + 2 < sizeof(rbuf)); ii++)
*(card->serialnr.value + ii) = ((rbuf[ii + offs + 1] & 0x0F) << 4)
+ ((rbuf[ii + offs + 2] & 0xF0) >> 4) ;
card->serialnr.len = ii;
Index: opensc-0.13.0/src/libopensc/card-oberthur.c
===================================================================
--- opensc-0.13.0.orig/src/libopensc/card-oberthur.c
+++ opensc-0.13.0/src/libopensc/card-oberthur.c
@@ -495,6 +495,9 @@ auth_select_file(struct sc_card *card, c
assert(card != NULL && in_path != NULL);
memcpy(&path, in_path, sizeof(struct sc_path));
+
+ if (!auth_current_df)
+ return SC_ERROR_OBJECT_NOT_FOUND;
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "in_path; type=%d, path=%s, out %p\n",
in_path->type, sc_print_path(in_path), file_out);
@@ -2126,6 +2129,10 @@ auth_read_binary(struct sc_card *card, u
char debug_buf[2048];
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
+
+ if (!auth_current_ef)
+ SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS, "Invalid auth_current_ef");
+
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"offset %i; size %i; flags 0x%lX\n", offset, count, flags);
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"last selected : magic %X; ef %X\n",
auth_current_ef->magic, auth_current_ef->ef_structure);
Index: opensc-0.13.0/src/libopensc/card-openpgp.c
===================================================================
--- opensc-0.13.0.orig/src/libopensc/card-openpgp.c
+++ opensc-0.13.0/src/libopensc/card-openpgp.c
@@ -763,6 +763,9 @@ pgp_enumerate_blob(sc_card_t *card, stru
const u8 *data = in;
struct blob *new;
+ if (!in)
+ return SC_ERROR_OBJECT_NOT_VALID;
+
r = sc_asn1_read_tag(&data, blob->len - (in - blob->data),
&cla, &tag, &len);
if (r < 0) {
@@ -771,6 +774,9 @@ pgp_enumerate_blob(sc_card_t *card, stru
return SC_ERROR_OBJECT_NOT_VALID;
}
+ if (data + len > blob->data + blob->len)
+ return SC_ERROR_OBJECT_NOT_VALID;
+
/* undo ASN1's split of tag & class */
for (tmptag = tag; tmptag > 0x0FF; tmptag >>= 8) {
cla <<= 8;
Index: opensc-0.13.0/src/libopensc/card-rtecp.c
===================================================================
--- opensc-0.13.0.orig/src/libopensc/card-rtecp.c
+++ opensc-0.13.0/src/libopensc/card-rtecp.c
@@ -273,7 +273,7 @@ static int rtecp_select_file(sc_card_t *
set_acl_from_sec_attr(card, file);
else
r = SC_ERROR_UNKNOWN_DATA_RECEIVED;
- if (r)
+ if (r && !file_out)
sc_file_free(file);
else
{
Index: opensc-0.13.0/src/libopensc/card-setcos.c
===================================================================
--- opensc-0.13.0.orig/src/libopensc/card-setcos.c
+++ opensc-0.13.0/src/libopensc/card-setcos.c
@@ -789,6 +789,8 @@ static void parse_sec_attr_44(sc_file_t
/* Check all sub-AC definitions whitin the total AC */
while (len > 1) { /* minimum length = 2 */
int iACLen = buf[iOffset] & 0x0F;
+ if ((size_t) iACLen > len)
+ break;
iPinCount = -1; /* default no pin required */
iMethod = SC_AC_NONE; /* default no authentication required */
@@ -806,7 +808,10 @@ static void parse_sec_attr_44(sc_file_t
/* Get KeyNumber if available */
if(iKeyLen) {
- int iSC = buf[iOffset+iACLen];
+ int iSC;
+ if (len < 1+iACLen)
+ break;
+ iSC = buf[iOffset+iACLen];
switch( (iSC>>5) & 0x03 ){
case 0:
@@ -825,11 +830,15 @@ static void parse_sec_attr_44(sc_file_t
/* Get PinNumber if available */
if (iACLen > (1+iParmLen+iKeyLen)) { /* check via total length if pin is present */
+ if (len < 1+1+1+iParmLen)
+ break;
iKeyRef = buf[iOffset+1+1+iParmLen]; /* PTL + AM-header + parameter-bytes */
iMethod = SC_AC_CHV;
}
/* Convert SETCOS command to OpenSC command group */
+ if (len < 1+2)
+ break;
switch(buf[iOffset+2]){
case 0x2A: /* crypto operation */
iOperation = SC_AC_OP_CRYPTO;
@@ -863,7 +872,10 @@ static void parse_sec_attr_44(sc_file_t
iPinCount = iACLen - 1;
if (buf[iOffset] & 0x20) {
- int iSC = buf[iOffset + iACLen];
+ int iSC;
+ if (len < 1 + iACLen)
+ break;
+ iSC = buf[iOffset + iACLen];
switch( (iSC>>5) & 0x03 ) {
case 0:
@@ -884,6 +896,8 @@ static void parse_sec_attr_44(sc_file_t
/* Pin present ? */
if ( iPinCount > 0 ) {
+ if (len < 1 + 2)
+ break;
iKeyRef = buf[iOffset + 2]; /* pin ref */
iMethod = SC_AC_CHV;
}
Index: opensc-0.13.0/src/libopensc/pkcs15-itacns.c
===================================================================
--- opensc-0.13.0.orig/src/libopensc/pkcs15-itacns.c
+++ opensc-0.13.0/src/libopensc/pkcs15-itacns.c
@@ -542,6 +542,7 @@ static int itacns_add_data_files(sc_pkcs
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,
"Could not read EF_DatiPersonali: "
"keeping generic card name");
+ return SC_SUCCESS;
}
{
Index: opensc-0.13.0/src/libopensc/pkcs15-tcos.c
===================================================================
--- opensc-0.13.0.orig/src/libopensc/pkcs15-tcos.c
+++ opensc-0.13.0/src/libopensc/pkcs15-tcos.c
@@ -128,7 +128,7 @@ static int insert_key(
int i, rec_no=0;
if(prkey_info.path.len>=2) prkey_info.path.len-=2;
sc_append_file_id(&prkey_info.path, 0x5349);
- if(sc_select_file(card, &prkey_info.path, NULL)!=SC_SUCCESS){
+ if(sc_select_file(card, &prkey_info.path, NULL)!=SC_SUCCESS || !f->prop_attr){
sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
"Select(%s) failed\n",
sc_print_path(&prkey_info.path));
@@ -153,7 +153,8 @@ static int insert_key(
if(buf[i]==0xB8) can_crypt++;
}
} else {
- if(sc_select_file(card, &prkey_info.path, &f)!=SC_SUCCESS){
+ if(sc_select_file(card, &prkey_info.path, &f)!=SC_SUCCESS
+ || !f->prop_attr || f->prop_attr_len < 2){
sc_debug(ctx, SC_LOG_DEBUG_NORMAL,
"Select(%s) failed\n",
sc_print_path(&prkey_info.path));
@@ -240,7 +241,8 @@ static int insert_pin(
return 1;
}
} else {
- if(sc_select_file(card, &pin_info.path, &f)!=SC_SUCCESS){
+ if(sc_select_file(card, &pin_info.path, &f)!=SC_SUCCESS
+ || !f->prop_attr || f->prop_attr_len < 4){
sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"Select(%s) failed\n", path);
return 1;
}
Index: opensc-0.13.0/src/tools/opensc-tool.c
===================================================================
--- opensc-0.13.0.orig/src/tools/opensc-tool.c
+++ opensc-0.13.0/src/tools/opensc-tool.c
@@ -445,7 +445,7 @@ static int enum_dir(sc_path_t path, int
{
sc_file_t *file;
int r, file_type;
- u8 files[SC_MAX_APDU_BUFFER_SIZE];
+ u8 files[SC_MAX_EXT_APDU_BUFFER_SIZE];
r = sc_select_file(card, &path, &file);
if (r) {
@@ -465,15 +465,16 @@ static int enum_dir(sc_path_t path, int
}
if (r == 0) {
printf("Empty directory\n");
- } else
- for (i = 0; i < r/2; i++) {
- sc_path_t tmppath;
+ } else {
+ for (i = 0; i < r/2; i++) {
+ sc_path_t tmppath;
- memset(&tmppath, 0, sizeof(tmppath));
- memcpy(&tmppath, &path, sizeof(path));
- memcpy(tmppath.value + tmppath.len, files + 2*i, 2);
- tmppath.len += 2;
- enum_dir(tmppath, depth + 1);
+ memset(&tmppath, 0, sizeof(tmppath));
+ memcpy(&tmppath, &path, sizeof(path));
+ memcpy(tmppath.value + tmppath.len, files + 2*i, 2);
+ tmppath.len += 2;
+ enum_dir(tmppath, depth + 1);
+ }
}
}
return 0;
Index: opensc-0.13.0/src/libopensc/card-epass2003.c
===================================================================
--- opensc-0.13.0.orig/src/libopensc/card-epass2003.c
+++ opensc-0.13.0/src/libopensc/card-epass2003.c
@@ -579,11 +579,11 @@ construct_mac_tlv(unsigned char *apdu_bu
memcpy(mac_tlv + 2, &mac[mac_len - 16], 8);
}
else {
- unsigned char iv[8] = { 0 };
+ unsigned char iv[EVP_MAX_IV_LENGTH] = { 0 };
unsigned char tmp[8] = { 0 };
des_encrypt_cbc(g_sk_mac, 8, icv, apdu_buf, mac_len, mac);
des_decrypt_cbc(&g_sk_mac[8], 8, iv, &mac[mac_len - 8], 8, tmp);
- memset(iv, 0x00, 8);
+ memset(iv, 0x00, sizeof iv);
des_encrypt_cbc(g_sk_mac, 8, iv, tmp, 8, mac_tlv + 2);
}
@@ -758,7 +758,7 @@ epass2003_sm_wrap_apdu(struct sc_card *c
* SW12(TLV)=0x99|0x02|SW1+SW2
* MAC(TLV)=0x8e|0x08|MAC */
static int
-decrypt_response(unsigned char *in, unsigned char *out, size_t * out_len)
+decrypt_response(unsigned char *in, size_t inlen, unsigned char *out, size_t * out_len)
{
size_t in_len;
size_t i;
@@ -787,6 +787,9 @@ decrypt_response(unsigned char *in, unsi
return -1;
}
+ if (in_len < 2 || i+in_len > inlen || in_len > sizeof plaintext)
+ return -1;
+
/* decrypt */
if (KEY_TYPE_AES == g_smtype)
aes128_decrypt_cbc(g_sk_enc, 16, iv, &in[i], in_len - 1, plaintext);
@@ -817,7 +820,7 @@ epass2003_sm_unwrap_apdu(struct sc_card
r = sc_check_sw(card, sm->sw1, sm->sw2);
if (r == SC_SUCCESS) {
if (g_sm) {
- if (0 != decrypt_response(sm->resp, plain->resp, &len))
+ if (0 != decrypt_response(sm->resp, sm->resplen, plain->resp, &len))
return SC_ERROR_CARD_CMD_FAILED;
}
else {
Index: opensc-0.13.0/src/libopensc/card-piv.c
===================================================================
--- opensc-0.13.0.orig/src/libopensc/card-piv.c
+++ opensc-0.13.0/src/libopensc/card-piv.c
@@ -517,7 +517,7 @@ static int piv_general_io(sc_card_t *car
* the buffer is bigger, so it will not produce "ASN1.tag too long!" */
body = rbuf;
- if (sc_asn1_read_tag(&body, 0xffff, &cla_out, &tag_out, &bodylen) != SC_SUCCESS) {
+ if (sc_asn1_read_tag(&body, rbuflen, &cla_out, &tag_out, &bodylen) != SC_SUCCESS) {
/* only early beta cards had this problem */
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "***** received buffer tag MISSING ");
body = rbuf;