aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2003-07-01 08:34:45 +0000
committerWerner Koch <[email protected]>2003-07-01 08:34:45 +0000
commit39046ea7ec221efa9db946230ddc9fb3e65d19ab (patch)
treeaa251dc190129aef89d82597f7ffb53ba6486fc9
parentKey generation and signing using the OpenPGP card does rudimentary work. (diff)
downloadgnupg-39046ea7ec221efa9db946230ddc9fb3e65d19ab.tar.gz
gnupg-39046ea7ec221efa9db946230ddc9fb3e65d19ab.zip
* 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.
Diffstat (limited to '')
-rw-r--r--g10/ChangeLog20
-rw-r--r--g10/build-packet.c9
-rw-r--r--g10/call-agent.c52
-rw-r--r--g10/call-agent.h1
-rw-r--r--g10/keydb.h6
-rw-r--r--g10/keygen.c48
-rw-r--r--g10/keyid.c30
-rw-r--r--g10/packet.h2
-rw-r--r--g10/parse-packet.c23
-rw-r--r--g10/seskey.c6
-rw-r--r--g10/sign.c7
11 files changed, 143 insertions, 61 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 023f66b0d..bf394f211 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,23 @@
+2003-07-01 Werner Koch <[email protected]>
+
+ * 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 <[email protected]>
+
+ * 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 <[email protected]>
* seckey-cert.c (check_secret_key): Bypass the unprotection for
diff --git a/g10/build-packet.c b/g10/build-packet.c
index afc123624..a24bdfcc6 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -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 */
diff --git a/g10/call-agent.c b/g10/call-agent.c
index 67aa333ee..d38e4c0fc 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -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;
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/g10/call-agent.h b/g10/call-agent.h
index c620268f2..2169a5319 100644
--- a/g10/call-agent.h
+++ b/g10/call-agent.h
@@ -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;
diff --git a/g10/keydb.h b/g10/keydb.h
index 6652db32a..4920e88a1 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -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 );
diff --git a/g10/keygen.c b/g10/keygen.c
index 328647f03..5dab70ff1 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -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;
diff --git a/g10/keyid.c b/g10/keyid.c
index 49a316db5..54a79bcdb 100644
--- a/g10/keyid.c
+++ b/g10/keyid.c
@@ -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;
+}
+
+
+
+
+
+
+
diff --git a/g10/packet.h b/g10/packet.h
index 81851373d..dc5b1583a 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -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 */
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index fc9e2559f..57a6d3d7b 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -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');
diff --git a/g10/seskey.c b/g10/seskey.c
index 5d0490cdf..ae22032a1 100644
--- a/g10/seskey.c
+++ b/g10/seskey.c
@@ -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();
diff --git a/g10/sign.c b/g10/sign.c
index 86159a4a1..d9ce074d4 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -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;