diff --git a/src/libopensc/card-dnie.c b/src/libopensc/card-dnie.c index c4f16419..204ffbde 100644 --- a/src/libopensc/card-dnie.c +++ b/src/libopensc/card-dnie.c @@ -658,7 +658,6 @@ static int dnie_get_serialnr(sc_card_t * card, sc_serial_number_t * serial) /* send apdu */ result = sc_transmit_apdu(card, &apdu); if (result != SC_SUCCESS) { - dnie_free_apdu_buffers(&apdu, rbuf, sizeof(rbuf)); LOG_TEST_RET(card->ctx, result, "APDU transmit failed"); } if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) @@ -676,7 +675,6 @@ static int dnie_get_serialnr(sc_card_t * card, sc_serial_number_t * serial) memcpy(serial, &card->serialnr, sizeof(*serial)); sc_log(card->ctx, "Serial Number (apdu): '%s'", sc_dump_hex(serial->value, serial->len)); - dnie_free_apdu_buffers(&apdu, rbuf, sizeof(rbuf)); LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); } @@ -761,17 +759,17 @@ static int dnie_sm_free_wrapped_apdu(struct sc_card *card, LOG_FUNC_RETURN(ctx, SC_SUCCESS); if ((*sm_apdu) != plain) { + rv = cwa_decode_response(card, provider, *sm_apdu); if (plain) { - plain->resp = (*sm_apdu)->resp; plain->resplen = (*sm_apdu)->resplen; plain->sw1 = (*sm_apdu)->sw1; plain->sw2 = (*sm_apdu)->sw2; if (((*sm_apdu)->data) != plain->data) free((unsigned char *) (*sm_apdu)->data); + if ((*sm_apdu)->resp != plain->resp) + free((*sm_apdu)->resp); } - free(*sm_apdu); - rv = cwa_decode_response(card, provider, plain); } *sm_apdu = NULL; @@ -1179,8 +1177,7 @@ static int dnie_compose_and_send_apdu(sc_card_t *card, const u8 *path, size_t pa res = sc_transmit_apdu(card, &apdu); if ((res != SC_SUCCESS) || (file_out == NULL)) - dnie_free_apdu_buffers(&apdu, rbuf, sizeof(rbuf)); - LOG_TEST_RET(ctx, res, "SelectFile() APDU transmit failed"); + LOG_TEST_RET(ctx, res, "SelectFile() APDU transmit failed"); if (file_out == NULL) { if (apdu.sw1 == 0x61) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, 0); @@ -1191,24 +1188,20 @@ static int dnie_compose_and_send_apdu(sc_card_t *card, const u8 *path, size_t pa /* analyze response. if FCI, try to parse */ res = sc_check_sw(card, apdu.sw1, apdu.sw2); if (res != SC_SUCCESS) { - dnie_free_apdu_buffers(&apdu, rbuf, sizeof(rbuf)); LOG_TEST_RET(ctx, res, "SelectFile() check_sw failed"); } if ((apdu.resplen < 2) || (apdu.resp[0] == 0x00)) { - dnie_free_apdu_buffers(&apdu, rbuf, sizeof(rbuf)); LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED); } /* finally process FCI response */ file = sc_file_new(); if (file == NULL) { - dnie_free_apdu_buffers(&apdu, rbuf, sizeof(rbuf)); LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); } res = card->ops->process_fci(card, file, apdu.resp + 2, apdu.resp[1]); sc_file_free(*file_out); *file_out = file; - dnie_free_apdu_buffers(&apdu, rbuf, sizeof(rbuf)); LOG_FUNC_RETURN(ctx, res); } @@ -1384,16 +1377,13 @@ static int dnie_get_challenge(struct sc_card *card, u8 * rnd, size_t len) apdu.resplen = MAX_RESP_BUFFER_SIZE; /* include SW's */ result = sc_transmit_apdu(card, &apdu); if (result != SC_SUCCESS) { - dnie_free_apdu_buffers(&apdu, buf, MAX_RESP_BUFFER_SIZE); LOG_TEST_RET(card->ctx, result, "APDU transmit failed"); } if (apdu.resplen != BUFFER_SIZE) { result = sc_check_sw(card, apdu.sw1, apdu.sw2); - dnie_free_apdu_buffers(&apdu, buf, MAX_RESP_BUFFER_SIZE); goto dnie_get_challenge_error; } memcpy(rnd, apdu.resp, n); - dnie_free_apdu_buffers(&apdu, buf, MAX_RESP_BUFFER_SIZE); len -= n; rnd += n; } @@ -1551,7 +1541,6 @@ static int dnie_set_security_env(struct sc_card *card, /* send composed apdu and parse result */ result = sc_transmit_apdu(card, &apdu); - dnie_free_apdu_buffers(&apdu, rbuf, MAX_RESP_BUFFER_SIZE); LOG_TEST_RET(card->ctx, result, "Set Security Environment failed"); result = sc_check_sw(card, apdu.sw1, apdu.sw2); @@ -1701,13 +1690,11 @@ static int dnie_compute_signature(struct sc_card *card, /* tell card to compute signature */ result = sc_transmit_apdu(card, &apdu); if (result != SC_SUCCESS) { - dnie_free_apdu_buffers(&apdu, rbuf, sizeof(rbuf)); LOG_TEST_RET(card->ctx, result, "compute_signature() failed"); } /* check response */ result = sc_check_sw(card, apdu.sw1, apdu.sw2); if (result != SC_SUCCESS) { - dnie_free_apdu_buffers(&apdu, rbuf, sizeof(rbuf)); LOG_TEST_RET(card->ctx, result, "compute_signature() response error"); } @@ -1715,7 +1702,6 @@ static int dnie_compute_signature(struct sc_card *card, result_resplen = apdu.resplen; memcpy(out, apdu.resp, result_resplen); /* and return response length */ - dnie_free_apdu_buffers(&apdu, rbuf, sizeof(rbuf)); LOG_FUNC_RETURN(card->ctx, result_resplen); } @@ -1775,7 +1761,6 @@ static int dnie_list_files(sc_card_t * card, u8 * buf, size_t buflen) data[0] = (u8) (0xff & id1); data[1] = (u8) (0xff & id2); res = sc_transmit_apdu(card, &apdu); - dnie_free_apdu_buffers(&apdu, NULL, 0); if (res != SC_SUCCESS) { sc_log(card->ctx, "List file '%02X%02X' failed", id1, id2); @@ -1928,7 +1913,6 @@ static int dnie_read_header(struct sc_card *card) /* transmit apdu */ r = sc_transmit_apdu(card, &apdu); if (r != SC_SUCCESS) { - dnie_free_apdu_buffers(&apdu, buf, SC_MAX_APDU_BUFFER_SIZE); sc_log(ctx, "read_header() APDU transmit failed"); LOG_FUNC_RETURN(ctx, r); } @@ -1943,12 +1927,10 @@ static int dnie_read_header(struct sc_card *card) goto header_notcompressed; /* ok: assume data is correct */ sc_log(ctx, "read_header: uncompressed file size is %lu", uncompressed); - dnie_free_apdu_buffers(&apdu, buf, SC_MAX_APDU_BUFFER_SIZE); return (int)(0x7FFF & uncompressed); header_notcompressed: sc_log(ctx, "response doesn't match compressed file header"); - dnie_free_apdu_buffers(&apdu, buf, SC_MAX_APDU_BUFFER_SIZE); return 0; } @@ -2175,7 +2157,6 @@ static int dnie_pin_verify(struct sc_card *card, sc_apdu_t apdu; u8 pinbuffer[SC_MAX_APDU_BUFFER_SIZE]; - u8 resp[MAX_RESP_BUFFER_SIZE]; int pinlen = 0; int padding = 0; @@ -2200,13 +2181,12 @@ static int dnie_pin_verify(struct sc_card *card, pinlen = res; /* compose apdu */ - dnie_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x20, 0x00, 0x00, 255, pinlen, - resp, MAX_RESP_BUFFER_SIZE, pinbuffer, pinlen); + dnie_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x20, 0x00, 0x00, 0, pinlen, + NULL, 0, pinbuffer, pinlen); /* and send to card throught virtual channel */ res = sc_transmit_apdu(card, &apdu); if (res != SC_SUCCESS) { - dnie_free_apdu_buffers(&apdu, resp, MAX_RESP_BUFFER_SIZE); LOG_TEST_RET(card->ctx, res, "VERIFY APDU Transmit fail"); } @@ -2214,16 +2194,11 @@ static int dnie_pin_verify(struct sc_card *card, if (tries_left != NULL) { /* returning tries_left count is requested */ if ((apdu.sw1 == 0x63) && ((apdu.sw2 & 0xF0) == 0xC0)) { *tries_left = apdu.sw2 & 0x0F; - dnie_free_apdu_buffers(&apdu, resp, MAX_RESP_BUFFER_SIZE); LOG_FUNC_RETURN(card->ctx, SC_ERROR_PIN_CODE_INCORRECT); } } res = dnie_check_sw(card, apdu.sw1, apdu.sw2); /* not a pinerr: parse result */ - /* the end: a bit of Mister Proper and return */ - dnie_free_apdu_buffers(&apdu, resp, MAX_RESP_BUFFER_SIZE); - data->apdu = NULL; - /* ensure that secure channel is established after a PIN channel in 3.0 */ if (card->atr.value[15] >= DNIE_30_VERSION) { sc_log(card->ctx, "DNIe 3.0 detected => re-establish secure channel"); diff --git a/src/libopensc/cwa-dnie.c b/src/libopensc/cwa-dnie.c index 7e54e4a8..be2154c8 100644 --- a/src/libopensc/cwa-dnie.c +++ b/src/libopensc/cwa-dnie.c @@ -913,15 +913,5 @@ void dnie_format_apdu(sc_card_t *card, sc_apdu_t *apdu, } } -void dnie_free_apdu_buffers(sc_apdu_t *apdu, - unsigned char * resp, size_t resplen) -{ - if (apdu->resp != resp) { - free(apdu->resp); - apdu->resp = resp; - apdu->resplen = resplen; - } -} - #endif /* HAVE_OPENSSL */ /* _ end of cwa-dnie.c - */ diff --git a/src/libopensc/cwa-dnie.h b/src/libopensc/cwa-dnie.h index 0fd5ed8e..91b0135d 100644 --- a/src/libopensc/cwa-dnie.h +++ b/src/libopensc/cwa-dnie.h @@ -75,9 +75,6 @@ void dnie_format_apdu(sc_card_t *card, sc_apdu_t *apdu, unsigned char * resp, size_t resplen, const unsigned char * data, size_t datalen); -void dnie_free_apdu_buffers(sc_apdu_t *apdu, - unsigned char * resp, size_t resplen); - #endif #endif diff --git a/src/libopensc/cwa14890.c b/src/libopensc/cwa14890.c index 4352fdcf..ee254aff 100644 --- a/src/libopensc/cwa14890.c +++ b/src/libopensc/cwa14890.c @@ -435,7 +435,6 @@ static int cwa_verify_cvc_certificate(sc_card_t * card, sc_apdu_t apdu; int result = SC_SUCCESS; sc_context_t *ctx = NULL; - u8 resp[MAX_RESP_BUFFER_SIZE]; /* safety check */ if (!card || !card->ctx) @@ -446,8 +445,8 @@ static int cwa_verify_cvc_certificate(sc_card_t * card, LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); /* compose apdu for Perform Security Operation (Verify cert) cmd */ - dnie_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x00, 0xAE, 255, len, - resp, MAX_RESP_BUFFER_SIZE, cert, len); + dnie_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A, 0x00, 0xAE, 0, len, + NULL, 0, cert, len); /* send composed apdu and parse result */ result = sc_transmit_apdu(card, &apdu); @@ -476,7 +475,6 @@ static int cwa_set_security_env(sc_card_t * card, sc_apdu_t apdu; int result = SC_SUCCESS; sc_context_t *ctx = NULL; - u8 resp[MAX_RESP_BUFFER_SIZE]; /* safety check */ if (!card || !card->ctx) @@ -487,8 +485,8 @@ static int cwa_set_security_env(sc_card_t * card, LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); /* compose apdu for Manage Security Environment cmd */ - dnie_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x22, p1, p2, 255, length, - resp, MAX_RESP_BUFFER_SIZE, buffer, length); + dnie_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, p1, p2, 0, length, + NULL, 0, buffer, length); /* send composed apdu and parse result */ result = sc_transmit_apdu(card, &apdu); @@ -726,7 +724,6 @@ static int cwa_external_auth(sc_card_t * card, u8 * sig, size_t sig_len) sc_apdu_t apdu; int result = SC_SUCCESS; sc_context_t *ctx = NULL; - u8 resp[MAX_RESP_BUFFER_SIZE]; /* safety check */ if (!card || !card->ctx) @@ -735,8 +732,8 @@ static int cwa_external_auth(sc_card_t * card, u8 * sig, size_t sig_len) LOG_FUNC_CALLED(ctx); /* compose apdu for External Authenticate cmd */ - dnie_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x82, 0x00, 0x00, 255, sig_len, - resp, MAX_RESP_BUFFER_SIZE, sig, sig_len); + dnie_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x82, 0x00, 0x00, 0, sig_len, + NULL, 0, sig, sig_len); /* send composed apdu and parse result */ result = sc_transmit_apdu(card, &apdu); @@ -1467,13 +1464,16 @@ int cwa_encode_apdu(sc_card_t * card, /* reserve enough space for apdulen+tlv bytes * to-be-crypted buffer and result apdu buffer */ /* TODO DEE add 4 more bytes for testing.... */ - apdubuf = - calloc(MAX(SC_MAX_APDU_BUFFER_SIZE, 20 + from->datalen), + apdubuf = calloc(MAX(SC_MAX_APDU_BUFFER_SIZE, 20 + from->datalen), sizeof(u8)); - ccbuf = - calloc(MAX(SC_MAX_APDU_BUFFER_SIZE, 20 + from->datalen), + ccbuf = calloc(MAX(SC_MAX_APDU_BUFFER_SIZE, 20 + from->datalen), sizeof(u8)); - if (!apdubuf || !ccbuf) { + if (!to->resp) { + /* if no response create a buffer for the encoded response */ + to->resp = calloc(MAX_RESP_BUFFER_SIZE, sizeof(u8)); + to->resplen = MAX_RESP_BUFFER_SIZE; + } + if (!apdubuf || !ccbuf || (!from->resp && !to->resp)) { res = SC_ERROR_OUT_OF_MEMORY; goto err; } @@ -1485,6 +1485,8 @@ int cwa_encode_apdu(sc_card_t * card, to->p1 = from->p1; to->p2 = from->p2; to->le = from->le; + if (!to->le) + to->le = 255; to->lc = 0; /* to be evaluated */ /* fill buffer with header info */ *(ccbuf + cclen++) = to->cla; @@ -1591,6 +1593,8 @@ err: encode_end: if (apdubuf) free(apdubuf); + if (from->resp != to->resp) + free(to->resp); encode_end_apdu_valid: if (msg) sc_log(ctx, "%s", msg); @@ -1784,13 +1788,9 @@ int cwa_decode_response(sc_card_t * card, /* allocate response buffer */ resplen = 10 + MAX(p_tlv->len, e_tlv->len); /* estimate response buflen */ if (apdu->resplen < resplen) { - free(apdu->resp); - apdu->resp = calloc(resplen, sizeof(u8)); - if (!apdu->resp) { - msg = "Cannot allocate buffer to store response"; - res = SC_ERROR_OUT_OF_MEMORY; - goto response_decode_end; - } + msg = "Cannot allocate buffer to store response"; + res = SC_ERROR_BUFFER_TOO_SMALL; + goto response_decode_end; } apdu->resplen = resplen;