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:
parent
56341c289c
commit
f8efc7c4ef
110
scd/card.c
110
scd/card.c
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
135
scd/command.c
135
scd/command.c
|
@ -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 }
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user