[pkg-opensc-commit] [opensc] 01/295: DNIe. Removing all memory leaks and using SM wrapping and unwrapping.

Eric Dorland eric at moszumanska.debian.org
Sat Jun 24 21:11:10 UTC 2017


This is an automated email from the git hooks/post-receive script.

eric pushed a commit to branch master
in repository opensc.

commit 1dd501a705575a8041e62bd3822896c8b104d79f
Author: German Blanco <german.blanco at gmail.com>
Date:   Sun Feb 28 08:13:45 2016 +0100

    DNIe. Removing all memory leaks and using SM wrapping and unwrapping.
---
 src/libopensc/card-dnie.c | 142 ++++++++++++++++++++-------
 src/libopensc/cwa-dnie.c  | 242 ++++------------------------------------------
 src/libopensc/cwa14890.c  | 143 ++++++---------------------
 src/libopensc/cwa14890.h  |  61 +-----------
 4 files changed, 158 insertions(+), 430 deletions(-)

diff --git a/src/libopensc/card-dnie.c b/src/libopensc/card-dnie.c
index e442cb4..cc15be0 100644
--- a/src/libopensc/card-dnie.c
+++ b/src/libopensc/card-dnie.c
@@ -53,6 +53,9 @@
 #ifdef __APPLE__
 #include <Carbon/Carbon.h>
 #endif
+
+#define MAX_RESP_BUFFER_SIZE 2048
+
 /* default titles */
 #define USER_CONSENT_TITLE "Confirm"
 
@@ -619,7 +622,7 @@ static int dnie_get_serialnr(sc_card_t * card, sc_serial_number_t * serial)
 {
 	int result;
 	sc_apdu_t apdu;
-	u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
+	u8 rbuf[MAX_RESP_BUFFER_SIZE];
 	if ((card == NULL) || (card->ctx == NULL) || (serial == NULL))
 		return SC_ERROR_INVALID_ARGUMENTS;
 
@@ -729,6 +732,73 @@ int dnie_match_card(struct sc_card *card)
 	LOG_FUNC_RETURN(card->ctx, result);
 }
 
+static int dnie_sm_free_wrapped_apdu(struct sc_card *card,
+		struct sc_apdu *plain, struct sc_apdu **sm_apdu)
+{
+	struct sc_context *ctx = card->ctx;
+	int rv = SC_SUCCESS;
+
+	LOG_FUNC_CALLED(ctx);
+	if (!sm_apdu)
+		LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
+	if (!(*sm_apdu))
+		LOG_FUNC_RETURN(ctx, SC_SUCCESS);
+
+	if ((*sm_apdu) != 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);
+		free(*sm_apdu);
+	}
+	*sm_apdu = NULL;
+
+	LOG_FUNC_RETURN(ctx, rv);
+}
+
+static int dnie_sm_get_wrapped_apdu(struct sc_card *card,
+		struct sc_apdu *plain, struct sc_apdu **sm_apdu)
+{
+	struct sc_context *ctx = card->ctx;
+	struct sc_apdu *apdu = NULL;
+	cwa_provider_t *provider = NULL;
+	int rv = SC_SUCCESS;
+
+	LOG_FUNC_CALLED(ctx);
+	if (!plain || !sm_apdu)
+		LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
+
+	provider = GET_DNIE_PRIV_DATA(card)->cwa_provider;
+
+	if (((plain->cla & 0x0C) == 0) && (plain->ins != 0xC0)) {
+		*sm_apdu = NULL;
+		//construct new SM apdu from original apdu
+		apdu = calloc(1, sizeof(struct sc_apdu));
+		if (!apdu)
+			return SC_ERROR_OUT_OF_MEMORY;
+
+		memcpy(apdu, plain, sizeof(sc_apdu_t));
+
+		rv = cwa_encode_apdu(card, provider, plain, apdu);
+
+		if (rv != SC_SUCCESS) {
+			dnie_sm_free_wrapped_apdu(card, NULL, &apdu);
+			goto err;
+		}
+
+		*sm_apdu = apdu;
+	} else 
+		*sm_apdu = plain;
+
+	apdu = NULL;
+err:
+	free(apdu);
+	LOG_FUNC_RETURN(ctx, rv);
+}
+
 /**
  * OpenDNIe card structures initialization.
  *
@@ -759,8 +829,9 @@ static int dnie_init(struct sc_card *card)
 #ifdef ENABLE_SM
 	/** Secure messaging initialization section **/
 	memset(&(card->sm_ctx), 0, sizeof(sm_context_t));
-	card->sm_ctx.ops.get_sm_apdu = NULL;
-	card->sm_ctx.ops.free_sm_apdu = NULL;
+	card->sm_ctx.ops.get_sm_apdu = dnie_sm_get_wrapped_apdu;
+	card->sm_ctx.ops.free_sm_apdu = dnie_sm_free_wrapped_apdu;
+	card->sm_ctx.sm_mode = SM_MODE_NONE;
 #endif
 
 	init_flags(card);
@@ -916,7 +987,7 @@ static u8 *dnie_uncompress(sc_card_t * card, u8 * from, size_t *len)
  */
 static int dnie_fill_cache(sc_card_t * card)
 {
-	u8 tmp[SC_MAX_APDU_BUFFER_SIZE];
+	u8 tmp[MAX_RESP_BUFFER_SIZE];
 	sc_apdu_t apdu;
 	size_t count = 0;
 	size_t len = 0;
@@ -944,7 +1015,7 @@ static int dnie_fill_cache(sc_card_t * card)
 		apdu.p1 = 0xff & (len >> 8);
 		apdu.p2 = 0xff & len;
 		apdu.le = count;
-		apdu.resplen = count;
+		apdu.resplen = MAX_RESP_BUFFER_SIZE;
 		apdu.resp = tmp;
 		/* transmit apdu */
 		r = dnie_transmit_apdu(card, &apdu);
@@ -1070,7 +1141,7 @@ static int dnie_compose_and_send_apdu(sc_card_t *card, const u8 *path, size_t pa
 {
 	int res = 0;
 	sc_apdu_t apdu;
-	u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
+	u8 rbuf[MAX_RESP_BUFFER_SIZE];
 	sc_file_t *file = NULL;
 
 	sc_context_t *ctx = NULL;
@@ -1081,17 +1152,15 @@ static int dnie_compose_and_send_apdu(sc_card_t *card, const u8 *path, size_t pa
 
 	LOG_FUNC_CALLED(ctx);
 
-	/* Arriving here means need to compose and send apdu */
 	dnie_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, p1, 0, 
 					sc_get_max_recv_size(card), pathlen,
 					rbuf, sizeof(rbuf), path, pathlen);
 	if (p1 == 3)
 		apdu.cse= SC_APDU_CASE_1;
 
-	if (file_out == NULL) {
-		apdu.cse = (apdu.lc == 0) ? SC_APDU_CASE_1 : SC_APDU_CASE_3_SHORT;
-		apdu.le = 0;
-	}
+	if (file_out == NULL)
+		apdu.cse = SC_APDU_CASE_4_SHORT;
+
 	res = dnie_transmit_apdu(card, &apdu);
 	if ((res != SC_SUCCESS) || (file_out == NULL))
 		dnie_free_apdu_buffers(&apdu, rbuf, sizeof(rbuf));
@@ -1196,7 +1265,6 @@ static int dnie_select_file(struct sc_card *card,
 
 		sc_log(ctx, "select_file(PATH): requested:%s ", sc_dump_hex(in_path->value, in_path->len));
 
-
 		/* convert to SC_PATH_TYPE_FILE_ID */
 		res = sc_lock(card); /* lock to ensure path traversal */
 		LOG_TEST_RET(ctx, res, "sc_lock() failed");
@@ -1269,10 +1337,12 @@ static int dnie_select_file(struct sc_card *card,
  * @param len requested challenge length
  * @return SC_SUCCESS if OK; else error code
  */
+#define BUFFER_SIZE 8
+
 static int dnie_get_challenge(struct sc_card *card, u8 * rnd, size_t len)
 {
 	sc_apdu_t apdu;
-	u8 buf[10];
+	u8 buf[MAX_RESP_BUFFER_SIZE];
 	int result = SC_SUCCESS;
 	if ((card == NULL) || (card->ctx == NULL))
 		return SC_ERROR_INVALID_ARGUMENTS;
@@ -1284,27 +1354,31 @@ static int dnie_get_challenge(struct sc_card *card, u8 * rnd, size_t len)
 		result = SC_ERROR_INVALID_ARGUMENTS;
 		goto dnie_get_challenge_error;
 	}
-	dnie_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x84, 0x00, 0x00, 8, 0,
-					buf, 8, NULL, 0);
+	dnie_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x84, 0x00, 0x00, BUFFER_SIZE, 0,
+					buf, MAX_RESP_BUFFER_SIZE, NULL, 0);
 
 	/* 
 	* As DNIe cannot handle other data length than 0x08 and 0x14, 
 	* perform consecutive reads of 8 bytes until retrieve requested length
 	*/
 	while (len > 0) {
-		size_t n = len > 8 ? 8 : len;
+		size_t n = len > BUFFER_SIZE ? BUFFER_SIZE : len;
+		sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x84, 0x00, 0x00);
+		apdu.le = BUFFER_SIZE;
+		apdu.resp = buf;
+		apdu.resplen = MAX_RESP_BUFFER_SIZE;	/* include SW's */
 		result = dnie_transmit_apdu(card, &apdu);
 		if (result != SC_SUCCESS) {
-			dnie_free_apdu_buffers(&apdu, buf, 8);
+			dnie_free_apdu_buffers(&apdu, buf, MAX_RESP_BUFFER_SIZE);
 			LOG_TEST_RET(card->ctx, result, "APDU transmit failed");
 		}
-		if (apdu.resplen != 8) {
+		if (apdu.resplen != BUFFER_SIZE) {
 			result = sc_check_sw(card, apdu.sw1, apdu.sw2);
-			dnie_free_apdu_buffers(&apdu, buf, 8);
+			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, 8);
+		dnie_free_apdu_buffers(&apdu, buf, MAX_RESP_BUFFER_SIZE);
 		len -= n;
 		rnd += n;
 	}
@@ -1363,6 +1437,7 @@ static int dnie_set_security_env(struct sc_card *card,
 {
 	sc_apdu_t apdu;
 	u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];	/* buffer to compose apdu data */
+	u8 rbuf[MAX_RESP_BUFFER_SIZE];
 	u8 *p = sbuf;
 	int result = SC_SUCCESS;
 	if ((card == NULL) || (card->ctx == NULL) || (env == NULL))
@@ -1434,8 +1509,8 @@ static int dnie_set_security_env(struct sc_card *card,
 	}
 
 	/* create and format apdu */
-	dnie_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x00, 0x00, 0, p - sbuf,
-					NULL, 0, sbuf, p - sbuf);
+	dnie_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x22, 0x00, 0x00, 255, p - sbuf,
+					rbuf, MAX_RESP_BUFFER_SIZE, sbuf, p - sbuf);
 
 	/* check and perform operation */
 	switch (env->operation) {
@@ -1463,7 +1538,7 @@ static int dnie_set_security_env(struct sc_card *card,
 
 	/* send composed apdu and parse result */
 	result = dnie_transmit_apdu(card, &apdu);
-	dnie_free_apdu_buffers(&apdu, NULL, 0);
+	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);
 
@@ -1497,7 +1572,7 @@ static int dnie_decipher(struct sc_card *card,
 {
 	struct sc_apdu apdu;
 	u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
-	u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
+	u8 sbuf[MAX_RESP_BUFFER_SIZE];
 	size_t len;
 	int result = SC_SUCCESS;
 	if ((card == NULL) || (card->ctx == NULL))
@@ -1571,7 +1646,7 @@ static int dnie_compute_signature(struct sc_card *card,
 	int result = SC_SUCCESS;
 	int result_resplen = 0;
 	struct sc_apdu apdu;
-	u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];	/* to receive sign response */
+	u8 rbuf[MAX_RESP_BUFFER_SIZE];	/* to receive sign response */
 
 	/* some preliminar checks */
 	if ((card == NULL) || (card->ctx == NULL))
@@ -1666,7 +1741,7 @@ static int dnie_list_files(sc_card_t * card, u8 * buf, size_t buflen)
 		LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
 
 	/* compose select_file(ID) command */
-	dnie_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x00, 0x00, 0, 2,
+	dnie_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0x00, 0x00, 0, 2,
 					NULL, 0, data, 2);
 	/* iterate on every possible ids */
 	for (id1 = 0; id1 < 256; id1++) {
@@ -1824,7 +1899,7 @@ static int dnie_read_header(struct sc_card *card)
 {
 	sc_apdu_t apdu;
 	int r;
-	u8 buf[SC_MAX_APDU_BUFFER_SIZE];
+	u8 buf[MAX_RESP_BUFFER_SIZE];
 	unsigned long uncompressed = 0L;
 	unsigned long compressed = 0L;
 	sc_context_t *ctx = NULL;
@@ -1836,7 +1911,7 @@ static int dnie_read_header(struct sc_card *card)
 
 	/* initialize apdu */
 	dnie_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xB0, 0x00, 0x00, 8, 0,
-					buf, SC_MAX_APDU_BUFFER_SIZE, NULL, 0);
+					buf, MAX_RESP_BUFFER_SIZE, NULL, 0);
 	/* transmit apdu */
 	r = dnie_transmit_apdu(card, &apdu);
 	if (r != SC_SUCCESS) {
@@ -2090,6 +2165,7 @@ 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;
 
@@ -2109,13 +2185,13 @@ static int dnie_pin_verify(struct sc_card *card,
 	pinlen = res;
 
 	/* compose apdu */
-	dnie_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x20, 0x00, 0x00, 0x00, pinlen,
-					NULL, 0, pinbuffer, pinlen);
+	dnie_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x20, 0x00, 0x00, 255, pinlen,
+					resp, MAX_RESP_BUFFER_SIZE, pinbuffer, pinlen);
 
 	/* and send to card throught virtual channel */
 	res = dnie_transmit_apdu(card, &apdu);
 	if (res != SC_SUCCESS) {
-		dnie_free_apdu_buffers(&apdu, NULL, 0);
+		dnie_free_apdu_buffers(&apdu, resp, MAX_RESP_BUFFER_SIZE);
 		LOG_TEST_RET(card->ctx, res, "VERIFY APDU Transmit fail");
 	}
 
@@ -2123,14 +2199,14 @@ 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, NULL, 0);
+			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, NULL, 0);
+	dnie_free_apdu_buffers(&apdu, resp, MAX_RESP_BUFFER_SIZE);
 	data->apdu = NULL;
 	LOG_FUNC_RETURN(card->ctx, res);
 #else
diff --git a/src/libopensc/cwa-dnie.c b/src/libopensc/cwa-dnie.c
index 6cabcd3..311d499 100644
--- a/src/libopensc/cwa-dnie.c
+++ b/src/libopensc/cwa-dnie.c
@@ -619,6 +619,13 @@ static int dnie_create_pre_ops(sc_card_t * card, cwa_provider_t * provider)
 	return sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
 }
 
+static int dnie_create_post_ops(sc_card_t * card, cwa_provider_t * provider)
+{
+        card->sm_ctx.sm_mode = SM_MODE_TRANSMIT;
+
+        return SC_SUCCESS;
+}
+
 /**
  * Main entry point for DNIe CWA14890 SM data provider.
  *
@@ -638,7 +645,7 @@ cwa_provider_t *dnie_get_cwa_provider(sc_card_t * card)
 
 	/* pre and post operations */
 	res->cwa_create_pre_ops = dnie_create_pre_ops;
-	res->cwa_create_post_ops = NULL;
+	res->cwa_create_post_ops = dnie_create_post_ops;
 
 	/* Get ICC intermediate CA  path */
 	res->cwa_get_icc_intermediate_ca_cert =
@@ -675,239 +682,26 @@ cwa_provider_t *dnie_get_cwa_provider(sc_card_t * card)
 	/* Get ICC Serial Number */
 	res->cwa_get_sn_icc = dnie_get_sn_icc;
 
-    /************** operations related with APDU encoding ******************/
-
-	/* pre and post operations */
-	res->cwa_encode_pre_ops = NULL;
-	res->cwa_encode_post_ops = NULL;
-
-    /************** operations related APDU response decoding **************/
-
-	/* pre and post operations */
-	res->cwa_decode_pre_ops = NULL;
-	res->cwa_decode_post_ops = NULL;
-
 	return res;
 }
 
-static int dnie_transmit_apdu_internal(sc_card_t * card, sc_apdu_t * apdu)
-{
-	u8 buf[MAX_RESP_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))
-		return SC_ERROR_INVALID_ARGUMENTS;
-	LOG_FUNC_CALLED(card->ctx);
-	provider = GET_DNIE_PRIV_DATA(card)->cwa_provider;
-	memset(buf, 0, sizeof(buf));
-
-	/* check if envelope is needed */
-	if (apdu->lc <= card->max_send_size) {
-		int tmp;
-		/* no envelope needed */
-		sc_log(card->ctx, "envelope tx is not required");
-
-		tmp = apdu->cse;	/* save original apdu type */
-		/* if SM is on, assure rx buffer exists and force get_response */
-		if (provider->status.session.state == CWA_SM_ACTIVE) {
-			if (tmp == SC_APDU_CASE_3_SHORT)
-				apdu->cse = SC_APDU_CASE_4_SHORT;
-			if (apdu->resplen == 0) {	/* no response buffer: create */
-				apdu->resp = calloc(1, MAX_RESP_BUFFER_SIZE);
-				if (apdu->resp == NULL)
-					LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
-				apdu->resplen = MAX_RESP_BUFFER_SIZE;
-				apdu->le = card->max_recv_size;
-			}
-		}
-		/* call std sc_transmit_apdu */
-		res = sc_transmit_apdu(card, apdu);
-		/* and restore original apdu type */
-		apdu->cse = tmp;
-	} else {
-
-		size_t e_txlen = 0;
-		size_t index = 0;
-		sc_apdu_t e_apdu;
-		u8 * e_tx = NULL;
-
-		/* envelope needed */
-		sc_log(card->ctx, "envelope tx required: lc:%d", apdu->lc);
-
-		e_tx = calloc(7 + apdu->datalen, sizeof(u8));	/* enveloped data */
-
-		if (!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;
-		*(e_tx + 2) = apdu->p1;
-		*(e_tx + 3) = apdu->p2;
-		*(e_tx + 4) = 0x00;	/* length in extended format */
-		*(e_tx + 5) = 0xff & (apdu->lc >> 8);
-		*(e_tx + 6) = 0xff & apdu->lc;
-		memcpy(e_tx + 7, apdu->data, apdu->lc);
-		e_txlen = 7 + apdu->lc;
-		/* sc_log(card->ctx, "Data to be enveloped & sent: (%d bytes)\n%s\n===============================================================",e_txlen,sc_dump_hex(e_tx,e_txlen)); */
-		/* split apdu in n chunks of max_send_size len */
-		for (index = 0; index < e_txlen; index += card->max_send_size) {
-			size_t len = MIN(card->max_send_size, e_txlen - index);
-			sc_log(card->ctx, "envelope tx offset:%04X size:%02X",
-			       index, len);
-
-			/* compose envelope apdu command */
-			dnie_format_apdu(card, &e_apdu, apdu->cse, 0xC2, 0x00, 0x00, apdu->le, len,
-							apdu->resp, apdu->resplen, e_tx + index, len);
-			e_apdu.cla = 0x90;	/* propietary CLA */
-			/* 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 no response buffer: create */
-				if (apdu->resplen == 0) {
-					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);
-			if (res != SC_SUCCESS) {
-				if (e_tx) {
-					free(e_tx);
-					e_tx = NULL;
-				}
-				sc_log(card->ctx, "Error in envelope() send apdu");
-				LOG_FUNC_RETURN(card->ctx, res);
-			}
-		}		/* for */
-		if (e_tx) {
-			free(e_tx);
-			e_tx = NULL;
-		}
-		/* last apdu sent contains response to enveloped cmd */
-		apdu->resp = calloc(1, MAX_RESP_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);
-}
-
-/**
- * APDU Wrapping routine.
- *
- * Called before sc_transmit_apdu() to allowing APDU wrapping
- * If set to NULL no wrapping process will be done
- * Usefull on Secure Messaging APDU encode/decode
- * If returned value is greater than zero, do_single_transmit() 
- * will be called, else means either SC_SUCCESS or error code 
- *
- * NOTE:
- * DNIe doesn't handle apdu chaining; instead apdus with
- * lc>max_send_size are sent by mean of envelope() apdu command
- * So we use this method for
- * - encode and decode SM if SM is on
- * - use envelope instead of apdu chain if lc>max_send_size
- *
- * @param card Pointer to Card Structure
- * @param apdu to be wrapped
- * @return 
- * - positive: use OpenSC's sc_transmit_apdu()
- * - negative: error
- * - zero: success: no need to further transmission
- */
-static int dnie_wrap_apdu(sc_card_t * card, sc_apdu_t * apdu)
+int dnie_transmit_apdu(sc_card_t * card, sc_apdu_t * apdu)
 {
 	int res = SC_SUCCESS;
-	sc_apdu_t wrapped;
 	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;
 	ctx=card->ctx;
-	LOG_FUNC_CALLED(ctx);
 	provider = GET_DNIE_PRIV_DATA(card)->cwa_provider;
-	for (retries=3; retries>0; retries--) {
-		/* preserve original apdu to take care of retransmission */
-		memcpy(&wrapped, apdu, sizeof(sc_apdu_t));
-		/* SM is active, encode apdu */
-		if (provider->status.session.state == CWA_SM_ACTIVE) {
-			wrapped.resp = NULL;
-			wrapped.resplen = 0;	/* let get_response() assign space */
-			res = cwa_encode_apdu(card, provider, apdu, &wrapped);
-			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 */
-		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);
-		if ( res == SC_ERROR_SM ) {
-			sc_log(ctx,"Detected SM error/collision. Try %d",retries);
-			switch(provider->status.session.state) {
-				/* No SM or creating: collision with other process
-				   just retry as SM error reset ICC SM state */
-				case CWA_SM_NONE: 
-				case CWA_SM_INPROGRESS: 
-					continue;
-				/* SM was active: force restart SM and retry */
-				case CWA_SM_ACTIVE:
-					res=cwa_create_secure_channel(card, provider, CWA_SM_COLD);
-					if (res != SC_SUCCESS) {
-						msg = "Cannot re-enable SM";
-						goto cleanup_and_return;
-					}
-					continue;
-			}
-		}
-
-		/* if SM is active; decode apdu */
-		if (provider->status.session.state == CWA_SM_ACTIVE) {
-			apdu->resp = NULL;
-			apdu->resplen = 0;	/* let cwa_decode_response() eval & create size */
-			res = cwa_decode_response(card, provider, &wrapped, apdu);
-			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);
-		}
+	if ((provider->status.session.state == CWA_SM_ACTIVE) &&
+		(card->sm_ctx.sm_mode == SM_MODE_TRANSMIT)) {
+		res = sc_transmit_apdu(card, apdu);
+		LOG_TEST_RET(ctx, res, "Error in dnie_wrap_apdu process");
+		res = cwa_decode_response(card, provider, apdu);
+		LOG_TEST_RET(ctx, res, "Error in cwa_decode_response process");
 	}
-	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)
-{
-	int res = SC_SUCCESS;
-	res = dnie_wrap_apdu(card, apdu);
-	if (res <= 0) return res;
-	return sc_transmit_apdu(card, apdu);
+	else 
+		res = sc_transmit_apdu(card, apdu);
+	return res;
 }
 
 void dnie_format_apdu(sc_card_t *card, sc_apdu_t *apdu,
diff --git a/src/libopensc/cwa14890.c b/src/libopensc/cwa14890.c
index 9d3e1a8..46594dd 100644
--- a/src/libopensc/cwa14890.c
+++ b/src/libopensc/cwa14890.c
@@ -1463,15 +1463,6 @@ int cwa_encode_apdu(sc_card_t * card,
 		goto encode_end;
 	}
 
-	/* call provider pre-operation method */
-	if (provider->cwa_encode_pre_ops) {
-		res = provider->cwa_encode_pre_ops(card, provider, from, to);
-		if (res != SC_SUCCESS) {
-			msg = "Encode APDU: provider pre_ops() failed";
-			goto encode_end;
-		}
-	}
-
 	/* trace APDU before encoding process */
 	cwa_trace_apdu(card, from, 0);
 
@@ -1490,7 +1481,7 @@ int cwa_encode_apdu(sc_card_t * card,
 	}
 
 	/* set up data on destination apdu */
-	to->cse = SC_APDU_CASE_3_SHORT;
+	to->cse = SC_APDU_CASE_4_SHORT;
 	to->cla = from->cla | 0x0C;	/* mark apdu as encoded */
 	to->ins = from->ins;
 	to->p1 = from->p1;
@@ -1588,15 +1579,6 @@ int cwa_encode_apdu(sc_card_t * card,
 	to->data = apdubuf;
 	to->datalen = apdulen;
 
-	/* call provider post-operation method */
-	if (provider->cwa_encode_post_ops) {
-		res = provider->cwa_encode_post_ops(card, provider, from, to);
-		if (res != SC_SUCCESS) {
-			msg = "Encode APDU: provider post_ops() failed";
-			goto encode_end;
-		}
-	}
-
 	/* that's all folks */
 	res = SC_SUCCESS;
 	goto encode_end_apdu_valid;
@@ -1630,7 +1612,7 @@ encode_end_apdu_valid:
  */
 int cwa_decode_response(sc_card_t * card,
 			cwa_provider_t * provider,
-			sc_apdu_t * from, sc_apdu_t * to)
+			sc_apdu_t * apdu)
 {
 	size_t i, j;
 	cwa_tlv_t tlv_array[4];
@@ -1658,27 +1640,26 @@ int cwa_decode_response(sc_card_t * card,
 
 	LOG_FUNC_CALLED(ctx);
 	/* check remaining arguments */
-	if ((from == NULL) || (to == NULL) || (sm_session == NULL))
+	if ((apdu == NULL) || (sm_session == NULL))
 		LOG_FUNC_RETURN(ctx, SC_ERROR_SM_NOT_INITIALIZED);
 	if (sm_session->state != CWA_SM_ACTIVE)
 		LOG_FUNC_RETURN(ctx, SC_ERROR_SM_INVALID_LEVEL);
 
 	/* cwa14890 sect 9.3: check SW1 or SW2 for SM related errors */
-	if (from->sw1 == 0x69) {
-		if ((from->sw2 == 0x88) || (from->sw2 == 0x87)) {
+	if (apdu->sw1 == 0x69) {
+		if ((apdu->sw2 == 0x88) || (apdu->sw2 == 0x87)) {
 			msg = "SM related errors in APDU response";
 			res = SC_ERROR_SM_ENCRYPT_FAILED;	/* tell driver to restart SM */
 			goto response_decode_end;
 		}
 	}
 	/* if response is null/empty assume unencoded apdu */
-	if (!from->resp || (from->resplen == 0)) {
+	if (!apdu->resp || (apdu->resplen == 0)) {
 		sc_log(ctx, "Empty APDU response: assume not cwa encoded");
-		memcpy(to, from, sizeof(sc_apdu_t));
 		return SC_SUCCESS;
 	}
 	/* checks if apdu response needs decoding by checking tags in response */
-	switch (*from->resp) {
+	switch (*apdu->resp) {
 	case CWA_SM_PLAIN_TAG:
 	case CWA_SM_CRYPTO_TAG:
 	case CWA_SM_MAC_TAG:
@@ -1687,31 +1668,21 @@ int cwa_decode_response(sc_card_t * card,
 		break;		/* cwa tags found: continue decoding */
 	default:		/* else apdu response seems not to be cwa encoded */
 		sc_log(card->ctx, "APDU Response seems not to be cwa encoded");
-		memcpy(to, from, sizeof(sc_apdu_t));
 		return SC_SUCCESS;	/* let process continue */
 	}
 
-	/* call provider pre-operation method */
-	if (provider->cwa_decode_pre_ops) {
-		res = provider->cwa_decode_pre_ops(card, provider, from, to);
-		if (res != SC_SUCCESS) {
-			sc_log(ctx, "Decode APDU: provider pre_ops() failed");
-			LOG_FUNC_RETURN(ctx, res);
-		}
-	}
-
 	/* parse response to find TLV's data and check results */
 	memset(tlv_array, 0, 4 * sizeof(cwa_tlv_t));
 	/* create buffer and copy data into */
-	buffer = calloc(from->resplen, sizeof(u8));
+	buffer = calloc(apdu->resplen, sizeof(u8));
 	if (!buffer) {
 		msg = "Cannot allocate space for response buffer";
 		res = SC_ERROR_OUT_OF_MEMORY;
 		goto response_decode_end;
 	}
-	memcpy(buffer, from->resp, from->resplen);
+	memcpy(buffer, apdu->resp, apdu->resplen);
 
-	res = cwa_parse_tlv(card, buffer, from->resplen, tlv_array);
+	res = cwa_parse_tlv(card, buffer, apdu->resplen, tlv_array);
 	if (res != SC_SUCCESS) {
 		msg = "Error in TLV parsing";
 		goto response_decode_end;
@@ -1737,7 +1708,7 @@ int cwa_decode_response(sc_card_t * card,
 
 	/* compose buffer to evaluate mac */
 
-	/* reserve enought space for data+status+padding */
+	/* reserve enough space for data+status+padding */
 	ccbuf =
 	    calloc(e_tlv->buflen + s_tlv->buflen + p_tlv->buflen + 8,
 		   sizeof(u8));
@@ -1764,12 +1735,9 @@ int cwa_decode_response(sc_card_t * card,
 		}
 		memcpy(ccbuf + cclen, s_tlv->buf, s_tlv->buflen);
 		cclen += s_tlv->buflen;
-		to->sw1 = s_tlv->data[0];
-		to->sw2 = s_tlv->data[1];
-	} else {		/* if no response status tag, use sw1 and sw2 from apdu */
-		to->sw1 = from->sw1;
-		to->sw2 = from->sw2;
-	}
+		apdu->sw1 = s_tlv->data[0];
+		apdu->sw2 = s_tlv->data[1];
+	}		/* if no response status tag, use sw1 and sw2 from apdu */
 	/* add iso7816 padding */
 	cwa_iso7816_padding(ccbuf, &cclen);
 
@@ -1809,29 +1777,23 @@ int cwa_decode_response(sc_card_t * card,
 
 	/* allocate response buffer */
 	resplen = 10 + MAX(p_tlv->len, e_tlv->len);	/* estimate response buflen */
-	if (to->resp) {		/* if response apdu provides buffer, try to use it */
-		if (to->resplen < resplen) {
-			msg =
-			    "Provided buffer has not enough size to store response";
-			res = SC_ERROR_OUT_OF_MEMORY;
-			goto response_decode_end;
-		}
-	} else {		/* buffer not provided: create and assing to response apdu */
-		to->resp = calloc(resplen, sizeof(u8));
-		if (!to->resp) {
+	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;
 		}
 	}
-	to->resplen = resplen;
+	apdu->resplen = resplen;
 
 	/* fill destination response apdu buffer with data */
 
 	/* if plain data, just copy TLV data into apdu response */
 	if (p_tlv->buf) {	/* plain data */
-		memcpy(to->resp, p_tlv->data, p_tlv->len);
-		to->resplen = p_tlv->len;
+		memcpy(apdu->resp, p_tlv->data, p_tlv->len);
+		apdu->resplen = p_tlv->len;
 	}
 
 	/* if encoded data, decode and store into apdu response */
@@ -1856,33 +1818,24 @@ int cwa_decode_response(sc_card_t * card,
 				      &k2);
 		/* decrypt into response buffer
 		 * by using 3DES CBC by mean of kenc and iv={0,...0} */
-		DES_ede3_cbc_encrypt(&e_tlv->data[1], to->resp, e_tlv->len - 1,
+		DES_ede3_cbc_encrypt(&e_tlv->data[1], apdu->resp, e_tlv->len - 1,
 				     &k1, &k2, &k1, &iv, DES_DECRYPT);
-		to->resplen = e_tlv->len - 1;
+		apdu->resplen = e_tlv->len - 1;
 		/* remove iso padding from response length */
-		for (; (to->resplen > 0) && *(to->resp + to->resplen - 1) == 0x00; to->resplen--) ;	/* empty loop */
+		for (; (apdu->resplen > 0) && *(apdu->resp + apdu->resplen - 1) == 0x00; apdu->resplen--) ;	/* empty loop */
 
-		if (*(to->resp + to->resplen - 1) != 0x80) {	/* check padding byte */
+		if (*(apdu->resp + apdu->resplen - 1) != 0x80) {	/* check padding byte */
 			msg =
 			    "Decrypted TLV has no 0x80 iso padding indicator!";
 			res = SC_ERROR_INVALID_DATA;
 			goto response_decode_end;
 		}
 		/* everything ok: remove ending 0x80 from response */
-		to->resplen--;
+		apdu->resplen--;
 	}
 
 	else
-		to->resplen = 0;	/* neither plain, nor encoded data */
-
-	/* call provider post-operation method */
-	if (provider->cwa_decode_post_ops) {
-		res = provider->cwa_decode_post_ops(card, provider, from, to);
-		if (res != SC_SUCCESS) {
-			sc_log(ctx, "Decode APDU: provider post_ops() failed");
-			goto response_decode_end;
-		}
-	}
+		apdu->resplen = 0;	/* neither plain, nor encoded data */
 
 	/* that's all folks */
 	res = SC_SUCCESS;
@@ -1895,7 +1848,7 @@ int cwa_decode_response(sc_card_t * card,
 	if (msg) {
 		sc_log(ctx, msg);
 	} else {
-		cwa_trace_apdu(card, to, 1);
+		cwa_trace_apdu(card, apdu, 1);
 	}			/* trace apdu response */
 	LOG_FUNC_RETURN(ctx, res);
 }
@@ -1989,36 +1942,6 @@ static int default_get_sn_icc(sc_card_t * card, u8 ** buf)
 	return SC_ERROR_NOT_SUPPORTED;
 }
 
-/************** operations related with APDU encoding ******************/
-
-/* pre and post operations */
-static int default_encode_pre_ops(sc_card_t * card, cwa_provider_t * provider,
-				  sc_apdu_t * from, sc_apdu_t * to)
-{
-	return SC_SUCCESS;
-}
-
-static int default_encode_post_ops(sc_card_t * card, cwa_provider_t * provider,
-				   sc_apdu_t * from, sc_apdu_t * to)
-{
-	return SC_SUCCESS;
-}
-
-/************** operations related APDU response decoding **************/
-
-/* pre and post operations */
-static int default_decode_pre_ops(sc_card_t * card, cwa_provider_t * provider,
-				  sc_apdu_t * from, sc_apdu_t * to)
-{
-	return SC_SUCCESS;
-}
-
-static int default_decode_post_ops(sc_card_t * card, cwa_provider_t * provider,
-				   sc_apdu_t * from, sc_apdu_t * to)
-{
-	return SC_SUCCESS;
-}
-
 static cwa_provider_t default_cwa_provider = {
 
     /************ data related with SM operations *************************/
@@ -2106,17 +2029,7 @@ static cwa_provider_t default_cwa_provider = {
 	/* Get ICC Serial Number */
 	default_get_sn_icc,
 
-    /************** operations related with APDU encoding ******************/
-
-	/* pre and post operations */
-	default_encode_pre_ops,
-	default_encode_post_ops,
-
-    /************** operations related APDU response decoding **************/
 
-	/* pre and post operations */
-	default_decode_pre_ops,
-	default_decode_post_ops,
 };
 
 /**
diff --git a/src/libopensc/cwa14890.h b/src/libopensc/cwa14890.h
index 5cebe72..b55d3b5 100644
--- a/src/libopensc/cwa14890.h
+++ b/src/libopensc/cwa14890.h
@@ -274,61 +274,7 @@ typedef struct cwa_provider_st {
 	*/
 	int (*cwa_get_sn_icc) (sc_card_t * card, u8 ** buf);
 
-    /************** operations related with APDU encoding ******************/
-
-	/**
- 	* Operation to be done before any APDU encode procedure.
- 	*
- 	* @param card Pointer to card driver data structure
- 	* @param provider pointer to cwa1890 SM provider
- 	* @param from APDU to be encoded
- 	* @param to resulting APDU to be sent to encode procedure
- 	* @return SC_SUCCESS if OK, else error code
- 	*/
-	int (*cwa_encode_pre_ops) (sc_card_t * card,
-				   struct cwa_provider_st * provider,
-				   sc_apdu_t * from, sc_apdu_t * to);
-
-	/**
- 	* Operation to be done after APDU encode process finished ok.
- 	*
- 	* @param card Pointer to card driver data structure
- 	* @param provider pointer to cwa1890 SM provider
- 	* @param from encoded APDU
- 	* @param to resulting encoded APDU to be returned to libopensc
- 	* @return SC_SUCCESS if OK, else error code
- 	*/
-	int (*cwa_encode_post_ops) (sc_card_t * card,
-				    struct cwa_provider_st * provider,
-				    sc_apdu_t * from, sc_apdu_t * to);
-
-    /************** operations related APDU response decoding **************/
-
-	/**
- 	* Operation to be done before any APDU Response decode procedure.
- 	*
- 	* @param card Pointer to card driver data structure
- 	* @param provider pointer to cwa1890 SM provider
- 	* @param from APDU Response to be decoded
- 	* @param to resulting APDU response to be sent to decode procedure
- 	* @return SC_SUCCESS if OK, else error code
- 	*/
-	int (*cwa_decode_pre_ops) (sc_card_t * card,
-				   struct cwa_provider_st * provider,
-				   sc_apdu_t * from, sc_apdu_t * to);
-
-	/**
- 	* Operation to be done after APDU Response decode process finished ok.
- 	*
- 	* @param card Pointer to card driver data structure
- 	* @param provider pointer to cwa1890 SM provider
- 	* @param from decoded APDU Response
- 	* @param to resulting APDU Response to be returned to libopensc
- 	* @return SC_SUCCESS if OK, else error code
- 	*/
-	int (*cwa_decode_post_ops) (sc_card_t * card,
-				    struct cwa_provider_st * provider,
-				    sc_apdu_t * from, sc_apdu_t * to);
+ 
 } cwa_provider_t;
 
 /************************** external function prototypes ******************/
@@ -359,13 +305,12 @@ extern int cwa_create_secure_channel(sc_card_t * card,
  *
  * @param card card info structure
  * @param provider cwa provider data to handle SM channel
- * @param from apdu to be decoded
- * @param to   where to store decoded apdu
+ * @param apdu apdu to be decoded
  * @return SC_SUCCESS if ok; else error code
  */
 extern int cwa_decode_response(sc_card_t * card,
 			       cwa_provider_t * provider,
-			       sc_apdu_t * from, sc_apdu_t * to);
+			       sc_apdu_t * apdu);
 
 /**
  * Encode an APDU.

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-opensc/opensc.git



More information about the pkg-opensc-commit mailing list