* app-openpgp.c (store_fpr): Fixed fingerprint calculation.
authorWerner Koch <wk@gnupg.org>
Tue, 1 Jul 2003 08:34:45 +0000 (08:34 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 1 Jul 2003 08:34:45 +0000 (08:34 +0000)
* 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.

g10/ChangeLog
g10/build-packet.c
g10/call-agent.c
g10/call-agent.h
g10/keydb.h
g10/keygen.c
g10/keyid.c
g10/packet.h
g10/parse-packet.c
g10/seskey.c
g10/sign.c

index 023f66b..bf394f2 100644 (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
index afc1236..a24bdfc 100644 (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 */
index 67aa333..d38e4c0 100644 (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;
+}
+
 
 \f
 #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;
 }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
index c620268..2169a53 100644 (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;
index 6652db3..4920e88 100644 (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 );
index 328647f..5dab70f 100644 (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;
index 49a316d..54a79bc 100644 (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;
+}
+
+
+
+
+
+
+
 
index 8185137..dc5b158 100644 (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 */
index fc9e255..57a6d3d 100644 (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');
index 5d0490c..ae22032 100644 (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();
index 86159a4..d9ce074 100644 (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;