Fixing part of the memory allocation problems in DNIe module.
This commit is contained in:
parent
b48fa70308
commit
76517b7d43
|
@ -293,7 +293,7 @@ data_found:
|
|||
static int dnie_get_info(sc_card_t * card, char *data[])
|
||||
{
|
||||
sc_file_t *file = NULL;
|
||||
sc_path_t *path = NULL;
|
||||
sc_path_t path;
|
||||
u8 *buffer = NULL;
|
||||
size_t bufferlen = 0;
|
||||
char *msg = NULL;
|
||||
|
@ -309,14 +309,8 @@ static int dnie_get_info(sc_card_t * card, char *data[])
|
|||
/* phase 1: get DNIe number, Name and GivenName */
|
||||
|
||||
/* read EF(CDF) at 3F0050156004 */
|
||||
path = (sc_path_t *) calloc(1, sizeof(sc_path_t));
|
||||
if (!path) {
|
||||
msg = "Cannot allocate path data for EF(CDF) read";
|
||||
res = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto get_info_end;
|
||||
}
|
||||
sc_format_path("3F0050156004", path);
|
||||
res = dnie_read_file(card, path, &file, &buffer, &bufferlen);
|
||||
sc_format_path("3F0050156004", &path);
|
||||
res = dnie_read_file(card, &path, &file, &buffer, &bufferlen);
|
||||
if (res != SC_SUCCESS) {
|
||||
msg = "Cannot read EF(CDF)";
|
||||
goto get_info_end;
|
||||
|
@ -334,7 +328,7 @@ static int dnie_get_info(sc_card_t * card, char *data[])
|
|||
}
|
||||
|
||||
/* phase 2: get IDESP */
|
||||
sc_format_path("3F000006", path);
|
||||
sc_format_path("3F000006", &path);
|
||||
if (file) {
|
||||
sc_file_free(file);
|
||||
file = NULL;
|
||||
|
@ -344,7 +338,7 @@ static int dnie_get_info(sc_card_t * card, char *data[])
|
|||
buffer=NULL;
|
||||
bufferlen=0;
|
||||
}
|
||||
res = dnie_read_file(card, path, &file, &buffer, &bufferlen);
|
||||
res = dnie_read_file(card, &path, &file, &buffer, &bufferlen);
|
||||
if (res != SC_SUCCESS) {
|
||||
data[3]=NULL;
|
||||
goto get_info_ph3;
|
||||
|
@ -359,7 +353,7 @@ static int dnie_get_info(sc_card_t * card, char *data[])
|
|||
|
||||
get_info_ph3:
|
||||
/* phase 3: get DNIe software version */
|
||||
sc_format_path("3F002F03", path);
|
||||
sc_format_path("3F002F03", &path);
|
||||
if (file) {
|
||||
sc_file_free(file);
|
||||
file = NULL;
|
||||
|
@ -373,7 +367,7 @@ get_info_ph3:
|
|||
* Some old DNIe cards seems not to include SW version file,
|
||||
* so let this code fail without notice
|
||||
*/
|
||||
res = dnie_read_file(card, path, &file, &buffer, &bufferlen);
|
||||
res = dnie_read_file(card, &path, &file, &buffer, &bufferlen);
|
||||
if (res != SC_SUCCESS) {
|
||||
msg = "Cannot read DNIe Version EF";
|
||||
data[4]=NULL;
|
||||
|
@ -395,10 +389,12 @@ get_info_ph3:
|
|||
get_info_end:
|
||||
if (file) {
|
||||
sc_file_free(file);
|
||||
free(buffer);
|
||||
file = NULL;
|
||||
buffer = NULL;
|
||||
bufferlen = 0;
|
||||
}
|
||||
if (buffer) {
|
||||
free(buffer);
|
||||
buffer=NULL;
|
||||
bufferlen=0;
|
||||
}
|
||||
if (msg)
|
||||
sc_log(card->ctx,msg);
|
||||
|
@ -905,6 +901,8 @@ static int dnie_compose_and_send_apdu(sc_card_t *card, const u8 *path, size_t pa
|
|||
if (file == NULL)
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
res = card->ops->process_fci(card, file, apdu.resp + 2, apdu.resp[1]);
|
||||
if (*file_out != NULL)
|
||||
sc_file_free(*file_out);
|
||||
*file_out = file;
|
||||
LOG_FUNC_RETURN(ctx, res);
|
||||
}
|
||||
|
|
|
@ -265,6 +265,8 @@ int dnie_read_file(sc_card_t * card,
|
|||
res = SC_SUCCESS;
|
||||
goto dnie_read_file_end;
|
||||
dnie_read_file_err:
|
||||
if (data)
|
||||
free(data);
|
||||
if (*file) {
|
||||
sc_file_free(*file);
|
||||
*file = NULL;
|
||||
|
@ -289,39 +291,37 @@ int dnie_read_file(sc_card_t * card,
|
|||
static int dnie_read_certificate(sc_card_t * card, char *certpath, X509 ** cert)
|
||||
{
|
||||
sc_file_t *file = NULL;
|
||||
sc_path_t *path = NULL;
|
||||
u8 *buffer = NULL;
|
||||
sc_path_t path;
|
||||
u8 *buffer = NULL, *buffer2 = NULL;
|
||||
char *msg = NULL;
|
||||
size_t bufferlen = 0;
|
||||
int res = SC_SUCCESS;
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
path = (sc_path_t *) calloc(1, sizeof(sc_path_t));
|
||||
if (!path) {
|
||||
msg = "Cannot allocate path data for cert read";
|
||||
res = SC_ERROR_OUT_OF_MEMORY;
|
||||
goto read_cert_end;
|
||||
}
|
||||
sc_format_path(certpath, path);
|
||||
res = dnie_read_file(card, path, &file, &buffer, &bufferlen);
|
||||
sc_format_path(certpath, &path);
|
||||
res = dnie_read_file(card, &path, &file, &buffer, &bufferlen);
|
||||
if (res != SC_SUCCESS) {
|
||||
msg = "Cannot get intermediate CA cert";
|
||||
goto read_cert_end;
|
||||
}
|
||||
*cert = d2i_X509(NULL, (const unsigned char **)&buffer, bufferlen);
|
||||
buffer2 = buffer;
|
||||
*cert = d2i_X509(NULL, (const unsigned char **)&buffer2, bufferlen);
|
||||
if (*cert == NULL) { /* received data is not a certificate */
|
||||
res = SC_ERROR_OBJECT_NOT_VALID;
|
||||
msg = "Readed data is not a certificate";
|
||||
msg = "Read data is not a certificate";
|
||||
goto read_cert_end;
|
||||
}
|
||||
res = SC_SUCCESS;
|
||||
|
||||
read_cert_end:
|
||||
if (buffer) {
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
bufferlen = 0;
|
||||
}
|
||||
if (file) {
|
||||
sc_file_free(file);
|
||||
file = NULL;
|
||||
buffer = NULL;
|
||||
bufferlen = 0;
|
||||
}
|
||||
if (msg)
|
||||
sc_log(card->ctx, msg);
|
||||
|
@ -690,7 +690,7 @@ cwa_provider_t *dnie_get_cwa_provider(sc_card_t * card)
|
|||
|
||||
static int dnie_transmit_apdu_internal(sc_card_t * card, sc_apdu_t * apdu)
|
||||
{
|
||||
u8 buf[2048]; /* use for store partial le responses */
|
||||
u8 buf[2*SC_MAX_APDU_BUFFER_SIZE]; /* use for store partial le responses */
|
||||
int res = SC_SUCCESS;
|
||||
cwa_provider_t *provider = NULL;
|
||||
if ((card == NULL) || (card->ctx == NULL) || (apdu == NULL))
|
||||
|
@ -711,8 +711,10 @@ static int dnie_transmit_apdu_internal(sc_card_t * card, sc_apdu_t * apdu)
|
|||
if (tmp == SC_APDU_CASE_3_SHORT)
|
||||
apdu->cse = SC_APDU_CASE_4_SHORT;
|
||||
if (apdu->resplen == 0) { /* no response buffer: create */
|
||||
apdu->resp = buf;
|
||||
apdu->resplen = 2048;
|
||||
apdu->resp = calloc(1, 2*SC_MAX_APDU_BUFFER_SIZE);
|
||||
if (apdu->resp == NULL)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
apdu->resplen = 2*SC_MAX_APDU_BUFFER_SIZE;
|
||||
apdu->le = card->max_recv_size;
|
||||
}
|
||||
}
|
||||
|
@ -724,17 +726,12 @@ static int dnie_transmit_apdu_internal(sc_card_t * card, sc_apdu_t * apdu)
|
|||
|
||||
size_t e_txlen = 0;
|
||||
size_t index = 0;
|
||||
sc_apdu_t *e_apdu = NULL;
|
||||
u8 *e_tx = NULL;
|
||||
sc_apdu_t e_apdu;
|
||||
u8 e_tx[2*SC_MAX_APDU_BUFFER_SIZE];
|
||||
|
||||
/* envelope needed */
|
||||
sc_log(card->ctx, "envelope tx required: lc:%d", apdu->lc);
|
||||
|
||||
e_apdu = calloc(1, sizeof(sc_apdu_t)); /* enveloped apdu */
|
||||
e_tx = calloc(7 + apdu->datalen, sizeof(u8)); /* enveloped data */
|
||||
if (!e_apdu || !e_tx)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
/* copy apdu info into enveloped data */
|
||||
*(e_tx + 0) = apdu->cla; /* apdu header */
|
||||
*(e_tx + 1) = apdu->ins;
|
||||
|
@ -753,35 +750,37 @@ static int dnie_transmit_apdu_internal(sc_card_t * card, sc_apdu_t * apdu)
|
|||
index, len);
|
||||
|
||||
/* compose envelope apdu command */
|
||||
sc_format_apdu(card, e_apdu, apdu->cse, 0xC2, 0x00,
|
||||
0x00);
|
||||
e_apdu->cla = 0x90; /* propietary CLA */
|
||||
e_apdu->data = e_tx + index;
|
||||
e_apdu->lc = len;
|
||||
e_apdu->datalen = len;
|
||||
e_apdu->le = apdu->le;
|
||||
e_apdu->resp = apdu->resp;
|
||||
e_apdu->resplen = apdu->resplen;
|
||||
sc_format_apdu(card, &e_apdu, apdu->cse, 0xC2, 0x00, 0x00);
|
||||
e_apdu.cla = 0x90; /* propietary CLA */
|
||||
e_apdu.data = e_tx + index;
|
||||
e_apdu.lc = len;
|
||||
e_apdu.datalen = len;
|
||||
e_apdu.le = apdu->le;
|
||||
e_apdu.resp = apdu->resp;
|
||||
e_apdu.resplen = apdu->resplen;
|
||||
/* if SM is ON, ensure resp exists, and force getResponse() */
|
||||
if (provider->status.session.state == CWA_SM_ACTIVE) {
|
||||
/* set up proper apdu type */
|
||||
if (e_apdu->cse == SC_APDU_CASE_3_SHORT)
|
||||
e_apdu->cse = SC_APDU_CASE_4_SHORT;
|
||||
if (e_apdu.cse == SC_APDU_CASE_3_SHORT)
|
||||
e_apdu.cse = SC_APDU_CASE_4_SHORT;
|
||||
/* if no response buffer: create */
|
||||
if (apdu->resplen == 0) {
|
||||
e_apdu->resp = buf;
|
||||
e_apdu->resplen = 2048;
|
||||
e_apdu->le = card->max_recv_size;
|
||||
e_apdu.resp = buf;
|
||||
e_apdu.resplen = 2048;
|
||||
e_apdu.le = card->max_recv_size;
|
||||
}
|
||||
}
|
||||
/* send data chunk bypassing apdu wrapping */
|
||||
res = sc_transmit_apdu(card, e_apdu);
|
||||
res = sc_transmit_apdu(card, &e_apdu);
|
||||
LOG_TEST_RET(card->ctx, res,
|
||||
"Error in envelope() send apdu");
|
||||
} /* for */
|
||||
/* last apdu sent contains response to enveloped cmd */
|
||||
apdu->resp = e_apdu->resp;
|
||||
apdu->resplen = e_apdu->resplen;
|
||||
apdu->resp = calloc(1, 2*SC_MAX_APDU_BUFFER_SIZE);
|
||||
if (apdu->resp == NULL)
|
||||
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
|
||||
memcpy(apdu->resp, e_apdu.resp, e_apdu.resplen);
|
||||
apdu->resplen = e_apdu.resplen;
|
||||
res = SC_SUCCESS;
|
||||
}
|
||||
LOG_FUNC_RETURN(card->ctx, res);
|
||||
|
@ -817,6 +816,7 @@ static int dnie_wrap_apdu(sc_card_t * card, sc_apdu_t * apdu)
|
|||
sc_context_t *ctx;
|
||||
cwa_provider_t *provider = NULL;
|
||||
int retries = 3;
|
||||
char * msg = NULL;
|
||||
|
||||
if ((card == NULL) || (card->ctx == NULL) || (apdu == NULL))
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
@ -831,13 +831,18 @@ static int dnie_wrap_apdu(sc_card_t * card, sc_apdu_t * apdu)
|
|||
wrapped.resp = NULL;
|
||||
wrapped.resplen = 0; /* let get_response() assign space */
|
||||
res = cwa_encode_apdu(card, provider, apdu, &wrapped);
|
||||
LOG_TEST_RET(ctx, res,
|
||||
"Error in cwa_encode_apdu process");
|
||||
if (res != SC_SUCCESS) {
|
||||
msg = "Error in cwa_encode_apdu process";
|
||||
goto cleanup_and_return;
|
||||
}
|
||||
}
|
||||
/* send apdu via envelope() cmd if needed */
|
||||
res = dnie_transmit_apdu_internal(card, &wrapped);
|
||||
/* check for tx errors */
|
||||
LOG_TEST_RET(ctx, res, "Error in dnie_transmit_apdu process");
|
||||
if (res != SC_SUCCESS) {
|
||||
msg = "Error in dnie_transmit_apdu process";
|
||||
goto cleanup_and_return;
|
||||
}
|
||||
|
||||
/* parse response and handle SM related errors */
|
||||
res=card->ops->check_sw(card,wrapped.sw1,wrapped.sw2);
|
||||
|
@ -852,7 +857,10 @@ static int dnie_wrap_apdu(sc_card_t * card, sc_apdu_t * apdu)
|
|||
/* SM was active: force restart SM and retry */
|
||||
case CWA_SM_ACTIVE:
|
||||
res=cwa_create_secure_channel(card, provider, CWA_SM_COLD);
|
||||
LOG_TEST_RET(ctx,res,"Cannot re-enable SM");
|
||||
if (res != SC_SUCCESS) {
|
||||
msg = "Cannot re-enable SM";
|
||||
goto cleanup_and_return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -862,15 +870,24 @@ static int dnie_wrap_apdu(sc_card_t * card, sc_apdu_t * apdu)
|
|||
apdu->resp = NULL;
|
||||
apdu->resplen = 0; /* let cwa_decode_response() eval & create size */
|
||||
res = cwa_decode_response(card, provider, &wrapped, apdu);
|
||||
LOG_TEST_RET(ctx, res, "Error in cwa_decode_response process");
|
||||
if (res != SC_SUCCESS)
|
||||
msg = "Error in cwa_decode_response process";
|
||||
goto cleanup_and_return;
|
||||
} else {
|
||||
if (apdu->resp != wrapped.resp) free(apdu->resp);
|
||||
/* memcopy result to original apdu */
|
||||
memcpy(apdu, &wrapped, sizeof(sc_apdu_t));
|
||||
LOG_FUNC_RETURN(ctx, res);
|
||||
}
|
||||
LOG_FUNC_RETURN(ctx, res);
|
||||
}
|
||||
sc_log(ctx,"Too many retransmissions. Abort and return");
|
||||
LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
|
||||
msg = "Too many retransmissions. Abort and return";
|
||||
res = SC_ERROR_INTERNAL;
|
||||
|
||||
cleanup_and_return:
|
||||
if (apdu->resp != wrapped.resp) free(wrapped.resp);
|
||||
if (msg)
|
||||
sc_log(ctx, msg);
|
||||
LOG_FUNC_RETURN(ctx, res);
|
||||
}
|
||||
|
||||
int dnie_transmit_apdu(sc_card_t * card, sc_apdu_t * apdu)
|
||||
|
|
|
@ -1397,6 +1397,10 @@ int cwa_create_secure_channel(sc_card_t * card,
|
|||
/* arriving here means ok: cleanup */
|
||||
res = SC_SUCCESS;
|
||||
csc_end:
|
||||
if (icc_cert)
|
||||
X509_free(icc_cert);
|
||||
if (ca_cert)
|
||||
X509_free(ca_cert);
|
||||
if (icc_pubkey)
|
||||
EVP_PKEY_free(icc_pubkey);
|
||||
if (ifd_privkey)
|
||||
|
|
|
@ -42,13 +42,19 @@ int dump_ef(sc_card_t * card, const char *path, u8 * buf, size_t * buf_len)
|
|||
{
|
||||
int rv;
|
||||
sc_file_t *file = sc_file_new();
|
||||
sc_format_path(path, &file->path);
|
||||
rv = sc_select_file(card, &file->path, &file);
|
||||
if (rv < 0)
|
||||
sc_path_t scpath;
|
||||
sc_format_path(path, &scpath);
|
||||
rv = sc_select_file(card, &scpath, &file);
|
||||
if (rv < 0) {
|
||||
sc_file_free(file);
|
||||
return rv;
|
||||
if (file->size > *buf_len)
|
||||
}
|
||||
if (file->size > *buf_len) {
|
||||
sc_file_free(file);
|
||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
rv = sc_read_binary(card, 0, buf, file->size, 0);
|
||||
sc_file_free(file);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
*buf_len = rv;
|
||||
|
|
Loading…
Reference in New Issue