]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
** Corrected bugs in the openpgp certificate verification functions using a keyring.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 14 Oct 2007 22:00:28 +0000 (01:00 +0300)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 14 Oct 2007 22:00:28 +0000 (01:00 +0300)
Now it correctly verifies openpgp certificates.

** Removed the ancient pgpkeyserver support (which was not used anywhere)

14 files changed:
NEWS
configure.in
lib/auth_cert.h
lib/gnutls_cert.c
lib/gnutls_errors.c
lib/gnutls_extra_hooks.c
lib/gnutls_extra_hooks.h
libextra/gnutls_extra.c
libextra/gnutls_openpgp.c
libextra/opencdk/main.h
libextra/opencdk/sig-check.c
libextra/openpgp/compat.c
libextra/openpgp/gnutls_openpgp.h
libextra/openpgp/pgpverify.c

diff --git a/NEWS b/NEWS
index f87aa8ba7c676b72921ab899d32150c3d7289c0c..e9b6ec39ce149d2323f1f29055ed6b92961f4f5d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,14 @@ Copyright (C) 2004, 2005, 2006, 2007 Simon Josefsson
 Copyright (C) 2000, 2001, 2002, 2003, 2004 Nikos Mavroyanopoulos
 See the end for copying conditions.
 
+* Version 2.1.3 (unreleased)
+
+** Corrected bugs in openpgp key verification using a keyring (both in
+gnutls and opencdk)
+
+** API and ABI modifications:
+gnutls_certificate_set_openpgp_keyserver: REMOVED
+
 * Version 2.1.2 (released 2007-10-14)
 
 ** Removed all the trustdb code from openpgp authentication.
index 93c152be6a1d89c1db5dd1c228c3c271966b26f9..0b1b435cef91d1fcfa348339fa46c45cee311fe0 100644 (file)
@@ -44,6 +44,8 @@ ac_full=1
 SOVERSION=`expr ${LT_CURRENT} - ${LT_AGE}`
 AC_SUBST(SOVERSION)
 
+dnl for opencdk needs also change in the test
+GNUTLS_OPENCDK_VERSION=0.6.5
 GNUTLS_GCRYPT_VERSION=1:1.3.0
 GNUTLS_LIBTASN1_VERSION=0.3.4
 AC_DEFINE_UNQUOTED(GNUTLS_GCRYPT_VERSION, "$GNUTLS_GCRYPT_VERSION", [version of gcrypt])
@@ -510,7 +512,13 @@ if test x$ac_enable_openpgp = xyes; then
                ac_enable_included_opencdk=no)
  if test x$ac_enable_included_opencdk = xno;then 
   AC_LIB_HAVE_LINKFLAGS(opencdk,, [
-#include <opencdk.h>], [cdk_armor_encode_buffer (NULL, 0, NULL, 0, NULL, 0);])
+#include <opencdk.h>], [
+#if OPENCDK_VERSION_MINOR < 6 || OPENCDK_VERSION_PATCH < 5
+# error "OpenCDK 0.6.5 is required"
+#else
+cdk_check_version( NULL);
+#endif
+])
   if test "$ac_cv_libopencdk" != yes; then
    ac_enable_included_opencdk=yes
    AC_MSG_WARN([[
index 778a3e18b0b95df5f2819f4735bed6908acd87c5..c38582218266e2c0626bf48ef7aa8b0b146cc2f2 100644 (file)
@@ -64,11 +64,7 @@ typedef struct gnutls_certificate_credentials_st
 
   /* OpenPGP specific stuff */
 
-  gnutls_datum_t keyring;
-  char *pgp_key_server;
-  int pgp_key_server_port;
-
-  char *pgp_trustdb;
+  gnutls_openpgp_keyring_t keyring;
 
   /* X509 specific stuff */
 
index b22d8a113a475c3fba38cc6b1625562339679725..c1281a24ab19459ec1395dd06ab4208bc732cc81 100644 (file)
@@ -190,8 +190,8 @@ gnutls_certificate_free_credentials (gnutls_certificate_credentials_t sc)
 #ifdef ENABLE_PKI
   gnutls_certificate_free_crls (sc);
 #endif
-
-  _gnutls_free_datum (&sc->keyring);
+  if (_E_gnutls_openpgp_keyring_deinit)
+    _E_gnutls_openpgp_keyring_deinit( sc->keyring);
 
   gnutls_free (sc);
 }
index 2c8afd40389935cc6429801112194576b0c97d52..62203b31008bbd005383e98b88d4df5d9089ec52 100644 (file)
@@ -195,8 +195,6 @@ static const gnutls_error_entry error_algorithms[] = {
 
   ERROR_ENTRY (N_("The tasn1 library version is too old."),
               GNUTLS_E_INCOMPATIBLE_LIBTASN1_LIBRARY, 1),
-  ERROR_ENTRY (N_("The specified GnuPG TrustDB version is not supported. TrustDB v4 is supported."),
-     GNUTLS_E_OPENPGP_TRUSTDB_VERSION_UNSUPPORTED, 1),
 
   ERROR_ENTRY (N_("Error loading the keyring."),
               GNUTLS_E_OPENPGP_KEYRING_ERROR, 1),
index f2bfb3f25f825252f18e45f143d907ec8e2e7ab1..1b3484c7a0e512d3773d3a8aca7f5bbaae40c82e 100644 (file)
 /* Variables used by libgnutls, set by
    _gnutls_add_openpgp_functions(), typically invoked by
    libgnutls_extra. */
-_gnutls_openpgp_verify_key_func _E_gnutls_openpgp_verify_key;
+_gnutls_openpgp_verify_key_func _E_gnutls_openpgp_verify_key = NULL;
 _gnutls_openpgp_key_creation_time_func
-_E_gnutls_openpgp_get_raw_key_creation_time;
+_E_gnutls_openpgp_get_raw_key_creation_time = NULL;
 _gnutls_openpgp_key_expiration_time_func
-_E_gnutls_openpgp_get_raw_key_expiration_time;
-_gnutls_openpgp_fingerprint_func _E_gnutls_openpgp_fingerprint;
-_gnutls_openpgp_key_request_func _E_gnutls_openpgp_request_key;
-_gnutls_openpgp_raw_key_to_gcert_func _E_gnutls_openpgp_raw_key_to_gcert;
-_gnutls_openpgp_raw_privkey_to_gkey_func _E_gnutls_openpgp_raw_privkey_to_gkey;
-_gnutls_openpgp_key_to_gcert_func _E_gnutls_openpgp_key_to_gcert;
-_gnutls_openpgp_privkey_to_gkey_func _E_gnutls_openpgp_privkey_to_gkey;
-_gnutls_openpgp_key_deinit_func _E_gnutls_openpgp_key_deinit;
-_gnutls_openpgp_privkey_deinit_func _E_gnutls_openpgp_privkey_deinit;
+_E_gnutls_openpgp_get_raw_key_expiration_time = NULL;
+_gnutls_openpgp_fingerprint_func _E_gnutls_openpgp_fingerprint = NULL;
+_gnutls_openpgp_key_request_func _E_gnutls_openpgp_request_key = NULL;
+_gnutls_openpgp_raw_key_to_gcert_func _E_gnutls_openpgp_raw_key_to_gcert = NULL;
+_gnutls_openpgp_raw_privkey_to_gkey_func _E_gnutls_openpgp_raw_privkey_to_gkey = NULL;
+_gnutls_openpgp_key_to_gcert_func _E_gnutls_openpgp_key_to_gcert = NULL;
+_gnutls_openpgp_privkey_to_gkey_func _E_gnutls_openpgp_privkey_to_gkey = NULL;
+_gnutls_openpgp_key_deinit_func _E_gnutls_openpgp_key_deinit = NULL;
+_gnutls_openpgp_keyring_deinit_func _E_gnutls_openpgp_keyring_deinit = NULL;
+_gnutls_openpgp_privkey_deinit_func _E_gnutls_openpgp_privkey_deinit = NULL;
 
 /* Called by libgnutls_extra to set the OpenPGP functions that are
    needed by GnuTLS.  */
@@ -56,6 +57,7 @@ _gnutls_add_openpgp_functions
  _gnutls_openpgp_key_to_gcert_func key_to_gcert,
  _gnutls_openpgp_privkey_to_gkey_func privkey_to_gkey,
  _gnutls_openpgp_key_deinit_func key_deinit,
+ _gnutls_openpgp_keyring_deinit_func keyring_deinit,
  _gnutls_openpgp_privkey_deinit_func privkey_deinit)
 {
   _E_gnutls_openpgp_verify_key = verify_key;
@@ -68,6 +70,7 @@ _gnutls_add_openpgp_functions
   _E_gnutls_openpgp_key_to_gcert = key_to_gcert;
   _E_gnutls_openpgp_privkey_to_gkey = privkey_to_gkey;
   _E_gnutls_openpgp_key_deinit = key_deinit;
+  _E_gnutls_openpgp_keyring_deinit = keyring_deinit;
   _E_gnutls_openpgp_privkey_deinit = privkey_deinit;
 
 }
index 146979030409cb05763aa06a360ac44cce3768d3..4ef8bb4cda4c1875a293e7ddbdb479a73d326d29 100644 (file)
@@ -66,6 +66,9 @@ typedef int (*_gnutls_openpgp_privkey_to_gkey_func)
 typedef void (*_gnutls_openpgp_key_deinit_func)
 (gnutls_openpgp_key_t);
 
+typedef void (*_gnutls_openpgp_keyring_deinit_func)
+(gnutls_openpgp_keyring_t);
+
 typedef void (*_gnutls_openpgp_privkey_deinit_func)
 (gnutls_openpgp_privkey_t);
 
@@ -85,6 +88,7 @@ extern _gnutls_openpgp_raw_privkey_to_gkey_func _E_gnutls_openpgp_raw_privkey_to
 extern _gnutls_openpgp_key_to_gcert_func _E_gnutls_openpgp_key_to_gcert;
 extern _gnutls_openpgp_privkey_to_gkey_func _E_gnutls_openpgp_privkey_to_gkey;
 extern _gnutls_openpgp_key_deinit_func _E_gnutls_openpgp_key_deinit;
+extern _gnutls_openpgp_keyring_deinit_func _E_gnutls_openpgp_keyring_deinit;
 extern _gnutls_openpgp_privkey_deinit_func _E_gnutls_openpgp_privkey_deinit;
 
 extern void _gnutls_add_openpgp_functions
@@ -98,4 +102,5 @@ extern void _gnutls_add_openpgp_functions
  _gnutls_openpgp_key_to_gcert_func key_to_gcert,
  _gnutls_openpgp_privkey_to_gkey_func privkey_to_gkey,
  _gnutls_openpgp_key_deinit_func key_deinit,
+ _gnutls_openpgp_keyring_deinit_func keyring_deinit,
  _gnutls_openpgp_privkey_deinit_func privkey_deinit);
index 7471fca9358bd0713cb9ad8a74af2d9a0de60c18..6dbb79e4bfd080454870dff78bc267fc864b41fe 100644 (file)
@@ -153,6 +153,7 @@ gnutls_global_init_extra (void)
                                 _gnutls_openpgp_key_to_gcert,
                                 _gnutls_openpgp_privkey_to_gkey,
                                 gnutls_openpgp_key_deinit,
+                                gnutls_openpgp_keyring_deinit,
                                 gnutls_openpgp_privkey_deinit);
 
   return 0;
index 5b3c2415acf51271d56415c3a9a232a3bbc40754..0b9ec2d23233a394f67638d2444178b233aec1c9 100644 (file)
@@ -454,11 +454,9 @@ _gnutls_openpgp_raw_key_to_gcert (gnutls_cert * cert,
  -*/
 int
 gnutls_openpgp_get_key (gnutls_datum_t * key,
-                       const gnutls_datum_t * keyring, key_attr_t by,
+                       gnutls_openpgp_keyring_t keyring, key_attr_t by,
                        opaque * pattern)
 {
-  keybox_blob *blob = NULL;
-  cdk_keydb_hd_t db = NULL;
   cdk_kbnode_t knode = NULL;
   unsigned long keyid[2];
   unsigned char *buf;
@@ -473,10 +471,6 @@ gnutls_openpgp_get_key (gnutls_datum_t * key,
     }
 
   memset (key, 0, sizeof *key);
-  blob = kbx_read_blob (keyring, 0);
-  if (!blob)
-    return GNUTLS_E_MEMORY_ERROR;
-  db = kbx_to_keydb (blob);
 
   if (by == KEY_ATTR_SHORT_KEYID)
     {
@@ -491,9 +485,9 @@ gnutls_openpgp_get_key (gnutls_datum_t * key,
     }
   else
     desc = pattern;
-  rc = cdk_keydb_search_start (db, by, desc);
+  rc = cdk_keydb_search_start (keyring->db, by, desc);
   if (!rc)
-    rc = cdk_keydb_search (db, &knode);
+    rc = cdk_keydb_search (keyring->db, &knode);
   if (rc)
     {
       rc = _gnutls_map_cdk_rc (rc);
@@ -514,9 +508,7 @@ gnutls_openpgp_get_key (gnutls_datum_t * key,
   cdk_free (buf);
 
 leave:
-  cdk_keydb_free (db);
   cdk_kbnode_release (knode);
-  kbx_blob_release (blob);
   return rc;
 }
 
@@ -807,93 +799,8 @@ gnutls_openpgp_count_key_names (const gnutls_datum_t * cert)
 }
 
 
-
-
-
-/*-
- * gnutls_openpgp_add_keyring_file - Adds a keyring file for OpenPGP
- * @keyring: data buffer to store the file.
- * @name: filename of the keyring.
- *
- * The function is used to set keyrings that will be used internally
- * by various OpenCDK functions. For example to find a key when it
- * is needed for an operations.
- -*/
-int
-gnutls_openpgp_add_keyring_file (gnutls_datum_t * keyring, const char *name)
-{
-  cdk_stream_t inp = NULL;
-  uint8_t *blob;
-  size_t nbytes;
-  int enc = 0;
-  int rc = 0;
-
-  if (!keyring || !name)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
-    }
-
-  rc = cdk_stream_open (name, &inp);
-  if (rc)
-    return _gnutls_map_cdk_rc (rc);
-  enc = cdk_armor_filter_use (inp);
-  cdk_stream_close (inp);
-
-  blob = kbx_data_to_keyring (KBX_BLOB_FILE, enc, name,
-                             strlen (name), &nbytes);
-  if (blob && nbytes)
-    {
-      if (datum_append (keyring, blob, nbytes) < 0)
-       {
-         gnutls_assert ();
-         return GNUTLS_E_MEMORY_ERROR;
-       }
-      gnutls_free (blob);
-    }
-  return 0;
-}
-
-
-/*-
- * gnutls_openpgp_add_keyring_mem - Adds keyring data for OpenPGP
- * @keyring: data buffer to store the file.
- * @data: the binary data of the keyring.
- * @len: the size of the binary buffer.
- *
- * Same as gnutls_openpgp_add_keyring_mem but now we store the
- * data instead of the filename.
- -*/
-int
-gnutls_openpgp_add_keyring_mem (gnutls_datum_t * keyring,
-                               const void *data, size_t len)
-{
-  uint8_t *blob;
-  size_t nbytes = 0;
-
-  if (!keyring || !data || !len)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
-    }
-
-  blob = kbx_data_to_keyring (KBX_BLOB_DATA, 0, data, len, &nbytes);
-  if (blob && nbytes)
-    {
-      if (datum_append (keyring, blob, nbytes) < 0)
-       {
-         gnutls_assert ();
-         return GNUTLS_E_MEMORY_ERROR;
-       }
-      gnutls_free (blob);
-    }
-
-  return 0;
-}
-
-
 /**
- * gnutls_certificate_set_openpgp_keyring_file - Adds a keyring file for OpenPGP
+ * gnutls_certificate_set_openpgp_keyring_file - Sets a keyring file for OpenPGP
  * @c: A certificate credentials structure
  * @file: filename of the keyring.
  *
@@ -907,7 +814,9 @@ int
   gnutls_certificate_set_openpgp_keyring_file
   (gnutls_certificate_credentials_t c, const char *file)
 {
-  struct stat statbuf;
+gnutls_datum ring;
+size_t size;
+int rc;
 
   if (!c || !file)
     {
@@ -915,10 +824,19 @@ int
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  if (stat (file, &statbuf))
-    return GNUTLS_E_FILE_ERROR;
+  ring.data = read_binary_file (file, &size);
+  ring.size = (unsigned int)size;
+  if (ring.data == NULL)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_FILE_ERROR;
+    }
 
-  return gnutls_openpgp_add_keyring_file (&c->keyring, file);
+  rc = gnutls_certificate_set_openpgp_keyring_mem (c, ring.data, ring.size);
+  
+  free( ring.data);
+  
+  return rc;
 }
 
 /**
@@ -941,40 +859,32 @@ gnutls_certificate_set_openpgp_keyring_mem (gnutls_certificate_credentials_t
   cdk_stream_t inp;
   size_t count;
   uint8_t *buf;
+  gnutls_datum ddata;
   int rc;
-
+  
+  ddata.data = (void*)data;
+  ddata.size = dlen;
+  
   if (!c || !data || !dlen)
     {
       gnutls_assert ();
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  rc = cdk_stream_tmp_from_mem (data, dlen, &inp);
-  if (rc)
-    return GNUTLS_E_FILE_ERROR;
-
-  /* Maybe it's a little confusing that we check the output..
-     but it's possible, that the data we want to add, is armored
-     and we only want to store plaintext keyring data. */
-  if (cdk_armor_filter_use (inp))
-    cdk_stream_set_armor_flag (inp, 0);
-
-  /* fixme: this is possible the armored length. */
-  count = cdk_stream_get_length (inp);
-  buf = gnutls_malloc (count + 1);
-  if (!buf)
-    {
-      gnutls_assert ();
-      cdk_stream_close (inp);
-      return GNUTLS_E_MEMORY_ERROR;
-    }
-
-  count = cdk_stream_read (inp, buf, count);
-  buf[count] = '\0';
-  rc = gnutls_openpgp_add_keyring_mem (&c->keyring, buf, count);
-  cdk_stream_close (inp);
-
-  return rc;
+  rc = gnutls_openpgp_keyring_init( &c->keyring);
+  if (rc < 0) {
+    gnutls_assert();
+    return rc;
+  }
+  
+  rc = gnutls_openpgp_keyring_import( c->keyring, &ddata, GNUTLS_OPENPGP_FMT_BASE64);
+  if ( rc < 0) {
+    gnutls_assert();
+    gnutls_openpgp_keyring_deinit( c->keyring);
+    return rc;
+  }
+  
+  return 0;
 }
 
 /*-
@@ -1004,7 +914,7 @@ _gnutls_openpgp_request_key (gnutls_session_t session, gnutls_datum_t * ret,
   if (key_fpr_size != 16 && key_fpr_size != 20)
     return GNUTLS_E_HASH_FAILED; /* only MD5 and SHA1 are supported */
 
-  rc = gnutls_openpgp_get_key (ret, &cred->keyring, KEY_ATTR_FPR, key_fpr);
+  rc = gnutls_openpgp_get_key (ret, cred->keyring, KEY_ATTR_FPR, key_fpr);
   if (rc >= 0)                 /* key was found */
     return rc;
   else
@@ -1026,42 +936,6 @@ _gnutls_openpgp_request_key (gnutls_session_t session, gnutls_datum_t * ret,
   return rc;
 }
 
-
-/**
- * gnutls_certificate_set_openpgp_keyserver - Used to set an OpenPGP key server
- * @res: the destination context to save the data.
- * @keyserver: is the key server address
- * @port: is the key server port to connect to
- *
- * This funtion will set a key server for use with openpgp keys. This
- * key server will only be used if the peer sends a key fingerprint instead
- * of a key in the handshake. Using a key server may delay the handshake
- * process.
- *
- **/
-int
-gnutls_certificate_set_openpgp_keyserver (gnutls_certificate_credentials_t
-                                         res, const char *keyserver,
-                                         int port)
-{
-  if (!res || !keyserver)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
-    }
-
-  if (!port)
-    port = 11371;
-
-  gnutls_free (res->pgp_key_server);
-  res->pgp_key_server = gnutls_strdup (keyserver);
-  if (!res->pgp_key_server)
-    return GNUTLS_E_MEMORY_ERROR;
-  res->pgp_key_server_port = port;
-
-  return 0;
-}
-
 /**
  * gnutls_openpgp_set_recv_key_function - Used to set a key retrieval callback for PGP keys
  * @session: a TLS session
index 73c4b8d3a41468e5edea06ef6419666d6ac8d555..3e9a443d8fc04a7c93c63392f2540a84b4292e8e 100644 (file)
@@ -94,11 +94,11 @@ cdk_error_t _cdk_proc_packets (cdk_ctx_t hd, cdk_stream_t inp,
 cdk_error_t _cdk_pkt_write2 (cdk_stream_t out, int pkttype, void *pktctx);
 
 /*-- pubkey.c --*/
-u32 _cdk_pkt_get_keyid( cdk_packet_t pkt, u32 * keyid );
-int _cdk_pkt_get_fingerprint( cdk_packet_t pkt, byte * fpr );
-int _cdk_pk_algo_usage( int algo );
-int _cdk_pk_test_algo( int algo, unsigned int usage );
-int _cdk_sk_get_csum( cdk_pkt_seckey_t sk );
+u32 _cdk_pkt_get_keyid (cdk_packet_t pkt, u32 * keyid);
+cdk_error_t _cdk_pkt_get_fingerprint (cdk_packet_t pkt, byte *fpr);
+int _cdk_pk_algo_usage (int algo);
+int _cdk_pk_test_algo (int algo, unsigned int usage);
+int _cdk_sk_get_csum (cdk_pkt_seckey_t sk);
 
 /*-- new-packet.c --*/
 byte * _cdk_subpkt_get_array (cdk_subpkt_t s, int count, size_t * r_nbytes);
@@ -106,11 +106,12 @@ cdk_error_t _cdk_subpkt_copy (cdk_subpkt_t * r_dst, cdk_subpkt_t src);
 void _cdk_pkt_detach_free (cdk_packet_t pkt, int *r_pkttype, void **ctx);
 
 /*-- sig-check.c --*/
-int _cdk_sig_check (cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig,
-                    gcry_md_hd_t digest, int * r_expired);
+cdk_error_t _cdk_sig_check (cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig,
+                           gcry_md_hd_t digest, int * r_expired);
 cdk_error_t _cdk_hash_sig_data (cdk_pkt_signature_t sig, gcry_md_hd_t hd);
-void _cdk_hash_userid (cdk_pkt_userid_t uid, int sig_version, gcry_md_hd_t md);
-int _cdk_hash_pubkey (cdk_pkt_pubkey_t pk, gcry_md_hd_t md, int use_fpr);
+cdk_error_t _cdk_hash_userid (cdk_pkt_userid_t uid, int sig_version, gcry_md_hd_t md);
+cdk_error_t _cdk_hash_pubkey (cdk_pkt_pubkey_t pk, gcry_md_hd_t md, 
+                             int use_fpr);
 cdk_error_t _cdk_pk_check_sig (cdk_keydb_hd_t hd,
                               cdk_kbnode_t knode, 
                               cdk_kbnode_t snode, int *is_selfsig);
@@ -120,10 +121,11 @@ void _cdk_kbnode_add (cdk_kbnode_t root, cdk_kbnode_t node);
 void _cdk_kbnode_clone (cdk_kbnode_t node);
 
 /*-- sesskey.c --*/
-int _cdk_digest_encode_pkcs1 (byte ** r_md, size_t * r_mdlen, int pk_algo,
-                              const byte * md,
-                              int digest_algo, unsigned nbits);
-int _cdk_sk_unprotect_auto (cdk_ctx_t hd, cdk_pkt_seckey_t sk);
+cdk_error_t _cdk_digest_encode_pkcs1 (byte **r_md, size_t *r_mdlen, 
+                                     int pk_algo,
+                                     const byte * md,
+                                     int digest_algo, unsigned nbits);
+cdk_error_t _cdk_sk_unprotect_auto (cdk_ctx_t hd, cdk_pkt_seckey_t sk);
 
 /*-- keydb.c --*/
 int _cdk_keydb_is_secret (cdk_keydb_hd_t db);   
@@ -135,11 +137,11 @@ cdk_error_t _cdk_keydb_check_userid (cdk_keydb_hd_t hd, u32 * keyid,
                                     const char * id);
 
 /*-- sign.c --*/
-int _cdk_sig_create( cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig );
 int _cdk_sig_hash_for (cdk_pkt_pubkey_t pk);
-void _cdk_trim_string( char * s, int canon );
-cdk_error_t _cdk_sig_complete( cdk_pkt_signature_t sig, cdk_pkt_seckey_t sk,
-                              gcry_md_hd_t hd );
+void _cdk_trim_string (char * s, int canon);
+cdk_error_t _cdk_sig_create (cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig);
+cdk_error_t _cdk_sig_complete (cdk_pkt_signature_t sig, cdk_pkt_seckey_t sk,
+                              gcry_md_hd_t hd);
 
 /*-- stream.c --*/
 void _cdk_stream_set_compress_algo (cdk_stream_t s, int algo);   
index 75f63a51d9e85256d6461174b2a5a2bb717a8b84..948fe2993bbc89a4e6f5d221ecf4991a4edf1fcf 100644 (file)
@@ -32,9 +32,9 @@
 static int
 hash_mpibuf (cdk_pubkey_t pk, gcry_md_hd_t md, int usefpr)
 {
-  byte buf[MAX_MPI_BYTES];
+  byte buf[MAX_MPI_BYTES]; /* FIXME: do not use hardcoded length. */
   size_t nbytes;
-  int i, npkey;
+  size_t i, npkey;
   gcry_error_t err;
   
   /* We have to differ between two modes for v3 keys. To form the
@@ -57,14 +57,13 @@ hash_mpibuf (cdk_pubkey_t pk, gcry_md_hd_t md, int usefpr)
 
 
 /* Hash an entire public key PK with the given message digest context
-   MD. The USEFPR param is only valid for version 3 keys because of
+   MD. The @usefpr param is only valid for version 3 keys because of
    the different way to calculate the fingerprint. */
-int
+cdk_error_t
 _cdk_hash_pubkey (cdk_pubkey_t pk, gcry_md_hd_t md, int usefpr)
 {
   byte buf[12];
-  u16 n;
-  int i, npkey;
+  size_t i, n, npkey;
   
   if (!pk || !md)
     return CDK_Inv_Value;
@@ -72,7 +71,9 @@ _cdk_hash_pubkey (cdk_pubkey_t pk, gcry_md_hd_t md, int usefpr)
   if (usefpr && pk->version < 4 && is_RSA (pk->pubkey_algo)) 
     return hash_mpibuf (pk, md, 1);
   
-  n = pk->version < 4? 8 : 6;  /* v4: without the expire 'date' */
+  /* The version 4 public key packet does not have the 2 octets for
+     the expiration date. */
+  n = pk->version < 4? 8 : 6;
   npkey = cdk_pk_get_npkey (pk->pubkey_algo);
   for (i = 0; i < npkey; i++) 
     n = n + (gcry_mpi_get_nbits (pk->mpi[i])+7)/8 + 2;
@@ -91,6 +92,7 @@ _cdk_hash_pubkey (cdk_pubkey_t pk, gcry_md_hd_t md, int usefpr)
     {    
       u16 a = 0;
       
+      /* Convert the expiration date into days. */
       if (pk->expiredate)
        a = (u16)((pk->expiredate - pk->timestamp) / 86400L);
       buf[i++] = a >> 8;
@@ -104,7 +106,7 @@ _cdk_hash_pubkey (cdk_pubkey_t pk, gcry_md_hd_t md, int usefpr)
 
 /* Hash the user ID @uid with the given message digest @md.
    Use openpgp mode if @is_v4 is 1. */
-void
+cdk_error_t
 _cdk_hash_userid (cdk_pkt_userid_t uid, int is_v4, gcry_md_hd_t md)
 {
   const byte *data;
@@ -112,12 +114,12 @@ _cdk_hash_userid (cdk_pkt_userid_t uid, int is_v4, gcry_md_hd_t md)
   u32 dlen;
   
   if (!uid || !md)
-    return;
+    return CDK_Inv_Value;
 
   if (!is_v4)
     {
       gcry_md_write (md, (byte*)uid->name, uid->len);
-      return;
+      return 0;
     }
   
   dlen = uid->attrib_img? uid->attrib_len : uid->len;
@@ -129,6 +131,7 @@ _cdk_hash_userid (cdk_pkt_userid_t uid, int is_v4, gcry_md_hd_t md)
   buf[4] = dlen >>  0;
   gcry_md_write (md, buf, 5);
   gcry_md_write (md, data, dlen);
+  return 0;
 }
 
 
@@ -195,7 +198,7 @@ cache_sig_result (cdk_pkt_signature_t sig, int res)
 {
   sig->flags.checked = 0;
   sig->flags.valid = 0;
-  if (!res) 
+  if (res == 0)
     {
       sig->flags.checked = 1;
       sig->flags.valid = 1;
@@ -214,9 +217,9 @@ cdk_error_t
 _cdk_sig_check (cdk_pubkey_t pk, cdk_pkt_signature_t sig,
                 gcry_md_hd_t digest, int *r_expired)
 {
-  byte md[MAX_DIGEST_LEN];
-  time_t cur_time = (u32)time (NULL);
   cdk_error_t rc;
+  byte md[MAX_DIGEST_LEN];
+  time_t cur_time = (u32)time (NULL);  
 
   if (!pk || !sig || !digest)
     return CDK_Inv_Value;
@@ -254,12 +257,12 @@ _cdk_pk_check_sig (cdk_keydb_hd_t keydb,
                   cdk_kbnode_t knode, cdk_kbnode_t snode, int *is_selfsig)
 {
   gcry_md_hd_t md;
+  gcry_error_t err;
   cdk_pubkey_t pk;
   cdk_pkt_signature_t sig;
   cdk_kbnode_t node;
-  int is_expired;
-  gcry_error_t err;
   cdk_error_t rc = 0;
+  int is_expired;
 
   if (!knode || !snode)
     return CDK_Inv_Value;
@@ -345,7 +348,7 @@ _cdk_pk_check_sig (cdk_keydb_hd_t keydb,
 
 /**
  * cdk_pk_check_sigs:
- * @knode: the key node
+ * @key: the public key
  * @hd: an optinal key database handle
  * @r_status: variable to store the status of the key
  *
@@ -354,41 +357,40 @@ _cdk_pk_check_sig (cdk_keydb_hd_t keydb,
  * which are or-ed or zero when there are no flags.
  **/
 cdk_error_t
-cdk_pk_check_sigs (cdk_kbnode_t knode, cdk_keydb_hd_t keydb, int *r_status)
+cdk_pk_check_sigs (cdk_kbnode_t key, cdk_keydb_hd_t keydb, int *r_status)
 {
   cdk_pkt_signature_t sig;
   cdk_kbnode_t node;
+  cdk_error_t rc;
   u32 keyid;
   int key_status, is_selfsig = 0;
-  int no_signer = 0, n_sigs = 0;
-  cdk_error_t rc;
+  int no_signer, n_sigs = 0;  
   
-  if (!knode || !r_status)
+  if (!key || !r_status)
     return CDK_Inv_Value;
   
   *r_status = 0;
-  node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY);
+  node = cdk_kbnode_find (key, CDK_PKT_PUBLIC_KEY);
   if (!node)
     return CDK_Error_No_Key;
   
   key_status = 0;
+  /* Continue with the signature check but adjust the
+     key status flags accordingly. */
   if (node->pkt->pkt.public_key->is_revoked)
     key_status |= CDK_KEY_REVOKED;
   if (node->pkt->pkt.public_key->has_expired)
     key_status |= CDK_KEY_EXPIRED;
-  if (key_status) 
-    {
-      *r_status = key_status;
-      return CDK_General_Error;
-    }
+  
   rc = 0;
+  no_signer = 0;
   keyid = cdk_pk_get_keyid (node->pkt->pkt.public_key, NULL);
-  for (node = knode; node; node = node->next) 
+  for (node = key; node; node = node->next) 
     {
       if (node->pkt->pkttype != CDK_PKT_SIGNATURE)
        continue;
       sig = node->pkt->pkt.signature;
-      rc = _cdk_pk_check_sig (keydb, knode, node, &is_selfsig);
+      rc = _cdk_pk_check_sig (keydb, key, node, &is_selfsig);
       if (IS_UID_SIG (sig)) 
        {
          if (is_selfsig == 0)
@@ -396,58 +398,66 @@ cdk_pk_check_sigs (cdk_kbnode_t knode, cdk_keydb_hd_t keydb, int *r_status)
        }
       if (rc && IS_UID_SIG (sig) && rc == CDK_Error_No_Key)
        {
+         /* We do not consider it a problem when the signing key
+            is not avaiable. We just mark the signature accordingly
+            and contine.*/
          sig->flags.missing_key = 1;
          no_signer++;
-         continue;
         }
       else if (rc && rc != CDK_Error_No_Key)
        {
-         /* If there was an error during the verify process and
-            we checked the self signature, we immediately bail out. */
-         *r_status = CDK_KEY_INVALID;
-         if (is_selfsig)
-           return rc;
-         break;
+         /* It might be possible that a single signature has been
+            corrupted, thus we do not consider it a problem when
+            one ore more signatures are bad. But at least the self
+            signature has to be valid. */
+         if (is_selfsig) 
+           {
+             key_status |= CDK_KEY_INVALID;
+             break;
+           }     
         }
       _cdk_log_debug ("signature %s: signer %08lX keyid %08lX\n",
-                     rc==CDK_Bad_Sig? "BAD" : "good", sig->keyid[1],
+                     rc == CDK_Bad_Sig? "BAD" : "good", sig->keyid[1],
                      keyid);
     }
+  
   if (n_sigs == no_signer)
-    *r_status |= CDK_KEY_NOSIGNER;
-  if (!rc || rc == CDK_Error_No_Key)
-    *r_status = CDK_KEY_VALID;
+    key_status |= CDK_KEY_NOSIGNER;  
+  *r_status = key_status;  
+  if (rc == CDK_Error_No_Key)
+    rc = 0;
   return rc;
 }
 
 
 /**
  * cdk_pk_check_self_sig:
- * @knode: the key node
- * @keydb: an optional handle to the key database
+ * @key: the key node
  * @r_status: output the status of the key.
  * 
  * A convenient function to make sure the key is valid.
  * Valid means the self signature is ok.
  **/
 cdk_error_t
-cdk_pk_check_self_sig (cdk_kbnode_t knode, int *r_status)
+cdk_pk_check_self_sig (cdk_kbnode_t key, int *r_status)
 {
   cdk_pkt_signature_t sig;
   cdk_kbnode_t node;
-  u32 keyid[2], sigid[2];
   cdk_error_t rc;
+  u32 keyid[2], sigid[2];  
   int is_selfsig, sig_ok;
   
-  if (!knode || !r_status)
+  if (!key || !r_status)
     return CDK_Inv_Value;
   
-  node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY);
+  node = cdk_kbnode_find (key, CDK_PKT_PUBLIC_KEY);
   if (!node)
     return CDK_Error_No_Key;
-  cdk_pk_get_keyid (knode->pkt->pkt.public_key, keyid);
+  /* FIXME: we should set expire/revoke here also but callers
+     expect CDK_KEY_VALID=0 if the key is okay. */
+  cdk_pk_get_keyid (key->pkt->pkt.public_key, keyid);
   sig_ok = 0;
-  for (node = knode; node; node = node->next)
+  for (node = key; node; node = node->next)
     {
       if (node->pkt->pkttype != CDK_PKT_SIGNATURE)
        continue;
@@ -458,12 +468,12 @@ cdk_pk_check_self_sig (cdk_kbnode_t knode, int *r_status)
       if (sigid[0] != keyid[0] || sigid[1] != keyid[1])
        continue;
       /* FIXME: Now we check all self signatures. */
-      rc = _cdk_pk_check_sig (NULL, knode, node, &is_selfsig);
+      rc = _cdk_pk_check_sig (NULL, key, node, &is_selfsig);
       if (rc)
        {
          *r_status = CDK_KEY_INVALID;
          return rc;
-       }      
+       }
       else /* For each valid self sig we increase this counter. */
        sig_ok++;
     }
@@ -473,7 +483,8 @@ cdk_pk_check_self_sig (cdk_kbnode_t knode, int *r_status)
     {
       *r_status = CDK_KEY_INVALID;
       return CDK_General_Error;
-    }  
+    }
+  /* No flags indicate a valid key. */
   *r_status = CDK_KEY_VALID;
   return 0;
 }
index ba4b7614bd163f28e5686ff19198e5fc77efcb76..e98b8d1f60eaf3a5cb52bb5b047b5a9cef60ff26 100644 (file)
@@ -51,8 +51,7 @@ _gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t cred,
 {
   int ret = 0;
   gnutls_openpgp_key_t key = NULL;
-  gnutls_openpgp_keyring_t ring = NULL;
-  unsigned int verify_ring = 0, verify_db = 0, verify_self = 0;
+  unsigned int verify = 0, verify_self = 0;
 
   if (!cert_list || cert_list_length != 1)
     {
@@ -67,31 +66,16 @@ _gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t cred,
       return ret;
     }
 
-  ret = gnutls_openpgp_key_import (key, &cert_list[0], 0);
+  ret = gnutls_openpgp_key_import (key, &cert_list[0], GNUTLS_OPENPGP_FMT_RAW);
   if (ret < 0)
     {
       gnutls_assert ();
       goto leave;
     }
 
-  if (cred->keyring.data && cred->keyring.size != 0)
+  if (cred->keyring != NULL)
     {
-      /* use the keyring */
-      ret = gnutls_openpgp_keyring_init (&ring);
-      if (ret < 0)
-       {
-         gnutls_assert ();
-         goto leave;
-       }
-
-      ret = gnutls_openpgp_keyring_import (ring, &cred->keyring, 0);
-      if (ret < 0)
-       {
-         gnutls_assert ();
-         goto leave;
-       }
-      
-      ret = gnutls_openpgp_key_verify_ring (key, ring, 0, &verify_ring);
+      ret = gnutls_openpgp_key_verify_ring (key, cred->keyring, 0, &verify);
       if (ret < 0)
        {
          gnutls_assert ();
@@ -107,17 +91,16 @@ _gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t cred,
       goto leave;
     }
 
-  *status = verify_self | verify_ring | verify_db;
+  *status = verify_self | verify;
 
   /* If we only checked the self signature. */
-  if (!cred->keyring.data)
+  if (!cred->keyring)
     *status |= GNUTLS_CERT_SIGNER_NOT_FOUND;
 
   ret = 0;
 
 leave:
   gnutls_openpgp_key_deinit (key);
-  gnutls_openpgp_keyring_deinit (ring);
 
   return ret;
 }
@@ -145,7 +128,7 @@ _gnutls_openpgp_fingerprint (const gnutls_datum_t * cert,
       return ret;
     }
 
-  ret = gnutls_openpgp_key_import (key, cert, 0);
+  ret = gnutls_openpgp_key_import (key, cert, GNUTLS_OPENPGP_FMT_RAW);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -183,7 +166,7 @@ _gnutls_openpgp_get_raw_key_creation_time (const gnutls_datum_t * cert)
       return ret;
     }
 
-  ret = gnutls_openpgp_key_import (key, cert, 0);
+  ret = gnutls_openpgp_key_import (key, cert, GNUTLS_OPENPGP_FMT_RAW);
   if (ret < 0)
     {
       gnutls_assert ();
@@ -219,7 +202,7 @@ _gnutls_openpgp_get_raw_key_expiration_time (const gnutls_datum_t * cert)
       return ret;
     }
 
-  ret = gnutls_openpgp_key_import (key, cert, 0);
+  ret = gnutls_openpgp_key_import (key, cert, GNUTLS_OPENPGP_FMT_RAW);
   if (ret < 0)
     {
       gnutls_assert ();
index 790359ecadd6b80dc861efdd8dd7d0204b2db4a2..8d07de304e966494586c96ace368f0f9640185bf 100644 (file)
@@ -52,7 +52,7 @@ gnutls_certificate_set_openpgp_keyring_mem (gnutls_certificate_credentials_t
                                            size_t dlen);
 
 int gnutls_openpgp_get_key (gnutls_datum_t * key,
-                           const gnutls_datum_t * keyring,
+                           gnutls_openpgp_keyring_t keyring,
                            key_attr_t by, opaque * pattern);
 
 int gnutls_openpgp_recv_key (const char *host,
index 5d1af3f4040750813ddac5552cfffd72ad188eba..5712d3313bba9b0cac0744651b32bf23a9250054 100644 (file)
@@ -79,12 +79,14 @@ gnutls_openpgp_key_verify_ring (gnutls_openpgp_key_t key,
       gnutls_assert ();
       return rc;
     }
-  else if (rc)
+  else if (rc != CDK_Success)
     {
+      _gnutls_x509_log("cdk_pk_check_sigs: error %d\n", rc);
       rc = _gnutls_map_cdk_rc (rc);
       gnutls_assert ();
       return rc;
     }
+  _gnutls_x509_log("status: %x\n", status);
 
   if (status & CDK_KEY_INVALID)
     *verify |= GNUTLS_CERT_INVALID;