* app-openpgp.c (store_fpr): Fixed fingerprint calculation.

* keygen.c (gen_card_key): Obviously we should use the creation
date received from SCDAEMON, so that the fingerprints will match.
* sign.c (do_sign): Pass the serialno to the sign code.
* keyid.c (serialno_and_fpr_from_sk): New.
This commit is contained in:
Werner Koch 2003-07-01 08:34:45 +00:00
parent 5c46f134e2
commit 39046ea7ec
11 changed files with 143 additions and 61 deletions

View File

@ -1,3 +1,23 @@
2003-07-01 Werner Koch <wk@gnupg.org>
* keygen.c (gen_card_key): Obviously we should use the creation
date received from SCDAEMON, so that the fingerprints will match.
* sign.c (do_sign): Pass the serialno to the sign code.
* keyid.c (serialno_and_fpr_from_sk): New.
2003-06-30 Werner Koch <wk@gnupg.org>
* call-agent.h (agent_card_info_s): Add field serialno.
* call-agent.c (store_serialno): New.
(learn_status_cb): Store the serial number.
* keygen.c (gen_card_key): Store the serial number
(check_smartcard): New argument to return the serial number.
(generate_keypair): Get the serial number from check_smartcard and
store it as a parameter.
* parse-packet.c (parse_key): Use the protect.iv field to store the
serial number.
* build-packet.c (do_secret_key): Write the serial number.
2003-06-27 Werner Koch <wk@gnupg.org>
* seckey-cert.c (check_secret_key): Bypass the unprotection for

View File

@ -415,7 +415,7 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk )
if( sk->protect.s2k.mode == 3 )
iobuf_put(a, sk->protect.s2k.count );
/* For out special modes 1001 and 1002 we do not need an IV */
/* For our special modes 1001 and 1002 we do not need an IV */
if( sk->protect.s2k.mode != 1001
&& sk->protect.s2k.mode != 1002 )
iobuf_write(a, sk->protect.iv, sk->protect.ivlen );
@ -428,8 +428,11 @@ do_secret_key( iobuf_t out, int ctb, PKT_secret_key *sk )
; /* GnuPG extension - don't write a secret key at all */
else if( sk->protect.s2k.mode == 1002 )
{ /* GnuPG extension - divert to OpenPGP smartcard. */
iobuf_put(a, 0 ); /* length of the serial number or 0 for unknown. */
/* fixme: write the serial number. */
iobuf_put(a, sk->protect.ivlen ); /* length of the serial
number or 0 for no serial
number. */
/* The serial number gets stored in the IV field. */
iobuf_write(a, sk->protect.iv, sk->protect.ivlen);
}
else if( sk->is_protected && sk->version >= 4 ) {
/* The secret key is protected - write it out as it is */

View File

@ -340,6 +340,26 @@ unhexify_fpr (const char *hexstr, unsigned char *fpr)
return 1; /* okay */
}
/* Take the serial number from LINE and return it verbatim in a newly
allocated string. We make sure that only hex characters are
returned. */
static char *
store_serialno (const char *line)
{
const char *s;
char *p;
for (s=line; hexdigitp (s); s++)
;
p = xtrymalloc (s + 1 - line);
if (p)
{
memcpy (p, line, s-line);
p[s-line] = 0;
}
return p;
}
#if 0
@ -442,7 +462,11 @@ learn_status_cb (void *opaque, const char *line)
while (spacep (line))
line++;
if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
{
parm->serialno = store_serialno (line);
}
else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
{
parm->disp_name = unescape_status_string (line);
}
@ -619,7 +643,7 @@ membuf_data_cb (void *opaque, const void *buffer, size_t length)
/* Send a sign command to the scdaemon via gpg-agent's pass thru
mechanism. */
int
agent_scd_pksign (const char *keyid, int hashalgo,
agent_scd_pksign (const char *serialno, int hashalgo,
const unsigned char *indata, size_t indatalen,
char **r_buf, size_t *r_buflen)
{
@ -649,7 +673,7 @@ agent_scd_pksign (const char *keyid, int hashalgo,
return rc;
init_membuf (&data, 1024);
snprintf (line, DIM(line)-1, "SCD PKSIGN %s", keyid);
snprintf (line, DIM(line)-1, "SCD PKSIGN %s", serialno);
line[DIM(line)-1] = 0;
rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data,
NULL, NULL, NULL, NULL);
@ -662,25 +686,3 @@ agent_scd_pksign (const char *keyid, int hashalgo,
return 0;
}

View File

@ -23,6 +23,7 @@
struct agent_card_info_s {
int error; /* private. */
char *serialno; /* malloced hex string. */
char *disp_name; /* malloced. */
char *pubkey_url; /* malloced. */
char fpr1valid;

View File

@ -1,5 +1,5 @@
/* keydb.h - Key database
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
* Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -259,6 +259,10 @@ const char *colon_expirestr_from_sig (PKT_signature *sig);
byte *fingerprint_from_sk( PKT_secret_key *sk, byte *buf, size_t *ret_len );
byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len );
char *serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
PKT_secret_key *sk);
/*-- kbnode.c --*/
KBNODE new_kbnode( PACKET *pkt );
KBNODE clone_kbnode( KBNODE node );

View File

@ -61,7 +61,8 @@ enum para_name {
pSUBKEYEXPIRE, /* in n seconds */
pPASSPHRASE,
pPASSPHRASE_DEK,
pPASSPHRASE_S2K
pPASSPHRASE_S2K,
pSERIALNO
};
struct para_data_s {
@ -115,8 +116,9 @@ static int mdc_available,ks_modify;
static void do_generate_keypair( struct para_data_s *para,
struct output_control_s *outctrl, int card);
static int write_keyblock( iobuf_t out, KBNODE node );
static int check_smartcard (void);
static int gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root, u32 expireval);
static int check_smartcard (char **);
static int gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root,
u32 expireval, struct para_data_s *para);
@ -2078,6 +2080,7 @@ generate_keypair( const char *fname )
struct para_data_s *para = NULL;
struct para_data_s *r;
struct output_control_s outctrl;
char *serialno = NULL;
memset (&outctrl, 0, sizeof (outctrl));
@ -2089,7 +2092,8 @@ generate_keypair( const char *fname )
do
{
card = check_smartcard ();
xfree (serialno); serialno = NULL;
card = check_smartcard (&serialno);
if (card < 0)
return;
if (card > 1)
@ -2097,6 +2101,16 @@ generate_keypair( const char *fname )
}
while (card > 1);
if (serialno)
{
r = xcalloc (1, sizeof *r + strlen (serialno) );
r->key = pSERIALNO;
strcpy( r->u.value, serialno);
r->next = para;
para = r;
xfree (serialno); serialno = NULL;
}
if (card)
{
algo = PUBKEY_ALGO_RSA;
@ -2156,7 +2170,7 @@ generate_keypair( const char *fname )
r->next = para;
para = r;
}
expire = ask_expire_interval(0);
r = xcalloc (1, sizeof *r + 20 );
r->key = pKEYEXPIRE;
@ -2322,7 +2336,7 @@ do_generate_keypair (struct para_data_s *para,
else
{
rc = gen_card_key (PUBKEY_ALGO_RSA, 1, pub_root, sec_root,
get_parameter_u32 (para, pKEYEXPIRE));
get_parameter_u32 (para, pKEYEXPIRE), para);
if (!rc)
{
sk = sec_root->next->pkt->pkt.secret_key;
@ -2725,7 +2739,7 @@ smartcard_change_name (const char *current_name)
2 = generate subkey
*/
static int
check_smartcard (void)
check_smartcard (char **r_serialno)
{
struct agent_card_info_s info;
int rc;
@ -2738,7 +2752,8 @@ check_smartcard (void)
return 0;
}
tty_printf (_("OpenPGP card with serial number %s detected\n"), "xxx");
tty_printf (_("OpenPGP card no. %s detected\n"),
info.serialno? info.serialno : "[none]");
for (;;)
@ -2790,6 +2805,7 @@ check_smartcard (void)
if (reread)
{
xfree (info.serialno); info.serialno = NULL;
xfree (info.disp_name); info.disp_name = NULL;
xfree (info.pubkey_url); info.pubkey_url = NULL;
rc = agent_learn (&info);
@ -2803,6 +2819,10 @@ check_smartcard (void)
}
}
if (r_serialno && rc > 0)
*r_serialno = info.serialno;
else
xfree (info.serialno);
xfree (info.disp_name);
xfree (info.pubkey_url);
@ -2813,9 +2833,10 @@ check_smartcard (void)
static int
gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root,
u32 expireval)
u32 expireval, struct para_data_s *para)
{
int rc;
const char *s;
struct agent_card_genkey_s info;
PACKET *pkt;
PKT_secret_key *sk;
@ -2850,7 +2871,7 @@ gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root,
pk = xcalloc (1, sizeof *pk );
sk = xcalloc (1, sizeof *sk );
sk->timestamp = pk->timestamp = make_timestamp();
sk->timestamp = pk->timestamp = info.created_at;
sk->version = pk->version = 4;
if (expireval)
sk->expiredate = pk->expiredate = pk->timestamp + expireval;
@ -2862,6 +2883,13 @@ gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root,
sk->skey[2] = mpi_set_opaque (NULL, xstrdup ("dummydata"), 10);
sk->is_protected = 1;
sk->protect.s2k.mode = 1002;
s = get_parameter_value (para, pSERIALNO);
if (s)
{
for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1];
sk->protect.ivlen++, s += 2)
sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s);
}
pkt = xcalloc (1,sizeof *pkt);
pkt->pkttype = keyno == 1 ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY;

View File

@ -62,7 +62,6 @@ do_fingerprint_md( PKT_public_key *pk )
gcry_md_open (&md, pk->version < 4 ? DIGEST_ALGO_RMD160
: DIGEST_ALGO_SHA1, 0);
gcry_md_start_debug (md,"keyid");
n = pk->version < 4 ? 8 : 6;
for(i=0; i < npkey; i++ ) {
size_t nbytes;
@ -575,4 +574,33 @@ fingerprint_from_sk( PKT_secret_key *sk, byte *array, size_t *ret_len )
}
/* Create a serialno/fpr string from the serial number and the secret
* key. caller must free the returned string. There is no error
* return. */
char *
serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
PKT_secret_key *sk)
{
unsigned char fpr[MAX_FINGERPRINT_LEN];
size_t fprlen;
char *buffer, *p;
int i;
fingerprint_from_sk (sk, fpr, &fprlen);
buffer = p= xmalloc (snlen*2 + 1 + fprlen*2 + 1);
for (i=0; i < snlen; i++, p+=2)
sprintf (p, "%02X", sn[i]);
*p++ = '/';
for (i=0; i < fprlen; i++, p+=2)
sprintf (p, "%02X", fpr[i]);
*p = 0;
return buffer;
}

View File

@ -193,7 +193,7 @@ typedef struct {
* Note about the pkey/skey elements: We assume that the secret keys
* has the same elemts as the public key at the begin of the array, so
* that npkey < nskey and it is possible to compare the secret and
* public keys by comparing the first npkey elements of pkey againts skey.
* public keys by comparing the first npkey elements of pkey against skey.
*/
typedef struct {
u32 timestamp; /* key made */

View File

@ -1562,6 +1562,7 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) {
PKT_secret_key *sk = pkt->pkt.secret_key;
byte temp[16];
size_t snlen = 0;
if( !npkey ) {
sk->skey[0] = mpi_set_opaque( NULL,
@ -1672,7 +1673,6 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
(ulong)sk->protect.s2k.count);
}
else if( sk->protect.s2k.mode == 1002 ) {
size_t snlen;
/* Read the serial number. */
if (pktlen < 1) {
rc = GPG_ERR_INV_PACKET;
@ -1684,17 +1684,6 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
rc = GPG_ERR_INV_PACKET;
goto leave;
}
if( list_mode ) {
printf("\tserial-number: ");
for (;snlen; snlen--)
printf ("%02X", (unsigned int)iobuf_get_noeof (inp));
putchar ('\n');
}
else {
for (;snlen; snlen--)
iobuf_get_noeof (inp);
}
}
}
/* Note that a sk->protect.algo > 110 is illegal, but I'm
@ -1725,9 +1714,12 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
}
if( sk->protect.s2k.mode == 1001 )
sk->protect.ivlen = 0;
else if( sk->protect.s2k.mode == 1002 )
sk->protect.ivlen = 0;
else if( sk->protect.s2k.mode == 1002 ) {
if (snlen > 16)
log_info ("WARNING: serial number of card truncated\n");
sk->protect.ivlen = snlen < 16? snlen : 16;
}
if( pktlen < sk->protect.ivlen ) {
rc = GPG_ERR_INV_PACKET;
goto leave;
@ -1735,7 +1727,8 @@ parse_key( iobuf_t inp, int pkttype, unsigned long pktlen,
for(i=0; i < sk->protect.ivlen && pktlen; i++, pktlen-- )
temp[i] = iobuf_get_noeof(inp);
if( list_mode ) {
printf( "\tprotect IV: ");
printf( sk->protect.s2k.mode == 1002? "\tserial-number: "
: "\tprotect IV: ");
for(i=0; i < sk->protect.ivlen; i++ )
printf(" %02x", temp[i] );
putchar('\n');

View File

@ -215,12 +215,14 @@ encode_md_value (int pubkey_algo, gcry_md_hd_t md, int hash_algo,
}
else
{
gpg_error_t rc;
byte *asn;
size_t asnlen;
if( gcry_md_algo_info( algo, GCRYCTL_GET_ASNOID, NULL, &asnlen ) )
rc = gcry_md_algo_info( algo, GCRYCTL_GET_ASNOID, NULL, &asnlen);
if (rc)
log_fatal("can't get OID of algo %d: %s\n",
algo, gcry_strerror(-1));
algo, gpg_strerror (rc));
asn = xmalloc (asnlen);
if( gcry_md_algo_info( algo, GCRYCTL_GET_ASNOID, asn, &asnlen ) )
BUG();

View File

@ -277,13 +277,14 @@ do_sign( PKT_secret_key *sk, PKT_signature *sig,
{ /* FIXME: Note that we do only support RSA for now. */
char *rbuf;
size_t rbuflen;
char *snbuf;
/* FIXME: We need to pass the correct keyid or better the
fingerprint to the scdaemon. */
rc = agent_scd_pksign ("nokeyid", digest_algo,
snbuf = serialno_and_fpr_from_sk (sk->protect.iv, sk->protect.ivlen, sk);
rc = agent_scd_pksign (snbuf, digest_algo,
gcry_md_read (md, digest_algo),
gcry_md_get_algo_dlen (digest_algo),
&rbuf, &rbuflen);
xfree (snbuf);
if (!rc)
{
unsigned int nbytes = rbuflen;