mirror of
git://git.gnupg.org/gnupg.git
synced 2024-06-01 22:28:02 +02:00
Well and some stuff to access the SC will be helpful. Note, that the
code requires the latest OpenSC CVS code.
This commit is contained in:
parent
d8538d80dd
commit
2b5dca457c
70
scd/card.c
70
scd/card.c
|
@ -268,6 +268,8 @@ card_enum_keypairs (CARD card, int idx,
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
KsbaError krc;
|
KsbaError krc;
|
||||||
|
struct sc_pkcs15_object *objs[32], *tmpobj;
|
||||||
|
int nobjs;
|
||||||
struct sc_pkcs15_prkey_info *pinfo;
|
struct sc_pkcs15_prkey_info *pinfo;
|
||||||
struct sc_pkcs15_cert_info *certinfo;
|
struct sc_pkcs15_cert_info *certinfo;
|
||||||
struct sc_pkcs15_cert *certder;
|
struct sc_pkcs15_cert *certder;
|
||||||
|
@ -283,19 +285,22 @@ card_enum_keypairs (CARD card, int idx,
|
||||||
if (idx < 0)
|
if (idx < 0)
|
||||||
return GNUPG_Invalid_Index;
|
return GNUPG_Invalid_Index;
|
||||||
|
|
||||||
rc = sc_pkcs15_enum_private_keys (card->p15card);
|
rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_PRKEY_RSA,
|
||||||
|
objs, DIM (objs));
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
{
|
{
|
||||||
log_error ("sc_pkcs15_enum_private_keys failed: %s\n", sc_strerror (rc));
|
log_error ("private keys enumeration failed: %s\n", sc_strerror (rc));
|
||||||
return GNUPG_Card_Error;
|
return GNUPG_Card_Error;
|
||||||
}
|
}
|
||||||
if ( idx >= card->p15card->prkey_count)
|
nobjs = rc;
|
||||||
|
rc = 0;
|
||||||
|
if (idx >= nobjs)
|
||||||
return -1;
|
return -1;
|
||||||
pinfo = card->p15card->prkey_info + idx;
|
pinfo = objs[idx]->data;
|
||||||
|
|
||||||
/* now we need to read the certificate so that we can calculate the
|
/* now we need to read the certificate so that we can calculate the
|
||||||
keygrip */
|
keygrip */
|
||||||
rc = sc_pkcs15_find_cert_by_id (card->p15card, &pinfo->id, &certinfo);
|
rc = sc_pkcs15_find_cert_by_id (card->p15card, &pinfo->id, &tmpobj);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
log_info ("certificate for private key %d not found: %s\n",
|
log_info ("certificate for private key %d not found: %s\n",
|
||||||
|
@ -312,6 +317,7 @@ card_enum_keypairs (CARD card, int idx,
|
||||||
*nkeyid = pinfo->id.len;
|
*nkeyid = pinfo->id.len;
|
||||||
return GNUPG_Missing_Certificate;
|
return GNUPG_Missing_Certificate;
|
||||||
}
|
}
|
||||||
|
certinfo = tmpobj->data;
|
||||||
rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder);
|
rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
|
@ -389,6 +395,7 @@ int
|
||||||
card_read_cert (CARD card, const char *certidstr,
|
card_read_cert (CARD card, const char *certidstr,
|
||||||
unsigned char **cert, size_t *ncert)
|
unsigned char **cert, size_t *ncert)
|
||||||
{
|
{
|
||||||
|
struct sc_pkcs15_object *tmpobj;
|
||||||
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;
|
||||||
|
@ -401,13 +408,14 @@ card_read_cert (CARD card, const char *certidstr,
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
rc = sc_pkcs15_find_cert_by_id (card->p15card, &certid, &certinfo);
|
rc = sc_pkcs15_find_cert_by_id (card->p15card, &certid, &tmpobj);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
log_info ("certificate '%s' not found: %s\n",
|
log_info ("certificate '%s' not found: %s\n",
|
||||||
certidstr, sc_strerror (rc));
|
certidstr, sc_strerror (rc));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
certinfo = tmpobj->data;
|
||||||
rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder);
|
rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
|
@ -430,22 +438,28 @@ card_read_cert (CARD card, const char *certidstr,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Create the signature and return the allocated result in OUTDATA. */
|
/* Create the signature and return the allocated result in OUTDATA.
|
||||||
|
If a PIN is required the PINCB will be used to ask for the PIN; it
|
||||||
|
should return the PIN in an allocated buffer and put it into PIN. */
|
||||||
int
|
int
|
||||||
card_create_signature (CARD card, const char *keyidstr, int hashalgo,
|
card_create_signature (CARD card, const char *keyidstr, int hashalgo,
|
||||||
|
int (pincb)(void*, const char *, char **),
|
||||||
|
void *pincb_arg,
|
||||||
const void *indata, size_t indatalen,
|
const void *indata, size_t indatalen,
|
||||||
void **outdata, size_t *outdatalen )
|
void **outdata, size_t *outdatalen )
|
||||||
{
|
{
|
||||||
unsigned int cryptflags = 0;
|
unsigned int cryptflags = 0;
|
||||||
struct sc_pkcs15_id keyid;
|
struct sc_pkcs15_id keyid;
|
||||||
struct sc_pkcs15_prkey_info *key;
|
struct sc_pkcs15_prkey_info *key;
|
||||||
/* struct sc_pkcs15_pin_info *pin;*/
|
struct sc_pkcs15_pin_info *pin;
|
||||||
|
struct sc_pkcs15_object *keyobj, *pinobj;
|
||||||
|
char *pinvalue;
|
||||||
int rc;
|
int rc;
|
||||||
unsigned char *outbuf = NULL;
|
unsigned char *outbuf = NULL;
|
||||||
size_t outbuflen;
|
size_t outbuflen;
|
||||||
|
|
||||||
if (!card || !card->p15card || !indata || !indatalen
|
if (!card || !card->p15card || !indata || !indatalen
|
||||||
|| !outdata || !outdatalen)
|
|| !outdata || !outdatalen || !pincb)
|
||||||
return GNUPG_Invalid_Value;
|
return GNUPG_Invalid_Value;
|
||||||
|
|
||||||
if (hashalgo != GCRY_MD_SHA1)
|
if (hashalgo != GCRY_MD_SHA1)
|
||||||
|
@ -455,7 +469,7 @@ card_create_signature (CARD card, const char *keyidstr, int hashalgo,
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
rc = sc_pkcs15_find_prkey_by_id (card->p15card, &keyid, &key);
|
rc = sc_pkcs15_find_prkey_by_id (card->p15card, &keyid, &keyobj);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
{
|
{
|
||||||
log_error ("private key not found: %s\n", sc_strerror(rc));
|
log_error ("private key not found: %s\n", sc_strerror(rc));
|
||||||
|
@ -463,13 +477,40 @@ card_create_signature (CARD card, const char *keyidstr, int hashalgo,
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
rc = 0;
|
rc = 0;
|
||||||
key = card->p15card->prkey_info;
|
key = keyobj->data;
|
||||||
|
|
||||||
|
rc = sc_pkcs15_find_pin_by_auth_id (card->p15card,
|
||||||
|
&keyobj->auth_id, &pinobj);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
log_error ("failed to find PIN by auth ID: %s\n", sc_strerror (rc));
|
||||||
|
rc = GNUPG_Bad_PIN_Method;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
pin = pinobj->data;
|
||||||
|
|
||||||
/* FIXME: Handle PIN via callback */
|
/* Fixme: pack this into a verification loop */
|
||||||
|
/* Fixme: we might want to pass pin->min_length and
|
||||||
|
pin->stored_length */
|
||||||
|
rc = pincb (pincb_arg, pinobj->label, &pinvalue);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
log_info ("PIN callback returned error: %s\n", gnupg_strerror (rc));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
cryptflags |= SC_PKCS15_HASH_SHA1;
|
rc = sc_pkcs15_verify_pin (card->p15card, pin,
|
||||||
cryptflags |= SC_PKCS15_PAD_PKCS1_V1_5;
|
pinvalue, strlen (pinvalue));
|
||||||
|
xfree (pinvalue);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
log_info ("PIN verification failed: %s\n", sc_strerror (rc));
|
||||||
|
rc = GNUPG_Bad_PIN;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cryptflags |= SC_PKCS15_HASH_SHA1; */
|
||||||
|
/* cryptflags |= SC_PKCS15_PAD_PKCS1_V1_5; */
|
||||||
|
|
||||||
outbuflen = 1024;
|
outbuflen = 1024;
|
||||||
outbuf = xtrymalloc (outbuflen);
|
outbuf = xtrymalloc (outbuflen);
|
||||||
|
@ -494,7 +535,6 @@ card_create_signature (CARD card, const char *keyidstr, int hashalgo,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
xfree (outbuf);
|
xfree (outbuf);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -29,6 +29,9 @@
|
||||||
#include "scdaemon.h"
|
#include "scdaemon.h"
|
||||||
#include "../assuan/assuan.h"
|
#include "../assuan/assuan.h"
|
||||||
|
|
||||||
|
/* maximum length aloowed as a PIN; used for INQUIRE NEEDPIN */
|
||||||
|
#define MAXLEN_PIN 100
|
||||||
|
|
||||||
#define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t))
|
#define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t))
|
||||||
|
|
||||||
/* Data used to associate an Assuan context with local server data */
|
/* Data used to associate an Assuan context with local server data */
|
||||||
|
@ -329,6 +332,40 @@ cmd_setdata (ASSUAN_CONTEXT ctx, char *line)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
pin_cb (void *opaque, const char *info, char **retstr)
|
||||||
|
{
|
||||||
|
ASSUAN_CONTEXT ctx = opaque;
|
||||||
|
char *command;
|
||||||
|
int rc;
|
||||||
|
char *value;
|
||||||
|
size_t valuelen;
|
||||||
|
|
||||||
|
*retstr = NULL;
|
||||||
|
log_debug ("asking for PIN '%s'\n", info);
|
||||||
|
|
||||||
|
rc = asprintf (&command, "NEEDPIN %s", info);
|
||||||
|
if (rc < 0)
|
||||||
|
return GNUPG_Out_Of_Core;
|
||||||
|
|
||||||
|
/* FIXME: Write an inquire function which returns the result in
|
||||||
|
secure memory */
|
||||||
|
rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
|
||||||
|
free (command);
|
||||||
|
if (rc)
|
||||||
|
return map_assuan_err (rc);
|
||||||
|
|
||||||
|
if (!valuelen || value[valuelen-1])
|
||||||
|
{
|
||||||
|
/* We require that the returned value is an UTF-8 string */
|
||||||
|
xfree (value);
|
||||||
|
return GNUPG_Invalid_Response;
|
||||||
|
}
|
||||||
|
*retstr = value;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* PKSIGN <hexified_id>
|
/* PKSIGN <hexified_id>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -337,11 +374,28 @@ cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
|
||||||
{
|
{
|
||||||
CTRL ctrl = assuan_get_pointer (ctx);
|
CTRL ctrl = assuan_get_pointer (ctx);
|
||||||
int rc;
|
int rc;
|
||||||
|
void *outdata;
|
||||||
|
size_t outdatalen;
|
||||||
|
|
||||||
if ((rc = open_card (ctrl)))
|
if ((rc = open_card (ctrl)))
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
rc = card_create_signature (ctrl->card_ctx,
|
||||||
|
line, GCRY_MD_SHA1,
|
||||||
|
pin_cb, ctx,
|
||||||
|
ctrl->in_data.value, ctrl->in_data.valuelen,
|
||||||
|
&outdata, &outdatalen);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
log_error ("card_create_signature failed: %s\n", gnupg_strerror (rc));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = assuan_send_data (ctx, outdata, outdatalen);
|
||||||
|
xfree (outdata);
|
||||||
|
if (rc)
|
||||||
|
return rc; /* that is already an assuan error code */
|
||||||
|
}
|
||||||
|
|
||||||
return map_to_assuan_status (rc);
|
return map_to_assuan_status (rc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,12 @@ int card_enum_keypairs (CARD card, int idx,
|
||||||
unsigned char **keyid, size_t *nkeyid);
|
unsigned char **keyid, size_t *nkeyid);
|
||||||
int card_read_cert (CARD card, const char *certidstr,
|
int card_read_cert (CARD card, const char *certidstr,
|
||||||
unsigned char **cert, size_t *ncert);
|
unsigned char **cert, size_t *ncert);
|
||||||
|
int card_create_signature (CARD card,
|
||||||
|
const char *keyidstr, int hashalgo,
|
||||||
|
int (pincb)(void*, const char *, char **),
|
||||||
|
void *pincb_arg,
|
||||||
|
const void *indata, size_t indatalen,
|
||||||
|
void **outdata, size_t *outdatalen );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user