[pkg-opensc-commit] [opensc] 115/295: pkcs15-pteid: new implementation

Eric Dorland eric at moszumanska.debian.org
Sat Jun 24 21:11:22 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 dc073114a0a8d2a6a849f365305143061c5e492e
Author: Nuno Goncalves <nunojpg at gmail.com>
Date:   Sun Jul 10 12:52:32 2016 +0200

    pkcs15-pteid: new implementation
    
    This implementation reads most of the data from the pkcs15 structure on card, so the objects list are greatly reduced.
    
    This improves several pending issues:
    
    * drop support for IAS card type
    In accordance to [1] IAS card type is no longer issued since version
    004.003.11 (2010-06-15) and as a legal requirement all documents have
    been destroyed or declared lost.
    
    [1] https://www.cartaodecidadao.pt/documentos/DOC_01-DCM-15_V3_CC_Controlo_Versao_2016-01-20.pdf
    
    * fix pteid_cert_ids
    The Signature and Authentication Sub CA certificates ids were wrong.
    
    * add objects and fix flags
    Add Root CA certificate.
    Add data objects SOD and TRACe
    Data object 'Citizen Notepad' doesn't require login to be read. Remove flags.
    
    * Support PIN max tries and tries left report
    
    * Properly report cards with 2048b keys.
    
    Suggested-by: João Poupino <joao.poupino at gmail.com>
    Suggested-by: André Guerreiro <andre.guerreiro at caixamagica.pt>
    Signed-off-by: Nuno Goncalves <nunojpg at gmail.com>
    
    -- closes #806
---
 src/libopensc/Makefile.am    |   2 +-
 src/libopensc/Makefile.mak   |   2 +-
 src/libopensc/card-ias.c     | 533 -------------------------------------------
 src/libopensc/cards.h        |   5 -
 src/libopensc/ctx.c          |   1 -
 src/libopensc/pkcs15-pteid.c | 465 +++++++++++++++++++++----------------
 src/libopensc/pkcs15-syn.c   |   1 -
 7 files changed, 270 insertions(+), 739 deletions(-)

diff --git a/src/libopensc/Makefile.am b/src/libopensc/Makefile.am
index 39056ce..a31d5e6 100644
--- a/src/libopensc/Makefile.am
+++ b/src/libopensc/Makefile.am
@@ -38,7 +38,7 @@ libopensc_la_SOURCES = \
 	card-entersafe.c card-epass2003.c card-coolkey.c \
 	card-incrypto34.c card-piv.c card-muscle.c card-acos5.c \
 	card-asepcos.c card-akis.c card-gemsafeV1.c card-rutoken.c \
-	card-rtecp.c card-westcos.c card-myeid.c card-ias.c \
+	card-rtecp.c card-westcos.c card-myeid.c \
 	card-itacns.c card-authentic.c \
 	card-iasecc.c iasecc-sdo.c iasecc-sm.c card-sc-hsm.c \
 	card-dnie.c cwa14890.c cwa-dnie.c \
diff --git a/src/libopensc/Makefile.mak b/src/libopensc/Makefile.mak
index 8c92000..741be19 100644
--- a/src/libopensc/Makefile.mak
+++ b/src/libopensc/Makefile.mak
@@ -20,7 +20,7 @@ OBJECTS			= \
 	card-entersafe.obj card-epass2003.obj card-coolkey.obj \
 	card-incrypto34.obj card-piv.obj card-muscle.obj card-acos5.obj \
 	card-asepcos.obj card-akis.obj card-gemsafeV1.obj card-rutoken.obj \
-	card-rtecp.obj card-westcos.obj card-myeid.obj card-ias.obj \
+	card-rtecp.obj card-westcos.obj card-myeid.obj \
 	card-itacns.obj card-authentic.obj \
 	card-iasecc.obj iasecc-sdo.obj iasecc-sm.obj cwa-dnie.obj cwa14890.obj \
 	card-sc-hsm.obj card-dnie.obj card-isoApplet.obj pkcs15-coolkey.obj \
diff --git a/src/libopensc/card-ias.c b/src/libopensc/card-ias.c
deleted file mode 100644
index 584d5d9..0000000
--- a/src/libopensc/card-ias.c
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
- * Driver for IAS based cards, e.g. Portugal's eID card.
- *
- * Copyright (C) 2009, Joao Poupino <joao.poupino at ist.utl.pt>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Partially based on the ISO7816 driver.
- *
- * Thanks to Andre Cruz, Jorge Ferreira and Paulo F. Andrade
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "internal.h"
-#include "asn1.h"
-#include "cardctl.h"
-
-#define DRVDATA(card)	((struct ias_priv_data *) ((card)->drv_data))
-
-static struct sc_card_operations ias_ops;
-static struct sc_card_operations *iso_ops = NULL;
-
-static struct sc_card_driver ias_drv = {
-		"IAS",
-		"ias",
-		&ias_ops,
-		NULL, 0, NULL
-};
-
-/* Known ATRs */
-static struct sc_atr_table ias_atrs[] = {
-	/* Portugal eID cards */
-	{"3B:65:00:00:D0:00:54:01:31", NULL, NULL, SC_CARD_TYPE_IAS_PTEID, 0, NULL},
-	{"3B:65:00:00:D0:00:54:01:32", NULL, NULL, SC_CARD_TYPE_IAS_PTEID, 0, NULL},
-	{"3B:95:95:40:FF:D0:00:54:01:31", NULL, NULL, SC_CARD_TYPE_IAS_PTEID, 0, NULL},
-	{"3B:95:95:40:FF:D0:00:54:01:32", NULL, NULL, SC_CARD_TYPE_IAS_PTEID, 0, NULL},
-	{NULL, NULL, NULL, 0, 0, NULL}
-};
-
-/* Known AIDs */
-static const u8 ias_aid_pteid[] = {0x60, 0x46, 0x32, 0xFF, 0x00, 0x01, 0x02};
-
-static int ias_select_applet(sc_card_t *card, const u8 *aid, size_t aid_len)
-{
-	int 		r;
-	sc_path_t 	tpath;
-
-	memset(&tpath, 0, sizeof(sc_path_t));
-
-	tpath.type = SC_PATH_TYPE_DF_NAME;
-	tpath.len = aid_len;
-	memcpy(tpath.value, aid, aid_len);
-	r = iso_ops->select_file(card, &tpath, NULL);
-	if (r != SC_SUCCESS) {
-		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "unable to select applet");
-		return r;
-	}
-
-	return SC_SUCCESS;
-}
-
-static int ias_init(sc_card_t *card)
-{
-	unsigned long flags;
-
-	assert(card != NULL);
-
-	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
-	card->name = "IAS";
-	card->cla = 0x00;
-
-	/* Card version detection */
-	if (card->type == SC_CARD_TYPE_IAS_PTEID) {
-		int r = ias_select_applet(card, ias_aid_pteid, sizeof(ias_aid_pteid));
-		if (r != SC_SUCCESS)
-			return r;
-	/* Add other cards if necessary */
-	} else {
-		return SC_ERROR_INTERNAL;
-	}
-
-	/* Set card capabilities */
-	card->caps |= SC_CARD_CAP_RNG;
-
-	/* Set the supported algorithms */
-	flags = SC_ALGORITHM_RSA_PAD_PKCS1 |
-			SC_ALGORITHM_RSA_HASH_NONE;
-
-    /* Only 1024 bit key sizes were tested */
-     _sc_card_add_rsa_alg(card, 1024, flags, 0);
-
-	return SC_SUCCESS;
-}
-
-static int ias_match_card(sc_card_t *card)
-{
-	int i;
-
-	i = _sc_match_atr(card, ias_atrs, &card->type);
-	if (i < 0)
-		return 0;
-
-	return 1;
-}
-
-static int ias_build_pin_apdu(sc_card_t *card,
-		sc_apdu_t *apdu,
-		struct sc_pin_cmd_data *data)
-{
-	static u8 	sbuf[SC_MAX_APDU_BUFFER_SIZE];
-	int 		r, len, pad, use_pin_pad, ins, p1;
-
-	len = pad = use_pin_pad = p1 = 0;
-	assert(card != NULL);
-
-	switch (data->pin_type) {
-	case SC_AC_CHV:
-		break;
-	default:
-		return SC_ERROR_INVALID_ARGUMENTS;
-	}
-
-	if (data->flags & SC_PIN_CMD_USE_PINPAD)
-		use_pin_pad = 1;
-	/* "needs-padding" necessary for the PTEID card,
-	 * but not defined in the pin structure
-	 */
-	if ((data->flags & SC_PIN_CMD_NEED_PADDING) ||
-		 card->type == SC_CARD_TYPE_IAS_PTEID)
-		pad = 1;
-
-	data->pin1.offset = 5;
-
-	switch (data->cmd) {
-	case SC_PIN_CMD_VERIFY:
-		ins = 0x20;
-		if ( (r = sc_build_pin(sbuf, sizeof(sbuf), &data->pin1, pad)) < 0)
-			return r;
-		len = r;
-		break;
-	case SC_PIN_CMD_CHANGE:
-		ins = 0x24;
-		if ((data->flags & SC_PIN_CMD_IMPLICIT_CHANGE) == 0 &&
-			(data->pin1.len != 0 || use_pin_pad)) {
-			if ( (r = sc_build_pin(sbuf, sizeof(sbuf), &data->pin1, pad)) < 0)
-				return r;
-			len += r;
-		} else {
-			/* implicit test */
-			p1 = 1;
-		}
-		data->pin2.offset = data->pin1.offset + len;
-		if ( (r = sc_build_pin(sbuf+len, sizeof(sbuf)-len, &data->pin2, pad)) < 0)
-			return r;
-		len += r;
-		break;
-	case SC_PIN_CMD_UNBLOCK:
-		ins = 0x2C;
-		if (data->pin1.len != 0 || use_pin_pad) {
-			if ( (r = sc_build_pin(sbuf, sizeof(sbuf), &data->pin1, pad)) < 0)
-				return r;
-			len += r;
-		} else {
-			p1 |= 0x02;
-		}
-		if (data->pin2.len != 0 || use_pin_pad) {
-			data->pin2.offset = data->pin1.offset + len;
-			if ( (r = sc_build_pin(sbuf+len, sizeof(sbuf)-len, &data->pin2, pad)) < 0)
-				return r;
-			len += r;
-		} else {
-			p1 |= 0x01;
-		}
-		break;
-	default:
-		return SC_ERROR_NOT_SUPPORTED;
-	}
-
-	sc_format_apdu(card, apdu, SC_APDU_CASE_3_SHORT, ins, p1, data->pin_reference);
-	apdu->lc = len;
-	apdu->datalen = len;
-	apdu->data = sbuf;
-	apdu->resplen = 0;
-
-	return SC_SUCCESS;
-}
-
-static int ias_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
-		int *tries_left)
-{
-	int 		r;
-	sc_apdu_t 	local_apdu;
-
-	SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
-
-	/* Check if a PIN change operation is being requested,
-	 * as it requires sending two separate APDUs
-	 */
-	if (data->cmd == SC_PIN_CMD_CHANGE) {
-		/* Build a SC_PIN_CMD_VERIFY APDU */
-		data->cmd = SC_PIN_CMD_VERIFY;
-		r = ias_build_pin_apdu(card, &local_apdu, data);
-		if (r < 0)
-			return r;
-		data->apdu = &local_apdu;
-		r = iso_ops->pin_cmd(card, data, tries_left);
-		if (r < 0)
-			return r;
-		/* Continue processing */
-		data->cmd = SC_PIN_CMD_CHANGE;
-		/* The IAS spec mandates an implicit change PIN operation */
-		data->flags |= SC_PIN_CMD_IMPLICIT_CHANGE;
-	}
-
-	r = ias_build_pin_apdu(card, &local_apdu, data);
-	if (r < 0)
-		return r;
-	data->apdu = &local_apdu;
-
-	return iso_ops->pin_cmd(card, data, tries_left);
-}
-
-static int ias_set_security_env(sc_card_t *card,
-		const sc_security_env_t *env, int se_num)
-{
-	int 		r;
-	sc_apdu_t 	apdu;
-	u8 			sbuf[SC_MAX_APDU_BUFFER_SIZE];
-
-	sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "ias_set_security_env, keyRef = 0x%0x, algo = 0x%0x\n",
-			*env->key_ref, env->algorithm_flags);
-
-	assert(card != NULL && env != NULL);
-
-	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0);
-	switch (env->operation) {
-	case SC_SEC_OPERATION_DECIPHER:
-		apdu.p2 = 0xB8; /* confidentiality template */
-		sbuf[0] = 0x95;	/* tag for usage qualifier byte */
-		sbuf[1] = 0x01;	/* tag length */
-		sbuf[2] = 0x40; /* data decryption */
-		sbuf[3] = 0x84; /* tag for private key reference */
-		sbuf[4] = 0x01; /* tag length */
-		sbuf[5] = *env->key_ref;	/* key reference */
-		sbuf[6] = 0x80; /* tag for algorithm reference */
-		sbuf[7] = 0x01; /* tag length */
-		if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)
-			sbuf[8] = 0x1A; /* RSA PKCS#1 with no data formatting */
-		else {
-			sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Set Sec Env: unsupported algo 0X%0X\n",
-					env->algorithm_flags);
-			return SC_ERROR_INVALID_ARGUMENTS;
-		}
-		apdu.lc = 9;
-		apdu.datalen = 9;
-		break;
-	case SC_SEC_OPERATION_SIGN:
-		apdu.p2 = 0xA4; /* authentication template */
-		sbuf[0] = 0x95;	/* tag for usage qualifier byte */
-		sbuf[1] = 0x01;	/* tag length */
-		sbuf[2] = 0x40; /* internal authentication */
-		sbuf[3] = 0x84; /* tag for private key reference */
-		sbuf[4] = 0x01; /* tag length */
-		sbuf[5] = *env->key_ref;	/* key reference */
-		sbuf[6] = 0x80; /* tag for algorithm reference */
-		sbuf[7] = 0x01; /* tag length */
-		if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1)
-			sbuf[8] = 0x02; /* RSA PKCS#1 with no data formatting */
-		else {
-			sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Set Sec Env: unsupported algo 0X%0X\n",
-					env->algorithm_flags);
-			return SC_ERROR_INVALID_ARGUMENTS;
-		}
-		apdu.lc = 9;
-		apdu.datalen = 9;
-		break;
-	default:
-		return SC_ERROR_INVALID_ARGUMENTS;
-	}
-	apdu.le = 0;
-	apdu.data = sbuf;
-	apdu.resplen = 0;
-
-	r = sc_transmit_apdu(card, &apdu);
-	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "Set Security Env APDU transmit failed");
-
-	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
-	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "Card's Set Security Env command returned error");
-
-	return r;
-}
- 
-static int ias_compute_signature(sc_card_t *card, const u8 *data,
-		size_t data_len, u8 *out, size_t outlen)
-{
-	sc_apdu_t	apdu;
-	size_t		len;
-	/*
-	** XXX: Ensure sufficient space exists for the card's response
-	** as the caller's buffer size may not be sufficient
-	*/
-	u8		rbuf[SC_MAX_APDU_BUFFER_SIZE];
-	sc_context_t	*ctx = card->ctx;
-
-	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
-
-	if (data_len > 64) {
-		sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "error: input data too long: %lu bytes\n", data_len);
-		return SC_ERROR_INVALID_ARGUMENTS;
-	}
-	
-	sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x88, 0x02, 0x00);
-	apdu.data = (u8 *) data;
-	apdu.lc = data_len;
-	apdu.datalen = data_len;
-	apdu.resp = rbuf;
-	apdu.resplen = sizeof(rbuf);
-	apdu.le = 256;
-
-	LOG_TEST_RET(card->ctx, sc_transmit_apdu(card, &apdu), "APDU transmit failed");
-	LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "INTERNAL AUTHENTICATE failed");
-
-	len = apdu.resplen > outlen ? outlen : apdu.resplen;
-	memcpy(out, apdu.resp, len);
-	
-	LOG_FUNC_RETURN(card->ctx, apdu.resplen);
-}
-
-static int ias_select_file(sc_card_t *card, const sc_path_t *in_path,
-		sc_file_t **file_out)
-{
-	int 			r, pathlen, stripped_len;
-	u8 				buf[SC_MAX_APDU_BUFFER_SIZE];
-	u8 				pathbuf[SC_MAX_PATH_SIZE], *path;
-	sc_apdu_t 		apdu;
-	sc_file_t 		*file;
-
-	stripped_len = 0;
-	path = pathbuf;
-	file = NULL;
-
-	assert(card != NULL && in_path != NULL);
-
-	if (in_path->len > SC_MAX_PATH_SIZE)
-		return SC_ERROR_INVALID_ARGUMENTS;
-	memcpy(path, in_path->value, in_path->len);
-	pathlen = in_path->len;
-
-	sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0, 0);
-	apdu.p2 = 0; /* First record, return FCI */
-
-	switch (in_path->type) {
-	case SC_PATH_TYPE_FILE_ID:
-		apdu.p1 = 2;
-		if (pathlen != 2)
-			return SC_ERROR_INVALID_ARGUMENTS;
-		break;
-	case SC_PATH_TYPE_DF_NAME:
-		apdu.p1 = 4;
-		break;
-	case SC_PATH_TYPE_PATH:
-		apdu.p1 = 9;
-		/* Strip the MF */
-		if (pathlen >= 2 && memcmp(path, "\x3f\x00", 2) == 0) {
-			if (pathlen == 2) { /* Only 3f00 provided */
-				apdu.p1 = 0;
-				break;
-			}
-			path += 2;
-			pathlen -= 2;
-		}
-		/* Optimization based on the normal Portuguese eID usage pattern:
-		 * paths with len >= 4 shall be stripped - this avoids unnecessary
-		 * "file not found" errors. Other cards may benefit from this also.
-		 *
-		 * This works perfectly for the Portuguese eID card, but if you
-		 * are adapting this driver to another card, "false positives" may
-		 * occur depending, of course, on the file structure of the card.
-		 *
-		 * Please have this in mind if adapting this driver to another card.
-		 */
-		if (pathlen >= 4) {
-			stripped_len = pathlen - 2;
-			path += stripped_len;
-			pathlen = 2;
-		} else if (pathlen == 2) {
-			apdu.p1 = 0;
-		}
-		break;
-	case SC_PATH_TYPE_FROM_CURRENT:
-		apdu.p1 = 9;
-		break;
-	case SC_PATH_TYPE_PARENT:
-		apdu.p1 = 3;
-		apdu.p2 = 0x0C;
-		pathlen = 0;
-		apdu.cse = SC_APDU_CASE_2_SHORT;
-		break;
-	default:
-		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
-	}
-
-	apdu.lc = pathlen;
-	apdu.data = path;
-	apdu.datalen = pathlen;
-
-	if (file_out != NULL) {
-		apdu.resp = buf;
-		apdu.resplen = sizeof(buf);
-		apdu.le = 256;
-	} else {
-		apdu.p2 = 0x0C;
-		apdu.cse = (apdu.lc == 0) ? SC_APDU_CASE_1 : SC_APDU_CASE_3_SHORT;
-	}
-
-	r = sc_transmit_apdu(card, &apdu);
-	SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
-	if (file_out == NULL) {
-		if (apdu.sw1 == 0x61)
-			SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, 0);
-		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
-	}
-
-	/* A "file not found" error was received, this can mean two things:
-	 * 1) the file does not exist
-	 * 2) the current DF may be incorrect due to the optimization applied
-	 *    earlier. If the path was previously stripped, select the first DF
-	 *    and try to re-select the path with the full value.
-	 */
-	if (stripped_len > 0 && apdu.sw1 == 0x6A && apdu.sw2 == 0x82) {
-		sc_path_t tpath;
-
-		/* Restore original path value */
-		path -= stripped_len;
-		pathlen += stripped_len;
-
-		memset(&tpath, 0, sizeof(sc_path_t));
-		tpath.type = SC_PATH_TYPE_PATH;
-		tpath.len = 2;
-		tpath.value[0] = path[0];
-		tpath.value[1] = path[1];
-
-		/* Go up in the hierarchy to the correct DF */
-		r = ias_select_file(card, &tpath, NULL);
-		SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "Error selecting parent.");
-
-		/* We're now in the right place, reconstruct the APDU and retry */
-		path += 2;
-		pathlen -= 2;
-		apdu.lc = pathlen;
-		apdu.data = path;
-		apdu.datalen = pathlen;
-
-		if (file_out != NULL)
-			apdu.resplen = sizeof(buf);
-
-		r = sc_transmit_apdu(card, &apdu);
-		SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
-		if (file_out == NULL) {
-			SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
-		}
-	}
-
-	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
-	if (r)
-		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
-
-	if (apdu.resplen < 2)
-		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_UNKNOWN_DATA_RECEIVED);
-	switch (apdu.resp[0]) {
-	case 0x6F:
-		file = sc_file_new();
-		if (file == NULL)
-			SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY);
-		file->path = *in_path;
-		if (card->ops->process_fci == NULL) {
-			sc_file_free(file);
-			SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
-		}
-		if ((size_t)apdu.resp[1] + 2 <= apdu.resplen)
-			card->ops->process_fci(card, file, apdu.resp+2, apdu.resp[1]);
-		*file_out = file;
-		break;
-	case 0x00:	/* proprietary coding */
-		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_UNKNOWN_DATA_RECEIVED);
-	default:
-		SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_UNKNOWN_DATA_RECEIVED);
-	}
-
-	return SC_SUCCESS;
-}
-
-static struct sc_card_driver *sc_get_driver(void)
-{
-	struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
-
-	if (iso_ops == NULL)
-		iso_ops = iso_drv->ops;
-	/* Use the standard iso operations as default */
-	ias_ops = *iso_drv->ops;
-	/* IAS specific functions */
-	ias_ops.select_file = ias_select_file;
-	ias_ops.match_card = ias_match_card;
-	ias_ops.init = ias_init;
-	ias_ops.set_security_env = ias_set_security_env;
-	ias_ops.compute_signature = ias_compute_signature;
-	ias_ops.pin_cmd = ias_pin_cmd;
-
-	return &ias_drv;
-}
-
-struct sc_card_driver *sc_get_ias_driver(void)
-{
-	return sc_get_driver();
-}
diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h
index 7ab94bc..d0ce788 100644
--- a/src/libopensc/cards.h
+++ b/src/libopensc/cards.h
@@ -182,10 +182,6 @@ enum {
 	SC_CARD_TYPE_GEMSAFEV1_PTEID,
 	SC_CARD_TYPE_GEMSAFEV1_SEEID,
 
-	/* IAS cards */
-	SC_CARD_TYPE_IAS_BASE = 22000,
-	SC_CARD_TYPE_IAS_PTEID,
-
 	/* Italian CNS cards */
 	SC_CARD_TYPE_ITACNS_BASE = 23000,
 	SC_CARD_TYPE_ITACNS_GENERIC,
@@ -264,7 +260,6 @@ extern sc_card_driver_t *sc_get_rutoken_driver(void);
 extern sc_card_driver_t *sc_get_rtecp_driver(void);
 extern sc_card_driver_t *sc_get_westcos_driver(void);
 extern sc_card_driver_t *sc_get_myeid_driver(void);
-extern sc_card_driver_t *sc_get_ias_driver(void);
 extern sc_card_driver_t *sc_get_sc_hsm_driver(void);
 extern sc_card_driver_t *sc_get_itacns_driver(void);
 extern sc_card_driver_t *sc_get_authentic_driver(void);
diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c
index 0aaad09..2445c4b 100644
--- a/src/libopensc/ctx.c
+++ b/src/libopensc/ctx.c
@@ -85,7 +85,6 @@ static const struct _sc_driver_entry internal_card_drivers[] = {
 	{ "iasecc",	(void *(*)(void)) sc_get_iasecc_driver },
 #endif
 	{ "belpic",	(void *(*)(void)) sc_get_belpic_driver },
-	{ "ias",		(void *(*)(void)) sc_get_ias_driver },
 	{ "incrypto34", (void *(*)(void)) sc_get_incrypto34_driver },
 	{ "acos5",	(void *(*)(void)) sc_get_acos5_driver },
 	{ "akis",	(void *(*)(void)) sc_get_akis_driver },
diff --git a/src/libopensc/pkcs15-pteid.c b/src/libopensc/pkcs15-pteid.c
index 68dacac..0365ba1 100644
--- a/src/libopensc/pkcs15-pteid.c
+++ b/src/libopensc/pkcs15-pteid.c
@@ -1,6 +1,7 @@
 /*
  * PKCS15 emulation layer for Portugal eID card.
  *
+ * Copyright (C) 2016, Nuno Goncalves <nunojpg at gmail.com>
  * Copyright (C) 2009, Joao Poupino <joao.poupino at ist.utl.pt>
  * Copyright (C) 2004, Martin Paljak <martin at martinpaljak.net>
  *
@@ -47,198 +48,269 @@
 #include "internal.h"
 #include "pkcs15.h"
 
-#define IAS_CARD 0
-#define GEMSAFE_CARD 1
-
+static int pteid_detect_card(struct sc_card *card);
 int sc_pkcs15emu_pteid_init_ex(sc_pkcs15_card_t *, struct sc_aid *, sc_pkcs15emu_opt_t *);
 
-static int sc_pkcs15emu_pteid_init(sc_pkcs15_card_t * p15card)
+static
+int dump_ef(sc_card_t * card, const char *path, u8 * buf, size_t * buf_len)
 {
-	int r, i, 				type;
-	unsigned char 			*buf = NULL;
-	size_t 					len;
-	sc_pkcs15_tokeninfo_t 	tokeninfo;
-	sc_path_t 				tmppath;
-	sc_card_t 				*card = p15card->card;
-	sc_context_t 			*ctx = card->ctx;
-
-	/* Parse the TokenInfo EF */
-	sc_format_path("3f004f005032", &tmppath);
-	r = sc_select_file(card, &tmppath, &p15card->file_tokeninfo);
-	if (r)
-		goto end;
-	if ( (len = p15card->file_tokeninfo->size) == 0) {
-		sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "EF(TokenInfo) is empty\n");
-		goto end;
+	int rv;
+	sc_file_t *file = NULL;
+	sc_path_t scpath;
+	sc_format_path(path, &scpath);
+	rv = sc_select_file(card, &scpath, &file);
+	if (rv < 0) {
+		if (file)
+			sc_file_free(file);
+		return rv;
+	}
+	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;
+
+	return SC_SUCCESS;
+}
+
+static const struct sc_asn1_entry c_asn1_odf[] = {
+	{"privateKeys", SC_ASN1_STRUCT, SC_ASN1_CTX | 0 | SC_ASN1_CONS, 0, NULL, NULL},
+	{"publicKeys", SC_ASN1_STRUCT, SC_ASN1_CTX | 1 | SC_ASN1_CONS, 0, NULL,	 NULL},
+	{"trustedPublicKeys", SC_ASN1_STRUCT, SC_ASN1_CTX | 2 | SC_ASN1_CONS, 0, NULL, NULL},
+	{"secretKeys", SC_ASN1_STRUCT, SC_ASN1_CTX | 3 | SC_ASN1_CONS, 0, NULL,	 NULL},
+	{"certificates", SC_ASN1_STRUCT, SC_ASN1_CTX | 4 | SC_ASN1_CONS, 0,	 NULL, NULL},
+	{"trustedCertificates", SC_ASN1_STRUCT, SC_ASN1_CTX | 5 | SC_ASN1_CONS,	 0, NULL, NULL},
+	{"usefulCertificates", SC_ASN1_STRUCT, SC_ASN1_CTX | 6 | SC_ASN1_CONS,	 0, NULL, NULL},
+	{"dataObjects", SC_ASN1_STRUCT, SC_ASN1_CTX | 7 | SC_ASN1_CONS, 0, NULL,	 NULL},
+	{"authObjects", SC_ASN1_STRUCT, SC_ASN1_CTX | 8 | SC_ASN1_CONS, 0, NULL,	 NULL},
+	{NULL, 0, 0, 0, NULL, NULL}
+};
+
+static const unsigned int odf_indexes[] = {
+	SC_PKCS15_PRKDF,		//0
+	SC_PKCS15_PUKDF,		//1
+	SC_PKCS15_PUKDF_TRUSTED,	//2
+	SC_PKCS15_SKDF,			//3
+	SC_PKCS15_CDF,			//4
+	SC_PKCS15_CDF_TRUSTED,		//5
+	SC_PKCS15_CDF_USEFUL,		//6
+	SC_PKCS15_DODF,			//7
+	SC_PKCS15_AODF,			//8
+};
+
+static
+int parse_odf(const u8 * buf, size_t buflen, struct sc_pkcs15_card *p15card)
+{
+	const u8 *p = buf;
+	size_t left = buflen;
+	int r, i, type;
+	sc_path_t path;
+	struct sc_asn1_entry asn1_obj_or_path[] = {
+		{"path", SC_ASN1_PATH, SC_ASN1_CONS | SC_ASN1_SEQUENCE, 0,
+		 &path, NULL},
+		{NULL, 0, 0, 0, NULL, NULL}
+	};
+	struct sc_asn1_entry asn1_odf[10];
+
+	sc_path_t path_prefix;
+
+	sc_format_path("3F004F00", &path_prefix);
+
+	sc_copy_asn1_entry(c_asn1_odf, asn1_odf);
+	for (i = 0; asn1_odf[i].name != NULL; i++)
+		sc_format_asn1_entry(asn1_odf + i, asn1_obj_or_path, NULL, 0);
+	while (left > 0) {
+		r = sc_asn1_decode_choice(p15card->card->ctx, asn1_odf, p, left,
+					  &p, &left);
+		if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
+			break;
+		if (r < 0)
+			return r;
+		type = r;
+		r = sc_pkcs15_make_absolute_path(&path_prefix, &path);
+		if (r < 0)
+			return r;
+		r = sc_pkcs15_add_df(p15card, odf_indexes[type], &path);
+		if (r)
+			return r;
 	}
-	buf = malloc(len);
-	if (buf == NULL)
-		return SC_ERROR_OUT_OF_MEMORY;
-	r = sc_read_binary(card, 0, buf, len, 0);
-	if (r < 0)
-		goto end;
-	if (r <= 2) {
-		r = SC_ERROR_PKCS15_APP_NOT_FOUND;
-		goto end;
+	return 0;
+}
+
+static int sc_pkcs15emu_pteid_init(sc_pkcs15_card_t * p15card)
+{
+	u8 buf[1024];
+	sc_pkcs15_df_t *df;
+	sc_pkcs15_object_t *p15_obj;
+	sc_path_t path;
+	struct sc_file *file = NULL;
+	size_t len;
+	int rv;
+	int i;
+
+	sc_context_t *ctx = p15card->card->ctx;
+	LOG_FUNC_CALLED(ctx);
+
+	/* Check for correct card atr */
+	if (pteid_detect_card(p15card->card) != SC_SUCCESS)
+		return SC_ERROR_WRONG_CARD;
+
+	sc_log(p15card->card->ctx, "Selecting application DF");
+	sc_format_path("4F00", &path);
+	rv = sc_select_file(p15card->card, &path, &file);
+	if (rv != SC_SUCCESS || !file)
+		return SC_ERROR_INTERNAL;
+	/* set the application DF */
+	if (p15card->file_app)
+		free(p15card->file_app);
+	p15card->file_app = file;
+
+	/* Load TokenInfo */
+	len = sizeof(buf);
+	rv = dump_ef(p15card->card, "4F005032", buf, &len);
+	if (rv != SC_SUCCESS) {
+		sc_log(ctx, "Reading of EF.TOKENINFO failed: %d", rv);
+		LOG_FUNC_RETURN(ctx, rv);
 	}
-	memset(&tokeninfo, 0, sizeof(tokeninfo));
-	r = sc_pkcs15_parse_tokeninfo(ctx, &tokeninfo, buf, (size_t) r);
-	if (r != SC_SUCCESS)
-		goto end;
-
-	*(p15card->tokeninfo) = tokeninfo;
-
-	/* Card type detection */
-	if (card->type == SC_CARD_TYPE_IAS_PTEID)
-		type = IAS_CARD;
-	else if (card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID)
-		type = GEMSAFE_CARD;
-	else {
-		r = SC_ERROR_INTERNAL;
-		goto end;
+	memset(p15card->tokeninfo, 0, sizeof(*p15card->tokeninfo));
+	rv = sc_pkcs15_parse_tokeninfo(p15card->card->ctx, p15card->tokeninfo,
+				       buf, len);
+	if (rv != SC_SUCCESS) {
+		sc_log(ctx, "Decoding of EF.TOKENINFO failed: %d", rv);
+		LOG_FUNC_RETURN(ctx, rv);
 	}
 
-	p15card->tokeninfo->flags = SC_PKCS15_TOKEN_PRN_GENERATION
+	p15card->tokeninfo->flags |= SC_PKCS15_TOKEN_PRN_GENERATION
 				  | SC_PKCS15_TOKEN_EID_COMPLIANT
 				  | SC_PKCS15_TOKEN_READONLY;
 
-	/* TODO: Use the cardholder's name?  */
-	/* TODO: Use Portuguese descriptions? */
-	
-	/* Add X.509 Certificates */
-	for (i = 0; i < 4; i++) {
-		static const char *pteid_cert_names[4] = {
-				"AUTHENTICATION CERTIFICATE",
-				"SIGNATURE CERTIFICATE",
-				"SIGNATURE SUB CA",
-				"AUTHENTICATION SUB CA"
-		};
-		/* X.509 Certificate Paths */
-		static const char *pteid_cert_paths[4] = {
-			"3f005f00ef09", /* Authentication Certificate path */
-			"3f005f00ef08", /* Digital Signature Certificate path */
-			"3f005f00ef0f", /* Signature sub CA path */
-			"3f005f00ef10"	/* Authentication sub CA path */
-		};
-		/* X.509 Certificate IDs */
-		static const int pteid_cert_ids[4] = {0x45, 0x46, 0x51, 0x52};
-		struct sc_pkcs15_cert_info cert_info;
-		struct sc_pkcs15_object cert_obj;
-
-		memset(&cert_info, 0, sizeof(cert_info));
-		memset(&cert_obj, 0, sizeof(cert_obj));
-
-		cert_info.id.value[0] = pteid_cert_ids[i];
-		cert_info.id.len = 1;
-		sc_format_path(pteid_cert_paths[i], &cert_info.path);
-		strlcpy(cert_obj.label, pteid_cert_names[i], sizeof(cert_obj.label));
-		r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
-		if (r < 0) {
-			r = SC_ERROR_INTERNAL;
-			goto end;
-		}
+	/* Load ODF */
+	len = sizeof(buf);
+	rv = dump_ef(p15card->card, "4F005031", buf, &len);
+	if (rv != SC_SUCCESS) {
+		sc_log(ctx, "Reading of ODF failed: %d", rv);
+		LOG_FUNC_RETURN(ctx, rv);
 	}
-	
-	/* Add PINs */
-	for (i = 0; i < 3; i++) {
-		static const char *pteid_pin_names[3] = {
-			"Auth PIN",
-			"Sign PIN",
-			"Address PIN"
-		};
-		/* PIN References */
-		static const int pteid_pin_ref[2][3] = { {1, 130, 131}, {129, 130, 131} };
-		/* PIN Authentication IDs */
-		static const int pteid_pin_authid[3] = {1, 2, 3};
-		/* PIN Paths */
-		static const char *pteid_pin_paths[2][3] = { {NULL, "3f005f00", "3f005f00"},
-													 {NULL, NULL, NULL} };
-		struct sc_pkcs15_auth_info pin_info;
-		struct sc_pkcs15_object pin_obj;
-
-		memset(&pin_info, 0, sizeof(pin_info));
-		memset(&pin_obj, 0, sizeof(pin_obj));
-
-		pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
-		pin_info.auth_id.len = 1;
-		pin_info.auth_id.value[0] = pteid_pin_authid[i];
-		pin_info.attrs.pin.reference = pteid_pin_ref[type][i];
-		pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_NEEDS_PADDING
-						 | SC_PKCS15_PIN_FLAG_INITIALIZED
-						 | SC_PKCS15_PIN_FLAG_CASE_SENSITIVE;
-		pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC;
-		pin_info.attrs.pin.min_length = 4;
-		pin_info.attrs.pin.stored_length = 8;
-		pin_info.attrs.pin.max_length = 8;
-		pin_info.attrs.pin.pad_char = type == IAS_CARD ? 0x2F : 0xFF;
-		pin_info.tries_left = -1;
-		pin_info.logged_in = SC_PIN_STATE_UNKNOWN;
-		if (pteid_pin_paths[type][i] != NULL)
-			sc_format_path(pteid_pin_paths[type][i], &pin_info.path);
-		strlcpy(pin_obj.label, pteid_pin_names[i], sizeof(pin_obj.label));
-		pin_obj.flags = 0;
-		r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
-		if (r < 0) {
-			r = SC_ERROR_INTERNAL;
-			goto end;
+	rv = parse_odf(buf, len, p15card);
+	if (rv != SC_SUCCESS) {
+		sc_log(ctx, "Decoding of ODF failed: %d", rv);
+		LOG_FUNC_RETURN(ctx, rv);
+	}
+
+	/* Decode EF.PrKDF, EF.PuKDF, EF.CDF and EF.AODF */
+	for (df = p15card->df_list; df != NULL; df = df->next) {
+		if (df->type == SC_PKCS15_PRKDF) {
+			rv = sc_pkcs15_parse_df(p15card, df);
+			if (rv != SC_SUCCESS) {
+				sc_log(ctx,
+				       "Decoding of EF.PrKDF (%s) failed: %d",
+				       sc_print_path(&df->path), rv);
+			}
+		}
+		if (df->type == SC_PKCS15_PUKDF) {
+			rv = sc_pkcs15_parse_df(p15card, df);
+			if (rv != SC_SUCCESS) {
+				sc_log(ctx,
+				       "Decoding of EF.PuKDF (%s) failed: %d",
+				       sc_print_path(&df->path), rv);
+			}
+		}
+		if (df->type == SC_PKCS15_CDF) {
+			rv = sc_pkcs15_parse_df(p15card, df);
+			if (rv != SC_SUCCESS) {
+				sc_log(ctx,
+				       "Decoding of EF.CDF (%s) failed: %d",
+				       sc_print_path(&df->path), rv);
+			}
+		}
+		if (df->type == SC_PKCS15_AODF) {
+			rv = sc_pkcs15_parse_df(p15card, df);
+			if (rv != SC_SUCCESS) {
+				sc_log(ctx,
+				       "Decoding of EF.AODF (%s) failed: %d",
+				       sc_print_path(&df->path), rv);
+			}
 		}
 	}
 
-	/* Add Private Keys */
-	for (i = 0; i < 2; i++) {
-		/* Key reference */
-		static const int pteid_prkey_keyref[2][2] = { {1, 130}, {2, 1} };
-		/* RSA Private Key usage */
-		static int pteid_prkey_usage[2] = {
-			SC_PKCS15_PRKEY_USAGE_SIGN,
-			SC_PKCS15_PRKEY_USAGE_NONREPUDIATION};
-		/* RSA Private Key IDs */
-		static const int pteid_prkey_ids[2] = {0x45, 0x46};
-		static const char *pteid_prkey_names[2] = {
-				"CITIZEN AUTHENTICATION KEY",
-				"CITIZEN SIGNATURE KEY"};
-		/* RSA Private Key Paths */
-		static const char *pteid_prkey_paths[2][2] = { {NULL, "3f005f00"}, {NULL, NULL} };
-		struct sc_pkcs15_prkey_info prkey_info;
-		struct sc_pkcs15_object prkey_obj;
-
-		memset(&prkey_info, 0, sizeof(prkey_info));
-		memset(&prkey_obj, 0, sizeof(prkey_obj));
-
-		prkey_info.id.len = 1;
-		prkey_info.id.value[0] = pteid_prkey_ids[i];
-		prkey_info.usage = pteid_prkey_usage[i];
-		prkey_info.native = 1;
-		prkey_info.key_reference = pteid_prkey_keyref[type][i];
-		prkey_info.modulus_length = 1024;
-		if (pteid_prkey_paths[type][i] != NULL)
-			sc_format_path(pteid_prkey_paths[type][i], &prkey_info.path);
-		strlcpy(prkey_obj.label, pteid_prkey_names[i], sizeof(prkey_obj.label));
-		prkey_obj.auth_id.len = 1;
-		prkey_obj.auth_id.value[0] = i + 1;
-		prkey_obj.user_consent = (i == 1) ? 1 : 0;
-		prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
-
-		r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
-		if (r < 0) {
-			r = SC_ERROR_INTERNAL;
-			goto end;
+	p15_obj = p15card->obj_list;
+	while (p15_obj != NULL) {
+		if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_PRKDF) ) {
+			struct sc_pkcs15_prkey_info *prkey_info = (sc_pkcs15_prkey_info_t *) p15_obj->data;
+			prkey_info->access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE
+					| SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE
+					| SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE
+					| SC_PKCS15_PRKEY_ACCESS_LOCAL;
+			p15_obj->flags = SC_PKCS15_CO_FLAG_PRIVATE;
+		}
+
+
+		if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_AODF) ) {
+			static const char *pteid_pin_names[3] = {
+			    "Auth PIN",
+			    "Sign PIN",
+			    "Address PIN"
+			};
+
+			struct sc_pin_cmd_data pin_cmd_data;
+			struct sc_pkcs15_auth_info *pin_info = (sc_pkcs15_auth_info_t *) p15_obj->data;
+
+			strlcpy(p15_obj->label, pteid_pin_names[pin_info->auth_id.value[0]-1], sizeof(p15_obj->label));
+
+			pin_info->attrs.pin.flags |= SC_PKCS15_PIN_FLAG_NEEDS_PADDING;
+			pin_info->tries_left = -1;
+			pin_info->max_tries = 3;
+			pin_info->auth_method = SC_AC_CHV;
+
+			memset(&pin_cmd_data, 0, sizeof(pin_cmd_data));
+			pin_cmd_data.cmd = SC_PIN_CMD_GET_INFO;
+			pin_cmd_data.pin_type = pin_info->attrs.pin.type;
+			pin_cmd_data.pin_reference = pin_info->attrs.pin.reference;
+			rv = sc_pin_cmd(p15card->card, &pin_cmd_data, NULL);
+			if (rv == SC_SUCCESS) {
+				pin_info->tries_left = pin_cmd_data.pin1.tries_left;
+			}
+		}
+		/* Remove found public keys as cannot be read_binary()'d */
+		if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_PUKDF) ) {
+			sc_pkcs15_object_t *puk = p15_obj;
+			p15_obj = p15_obj->next;
+			sc_pkcs15_remove_object(p15card, puk);
+			sc_pkcs15_free_object(puk);
+		} else {
+			p15_obj = p15_obj->next;
 		}
 	}
 
-	/* Add objects */
-	for (i = 0; i < 3; i++) {
-		static const char *object_ids[3] = {"01", "02", "03"};
-		static const char *object_labels[3] = {"Citizen Data",
-											   "Citizen Address Data",
-											   "Citizen Notepad"};
-		static const char *object_authids[3] = {NULL, "03", "01"};
-		static const char *object_paths[3] = {"3f005f00ef02",
-											  "3f005f00ef05",
-											  "3f005f00ef07"};
-		static const int object_flags[3] = {0,
-											SC_PKCS15_CO_FLAG_PRIVATE,
-											SC_PKCS15_CO_FLAG_MODIFIABLE};
+	/* Add data objects */
+	for (i = 0; i < 5; i++) {
+		static const char *object_ids[5] = {"1", "2", "3", "4", "5"};
+		static const char *object_labels[5] = {
+			"Citizen Data",
+			"Citizen Address Data",
+			"Citizen Notepad",
+			"SOD",
+			"TRACE",
+		};
+		static const char *object_authids[5] = {NULL, "3", NULL, NULL, NULL};
+		static const char *object_paths[5] = {
+			"3f005f00ef02",
+			"3f005f00ef05",
+			"3f005f00ef07",
+			"3f005f00ef06",
+			"3F000003",
+		};
+		static const int object_flags[5] = {
+			0,
+			SC_PKCS15_CO_FLAG_PRIVATE,
+			0,
+			0,
+			0,
+		};
 		struct sc_pkcs15_data_info obj_info;
 		struct sc_pkcs15_object obj_obj;
 
@@ -253,37 +325,36 @@ static int sc_pkcs15emu_pteid_init(sc_pkcs15_card_t * p15card)
 		strlcpy(obj_obj.label, object_labels[i], SC_PKCS15_MAX_LABEL_SIZE);
 		obj_obj.flags = object_flags[i];
 
-		r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT, &obj_obj, &obj_info);
-		if (r < 0)
-			goto end;
-	}
-end:
-	if (buf != NULL) {
-		free(buf);
-		buf = NULL;
+		rv = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT, &obj_obj, &obj_info);
+		if (rv != SC_SUCCESS){
+			sc_log(ctx, "Object add failed: %d", rv);
+			break;
+		}
 	}
-	if (r)
-		return r;
 
-	return SC_SUCCESS;
+	LOG_FUNC_RETURN(ctx, SC_SUCCESS);
 }
 
-static int pteid_detect_card(sc_pkcs15_card_t *p15card)
+static int pteid_detect_card(struct sc_card *card)
 {
-	if (p15card->card->type == SC_CARD_TYPE_IAS_PTEID ||
-		p15card->card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID)
+	if (card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID)
 		return SC_SUCCESS;
 	return SC_ERROR_WRONG_CARD;
 }
 
 int sc_pkcs15emu_pteid_init_ex(sc_pkcs15_card_t *p15card, struct sc_aid *aid, sc_pkcs15emu_opt_t *opts)
 {
-	if (opts != NULL && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)
-		return sc_pkcs15emu_pteid_init(p15card);
-	else {
-		int r = pteid_detect_card(p15card);
-		if (r)
-			return SC_ERROR_WRONG_CARD;
-		return sc_pkcs15emu_pteid_init(p15card);
-	}
+	int r=SC_SUCCESS;
+	sc_context_t *ctx = p15card->card->ctx;
+	LOG_FUNC_CALLED(ctx);
+
+	/* if no check flag execute unconditionally */
+	if (opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)
+		LOG_FUNC_RETURN(ctx, sc_pkcs15emu_pteid_init(p15card));
+	/* check for proper card */
+	r = pteid_detect_card(p15card->card);
+	if (r == SC_ERROR_WRONG_CARD)
+		LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_CARD);
+	/* ok: initialize and return */
+	LOG_FUNC_RETURN(ctx, sc_pkcs15emu_pteid_init(p15card));
 }
diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c
index 14f4d2f..0163f48 100644
--- a/src/libopensc/pkcs15-syn.c
+++ b/src/libopensc/pkcs15-syn.c
@@ -76,7 +76,6 @@ int sc_pkcs15_is_emulation_only(sc_card_t *card)
 		case SC_CARD_TYPE_MCRD_ESTEID_V10:
 		case SC_CARD_TYPE_MCRD_ESTEID_V11:
 		case SC_CARD_TYPE_MCRD_ESTEID_V30:
-		case SC_CARD_TYPE_IAS_PTEID:
 		case SC_CARD_TYPE_GEMSAFEV1_PTEID:
 		case SC_CARD_TYPE_OPENPGP_V1:
 		case SC_CARD_TYPE_OPENPGP_V2:

-- 
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