* certlist.c (cert_usable_p): New.
authorWerner Koch <wk@gnupg.org>
Fri, 12 Apr 2002 18:54:34 +0000 (18:54 +0000)
committerWerner Koch <wk@gnupg.org>
Fri, 12 Apr 2002 18:54:34 +0000 (18:54 +0000)
(gpgsm_cert_use_sign_p,gpgsm_cert_use_encrypt_p): New.
(gpgsm_cert_use_verify_p,gpgsm_cert_use_decrypt_p): New.
(gpgsm_add_to_certlist): Check the key usage.
* sign.c (gpgsm_sign): Ditto.
* verify.c (gpgsm_verify): Print a message wehn an unsuitable
certificate was used.
* decrypt.c (gpgsm_decrypt): Ditto
* keylist.c (print_capabilities): Determine values from the cert.

common/errors.h
sm/ChangeLog
sm/certlist.c
sm/decrypt.c
sm/gpgsm.h
sm/keylist.c
sm/sign.c
sm/verify.c

index 58508c9..22c8272 100644 (file)
@@ -102,6 +102,7 @@ enum {
   GNUPG_Bad_PIN_Method = 73,
   GNUPG_Card_Not_Initialized = 74,
   GNUPG_Unsupported_Operation = 75,
+  GNUPG_Wrong_Key_Usage = 76,
 };
 
 /* Status codes - fixme: should go into another file */
index 7793006..e28853f 100644 (file)
@@ -1,3 +1,15 @@
+2002-04-11  Werner Koch  <wk@gnupg.org>
+
+       * certlist.c (cert_usable_p): New.
+       (gpgsm_cert_use_sign_p,gpgsm_cert_use_encrypt_p): New.
+       (gpgsm_cert_use_verify_p,gpgsm_cert_use_decrypt_p): New.
+       (gpgsm_add_to_certlist): Check the key usage.
+       * sign.c (gpgsm_sign): Ditto.
+       * verify.c (gpgsm_verify): Print a message wehn an unsuitable
+       certificate was used.
+       * decrypt.c (gpgsm_decrypt): Ditto
+       * keylist.c (print_capabilities): Determine values from the cert.
+
 2002-03-28  Werner Koch  <wk@gnupg.org>
 
        * keylist.c (list_cert_colon): Fixed listing of crt record; the
index fe45f1d..2d52ada 100644 (file)
 
 #include "gpgsm.h"
 #include "keydb.h"
+#include "i18n.h"
+/* Return 0 if the cert is usable for encryption.  A MODE of 0 checks
+   for signing a MODE of 1 checks for encryption, a MODE of 2 checks
+   for verification and a MODE of 3 for decryption (just for
+   debugging) */
+static int
+cert_usage_p (KsbaCert cert, int mode)
+{
+  KsbaError err;
+  unsigned int use;
+
+  err = ksba_cert_get_key_usage (cert, &use);
+  if (err == KSBA_No_Data)
+    {
+      if (opt.verbose && mode < 2)
+        log_info (mode? 
+                  _("no key usage specified - accepted for encryption\n"):
+                  _("no key usage specified - accepted for signing\n"));
+      return 0;
+    }
+  if (err)
+    { 
+      log_error (_("error getting key usage information: %s\n"),
+                 ksba_strerror (err));
+      return map_ksba_err (err);
+    } 
+
+  if ((use & ((mode&1)? KSBA_KEYUSAGE_DIGITAL_SIGNATURE
+              : KSBA_KEYUSAGE_KEY_ENCIPHERMENT)))
+    return 0;
+  log_info (mode==3? _("certificate should have not been used for encryption\n"):
+            mode==2? _("certificate should have not been used for signing\n"):
+            mode==1? _("certificate is not usable for encryption\n"):
+                     _("certificate is not usable for signing\n"));
+  return GNUPG_Wrong_Key_Usage;
+}
+
+
+/* Return 0 if the cert is usable for signing */
+int
+gpgsm_cert_use_sign_p (KsbaCert cert)
+{
+  return cert_usage_p (cert, 0);
+}
+
+
+/* Return 0 if the cert is usable for encryption */
+int
+gpgsm_cert_use_encrypt_p (KsbaCert cert)
+{
+  return cert_usage_p (cert, 1);
+}
+
+int
+gpgsm_cert_use_verify_p (KsbaCert cert)
+{
+  return cert_usage_p (cert, 2);
+}
+
+int
+gpgsm_cert_use_decrypt_p (KsbaCert cert)
+{
+  return cert_usage_p (cert, 3);
+}
 
 /* add a certificate to a list of certificate and make sure that it is
    a valid certificate */
@@ -51,17 +116,40 @@ gpgsm_add_to_certlist (const char *name, CERTLIST *listaddr)
         rc = GNUPG_Out_Of_Core;
       else
         {
+          int wrong_usage = 0;
+        get_next:
           rc = keydb_search (kh, &desc, 1);
           if (!rc)
             rc = keydb_get_cert (kh, &cert);
           if (!rc)
             {
+              rc = gpgsm_cert_use_encrypt_p (cert);
+              if (rc == GNUPG_Wrong_Key_Usage)
+                {
+                  /* There might be another certificate with the
+                     correct usage, so we better try again */
+                  wrong_usage = rc;
+                  ksba_cert_release (cert);
+                  cert = NULL;
+                  goto get_next;
+                }
+            }
+          /* we want the error code from the first match in this case */
+          if (wrong_usage)
+            rc = wrong_usage;
+
+          if (!rc)
+            {
+              /* Fixme: If we ever have two certifciates differing
+                 only in the key usage, we should only bail out here
+                 if the certificate differes just in the key usage.
+                 However we need to find some criteria to match the
+                 identities */
               rc = keydb_search (kh, &desc, 1);
               if (rc == -1)
                 rc = 0;
               else if (!rc)
                 rc = GNUPG_Ambiguous_Name;
-
             }
           if (!rc)
             rc = gpgsm_validate_path (cert);
index 4e513a2..e3566fd 100644 (file)
@@ -378,6 +378,10 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
                       log_error ("failed to get cert: %s\n", gnupg_strerror (rc));
                       goto oops;     
                     }
+                  /* Just in case there is a problem with the own
+                     certificate we print this message - should never
+                     happen of course */
+                  gpgsm_cert_use_decrypt_p (cert);
 
                   hexkeygrip = gpgsm_get_keygrip_hexstring (cert);
 
index a46627d..9cba457 100644 (file)
@@ -178,6 +178,10 @@ int gpgsm_validate_path (KsbaCert cert);
 int gpgsm_basic_cert_check (KsbaCert cert);
 
 /*-- certlist.c --*/
+int gpgsm_cert_use_sign_p (KsbaCert cert);
+int gpgsm_cert_use_encrypt_p (KsbaCert cert);
+int gpgsm_cert_use_verify_p (KsbaCert cert);
+int gpgsm_cert_use_decrypt_p (KsbaCert cert);
 int gpgsm_add_to_certlist (const char *name, CERTLIST *listaddr);
 void gpgsm_release_certlist (CERTLIST list);
 int gpgsm_find_cert (const char *name, KsbaCert *r_cert);
index bccb26b..18d570e 100644 (file)
@@ -32,7 +32,7 @@
 
 #include "gpgsm.h"
 #include "keydb.h"
-
+#include "i18n.h"
 
 
 
@@ -56,12 +56,39 @@ print_key_data (KsbaCert cert, FILE *fp)
 static void
 print_capabilities (KsbaCert cert, FILE *fp)
 {
-  putc ('e', fp);
-  putc ('s', fp);
-  putc ('c', fp);
-  putc ('E', fp);
-  putc ('S', fp);
-  putc ('C', fp);
+  KsbaError err;
+  unsigned int use;
+
+  err = ksba_cert_get_key_usage (cert, &use);
+  if (err == KSBA_No_Data)
+    {
+      putc ('e', fp);
+      putc ('s', fp);
+      putc ('c', fp);
+      putc ('E', fp);
+      putc ('S', fp);
+      putc ('C', fp);
+      return;
+    }
+  if (err)
+    { 
+      log_error (_("error getting key usage information: %s\n"),
+                 ksba_strerror (err));
+      return;
+    } 
+
+  if ((use & KSBA_KEYUSAGE_KEY_ENCIPHERMENT))
+    putc ('e', fp);
+  if ((use & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
+    putc ('s', fp);
+  if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
+    putc ('c', fp);
+  if ((use & KSBA_KEYUSAGE_KEY_ENCIPHERMENT))
+    putc ('E', fp);
+  if ((use & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
+    putc ('S', fp);
+  if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
+    putc ('C', fp);
 }
 
 
index b16e840..2781baa 100644 (file)
--- a/sm/sign.c
+++ b/sm/sign.c
@@ -310,6 +310,10 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
       rc = seterr (General_Error);
       goto leave;
     }
+  rc = gpgsm_cert_use_sign_p (cert);
+  if (rc)
+    goto leave;
+
   err = ksba_cms_add_signer (cms, cert);
   if (err)
     {
index 69e18ac..f4d8039 100644 (file)
@@ -370,6 +370,7 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
           gpgsm_status (ctrl, STATUS_BADSIG, NULL);
           goto next_signer;
         }
+      gpgsm_cert_use_verify_p (cert); /* this displays an info message */
       log_debug ("signature okay - checking certs\n");
       gpgsm_status (ctrl, STATUS_GOODSIG, NULL);
       {