More stuff for the audit-log.
authorWerner Koch <wk@gnupg.org>
Wed, 2 Dec 2009 18:33:59 +0000 (18:33 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 2 Dec 2009 18:33:59 +0000 (18:33 +0000)
NEWS
common/ChangeLog
common/audit.c
common/audit.h
g10/ChangeLog
g10/keyedit.c
sm/ChangeLog
sm/decrypt.c
sm/gpgsm.c
sm/sign.c
sm/verify.c

diff --git a/NEWS b/NEWS
index d9b0207..8001381 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,11 @@ Noteworthy changes in version 2.1 (under development)
  * Encrypted OpenPGP messages with trailing data (e.g. other OpenPGP
    packets) are now correctly parsed.
 
  * Encrypted OpenPGP messages with trailing data (e.g. other OpenPGP
    packets) are now correctly parsed.
 
+ * The GPGSM --audit-log feature is now more complete.
+
+ * The G13 tool for disk encryption key management has been added.
+
+
 
 Noteworthy changes in version 2.0.13 (2009-09-04)
 -------------------------------------------------
 
 Noteworthy changes in version 2.0.13 (2009-09-04)
 -------------------------------------------------
index a519f38..6015768 100644 (file)
@@ -1,3 +1,11 @@
+2009-12-02  Werner Koch  <wk@g10code.com>
+
+       * audit.c (proc_type_decrypt, proc_type_sign): Implemented.
+       (proc_type_verify): Print hash algo infos.
+       * audit.h (AUDIT_DATA_CIPHER_ALGO, AUDIT_BAD_DATA_CIPHER_ALSO)
+       (AUDIT_NEW_RECP, AUDIT_DECRYPTION_RESULT, AUDIT_RECP_RESULT)
+       (AUDIT_ATTR_HASH_ALGO, AUDIT_SIGNED_BY, AUDIT_SIGNING_DONE):
+
 2009-11-05  Marcus Brinkmann  <marcus@g10code.de>
 
        * asshelp.c (start_new_gpg_agent): Update use of
 2009-11-05  Marcus Brinkmann  <marcus@g10code.de>
 
        * asshelp.c (start_new_gpg_agent): Update use of
index 436f0d2..02a0a2b 100644 (file)
@@ -1,5 +1,5 @@
 /* audit.c - GnuPG's audit subsystem
 /* audit.c - GnuPG's audit subsystem
- *     Copyright (C) 2007 Free Software Foundation, Inc.
+ *     Copyright (C) 2007, 2009 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
  *
  * This file is part of GnuPG.
  *
@@ -42,7 +42,7 @@ struct log_item_s
 {
   audit_event_t event; /* The event.  */
   gpg_error_t err;     /* The logged error code.  */
 {
   audit_event_t event; /* The event.  */
   gpg_error_t err;     /* The logged error code.  */
-  int intvalue;        /* A logged interger value.  */
+  int intvalue;        /* A logged integer value.  */
   char *string;        /* A malloced string or NULL.  */
   ksba_cert_t cert;    /* A certifciate or NULL. */
   int have_err:1;
   char *string;        /* A malloced string or NULL.  */
   ksba_cert_t cert;    /* A certifciate or NULL. */
   int have_err:1;
@@ -483,6 +483,14 @@ writeout_li (audit_ctx_t ctx, const char *oktext, const char *format, ...)
         oktext = _("|audit-log-result|Not enabled");
       else if (!strcmp (oktext, "error"))
         oktext = _("|audit-log-result|Error");
         oktext = _("|audit-log-result|Not enabled");
       else if (!strcmp (oktext, "error"))
         oktext = _("|audit-log-result|Error");
+      else if (!strcmp (oktext, "not-used"))
+        oktext = _("|audit-log-result|Not used");
+      else if (!strcmp (oktext, "okay"))
+        oktext = _("|audit-log-result|Okay");
+      else if (!strcmp (oktext, "skipped"))
+        oktext = _("|audit-log-result|Skipped");
+      else if (!strcmp (oktext, "some"))
+        oktext = _("|audit-log-result|Some");
       else
         s = "";
 
       else
         s = "";
 
@@ -806,16 +814,72 @@ proc_type_encrypt (audit_ctx_t ctx)
 static void
 proc_type_sign (audit_ctx_t ctx)
 {
 static void
 proc_type_sign (audit_ctx_t ctx)
 {
-  log_item_t item;
+  log_item_t item, loopitem;
+  int signer, idx;
+  const char *result;
+  ksba_cert_t cert;
+  char *name;
+  int lastalgo;
 
 
-  item = NULL;
+  item = find_log_item (ctx, AUDIT_SIGNING_DONE, 0);
   writeout_li (ctx, item?"Yes":"No", "%s", _("Data signing succeeded"));
 
   enter_li (ctx);
 
   item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
   writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
   writeout_li (ctx, item?"Yes":"No", "%s", _("Data signing succeeded"));
 
   enter_li (ctx);
 
   item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
   writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
+  /* Write remarks with the data hash algorithms.  We use a very
+     simple scheme to avoid some duplicates.  */
+  loopitem = NULL; 
+  lastalgo = 0;
+  while ((loopitem = find_next_log_item
+          (ctx, loopitem, AUDIT_DATA_HASH_ALGO, AUDIT_NEW_SIG)))
+    {
+      if (loopitem->intvalue && loopitem->intvalue != lastalgo)
+        writeout_rem (ctx, _("data hash algorithm: %s"),
+                      gcry_md_algo_name (loopitem->intvalue));
+      lastalgo = loopitem->intvalue;
+    }
 
 
+  /* Loop over all signer.  */
+  loopitem = NULL;
+  signer = 0;
+  while ((loopitem=find_next_log_item (ctx, loopitem, AUDIT_NEW_SIG, 0)))
+    {
+      signer++;
+
+      item = find_next_log_item (ctx, loopitem, AUDIT_SIGNED_BY, AUDIT_NEW_SIG);
+      if (!item)
+        result = "error";
+      else if (!item->err)
+        result = "okay";
+      else if (gpg_err_code (item->err) == GPG_ERR_CANCELED)
+        result = "skipped";
+      else
+        result = gpg_strerror (item->err);
+      cert = item? item->cert : NULL;
+
+      writeout_li (ctx, result, _("Signer %d"), signer);
+      item = find_next_log_item (ctx, loopitem,
+                                 AUDIT_ATTR_HASH_ALGO, AUDIT_NEW_SIG);
+      if (item)
+        writeout_rem (ctx, _("attr hash algorithm: %s"),
+                      gcry_md_algo_name (item->intvalue));
+
+      if (cert)
+        {
+          name = get_cert_name (cert);
+          writeout_rem (ctx, "%s", name);
+          xfree (name);
+          enter_li (ctx);
+          for (idx=0; (name = get_cert_subject (cert, idx)); idx++)
+            {
+              writeout_rem (ctx, "%s", name);
+              xfree (name);
+            }
+          leave_li (ctx);
+        }
+    }
 
   leave_li (ctx);
 }
 
   leave_li (ctx);
 }
@@ -826,16 +890,87 @@ proc_type_sign (audit_ctx_t ctx)
 static void
 proc_type_decrypt (audit_ctx_t ctx)
 {
 static void
 proc_type_decrypt (audit_ctx_t ctx)
 {
-  log_item_t item;
+  log_item_t loopitem, item;
+  int algo, recpno;
+  char *name;
+  char numbuf[35];
+  int idx;
 
 
-  item = NULL;
-  writeout_li (ctx, item?"Yes":"No", "%s", _("Data decryption succeeded"));
+  item = find_log_item (ctx, AUDIT_DECRYPTION_RESULT, 0);
+  writeout_li (ctx, item && !item->err?"Yes":"No",
+               "%s", _("Data decryption succeeded"));
 
   enter_li (ctx);
 
   item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
   writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
 
 
   enter_li (ctx);
 
   item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
   writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
 
+  item = find_log_item (ctx, AUDIT_DATA_CIPHER_ALGO, 0);
+  algo = item? item->intvalue : 0;
+  writeout_li (ctx, algo?"Yes":"No", "%s", _("Encryption algorithm supported"));
+  if (algo)
+    writeout_rem (ctx, _("algorithm: %s"), gcry_cipher_algo_name (algo));
+
+  item = find_log_item (ctx, AUDIT_BAD_DATA_CIPHER_ALGO, 0);
+  if (item && item->string)
+    {
+      algo = gcry_cipher_map_name (item->string);
+      if (algo)
+        writeout_rem (ctx, _("algorithm: %s"), gcry_cipher_algo_name (algo));
+      else if (item->string && !strcmp (item->string, "1.2.840.113549.3.2"))
+        writeout_rem (ctx, _("unsupported algorithm: %s"), "RC2");
+      else if (item->string)
+        writeout_rem (ctx, _("unsupported algorithm: %s"), item->string);
+      else
+        writeout_rem (ctx, _("seems to be not encrypted"));
+    }
+
+
+  for (recpno = 0, item = NULL;
+       (item = find_next_log_item (ctx, item, AUDIT_NEW_RECP, 0)); recpno++)
+    ;
+  snprintf (numbuf, sizeof numbuf, "%d", recpno);
+  writeout_li (ctx, numbuf, "%s", _("Number of recipients"));
+
+  /* Loop over all recipients.  */
+  loopitem = NULL;
+  while ((loopitem = find_next_log_item (ctx, loopitem, AUDIT_NEW_RECP, 0)))
+    {
+      const char *result;
+
+      recpno = loopitem->have_intvalue? loopitem->intvalue : -1;
+
+      item = find_next_log_item (ctx, loopitem,
+                                 AUDIT_RECP_RESULT, AUDIT_NEW_RECP);
+      if (!item)
+        result = "not-used";
+      else if (!item->err)
+        result = "okay";
+      else if (gpg_err_code (item->err) == GPG_ERR_CANCELED)
+        result = "skipped";
+      else
+        result = gpg_strerror (item->err);
+
+      item = find_next_log_item (ctx, loopitem,
+                                 AUDIT_RECP_NAME, AUDIT_NEW_RECP);
+      writeout_li (ctx, result, _("Recipient %d"), recpno);
+      if (item && item->string)
+        writeout_rem (ctx, "%s", item->string);
+
+      /* If we have a certificate write out more infos.  */
+      item = find_next_log_item (ctx, loopitem,
+                                 AUDIT_SAVE_CERT, AUDIT_NEW_RECP);
+      if (item && item->cert)
+        {
+          enter_li (ctx);
+          for (idx=0; (name = get_cert_subject (item->cert, idx)); idx++)
+            {
+              writeout_rem (ctx, "%s", name);
+              xfree (name);
+            }
+          leave_li (ctx);
+        }
+    }
 
   leave_li (ctx);
 }
 
   leave_li (ctx);
 }
@@ -847,11 +982,12 @@ static void
 proc_type_verify (audit_ctx_t ctx)
 {
   log_item_t loopitem, item;
 proc_type_verify (audit_ctx_t ctx)
 {
   log_item_t loopitem, item;
-  int signo, count, idx;
+  int signo, count, idx, n_good, n_bad;
   char numbuf[35];
   char numbuf[35];
+  const char *result;
 
   /* If there is at least one signature status we claim that the
 
   /* If there is at least one signature status we claim that the
-     verifciation succeeded.  This does not mean that the data has
+     verification succeeded.  This does not mean that the data has
      verified okay.  */
   item = find_log_item (ctx, AUDIT_SIG_STATUS, 0);
   writeout_li (ctx, item?"Yes":"No", "%s", _("Data verification succeeded"));
      verified okay.  */
   item = find_log_item (ctx, AUDIT_SIG_STATUS, 0);
   writeout_li (ctx, item?"Yes":"No", "%s", _("Data verification succeeded"));
@@ -867,17 +1003,41 @@ proc_type_verify (audit_ctx_t ctx)
   if (!item)
     goto leave;
 
   if (!item)
     goto leave;
 
-  item = find_log_item (ctx, AUDIT_DATA_HASH_ALGO, AUDIT_NEW_SIG);
-  writeout_li (ctx, item?"Yes":"No", "%s", _("Parsing signature succeeded"));
-  if (!item)
+  /* Print info about the used data hashing algorithms.  */
+  for (idx=0, n_good=n_bad=0; idx < ctx->logused; idx++)
     {
     {
-      item = find_log_item (ctx, AUDIT_BAD_DATA_HASH_ALGO, AUDIT_NEW_SIG);
-      if (item)
-        writeout_rem (ctx, _("Bad hash algorithm: %s"), 
-                      item->string? item->string:"?");
-
-      goto leave;
+      item = ctx->log + idx;
+      if (item->event == AUDIT_NEW_SIG)
+        break;
+      else if (item->event == AUDIT_DATA_HASH_ALGO)
+        n_good++;
+      else if (item->event == AUDIT_BAD_DATA_HASH_ALGO)
+        n_bad++;
     }
     }
+  item = find_log_item (ctx, AUDIT_DATA_HASHING, AUDIT_NEW_SIG);
+  if (!item || item->err || !n_good)
+    result = "No";
+  else if (n_good && !n_bad)
+    result = "Yes";
+  else
+    result = "Some";
+  writeout_li (ctx, result, "%s", _("Parsing data succeeded"));
+  if (n_good || n_bad)
+    {
+      for (idx=0; idx < ctx->logused; idx++)
+        {
+          item = ctx->log + idx;
+          if (item->event == AUDIT_NEW_SIG)
+            break;
+          else if (item->event == AUDIT_DATA_HASH_ALGO)
+            writeout_rem (ctx, _("data hash algorithm: %s"),
+                          gcry_md_algo_name (item->intvalue));
+          else if (item->event == AUDIT_BAD_DATA_HASH_ALGO)
+            writeout_rem (ctx, _("bad data hash algorithm: %s"), 
+                          item->string? item->string:"?");
+        }
+    }
+
 
   /* Loop over all signatures.  */
   loopitem = find_log_item (ctx, AUDIT_NEW_SIG, 0);
 
   /* Loop over all signatures.  */
   loopitem = find_log_item (ctx, AUDIT_NEW_SIG, 0);
@@ -893,6 +1053,18 @@ proc_type_verify (audit_ctx_t ctx)
                                  AUDIT_SIG_NAME, AUDIT_NEW_SIG);
       if (item)
         writeout_rem (ctx, "%s", item->string);
                                  AUDIT_SIG_NAME, AUDIT_NEW_SIG);
       if (item)
         writeout_rem (ctx, "%s", item->string);
+
+      item = find_next_log_item (ctx, loopitem,
+                                 AUDIT_DATA_HASH_ALGO, AUDIT_NEW_SIG);
+      if (item)
+        writeout_rem (ctx, _("data hash algorithm: %s"),
+                      gcry_md_algo_name (item->intvalue));
+      item = find_next_log_item (ctx, loopitem,
+                                 AUDIT_ATTR_HASH_ALGO, AUDIT_NEW_SIG);
+      if (item)
+        writeout_rem (ctx, _("attr hash algorithm: %s"),
+                      gcry_md_algo_name (item->intvalue));
+
       enter_li (ctx);
       
       /* List the certificate chain.  */
       enter_li (ctx);
       
       /* List the certificate chain.  */
@@ -1006,11 +1178,7 @@ audit_print_result (audit_ctx_t ctx, estream_t out, int use_html)
   /* We use an environment variable to include some debug info in the
      log.  */
   if ((s = getenv ("gnupg_debug_audit")))
   /* We use an environment variable to include some debug info in the
      log.  */
   if ((s = getenv ("gnupg_debug_audit")))
-    {
-      show_raw = 1;
-      if (!strcmp (s, "html"))
-        use_html = 1;
-    }
+    show_raw = 1;
 
   assert (!ctx->outstream);
   ctx->outstream = out;
 
   assert (!ctx->outstream);
   ctx->outstream = out;
index 5f5aff4..28d1edb 100644 (file)
@@ -81,15 +81,27 @@ typedef enum
     /* A certifciate only signature has been detected.  */
 
     AUDIT_DATA_HASH_ALGO,  /* int */
     /* A certifciate only signature has been detected.  */
 
     AUDIT_DATA_HASH_ALGO,  /* int */
-    /* The hash algo given as argument is used for this signature.
-       This event will be repeated for all hash algorithms used with
-       the data.  */
+    /* The hash algo given as argument is used for the data.  This
+       event will be repeated for all hash algorithms used with the
+       data.  */
+
+    AUDIT_ATTR_HASH_ALGO,  /* int */
+    /* The hash algo given as argument is used to hash the message
+       digest and other signed attributes of this signature. */
+
+    AUDIT_DATA_CIPHER_ALGO,  /* int */
+    /* The cipher algo given as argument is used for this data.  */
 
     AUDIT_BAD_DATA_HASH_ALGO,  /* string */
     /* The hash algo as specified by the signature can't be used.
        STRING is the description of this algorithm which usually is an
        OID string.  STRING may be NULL. */
 
 
     AUDIT_BAD_DATA_HASH_ALGO,  /* string */
     /* The hash algo as specified by the signature can't be used.
        STRING is the description of this algorithm which usually is an
        OID string.  STRING may be NULL. */
 
+    AUDIT_BAD_DATA_CIPHER_ALGO,  /* string */
+    /* The symmetric cipher algorithm is not supported.  STRING is the
+       description of this algorithm which usually is an OID string.
+       STRING may be NULL. */
+
     AUDIT_DATA_HASHING,    /* ok_err */
     /* Logs the result of the data hashing. */
 
     AUDIT_DATA_HASHING,    /* ok_err */
     /* Logs the result of the data hashing. */
 
@@ -118,7 +130,7 @@ typedef enum
        certificate used for verification.  An example for STRING when
        using CMS is: "#1234/CN=Prostetnic Vogon Jeltz".  */
 
        certificate used for verification.  An example for STRING when
        using CMS is: "#1234/CN=Prostetnic Vogon Jeltz".  */
 
-    AUDIT_SIG_STATUS,     /* string */
+    AUDIT_SIG_STATUS,      /* string */
     /* The signature status of the current signer.  This is the last
        audit information for one signature.  STRING gives the status:
 
     /* The signature status of the current signer.  This is the last
        audit information for one signature.  STRING gives the status:
 
@@ -130,6 +142,24 @@ typedef enum
          "good"        - good signature
     */
 
          "good"        - good signature
     */
 
+    AUDIT_NEW_RECP,        /* int */
+    /* A new recipient has been seen during decryption.  The argument
+       is the recipient number as used internally by the program.  */
+    
+    AUDIT_RECP_NAME,       /* string */
+    /* The name of a recipient.  This is the name or other identification
+       data as known from the decryption and not the name from the
+       certificate used for decryption.  An example for STRING when
+       using CMS is: "#1234/CN=Prostetnic Vogon Jeltz".  */
+
+    AUDIT_RECP_RESULT,    /* ok_err */
+    /* The status of the session key decryption.  This is only written
+       for recipients tried. */
+
+    AUDIT_DECRYPTION_RESULT,    /* ok_err */
+    /* The status of the entire decryption.  The decryption was
+       successful if the error code is 0. */
+
     AUDIT_VALIDATE_CHAIN,
     /* Start the validation of a certificate chain. */
 
     AUDIT_VALIDATE_CHAIN,
     /* Start the validation of a certificate chain. */
 
@@ -167,7 +197,12 @@ typedef enum
     AUDIT_ENCRYPTION_DONE,
     /* Encryption succeeded.  */
 
     AUDIT_ENCRYPTION_DONE,
     /* Encryption succeeded.  */
 
-    
+    AUDIT_SIGNED_BY,   /* cert, err */
+    /* Records the certificate used for signed and whether the signure
+       could be created (if err==0).  */
+
+    AUDIT_SIGNING_DONE,
+    /* Signing succeeded.  */
 
 
     AUDIT_LAST_EVENT  /* Marker for parsing this list.  */
 
 
     AUDIT_LAST_EVENT  /* Marker for parsing this list.  */
index c8978f6..67a2eea 100644 (file)
@@ -1,3 +1,7 @@
+2009-11-27  Werner Koch  <wk@g10code.com>
+
+       * keyedit.c (cmds, keyedit_menu): New command "checkbkupkey".
+
 2009-11-25  Marcus Brinkmann  <marcus@g10code.de>
 
        * server.c (gpg_server): Use assuan_fd_t and assuan_fdopen on fds.
 2009-11-25  Marcus Brinkmann  <marcus@g10code.de>
 
        * server.c (gpg_server): Use assuan_fd_t and assuan_fdopen on fds.
index bc79e8f..847e187 100644 (file)
@@ -1143,11 +1143,11 @@ change_passphrase( KBNODE keyblock )
        break;
       default:
        if( sk->protect.s2k.mode == 1001 ) {
        break;
       default:
        if( sk->protect.s2k.mode == 1001 ) {
-           tty_printf(_("Secret parts of primary key are not available.\n"));
+           tty_printf(_("Secret parts of key are not available.\n"));
            no_primary_secrets = 1;
        }
        else if( sk->protect.s2k.mode == 1002 ) {
            no_primary_secrets = 1;
        }
        else if( sk->protect.s2k.mode == 1002 ) {
-           tty_printf(_("Secret parts of primary key are stored on-card.\n"));
+           tty_printf(_("Secret parts of key are stored on-card.\n"));
            no_primary_secrets = 1;
        }
        else {
            no_primary_secrets = 1;
        }
        else {
@@ -1365,8 +1365,8 @@ enum cmdids
     cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
     cmdEXPIRE, cmdBACKSIGN, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF,
     cmdSETPREF, cmdPREFKS, cmdNOTATION, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST,
     cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
     cmdEXPIRE, cmdBACKSIGN, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF,
     cmdSETPREF, cmdPREFKS, cmdNOTATION, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST,
-    cmdCHKTRUST, cmdADDCARDKEY, cmdKEYTOCARD, cmdBKUPTOCARD, cmdCLEAN,
-    cmdMINIMIZE, cmdNOP
+    cmdCHKTRUST, cmdADDCARDKEY, cmdKEYTOCARD, cmdBKUPTOCARD, cmdCHECKBKUPKEY,
+    cmdCLEAN, cmdMINIMIZE, cmdNOP
   };
 
 static struct
   };
 
 static struct
@@ -1423,6 +1423,8 @@ static struct
       N_("move a key to a smartcard")},
     { "bkuptocard", cmdBKUPTOCARD , KEYEDIT_NEED_SK|KEYEDIT_ONLY_SK, 
       N_("move a backup key to a smartcard")},
       N_("move a key to a smartcard")},
     { "bkuptocard", cmdBKUPTOCARD , KEYEDIT_NEED_SK|KEYEDIT_ONLY_SK, 
       N_("move a backup key to a smartcard")},
+    { "checkbkupkey", cmdCHECKBKUPKEY, KEYEDIT_NEED_SK|KEYEDIT_ONLY_SK, 
+      NULL},
 #endif /*ENABLE_CARD_SUPPORT*/
 
     { "delkey"  , cmdDELKEY    , KEYEDIT_NOT_SK,
 #endif /*ENABLE_CARD_SUPPORT*/
 
     { "delkey"  , cmdDELKEY    , KEYEDIT_NOT_SK,
@@ -1940,6 +1942,7 @@ keyedit_menu( const char *username, strlist_t locusr,
           break;
 
         case cmdBKUPTOCARD:
           break;
 
         case cmdBKUPTOCARD:
+        case cmdCHECKBKUPKEY:
          {
             /* Ask for a filename, check whether this is really a
                backup key as generated by the card generation, parse
          {
             /* Ask for a filename, check whether this is really a
                backup key as generated by the card generation, parse
@@ -1991,11 +1994,35 @@ keyedit_menu( const char *username, strlist_t locusr,
               }
             node = new_kbnode (pkt);
 
               }
             node = new_kbnode (pkt);
 
-            /* Store it.  */
-            if (card_store_subkey (node, 0))
+            if (cmd == cmdCHECKBKUPKEY)
               {
               {
-                redisplay = 1;
-                sec_modified = 1;
+                PKT_secret_key *sk = node->pkt->pkt.secret_key;
+                switch (is_secret_key_protected (sk) )
+                  {
+                  case 0: /* Not protected. */
+                    tty_printf (_("This key is not protected.\n"));
+                    break;
+                  case -1:
+                    log_error (_("unknown key protection algorithm\n"));
+                    break;
+                  default:
+                    if (sk->protect.s2k.mode == 1001)
+                      tty_printf (_("Secret parts of key"
+                                    " are not available.\n"));
+                    if (sk->protect.s2k.mode == 1002)
+                      tty_printf (_("Secret parts of key"
+                                    " are stored on-card.\n"));
+                    else
+                      check_secret_key (sk, 0);
+                  }
+              }
+            else /* Store it.  */
+              {
+                if (card_store_subkey (node, 0))
+                  {
+                    redisplay = 1;
+                    sec_modified = 1;
+                  }
               }
             release_kbnode (node);
          }
               }
             release_kbnode (node);
          }
index 80235db..1673163 100644 (file)
@@ -1,3 +1,16 @@
+2009-12-02  Werner Koch  <wk@g10code.com>
+
+       * verify.c (gpgsm_verify): Add audit info on hash algorithms.
+
+       * sign.c (gpgsm_sign): Add audit log calls.
+       (hash_data): Return an error indicator.
+
+2009-12-01  Werner Koch  <wk@g10code.com>
+
+       * decrypt.c (gpgsm_decrypt): Add audit log calls.
+
+       * gpgsm.c: New option --html-audit-log.
+
 2009-11-25  Marcus Brinkmann  <marcus@g10code.de>
 
        * server.c (gpgsm_server): Use assuan_fd_t and assuan_fdopen on
 2009-11-25  Marcus Brinkmann  <marcus@g10code.de>
 
        * server.c (gpgsm_server): Use assuan_fd_t and assuan_fdopen on
index 8fb9f2d..de02551 100644 (file)
@@ -253,6 +253,8 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
 
   memset (&dfparm, 0, sizeof dfparm);
 
 
   memset (&dfparm, 0, sizeof dfparm);
 
+  audit_set_type (ctrl->audit, AUDIT_TYPE_DECRYPT);
+
   kh = keydb_new (0);
   if (!kh)
     {
   kh = keydb_new (0);
   if (!kh)
     {
@@ -296,6 +298,8 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
       goto leave;
     }
 
       goto leave;
     }
 
+  audit_log (ctrl->audit, AUDIT_SETUP_READY);
+
   /* Parser loop. */
   do 
     {
   /* Parser loop. */
   do 
     {
@@ -313,6 +317,8 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
           const char *algoid;
           int any_key = 0;
           
           const char *algoid;
           int any_key = 0;
           
+          audit_log (ctrl->audit, AUDIT_GOT_DATA);
+
           algoid = ksba_cms_get_content_oid (cms, 2/* encryption algo*/);
           algo = gcry_cipher_map_name (algoid);
           mode = gcry_cipher_mode_from_oid (algoid);
           algoid = ksba_cms_get_content_oid (cms, 2/* encryption algo*/);
           algo = gcry_cipher_map_name (algoid);
           mode = gcry_cipher_mode_from_oid (algoid);
@@ -330,6 +336,7 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
                 sprintf (numbuf, "%d", rc);
                 gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.algorithm",
                                numbuf, algoid?algoid:"?", NULL);
                 sprintf (numbuf, "%d", rc);
                 gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.algorithm",
                                numbuf, algoid?algoid:"?", NULL);
+                audit_log_s (ctrl->audit, AUDIT_BAD_DATA_CIPHER_ALGO, algoid);
               }
 
               /* If it seems that this is not an encrypted message we
               }
 
               /* If it seems that this is not an encrypted message we
@@ -339,6 +346,8 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
 
               goto leave;
             }
 
               goto leave;
             }
+
+          audit_log_i (ctrl->audit, AUDIT_DATA_CIPHER_ALGO, algo);
           dfparm.algo = algo;
           dfparm.mode = mode;
           dfparm.blklen = gcry_cipher_get_algo_blklen (algo);
           dfparm.algo = algo;
           dfparm.mode = mode;
           dfparm.blklen = gcry_cipher_get_algo_blklen (algo);
@@ -369,6 +378,7 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
               rc = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial);
               if (rc == -1 && recp)
                 break; /* no more recipients */
               rc = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial);
               if (rc == -1 && recp)
                 break; /* no more recipients */
+              audit_log_i (ctrl->audit, AUDIT_NEW_RECP, recp);
               if (rc)
                 log_error ("recp %d - error getting info: %s\n",
                            recp, gpg_strerror (rc));
               if (rc)
                 log_error ("recp %d - error getting info: %s\n",
                            recp, gpg_strerror (rc));
@@ -382,6 +392,13 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
                   gpgsm_dump_serial (serial);
                   log_printf ("\n");
 
                   gpgsm_dump_serial (serial);
                   log_printf ("\n");
 
+                  if (ctrl->audit)
+                    {
+                      char *tmpstr = gpgsm_format_sn_issuer (serial, issuer);
+                      audit_log_s (ctrl->audit, AUDIT_RECP_NAME, tmpstr);
+                      xfree (tmpstr);
+                    }
+
                   keydb_search_reset (kh);
                   rc = keydb_search_issuer_sn (kh, issuer, serial);
                   if (rc)
                   keydb_search_reset (kh);
                   rc = keydb_search_issuer_sn (kh, issuer, serial);
                   if (rc)
@@ -415,6 +432,8 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
                                    kidbuf, "0", "0", NULL);
                   }
 
                                    kidbuf, "0", "0", NULL);
                   }
 
+                  /* Put the certificate into the audit log.  */
+                  audit_log_cert (ctrl->audit, AUDIT_SAVE_CERT, cert, 0);
 
                   /* Just in case there is a problem with the own
                      certificate we print this message - should never
 
                   /* Just in case there is a problem with the own
                      certificate we print this message - should never
@@ -462,10 +481,41 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
                                               decrypt_filter,
                                               &dfparm);
                     }
                                               decrypt_filter,
                                               &dfparm);
                     }
+                  audit_log_ok (ctrl->audit, AUDIT_RECP_RESULT, rc);
                 }
               xfree (hexkeygrip);
               xfree (desc);
             }
                 }
               xfree (hexkeygrip);
               xfree (desc);
             }
+
+          /* If we write an audit log add the unused recipients to the
+             log as well.  */
+          if (ctrl->audit && any_key)
+            {
+              for (;; recp++)
+                {
+                  char *issuer;
+                  ksba_sexp_t serial;
+                  int tmp_rc;
+
+                  tmp_rc = ksba_cms_get_issuer_serial (cms, recp,
+                                                       &issuer, &serial);
+                  if (tmp_rc == -1)
+                    break; /* no more recipients */
+                  audit_log_i (ctrl->audit, AUDIT_NEW_RECP, recp);
+                  if (tmp_rc)
+                    log_error ("recp %d - error getting info: %s\n",
+                               recp, gpg_strerror (rc));
+                  else
+                    {
+                      char *tmpstr = gpgsm_format_sn_issuer (serial, issuer);
+                      audit_log_s (ctrl->audit, AUDIT_RECP_NAME, tmpstr);
+                      xfree (tmpstr);
+                      xfree (issuer);
+                      xfree (serial);
+                    }
+                }
+            }
+
           if (!any_key)
             {
               rc = gpg_error (GPG_ERR_NO_SECKEY);
           if (!any_key)
             {
               rc = gpg_error (GPG_ERR_NO_SECKEY);
@@ -488,7 +538,7 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
                                       dfparm.lastblock, 
                                       dfparm.blklen - npadding);
               if (rc)
                                       dfparm.lastblock, 
                                       dfparm.blklen - npadding);
               if (rc)
-                  goto leave;
+                goto leave;
 
               for (i=dfparm.blklen - npadding; i < dfparm.blklen; i++)
                 {
 
               for (i=dfparm.blklen - npadding; i < dfparm.blklen; i++)
                 {
@@ -515,6 +565,7 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp)
 
 
  leave:
 
 
  leave:
+  audit_log_ok (ctrl->audit, AUDIT_DECRYPTION_RESULT, rc);
   if (rc)
     {
       gpgsm_status (ctrl, STATUS_DECRYPTION_FAILED, NULL);
   if (rc)
     {
       gpgsm_status (ctrl, STATUS_DECRYPTION_FAILED, NULL);
index 2d262b7..6e7cd84 100644 (file)
@@ -99,6 +99,7 @@ enum cmd_and_opt_values {
   oLogFile,
   oNoLogFile,
   oAuditLog,
   oLogFile,
   oNoLogFile,
   oAuditLog,
+  oHtmlAuditLog,
 
   oEnableSpecialFilenames,
 
 
   oEnableSpecialFilenames,
 
@@ -286,6 +287,7 @@ static ARGPARSE_OPTS opts[] = {
 
   ARGPARSE_s_s (oAuditLog, "audit-log", 
                 N_("|FILE|write an audit log to FILE")),
 
   ARGPARSE_s_s (oAuditLog, "audit-log", 
                 N_("|FILE|write an audit log to FILE")),
+  ARGPARSE_s_s (oHtmlAuditLog, "html-audit-log", ""),
   ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")),
   ARGPARSE_s_n (oBatch, "batch", N_("batch mode: never ask")),
   ARGPARSE_s_n (oAnswerYes, "yes", N_("assume yes on most questions")),
   ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")),
   ARGPARSE_s_n (oBatch, "batch", N_("batch mode: never ask")),
   ARGPARSE_s_n (oAnswerYes, "yes", N_("assume yes on most questions")),
@@ -851,6 +853,7 @@ main ( int argc, char **argv)
   int default_keyring = 1;
   char *logfile = NULL;
   char *auditlog = NULL;
   int default_keyring = 1;
   char *logfile = NULL;
   char *auditlog = NULL;
+  char *htmlauditlog = NULL;
   int greeting = 0;
   int nogreeting = 0;
   int debug_wait = 0;
   int greeting = 0;
   int nogreeting = 0;
   int debug_wait = 0;
@@ -866,6 +869,7 @@ main ( int argc, char **argv)
   int do_not_setup_keys = 0;
   int recp_required = 0;
   estream_t auditfp = NULL;
   int do_not_setup_keys = 0;
   int recp_required = 0;
   estream_t auditfp = NULL;
+  estream_t htmlauditfp = NULL;
   struct assuan_malloc_hooks malloc_hooks;
 
   /*mtrace();*/
   struct assuan_malloc_hooks malloc_hooks;
 
   /*mtrace();*/
@@ -1182,6 +1186,7 @@ main ( int argc, char **argv)
         case oNoLogFile: logfile = NULL; break;          
 
         case oAuditLog: auditlog = pargs.r.ret_str; break;
         case oNoLogFile: logfile = NULL; break;          
 
         case oAuditLog: auditlog = pargs.r.ret_str; break;
+        case oHtmlAuditLog: htmlauditlog = pargs.r.ret_str; break;
 
         case oBatch: 
           opt.batch = 1;
 
         case oBatch: 
           opt.batch = 1;
@@ -1410,11 +1415,6 @@ main ( int argc, char **argv)
     }
 #  endif
 
     }
 #  endif
 
-  if (auditlog)
-    log_info ("NOTE: The audit log feature (--audit-log) is "
-              "WORK IN PRORESS and not ready for use!\n");
-
-
   if (may_coredump && !opt.quiet)
     log_info (_("WARNING: program may create a core file!\n"));
 
   if (may_coredump && !opt.quiet)
     log_info (_("WARNING: program may create a core file!\n"));
 
@@ -1546,7 +1546,7 @@ main ( int argc, char **argv)
 
 
   /* Prepare the audit log feature for certain commands.  */
 
 
   /* Prepare the audit log feature for certain commands.  */
-  if (auditlog)
+  if (auditlog || htmlauditlog)
     {
       switch (cmd)
         {
     {
       switch (cmd)
         {
@@ -1556,7 +1556,10 @@ main ( int argc, char **argv)
         case aVerify:
           audit_release (ctrl.audit);
           ctrl.audit = audit_new ();
         case aVerify:
           audit_release (ctrl.audit);
           ctrl.audit = audit_new ();
-          auditfp = open_es_fwrite (auditlog);
+          if (auditlog)
+            auditfp = open_es_fwrite (auditlog);
+          if (htmlauditlog)
+            htmlauditfp = open_es_fwrite (htmlauditlog);
           break;
         default:
           break;
           break;
         default:
           break;
@@ -1914,12 +1917,16 @@ main ( int argc, char **argv)
     }
 
   /* Print the audit result if needed.  */
     }
 
   /* Print the audit result if needed.  */
-  if (auditlog && auditfp)
+  if ((auditlog && auditfp) || (htmlauditlog && htmlauditfp))
     {
     {
-      audit_print_result (ctrl.audit, auditfp, 0);
+      if (auditlog && auditfp)
+        audit_print_result (ctrl.audit, auditfp, 0);
+      if (htmlauditlog && htmlauditfp)
+        audit_print_result (ctrl.audit, htmlauditfp, 1);
       audit_release (ctrl.audit);
       ctrl.audit = NULL;
       es_fclose (auditfp);
       audit_release (ctrl.audit);
       ctrl.audit = NULL;
       es_fclose (auditfp);
+      es_fclose (htmlauditfp);
     }
   
   /* cleanup */
     }
   
   /* cleanup */
index 776a5a5..fd7c4ff 100644 (file)
--- a/sm/sign.c
+++ b/sm/sign.c
 #include "i18n.h"
 
 
 #include "i18n.h"
 
 
-static void
+/* Hash the data and return if something was hashed.  Return -1 on error.  */
+static int
 hash_data (int fd, gcry_md_hd_t md)
 {
   FILE *fp;
   char buffer[4096];
   int nread;
 hash_data (int fd, gcry_md_hd_t md)
 {
   FILE *fp;
   char buffer[4096];
   int nread;
+  int rc = 0;
 
   fp = fdopen ( dup (fd), "rb");
   if (!fp)
     {
       log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
 
   fp = fdopen ( dup (fd), "rb");
   if (!fp)
     {
       log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
-      return;
+      return -1;
     }
 
   do 
     }
 
   do 
@@ -55,8 +57,12 @@ hash_data (int fd, gcry_md_hd_t md)
     }
   while (nread);
   if (ferror (fp))
     }
   while (nread);
   if (ferror (fp))
+    {
       log_error ("read error on fd %d: %s\n", fd, strerror (errno));
       log_error ("read error on fd %d: %s\n", fd, strerror (errno));
+      rc = -1;
+    }
   fclose (fp);
   fclose (fp);
+  return rc;
 }
 
 static int
 }
 
 static int
@@ -321,6 +327,8 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
   certlist_t cl;
   int release_signerlist = 0;
 
   certlist_t cl;
   int release_signerlist = 0;
 
+  audit_set_type (ctrl->audit, AUDIT_TYPE_SIGN);
+
   kh = keydb_new (0);
   if (!kh)
     {
   kh = keydb_new (0);
   if (!kh)
     {
@@ -539,8 +547,11 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
           goto leave;
         }
       gcry_md_enable (data_md, algo);
           goto leave;
         }
       gcry_md_enable (data_md, algo);
+      audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, algo);
     }
 
     }
 
+  audit_log (ctrl->audit, AUDIT_SETUP_READY);
+
   if (detached)
     { /* We hash the data right now so that we can store the message
          digest.  ksba_cms_build() takes this as an flag that detached
   if (detached)
     { /* We hash the data right now so that we can store the message
          digest.  ksba_cms_build() takes this as an flag that detached
@@ -548,7 +559,8 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
       unsigned char *digest;
       size_t digest_len;
 
       unsigned char *digest;
       size_t digest_len;
 
-      hash_data (data_fd, data_md);
+      if (!hash_data (data_fd, data_md))
+        audit_log (ctrl->audit, AUDIT_GOT_DATA);
       for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
         {
           digest = gcry_md_read (data_md, cl->hash_algo);
       for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
         {
           digest = gcry_md_read (data_md, cl->hash_algo);
@@ -623,6 +635,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
           rc = hash_and_copy_data (data_fd, data_md, writer);
           if (rc)
             goto leave;
           rc = hash_and_copy_data (data_fd, data_md, writer);
           if (rc)
             goto leave;
+          audit_log (ctrl->audit, AUDIT_GOT_DATA);
           for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
             {
               digest = gcry_md_read (data_md, cl->hash_algo);
           for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
             {
               digest = gcry_md_read (data_md, cl->hash_algo);
@@ -663,13 +676,18 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
               unsigned char *sigval = NULL;
               char *buf, *fpr;
 
               unsigned char *sigval = NULL;
               char *buf, *fpr;
 
+              audit_log_i (ctrl->audit, AUDIT_NEW_SIG, signer);
               if (signer)
                 gcry_md_reset (md);
               {
                 certlist_t cl_tmp;
 
                 for (cl_tmp=signerlist; cl_tmp; cl_tmp = cl_tmp->next)
               if (signer)
                 gcry_md_reset (md);
               {
                 certlist_t cl_tmp;
 
                 for (cl_tmp=signerlist; cl_tmp; cl_tmp = cl_tmp->next)
-                  gcry_md_enable (md, cl_tmp->hash_algo);
+                  {
+                    gcry_md_enable (md, cl_tmp->hash_algo);
+                    audit_log_i (ctrl->audit, AUDIT_ATTR_HASH_ALGO, 
+                                 cl_tmp->hash_algo);
+                  }
               }
 
               rc = ksba_cms_hash_signed_attrs (cms, signer);
               }
 
               rc = ksba_cms_hash_signed_attrs (cms, signer);
@@ -685,6 +703,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
                                                md, cl->hash_algo, &sigval);
               if (rc)
                 {
                                                md, cl->hash_algo, &sigval);
               if (rc)
                 {
+                  audit_log_cert (ctrl->audit, AUDIT_SIGNED_BY, cl->cert, rc);
                   gcry_md_close (md);
                   goto leave;
                 }
                   gcry_md_close (md);
                   goto leave;
                 }
@@ -693,6 +712,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
               xfree (sigval);
               if (err)
                 {
               xfree (sigval);
               if (err)
                 {
+                  audit_log_cert (ctrl->audit, AUDIT_SIGNED_BY, cl->cert, err);
                   log_error ("failed to store the signature: %s\n",
                              gpg_strerror (err));
                   rc = err;
                   log_error ("failed to store the signature: %s\n",
                              gpg_strerror (err));
                   rc = err;
@@ -708,28 +728,29 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
                   gcry_md_close (md);
                   goto leave;
                 }
                   gcry_md_close (md);
                   goto leave;
                 }
+              rc = 0;
               {
                 int pkalgo = gpgsm_get_key_algo_info (cl->cert, NULL);
               {
                 int pkalgo = gpgsm_get_key_algo_info (cl->cert, NULL);
-                rc = asprintf (&buf, "%c %d %d 00 %s %s",
-                               detached? 'D':'S',
-                               pkalgo, 
-                               cl->hash_algo, 
-                               signed_at,
-                               fpr);
+                buf = xtryasprintf ("%c %d %d 00 %s %s",
+                                    detached? 'D':'S',
+                                    pkalgo, 
+                                    cl->hash_algo, 
+                                    signed_at,
+                                    fpr);
+                if (!buf)
+                  rc = gpg_error_from_syserror ();
               }
               xfree (fpr);
               }
               xfree (fpr);
-              if (rc < 0)
+              if (rc)
                 {
                 {
-                  rc = gpg_error (GPG_ERR_ENOMEM);
                   gcry_md_close (md);
                   goto leave;
                 }
                   gcry_md_close (md);
                   goto leave;
                 }
-              rc = 0;
               gpgsm_status (ctrl, STATUS_SIG_CREATED, buf);
               gpgsm_status (ctrl, STATUS_SIG_CREATED, buf);
-              free (buf); /* yes, we must use the regular free() here */
+              xfree (buf);
+              audit_log_cert (ctrl->audit, AUDIT_SIGNED_BY, cl->cert, 0);
             }
           gcry_md_close (md);
             }
           gcry_md_close (md);
-
         }
     }
   while (stopreason != KSBA_SR_READY);   
         }
     }
   while (stopreason != KSBA_SR_READY);   
@@ -741,6 +762,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
       goto leave;
     }
 
       goto leave;
     }
 
+  audit_log (ctrl->audit, AUDIT_SIGNING_DONE);
   log_info ("signature created\n");
 
 
   log_info ("signature created\n");
 
 
index 77517c6..c8663e3 100644 (file)
@@ -216,6 +216,8 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp)
                 log_debug ("enabling extra hash algorithm %d\n", 
                            opt.extra_digest_algo);
               gcry_md_enable (data_md, opt.extra_digest_algo);
                 log_debug ("enabling extra hash algorithm %d\n", 
                            opt.extra_digest_algo);
               gcry_md_enable (data_md, opt.extra_digest_algo);
+              audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO,
+                           opt.extra_digest_algo);
             }
           if (is_detached)
             {
             }
           if (is_detached)
             {
@@ -236,7 +238,7 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp)
         }
       else if (stopreason == KSBA_SR_END_DATA)
         { /* The data bas been hashed */
         }
       else if (stopreason == KSBA_SR_END_DATA)
         { /* The data bas been hashed */
-
+          audit_log_ok (ctrl->audit, AUDIT_DATA_HASHING, 0);
         }
     }
   while (stopreason != KSBA_SR_READY);   
         }
     }
   while (stopreason != KSBA_SR_READY);   
@@ -452,6 +454,7 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp)
       log_printf (_(" using certificate ID 0x%08lX\n"),
                   gpgsm_get_short_fingerprint (cert, NULL));
 
       log_printf (_(" using certificate ID 0x%08lX\n"),
                   gpgsm_get_short_fingerprint (cert, NULL));
 
+      audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, algo);
 
       if (msgdigest)
         { /* Signed attributes are available. */
 
       if (msgdigest)
         { /* Signed attributes are available. */
@@ -484,6 +487,7 @@ gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp)
               goto next_signer; 
             }
             
               goto next_signer; 
             }
             
+          audit_log_i (ctrl->audit, AUDIT_ATTR_HASH_ALGO, sigval_hash_algo);
           rc = gcry_md_open (&md, sigval_hash_algo, 0);
           if (rc)
             {
           rc = gcry_md_open (&md, sigval_hash_algo, 0);
           if (rc)
             {