mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
More stuff for SCs - don't expect them to work.
This commit is contained in:
parent
c39b866d2a
commit
2e553c1777
67
scd/card-common.h
Normal file
67
scd/card-common.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* card-common.h - Common declarations for all card types
|
||||
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#ifndef CARD_COMMON_H
|
||||
#define CARD_COMMON_H
|
||||
|
||||
|
||||
struct card_ctx_s {
|
||||
int reader; /* used reader */
|
||||
struct sc_context *ctx;
|
||||
struct sc_card *scard;
|
||||
struct sc_pkcs15_card *p15card; /* only if there is a pkcs15 application */
|
||||
|
||||
struct {
|
||||
int initialized; /* the card has been initialied and the function
|
||||
pointers may be used. However for
|
||||
unsupported operations the particular
|
||||
function pointer is set to NULL */
|
||||
|
||||
int (*enum_keypairs) (CARD card, int idx,
|
||||
unsigned char *keygrip, char **keyid);
|
||||
int (*read_cert) (CARD card, const char *certidstr,
|
||||
unsigned char **cert, size_t *ncert);
|
||||
int (*sign) (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 );
|
||||
int (*decipher) (CARD card, const char *keyidstr,
|
||||
int (pincb)(void*, const char *, char **),
|
||||
void *pincb_arg,
|
||||
const void *indata, size_t indatalen,
|
||||
void **outdata, size_t *outdatalen);
|
||||
} fnc;
|
||||
|
||||
};
|
||||
|
||||
/*-- card.c --*/
|
||||
int map_sc_err (int rc);
|
||||
int card_help_get_keygrip (KsbaCert cert, unsigned char *array);
|
||||
|
||||
|
||||
|
||||
/* constructors */
|
||||
void card_p15_bind (CARD card);
|
||||
void card_dinsig_bind (CARD card);
|
||||
|
||||
|
||||
#endif /*CARD_COMMON_H*/
|
205
scd/card-dinsig.c
Normal file
205
scd/card-dinsig.c
Normal file
@ -0,0 +1,205 @@
|
||||
/* card-dinsig.c - German signature law (DINSIG) functions
|
||||
* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <opensc-pkcs15.h>
|
||||
#include <ksba.h>
|
||||
|
||||
#include "scdaemon.h"
|
||||
#include "card-common.h"
|
||||
|
||||
static int dinsig_read_cert (CARD card, const char *certidstr,
|
||||
unsigned char **cert, size_t *ncert);
|
||||
|
||||
|
||||
|
||||
/* See card.c for interface description. Frankly we don't do any real
|
||||
enumeration but just check whether the well know files are
|
||||
available.
|
||||
*/
|
||||
static int
|
||||
dinsig_enum_keypairs (CARD card, int idx,
|
||||
unsigned char *keygrip, char **keyid)
|
||||
{
|
||||
int rc;
|
||||
unsigned char *buf;
|
||||
size_t buflen;
|
||||
KsbaError krc;
|
||||
KsbaCert cert;
|
||||
|
||||
/* fixme: We should locate the application via the EF(DIR) and not
|
||||
assume a Netkey card */
|
||||
if (!idx)
|
||||
rc = dinsig_read_cert (card, "DINSIG-DF01.C000", &buf, &buflen);
|
||||
else if (idx == 1)
|
||||
rc = dinsig_read_cert (card, "DINSIG-DF01.C200", &buf, &buflen);
|
||||
else
|
||||
rc = -1;
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
cert = ksba_cert_new ();
|
||||
if (!cert)
|
||||
{
|
||||
xfree (buf);
|
||||
return GNUPG_Out_Of_Core;
|
||||
}
|
||||
|
||||
krc = ksba_cert_init_from_mem (cert, buf, buflen);
|
||||
xfree (buf);
|
||||
if (krc)
|
||||
{
|
||||
log_error ("failed to parse the certificate at idx %d: %s\n",
|
||||
idx, ksba_strerror (krc));
|
||||
ksba_cert_release (cert);
|
||||
return GNUPG_Card_Error;
|
||||
}
|
||||
if (card_help_get_keygrip (cert, keygrip))
|
||||
{
|
||||
log_error ("failed to calculate the keygrip at index %d\n", idx);
|
||||
ksba_cert_release (cert);
|
||||
return GNUPG_Card_Error;
|
||||
}
|
||||
ksba_cert_release (cert);
|
||||
|
||||
/* return the iD */
|
||||
if (keyid)
|
||||
{
|
||||
*keyid = xtrymalloc (17);
|
||||
if (!*keyid)
|
||||
return GNUPG_Out_Of_Core;
|
||||
if (!idx)
|
||||
strcpy (*keyid, "DINSIG-DF01.C000");
|
||||
else
|
||||
strcpy (*keyid, "DINSIG-DF01.C200");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* See card.c for interface description */
|
||||
static int
|
||||
dinsig_read_cert (CARD card, const char *certidstr,
|
||||
unsigned char **cert, size_t *ncert)
|
||||
{
|
||||
int rc;
|
||||
struct sc_path path;
|
||||
struct sc_file *file;
|
||||
unsigned char *buf;
|
||||
int buflen;
|
||||
|
||||
if (!strcmp (certidstr, "DINSIG-DF01.C000"))
|
||||
sc_format_path ("3F00DF01C000", &path);
|
||||
else if (!strcmp (certidstr, "DINSIG-DF01.C200"))
|
||||
sc_format_path ("3F00DF01C200", &path);
|
||||
else
|
||||
return GNUPG_Invalid_Id;
|
||||
|
||||
rc = sc_select_file (card->scard, &path, &file);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("sc_select_file failed: %s\n", sc_strerror (rc));
|
||||
return map_sc_err (rc);
|
||||
}
|
||||
if (file->type != SC_FILE_TYPE_WORKING_EF
|
||||
|| file->ef_structure != SC_FILE_EF_TRANSPARENT)
|
||||
{
|
||||
log_error ("wrong type or structure of certificate EF\n");
|
||||
sc_file_free (file);
|
||||
return GNUPG_Card_Error;
|
||||
}
|
||||
if (file->size < 20) /* check against a somewhat arbitrary length */
|
||||
{
|
||||
log_error ("certificate EF too short\n");
|
||||
sc_file_free (file);
|
||||
return GNUPG_Card_Error;
|
||||
}
|
||||
buf = xtrymalloc (file->size);
|
||||
if (!buf)
|
||||
{
|
||||
sc_file_free (file);
|
||||
return GNUPG_Out_Of_Core;
|
||||
}
|
||||
|
||||
rc = sc_read_binary (card->scard, 0, buf, file->size, 0);
|
||||
if (rc >= 0 && rc != file->size)
|
||||
{
|
||||
log_error ("short read on certificate EF\n");
|
||||
sc_file_free (file);
|
||||
xfree (buf);
|
||||
return GNUPG_Card_Error;
|
||||
}
|
||||
sc_file_free (file);
|
||||
if (rc < 0)
|
||||
{
|
||||
log_error ("error reading certificate EF: %s\n", sc_strerror (rc));
|
||||
xfree (buf);
|
||||
return map_sc_err (rc);
|
||||
}
|
||||
buflen = rc;
|
||||
|
||||
/* The object is not a plain certificate but wrapped into id-at
|
||||
userCertificate - fixme: we should check the specs and decided
|
||||
whether libksba should support it */
|
||||
if (buflen > 9 && buf[0] == 0x30 && buf[4] == 6 && buf[5] == 3
|
||||
&& buf[6] == 0x55 && buf[7] == 4 && buf[8] == 0x24)
|
||||
{
|
||||
/* We have to strip the padding. Although this is a good idea
|
||||
anyway, we have to do it due to a KSBA problem; KSBA does not
|
||||
work correct when the buffer is larger than the ASN.1
|
||||
structure and the certificates here are padded with FF. So
|
||||
as a workaround we look at the outer structure to get the
|
||||
size of the entire thing and adjust the buflen. We can only
|
||||
do this when there is a 2 byte length field */
|
||||
size_t seqlen;
|
||||
if (buf[1] == 0x82)
|
||||
{
|
||||
seqlen = ((buf[2] << 8) | buf[3]) + 4;
|
||||
if (seqlen < buflen)
|
||||
buflen = seqlen;
|
||||
}
|
||||
memmove (buf, buf+9, buflen-9);
|
||||
buflen -= 9;
|
||||
}
|
||||
|
||||
*cert = buf;
|
||||
*ncert = buflen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Bind our operations to the card */
|
||||
void
|
||||
card_dinsig_bind (CARD card)
|
||||
{
|
||||
card->fnc.enum_keypairs = dinsig_enum_keypairs;
|
||||
card->fnc.read_cert = dinsig_read_cert;
|
||||
|
||||
}
|
399
scd/card-p15.c
Normal file
399
scd/card-p15.c
Normal file
@ -0,0 +1,399 @@
|
||||
/* card-p15.c - PKCS-15 based card access
|
||||
* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <opensc-pkcs15.h>
|
||||
#include <ksba.h>
|
||||
|
||||
#include "scdaemon.h"
|
||||
#include "card-common.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* See card.c for interface description */
|
||||
static int
|
||||
p15_enum_keypairs (CARD card, int idx,
|
||||
unsigned char *keygrip, char **keyid)
|
||||
{
|
||||
int rc;
|
||||
KsbaError krc;
|
||||
struct sc_pkcs15_object *objs[32], *tmpobj;
|
||||
int nobjs;
|
||||
struct sc_pkcs15_prkey_info *pinfo;
|
||||
struct sc_pkcs15_cert_info *certinfo;
|
||||
struct sc_pkcs15_cert *certder;
|
||||
KsbaCert cert;
|
||||
|
||||
rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_PRKEY_RSA,
|
||||
objs, DIM (objs));
|
||||
if (rc < 0)
|
||||
{
|
||||
log_error ("private keys enumeration failed: %s\n", sc_strerror (rc));
|
||||
return GNUPG_Card_Error;
|
||||
}
|
||||
nobjs = rc;
|
||||
rc = 0;
|
||||
if (idx >= nobjs)
|
||||
return -1;
|
||||
pinfo = objs[idx]->data;
|
||||
|
||||
/* now we need to read the certificate so that we can calculate the
|
||||
keygrip */
|
||||
rc = sc_pkcs15_find_cert_by_id (card->p15card, &pinfo->id, &tmpobj);
|
||||
if (rc)
|
||||
{
|
||||
log_info ("certificate for private key %d not found: %s\n",
|
||||
idx, sc_strerror (rc));
|
||||
/* note, that we return the ID anyway */
|
||||
rc = GNUPG_Missing_Certificate;
|
||||
goto return_keyid;
|
||||
}
|
||||
certinfo = tmpobj->data;
|
||||
rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder);
|
||||
if (rc)
|
||||
{
|
||||
log_info ("failed to read certificate for private key %d: %s\n",
|
||||
idx, sc_strerror (rc));
|
||||
return GNUPG_Card_Error;
|
||||
}
|
||||
|
||||
cert = ksba_cert_new ();
|
||||
if (!cert)
|
||||
{
|
||||
sc_pkcs15_free_certificate (certder);
|
||||
return GNUPG_Out_Of_Core;
|
||||
}
|
||||
krc = ksba_cert_init_from_mem (cert, certder->data, certder->data_len);
|
||||
sc_pkcs15_free_certificate (certder);
|
||||
if (krc)
|
||||
{
|
||||
log_error ("failed to parse the certificate for private key %d: %s\n",
|
||||
idx, ksba_strerror (krc));
|
||||
ksba_cert_release (cert);
|
||||
return GNUPG_Card_Error;
|
||||
}
|
||||
if (card_help_get_keygrip (cert, keygrip))
|
||||
{
|
||||
log_error ("failed to calculate the keygrip of private key %d\n", idx);
|
||||
ksba_cert_release (cert);
|
||||
return GNUPG_Card_Error;
|
||||
}
|
||||
ksba_cert_release (cert);
|
||||
|
||||
rc = 0;
|
||||
return_keyid:
|
||||
if (keyid)
|
||||
{
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
*keyid = p = xtrymalloc (9+pinfo->id.len*2+1);
|
||||
if (!*keyid)
|
||||
return GNUPG_Out_Of_Core;
|
||||
p = stpcpy (p, "P15-5015.");
|
||||
for (i=0; i < pinfo->id.len; i++, p += 2)
|
||||
sprintf (p, "%02X", pinfo->id.value[i]);
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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, "P15-5015.", 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;
|
||||
}
|
||||
|
||||
|
||||
/* See card.c for interface description */
|
||||
static int
|
||||
p15_read_cert (CARD card, const char *certidstr,
|
||||
unsigned char **cert, size_t *ncert)
|
||||
{
|
||||
struct sc_pkcs15_object *tmpobj;
|
||||
struct sc_pkcs15_id certid;
|
||||
struct sc_pkcs15_cert_info *certinfo;
|
||||
struct sc_pkcs15_cert *certder;
|
||||
int rc;
|
||||
|
||||
if (!card || !certidstr || !cert || !ncert)
|
||||
return GNUPG_Invalid_Value;
|
||||
if (!card->p15card)
|
||||
return GNUPG_No_PKCS15_App;
|
||||
|
||||
rc = idstr_to_id (certidstr, &certid);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = sc_pkcs15_find_cert_by_id (card->p15card, &certid, &tmpobj);
|
||||
if (rc)
|
||||
{
|
||||
log_info ("certificate '%s' not found: %s\n",
|
||||
certidstr, sc_strerror (rc));
|
||||
return -1;
|
||||
}
|
||||
certinfo = tmpobj->data;
|
||||
rc = sc_pkcs15_read_certificate (card->p15card, certinfo, &certder);
|
||||
if (rc)
|
||||
{
|
||||
log_info ("failed to read certificate '%s': %s\n",
|
||||
certidstr, sc_strerror (rc));
|
||||
return GNUPG_Card_Error;
|
||||
}
|
||||
|
||||
*cert = xtrymalloc (certder->data_len);
|
||||
if (!*cert)
|
||||
{
|
||||
sc_pkcs15_free_certificate (certder);
|
||||
return GNUPG_Out_Of_Core;
|
||||
}
|
||||
memcpy (*cert, certder->data, certder->data_len);
|
||||
*ncert = certder->data_len;
|
||||
sc_pkcs15_free_certificate (certder);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* See card.c for interface description */
|
||||
static int
|
||||
p15_sign (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 )
|
||||
{
|
||||
unsigned int cryptflags = 0;
|
||||
struct sc_pkcs15_id keyid;
|
||||
struct sc_pkcs15_pin_info *pin;
|
||||
struct sc_pkcs15_object *keyobj, *pinobj;
|
||||
char *pinvalue;
|
||||
int rc;
|
||||
unsigned char *outbuf = NULL;
|
||||
size_t outbuflen;
|
||||
|
||||
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, &keyobj);
|
||||
if (rc < 0)
|
||||
{
|
||||
log_error ("private key not found: %s\n", sc_strerror(rc));
|
||||
rc = GNUPG_No_Secret_Key;
|
||||
goto leave;
|
||||
}
|
||||
rc = 0;
|
||||
|
||||
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: 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;
|
||||
}
|
||||
|
||||
rc = sc_pkcs15_verify_pin (card->p15card, pin,
|
||||
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;
|
||||
outbuf = xtrymalloc (outbuflen);
|
||||
if (!outbuf)
|
||||
return GNUPG_Out_Of_Core;
|
||||
|
||||
rc = sc_pkcs15_compute_signature (card->p15card, keyobj,
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* See card.c for description */
|
||||
static int
|
||||
p15_decipher (CARD card, const char *keyidstr,
|
||||
int (pincb)(void*, const char *, char **),
|
||||
void *pincb_arg,
|
||||
const void *indata, size_t indatalen,
|
||||
void **outdata, size_t *outdatalen )
|
||||
{
|
||||
struct sc_pkcs15_id keyid;
|
||||
struct sc_pkcs15_pin_info *pin;
|
||||
struct sc_pkcs15_object *keyobj, *pinobj;
|
||||
char *pinvalue;
|
||||
int rc;
|
||||
unsigned char *outbuf = NULL;
|
||||
size_t outbuflen;
|
||||
|
||||
rc = idstr_to_id (keyidstr, &keyid);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = sc_pkcs15_find_prkey_by_id (card->p15card, &keyid, &keyobj);
|
||||
if (rc < 0)
|
||||
{
|
||||
log_error ("private key not found: %s\n", sc_strerror(rc));
|
||||
rc = GNUPG_No_Secret_Key;
|
||||
goto leave;
|
||||
}
|
||||
rc = 0;
|
||||
|
||||
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: 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;
|
||||
}
|
||||
|
||||
rc = sc_pkcs15_verify_pin (card->p15card, pin,
|
||||
pinvalue, strlen (pinvalue));
|
||||
xfree (pinvalue);
|
||||
if (rc)
|
||||
{
|
||||
log_info ("PIN verification failed: %s\n", sc_strerror (rc));
|
||||
rc = GNUPG_Bad_PIN;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
outbuflen = indatalen < 256? 256 : indatalen;
|
||||
outbuf = xtrymalloc (outbuflen);
|
||||
if (!outbuf)
|
||||
return GNUPG_Out_Of_Core;
|
||||
|
||||
/* OpenSC does not yet support decryption for cryptflex cards */
|
||||
/* rc = sc_pkcs15_decipher (card->p15card, key, */
|
||||
/* indata, indatalen, */
|
||||
/* outbuf, outbuflen); */
|
||||
rc = sc_pkcs15_compute_signature (card->p15card, keyobj,
|
||||
0,
|
||||
indata, indatalen,
|
||||
outbuf, outbuflen );
|
||||
if (rc < 0)
|
||||
{
|
||||
log_error ("failed to decipger the data: %s\n", sc_strerror (rc));
|
||||
rc = GNUPG_Card_Error;
|
||||
}
|
||||
else
|
||||
{
|
||||
*outdatalen = rc;
|
||||
*outdata = outbuf;
|
||||
outbuf = NULL;
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
|
||||
leave:
|
||||
xfree (outbuf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Bind our operations to the card */
|
||||
void
|
||||
card_p15_bind (CARD card)
|
||||
{
|
||||
card->fnc.enum_keypairs = p15_enum_keypairs;
|
||||
card->fnc.read_cert = p15_read_cert;
|
||||
card->fnc.sign = p15_sign;
|
||||
card->fnc.decipher = p15_decipher;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user