]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Fixes in openpgp handshake with fingerprints. Reported by Joke de Buhr.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 21 Mar 2013 16:50:09 +0000 (17:50 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 21 Mar 2013 16:51:59 +0000 (17:51 +0100)
NEWS
lib/abstract_int.h
lib/auth/cert.c
lib/gnutls_pubkey.c
lib/includes/gnutls/abstract.h
lib/includes/gnutls/openpgp.h
lib/openpgp/gnutls_openpgp.c

diff --git a/NEWS b/NEWS
index 02b8e0343a254f5afe4181db5cf1e3f92377ee18..c09ccfdf8876773f32bf30105c0b8ad3edd183e6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -23,6 +23,9 @@ cards are present.
 ** libgnutls: Corrected issue in the (deprecated) external key
 signing interface, when used with TLS 1.2. Reported by Bjorn H. Christensen.
 
+** libgnutls: Fixes in openpgp handshake with fingerprints. Reported by 
+Joke de Buhr.
+
 ** libgnutls-dane: Updated DANE verification options.
 
 ** configure: Trust store file must be explicitly set or unset when 
index ae7af940c5bedfd67cd96140b3a24a94ced0153e..00141a222e5e80eee87436b2ad9aa468a1fb2ed7 100644 (file)
@@ -67,8 +67,13 @@ struct gnutls_pubkey_st
    */
   gnutls_pk_params_st params;
 
+#ifdef ENABLE_OPENPGP
   uint8_t openpgp_key_id[GNUTLS_OPENPGP_KEYID_SIZE];
-  int openpgp_key_id_set;
+  unsigned int openpgp_key_id_set;
+
+  uint8_t openpgp_key_fpr[GNUTLS_OPENPGP_V4_FINGERPRINT_SIZE];
+  unsigned int openpgp_key_fpr_set:1;
+#endif
 
   unsigned int key_usage;       /* bits from GNUTLS_KEY_* */
   
index 77538eb4ec2c9418eae86ed00c7ece3e1d8181c2..0d57048063e38baffc8ac55c6f0ecc61d2ac7e7a 100644 (file)
@@ -935,7 +935,9 @@ _gnutls_gen_openpgp_certificate_fpr (gnutls_session_t session,
 {
   int ret, packet_size;
   uint8_t type, fpr[20];
-  size_t fpr_size;
+  uint8_t id[20];
+  unsigned int subkey;
+  size_t fpr_size, id_size;
   gnutls_pcert_st *apr_cert_list;
   gnutls_privkey_t apr_pkey;
   int apr_cert_list_length;
@@ -949,10 +951,21 @@ _gnutls_gen_openpgp_certificate_fpr (gnutls_session_t session,
       return ret;
     }
 
+  if (apr_cert_list_length <= 0)
+    return _gnutls_gen_openpgp_certificate (session, data);
+
+  id_size = sizeof (id);
+  ret =
+    gnutls_pubkey_get_openpgp_key_id (apr_cert_list[0].pubkey, 0, id,
+                                      &id_size, &subkey);
+  if (ret < 0)
+    return gnutls_assert_val (ret);
+
   fpr_size = sizeof (fpr);
   ret =
-    gnutls_pubkey_get_openpgp_key_id (apr_cert_list[0].pubkey, 0, fpr,
-                                      &fpr_size, NULL);
+    gnutls_pubkey_get_openpgp_key_id (apr_cert_list[0].pubkey, 
+                                       GNUTLS_PUBKEY_GET_OPENPGP_FINGERPRINT, 
+                                       fpr, &fpr_size, NULL);
   if (ret < 0)
     return gnutls_assert_val (ret);
 
@@ -961,10 +974,7 @@ _gnutls_gen_openpgp_certificate_fpr (gnutls_session_t session,
 
   /* Only v4 fingerprints are sent 
    */
-  if (apr_cert_list_length > 0)
-    packet_size += 20 + 1;
-  else                          /* empty certificate case */
-    return _gnutls_gen_openpgp_certificate (session, data);
+  packet_size += 20 + 1;
 
   ret = _gnutls_buffer_append_prefix (data, 24, packet_size - 3);
   if (ret < 0)
@@ -975,6 +985,10 @@ _gnutls_gen_openpgp_certificate_fpr (gnutls_session_t session,
   if (ret < 0)
     return gnutls_assert_val (ret);
 
+  ret = _gnutls_buffer_append_data_prefix (data, 8, id, id_size);
+  if (ret < 0)
+    return gnutls_assert_val (ret);
+
   ret = _gnutls_buffer_append_data_prefix (data, 8, fpr, fpr_size);
   if (ret < 0)
     return gnutls_assert_val (ret);
index d8e44afe7bf3cea037ddb92003c8c1126b67c36b..f11cc5e5e4cbfdc29c6983d512f11ddd63a5b5e1 100644 (file)
@@ -400,6 +400,13 @@ gnutls_pubkey_import_openpgp (gnutls_pubkey_t key,
   uint32_t kid32[2];
   uint32_t *k;
   uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
+  size_t len;
+
+  len = sizeof(key->openpgp_key_fpr);
+  ret = gnutls_openpgp_crt_get_fingerprint(crt, key->openpgp_key_fpr, &len);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
+  key->openpgp_key_fpr_set = 1;
 
   ret = gnutls_openpgp_crt_get_preferred_key_id (crt, keyid);
   if (ret == GNUTLS_E_OPENPGP_PREFERRED_KEY_ERROR)
@@ -453,16 +460,19 @@ gnutls_pubkey_import_openpgp (gnutls_pubkey_t key,
 /**
  * gnutls_pubkey_get_openpgp_key_id:
  * @key: Holds the public key
- * @flags: should be 0 for now
+ * @flags: should be 0 or %GNUTLS_PUBKEY_GET_OPENPGP_FINGERPRINT
  * @output_data: will contain the key ID
  * @output_data_size: holds the size of output_data (and will be
  *   replaced by the actual size of parameters)
  * @subkey: Will be non zero if the key ID corresponds to a subkey
  *
- * This function returned the OpenPGP key ID of the corresponding key.
+ * This function returns the OpenPGP key ID of the corresponding key.
  * The key is a unique ID that depends on the public
  * key parameters. 
  *
+ * If the flag %GNUTLS_PUBKEY_GET_OPENPGP_FINGERPRINT is specified
+ * this function returns the fingerprint of the master key.
+ *
  * If the buffer provided is not long enough to hold the output, then
  * *output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER will
  * be returned.  The output is %GNUTLS_OPENPGP_KEYID_SIZE bytes long.
@@ -484,6 +494,24 @@ gnutls_pubkey_get_openpgp_key_id (gnutls_pubkey_t key, unsigned int flags,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
+  if (flags & GNUTLS_PUBKEY_GET_OPENPGP_FINGERPRINT)
+    {
+      if (*output_data_size < sizeof(key->openpgp_key_fpr))
+        {
+          *output_data_size = sizeof(key->openpgp_key_fpr);
+          return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+        }
+
+      if (key->openpgp_key_fpr_set == 0)
+        return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+      if (output_data)
+        memcpy(output_data, key->openpgp_key_fpr, sizeof(key->openpgp_key_fpr));
+      *output_data_size = sizeof(key->openpgp_key_fpr);
+      
+      return 0;
+    }
+    
   if (*output_data_size < sizeof(key->openpgp_key_id))
     {
       *output_data_size = sizeof(key->openpgp_key_id);
index 5bcc5aca53e43514d7be394e2a6ecfcde5c7d1a5..6c121b3acc8f079c0e275fd248669a68b73cd503 100644 (file)
@@ -36,6 +36,13 @@ extern "C"
 
 /* Public key operations */
 
+#define GNUTLS_PUBKEY_VERIFY_FLAG_TLS_RSA 1
+/* The following flag disables call to PIN callbacks etc.
+ * Only works for TPM keys.
+ */
+#define GNUTLS_PUBKEY_DISABLE_CALLBACKS (1<<2)
+#define GNUTLS_PUBKEY_GET_OPENPGP_FINGERPRINT (1<<3)
+
 struct gnutls_pubkey_st;
 typedef struct gnutls_pubkey_st *gnutls_pubkey_t;
 
@@ -175,11 +182,6 @@ int gnutls_x509_crt_set_pubkey (gnutls_x509_crt_t crt, gnutls_pubkey_t key);
 
 int gnutls_x509_crq_set_pubkey (gnutls_x509_crq_t crq, gnutls_pubkey_t key);
 
-#define GNUTLS_PUBKEY_VERIFY_FLAG_TLS_RSA 1
-/* The following flag disables call to PIN callbacks etc.
- * Only works for TPM keys.
- */
-#define GNUTLS_PUBKEY_DISABLE_CALLBACKS (1<<2)
 int
 gnutls_pubkey_verify_hash2 (gnutls_pubkey_t key, 
                             gnutls_sign_algorithm_t algo,
index bc6b3f13d42b11ecdc3b74053c5e733c8e18d2aa..e87e2d307f9a03da18d77f04b7a88c0f6d6e36dd 100644 (file)
@@ -52,6 +52,7 @@ extern "C"
   } gnutls_openpgp_crt_fmt_t;
 
 #define GNUTLS_OPENPGP_KEYID_SIZE 8
+#define GNUTLS_OPENPGP_V4_FINGERPRINT_SIZE 20
   typedef unsigned char gnutls_openpgp_keyid_t[GNUTLS_OPENPGP_KEYID_SIZE];
 
 /* gnutls_openpgp_cert_t should be defined in gnutls.h
@@ -310,6 +311,8 @@ extern "C"
  * fingerprint instead of a full key.  See also
  * gnutls_openpgp_set_recv_key_function().
  *
+ * The variable @key must be allocated using gnutls_malloc().
+ *
  * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
  *   otherwise an error code is returned.
  */
index 6ca59e37a9ad1817271db8da2bfde2a1efd6c3ac..cbc0da7a980da246a2e9e793799b186e76939b2a 100644 (file)
@@ -686,6 +686,8 @@ error:
  * callback is only useful in server side, and will be used if the peer
  * sent a key fingerprint instead of a full key.
  *
+ * The retrieved key must be allocated using gnutls_malloc().
+ *
  **/
 void
 gnutls_openpgp_set_recv_key_function (gnutls_session_t session,