summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2013-03-21 17:50:09 +0100
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2013-03-21 17:59:02 +0100
commit26c8c8ed8bd6d7f1848adf59f6cf0371c3c6232b (patch)
treefd193d81a9610e96bdec14ed59fcfe7bac863211
parent2f28a301dcda092626833b58ba95ebc2187bebb6 (diff)
downloadgnutls-26c8c8ed8bd6d7f1848adf59f6cf0371c3c6232b.tar.gz
Fixes in openpgp handshake with fingerprints. Reported by Joke de Buhr.
-rw-r--r--NEWS3
-rw-r--r--lib/auth/cert.c28
-rw-r--r--lib/gnutls_pubkey.c41
-rw-r--r--lib/includes/gnutls/abstract.h7
-rw-r--r--lib/includes/gnutls/openpgp.h3
-rw-r--r--lib/openpgp/gnutls_openpgp.c2
6 files changed, 72 insertions, 12 deletions
diff --git a/NEWS b/NEWS
index d3a8dcd713..ca936a5037 100644
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,9 @@ signing interface, when used with TLS 1.2. Reported by Bjorn H. Christensen.
on initialization. This speeds up gnutls initialization when smart
cards are present.
+** libgnutls: Fixes in openpgp handshake with fingerprints. Reported by
+Joke de Buhr.
+
** configure: Trust store file must be explicitly set or unset when
cross compiling.
diff --git a/lib/auth/cert.c b/lib/auth/cert.c
index 3e10051df3..2ff0cc00ff 100644
--- a/lib/auth/cert.c
+++ b/lib/auth/cert.c
@@ -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);
diff --git a/lib/gnutls_pubkey.c b/lib/gnutls_pubkey.c
index 5d0270b7d0..941ac934d3 100644
--- a/lib/gnutls_pubkey.c
+++ b/lib/gnutls_pubkey.c
@@ -57,8 +57,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[20];
+ unsigned int openpgp_key_fpr_set:1;
+#endif
unsigned int key_usage; /* bits from GNUTLS_KEY_* */
};
@@ -349,6 +354,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)
@@ -402,16 +414,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.
- * The key is a unique ID the depends on the public
+ * 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.
@@ -433,6 +448,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);
diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h
index 50c1ecac35..e9b0e0fa23 100644
--- a/lib/includes/gnutls/abstract.h
+++ b/lib/includes/gnutls/abstract.h
@@ -36,6 +36,12 @@ 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_GET_OPENPGP_FINGERPRINT (1<<3)
+
struct gnutls_pubkey_st;
typedef struct gnutls_pubkey_st *gnutls_pubkey_t;
@@ -135,7 +141,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
int
gnutls_pubkey_verify_hash (gnutls_pubkey_t key, unsigned int flags,
const gnutls_datum_t * hash,
diff --git a/lib/includes/gnutls/openpgp.h b/lib/includes/gnutls/openpgp.h
index b53b165484..4c0dbf87f2 100644
--- a/lib/includes/gnutls/openpgp.h
+++ b/lib/includes/gnutls/openpgp.h
@@ -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
@@ -302,6 +303,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.
*/
diff --git a/lib/openpgp/gnutls_openpgp.c b/lib/openpgp/gnutls_openpgp.c
index 7065bf2af4..99e2c4ed43 100644
--- a/lib/openpgp/gnutls_openpgp.c
+++ b/lib/openpgp/gnutls_openpgp.c
@@ -681,6 +681,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,