fixed use after free
ICCSN and CHN pointed into EF.GDO's content, which was freed
preemptively. Regression of 0502a839c6
This commit is contained in:
parent
b403934718
commit
196c838957
|
@ -1700,8 +1700,6 @@ static int starcos_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
|
||||||
const unsigned char *iccsn;
|
|
||||||
size_t iccsn_len;
|
|
||||||
sc_apdu_t apdu;
|
sc_apdu_t apdu;
|
||||||
|
|
||||||
if (!serial)
|
if (!serial)
|
||||||
|
@ -1715,12 +1713,12 @@ static int starcos_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
|
||||||
|
|
||||||
switch (card->type) {
|
switch (card->type) {
|
||||||
case SC_CARD_TYPE_STARCOS_V3_4:
|
case SC_CARD_TYPE_STARCOS_V3_4:
|
||||||
r = sc_parse_ef_gdo(card, &iccsn, &iccsn_len, NULL, 0);
|
card->serialnr.len = SC_MAX_SERIALNR;
|
||||||
if (r < 0)
|
r = sc_parse_ef_gdo(card, card->serialnr.value, &card->serialnr.len, NULL, 0);
|
||||||
|
if (r < 0) {
|
||||||
|
card->serialnr.len = 0;
|
||||||
return r;
|
return r;
|
||||||
/* cache serial number */
|
}
|
||||||
memcpy(card->serialnr.value, iccsn, MIN(iccsn_len, SC_MAX_SERIALNR));
|
|
||||||
card->serialnr.len = MIN(iccsn_len, SC_MAX_SERIALNR);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -707,8 +707,6 @@ static int tcos_setperm(sc_card_t *card, int enable_nullpin)
|
||||||
static int tcos_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
|
static int tcos_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
const unsigned char *iccsn;
|
|
||||||
size_t iccsn_len;
|
|
||||||
|
|
||||||
if (!serial)
|
if (!serial)
|
||||||
return SC_ERROR_INVALID_ARGUMENTS;
|
return SC_ERROR_INVALID_ARGUMENTS;
|
||||||
|
@ -719,13 +717,12 @@ static int tcos_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sc_parse_ef_gdo(card, &iccsn, &iccsn_len, NULL, 0);
|
card->serialnr.len = sizeof card->serialnr.value;
|
||||||
if (r < 0)
|
r = sc_parse_ef_gdo(card, card->serialnr.value, &card->serialnr.len, NULL, 0);
|
||||||
|
if (r < 0) {
|
||||||
|
card->serialnr.len = 0;
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
/* cache serial number */
|
|
||||||
memcpy(card->serialnr.value, iccsn, MIN(iccsn_len, SC_MAX_SERIALNR));
|
|
||||||
card->serialnr.len = MIN(iccsn_len, SC_MAX_SERIALNR);
|
|
||||||
|
|
||||||
/* copy and return serial number */
|
/* copy and return serial number */
|
||||||
memcpy(serial, &card->serialnr, sizeof(*serial));
|
memcpy(serial, &card->serialnr, sizeof(*serial));
|
||||||
|
|
|
@ -24,25 +24,17 @@
|
||||||
#include "asn1.h"
|
#include "asn1.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sc_parse_ef_gdo_content(const unsigned char *gdo, size_t gdo_len,
|
sc_parse_ef_gdo_content(const unsigned char *gdo, size_t gdo_len,
|
||||||
const unsigned char **iccsn, size_t *iccsn_len,
|
unsigned char *iccsn, size_t *iccsn_len,
|
||||||
const unsigned char **chn, size_t *chn_len)
|
unsigned char *chn, size_t *chn_len)
|
||||||
{
|
{
|
||||||
int r = SC_SUCCESS;
|
int r = SC_SUCCESS, iccsn_found = 0, chn_found = 0;
|
||||||
const unsigned char *p = gdo;
|
const unsigned char *p = gdo;
|
||||||
size_t left = gdo_len;
|
size_t left = gdo_len;
|
||||||
|
|
||||||
if (iccsn)
|
|
||||||
*iccsn = NULL;
|
|
||||||
if (iccsn_len)
|
|
||||||
*iccsn_len = 0;
|
|
||||||
if (chn)
|
|
||||||
*chn = NULL;
|
|
||||||
if (chn_len)
|
|
||||||
*chn_len = 0;
|
|
||||||
|
|
||||||
while (left >= 2) {
|
while (left >= 2) {
|
||||||
unsigned int cla, tag;
|
unsigned int cla, tag;
|
||||||
size_t tag_len;
|
size_t tag_len;
|
||||||
|
@ -63,16 +55,18 @@ sc_parse_ef_gdo_content(const unsigned char *gdo, size_t gdo_len,
|
||||||
if (cla == SC_ASN1_TAG_APPLICATION) {
|
if (cla == SC_ASN1_TAG_APPLICATION) {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case 0x1A:
|
case 0x1A:
|
||||||
if (iccsn)
|
iccsn_found = 1;
|
||||||
*iccsn = p;
|
if (iccsn && iccsn_len) {
|
||||||
if (iccsn_len)
|
memcpy(iccsn, p, MIN(tag_len, *iccsn_len));
|
||||||
*iccsn_len = tag_len;
|
*iccsn_len = MIN(tag_len, *iccsn_len);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0x1F20:
|
case 0x1F20:
|
||||||
if (chn)
|
chn_found = 1;
|
||||||
*chn = p;
|
if (chn && chn_len) {
|
||||||
if (chn_len)
|
memcpy(chn, p, MIN(tag_len, *chn_len));
|
||||||
*chn_len = tag_len;
|
*chn_len = MIN(tag_len, *chn_len);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,6 +75,11 @@ sc_parse_ef_gdo_content(const unsigned char *gdo, size_t gdo_len,
|
||||||
left -= (p - gdo);
|
left -= (p - gdo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!iccsn_found && iccsn_len)
|
||||||
|
*iccsn_len = 0;
|
||||||
|
if (!chn_found && chn_len)
|
||||||
|
*chn_len = 0;
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,8 +87,8 @@ sc_parse_ef_gdo_content(const unsigned char *gdo, size_t gdo_len,
|
||||||
|
|
||||||
int
|
int
|
||||||
sc_parse_ef_gdo(struct sc_card *card,
|
sc_parse_ef_gdo(struct sc_card *card,
|
||||||
const unsigned char **iccsn, size_t *iccsn_len,
|
unsigned char *iccsn, size_t *iccsn_len,
|
||||||
const unsigned char **chn, size_t *chn_len)
|
unsigned char *chn, size_t *chn_len)
|
||||||
{
|
{
|
||||||
struct sc_context *ctx;
|
struct sc_context *ctx;
|
||||||
struct sc_path path;
|
struct sc_path path;
|
||||||
|
|
|
@ -1336,8 +1336,8 @@ void sc_free_apps(struct sc_card *card);
|
||||||
int sc_parse_ef_atr(struct sc_card *card);
|
int sc_parse_ef_atr(struct sc_card *card);
|
||||||
void sc_free_ef_atr(struct sc_card *card);
|
void sc_free_ef_atr(struct sc_card *card);
|
||||||
int sc_parse_ef_gdo(struct sc_card *card,
|
int sc_parse_ef_gdo(struct sc_card *card,
|
||||||
const unsigned char **iccsn, size_t *iccsn_len,
|
unsigned char *iccsn, size_t *iccsn_len,
|
||||||
const unsigned char **chn, size_t *chn_len);
|
unsigned char *chn, size_t *chn_len);
|
||||||
int sc_update_dir(struct sc_card *card, sc_app_info_t *app);
|
int sc_update_dir(struct sc_card *card, sc_app_info_t *app);
|
||||||
|
|
||||||
void sc_print_cache(struct sc_card *card);
|
void sc_print_cache(struct sc_card *card);
|
||||||
|
|
|
@ -234,18 +234,21 @@ static int infocamere_1200_init(sc_pkcs15_card_t * p15card)
|
||||||
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
const unsigned char *iccsn, *chn;
|
unsigned char chn[8];
|
||||||
size_t iccsn_len, chn_len;
|
size_t chn_len = sizeof chn;
|
||||||
|
sc_serial_number_t iccsn;
|
||||||
|
iccsn.len = sizeof iccsn.value;
|
||||||
|
|
||||||
r = sc_parse_ef_gdo(card, &iccsn, &iccsn_len, &chn, &chn_len);
|
|
||||||
|
r = sc_parse_ef_gdo(card, iccsn.value, &iccsn.len, chn, &chn_len);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (!iccsn_len || chn_len < 2 || chn_len > 8) {
|
if (!iccsn.len || chn_len < 2 || chn_len > 8) {
|
||||||
return SC_ERROR_WRONG_CARD;
|
return SC_ERROR_WRONG_CARD;
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_bin_to_hex(iccsn, iccsn_len, serial, sizeof(serial), 0);
|
sc_bin_to_hex(iccsn.value, iccsn.len, serial, sizeof(serial), 0);
|
||||||
|
|
||||||
if (!
|
if (!
|
||||||
(chn[0] == 0x12
|
(chn[0] == 0x12
|
||||||
|
|
|
@ -305,9 +305,9 @@ static int sc_pkcs15_tccardos_init_func(sc_pkcs15_card_t *p15card)
|
||||||
struct sc_path path;
|
struct sc_path path;
|
||||||
struct sc_file *file = NULL;
|
struct sc_file *file = NULL;
|
||||||
char hex_buf[256];
|
char hex_buf[256];
|
||||||
const unsigned char *iccsn;
|
|
||||||
size_t iccsn_len;
|
|
||||||
struct sc_card *card = p15card->card;
|
struct sc_card *card = p15card->card;
|
||||||
|
sc_serial_number_t iccsn;
|
||||||
|
iccsn.len = sizeof iccsn.value;
|
||||||
|
|
||||||
/* check if we have the correct card OS */
|
/* check if we have the correct card OS */
|
||||||
if (strcmp(card->name, "CardOS M4"))
|
if (strcmp(card->name, "CardOS M4"))
|
||||||
|
@ -329,10 +329,10 @@ static int sc_pkcs15_tccardos_init_func(sc_pkcs15_card_t *p15card)
|
||||||
if (p15card->tokeninfo->manufacturer_id == NULL)
|
if (p15card->tokeninfo->manufacturer_id == NULL)
|
||||||
return SC_ERROR_OUT_OF_MEMORY;
|
return SC_ERROR_OUT_OF_MEMORY;
|
||||||
/* set the serial number */
|
/* set the serial number */
|
||||||
r = sc_parse_ef_gdo(card, &iccsn, &iccsn_len, NULL, 0);
|
r = sc_parse_ef_gdo(card, iccsn.value, &iccsn.len, NULL, 0);
|
||||||
if (r != SC_SUCCESS || iccsn_len < 5+8)
|
if (r != SC_SUCCESS || iccsn.len < 5+8)
|
||||||
return SC_ERROR_INTERNAL;
|
return SC_ERROR_INTERNAL;
|
||||||
sc_bin_to_hex(iccsn + 5, 8, hex_buf, sizeof(hex_buf), 0);
|
sc_bin_to_hex(iccsn.value + 5, 8, hex_buf, sizeof(hex_buf), 0);
|
||||||
p15card->tokeninfo->serial_number = strdup(hex_buf);
|
p15card->tokeninfo->serial_number = strdup(hex_buf);
|
||||||
if (p15card->tokeninfo->serial_number == NULL)
|
if (p15card->tokeninfo->serial_number == NULL)
|
||||||
return SC_ERROR_OUT_OF_MEMORY;
|
return SC_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
Loading…
Reference in New Issue