Provide inforation about smartcards.
authorWerner Koch <wk@gnupg.org>
Wed, 4 Feb 2009 09:51:43 +0000 (09:51 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 4 Feb 2009 09:51:43 +0000 (09:51 +0000)
NEWS
src/ChangeLog
src/gpgme.h.in
src/key.c
src/keylist.c
tests/ChangeLog
tests/gpg/t-keylist.c

diff --git a/NEWS b/NEWS
index 551f117d1027d9506c2d0978a55e6137ed876c3a..c2b812a739b190585a958fbeecfd908cd2b4938d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,7 @@ Noteworthy changes in version 1.1.9
  gpgme_op_assuan_transact_start NEW.
  gpgme_op_assuan_transact       NEW.
  gpgme_op_assuan_result         NEW.
+ gpgme_subkey_t                 EXTENDED: New fields is_cardkey, card_number.
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 
index bf272bcaa6b73b3b12c263b17a9907a02f110809..f98e1a3cdb5ace9f0f1e1496fc41a4ab49f0bb5a 100644 (file)
@@ -1,3 +1,11 @@
+2009-02-03  Werner Koch  <wk@g10code.com>
+
+       * gpgme.h.in (struct _gpgme_subkey): Add fields IS_CARDKEY and
+       CARD_NUMBER..
+       * key.c (gpgme_key_unref): Release field CARD_NUMBER.
+       * keylist.c (keylist_colon_handler): Factor common code out to ...
+       (parse_sec_field15): New.  Set card number.
+
 2009-01-26  Werner Koch  <wk@g10code.com>
 
        * opassuan.c, dirinfo.c, engine-assuan.c: New.
index 4b68d801b59d851516fd5563f98ce244f18b56f6..e83b1fb14a0b312504aac86d89d5931273297e3e 100644 (file)
@@ -519,8 +519,11 @@ struct _gpgme_subkey
   /* True if subkey is qualified for signatures according to German law.  */
   unsigned int is_qualified : 1;
 
+  /* True if the secret key is stored on a smart card.  */
+  unsigned int is_cardkey : 1;
+
   /* Internal to GPGME, do not use.  */
-  unsigned int _unused : 22;
+  unsigned int _unused : 21;
   
   /* Public key algorithm supported by this subkey.  */
   gpgme_pubkey_algo_t pubkey_algo;
@@ -542,6 +545,9 @@ struct _gpgme_subkey
 
   /* The expiration timestamp, 0 if the subkey does not expire.  */
   long int expires;
+
+  /* The serial number of a smart card holding this key or NULL.  */
+  char *card_number;
 };
 typedef struct _gpgme_subkey *gpgme_subkey_t;
 
index c9f48f87c9cbddcc3dba005ec0034d8ba4a745de..468946fe83ed8e8cdab2d31fe39af019befe0497 100644 (file)
--- a/src/key.c
+++ b/src/key.c
@@ -327,6 +327,8 @@ gpgme_key_unref (gpgme_key_t key)
       gpgme_subkey_t next = subkey->next;
       if (subkey->fpr)
        free (subkey->fpr);
+      if (subkey->card_number)
+       free (subkey->card_number);
       free (subkey);
       subkey = next;
     }
index 69b0dc9e73679d7332ecdcf4e86448ebbaddbabc..2ee34b8196095d5df3ae9be91172c79f62385212 100644 (file)
@@ -1,7 +1,7 @@
 /* keylist.c - Listing keys.
    Copyright (C) 2000 Werner Koch (dd9jn)
    Copyright (C) 2001, 2002, 2003, 2004, 2006, 2007,
-                 2008  g10 Code GmbH
+                 2008, 2009  g10 Code GmbH
 
    This file is part of GPGME.
  
@@ -351,6 +351,38 @@ set_ownertrust (gpgme_key_t key, const char *src)
 }
 
 
+/* Parse field 15 of a secret key or subkey.  This fields holds a
+   reference to smartcards.  FIELD is the content of the field and we
+   are allowed to modify it.  */
+static gpg_error_t
+parse_sec_field15 (gpgme_subkey_t subkey, char *field)
+{
+  if (!*field)
+    ; /* Empty.  */
+  else if (*field == '#')
+    {
+      /* This is a stub for an offline key.  We reset the SECRET flag
+         of the subkey here.  Note that the secret flag of the entire
+         key will be true even then.  */
+      subkey->secret = 0;
+    }
+  else if (strchr ("01234567890ABCDEFabcdef", *field))
+    {
+      /* Fields starts with a hex digit; thus it is a serial number.  */
+      subkey->is_cardkey = 1;
+      subkey->card_number = strdup (field);
+      if (!subkey->card_number)
+        return gpg_error_from_syserror ();
+    }
+  else
+    {
+      /* RFU.  */
+    }
+
+  return 0;
+}
+
+
 /* We have read an entire key into tmp_key and should now finish it.
    It is assumed that this releases tmp_key.  */
 static void
@@ -533,12 +565,13 @@ keylist_colon_handler (void *priv, char *line)
       if (fields >= 12)
        set_mainkey_capability (key, field[11]);
 
-      /* Field 15 carries special flags of a secret key.  We reset the
-         SECRET flag of a subkey here if the key is actually only a
-         stub. The SECRET flag of the key will be true even then. */
+      /* Field 15 carries special flags of a secret key.  */
       if (fields >= 15 && key->secret)
-        if (*field[14] == '#')
-          subkey->secret = 0;
+        {
+          err = parse_sec_field15 (subkey, field[14]);
+          if (err)
+            return err;
+        }
       break;
 
     case RT_SUB:
@@ -596,8 +629,11 @@ keylist_colon_handler (void *priv, char *line)
 
       /* Field 15 carries special flags of a secret key. */
       if (fields >= 15 && key->secret)
-        if (*field[14] == '#')
-          subkey->secret = 0;
+        {
+          err = parse_sec_field15 (subkey, field[14]);
+          if (err)
+            return err;
+        }
       break;
 
     case RT_UID:
index 1248a8f2f8f368daf86a4255f393a00513188d6a..efd756c456ecc26d56f51dd12e67c8c96c6a95fe 100644 (file)
@@ -1,3 +1,8 @@
+2009-02-03  Werner Koch  <wk@g10code.com>
+
+       * gpg/t-keylist.c (main): Check that new fields is_cardkey and
+       card_number are not set.
+
 2009-01-26  Werner Koch  <wk@g10code.com>
 
        * opassuan/: New.
index c8c71d0c8ae7142b7a984d09b63abebbd1d9311d..e536b47a64fa14d58e411a0d31a24044c7bc55f4 100644 (file)
@@ -270,6 +270,16 @@ main (int argc, char **argv)
          fprintf (stderr, "Primary key unexpectedly secret\n");
          exit (1);
        }
+      if (key->subkeys->is_cardkey)
+       {
+         fprintf (stderr, "Public key marked as card key\n");
+         exit (1);
+       }
+      if (key->subkeys->card_number)
+       {
+         fprintf (stderr, "Public key with card number set\n");
+         exit (1);
+       }
       if (key->subkeys->pubkey_algo != GPGME_PK_DSA)
        {
          fprintf (stderr, "Primary key has unexpected public key algo: %s\n",
@@ -342,6 +352,16 @@ main (int argc, char **argv)
          fprintf (stderr, "Secondary key unexpectedly secret\n");
          exit (1);
        }
+      if (key->subkeys->next->is_cardkey)
+       {
+         fprintf (stderr, "Secondary public key marked as card key\n");
+         exit (1);
+       }
+      if (key->subkeys->next->card_number)
+       {
+         fprintf (stderr, "Secondary public key with card number set\n");
+         exit (1);
+       }
       if (key->subkeys->next->pubkey_algo != GPGME_PK_ELG_E)
        {
          fprintf (stderr, "Secondary key has unexpected public key algo: %s\n",