[svn] GnuPG - r4912 - in trunk: g10 scd
svn author wk
cvs at cvs.gnupg.org
Thu Jan 8 20:56:30 CET 2009
Author: wk
Date: 2009-01-08 20:56:30 +0100 (Thu, 08 Jan 2009)
New Revision: 4912
Modified:
trunk/g10/misc.c
trunk/scd/ChangeLog
trunk/scd/apdu.c
trunk/scd/app-nks.c
trunk/scd/command.c
trunk/scd/iso7816.c
trunk/scd/iso7816.h
Log:
Add limited support for NetKey 3.0 cards.
Modified: trunk/scd/ChangeLog
===================================================================
--- trunk/scd/ChangeLog 2009-01-08 19:51:59 UTC (rev 4911)
+++ trunk/scd/ChangeLog 2009-01-08 19:56:30 UTC (rev 4912)
@@ -1,3 +1,18 @@
+2009-01-08 Werner Koch <wk at g10code.com>
+
+ * iso7816.c (iso7816_read_record, iso7816_read_binary): Pass 0 for
+ L_e because the problem with the CCID driver has gone.
+ (iso7816_apdu_direct): New.
+
+ * app-nks.c (filelist): Add NKS_VER field. Add NKS 3 specific
+ entries.
+ (app_local_s, do_deinit): New.
+ (get_nks_version): New.
+ (app_select_nks): Setup local data.
+ (keygripstr_from_pk_file): Replace SLOT by APP and take care of
+ NKS version > 2.
+ (do_learn_status): Take care of NKS version.
+
2009-01-05 Werner Koch <wk at g10code.com>
* apdu.c (apdu_get_status): Save the last status.
Modified: trunk/g10/misc.c
===================================================================
--- trunk/g10/misc.c 2009-01-08 19:51:59 UTC (rev 4911)
+++ trunk/g10/misc.c 2009-01-08 19:56:30 UTC (rev 4912)
@@ -1248,17 +1248,16 @@
}
-/* Check whether the string has characters not valid in an RFC822
+/* Check whether the string has characters not valid in an RFC-822
address. To cope with OpenPGP we ignore allow non-ascii characters
so that for example umlauts are legal in an email address. An
- OpenPGP user ID must be utf-8 encoded and tehre is no strict
+ OpenPGP user ID must be utf-8 encoded but there is no strict
requirement for RFC-822. Thus to avoid IDNA encoding we put the
- address verbatim as utf-8 into the user ID under the assumtiopn
- that mail programs etc handle IDNA at a lower level and take
- OpenPGP user IDS as utf-8. Note that we can't do an utf-8 encoding
- checking here becuase in keygen.c this function is called with the
- native encoding and native to utf-8 encoding is done only after
- checking. */
+ address verbatim as utf-8 into the user ID under the assumption
+ that mail programs handle IDNA at a lower level and take OpenPGP
+ user IDs as utf-8. Note that we can't do an utf-8 encoding
+ checking here because in keygen.c this function is called with the
+ native encoding and native to utf-8 encoding is only done later. */
int
has_invalid_email_chars (const char *s)
{
Modified: trunk/scd/apdu.c
===================================================================
--- trunk/scd/apdu.c 2009-01-08 19:51:59 UTC (rev 4911)
+++ trunk/scd/apdu.c 2009-01-08 19:56:30 UTC (rev 4912)
@@ -2793,9 +2793,9 @@
related operations if not NULL. If EXTENDED_MODE is not NULL
command chaining or extended length will be used according to these
values:
- n < 0 := Use command chaining without the data part limited to -n
+ n < 0 := Use command chaining with the data part limited to -n
in each chunk. If -1 is used a default value is used.
- n == 1 := Use extended length for input and output with out a
+ n == 1 := Use extended length for input and output without a
length limit.
n > 1 := Use extended length with up to N bytes.
*/
@@ -3107,7 +3107,7 @@
/* This is a more generic version of the apdu sending routine. It
takes an already formatted APDU in APDUDATA or length APDUDATALEN
- and returns the with an APDU including the status word. With
+ and returns with an APDU including the status word. With
HANDLE_MORE set to true this function will handle the MORE DATA
status and return all APDUs concatenated with one status word at
the end. The function does not return a regular status word but 0
@@ -3237,7 +3237,7 @@
}
}
else
- log_info ("apdu_send_sdirect(%d) "
+ log_info ("apdu_send_direct(%d) "
"got unexpected status %04X from get response\n",
slot, sw);
}
@@ -3268,8 +3268,8 @@
unlock_slot (slot);
- /* Append the status word - we reseved the two extra bytes while
- allocating the buffer. */
+ /* Append the status word. Note that we reserved the two extra
+ bytes while allocating the buffer. */
if (retbuf)
{
(*retbuf)[(*retbuflen)++] = (sw >> 8);
Modified: trunk/scd/app-nks.c
===================================================================
--- trunk/scd/app-nks.c 2009-01-08 19:51:59 UTC (rev 4911)
+++ trunk/scd/app-nks.c 2009-01-08 19:56:30 UTC (rev 4912)
@@ -1,5 +1,5 @@
-/* app-nks.c - The Telesec NKS 2.0 card application.
- * Copyright (C) 2004, 2007, 2008 Free Software Foundation, Inc.
+/* app-nks.c - The Telesec NKS card application.
+ * Copyright (C) 2004, 2007, 2008, 2009 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -34,29 +34,55 @@
static struct
{
int fid; /* File ID. */
+ int nks_ver; /* 0 for NKS version 2, 3 for version 3. */
int certtype; /* Type of certificate or 0 if it is not a certificate. */
int iskeypair; /* If true has the FID of the correspoding certificate. */
int issignkey; /* True if file is a key usable for signing. */
int isenckey; /* True if file is a key usable for decryption. */
} filelist[] = {
- { 0x4531, 0, 0xC000, 1, 0 },
- { 0xC000, 101 },
- { 0x4331, 100 },
- { 0x4332, 100 },
- { 0xB000, 110 },
- { 0x45B1, 0, 0xC200, 0, 1 },
- { 0xC200, 101 },
- { 0x43B1, 100 },
- { 0x43B2, 100 },
- { 0, 0 }
+ { 0x4531, 0, 0, 0xC000, 1, 0 }, /* EF_PK.NKS.SIG */
+ { 0xC000, 0, 101 }, /* EF_C.NKS.SIG */
+ { 0x4331, 0, 100 },
+ { 0x4332, 0, 100 },
+ { 0xB000, 0, 110 }, /* EF_PK.RCA.NKS */
+ { 0x45B1, 0, 0, 0xC200, 0, 1 }, /* EF_PK.NKS.ENC */
+ { 0xC200, 0, 101 }, /* EF_C.NKS.ENC */
+ { 0x43B1, 0, 100 },
+ { 0x43B2, 0, 100 },
+ { 0x4571, 3, 0, 0xc500, 0, 0 }, /* EF_PK.NKS.AUT */
+ { 0xC500, 3, 101 }, /* EF_C.NKS.AUT */
+ { 0x45B2, 3, 0, 0xC201, 0, 1 }, /* EF_PK.NKS.ENC1024 */
+ { 0xC201, 3, 101 }, /* EF_C.NKS.ENC1024 */
+ { 0 }
};
+/* Object with application (i.e. NKS) specific data. */
+struct app_local_s {
+ int nks_version; /* NKS version. */
+
+};
+
+
+
+
+/* Release local data. */
+static void
+do_deinit (app_t app)
+{
+ if (app && app->app_local)
+ {
+ xfree (app->app_local);
+ app->app_local = NULL;
+ }
+}
+
+
/* Read the file with FID, assume it contains a public key and return
its keygrip in the caller provided 41 byte buffer R_GRIPSTR. */
static gpg_error_t
-keygripstr_from_pk_file (int slot, int fid, char *r_gripstr)
+keygripstr_from_pk_file (app_t app, int fid, char *r_gripstr)
{
gpg_error_t err;
unsigned char grip[20];
@@ -65,29 +91,34 @@
gcry_sexp_t sexp;
int i;
- err = iso7816_select_file (slot, fid, 0, NULL, NULL);
+ err = iso7816_select_file (app->slot, fid, 0, NULL, NULL);
if (err)
return err;
- err = iso7816_read_record (slot, 1, 1, 0, &buffer[0], &buflen[0]);
+ err = iso7816_read_record (app->slot, 1, 1, 0, &buffer[0], &buflen[0]);
if (err)
return err;
- err = iso7816_read_record (slot, 2, 1, 0, &buffer[1], &buflen[1]);
+ err = iso7816_read_record (app->slot, 2, 1, 0, &buffer[1], &buflen[1]);
if (err)
{
xfree (buffer[0]);
return err;
}
- for (i=0; i < 2; i++)
+ if (app->app_local->nks_version < 3)
{
- /* Check that the value appears like an integer encoded as
- Simple-TLV. We don't check the tag because the tests cards I
- have use 1 for both, the modulus and the exponent - the
- example in the documentation gives 2 for the exponent. */
- if (buflen[i] < 3)
- err = gpg_error (GPG_ERR_TOO_SHORT);
- else if (buffer[i][1] != buflen[i]-2 )
- err = gpg_error (GPG_ERR_INV_OBJ);
+ /* Old versions of NKS store the values in a TLV encoded format.
+ We need to do some checks. */
+ for (i=0; i < 2; i++)
+ {
+ /* Check that the value appears like an integer encoded as
+ Simple-TLV. We don't check the tag because the tests cards I
+ have use 1 for both, the modulus and the exponent - the
+ example in the documentation gives 2 for the exponent. */
+ if (buflen[i] < 3)
+ err = gpg_error (GPG_ERR_TOO_SHORT);
+ else if (buffer[i][1] != buflen[i]-2 )
+ err = gpg_error (GPG_ERR_INV_OBJ);
+ }
}
if (!err)
@@ -126,6 +157,9 @@
/* Output information about all useful objects. */
for (i=0; filelist[i].fid; i++)
{
+ if (filelist[i].nks_ver > app->app_local->nks_version)
+ continue;
+
if (filelist[i].certtype)
{
size_t len;
@@ -149,7 +183,7 @@
{
char gripstr[40+1];
- err = keygripstr_from_pk_file (app->slot, filelist[i].fid, gripstr);
+ err = keygripstr_from_pk_file (app, filelist[i].fid, gripstr);
if (err)
log_error ("can't get keygrip from FID 0x%04X: %s\n",
filelist[i].fid, gpg_strerror (err));
@@ -580,7 +614,40 @@
}
-/* Select the NKS 2.0 application. */
+/* Return the version of the NKS application. */
+static int
+get_nks_version (int slot)
+{
+ unsigned char *result = NULL;
+ size_t resultlen;
+ int type;
+
+ if (iso7816_apdu_direct (slot, "\x80\xaa\x06\x00\x00", 5, 0,
+ &result, &resultlen))
+ return 2; /* NKS 2 does not support this command. */
+
+ /* Example value: 04 11 19 22 21 6A 20 80 03 03 01 01 01 00 00 00
+ vv tt ccccccccccccccccc aa bb cc vvvvvvvvvvv xx
+ vendor (Philips) -+ | | | | | | |
+ chip type -----------+ | | | | | |
+ chip id ----------------+ | | | | |
+ card type (3 - tcos 3) -------------------+ | | | |
+ OS version of card type ---------------------+ | | |
+ OS release of card type ------------------------+ | |
+ OS vendor internal version ------------------------+ |
+ RFU -----------------------------------------------------------+
+ */
+ if (resultlen < 16)
+ type = 0; /* Invalid data returned. */
+ else
+ type = result[8];
+ xfree (result);
+
+ return type;
+}
+
+
+/* Select the NKS application. */
gpg_error_t
app_select_nks (app_t app)
{
@@ -593,6 +660,18 @@
{
app->apptype = "NKS";
+ app->app_local = xtrycalloc (1, sizeof *app->app_local);
+ if (!app->app_local)
+ {
+ rc = gpg_error (gpg_err_code_from_errno (errno));
+ goto leave;
+ }
+
+ app->app_local->nks_version = get_nks_version (slot);
+ if (opt.verbose)
+ log_info ("Detected NKS version: %d\n", app->app_local->nks_version);
+
+ app->fnc.deinit = do_deinit;
app->fnc.learn_status = do_learn_status;
app->fnc.readcert = do_readcert;
app->fnc.getattr = NULL;
@@ -605,6 +684,9 @@
app->fnc.check_pin = do_check_pin;
}
+ leave:
+ if (rc)
+ do_deinit (app);
return rc;
}
Modified: trunk/scd/command.c
===================================================================
--- trunk/scd/command.c 2009-01-08 19:51:59 UTC (rev 4911)
+++ trunk/scd/command.c 2009-01-08 19:56:30 UTC (rev 4912)
@@ -559,7 +559,7 @@
100 := Regular X.509 cert
101 := Trusted X.509 cert
102 := Useful X.509 cert
- 110 := Root CA cert (DINSIG)
+ 110 := Root CA cert (e.g. DINSIG)
For certain cards, more information will be returned:
Modified: trunk/scd/iso7816.c
===================================================================
--- trunk/scd/iso7816.c 2009-01-08 19:51:59 UTC (rev 4911)
+++ trunk/scd/iso7816.c 2009-01-08 19:56:30 UTC (rev 4912)
@@ -1,5 +1,5 @@
/* iso7816.c - ISO 7816 commands
- * Copyright (C) 2003, 2004, 2008 Free Software Foundation, Inc.
+ * Copyright (C) 2003, 2004, 2008, 2009 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -226,6 +226,48 @@
}
+/* This funcion sends an already formatted APDU to the card. With
+ HANDLE_MORE set to true a MORE DATA status will be handled
+ internally. The return value is a gpg error code (i.e. a mapped
+ status word). This is basically the same as apdu_send_direct but
+ it maps the status word and does not return it in the result
+ buffer. */
+gpg_error_t
+iso7816_apdu_direct (int slot, const void *apdudata, size_t apdudatalen,
+ int handle_more,
+ unsigned char **result, size_t *resultlen)
+{
+ int sw;
+
+ if (!result || !resultlen)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ *result = NULL;
+ *resultlen = 0;
+
+ sw = apdu_send_direct (slot, apdudata, apdudatalen, handle_more,
+ result, resultlen);
+ if (!sw)
+ {
+ if (*resultlen < 2)
+ sw = SW_HOST_GENERAL_ERROR;
+ else
+ {
+ sw = ((*result)[*resultlen-2] << 8) | (*result)[*resultlen-1];
+ (*resultlen)--;
+ (*resultlen)--;
+ }
+ }
+ if (sw != SW_SUCCESS)
+ {
+ /* Make sure that pending buffers are released. */
+ xfree (*result);
+ *result = NULL;
+ *resultlen = 0;
+ }
+ return map_sw (sw);
+}
+
+
/* Check whether the reader supports the ISO command code COMMAND on
the keypad. Returns 0 on success. */
gpg_error_t
@@ -668,14 +710,7 @@
{
buffer = NULL;
bufferlen = 0;
- /* Note, that we to set N to 254 due to problems either with the
- ccid driver or some TCOS cards. It actually should be 0
- which is the official ISO value to read a variable length
- object. */
- if (read_all || nmax > 254)
- n = 254;
- else
- n = nmax;
+ n = read_all? 0 : nmax;
sw = apdu_send_le (slot, 0x00, CMD_READ_BINARY,
((offset>>8) & 0xff), (offset & 0xff) , -1, NULL,
n, &buffer, &bufferlen);
@@ -769,13 +804,11 @@
buffer = NULL;
bufferlen = 0;
- /* Fixme: Either the ccid driver or the TCOS cards have problems
- with an Le of 0. */
sw = apdu_send_le (slot, 0x00, CMD_READ_RECORD,
recno,
short_ef? short_ef : 0x04,
-1, NULL,
- 254, &buffer, &bufferlen);
+ 0, &buffer, &bufferlen);
if (sw != SW_SUCCESS && sw != SW_EOF_REACHED)
{
Modified: trunk/scd/iso7816.h
===================================================================
--- trunk/scd/iso7816.h 2009-01-08 19:51:59 UTC (rev 4911)
+++ trunk/scd/iso7816.h 2009-01-08 19:56:30 UTC (rev 4912)
@@ -57,6 +57,10 @@
unsigned char **result, size_t *resultlen);
gpg_error_t iso7816_list_directory (int slot, int list_dirs,
unsigned char **result, size_t *resultlen);
+gpg_error_t iso7816_apdu_direct (int slot,
+ const void *apdudata, size_t apdudatalen,
+ int handle_more,
+ unsigned char **result, size_t *resultlen);
gpg_error_t iso7816_check_keypad (int slot, int command,
iso7816_pininfo_t *pininfo);
gpg_error_t iso7816_verify (int slot,
More information about the Gnupg-commits
mailing list