1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

Signing using a PKCS15 smartcard does work. How to create such a card

is of course a different thing.  Note, that you need to create the
shadowed-private-key file manually.
This commit is contained in:
Werner Koch 2002-03-05 17:14:45 +00:00
parent c8454f792d
commit 2fa73e781f
5 changed files with 354 additions and 29 deletions

View file

@ -126,20 +126,135 @@ ask_for_card (const unsigned char *shadow_info, char **r_kid)
}
/* fixme: this should be moved to libgcrypt and only be used if the
smartcard does not support pkcs-1 itself */
static int
encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo,
unsigned int nbits, unsigned char **r_val, size_t *r_len)
{
int nframe = (nbits+7) / 8;
byte *frame;
int i, n;
byte asn[100];
size_t asnlen;
asnlen = DIM(asn);
if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
{
log_error ("no object identifier for algo %d\n", algo);
return GNUPG_Internal_Error;
}
if (digestlen + asnlen + 4 > nframe )
{
log_error ("can't encode a %d bit MD into a %d bits frame\n",
(int)(digestlen*8), (int)nbits);
return GNUPG_Internal_Error;
}
/* We encode the MD in this way:
*
* 0 1 PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
*
* PAD consists of FF bytes.
*/
frame = xtrymalloc (nframe);
if (!frame)
return GNUPG_Out_Of_Core;
n = 0;
frame[n++] = 0;
frame[n++] = 1; /* block type */
i = nframe - digestlen - asnlen -3 ;
assert ( i > 1 );
memset ( frame+n, 0xff, i ); n += i;
frame[n++] = 0;
memcpy ( frame+n, asn, asnlen ); n += asnlen;
memcpy ( frame+n, digest, digestlen ); n += digestlen;
assert ( n == nframe );
if (DBG_CRYPTO)
log_printhex ("encoded hash:", frame, nframe);
*r_val = frame;
*r_len = nframe;
return 0;
}
/* Callback used to ask for the PIN which should be set into BUF. The
buf has been allocated by the caller and is of size MAXBUF which
includes the terminating null. The function should return an UTF-8
string with the passphrase, the buffer may optioanlly be padded
with arbitrary characters */
static int
getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
{
struct pin_entry_info_s *pi;
int rc;
int tries = 0;
const char *errtext;
assert (!opaque);
if (maxbuf < 2)
return GNUPG_Invalid_Value;
/* FIXME: keep PI and TRIES in OPAQUE */
pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
pi->max_length = maxbuf-1;
pi->min_digits = 0; /* we want a real passphrase */
pi->max_digits = 8;
pi->max_tries = 3;
errtext = NULL;
do
{
rc = agent_askpin (info, errtext, pi);
if (!rc)
{
strncpy (buf, pi->pin, maxbuf-1);
buf[maxbuf-1] = 0;
xfree (pi);
return 0;
}
errtext = pi->min_digits? trans ("Bad PIN") : trans ("Bad Passphrase");
}
while ((rc == GNUPG_Bad_Passphrase || rc == GNUPG_Bad_PIN)
&& tries++ < 3);
xfree (pi);
return rc;
}
int
divert_pksign (GCRY_SEXP *s_sig, GCRY_SEXP s_hash, const char *shadow_info)
divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
const char *shadow_info, unsigned char **r_sig)
{
int rc;
char *kid;
size_t siglen;
char *sigval;
unsigned char *data;
size_t ndata;
rc = ask_for_card (shadow_info, &kid);
if (rc)
return rc;
rc = encode_md_for_card (digest, digestlen, algo, 1024 /* fixme*/,
&data, &ndata);
if (rc)
return rc;
rc = agent_card_pksign (kid, getpin_cb, NULL,
data, ndata, &sigval, &siglen);
if (!rc)
*r_sig = sigval;
xfree (data);
xfree (kid);
return GNUPG_Not_Implemented;
return rc;
}