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

Added more code fragments.

This commit is contained in:
Werner Koch 2002-03-04 10:34:09 +00:00
parent 56341c289c
commit f8efc7c4ef
3 changed files with 220 additions and 29 deletions

View File

@ -359,6 +359,28 @@ card_enum_keypairs (CARD card, int idx,
static int
idstr_to_id (const char *idstr, struct sc_pkcs15_id *id)
{
const char *s;
int n;
/* For now we only support the standard DF */
if (strncmp (idstr, "3F005015.", 9) )
return GNUPG_Invalid_Id;
for (s=idstr+9, n=0; hexdigitp (s); s++, n++)
;
if (*s || (n&1))
return GNUPG_Invalid_Id; /* invalid or odd number of digits */
n /= 2;
if (!n || n > SC_PKCS15_MAX_ID_SIZE)
return GNUPG_Invalid_Id; /* empty or too large */
for (s=idstr+9, n=0; *s; s += 2, n++)
id->value[n] = xtoi_2 (s);
id->len = n;
return 0;
}
/* Read the certificate identified by CERTIDSTR which is the /* Read the certificate identified by CERTIDSTR which is the
hexadecimal encoded ID of the certificate, prefixed with the string hexadecimal encoded ID of the certificate, prefixed with the string
"3F005015.". The certificate is return in DER encoded form in CERT "3F005015.". The certificate is return in DER encoded form in CERT
@ -370,25 +392,14 @@ card_read_cert (CARD card, const char *certidstr,
struct sc_pkcs15_id certid; struct sc_pkcs15_id certid;
struct sc_pkcs15_cert_info *certinfo; struct sc_pkcs15_cert_info *certinfo;
struct sc_pkcs15_cert *certder; struct sc_pkcs15_cert *certder;
const char *s; int rc;
int rc, n;
if (!card || !certidstr || !card->p15card || !cert || !ncert) if (!card || !certidstr || !card->p15card || !cert || !ncert)
return GNUPG_Invalid_Value; return GNUPG_Invalid_Value;
/* For now we only support the standard DF */ rc = idstr_to_id (certidstr, &certid);
if (strncmp (certidstr, "3F005015.", 9) ) if (rc)
return GNUPG_Invalid_Id; return rc;
for (s=certidstr+9, n=0; hexdigitp (s); s++, n++)
;
if (*s || (n&1))
return GNUPG_Invalid_Id; /* invalid or odd number of digits */
n /= 2;
if (!n || n > SC_PKCS15_MAX_ID_SIZE)
return GNUPG_Invalid_Id; /* empty or too large */
for (s=certidstr+9, n=0; *s; s += 2, n++)
certid.value[n] = xtoi_2 (s);
certid.len = n;
rc = sc_pkcs15_find_cert_by_id (card->p15card, &certid, &certinfo); rc = sc_pkcs15_find_cert_by_id (card->p15card, &certid, &certinfo);
if (rc) if (rc)
@ -418,6 +429,75 @@ card_read_cert (CARD card, const char *certidstr,
} }
/* Create the signature and return the allocated result in OUTDATA. */
int
card_create_signature (CARD card, const char *keyidstr, int hashalgo,
const void *indata, size_t indatalen,
void **outdata, size_t *outdatalen )
{
unsigned int cryptflags = 0;
struct sc_pkcs15_id keyid;
struct sc_pkcs15_prkey_info *key;
/* struct sc_pkcs15_pin_info *pin;*/
int rc;
unsigned char *outbuf = NULL;
size_t outbuflen;
if (!card || !card->p15card || !indata || !indatalen
|| !outdata || !outdatalen)
return GNUPG_Invalid_Value;
if (hashalgo != GCRY_MD_SHA1)
return GNUPG_Unsupported_Algorithm;
rc = idstr_to_id (keyidstr, &keyid);
if (rc)
return rc;
rc = sc_pkcs15_find_prkey_by_id (card->p15card, &keyid, &key);
if (rc < 0)
{
log_error ("private key not found: %s\n", sc_strerror(rc));
rc = GNUPG_No_Secret_Key;
goto leave;
}
rc = 0;
key = card->p15card->prkey_info;
/* FIXME: Handle PIN via callback */
cryptflags |= SC_PKCS15_HASH_SHA1;
cryptflags |= SC_PKCS15_PAD_PKCS1_V1_5;
outbuflen = 1024;
outbuf = xtrymalloc (outbuflen);
if (!outbuf)
return GNUPG_Out_Of_Core;
rc = sc_pkcs15_compute_signature (card->p15card, key,
cryptflags,
indata, indatalen,
outbuf, outbuflen );
if (rc < 0)
{
log_error ("failed to create signature: %s\n", sc_strerror (rc));
rc = GNUPG_Card_Error;
}
else
{
*outdatalen = rc;
*outdata = outbuf;
outbuf = NULL;
rc = 0;
}
leave:
xfree (outbuf);
return rc;
}

View File

@ -61,6 +61,8 @@ reset_notify (ASSUAN_CONTEXT ctx)
{ {
card_close (ctrl->card_ctx); card_close (ctrl->card_ctx);
ctrl->card_ctx = NULL; ctrl->card_ctx = NULL;
xfree (ctrl->in_data.value);
ctrl->in_data.value = NULL;
} }
} }
@ -72,6 +74,63 @@ option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
} }
/* If the card has not yet been opened, do it. Note that this
function returns an Assuan error, so don't map the error a second
time */
static AssuanError
open_card (CTRL ctrl)
{
if (!ctrl->card_ctx)
{
int rc = card_open (&ctrl->card_ctx);
if (rc)
return map_to_assuan_status (rc);
}
return 0;
}
/* SERIALNO
Return the serial number of the card using a status reponse. This
functon should be used to check for the presence of a card.
This function is special in that it can be used to reset the card.
Most other functions will return an error when a card change has
been detected and the use of this function is therefore required.
Background: We want to keep the client clear of handling card
changes between operations; i.e. the client can assume that all
operations are doneon the same card unless he call this function.
*/
static int
cmd_serialno (ASSUAN_CONTEXT ctx, char *line)
{
CTRL ctrl = assuan_get_pointer (ctx);
int rc = 0;
char *serial_and_stamp;
char *serial;
time_t stamp;
if ((rc = open_card (ctrl)))
return rc;
rc = card_get_serial_and_stamp (ctrl->card_ctx, &serial, &stamp);
if (rc)
return map_to_assuan_status (rc);
rc = asprintf (&serial_and_stamp, "%s %lu", serial, (unsigned long)stamp);
xfree (serial);
if (rc < 0)
return ASSUAN_Out_Of_Core;
rc = 0;
assuan_write_status (ctx, "SERIALNO", serial_and_stamp);
free (serial_and_stamp);
return 0;
}
/* LEARN [--force] /* LEARN [--force]
Learn all useful information of the currently inserted card. When Learn all useful information of the currently inserted card. When
@ -98,14 +157,8 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line)
int rc = 0; int rc = 0;
int idx; int idx;
/* if this is the first command issued for a new card, open the card and if ((rc = open_card (ctrl)))
and create a context */ return rc;
if (!ctrl->card_ctx)
{
rc = card_open (&ctrl->card_ctx);
if (rc)
return map_to_assuan_status (rc);
}
/* Unless the force option is used we try a shortcut by identifying /* Unless the force option is used we try a shortcut by identifying
the card using a serial number and inquiring the client with the card using a serial number and inquiring the client with
@ -221,12 +274,8 @@ cmd_readcert (ASSUAN_CONTEXT ctx, char *line)
unsigned char *cert; unsigned char *cert;
size_t ncert; size_t ncert;
if (!ctrl->card_ctx) if ((rc = open_card (ctrl)))
{ return rc;
rc = card_open (&ctrl->card_ctx);
if (rc)
return map_to_assuan_status (rc);
}
rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert); rc = card_read_cert (ctrl->card_ctx, line, &cert, &ncert);
if (rc) if (rc)
@ -244,6 +293,61 @@ cmd_readcert (ASSUAN_CONTEXT ctx, char *line)
return map_to_assuan_status (rc); return map_to_assuan_status (rc);
} }
/* SETDATA <hexstring>
The client should use this command to tell us the data he want to
sign. */
static int
cmd_setdata (ASSUAN_CONTEXT ctx, char *line)
{
CTRL ctrl = assuan_get_pointer (ctx);
int n;
char *p;
unsigned char *buf;
/* parse the hexstring */
for (p=line,n=0; hexdigitp (p); p++, n++)
;
if (*p)
return set_error (Parameter_Error, "invalid hexstring");
if ((n&1))
return set_error (Parameter_Error, "odd number of digits");
n /= 2;
buf = xtrymalloc (n);
if (!buf)
return ASSUAN_Out_Of_Core;
ctrl->in_data.value = buf;
ctrl->in_data.valuelen = n;
for (p=line, n=0; n < ctrl->in_data.valuelen; p += 2, n++)
buf[n] = xtoi_2 (p);
return 0;
}
/* PKSIGN <hexified_id>
*/
static int
cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
{
CTRL ctrl = assuan_get_pointer (ctx);
int rc;
if ((rc = open_card (ctrl)))
return rc;
return map_to_assuan_status (rc);
}
/* Tell the assuan library about our commands */ /* Tell the assuan library about our commands */
static int static int
@ -254,8 +358,11 @@ register_commands (ASSUAN_CONTEXT ctx)
int cmd_id; int cmd_id;
int (*handler)(ASSUAN_CONTEXT, char *line); int (*handler)(ASSUAN_CONTEXT, char *line);
} table[] = { } table[] = {
{ "SERIALNO", 0, cmd_serialno },
{ "LEARN", 0, cmd_learn }, { "LEARN", 0, cmd_learn },
{ "READCERT", 0, cmd_readcert }, { "READCERT", 0, cmd_readcert },
{ "SETDATA", 0, cmd_setdata },
{ "PKSIGN", 0, cmd_pksign },
{ "", ASSUAN_CMD_INPUT, NULL }, { "", ASSUAN_CMD_INPUT, NULL },
{ "", ASSUAN_CMD_OUTPUT, NULL }, { "", ASSUAN_CMD_OUTPUT, NULL },
{ NULL } { NULL }

View File

@ -61,6 +61,10 @@ struct card_ctx_s;
struct server_control_s { struct server_control_s {
struct server_local_s *server_local; struct server_local_s *server_local;
struct card_ctx_s *card_ctx; struct card_ctx_s *card_ctx;
struct {
unsigned char *value;
int valuelen;
} in_data; /* helper to store the value we are going to sign */
}; };
typedef struct server_control_s *CTRL; typedef struct server_control_s *CTRL;