summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2007-10-15 01:00:28 +0300
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2007-10-15 01:00:28 +0300
commit3512501e6dc6717a3bb70ba878dd892b253e2dcd (patch)
tree70f6c2b06dd6d1383af0aafeb69e5ed360015db3
parent575dc4cd9f78a7a04f5408af4e51fd89f6dd7cc8 (diff)
downloadgnutls-3512501e6dc6717a3bb70ba878dd892b253e2dcd.tar.gz
** Corrected bugs in the openpgp certificate verification functions using a keyring.
Now it correctly verifies openpgp certificates. ** Removed the ancient pgpkeyserver support (which was not used anywhere)
-rw-r--r--NEWS8
-rw-r--r--configure.in10
-rw-r--r--lib/auth_cert.h6
-rw-r--r--lib/gnutls_cert.c4
-rw-r--r--lib/gnutls_errors.c2
-rw-r--r--lib/gnutls_extra_hooks.c25
-rw-r--r--lib/gnutls_extra_hooks.h5
-rw-r--r--libextra/gnutls_extra.c1
-rw-r--r--libextra/gnutls_openpgp.c204
-rw-r--r--libextra/opencdk/main.h36
-rw-r--r--libextra/opencdk/sig-check.c111
-rw-r--r--libextra/openpgp/compat.c35
-rw-r--r--libextra/openpgp/gnutls_openpgp.h2
-rw-r--r--libextra/openpgp/pgpverify.c4
14 files changed, 172 insertions, 281 deletions
diff --git a/NEWS b/NEWS
index f87aa8ba7c..e9b6ec39ce 100644
--- 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.
diff --git a/configure.in b/configure.in
index 93c152be6a..0b1b435cef 100644
--- a/configure.in
+++ b/configure.in
@@ -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([[
diff --git a/lib/auth_cert.h b/lib/auth_cert.h
index 778a3e18b0..c385822182 100644
--- a/lib/auth_cert.h
+++ b/lib/auth_cert.h
@@ -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 */
diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c
index b22d8a113a..c1281a24ab 100644
--- a/lib/gnutls_cert.c
+++ b/lib/gnutls_cert.c
@@ -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);
}
diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c
index 2c8afd4038..62203b3100 100644
--- a/lib/gnutls_errors.c
+++ b/lib/gnutls_errors.c
@@ -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),
diff --git a/lib/gnutls_extra_hooks.c b/lib/gnutls_extra_hooks.c
index f2bfb3f25f..1b3484c7a0 100644
--- a/lib/gnutls_extra_hooks.c
+++ b/lib/gnutls_extra_hooks.c
@@ -28,19 +28,20 @@
/* 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;
}
diff --git a/lib/gnutls_extra_hooks.h b/lib/gnutls_extra_hooks.h
index 1469790304..4ef8bb4cda 100644
--- a/lib/gnutls_extra_hooks.h
+++ b/lib/gnutls_extra_hooks.h
@@ -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);
diff --git a/libextra/gnutls_extra.c b/libextra/gnutls_extra.c
index 7471fca935..6dbb79e4bf 100644
--- a/libextra/gnutls_extra.c
+++ b/libextra/gnutls_extra.c
@@ -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;
diff --git a/libextra/gnutls_openpgp.c b/libextra/gnutls_openpgp.c
index 5b3c2415ac..0b9ec2d232 100644
--- a/libextra/gnutls_openpgp.c
+++ b/libextra/gnutls_openpgp.c
@@ -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
diff --git a/libextra/opencdk/main.h b/libextra/opencdk/main.h
index 73c4b8d3a4..3e9a443d8f 100644
--- a/libextra/opencdk/main.h
+++ b/libextra/opencdk/main.h
@@ -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);
diff --git a/libextra/opencdk/sig-check.c b/libextra/opencdk/sig-check.c
index 75f63a51d9..948fe2993b 100644
--- a/libextra/opencdk/sig-check.c
+++ b/libextra/opencdk/sig-check.c
@@ -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;
}
diff --git a/libextra/openpgp/compat.c b/libextra/openpgp/compat.c
index ba4b7614bd..e98b8d1f60 100644
--- a/libextra/openpgp/compat.c
+++ b/libextra/openpgp/compat.c
@@ -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 ();
diff --git a/libextra/openpgp/gnutls_openpgp.h b/libextra/openpgp/gnutls_openpgp.h
index 790359ecad..8d07de304e 100644
--- a/libextra/openpgp/gnutls_openpgp.h
+++ b/libextra/openpgp/gnutls_openpgp.h
@@ -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,
diff --git a/libextra/openpgp/pgpverify.c b/libextra/openpgp/pgpverify.c
index 5d1af3f404..5712d3313b 100644
--- a/libextra/openpgp/pgpverify.c
+++ b/libextra/openpgp/pgpverify.c
@@ -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;