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 + + * 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 + + * 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 * 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;