aboutsummaryrefslogtreecommitdiffstats
path: root/scd/app-dinsig.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2008-06-26 19:09:07 +0000
committerWerner Koch <[email protected]>2008-06-26 19:09:07 +0000
commita6a9181818d86219da202137c1697b826a3ea151 (patch)
treeeeaf866d273a9308bf19091b06cd248333cc058a /scd/app-dinsig.c
parentg10/ (diff)
downloadgnupg-a6a9181818d86219da202137c1697b826a3ea151.tar.gz
gnupg-a6a9181818d86219da202137c1697b826a3ea151.zip
Start support of TCOS 3 cards.
Support restriction attribute. Fix utf-8 printing problems. Use AES by default.
Diffstat (limited to 'scd/app-dinsig.c')
-rw-r--r--scd/app-dinsig.c106
1 files changed, 96 insertions, 10 deletions
diff --git a/scd/app-dinsig.c b/scd/app-dinsig.c
index 54b54b150..cd6c3d096 100644
--- a/scd/app-dinsig.c
+++ b/scd/app-dinsig.c
@@ -1,5 +1,5 @@
/* app-dinsig.c - The DINSIG (DIN V 66291-1) card application.
- * Copyright (C) 2002, 2004, 2005, 2007 Free Software Foundation, Inc.
+ * Copyright (C) 2002, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -397,14 +397,20 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */
{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
+ static unsigned char sha256_prefix[19] = /* OID is 2.16.840.1.101.3.4.2.1 */
+ { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+ 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
+ 0x00, 0x04, 0x20 };
int rc;
int fid;
- unsigned char data[35]; /* Must be large enough for a SHA-1 digest
- + the largest OID _prefix above. */
+ unsigned char data[19+32]; /* Must be large enough for a SHA-256 digest
+ + the largest OID _prefix above. */
+ int datalen;
if (!keyidstr || !*keyidstr)
return gpg_error (GPG_ERR_INV_VALUE);
- if (indatalen != 20 && indatalen != 16 && indatalen != 35)
+ if (indatalen != 20 && indatalen != 16 && indatalen != 32
+ && indatalen != (15+20) && indatalen != (19+32))
return gpg_error (GPG_ERR_INV_VALUE);
/* Check that the provided ID is vaid. This is not really needed
@@ -421,7 +427,8 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
return gpg_error (GPG_ERR_NOT_FOUND);
/* Prepare the DER object from INDATA. */
- if (indatalen == 35)
+ datalen = 35;
+ if (indatalen == 15+20)
{
/* Alright, the caller was so kind to send us an already
prepared DER object. Check that it is what we want and that
@@ -434,24 +441,103 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
memcpy (data, indata, indatalen);
}
+ else if (indatalen == 19+32)
+ {
+ /* Alright, the caller was so kind to send us an already
+ prepared DER object. Check that it is what we want and that
+ it matches the hash algorithm. */
+ datalen = indatalen;
+ if (hashalgo == GCRY_MD_SHA256 && !memcmp (indata, sha256_prefix, 19))
+ ;
+ else if (hashalgo == GCRY_MD_SHA1 && !memcmp (indata, sha256_prefix, 19))
+ {
+ /* Fixme: This is a kludge. A better solution is not to use
+ SHA1 as default but use an autodetection. However this
+ needs changes in all app-*.c */
+ hashalgo = GCRY_MD_SHA256;
+ datalen = indatalen;
+ }
+ else
+ return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
+ memcpy (data, indata, indatalen);
+ }
else
{
+ int len = 15;
if (hashalgo == GCRY_MD_SHA1)
- memcpy (data, sha1_prefix, 15);
+ memcpy (data, sha1_prefix, len);
else if (hashalgo == GCRY_MD_RMD160)
- memcpy (data, rmd160_prefix, 15);
+ memcpy (data, rmd160_prefix, len);
+ else if (hashalgo == GCRY_MD_SHA256)
+ {
+ len = 19;
+ datalen = len + indatalen;
+ memcpy (data, sha256_prefix, len);
+ }
else
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
- memcpy (data+15, indata, indatalen);
+ memcpy (data+len, indata, indatalen);
}
rc = verify_pin (app, pincb, pincb_arg);
if (!rc)
- rc = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen);
+ rc = iso7816_compute_ds (app->slot, data, datalen, outdata, outdatalen);
return rc;
}
+#if 0
+#warning test function - works but may brick your card
+/* Handle the PASSWD command. CHVNOSTR is currently ignored; we
+ always use VHV0. RESET_MODE is not yet implemented. */
+static gpg_error_t
+do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
+ unsigned int flags,
+ gpg_error_t (*pincb)(void*, const char *, char **),
+ void *pincb_arg)
+{
+ gpg_error_t err;
+ char *pinvalue;
+ const char *oldpin;
+ size_t oldpinlen;
+
+ if ((flags & APP_CHANGE_FLAG_RESET))
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ if ((flags & APP_CHANGE_FLAG_NULLPIN))
+ {
+ /* With the nullpin flag, we do not verify the PIN - it would fail
+ if the Nullpin is still set. */
+ oldpin = "\0\0\0\0\0";
+ oldpinlen = 6;
+ }
+ else
+ {
+ err = verify_pin (app, pincb, pincb_arg);
+ if (err)
+ return err;
+ oldpin = NULL;
+ oldpinlen = 0;
+ }
+
+ /* TRANSLATORS: Do not translate the "|*|" prefixes but
+ keep it at the start of the string. We need this elsewhere
+ to get some infos on the string. */
+ err = pincb (pincb_arg, _("|N|Initial New PIN"), &pinvalue);
+ if (err)
+ {
+ log_error (_("error getting new PIN: %s\n"), gpg_strerror (err));
+ return err;
+ }
+
+ err = iso7816_change_reference_data (app->slot, 0x81,
+ oldpin, oldpinlen,
+ pinvalue, strlen (pinvalue));
+ xfree (pinvalue);
+ return err;
+}
+
+
/* Select the DINSIG application on the card in SLOT. This function
must be used before any other DINSIG application functions. */
@@ -475,7 +561,7 @@ app_select_dinsig (app_t app)
app->fnc.sign = do_sign;
app->fnc.auth = NULL;
app->fnc.decipher = NULL;
- app->fnc.change_pin = NULL;
+ app->fnc.change_pin = NULL /*do_change_pin*/;
app->fnc.check_pin = NULL;
app->force_chv1 = 1;