[pkg-opensc-commit] [SCM] OpenSC packaging branch, master, updated. e33dcfc0130b71d0eb1e023fa996e19232e2f7cc

Eric Dorland eric at debian.org
Thu Jul 31 19:18:07 UTC 2008


The following commit has been merged in the master branch:
commit e33dcfc0130b71d0eb1e023fa996e19232e2f7cc
Author: Eric Dorland <eric at debian.org>
Date:   Thu Jul 31 13:28:23 2008 -0400

    src/libopensc/card-cardos.c, src/tools/pkcs15-tool.c: Patch to fix CVE-2008-2235 "OpenSC initializes CardOS cards with improper  access rights".

diff --git a/debian/changelog b/debian/changelog
index dc188a0..edb0e2d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,9 +1,12 @@
-opensc (0.11.4-4) unstable; urgency=low
+opensc (0.11.4-4) unstable; urgency=high
 
+  * src/libopensc/card-cardos.c, src/tools/pkcs15-tool.c: Patch to fix
+    CVE-2008-2235 "OpenSC initializes CardOS cards with improper 
+    access rights".
   * debian/control: Up Standards-Version to 3.7.3.
   * debian/opensc.NEWS: Fix typo.
 
- --
+ -- Eric Dorland <eric at debian.org>  Thu, 31 Jul 2008 13:27:31 -0400
 
 opensc (0.11.4-3) unstable; urgency=low
 
diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c
index 6e7ca10..7a5ee6e 100644
--- a/src/libopensc/card-cardos.c
+++ b/src/libopensc/card-cardos.c
@@ -385,7 +385,7 @@ static const int df_acl[9] = {
 	SC_AC_OP_REHABILITATE,	/* DF */
 	SC_AC_OP_DELETE,	/* DF */
 
-	-1,			/* ADMIN DF */
+	SC_AC_OP_UPDATE,	/* ADMIN DF */
 	SC_AC_OP_CREATE,	/* Files */
 	-1			/* Reserved */
 };
@@ -400,7 +400,7 @@ static const int ef_acl[9] = {
 
 	/* XXX: ADMIN should be an ACL type of its own, or mapped
 	 * to erase */
-	-1,			/* ADMIN EF (modify meta information?) */
+	SC_AC_OP_UPDATE,	/* ADMIN EF (modify meta information?) */
 	-1,			/* INC (-> cylic fixed files) */
 	-1			/* DEC */
 };
diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c
index 0d38ce2..1ce8d56 100644
--- a/src/tools/pkcs15-tool.c
+++ b/src/tools/pkcs15-tool.c
@@ -2,6 +2,7 @@
  * pkcs15-tool.c: Tool for poking with PKCS #15 smart cards
  *
  * Copyright (C) 2001  Juha Yrjölä <juha.yrjola at iki.fi>
+ * Copyright (C) 2008  Andreas Jellinghaus <aj at dungeon.inka.de>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -90,6 +91,8 @@ static const struct option options[] = {
 #if defined(HAVE_OPENSSL) && (defined(_WIN32) || defined(HAVE_INTTYPES_H))
 	{ "read-ssh-key",	required_argument, NULL,	OPT_READ_SSH },
 #endif
+	{ "test-update",	no_argument, NULL,		'T' },
+	{ "update",		no_argument, NULL,		'U' },
 	{ "reader",		required_argument, NULL,	OPT_READER },
 	{ "pin",                required_argument, NULL,   OPT_PIN },
 	{ "new-pin",		required_argument, NULL,	OPT_NEWPIN },
@@ -116,6 +119,8 @@ static const char *option_help[] = {
 	"Lists public keys",
 	"Reads public key with ID <arg>",
 	"Reads public key with ID <arg>, outputs ssh format",
+	"Test if the card needs a security update",
+	"Update the card with a security update",
 	"Uses reader number <arg>",
 	"Specify PIN",
 	"Specify New PIN (when changing or unblocking)",
@@ -1175,6 +1180,182 @@ static int learn_card(void)
 	return 0;
 }
 
+static int test_update(sc_card_t *in_card)
+{
+	sc_apdu_t apdu;
+	static u8 cmd1[2] = { 0x50, 0x15};
+	u8 rbuf[258];
+        int rc;
+	int r;
+	static u8 fci_bad[] = { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+	static u8 fci_good[] = { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00 };
+
+
+
+        if (strcmp("cardos",in_card->driver->short_name) != 0) {
+ 		printf("not using the cardos driver, card is fine.");
+		rc = 0;
+                goto end;
+        }
+
+        if (strcmp("OpenSC Card",p15card->label) != 0) {
+		printf("not initialized by opensc, card is fine.");
+		rc = 0;
+                goto end;
+        }
+
+	/* first select file on 5015 and get fci */
+	sc_format_apdu(in_card, &apdu, SC_APDU_CASE_4_SHORT, 0xa4, 0x08, 0x00);
+	apdu.lc = sizeof(cmd1);
+	apdu.datalen = sizeof(cmd1);
+	apdu.data = cmd1;
+	apdu.le = 256;
+	apdu.resp = rbuf;
+	apdu.resplen = sizeof(rbuf);
+
+	r = sc_transmit_apdu(card, &apdu);
+	if (r < 0) {
+		printf("selecting folder failed: %s\n", sc_strerror(r));
+		rc = 2;
+		goto end;
+	}
+
+	if (apdu.sw1 != 0x90) {
+		printf("apdu command select file: card returned %02X %02X\n",
+			apdu.sw1, apdu.sw2);
+		rc = 2;
+		goto end;
+
+	}
+
+	if (apdu.resplen < 6) {
+		printf("select file did not return enough data (length %d)\n",
+			(int) apdu.resplen);
+		goto bad_fci;
+	}
+
+	if (rbuf[0] != 0x6f) {
+		printf("select file did not return the information we need\n");
+		goto bad_fci;
+	}
+
+	if (rbuf[1] != apdu.resplen -2) {
+		printf("select file did return inconsistent information\n");
+		goto bad_fci;
+	}
+
+	{
+		int i=0;
+	  	while(i < rbuf[1]) {
+			if (rbuf[2+i] == 0x86) { /* found our buffer */
+				break;
+			}
+			/* other tag */
+			i += 2 + rbuf[2+i+1]; /* length of this tag*/
+		}	
+		if (rbuf[2+i+1] < 9 || 2+i+2+9 > apdu.resplen) {
+			printf("select file did return short fci\n");
+			goto bad_fci;
+		}
+
+		if (memcmp(&rbuf[2+i+2],fci_good,sizeof(fci_good)) == 0) {
+			printf("fci is up-to-date, card is fine\n");
+			rc = 0;
+			goto end;
+		}
+
+		if (memcmp(&rbuf[2+i+2],fci_bad,sizeof(fci_bad)) == 0) {
+			printf("fci is out-off-date, card is vulnerable\n");
+			rc = 1;
+			goto end;
+		}
+
+		printf("select file returned fci with unknown data\n");
+		goto bad_fci;
+	}
+end:
+	/* 0 = card ok, 1 = card vulnerable, 2 = problem! */
+        return rc;
+
+bad_fci:
+	hex_dump(stdout,rbuf,apdu.resplen," ");
+	printf("\n");
+	return 2;
+}
+
+static int update(sc_card_t *in_card)
+{
+	sc_apdu_t apdu;
+	static u8 cmd1[2] = { 0x50, 0x15};
+	static u8 cmd3[11] = { 0x86, 0x09, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+				0xff, 0x00, 0x00};
+	int r;
+
+	/* first select file on 5015 */
+	sc_format_apdu(in_card, &apdu, SC_APDU_CASE_3_SHORT, 0xa4, 0x08, 0x00);
+	apdu.lc = sizeof(cmd1);
+	apdu.datalen = sizeof(cmd1);
+	apdu.data = cmd1;
+
+	r = sc_transmit_apdu(card, &apdu);
+	if (r < 0) {
+		printf("selecting folder failed: %s\n", sc_strerror(r));
+		goto end;
+	}
+
+	if (apdu.sw1 != 0x90) {
+		printf("apdu command select file: card returned %02X %02X\n",
+			apdu.sw1, apdu.sw2);
+		goto end;
+
+	}
+
+	/* next phase control / change lifecycle to operational */
+	memset(&apdu, 0, sizeof(apdu));
+	sc_format_apdu(in_card, &apdu, SC_APDU_CASE_1, 0x10, 0x00, 0x00);
+	apdu.cla = 0x80;
+
+	r = sc_transmit_apdu(card, &apdu);
+	if (r < 0) {
+		printf("change lifecycle failed: %s\n", sc_strerror(r));
+		goto end;
+	}
+
+	if (apdu.sw1 != 0x90) {
+		printf("apdu command change lifecycle failed: card returned %02X %02X\n",
+			apdu.sw1, apdu.sw2);
+		goto end;
+
+	}
+	
+	/* last update AC */
+	memset(&apdu, 0, sizeof(apdu));
+	sc_format_apdu(in_card, &apdu, SC_APDU_CASE_3_SHORT, 0xda, 0x01, 0x6f);
+	apdu.lc = sizeof(cmd3);
+	apdu.datalen = sizeof(cmd3);
+	apdu.data = cmd3;
+	apdu.le = 0;
+	apdu.resplen = 0;
+	apdu.resp = NULL;
+
+	r = sc_transmit_apdu(card, &apdu);
+	if (r < 0) {
+		printf("update fci failed: %s\n", sc_strerror(r));
+		goto end;
+	}
+
+	if (apdu.sw1 != 0x90) {
+		printf("apdu command update fci failed: card returned %02X %02X\n",
+			apdu.sw1, apdu.sw2);
+		goto end;
+
+	}
+	
+	printf("security update applied with success.\n");
+end:
+        return 0;
+}
+
 int main(int argc, char * const argv[])
 {
 	int err = 0, r, c, long_optind = 0;
@@ -1193,11 +1374,13 @@ int main(int argc, char * const argv[])
 	int do_change_pin = 0;
 	int do_unblock_pin = 0;
 	int do_learn_card = 0;
+	int do_test_update = 0;
+	int do_update = 0;
 	int action_count = 0;
 	sc_context_param_t ctx_param;
 
 	while (1) {
-		c = getopt_long(argc, argv, "r:cuko:va:LR:CwD", options, &long_optind);
+		c = getopt_long(argc, argv, "r:cuko:va:LR:CwDTU", options, &long_optind);
 		if (c == -1)
 			break;
 		if (c == '?')
@@ -1261,6 +1444,14 @@ int main(int argc, char * const argv[])
 			do_learn_card = 1;
 			action_count++;
 			break;
+		case 'T':
+			do_test_update = 1;
+			action_count++;
+			break;
+		case 'U':
+			do_update = 1;
+			action_count++;
+			break;
 		case OPT_READER:
 			opt_reader = atoi(optarg);
 			break;
@@ -1388,6 +1579,18 @@ int main(int argc, char * const argv[])
 			goto end;
 		action_count--;
 	}
+	if (do_test_update || do_update) {
+ 		err = test_update(card);
+		action_count--;
+		if (err == 2) { /* problem */
+			err =1;
+			goto end;
+		}
+		if (do_update && err == 1) { /* card vulnerable */
+			if ((err = update(card)))
+				goto end;
+		}
+	}
 end:
 	if (p15card)
 		sc_pkcs15_unbind(p15card);

-- 
OpenSC packaging



More information about the pkg-opensc-commit mailing list