1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-16 00:29:50 +02:00

scd:p15: Support signing with CardOS 5 cards.

* scd/app-help.c (app_help_get_keygrip_string_pk): Add optional arg
r_pkey and change all callers.
(app_help_get_keygrip_string): Ditto.
* scd/app-p15.c (struct cdf_object_s): Use bit flags
(struct aodf_object_s): Ditto.  Add field 'fid'.
(struct prkdf_object_s): Ditto.  Add fields keygrip, keyalgo, and
keynbits.
(parse_certid): Allow a keygrip instead of a certid aka keyref.
(read_ef_aodf): Store the FID.
(keygripstr_from_prkdf): Rename to ...
(keygrip_from_prkdf): this.  Remove arg r_gripstr and implement cache.
Change callers to directly use the values from the object.  Also store
the algo and length of the key ion the object.
(keyref_from_keyinfo): New. Factored out code.
(do_sign): Support SHA-256 and >2048 bit RSA keys.
common/scd:p15: Support signing with CardOS 5 cards.
* common/util.h (KEYGRIP_LEN): New.
--

This has been tested with a D-Trust card featuring 3072 bit keys.
Note that non-repudiation key for a qualified signature does not yet
work because we do not yet support rsaPSS padding.  Thus a gpgsm
--learn shows a couple of Bad Signature errors for this key.

Signed-off-by: Werner Koch <wk@gnupg.org>

Back ported from master:
- Removed do_with_keygrip
- Added KEYGRIP_LEN
- app_help_get_keygrip_string_pk actually added.
- Move keygrip_from_prkdf in do_sign before the verification.
  It used to work in master only because there it is implictly
  called prior to signing by do_with_keygrip

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2020-03-31 19:55:15 +02:00
parent 368f006a28
commit e730444e7b
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
6 changed files with 289 additions and 100 deletions

View File

@ -66,6 +66,11 @@
/* Hash function used with libksba. */ /* Hash function used with libksba. */
#define HASH_FNC ((void (*)(void *, const void*,size_t))gcry_md_write) #define HASH_FNC ((void (*)(void *, const void*,size_t))gcry_md_write)
/* The length of the keygrip. This is a SHA-1 hash of the key
* parameters as generated by gcry_pk_get_keygrip. */
#define KEYGRIP_LEN 20
/* Get all the stuff from jnlib. */ /* Get all the stuff from jnlib. */
#include "../common/logging.h" #include "../common/logging.h"
#include "../common/argparse.h" #include "../common/argparse.h"

View File

@ -134,7 +134,11 @@ app_get_slot (app_t app)
/*-- app-help.c --*/ /*-- app-help.c --*/
unsigned int app_help_count_bits (const unsigned char *a, size_t len); unsigned int app_help_count_bits (const unsigned char *a, size_t len);
gpg_error_t app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip); gpg_error_t app_help_get_keygrip_string_pk (const void *pk, size_t pklen,
char *hexkeygrip,
gcry_sexp_t *r_pkey);
gpg_error_t app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip,
gcry_sexp_t *r_pkey);
size_t app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff); size_t app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff);

View File

@ -137,7 +137,7 @@ do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
ksba_cert_release (cert); ksba_cert_release (cert);
return err; return err;
} }
err = app_help_get_keygrip_string (cert, hexkeygrip); err = app_help_get_keygrip_string (cert, hexkeygrip, NULL);
if (err) if (err)
{ {
log_error ("failed to calculate the keygrip for FID 0x%04X\n", fid); log_error ("failed to calculate the keygrip for FID 0x%04X\n", fid);

View File

@ -52,26 +52,24 @@ app_help_count_bits (const unsigned char *a, size_t len)
} }
/* Return the KEYGRIP for the certificate CERT as an hex encoded /* Return the KEYGRIP for the canonical encoded public key (PK,PKLEN)
string in the user provided buffer HEXKEYGRIP which must be of at * as an hex encoded string in the user provided buffer HEXKEYGRIP
least 41 bytes. */ * which must be of at least 41 bytes. If R_PKEY is not NULL and the
* function succeeded, the S-expression representing the key is
* stored there. The caller needs to call gcry_sexp_release on
* that. */
gpg_error_t gpg_error_t
app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip) app_help_get_keygrip_string_pk (const void *pk, size_t pklen, char *hexkeygrip,
gcry_sexp_t *r_pkey)
{ {
gpg_error_t err; gpg_error_t err;
gcry_sexp_t s_pkey; gcry_sexp_t s_pkey;
ksba_sexp_t p; unsigned char array[KEYGRIP_LEN];
size_t n;
unsigned char array[20];
p = ksba_cert_get_public_key (cert); if (r_pkey)
if (!p) *r_pkey = NULL;
return gpg_error (GPG_ERR_BUG);
n = gcry_sexp_canon_len (p, 0, NULL, NULL); err = gcry_sexp_sscan (&s_pkey, NULL, pk, pklen);
if (!n)
return gpg_error (GPG_ERR_INV_SEXP);
err = gcry_sexp_sscan (&s_pkey, NULL, (char*)p, n);
xfree (p);
if (err) if (err)
return err; /* Can't parse that S-expression. */ return err; /* Can't parse that S-expression. */
if (!gcry_pk_get_keygrip (s_pkey, array)) if (!gcry_pk_get_keygrip (s_pkey, array))
@ -79,14 +77,45 @@ app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip)
gcry_sexp_release (s_pkey); gcry_sexp_release (s_pkey);
return gpg_error (GPG_ERR_GENERAL); /* Failed to calculate the keygrip.*/ return gpg_error (GPG_ERR_GENERAL); /* Failed to calculate the keygrip.*/
} }
if (r_pkey)
*r_pkey = s_pkey;
else
gcry_sexp_release (s_pkey); gcry_sexp_release (s_pkey);
bin2hex (array, 20, hexkeygrip); bin2hex (array, KEYGRIP_LEN, hexkeygrip);
return 0; return 0;
} }
/* Return the KEYGRIP for the certificate CERT as an hex encoded
* string in the user provided buffer HEXKEYGRIP which must be of at
* least 41 bytes. If R_PKEY is not NULL and the function succeeded,
* the S-expression representing the key is stored there. The caller
* needs to call gcry_sexp_release on that. */
gpg_error_t
app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip,
gcry_sexp_t *r_pkey)
{
gpg_error_t err;
ksba_sexp_t p;
size_t n;
if (r_pkey)
*r_pkey = NULL;
p = ksba_cert_get_public_key (cert);
if (!p)
return gpg_error (GPG_ERR_BUG);
n = gcry_sexp_canon_len (p, 0, NULL, NULL);
if (!n)
return gpg_error (GPG_ERR_INV_SEXP);
err = app_help_get_keygrip_string_pk ((void*)p, n, hexkeygrip, r_pkey);
ksba_free (p);
return err;
}
/* Given the SLOT and the File ID FID, return the length of the /* Given the SLOT and the File ID FID, return the length of the
certificate contained in that file. Returns 0 if the file does not certificate contained in that file. Returns 0 if the file does not

View File

@ -139,6 +139,9 @@ struct cdf_object_s
/* Link to next item when used in a linked list. */ /* Link to next item when used in a linked list. */
struct cdf_object_s *next; struct cdf_object_s *next;
/* Flags to indicate whether fields are valid. */
unsigned int have_off:1;
/* Length and allocated buffer with the Id of this object. /* Length and allocated buffer with the Id of this object.
* This field is used for X.509 in PKCS#11 to make it easier to * This field is used for X.509 in PKCS#11 to make it easier to
* match a private key with a certificate. */ * match a private key with a certificate. */
@ -150,8 +153,6 @@ struct cdf_object_s
size_t imagelen; size_t imagelen;
unsigned char *image; unsigned char *image;
/* Set to true if a length and offset is available. */
int have_off;
/* The offset and length of the object. They are only valid if /* The offset and length of the object. They are only valid if
HAVE_OFF is true and set to 0 if HAVE_OFF is false. */ HAVE_OFF is true and set to 0 if HAVE_OFF is false. */
unsigned long off, len; unsigned long off, len;
@ -175,6 +176,25 @@ struct prkdf_object_s
/* Link to next item when used in a linked list. */ /* Link to next item when used in a linked list. */
struct prkdf_object_s *next; struct prkdf_object_s *next;
/* Flags to indicate whether fields are valid. */
unsigned int keygrip_valid:1;
unsigned int key_reference_valid:1;
unsigned int have_off:1;
/* The key's usage flags. */
keyusage_flags_t usageflags;
/* The keygrip of the key. This is used as a cache. */
char keygrip[2*KEYGRIP_LEN+1];
/* The Gcrypt algo identifier for the key. It is valid if the
* keygrip is also valid. */
int keyalgo;
/* The length of the key in bits (e.g. for RSA the length of the
* modulus). It is valid if the keygrip is also valid. */
unsigned int keynbits;
/* Length and allocated buffer with the Id of this object. */ /* Length and allocated buffer with the Id of this object. */
size_t objidlen; size_t objidlen;
unsigned char *objid; unsigned char *objid;
@ -184,17 +204,11 @@ struct prkdf_object_s
size_t authidlen; size_t authidlen;
unsigned char *authid; unsigned char *authid;
/* The key's usage flags. */
keyusage_flags_t usageflags;
/* The keyReference and a flag telling whether it is valid. */ /* The keyReference and a flag telling whether it is valid. */
unsigned long key_reference; unsigned long key_reference;
int key_reference_valid;
/* Set to true if a length and offset is available. */
int have_off;
/* The offset and length of the object. They are only valid if /* The offset and length of the object. They are only valid if
HAVE_OFF is true and set to 0 if HAVE_OFF is false. */ * HAVE_OFF is true otherwise they are set to 0. */
unsigned long off, len; unsigned long off, len;
/* The length of the path as given in the PrKDF and the path itself. /* The length of the path as given in the PrKDF and the path itself.
@ -215,6 +229,9 @@ struct aodf_object_s
/* Link to next item when used in a linked list. */ /* Link to next item when used in a linked list. */
struct aodf_object_s *next; struct aodf_object_s *next;
/* Flags to indicate whether fields are valid. */
unsigned int have_off:1;
/* Length and allocated buffer with the Id of this object. */ /* Length and allocated buffer with the Id of this object. */
size_t objidlen; size_t objidlen;
unsigned char *objid; unsigned char *objid;
@ -224,6 +241,9 @@ struct aodf_object_s
size_t authidlen; size_t authidlen;
unsigned char *authid; unsigned char *authid;
/* The file ID of this AODF. */
unsigned short fid;
/* The PIN Flags. */ /* The PIN Flags. */
struct struct
{ {
@ -262,9 +282,6 @@ struct aodf_object_s
char pad_char; char pad_char;
int pad_char_valid; int pad_char_valid;
/* Set to true if a length and offset is available. */
int have_off;
/* The offset and length of the object. They are only valid if /* The offset and length of the object. They are only valid if
HAVE_OFF is true and set to 0 if HAVE_OFF is false. */ HAVE_OFF is true and set to 0 if HAVE_OFF is false. */
unsigned long off, len; unsigned long off, len;
@ -327,6 +344,7 @@ struct app_local_s
/*** Local prototypes. ***/ /*** Local prototypes. ***/
static gpg_error_t keygrip_from_prkdf (app_t app, prkdf_object_t prkdf);
static gpg_error_t readcert_by_cdf (app_t app, cdf_object_t cdf, static gpg_error_t readcert_by_cdf (app_t app, cdf_object_t cdf,
unsigned char **r_cert, size_t *r_certlen); unsigned char **r_cert, size_t *r_certlen);
@ -498,9 +516,28 @@ parse_certid (app_t app, const char *certid,
*r_objid = NULL; *r_objid = NULL;
*r_objidlen = 0; *r_objidlen = 0;
if (certid[0] != 'P' && strlen (certid) == 40) /* This is a keygrip. */
{
prkdf_object_t keyinfo;
for (keyinfo = app->app_local->private_key_info;
keyinfo; keyinfo = keyinfo->next)
if (!keygrip_from_prkdf (app, keyinfo)
&& !strcmp (certid, keyinfo->keygrip))
break;
if (!keyinfo || !keyinfo->objidlen || !keyinfo->objid)
return gpg_error (GPG_ERR_NOT_FOUND);
objidlen = keyinfo->objidlen;
objid = xtrymalloc (objidlen);
if (!objid)
return gpg_error_from_syserror ();
memcpy (objid, keyinfo->objid, keyinfo->objidlen);
}
else /* This is a usual keyref. */
{
if (app->app_local->home_df) if (app->app_local->home_df)
snprintf (tmpbuf, sizeof tmpbuf, snprintf (tmpbuf, sizeof tmpbuf, "P15-%04X.",
"P15-%04X.", (unsigned int)(app->app_local->home_df & 0xffff)); (unsigned int)(app->app_local->home_df & 0xffff));
else else
strcpy (tmpbuf, "P15."); strcpy (tmpbuf, "P15.");
if (strncmp (certid, tmpbuf, strlen (tmpbuf)) ) if (strncmp (certid, tmpbuf, strlen (tmpbuf)) )
@ -516,7 +553,6 @@ parse_certid (app_t app, const char *certid,
return gpg_error (GPG_ERR_INV_ID); return gpg_error (GPG_ERR_INV_ID);
} }
certid += strlen (tmpbuf); certid += strlen (tmpbuf);
for (s=certid, objidlen=0; hexdigitp (s); s++, objidlen++) for (s=certid, objidlen=0; hexdigitp (s); s++, objidlen++)
; ;
if (*s || !objidlen || (objidlen%2)) if (*s || !objidlen || (objidlen%2))
@ -527,6 +563,8 @@ parse_certid (app_t app, const char *certid,
return gpg_error_from_syserror (); return gpg_error_from_syserror ();
for (s=certid, i=0; i < objidlen; i++, s+=2) for (s=certid, i=0; i < objidlen; i++, s+=2)
objid[i] = xtoi_2 (s); objid[i] = xtoi_2 (s);
}
*r_objid = objid; *r_objid = objid;
*r_objidlen = objidlen; *r_objidlen = objidlen;
return 0; return 0;
@ -1640,6 +1678,7 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
aodf = xtrycalloc (1, sizeof *aodf); aodf = xtrycalloc (1, sizeof *aodf);
if (!aodf) if (!aodf)
goto no_core; goto no_core;
aodf->fid = fid;
/* Parse the commonObjectAttributes. */ /* Parse the commonObjectAttributes. */
where = __LINE__; where = __LINE__;
@ -2548,21 +2587,26 @@ send_certinfo (app_t app, ctrl_t ctrl, const char *certtype,
/* Get the keygrip of the private key object PRKDF. On success the /* Get the keygrip of the private key object PRKDF. On success the
keygrip gets returned in the caller provided 41 byte buffer * keygrip, the algo and the length are stored in the KEYGRIP,
R_GRIPSTR. */ * KEYALFO, and KEYNBITS fields of the PRKDF object. */
static gpg_error_t static gpg_error_t
keygripstr_from_prkdf (app_t app, prkdf_object_t prkdf, char *r_gripstr) keygrip_from_prkdf (app_t app, prkdf_object_t prkdf)
{ {
gpg_error_t err; gpg_error_t err;
cdf_object_t cdf; cdf_object_t cdf;
unsigned char *der; unsigned char *der;
size_t derlen; size_t derlen;
ksba_cert_t cert; ksba_cert_t cert;
gcry_sexp_t s_pkey = NULL;
/* Easy if we got a cached version. */
if (prkdf->keygrip_valid)
return 0;
/* FIXME: We should check whether a public key directory file and a /* FIXME: We should check whether a public key directory file and a
matching public key for PRKDF is available. This should make matching public key for PRKDF is available. This should make
extraction of the key much easier. My current test card doesn't extraction of the key much easier. My current test card doesn't
have one, so we can only use the fallback solution bu looking for have one, so we can only use the fallback solution by looking for
a matching certificate and extract the key from there. */ a matching certificate and extract the key from there. */
/* Look for a matching certificate. A certificate matches if the Id /* Look for a matching certificate. A certificate matches if the Id
@ -2582,24 +2626,68 @@ keygripstr_from_prkdf (app_t app, prkdf_object_t prkdf, char *r_gripstr)
&& !memcmp (cdf->objid, prkdf->objid, prkdf->objidlen)) && !memcmp (cdf->objid, prkdf->objid, prkdf->objidlen))
break; break;
if (!cdf) if (!cdf)
return gpg_error (GPG_ERR_NOT_FOUND); {
err = gpg_error (GPG_ERR_NOT_FOUND);
goto leave;
}
err = readcert_by_cdf (app, cdf, &der, &derlen); err = readcert_by_cdf (app, cdf, &der, &derlen);
if (err) if (err)
return err; goto leave;
err = ksba_cert_new (&cert); err = ksba_cert_new (&cert);
if (!err) if (!err)
err = ksba_cert_init_from_mem (cert, der, derlen); err = ksba_cert_init_from_mem (cert, der, derlen);
xfree (der); xfree (der);
if (!err) if (!err)
err = app_help_get_keygrip_string (cert, r_gripstr); err = app_help_get_keygrip_string (cert, prkdf->keygrip, &s_pkey);
ksba_cert_release (cert); ksba_cert_release (cert);
if (err)
goto leave;
prkdf->keyalgo = get_pk_algo_from_key (s_pkey);
if (!prkdf->keyalgo)
{
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
goto leave;
}
prkdf->keynbits = gcry_pk_get_nbits (s_pkey);
if (!prkdf->keynbits)
{
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
goto leave;
}
prkdf->keygrip_valid = 1; /* Yeah, got everything. */
leave:
gcry_sexp_release (s_pkey);
return err; return err;
} }
/* Return a malloced keyref string for KEYINFO. Returns NULL on
* malloc failure. */
static char *
keyref_from_keyinfo (app_t app, prkdf_object_t keyinfo)
{
char *buf, *p;
buf = xtrymalloc (4 + 5 + keyinfo->objidlen*2 + 1);
if (!buf)
return NULL;
p = stpcpy (buf, "P15");
if (app->app_local->home_df)
{
snprintf (p, 6, "-%04X",
(unsigned int)(app->app_local->home_df & 0xffff));
p += 5;
}
p = stpcpy (p, ".");
bin2hex (keyinfo->objid, keyinfo->objidlen, p);
return buf;
}
/* Helper to do_learn_status: Send information about all known /* Helper to do_learn_status: Send information about all known
@ -2612,36 +2700,26 @@ send_keypairinfo (app_t app, ctrl_t ctrl, prkdf_object_t keyinfo)
for (; keyinfo; keyinfo = keyinfo->next) for (; keyinfo; keyinfo = keyinfo->next)
{ {
char gripstr[40+1]; char *buf;
char *buf, *p;
int j; int j;
buf = xtrymalloc (9 + keyinfo->objidlen*2 + 1); buf = keyref_from_keyinfo (app, keyinfo);
if (!buf) if (!buf)
return gpg_error_from_syserror (); return gpg_error_from_syserror ();
p = stpcpy (buf, "P15");
if (app->app_local->home_df)
{
snprintf (p, 6, "-%04X",
(unsigned int)(app->app_local->home_df & 0xffff));
p += 5;
}
p = stpcpy (p, ".");
bin2hex (keyinfo->objid, keyinfo->objidlen, p);
err = keygripstr_from_prkdf (app, keyinfo, gripstr); err = keygrip_from_prkdf (app, keyinfo);
if (err) if (err)
{ {
log_error ("p15: error getting keygrip from "); log_error ("p15: error getting keygrip from ");
for (j=0; j < keyinfo->pathlen; j++) for (j=0; j < keyinfo->pathlen; j++)
log_printf ("%04hX", keyinfo->path[j]); log_printf ("%s%04hX", j?"/":"", keyinfo->path[j]);
log_printf (": %s\n", gpg_strerror (err)); log_printf (": %s\n", gpg_strerror (err));
} }
else else
{ {
assert (strlen (gripstr) == 40); log_assert (strlen (keyinfo->keygrip) == 40);
send_status_info (ctrl, "KEYPAIRINFO", send_status_info (ctrl, "KEYPAIRINFO",
gripstr, 40, keyinfo->keygrip, 2*KEYGRIP_LEN,
buf, strlen (buf), buf, strlen (buf),
NULL, (size_t)0); NULL, (size_t)0);
} }
@ -3022,6 +3100,9 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
const void *indata, size_t indatalen, const void *indata, size_t indatalen,
unsigned char **outdata, size_t *outdatalen ) unsigned char **outdata, size_t *outdatalen )
{ {
static unsigned char sha256_prefix[19] = /* OID: 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 };
static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */ static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */
{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
@ -3031,17 +3112,25 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
gpg_error_t err; gpg_error_t err;
int i; int i;
unsigned char data[36]; /* Must be large enough for a SHA-1 digest unsigned char data[32+19]; /* Must be large enough for a SHA-256 digest
+ the largest OID prefix above and also * + the largest OID prefix above and also
fit the 36 bytes of md5sha1. */ * fit the 36 bytes of md5sha1. */
prkdf_object_t prkdf; /* The private key object. */ prkdf_object_t prkdf; /* The private key object. */
aodf_object_t aodf; /* The associated authentication object. */ aodf_object_t aodf; /* The associated authentication object. */
int no_data_padding = 0; /* True if the card want the data without padding.*/ int no_data_padding = 0; /* True if the card want the data without padding.*/
int mse_done = 0; /* Set to true if the MSE has been done. */ int mse_done = 0; /* Set to true if the MSE has been done. */
unsigned int hashlen; /* Length of the hash. */
unsigned int datalen; /* Length of the data to sign (prefix+hash). */
unsigned char *dataptr;
int exmode, le_value;
log_debug ("p15:sign: keyidstr='%s' indatalen=%zu\n", keyidstr, indatalen);
if (!keyidstr || !*keyidstr) if (!keyidstr || !*keyidstr)
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
if (indatalen != 20 && indatalen != 16 && indatalen != 35 && indatalen != 36) if (indatalen != 20 && indatalen != 16
&& indatalen != 35 && indatalen != 36
&& indatalen != (32+19))
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
err = prkdf_object_from_keyidstr (app, keyidstr, &prkdf); err = prkdf_object_from_keyidstr (app, keyidstr, &prkdf);
@ -3072,12 +3161,27 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
log_error ("p15: authentication object for %s missing\n", keyidstr); log_error ("p15: authentication object for %s missing\n", keyidstr);
return gpg_error (GPG_ERR_INV_CARD); return gpg_error (GPG_ERR_INV_CARD);
} }
if (aodf->authid)
/* We need some more info about the key - get the keygrip to
* populate these fields. */
err = keygrip_from_prkdf (app, prkdf);
if (err)
{ {
log_error ("p15: PIN verification is protected by an " log_error ("p15: keygrip_from_prkdf failed: %s\n", gpg_strerror (err));
"additional authentication token\n"); return err;
return gpg_error (GPG_ERR_BAD_PIN_METHOD);
} }
if (opt.verbose)
{
log_info ("p15: using AODF %04hX id=", aodf->fid);
for (i=0; i < aodf->objidlen; i++)
log_printf ("%02X", aodf->objid[i]);
log_printf ("\n");
}
if (aodf->authid && opt.verbose)
log_info ("p15: PIN is controlled by another authentication token\n");
if (aodf->pinflags.integrity_protected if (aodf->pinflags.integrity_protected
|| aodf->pinflags.confidentiality_protected) || aodf->pinflags.confidentiality_protected)
{ {
@ -3275,7 +3379,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
else else
pinvaluelen = strlen (pinvalue); pinvaluelen = strlen (pinvalue);
err = iso7816_verify (app->slot, err = iso7816_verify (app_get_slot (app),
aodf->pin_reference_valid? aodf->pin_reference : 0, aodf->pin_reference_valid? aodf->pin_reference : 0,
pinvalue, pinvaluelen); pinvalue, pinvaluelen);
xfree (pinvalue); xfree (pinvalue);
@ -3295,6 +3399,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
if (hashalgo != MD_USER_TLS_MD5SHA1) if (hashalgo != MD_USER_TLS_MD5SHA1)
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
memcpy (data, indata, indatalen); memcpy (data, indata, indatalen);
datalen = hashlen = 36;
} }
else if (indatalen == 35) else if (indatalen == 35)
{ {
@ -3309,19 +3414,49 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
else else
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
memcpy (data, indata, indatalen); memcpy (data, indata, indatalen);
datalen = 35;
hashlen = 20;
}
else if (indatalen == 32 + 19)
{
/* Seems to be a prepared SHA256 DER object. */
if (hashalgo == GCRY_MD_SHA256 && !memcmp (indata, sha256_prefix, 19))
;
else
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
memcpy (data, indata, indatalen);
datalen = 51;
hashlen = 32;
} }
else else
{ {
/* Need to prepend the prefix. */ /* Need to prepend the prefix. */
if (hashalgo == GCRY_MD_SHA1) if (hashalgo == GCRY_MD_SHA256)
{
memcpy (data, sha256_prefix, 19);
memcpy (data+19, indata, indatalen);
datalen = 51;
hashlen = 32;
}
else if (hashalgo == GCRY_MD_SHA1)
{
memcpy (data, sha1_prefix, 15); memcpy (data, sha1_prefix, 15);
memcpy (data+15, indata, indatalen);
datalen = 35;
hashlen = 20;
}
else if (hashalgo == GCRY_MD_RMD160) else if (hashalgo == GCRY_MD_RMD160)
{
memcpy (data, rmd160_prefix, 15); memcpy (data, rmd160_prefix, 15);
memcpy (data+15, indata, indatalen);
datalen = 35;
hashlen = 20;
}
else else
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
memcpy (data+15, indata, indatalen);
} }
/* Manage security environment needs to be weaked for certain cards. */ /* Manage security environment needs to be weaked for certain cards. */
if (mse_done) if (mse_done)
err = 0; err = 0;
@ -3355,12 +3490,28 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
return err; return err;
} }
if (hashalgo == MD_USER_TLS_MD5SHA1) dataptr = data;
err = iso7816_compute_ds (app->slot, 0, data, 36, 0, outdata, outdatalen); if (no_data_padding)
else if (no_data_padding) {
err = iso7816_compute_ds (app->slot, 0, data+15, 20, 0,outdata,outdatalen); dataptr += datalen - hashlen;
datalen = hashlen;
}
if (prkdf->keyalgo == GCRY_PK_RSA && prkdf->keynbits > 2048)
{
exmode = 1;
le_value = prkdf->keynbits / 8;
}
else else
err = iso7816_compute_ds (app->slot, 0, data, 35, 0, outdata, outdatalen); {
exmode = 0;
le_value = 0;
}
err = iso7816_compute_ds (app_get_slot (app),
exmode, dataptr, datalen,
le_value, outdata, outdatalen);
return err; return err;
} }

View File

@ -1354,7 +1354,7 @@ keygripstr_from_prkdf (app_t app, prkdf_object_t prkdf, char *r_gripstr)
err = ksba_cert_init_from_mem (cert, der, derlen); err = ksba_cert_init_from_mem (cert, der, derlen);
xfree (der); xfree (der);
if (!err) if (!err)
err = app_help_get_keygrip_string (cert, r_gripstr); err = app_help_get_keygrip_string (cert, r_gripstr, NULL);
ksba_cert_release (cert); ksba_cert_release (cert);
return err; return err;