summaryrefslogtreecommitdiff
path: root/lib/openpgp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/openpgp')
-rw-r--r--lib/openpgp/Makefile.am50
-rw-r--r--lib/openpgp/compat.c247
-rw-r--r--lib/openpgp/extras.c172
-rw-r--r--lib/openpgp/gnutls_openpgp.h99
-rw-r--r--lib/openpgp/openpgp.h107
-rw-r--r--lib/openpgp/output.c402
-rw-r--r--lib/openpgp/pgp.c1079
-rw-r--r--lib/openpgp/pgpverify.c144
-rw-r--r--lib/openpgp/privkey.c575
9 files changed, 2875 insertions, 0 deletions
diff --git a/lib/openpgp/Makefile.am b/lib/openpgp/Makefile.am
new file mode 100644
index 0000000000..93c479ee9f
--- /dev/null
+++ b/lib/openpgp/Makefile.am
@@ -0,0 +1,50 @@
+## Process this file with automake to produce Makefile.in
+# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
+#
+# Author: Nikos Mavrogiannopoulos
+#
+# This file is part of GNUTLS-EXTRA.
+#
+# GNUTLS-EXTRA is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3 of the
+# License, or (at your option) any later version.
+#
+# GNUTLS-EXTRA is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNUTLS-EXTRA; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+AM_CPPFLAGS = -I$(top_srcdir)/lgl -I$(top_builddir)/lgl \
+ -I$(top_srcdir)/crypto -I$(top_srcdir)/lib \
+ -I$(top_srcdir)/includes -I../../includes \
+ -I$(top_srcdir)/lib/opencdk
+
+if ENABLE_MINITASN1
+AM_CPPFLAGS += -I$(top_srcdir)/lib/minitasn1
+else
+AM_CPPFLAGS += $(LIBTASN1_CFLAGS)
+endif
+
+noinst_LTLIBRARIES = libgnutls_openpgp.la
+
+COBJECTS = pgp.c pgpverify.c extras.c compat.c privkey.c output.c
+
+libgnutls_openpgp_la_SOURCES = $(COBJECTS) openpgp.h gnutls_openpgp.h
+
+EXTRA_DIST = pgp-api.texi
+
+pgp-api.texi: $(COBJECTS)
+ @echo "" > pgp-api.texi
+ @for i in ../gnutls_openpgp.c $(COBJECTS); do \
+ echo -n "Creating documentation for file $$i... " && \
+ $(top_srcdir)/doc/scripts/gdoc -texinfo $$i >> pgp-api.texi && \
+ echo "ok"; \
+ done
+
+dist-hook: pgp-api.texi
diff --git a/lib/openpgp/compat.c b/lib/openpgp/compat.c
new file mode 100644
index 0000000000..c04d861ab7
--- /dev/null
+++ b/lib/openpgp/compat.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Timo Schulz, Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS-EXTRA.
+ *
+ * GNUTLS-EXTRA is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNUTLS-EXTRA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Compatibility functions on OpenPGP key parsing.
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_openpgp.h>
+#include <openpgp.h>
+
+/*-
+ * gnutls_openpgp_verify_key - Verify all signatures on the key
+ * @cert_list: the structure that holds the certificates.
+ * @cert_list_lenght: the items in the cert_list.
+ * @status: the output of the verification function
+ *
+ * Verify all signatures in the certificate list. When the key
+ * is not available, the signature is skipped.
+ *
+ * The return value is one of the CertificateStatus entries.
+ *
+ * NOTE: this function does not verify using any "web of trust". You
+ * may use GnuPG for that purpose, or any other external PGP application.
+ -*/
+int
+_gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t cred,
+ const gnutls_datum_t * cert_list,
+ int cert_list_length, unsigned int *status)
+{
+ int ret = 0;
+ gnutls_openpgp_crt_t key = NULL;
+ unsigned int verify = 0, verify_self = 0;
+
+ if (!cert_list || cert_list_length != 1)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_NO_CERTIFICATE_FOUND;
+ }
+
+ ret = gnutls_openpgp_crt_init (&key);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ return ret;
+ }
+
+ ret = gnutls_openpgp_crt_import (key, &cert_list[0], GNUTLS_OPENPGP_FMT_RAW);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ goto leave;
+ }
+
+#ifndef KEYRING_HACK
+ if (cred->keyring != NULL)
+ {
+ ret = gnutls_openpgp_crt_verify_ring (key, cred->keyring, 0, &verify);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ goto leave;
+ }
+ }
+#else
+ {
+ gnutls_openpgp_keyring_t kring;
+
+ ret = gnutls_openpgp_keyring_init( &kring);
+ if ( ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ ret = gnutls_openpgp_keyring_import( kring, &cred->keyring, cred->keyring_format);
+ if ( ret < 0) {
+ gnutls_assert();
+ gnutls_openpgp_keyring_deinit( kring);
+ return ret;
+ }
+
+ ret = gnutls_openpgp_crt_verify_ring (key, kring, 0, &verify);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ gnutls_openpgp_keyring_deinit( kring);
+ return ret;
+ }
+ gnutls_openpgp_keyring_deinit( kring);
+ }
+#endif
+
+ /* Now try the self signature. */
+ ret = gnutls_openpgp_crt_verify_self (key, 0, &verify_self);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ goto leave;
+ }
+
+ *status = verify_self | verify;
+
+#ifndef KEYRING_HACK
+ /* If we only checked the self signature. */
+ if (!cred->keyring)
+#else
+ if (!cred->keyring.data || !cred->keyring.size)
+#endif
+ *status |= GNUTLS_CERT_SIGNER_NOT_FOUND;
+
+
+ ret = 0;
+
+leave:
+ gnutls_openpgp_crt_deinit (key);
+
+ return ret;
+}
+
+/*-
+ * gnutls_openpgp_fingerprint - Gets the fingerprint
+ * @cert: the raw data that contains the OpenPGP public key.
+ * @fpr: the buffer to save the fingerprint.
+ * @fprlen: the integer to save the length of the fingerprint.
+ *
+ * Returns the fingerprint of the OpenPGP key. Depence on the algorithm,
+ * the fingerprint can be 16 or 20 bytes.
+ -*/
+int
+_gnutls_openpgp_fingerprint (const gnutls_datum_t * cert,
+ unsigned char *fpr, size_t * fprlen)
+{
+ gnutls_openpgp_crt_t key;
+ int ret;
+
+ ret = gnutls_openpgp_crt_init (&key);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ return ret;
+ }
+
+ ret = gnutls_openpgp_crt_import (key, cert, GNUTLS_OPENPGP_FMT_RAW);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ return ret;
+ }
+
+ ret = gnutls_openpgp_crt_get_fingerprint (key, fpr, fprlen);
+ gnutls_openpgp_crt_deinit (key);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ return ret;
+ }
+
+ return 0;
+}
+
+/*-
+ * gnutls_openpgp_get_raw_key_creation_time - Extract the timestamp
+ * @cert: the raw data that contains the OpenPGP public key.
+ *
+ * Returns the timestamp when the OpenPGP key was created.
+ -*/
+time_t
+_gnutls_openpgp_get_raw_key_creation_time (const gnutls_datum_t * cert)
+{
+ gnutls_openpgp_crt_t key;
+ int ret;
+ time_t tim;
+
+ ret = gnutls_openpgp_crt_init (&key);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ return ret;
+ }
+
+ ret = gnutls_openpgp_crt_import (key, cert, GNUTLS_OPENPGP_FMT_RAW);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ return ret;
+ }
+
+ tim = gnutls_openpgp_crt_get_creation_time (key);
+
+ gnutls_openpgp_crt_deinit (key);
+
+ return tim;
+}
+
+
+/*-
+ * gnutls_openpgp_get_raw_key_expiration_time - Extract the expire date
+ * @cert: the raw data that contains the OpenPGP public key.
+ *
+ * Returns the time when the OpenPGP key expires. A value of '0' means
+ * that the key doesn't expire at all.
+ -*/
+time_t
+_gnutls_openpgp_get_raw_key_expiration_time (const gnutls_datum_t * cert)
+{
+ gnutls_openpgp_crt_t key;
+ int ret;
+ time_t tim;
+
+ ret = gnutls_openpgp_crt_init (&key);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ return ret;
+ }
+
+ ret = gnutls_openpgp_crt_import (key, cert, GNUTLS_OPENPGP_FMT_RAW);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ return ret;
+ }
+
+ tim = gnutls_openpgp_crt_get_expiration_time (key);
+
+ gnutls_openpgp_crt_deinit (key);
+
+ return tim;
+}
diff --git a/lib/openpgp/extras.c b/lib/openpgp/extras.c
new file mode 100644
index 0000000000..2ce4ce256d
--- /dev/null
+++ b/lib/openpgp/extras.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos, Timo Schulz
+ *
+ * This file is part of GNUTLS-EXTRA.
+ *
+ * GNUTLS-EXTRA is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNUTLS-EXTRA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Functions on OpenPGP keyring parsing
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_datum.h>
+#include <gnutls_global.h>
+#include <gnutls_errors.h>
+#include <gnutls_openpgp.h>
+#include <gnutls_num.h>
+#include <openpgp.h>
+
+/* Keyring stuff.
+ */
+
+/**
+ * gnutls_openpgp_keyring_init - This function initializes a gnutls_openpgp_keyring_t structure
+ * @keyring: The structure to be initialized
+ *
+ * This function will initialize an OpenPGP keyring structure.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int
+gnutls_openpgp_keyring_init (gnutls_openpgp_keyring_t * keyring)
+{
+ *keyring = gnutls_calloc (1, sizeof (gnutls_openpgp_keyring_int));
+
+ if (*keyring)
+ return 0; /* success */
+ return GNUTLS_E_MEMORY_ERROR;
+}
+
+
+/**
+ * gnutls_openpgp_keyring_deinit - This function deinitializes memory used by a gnutls_openpgp_keyring_t structure
+ * @keyring: The structure to be initialized
+ *
+ * This function will deinitialize a keyring structure.
+ *
+ **/
+void
+gnutls_openpgp_keyring_deinit (gnutls_openpgp_keyring_t keyring)
+{
+ if (!keyring)
+ return;
+
+ if (keyring->db)
+ {
+ cdk_keydb_free (keyring->db);
+ keyring->db = NULL;
+ }
+
+ /* In some cases the stream is also stored outside the keydb context
+ and we need to close it here then. */
+ if (keyring->db_stream)
+ {
+ cdk_stream_close (keyring->db_stream);
+ keyring->db_stream = NULL;
+ }
+
+ gnutls_free (keyring);
+}
+
+/**
+ * gnutls_openpgp_keyring_check_id - Check if a key id exists in the keyring
+ * @ring: holds the keyring to check against
+ * @keyid: will hold the keyid to check for.
+ * @flags: unused (should be 0)
+ *
+ * Check if a given key ID exists in the keyring.
+ *
+ * Returns 0 on success (if keyid exists) and a negative error code
+ * on failure.
+ **/
+int
+gnutls_openpgp_keyring_check_id (gnutls_openpgp_keyring_t ring,
+ gnutls_openpgp_keyid_t keyid,
+ unsigned int flags)
+{
+ cdk_pkt_pubkey_t pk;
+ uint32_t id[2];
+
+ id[0] = _gnutls_read_uint32 (keyid.keyid);
+ id[1] = _gnutls_read_uint32 (&keyid.keyid[4]);
+
+ if (!cdk_keydb_get_pk (ring->db, id, &pk))
+ {
+ cdk_pk_release (pk);
+ return 0;
+ }
+
+ _gnutls_debug_log ("PGP: key not found %08lX\n", (unsigned long)id[1]);
+ return GNUTLS_E_NO_CERTIFICATE_FOUND;
+}
+
+/**
+ * gnutls_openpgp_keyring_import - Import a raw- or Base64-encoded OpenPGP keyring
+ * @keyring: The structure to store the parsed key.
+ * @data: The RAW or BASE64 encoded keyring.
+ * @format: One of #gnutls_openpgp_keyring_fmt elements.
+ *
+ * This function will convert the given RAW or Base64 encoded keyring to the
+ * native #gnutls_openpgp_keyring_t format. The output will be stored in
+ * 'keyring'.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int
+gnutls_openpgp_keyring_import (gnutls_openpgp_keyring_t keyring,
+ const gnutls_datum_t *data,
+ gnutls_openpgp_crt_fmt_t format)
+{
+ cdk_error_t err;
+ cdk_stream_t input;
+
+ _gnutls_debug_log ("PGP: keyring import format '%s'\n",
+ format == GNUTLS_OPENPGP_FMT_RAW? "raw" : "base64");
+
+ if (format == GNUTLS_OPENPGP_FMT_RAW)
+ {
+ err = cdk_keydb_new (&keyring->db, CDK_DBTYPE_DATA,
+ data->data, data->size);
+ if (err)
+ gnutls_assert ();
+ return _gnutls_map_cdk_rc (err);
+ }
+
+ /* Create a new stream from the given data, which means to
+ allocate a new stream and to write the data in the stream.
+ Then push the armor filter to decode the data and to store
+ it in the raw format. */
+ err = cdk_stream_tmp_from_mem (data->data, data->size, &input);
+ if (!err)
+ err = cdk_stream_set_armor_flag (input, 0);
+ if (!err)
+ err = cdk_keydb_new_from_stream (&keyring->db, 0, input);
+ if (err)
+ {
+ cdk_stream_close (input);
+ gnutls_assert ();
+ }
+ else
+ /* The keydb function will not close the stream itself, so we need to
+ store it separately to close it later. */
+ keyring->db_stream = input;
+
+ return _gnutls_map_cdk_rc (err);
+}
+
diff --git a/lib/openpgp/gnutls_openpgp.h b/lib/openpgp/gnutls_openpgp.h
new file mode 100644
index 0000000000..067de99831
--- /dev/null
+++ b/lib/openpgp/gnutls_openpgp.h
@@ -0,0 +1,99 @@
+#include <config.h>
+
+#ifdef ENABLE_OPENPGP
+
+#ifndef GNUTLS_OPENPGP_LOCAL_H
+#define GNUTLS_OPENPGP_LOCAL_H
+
+#include <auth_cert.h>
+#include <opencdk.h>
+
+typedef struct
+{
+ int type;
+ size_t size;
+ uint8_t *data;
+} keybox_blob;
+
+typedef enum
+{
+ KBX_BLOB_FILE = 0x00,
+ KBX_BLOB_DATA = 0x01
+} keyring_blob_types;
+
+/* OpenCDK compatible */
+typedef enum
+{
+ KEY_ATTR_NONE = 0,
+ KEY_ATTR_SHORT_KEYID = 3,
+ KEY_ATTR_KEYID = 4,
+ KEY_ATTR_FPR = 5
+} key_attr_t;
+
+int
+gnutls_certificate_set_openpgp_key_file (gnutls_certificate_credentials_t
+ res, const char *CERTFILE,
+ const char *KEYFILE, gnutls_openpgp_crt_fmt_t);
+
+int gnutls_openpgp_count_key_names (const gnutls_datum_t * cert);
+
+int gnutls_certificate_set_openpgp_keyring_file
+ (gnutls_certificate_credentials_t c, const char *file, gnutls_openpgp_crt_fmt_t);
+
+int
+gnutls_certificate_set_openpgp_keyring_mem (gnutls_certificate_credentials_t
+ c, const opaque * data,
+ size_t dlen, gnutls_openpgp_crt_fmt_t);
+
+int gnutls_openpgp_get_key (gnutls_datum_t * key,
+ gnutls_openpgp_keyring_t keyring,
+ key_attr_t by, opaque * pattern);
+
+int gnutls_openpgp_recv_key (const char *host,
+ short port, uint32_t keyid,
+ gnutls_datum_t * key);
+
+/* internal */
+int _gnutls_openpgp_raw_crt_to_gcert (gnutls_cert * cert,
+ const gnutls_datum_t * raw);
+
+int
+_gnutls_openpgp_raw_privkey_to_gkey (gnutls_privkey * pkey,
+ const gnutls_datum_t * raw_key);
+
+int
+_gnutls_openpgp_request_key (gnutls_session_t,
+ gnutls_datum_t * ret,
+ const gnutls_certificate_credentials_t cred,
+ opaque * key_fpr, int key_fpr_size);
+
+int _gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t,
+ const gnutls_datum_t * cert_list,
+ int cert_list_length, unsigned int *status);
+int _gnutls_openpgp_fingerprint (const gnutls_datum_t * cert,
+ unsigned char *fpr, size_t * fprlen);
+time_t _gnutls_openpgp_get_raw_key_creation_time (const gnutls_datum_t *
+ cert);
+time_t _gnutls_openpgp_get_raw_key_expiration_time (const gnutls_datum_t *
+ cert);
+
+int
+gnutls_openpgp_privkey_init (gnutls_openpgp_privkey_t * key);
+
+int
+gnutls_openpgp_privkey_init (gnutls_openpgp_privkey_t * key);
+
+void
+gnutls_openpgp_privkey_deinit (gnutls_openpgp_privkey_t key);
+
+int
+gnutls_openpgp_privkey_import (gnutls_openpgp_privkey_t key,
+ const gnutls_datum_t * data,
+ gnutls_openpgp_crt_fmt_t format,
+ const char *pass, unsigned int flags);
+
+int _gnutls_openpgp_find_valid_subkey( gnutls_openpgp_crt_t crt, gnutls_openpgp_keyid_t* keyid);
+
+#endif /*GNUTLS_OPENPGP_LOCAL_H */
+
+#endif /*ENABLE_OPENPGP */
diff --git a/lib/openpgp/openpgp.h b/lib/openpgp/openpgp.h
new file mode 100644
index 0000000000..3ec9ba9111
--- /dev/null
+++ b/lib/openpgp/openpgp.h
@@ -0,0 +1,107 @@
+#ifndef OPENPGP_LOCAL_H
+# define OPENPGP_LOCAL_H
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef ENABLE_OPENPGP
+
+#include <opencdk.h>
+#include <gnutls/openpgp.h>
+
+#define KEYID_IMPORT(dst, src) \
+ dst[0] = _gnutls_read_uint32( src.keyid); \
+ dst[1] = _gnutls_read_uint32( src.keyid+4)
+
+/* Internal context to store the OpenPGP key. */
+typedef struct gnutls_openpgp_crt_int
+{
+ cdk_kbnode_t knode;
+} gnutls_openpgp_crt_int;
+
+/* Internal context to store the private OpenPGP key. */
+typedef struct gnutls_openpgp_privkey_int
+{
+ cdk_kbnode_t knode;
+} gnutls_openpgp_privkey_int;
+
+
+typedef struct gnutls_openpgp_keyring_int
+{
+ cdk_keydb_hd_t db;
+ cdk_stream_t db_stream;
+} gnutls_openpgp_keyring_int;
+
+int _gnutls_map_cdk_rc (int rc);
+int gnutls_openpgp_crt_get_name (gnutls_openpgp_crt_t key,
+ int idx, char *buf, size_t * sizeof_buf);
+int gnutls_openpgp_crt_get_fingerprint (gnutls_openpgp_crt_t key,
+ void *fpr, size_t * fprlen);
+gnutls_pk_algorithm_t
+gnutls_openpgp_crt_get_pk_algorithm (gnutls_openpgp_crt_t key,
+ unsigned int *bits);
+int gnutls_openpgp_crt_get_version (gnutls_openpgp_crt_t key);
+time_t gnutls_openpgp_crt_get_creation_time (gnutls_openpgp_crt_t key);
+time_t gnutls_openpgp_crt_get_expiration_time (gnutls_openpgp_crt_t key);
+int gnutls_openpgp_crt_get_id (gnutls_openpgp_crt_t key,
+ gnutls_openpgp_keyid_t* keyid);
+
+int gnutls_openpgp_crt_init (gnutls_openpgp_crt_t * key);
+void gnutls_openpgp_crt_deinit (gnutls_openpgp_crt_t key);
+int gnutls_openpgp_crt_import (gnutls_openpgp_crt_t key,
+ const gnutls_datum_t * data,
+ gnutls_openpgp_crt_fmt_t format);
+int gnutls_openpgp_crt_export (gnutls_openpgp_crt_t key,
+ gnutls_openpgp_crt_fmt_t format,
+ void *output_data, size_t * output_data_size);
+
+void gnutls_openpgp_keyring_deinit (gnutls_openpgp_keyring_t keyring);
+int gnutls_openpgp_keyring_init (gnutls_openpgp_keyring_t * keyring);
+int gnutls_openpgp_keyring_import (gnutls_openpgp_keyring_t keyring,
+ const gnutls_datum_t * data,
+ gnutls_openpgp_crt_fmt_t format);
+int gnutls_openpgp_keyring_check_id (gnutls_openpgp_keyring_t ring,
+ gnutls_openpgp_keyid_t keyid,
+ unsigned int flags);
+
+int gnutls_openpgp_crt_verify_ring (gnutls_openpgp_crt_t key,
+ gnutls_openpgp_keyring_t keyring,
+ unsigned int flags, unsigned int *verify);
+
+int gnutls_openpgp_crt_verify_self (gnutls_openpgp_crt_t key,
+ unsigned int flags, unsigned int *verify);
+
+int _gnutls_openpgp_crt_to_gcert (gnutls_cert * gcert,
+ gnutls_openpgp_crt_t cert, gnutls_openpgp_keyid_t keyid);
+int _gnutls_openpgp_privkey_to_gkey (gnutls_privkey * dest,
+ gnutls_openpgp_privkey_t src, gnutls_openpgp_keyid_t);
+
+void gnutls_openpgp_privkey_deinit (gnutls_openpgp_privkey_t key);
+
+cdk_packet_t _gnutls_get_valid_subkey(cdk_kbnode_t knode, int key_type);
+
+unsigned int _gnutls_get_pgp_key_usage(unsigned int pgp_usage);
+
+int
+_gnutls_openpgp_crt_get_mpis (gnutls_openpgp_crt_t cert, uint32_t keyid[2],
+ mpi_t * params, int *params_size);
+
+int
+_gnutls_openpgp_privkey_get_mpis (gnutls_openpgp_privkey_t pkey, uint32_t keyid[2],
+ mpi_t * params, int *params_size);
+
+cdk_packet_t _gnutls_openpgp_find_key( cdk_kbnode_t knode, uint32_t keyid[2], unsigned int priv);
+
+int _gnutls_read_pgp_mpi( cdk_packet_t pkt, unsigned int priv, size_t idx, mpi_t* m);
+
+int _gnutls_openpgp_find_subkey_idx( cdk_kbnode_t knode, uint32_t keyid[2],
+ unsigned int priv);
+
+#else /* no opencdk */
+
+typedef void *gnutls_openpgp_keyring_t;
+
+#endif /* ENABLE_OPENPGP */
+
+#endif /* OPENPGP_LOCAL_H */
diff --git a/lib/openpgp/output.c b/lib/openpgp/output.c
new file mode 100644
index 0000000000..71b997133f
--- /dev/null
+++ b/lib/openpgp/output.c
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2007 Free Software Foundation
+ *
+ * Author: Simon Josefsson, Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+/* Functions for printing X.509 Certificate structures
+ */
+
+#include <gnutls_int.h>
+#include <gnutls/openpgp.h>
+#include <gnutls_errors.h>
+
+/* I18n of error codes. */
+#include "gettext.h"
+#define _(String) dgettext (PACKAGE, String)
+#define N_(String) gettext_noop (String)
+
+#define addf _gnutls_string_append_printf
+#define adds _gnutls_string_append_str
+
+static void
+hexdump (gnutls_string * str, const char *data, size_t len, const char *spc)
+{
+ size_t j;
+
+ if (spc)
+ adds (str, spc);
+ for (j = 0; j < len; j++)
+ {
+ if (((j + 1) % 16) == 0)
+ {
+ addf (str, "%.2x\n", (unsigned char) data[j]);
+ if (spc && j != (len - 1))
+ adds (str, spc);
+ }
+ else if (j == (len - 1))
+ addf (str, "%.2x", (unsigned char) data[j]);
+ else
+ addf (str, "%.2x:", (unsigned char) data[j]);
+ }
+ if ((j % 16) != 0)
+ adds (str, "\n");
+}
+
+static void
+hexprint (gnutls_string * str, const char *data, size_t len)
+{
+ size_t j;
+
+ if (len == 0)
+ adds (str, "00");
+ else
+ {
+ for (j = 0; j < len; j++)
+ addf (str, "%.2x", (unsigned char) data[j]);
+ }
+}
+
+
+static void
+asciiprint (gnutls_string * str, const char *data, size_t len)
+{
+ size_t j;
+
+ for (j = 0; j < len; j++)
+ if (isprint (data[j]))
+ addf (str, "%c", (unsigned char) data[j]);
+ else
+ addf (str, ".");
+}
+
+static void
+print_key_usage (gnutls_string * str, gnutls_openpgp_crt_t cert, unsigned int idx)
+{
+ unsigned int key_usage;
+ int err;
+
+ addf (str, _("\t\tKey Usage:\n"));
+
+
+ if (idx == -1)
+ err = gnutls_openpgp_crt_get_key_usage (cert, &key_usage);
+ else
+ err = gnutls_openpgp_crt_get_subkey_usage (cert, idx, &key_usage);
+ if (err < 0)
+ {
+ addf (str, _("error: get_key_usage: %s\n"), gnutls_strerror (err));
+ return;
+ }
+
+ if (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)
+ addf (str, _("\t\t\tDigital signature.\n"));
+ if (key_usage & GNUTLS_KEY_NON_REPUDIATION)
+ addf (str, _("\t\t\tNon repudiation.\n"));
+ if (key_usage & GNUTLS_KEY_KEY_ENCIPHERMENT)
+ addf (str, _("\t\t\tKey encipherment.\n"));
+ if (key_usage & GNUTLS_KEY_DATA_ENCIPHERMENT)
+ addf (str, _("\t\t\tData encipherment.\n"));
+ if (key_usage & GNUTLS_KEY_KEY_AGREEMENT)
+ addf (str, _("\t\t\tKey agreement.\n"));
+ if (key_usage & GNUTLS_KEY_KEY_CERT_SIGN)
+ addf (str, _("\t\t\tCertificate signing.\n"));
+ if (key_usage & GNUTLS_KEY_CRL_SIGN)
+ addf (str, _("\t\t\tCRL signing.\n"));
+ if (key_usage & GNUTLS_KEY_ENCIPHER_ONLY)
+ addf (str, _("\t\t\tKey encipher only.\n"));
+ if (key_usage & GNUTLS_KEY_DECIPHER_ONLY)
+ addf (str, _("\t\t\tKey decipher only.\n"));
+}
+
+/* idx == -1 indicates main key
+ * otherwise the subkey.
+ */
+static void
+print_key_id (gnutls_string * str, gnutls_openpgp_crt_t cert, int idx)
+{
+ gnutls_openpgp_keyid_t id;
+ int err;
+
+ if (idx < 0)
+ err = gnutls_openpgp_crt_get_id (cert, &id);
+ else
+ err = gnutls_openpgp_crt_get_subkey_id( cert, idx, &id);
+
+ if (err < 0)
+ addf (str, "error: get_id: %s\n", gnutls_strerror (err));
+ else
+ {
+ addf (str, _("\tID (hex): "));
+ hexprint (str, id.keyid, sizeof(id.keyid));
+ addf (str, "\n");
+ }
+}
+
+/* idx == -1 indicates main key
+ * otherwise the subkey.
+ */
+static void
+print_key_fingerprint (gnutls_string * str, gnutls_openpgp_crt_t cert)
+{
+ char fpr[128];
+ size_t fpr_size = sizeof (fpr);
+ int err;
+
+ err = gnutls_openpgp_crt_get_fingerprint (cert, fpr, &fpr_size);
+ if (err < 0)
+ addf (str, "error: get_fingerprint: %s\n", gnutls_strerror (err));
+ else
+ {
+ addf (str, _("\tFingerprint (hex): "));
+ hexprint (str, fpr, fpr_size);
+ addf (str, "\n");
+ }
+}
+
+static void
+print_key_revoked (gnutls_string * str, gnutls_openpgp_crt_t cert, int idx)
+{
+ char fpr[128];
+ size_t fpr_size = sizeof (fpr);
+ int err;
+
+ if (idx < 0)
+ err = gnutls_openpgp_crt_get_revoked_status (cert);
+ else
+ err = gnutls_openpgp_crt_get_subkey_revoked_status( cert, idx);
+
+ if (err != 0)
+ addf (str, "Revoked: True");
+}
+
+static void
+print_key_times(gnutls_string * str, gnutls_openpgp_crt_t cert, int idx)
+{
+ time_t tim;
+
+ addf (str, _("\tTime stamps:\n"));
+
+ if (idx == -1)
+ tim = gnutls_openpgp_crt_get_creation_time (cert);
+ else
+ tim = gnutls_openpgp_crt_get_subkey_creation_time (cert, idx);
+
+ {
+ char s[42];
+ size_t max = sizeof (s);
+ struct tm t;
+
+ if (gmtime_r (&tim, &t) == NULL)
+ addf (str, "error: gmtime_r (%d)\n", t);
+ else if (strftime (s, max, "%a %b %e %H:%M:%S UTC %Y", &t) == 0)
+ addf (str, "error: strftime (%d)\n", t);
+ else
+ addf (str, _("\t\tCreation: %s\n"), s);
+ }
+
+ if (idx == -1)
+ tim = gnutls_openpgp_crt_get_expiration_time (cert);
+ else
+ tim = gnutls_openpgp_crt_get_subkey_expiration_time (cert, idx);
+ {
+ char s[42];
+ size_t max = sizeof (s);
+ struct tm t;
+
+ if (gmtime_r (&tim, &t) == NULL)
+ addf (str, "error: gmtime_r (%d)\n", t);
+ else if (strftime (s, max, "%a %b %e %H:%M:%S UTC %Y", &t) == 0)
+ addf (str, "error: strftime (%d)\n", t);
+ else
+ addf (str, _("\t\tExpiration: %s\n"), s);
+ }
+}
+
+static void
+print_key_info(gnutls_string * str, gnutls_openpgp_crt_t cert, int idx)
+{
+ int err;
+ unsigned int bits;
+
+ if (idx == -1)
+ err = gnutls_openpgp_crt_get_pk_algorithm (cert, &bits);
+ else
+ err = gnutls_openpgp_crt_get_subkey_pk_algorithm (cert, idx, &bits);
+
+ if (err < 0)
+ addf (str, "error: get_pk_algorithm: %s\n", gnutls_strerror (err));
+ else
+ {
+ const char *name = gnutls_pk_algorithm_get_name (err);
+ if (name == NULL)
+ name = "Unknown";
+
+ addf (str, _("\tPublic Key Algorithm: %s\n"), name);
+#if 0
+ switch (err)
+ {
+ case GNUTLS_PK_RSA:
+ {
+ gnutls_datum_t m, e;
+
+ err = gnutls_openpgp_crt_get_pk_rsa_raw (cert, &m, &e);
+ if (err < 0)
+ addf (str, "error: get_pk_rsa_raw: %s\n",
+ gnutls_strerror (err));
+ else
+ {
+ addf (str, _("\t\tModulus (bits %d):\n"), bits);
+ hexdump (str, m.data, m.size, "\t\t\t");
+ addf (str, _("\t\tExponent:\n"));
+ hexdump (str, e.data, e.size, "\t\t\t");
+ }
+
+ gnutls_free (m.data);
+ gnutls_free (e.data);
+ }
+ break;
+
+ case GNUTLS_PK_DSA:
+ {
+ gnutls_datum_t p, q, g, y;
+
+ err = gnutls_openpgp_crt_get_pk_dsa_raw (cert, &p, &q, &g, &y);
+ if (err < 0)
+ addf (str, "error: get_pk_dsa_raw: %s\n",
+ gnutls_strerror (err));
+ else
+ {
+ addf (str, _("\t\tPublic key (bits %d):\n"), bits);
+ hexdump (str, y.data, y.size, "\t\t\t");
+ addf (str, _("\t\tP:\n"));
+ hexdump (str, p.data, p.size, "\t\t\t");
+ addf (str, _("\t\tQ:\n"));
+ hexdump (str, q.data, q.size, "\t\t\t");
+ addf (str, _("\t\tG:\n"));
+ hexdump (str, g.data, g.size, "\t\t\t");
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+#endif
+ }
+}
+
+
+static void
+print_cert (gnutls_string * str, gnutls_openpgp_crt_t cert, unsigned int format)
+{
+int i, subkeys;
+int err;
+char dn[1024];
+size_t dn_size = sizeof (dn);
+
+ /* Version. */
+ {
+ int version = gnutls_openpgp_crt_get_version (cert);
+ if (version < 0)
+ addf (str, "error: get_version: %s\n", gnutls_strerror (version));
+ else
+ addf (str, _("\tVersion: %d\n"), version);
+ }
+
+ /* ID. */
+ print_key_id( str, cert, -1);
+
+ print_key_fingerprint( str, cert);
+
+ /* Names. */
+ i = 0;
+ do {
+
+ err = gnutls_openpgp_crt_get_name (cert, i++, dn, &dn_size);
+
+ if (err < 0 && err != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+ addf (str, "error: get_name: %s\n", gnutls_strerror (err));
+ break;
+ }
+
+ if (err > 0)
+ addf (str, _("\tName[%d]: %s\n"), i, dn);
+
+ } while( err > 0);
+
+ print_key_times( str, cert, -1);
+
+ print_key_info( str, cert, -1);
+ print_key_usage( str, cert, -1);
+ print_key_revoked( str, cert, -1);
+
+ subkeys = gnutls_openpgp_crt_get_subkey_count( cert);
+ if (subkeys < 0)
+ return;
+
+ for (i=0;i<subkeys;i++) {
+ addf( str, _("\n\tSubkey[%d]:\n"), i);
+
+ print_key_id( str, cert, i);
+ print_key_times( str, cert, i);
+ print_key_info( str, cert, i);
+ print_key_usage( str, cert, i);
+ print_key_revoked( str, cert, i);
+ }
+
+}
+
+/**
+ * gnutls_openpgp_crt_print - Pretty print OpenPGP certificates
+ * @cert: The structure to be printed
+ * @format: Indicate the format to use
+ * @out: Newly allocated datum with zero terminated string.
+ *
+ * This function will pretty print an OpenPGP certificate, suitable for
+ * display to a human.
+ *
+ * The format should be zero for future compatibility.
+ *
+ * The output @out needs to be deallocate using gnutls_free().
+ *
+ * Returns 0 on success.
+ **/
+int
+gnutls_openpgp_crt_print (gnutls_openpgp_crt_t cert,
+ gnutls_certificate_print_formats_t format,
+ gnutls_datum_t *out)
+{
+ gnutls_string str;
+
+ _gnutls_string_init (&str, gnutls_malloc, gnutls_realloc, gnutls_free);
+
+ _gnutls_string_append_str (&str, _("OpenPGP Certificate Information:\n"));
+
+ print_cert (&str, cert, format);
+
+ _gnutls_string_append_data (&str, "\0", 1);
+ out->data = str.data;
+ out->size = strlen (str.data);
+
+ return 0;
+}
+
diff --git a/lib/openpgp/pgp.c b/lib/openpgp/pgp.c
new file mode 100644
index 0000000000..e0f0472bf6
--- /dev/null
+++ b/lib/openpgp/pgp.c
@@ -0,0 +1,1079 @@
+/*
+ * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
+ *
+ * Author: Timo Schulz, Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS-EXTRA.
+ *
+ * GNUTLS-EXTRA is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNUTLS-EXTRA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Functions on OpenPGP key parsing
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_datum.h>
+#include <gnutls_global.h>
+#include <gnutls_errors.h>
+#include <openpgp.h>
+#include <x509/rfc2818.h>
+#include <gnutls_num.h>
+
+/**
+ * gnutls_openpgp_crt_init - This function initializes a gnutls_openpgp_crt_t structure
+ * @key: The structure to be initialized
+ *
+ * This function will initialize an OpenPGP key structure.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int
+gnutls_openpgp_crt_init (gnutls_openpgp_crt_t * key)
+{
+ *key = gnutls_calloc (1, sizeof (gnutls_openpgp_crt_int));
+
+ if (*key)
+ return 0; /* success */
+ return GNUTLS_E_MEMORY_ERROR;
+}
+
+/**
+ * gnutls_openpgp_crt_deinit - This function deinitializes memory used by a gnutls_openpgp_crt_t structure
+ * @key: The structure to be initialized
+ *
+ * This function will deinitialize a key structure.
+ **/
+void
+gnutls_openpgp_crt_deinit (gnutls_openpgp_crt_t key)
+{
+ if (!key)
+ return;
+
+ if (key->knode)
+ {
+ cdk_kbnode_release (key->knode);
+ key->knode = NULL;
+ }
+
+ gnutls_free (key);
+}
+
+/**
+ * gnutls_openpgp_crt_import - This function will import a RAW or BASE64 encoded key
+ * @key: The structure to store the parsed key.
+ * @data: The RAW or BASE64 encoded key.
+ * @format: One of gnutls_openpgp_crt_fmt_t elements.
+ *
+ * This function will convert the given RAW or Base64 encoded key
+ * to the native gnutls_openpgp_crt_t format. The output will be stored in 'key'.
+ *
+ * Returns 0 on success.
+ **/
+int
+gnutls_openpgp_crt_import (gnutls_openpgp_crt_t key,
+ const gnutls_datum_t * data,
+ gnutls_openpgp_crt_fmt_t format)
+{
+ cdk_stream_t inp;
+ int rc;
+
+ if (format == GNUTLS_OPENPGP_FMT_RAW)
+ rc = cdk_kbnode_read_from_mem (&key->knode, data->data, data->size);
+ else
+ {
+ rc = cdk_stream_tmp_from_mem (data->data, data->size, &inp);
+ if (rc)
+ {
+ rc = _gnutls_map_cdk_rc (rc);
+ gnutls_assert ();
+ return rc;
+ }
+ if (cdk_armor_filter_use (inp))
+ rc = cdk_stream_set_armor_flag (inp, 0);
+ if (!rc)
+ rc = cdk_keydb_get_keyblock (inp, &key->knode);
+ cdk_stream_close (inp);
+ if (rc)
+ {
+ rc = _gnutls_map_cdk_rc (rc);
+ gnutls_assert ();
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * gnutls_openpgp_crt_export - This function will export a RAW or BASE64 encoded key
+ * @key: Holds the key.
+ * @format: One of gnutls_openpgp_crt_fmt_t elements.
+ * @output_data: will contain the key base64 encoded or raw
+ * @output_data_size: holds the size of output_data (and will be replaced by the actual size of parameters)
+ *
+ * This function will convert the given key to RAW or Base64 format.
+ * If the buffer provided is not long enough to hold the output, then
+ * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int
+gnutls_openpgp_crt_export (gnutls_openpgp_crt_t key,
+ gnutls_openpgp_crt_fmt_t format,
+ void *output_data, size_t * output_data_size)
+{
+ size_t input_data_size = *output_data_size;
+ size_t calc_size;
+ int rc;
+
+ rc = cdk_kbnode_write_to_mem (key->knode, output_data, output_data_size);
+ if (rc)
+ {
+ rc = _gnutls_map_cdk_rc (rc);
+ gnutls_assert ();
+ return rc;
+ }
+
+ /* If the caller uses output_data == NULL then return what he expects.
+ */
+ if (!output_data)
+ {
+ gnutls_assert();
+ return GNUTLS_E_SHORT_MEMORY_BUFFER;
+ }
+
+ if (format == GNUTLS_OPENPGP_FMT_BASE64)
+ {
+ unsigned char *in = cdk_calloc (1, *output_data_size);
+ memcpy (in, output_data, *output_data_size);
+
+ /* Calculate the size of the encoded data and check if the provided
+ buffer is large enough. */
+ rc = cdk_armor_encode_buffer (in, *output_data_size,
+ NULL, 0, &calc_size, CDK_ARMOR_PUBKEY);
+ if (rc || calc_size > input_data_size)
+ {
+ cdk_free (in);
+ *output_data_size = calc_size;
+ gnutls_assert ();
+ return GNUTLS_E_SHORT_MEMORY_BUFFER;
+ }
+
+ rc = cdk_armor_encode_buffer (in, *output_data_size,
+ output_data, input_data_size, &calc_size,
+ CDK_ARMOR_PUBKEY);
+ cdk_free (in);
+ *output_data_size = calc_size;
+ }
+
+ return 0;
+}
+
+
+/**
+ * gnutls_openpgp_crt_get_fingerprint - Gets the fingerprint
+ * @key: the raw data that contains the OpenPGP public key.
+ * @fpr: the buffer to save the fingerprint, must hold at least 20 bytes.
+ * @fprlen: the integer to save the length of the fingerprint.
+ *
+ * Returns the fingerprint of the OpenPGP key. Depends on the algorithm,
+ * the fingerprint can be 16 or 20 bytes.
+ **/
+int
+gnutls_openpgp_crt_get_fingerprint (gnutls_openpgp_crt_t key,
+ void *fpr, size_t * fprlen)
+{
+ cdk_packet_t pkt;
+ cdk_pkt_pubkey_t pk = NULL;
+
+ if (!fpr || !fprlen)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ *fprlen = 0;
+
+ pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
+ if (!pkt)
+ return GNUTLS_E_OPENPGP_GETKEY_FAILED;
+
+ pk = pkt->pkt.public_key;
+ *fprlen = 20;
+
+ /* FIXME: Check if the draft allows old PGP keys. */
+ if (is_RSA (pk->pubkey_algo) && pk->version < 4)
+ *fprlen = 16;
+ cdk_pk_get_fingerprint (pk, fpr);
+
+ return 0;
+}
+
+int
+_gnutls_openpgp_count_key_names (gnutls_openpgp_crt_t key)
+{
+ cdk_kbnode_t p, ctx;
+ cdk_packet_t pkt;
+ int nuids;
+
+ if (key == NULL)
+ {
+ gnutls_assert ();
+ return 0;
+ }
+
+ ctx = NULL;
+ nuids = 0;
+ while ((p = cdk_kbnode_walk (key->knode, &ctx, 0)))
+ {
+ pkt = cdk_kbnode_get_packet (p);
+ if (pkt->pkttype == CDK_PKT_USER_ID)
+ nuids++;
+ }
+
+ return nuids;
+}
+
+
+/**
+ * gnutls_openpgp_crt_get_name - Extracts the userID
+ * @key: the structure that contains the OpenPGP public key.
+ * @idx: the index of the ID to extract
+ * @buf: a pointer to a structure to hold the name
+ * @sizeof_buf: holds the maximum size of @buf, on return hold the
+ * actual/required size of @buf.
+ *
+ * Extracts the userID from the parsed OpenPGP key.
+ *
+ * Returns 0 on success, and GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
+ * if the index of the ID does not exist.
+ *
+ **/
+int
+gnutls_openpgp_crt_get_name (gnutls_openpgp_crt_t key,
+ int idx, char *buf, size_t * sizeof_buf)
+{
+ cdk_kbnode_t ctx = NULL, p;
+ cdk_packet_t pkt = NULL;
+ cdk_pkt_userid_t uid = NULL;
+ int pos = 0;
+
+ if (!key || !buf)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ if (idx < 0 || idx > _gnutls_openpgp_count_key_names (key))
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+
+ if (!idx)
+ pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_USER_ID);
+ else
+ {
+ pos = 0;
+ while ((p = cdk_kbnode_walk (key->knode, &ctx, 0)))
+ {
+ pkt = cdk_kbnode_get_packet (p);
+ if (pkt->pkttype == CDK_PKT_USER_ID && ++pos == idx)
+ break;
+ }
+ }
+
+ if (!pkt)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ uid = pkt->pkt.user_id;
+ if (uid->len >= *sizeof_buf)
+ {
+ gnutls_assert ();
+ *sizeof_buf = uid->len + 1;
+ return GNUTLS_E_SHORT_MEMORY_BUFFER;
+ }
+
+ memcpy (buf, uid->name, uid->len);
+ buf[uid->len] = '\0'; /* make sure it's a string */
+ *sizeof_buf = uid->len + 1;
+
+ if (uid->is_revoked)
+ return GNUTLS_E_OPENPGP_UID_REVOKED;
+
+ return 0;
+}
+
+/**
+ * gnutls_openpgp_crt_get_pk_algorithm - This function returns the key's PublicKey algorithm
+ * @key: is an OpenPGP key
+ * @bits: if bits is non null it will hold the size of the parameters' in bits
+ *
+ * This function will return the public key algorithm of an OpenPGP
+ * certificate.
+ *
+ * If bits is non null, it should have enough size to hold the parameters
+ * size in bits. For RSA the bits returned is the modulus.
+ * For DSA the bits returned are of the public exponent.
+ *
+ * Returns a member of the GNUTLS_PKAlgorithm enumeration on success,
+ * or a negative value on error.
+ *
+ **/
+gnutls_pk_algorithm_t
+gnutls_openpgp_crt_get_pk_algorithm (gnutls_openpgp_crt_t key,
+ unsigned int *bits)
+{
+ cdk_packet_t pkt;
+ int algo;
+
+ if (!key)
+ return GNUTLS_PK_UNKNOWN;
+
+ algo = 0;
+ pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
+ if (pkt)
+ {
+ if (bits)
+ *bits = cdk_pk_get_nbits (pkt->pkt.public_key);
+ algo = pkt->pkt.public_key->pubkey_algo;
+ if (is_RSA (algo))
+ algo = GNUTLS_PK_RSA;
+ else if (is_DSA (algo))
+ algo = GNUTLS_PK_DSA;
+ else
+ algo = GNUTLS_E_UNKNOWN_PK_ALGORITHM;
+ }
+
+ return algo;
+}
+
+
+/**
+ * gnutls_openpgp_crt_get_version - Extracts the version of the key.
+ * @key: the structure that contains the OpenPGP public key.
+ *
+ * Extract the version of the OpenPGP key.
+ **/
+int
+gnutls_openpgp_crt_get_version (gnutls_openpgp_crt_t key)
+{
+ cdk_packet_t pkt;
+ int version;
+
+ if (!key)
+ return -1;
+
+ pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
+ if (pkt)
+ version = pkt->pkt.public_key->version;
+ else
+ version = 0;
+
+ return version;
+}
+
+
+/**
+ * gnutls_openpgp_crt_get_creation_time - Extract the timestamp
+ * @key: the structure that contains the OpenPGP public key.
+ *
+ * Returns the timestamp when the OpenPGP key was created.
+ **/
+time_t
+gnutls_openpgp_crt_get_creation_time (gnutls_openpgp_crt_t key)
+{
+ cdk_packet_t pkt;
+ time_t timestamp;
+
+ if (!key)
+ return (time_t) - 1;
+
+ pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
+ if (pkt)
+ timestamp = pkt->pkt.public_key->timestamp;
+ else
+ timestamp = 0;
+
+ return timestamp;
+}
+
+
+/**
+ * gnutls_openpgp_crt_get_expiration_time - Extract the expire date
+ * @key: the structure that contains the OpenPGP public key.
+ *
+ * Returns the time when the OpenPGP key expires. A value of '0' means
+ * that the key doesn't expire at all.
+ **/
+time_t
+gnutls_openpgp_crt_get_expiration_time (gnutls_openpgp_crt_t key)
+{
+ cdk_packet_t pkt;
+ time_t expiredate;
+
+ if (!key)
+ return (time_t) - 1;
+
+ pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
+ if (pkt)
+ expiredate = pkt->pkt.public_key->expiredate;
+ else
+ expiredate = 0;
+
+ return expiredate;
+}
+
+/**
+ * gnutls_openpgp_crt_get_id - Gets the keyID
+ * @key: the structure that contains the OpenPGP public key.
+ * @keyid: the buffer to save the keyid.
+ *
+ * Returns the 64-bit keyID of the OpenPGP key.
+ **/
+int
+gnutls_openpgp_crt_get_id (gnutls_openpgp_crt_t key, gnutls_openpgp_keyid_t* keyid)
+{
+ cdk_packet_t pkt;
+ uint32_t kid[2];
+
+ if (!key || !keyid)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
+ if (!pkt)
+ return GNUTLS_E_OPENPGP_GETKEY_FAILED;
+
+ cdk_pk_get_keyid (pkt->pkt.public_key, kid);
+ _gnutls_write_uint32( kid[0], keyid->keyid);
+ _gnutls_write_uint32( kid[1], keyid->keyid+4);
+
+ return 0;
+}
+
+/**
+ * gnutls_openpgp_crt_get_revoked_status - Gets the revoked status of the key
+ * @key: the structure that contains the OpenPGP public key.
+ *
+ * Returns the true (1) or false (0) based on whether this key has been revoked
+ * or not.
+ *
+ **/
+int
+gnutls_openpgp_crt_get_revoked_status (gnutls_openpgp_crt_t key)
+{
+ cdk_packet_t pkt;
+
+ if (!key)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
+ if (!pkt)
+ return GNUTLS_E_OPENPGP_GETKEY_FAILED;
+
+ if (pkt->pkt.public_key->is_revoked != 0) return 1;
+ return 0;
+}
+
+/**
+ * gnutls_openpgp_crt_check_hostname - This function compares the given hostname with the hostname in the key
+ * @key: should contain an gnutls_openpgp_crt_t structure
+ * @hostname: A null terminated string that contains a DNS name
+ *
+ * This function will check if the given key's owner matches
+ * the given hostname. This is a basic implementation of the matching
+ * described in RFC2818 (HTTPS), which takes into account wildcards.
+ *
+ * Returns non zero on success, and zero on failure.
+ *
+ **/
+int
+gnutls_openpgp_crt_check_hostname (gnutls_openpgp_crt_t key,
+ const char *hostname)
+{
+ char dnsname[MAX_CN];
+ size_t dnsnamesize;
+ int ret;
+ int i;
+
+ /* Check through all included names. */
+ for (i = 0; !(ret < 0); i++)
+ {
+ dnsnamesize = sizeof (dnsname);
+ ret = gnutls_openpgp_crt_get_name (key, i, dnsname, &dnsnamesize);
+ /* FIXME: ret is not used */
+ if (_gnutls_hostname_compare (dnsname, hostname))
+ return 1;
+ }
+
+ /* not found a matching name */
+ return 0;
+}
+
+unsigned int _gnutls_get_pgp_key_usage(unsigned int cdk_usage)
+{
+unsigned int usage = 0;
+
+ if (cdk_usage & CDK_KEY_USG_CERT_SIGN)
+ usage |= GNUTLS_KEY_KEY_CERT_SIGN;
+ if (cdk_usage & CDK_KEY_USG_DATA_SIGN)
+ usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
+ if (cdk_usage & CDK_KEY_USG_COMM_ENCR)
+ usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
+ if (cdk_usage & CDK_KEY_USG_STORAGE_ENCR)
+ usage |= GNUTLS_KEY_DATA_ENCIPHERMENT;
+ if (cdk_usage & CDK_KEY_USG_AUTH)
+ usage |= GNUTLS_KEY_KEY_AGREEMENT;
+
+ return usage;
+}
+
+/**
+ * gnutls_openpgp_crt_get_key_usage - This function returns the key's usage
+ * @key: should contain a gnutls_openpgp_crt_t structure
+ * @key_usage: where the key usage bits will be stored
+ *
+ * This function will return certificate's key usage, by checking the
+ * key algorithm. The key usage value will ORed values of the:
+ * GNUTLS_KEY_DIGITAL_SIGNATURE, GNUTLS_KEY_KEY_ENCIPHERMENT.
+ *
+ * A negative value may be returned in case of parsing error.
+ *
+ */
+int
+gnutls_openpgp_crt_get_key_usage (gnutls_openpgp_crt_t key,
+ unsigned int *key_usage)
+{
+ cdk_packet_t pkt;
+
+ if (!key)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY);
+ if (!pkt)
+ return GNUTLS_E_OPENPGP_GETKEY_FAILED;
+
+ *key_usage = _gnutls_get_pgp_key_usage(pkt->pkt.public_key->pubkey_usage);
+
+ return 0;
+}
+
+/**
+ * gnutls_openpgp_crt_get_subkey_count - This function returns the number of subkeys
+ * @key: is an OpenPGP key
+ *
+ * This function will return the number of subkeys present in the given
+ * OpenPGP certificate.
+ *
+ * Returns then number of subkeys or a negative value on error.
+ *
+ **/
+int
+gnutls_openpgp_crt_get_subkey_count (gnutls_openpgp_crt_t key)
+{
+ cdk_kbnode_t p, ctx;
+ cdk_packet_t pkt;
+ int subkeys;
+
+ if (key == NULL)
+ {
+ gnutls_assert ();
+ return 0;
+ }
+
+ ctx = NULL;
+ subkeys = 0;
+ while ((p = cdk_kbnode_walk (key->knode, &ctx, 0)))
+ {
+ pkt = cdk_kbnode_get_packet (p);
+ if (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
+ subkeys++;
+ }
+
+ return subkeys;
+}
+
+/* returns the subkey with the given index */
+static cdk_packet_t _get_public_subkey(gnutls_openpgp_crt_t key, unsigned int indx)
+{
+ cdk_kbnode_t p, ctx;
+ cdk_packet_t pkt;
+ int subkeys;
+
+ if (key == NULL)
+ {
+ gnutls_assert ();
+ return NULL;
+ }
+
+ ctx = NULL;
+ subkeys = 0;
+ while ((p = cdk_kbnode_walk (key->knode, &ctx, 0)))
+ {
+ pkt = cdk_kbnode_get_packet (p);
+ if (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY && indx == subkeys++)
+ return pkt;
+ }
+
+ return NULL;
+}
+
+/* returns the key with the given keyid
+ * depending on what requested:
+ * pkt->pkt.secret_key;
+ * pkt->pkt.public_key;
+ */
+cdk_packet_t _gnutls_openpgp_find_key( cdk_kbnode_t knode, uint32_t keyid[2],
+ unsigned int priv)
+{
+ cdk_pkt_pubkey_t ret;
+ cdk_kbnode_t p, ctx;
+ cdk_packet_t pkt;
+ int subkeys;
+ uint32_t local_keyid[2];
+
+ ctx = NULL;
+ while ((p = cdk_kbnode_walk (knode, &ctx, 0)))
+ {
+ pkt = cdk_kbnode_get_packet (p);
+
+ if ( (priv == 0 && (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY || pkt->pkttype == CDK_PKT_PUBLIC_KEY)) || \
+ (priv != 0 && (pkt->pkttype == CDK_PKT_SECRET_SUBKEY || pkt->pkttype == CDK_PKT_SECRET_KEY)))
+ {
+ if (priv == 0)
+ cdk_pk_get_keyid (pkt->pkt.public_key, local_keyid);
+ else
+ cdk_pk_get_keyid (pkt->pkt.secret_key->pk, local_keyid);
+
+ if (local_keyid[0] == keyid[0] && \
+ local_keyid[1] == keyid[1])
+ {
+ return pkt;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/* returns the key with the given keyid
+ * depending on what requested:
+ * pkt->pkt.secret_key;
+ * pkt->pkt.public_key;
+ */
+int _gnutls_openpgp_find_subkey_idx( cdk_kbnode_t knode, uint32_t keyid[2],
+ unsigned int priv)
+{
+ cdk_pkt_pubkey_t ret;
+ cdk_kbnode_t p, ctx;
+ cdk_packet_t pkt;
+ int subkeys, i=0;
+ uint32_t local_keyid[2];
+
+ ctx = NULL;
+ while ((p = cdk_kbnode_walk (knode, &ctx, 0)))
+ {
+ pkt = cdk_kbnode_get_packet (p);
+
+ if ( (priv == 0 && (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)) || \
+ (priv != 0 && (pkt->pkttype == CDK_PKT_SECRET_SUBKEY)))
+ {
+ if (priv == 0)
+ cdk_pk_get_keyid (pkt->pkt.public_key, local_keyid);
+ else
+ cdk_pk_get_keyid (pkt->pkt.secret_key->pk, local_keyid);
+
+ if (local_keyid[0] == keyid[0] && \
+ local_keyid[1] == keyid[1])
+ {
+ return i;
+ }
+ i++;
+ }
+ }
+
+ gnutls_assert();
+ return GNUTLS_E_OPENPGP_SUBKEY_ERROR;
+}
+
+/**
+ * gnutls_openpgp_crt_get_subkey_revoked_status - Gets the revoked status of the key
+ * @key: the structure that contains the OpenPGP public key.
+ * @idx: is the subkey index
+ *
+ * Returns the true (1) or false (0) based on whether this key has been revoked
+ * or not. A negative value indicates an error.
+ *
+ **/
+int
+gnutls_openpgp_crt_get_subkey_revoked_status (gnutls_openpgp_crt_t key, unsigned int idx)
+{
+ cdk_packet_t pkt;
+
+ if (!key)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ pkt = _get_public_subkey( key, idx);
+ if (!pkt)
+ return GNUTLS_E_OPENPGP_GETKEY_FAILED;
+
+ if (pkt->pkt.public_key->is_revoked != 0) return 1;
+ return 0;
+}
+
+/**
+ * gnutls_openpgp_crt_get_subkey_pk_algorithm - This function returns the subkey's PublicKey algorithm
+ * @key: is an OpenPGP key
+ * @idx: is the subkey index
+ * @bits: if bits is non null it will hold the size of the parameters' in bits
+ *
+ * This function will return the public key algorithm of a subkey of an OpenPGP
+ * certificate.
+ *
+ * If bits is non null, it should have enough size to hold the parameters
+ * size in bits. For RSA the bits returned is the modulus.
+ * For DSA the bits returned are of the public exponent.
+ *
+ * Returns a member of the gnutls_pk_algorithm_t enumeration on success,
+ * or a negative value on error.
+ *
+ **/
+gnutls_pk_algorithm_t
+gnutls_openpgp_crt_get_subkey_pk_algorithm (gnutls_openpgp_crt_t key,
+ unsigned int idx, unsigned int *bits)
+{
+ cdk_packet_t pkt;
+ int algo;
+
+ if (!key)
+ return GNUTLS_PK_UNKNOWN;
+
+ pkt = _get_public_subkey( key, idx);
+
+ algo = 0;
+ if (pkt)
+ {
+ if (bits)
+ *bits = cdk_pk_get_nbits (pkt->pkt.public_key);
+ algo = pkt->pkt.public_key->pubkey_algo;
+ if (is_RSA (algo))
+ algo = GNUTLS_PK_RSA;
+ else if (is_DSA (algo))
+ algo = GNUTLS_PK_DSA;
+ else
+ algo = GNUTLS_E_UNKNOWN_PK_ALGORITHM;
+ }
+
+ return algo;
+}
+
+/**
+ * gnutls_openpgp_crt_get_subkey_creation_time - Extract the timestamp
+ * @key: the structure that contains the OpenPGP public key.
+ * @idx: the subkey index
+ *
+ * Returns the timestamp when the OpenPGP key was created.
+ **/
+time_t
+gnutls_openpgp_crt_get_subkey_creation_time (gnutls_openpgp_crt_t key, unsigned int idx)
+{
+ cdk_packet_t pkt;
+ time_t timestamp;
+
+ if (!key)
+ return (time_t) - 1;
+
+ pkt = _get_public_subkey( key, idx);
+ if (pkt)
+ timestamp = pkt->pkt.public_key->timestamp;
+ else
+ timestamp = 0;
+
+ return timestamp;
+}
+
+
+/**
+ * gnutls_openpgp_crt_get_subkey_expiration_time - Extract the expire date
+ * @key: the structure that contains the OpenPGP public key.
+ * @idx: the subkey index
+ *
+ * Returns the time when the OpenPGP key expires. A value of '0' means
+ * that the key doesn't expire at all.
+ **/
+time_t
+gnutls_openpgp_crt_get_subkey_expiration_time (gnutls_openpgp_crt_t key, unsigned int idx)
+{
+ cdk_packet_t pkt;
+ time_t expiredate;
+
+ if (!key)
+ return (time_t) - 1;
+
+ pkt = _get_public_subkey( key, idx);
+ if (pkt)
+ expiredate = pkt->pkt.public_key->expiredate;
+ else
+ expiredate = 0;
+
+ return expiredate;
+}
+
+/**
+ * gnutls_openpgp_crt_get_subkey_id - Gets the keyID
+ * @key: the structure that contains the OpenPGP public key.
+ * @idx: the subkey index
+ * @keyid: the buffer to save the keyid.
+ *
+ * Returns the 64-bit keyID of the OpenPGP key.
+ **/
+int
+gnutls_openpgp_crt_get_subkey_id (gnutls_openpgp_crt_t key, unsigned int idx, gnutls_openpgp_keyid_t* keyid)
+{
+ cdk_packet_t pkt;
+ uint32_t kid[2];
+
+ if (!key || !keyid)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ pkt = _get_public_subkey( key, idx);
+ if (!pkt)
+ return GNUTLS_E_OPENPGP_GETKEY_FAILED;
+
+ cdk_pk_get_keyid (pkt->pkt.public_key, kid);
+ _gnutls_write_uint32( kid[0], keyid->keyid);
+ _gnutls_write_uint32( kid[1], keyid->keyid+4);
+
+ return 0;
+}
+
+/**
+ * gnutls_openpgp_crt_get_subkey_idx - Returns the subkey's index
+ * @key: the structure that contains the OpenPGP public key.
+ * @keyid: the keyid.
+ *
+ * Returns the index of the subkey or a negative error value.
+ *
+ **/
+int
+gnutls_openpgp_crt_get_subkey_idx (gnutls_openpgp_crt_t key, gnutls_openpgp_keyid_t keyid)
+{
+ cdk_packet_t pkt;
+ int ret;
+ uint32_t kid[2];
+
+ if (!key)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ KEYID_IMPORT( kid, keyid);
+ ret = _gnutls_openpgp_find_subkey_idx( key->knode, kid, 0);
+
+ if (ret < 0)
+ {
+ gnutls_assert();
+ }
+
+ return ret;
+}
+
+/**
+ * gnutls_openpgp_crt_get_subkey_usage - This function returns the key's usage
+ * @key: should contain a gnutls_openpgp_crt_t structure
+ * @idx: the subkey index
+ * @key_usage: where the key usage bits will be stored
+ *
+ * This function will return certificate's key usage, by checking the
+ * key algorithm. The key usage value will ORed values of the:
+ * GNUTLS_KEY_DIGITAL_SIGNATURE, GNUTLS_KEY_KEY_ENCIPHERMENT.
+ *
+ * A negative value may be returned in case of parsing error.
+ *
+ */
+int
+gnutls_openpgp_crt_get_subkey_usage (gnutls_openpgp_crt_t key, unsigned int idx,
+ unsigned int *key_usage)
+{
+ cdk_packet_t pkt;
+
+ if (!key)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ pkt = _get_public_subkey( key, idx);
+ if (!pkt)
+ return GNUTLS_E_OPENPGP_SUBKEY_ERROR;
+
+ *key_usage = _gnutls_get_pgp_key_usage(pkt->pkt.public_key->pubkey_usage);
+
+ return 0;
+}
+
+int _gnutls_read_pgp_mpi( cdk_packet_t pkt, unsigned int priv, size_t idx, mpi_t* m)
+{
+size_t buf_size = 512;
+opaque * buf = gnutls_malloc( buf_size);
+int err;
+int max_pub_params;
+
+ if (priv !=0)
+ max_pub_params = cdk_pk_get_npkey(pkt->pkt.secret_key->pk->pubkey_algo);
+
+ if (buf == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ /* FIXME: Note that opencdk doesn't like the buf to be NULL.
+ */
+ if (priv == 0)
+ err = cdk_pk_get_mpi (pkt->pkt.public_key, idx, buf, buf_size, &buf_size, NULL);
+ else
+ {
+ if (idx < max_pub_params)
+ err = cdk_pk_get_mpi (pkt->pkt.secret_key->pk, idx, buf, buf_size, &buf_size, NULL);
+ else
+ {
+ err = cdk_sk_get_mpi (pkt->pkt.secret_key, idx-max_pub_params, buf, buf_size, &buf_size, NULL);
+ }
+ }
+
+ if (err == CDK_Too_Short)
+ {
+ buf = gnutls_realloc_fast( buf, buf_size);
+ if (buf == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ if (priv == 0)
+ err = cdk_pk_get_mpi (pkt->pkt.public_key, idx, buf, buf_size, &buf_size, NULL);
+ else
+ {
+ if (idx < max_pub_params)
+ err = cdk_pk_get_mpi (pkt->pkt.secret_key->pk, idx, buf, buf_size, &buf_size, NULL);
+ else
+ {
+ err = cdk_sk_get_mpi (pkt->pkt.secret_key, idx-max_pub_params, buf, buf_size, &buf_size, NULL);
+ }
+ }
+ }
+
+ if (err != CDK_Success)
+ {
+_gnutls_x509_log( "err: %d/%d\n", err, idx);
+ gnutls_assert();
+ gnutls_free( buf);
+ return _gnutls_map_cdk_rc( err);
+ }
+
+ err = _gnutls_mpi_scan_pgp (m, buf, &buf_size);
+ gnutls_free( buf);
+
+ if (err < 0)
+ {
+ gnutls_assert();
+ return err;
+ }
+
+ return 0;
+}
+
+
+/* Extracts DSA and RSA parameters from a certificate.
+ */
+int
+_gnutls_openpgp_crt_get_mpis (gnutls_openpgp_crt_t cert, uint32_t keyid[2],
+ mpi_t * params, int *params_size)
+{
+ int result, i;
+ int pk_algorithm, local_params;
+ cdk_packet_t pkt;
+
+ /* Read the algorithm's OID
+ */
+ pk_algorithm = gnutls_openpgp_crt_get_pk_algorithm (cert, NULL);
+
+ switch (pk_algorithm)
+ {
+ case GNUTLS_PK_RSA:
+ local_params = RSA_PUBLIC_PARAMS;
+ break;
+ case GNUTLS_PK_DSA:
+ local_params = DSA_PUBLIC_PARAMS;
+ break;
+ default:
+ gnutls_assert ();
+ return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
+ }
+
+ if (*params_size < local_params)
+ {
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ *params_size = local_params;
+
+ pkt = _gnutls_openpgp_find_key( cert->knode, keyid, 0);
+ if (pkt == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_OPENPGP_GETKEY_FAILED;
+ }
+
+ for (i = 0; i < local_params; i++)
+ {
+ result = _gnutls_read_pgp_mpi( pkt, 0, i, &params[i]);
+ if (result < 0)
+ {
+ gnutls_assert();
+ goto error;
+ }
+ }
+
+ return 0;
+
+error:
+ {
+ int j;
+ for (j=0;j<i;j++)
+ _gnutls_mpi_release( &params[j]);
+ }
+
+ return result;
+}
diff --git a/lib/openpgp/pgpverify.c b/lib/openpgp/pgpverify.c
new file mode 100644
index 0000000000..34b06a0834
--- /dev/null
+++ b/lib/openpgp/pgpverify.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation
+ *
+ * Author: Timo Schulz, Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS-EXTRA.
+ *
+ * GNUTLS-EXTRA is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNUTLS-EXTRA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Functions on OpenPGP key parsing
+ */
+
+#include <gnutls_int.h>
+#include <openpgp.h>
+#include <gnutls_errors.h>
+#include <gnutls_openpgp.h>
+#include <gnutls_num.h>
+#include <x509/verify.h> /* lib/x509/verify.h */
+
+
+/**
+ * gnutls_openpgp_crt_verify_ring - Verify all signatures in the key
+ * @key: the structure that holds the key.
+ * @keyring: holds the keyring to check against
+ * @flags: unused (should be 0)
+ * @verify: will hold the certificate verification output.
+ *
+ * Verify all signatures in the key, using the given set of keys (keyring).
+ *
+ * The key verification output will be put in @verify and will be
+ * one or more of the gnutls_certificate_status_t enumerated elements bitwise or'd.
+ *
+ * GNUTLS_CERT_INVALID: A signature on the key is invalid.
+ *
+ * GNUTLS_CERT_REVOKED: The key has been revoked.
+ *
+ * Note that this function does not verify using any "web of
+ * trust". You may use GnuPG for that purpose, or any other external
+ * PGP application.
+ *
+ * Returns 0 on success.
+ **/
+int
+gnutls_openpgp_crt_verify_ring (gnutls_openpgp_crt_t key,
+ gnutls_openpgp_keyring_t keyring,
+ unsigned int flags, unsigned int *verify)
+{
+ gnutls_openpgp_keyid_t id;
+ cdk_error_t rc;
+ int status;
+
+ if (!key || !keyring)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_NO_CERTIFICATE_FOUND;
+ }
+
+ *verify = 0;
+
+ rc = cdk_pk_check_sigs (key->knode, keyring->db, &status);
+ if (rc == CDK_Error_No_Key)
+ {
+ rc = GNUTLS_E_NO_CERTIFICATE_FOUND;
+ gnutls_assert ();
+ return 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;
+ if (status & CDK_KEY_REVOKED)
+ *verify |= GNUTLS_CERT_REVOKED;
+ if (status & CDK_KEY_NOSIGNER)
+ *verify |= GNUTLS_CERT_SIGNER_NOT_FOUND;
+
+ /* Check if the key is included in the ring. */
+ if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_SAME))
+ {
+ rc = gnutls_openpgp_crt_get_id (key, &id);
+ if (rc < 0)
+ {
+ gnutls_assert ();
+ return rc;
+ }
+
+ rc = gnutls_openpgp_keyring_check_id (keyring, id, 0);
+ /* If it exists in the keyring don't treat it as unknown. */
+ if (rc == 0 && *verify & GNUTLS_CERT_SIGNER_NOT_FOUND)
+ *verify ^= GNUTLS_CERT_SIGNER_NOT_FOUND;
+ }
+
+ return 0;
+}
+
+
+/**
+ * gnutls_openpgp_crt_verify_self - Verify the self signature on the key
+ * @key: the structure that holds the key.
+ * @flags: unused (should be 0)
+ * @verify: will hold the key verification output.
+ *
+ * Verifies the self signature in the key.
+ * The key verification output will be put in @verify and will be
+ * one or more of the gnutls_certificate_status_t enumerated elements bitwise or'd.
+ *
+ * GNUTLS_CERT_INVALID: The self signature on the key is invalid.
+ *
+ * Returns 0 on success.
+ **/
+int
+gnutls_openpgp_crt_verify_self (gnutls_openpgp_crt_t key,
+ unsigned int flags, unsigned int *verify)
+{
+ int status;
+ cdk_error_t rc;
+
+ rc = cdk_pk_check_self_sig (key->knode, &status);
+ if (rc || status != CDK_KEY_VALID)
+ *verify |= GNUTLS_CERT_INVALID;
+ else
+ *verify = 0;
+
+ return 0;
+}
+
diff --git a/lib/openpgp/privkey.c b/lib/openpgp/privkey.c
new file mode 100644
index 0000000000..1083e30f22
--- /dev/null
+++ b/lib/openpgp/privkey.c
@@ -0,0 +1,575 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS-EXTRA.
+ *
+ * GNUTLS-EXTRA is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GNUTLS-EXTRA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Functions on OpenPGP privkey parsing
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_datum.h>
+#include <gnutls_global.h>
+#include <gnutls_errors.h>
+#include <gnutls_num.h>
+#include <openpgp.h>
+#include <gnutls_openpgp.h>
+#include <x509/rfc2818.h>
+#include <gnutls_cert.h>
+
+/**
+ * gnutls_openpgp_privkey_init - This function initializes a gnutls_openpgp_privkey_t structure
+ * @key: The structure to be initialized
+ *
+ * This function will initialize an OpenPGP key structure.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int
+gnutls_openpgp_privkey_init (gnutls_openpgp_privkey_t * key)
+{
+ *key = gnutls_calloc (1, sizeof (gnutls_openpgp_privkey_int));
+
+ if (*key)
+ return 0; /* success */
+ return GNUTLS_E_MEMORY_ERROR;
+}
+
+/**
+ * gnutls_openpgp_privkey_deinit - This function deinitializes memory used by a gnutls_openpgp_privkey_t structure
+ * @key: The structure to be initialized
+ *
+ * This function will deinitialize a key structure.
+ *
+ **/
+void
+gnutls_openpgp_privkey_deinit (gnutls_openpgp_privkey_t key)
+{
+ if (!key)
+ return;
+
+ if (key->knode)
+ {
+ cdk_kbnode_release (key->knode);
+ key->knode = NULL;
+ }
+
+ gnutls_free (key);
+}
+
+/**
+ * gnutls_openpgp_privkey_import - This function will import a RAW or BASE64 encoded key
+ * @key: The structure to store the parsed key.
+ * @data: The RAW or BASE64 encoded key.
+ * @format: One of gnutls_openpgp_crt_fmt_t elements.
+ * @pass: Unused for now
+ * @flags: should be zero
+ *
+ * This function will convert the given RAW or Base64 encoded key
+ * to the native gnutls_openpgp_privkey_t format. The output will be stored in 'key'.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int
+gnutls_openpgp_privkey_import (gnutls_openpgp_privkey_t key,
+ const gnutls_datum_t * data,
+ gnutls_openpgp_crt_fmt_t format,
+ const char *pass, unsigned int flags)
+{
+ cdk_stream_t inp;
+ int rc;
+
+ if (format == GNUTLS_OPENPGP_FMT_RAW)
+ rc = cdk_kbnode_read_from_mem (&key->knode, data->data, data->size);
+ else
+ {
+ rc = cdk_stream_tmp_from_mem (data->data, data->size, &inp);
+ if (rc)
+ {
+ rc = _gnutls_map_cdk_rc (rc);
+ gnutls_assert ();
+ return rc;
+ }
+ if (cdk_armor_filter_use (inp))
+ rc = cdk_stream_set_armor_flag (inp, 0);
+ if (!rc)
+ rc = cdk_keydb_get_keyblock (inp, &key->knode);
+ cdk_stream_close (inp);
+ if (rc)
+ {
+ rc = _gnutls_map_cdk_rc (rc);
+ gnutls_assert ();
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+
+/**
+ * gnutls_openpgp_privkey_get_pk_algorithm - This function returns the key's PublicKey algorithm
+ * @key: is an OpenPGP key
+ * @bits: if bits is non null it will hold the size of the parameters' in bits
+ *
+ * This function will return the public key algorithm of an OpenPGP
+ * certificate.
+ *
+ * If bits is non null, it should have enough size to hold the parameters
+ * size in bits. For RSA the bits returned is the modulus.
+ * For DSA the bits returned are of the public exponent.
+ *
+ * Returns a member of the GNUTLS_PKAlgorithm enumeration on success,
+ * or a negative value on error.
+ *
+ **/
+gnutls_pk_algorithm_t
+gnutls_openpgp_privkey_get_pk_algorithm (gnutls_openpgp_privkey_t key,
+ unsigned int *bits)
+{
+ cdk_packet_t pkt;
+ int algo;
+
+ if (!key)
+ return GNUTLS_PK_UNKNOWN;
+
+ algo = 0;
+ pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY);
+ if (pkt)
+ {
+ if (bits)
+ *bits = cdk_pk_get_nbits (pkt->pkt.secret_key->pk);
+ algo = pkt->pkt.secret_key->pk->pubkey_algo;
+ if (is_RSA (algo))
+ algo = GNUTLS_PK_RSA;
+ else if (is_DSA (algo))
+ algo = GNUTLS_PK_DSA;
+ else
+ algo = GNUTLS_PK_UNKNOWN;
+ }
+
+ return algo;
+}
+
+/**
+ * gnutls_openpgp_privkey_get_revoked_ status - Gets the revoked status of the key
+ * @key: the structure that contains the OpenPGP public key.
+ *
+ * Returns the true (1) or false (0) based on whether this key has been revoked
+ * or not. A negative value indicates an error.
+ *
+ **/
+int
+gnutls_openpgp_privkey_get_revoked_status (gnutls_openpgp_privkey_t key)
+{
+ cdk_packet_t pkt;
+
+ if (!key)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY);
+ if (!pkt)
+ return GNUTLS_E_OPENPGP_GETKEY_FAILED;
+
+ if (pkt->pkt.secret_key->is_revoked != 0) return 1;
+ return 0;
+}
+
+/**
+ * gnutls_openpgp_privkey_get_fingerprint - Gets the fingerprint
+ * @key: the raw data that contains the OpenPGP secret key.
+ * @fpr: the buffer to save the fingerprint, must hold at least 20 bytes.
+ * @fprlen: the integer to save the length of the fingerprint.
+ *
+ * Returns the fingerprint of the OpenPGP key. Depends on the algorithm,
+ * the fingerprint can be 16 or 20 bytes.
+ **/
+int
+gnutls_openpgp_privkey_get_fingerprint (gnutls_openpgp_privkey_t key,
+ void *fpr, size_t * fprlen)
+{
+ cdk_packet_t pkt;
+ cdk_pkt_pubkey_t pk = NULL;
+
+ if (!fpr || !fprlen)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ *fprlen = 0;
+
+ pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY);
+ if (!pkt)
+ {
+ gnutls_assert();
+ return GNUTLS_E_OPENPGP_GETKEY_FAILED;
+ }
+
+ pk = pkt->pkt.secret_key->pk;
+ *fprlen = 20;
+
+ if (is_RSA (pk->pubkey_algo) && pk->version < 4)
+ *fprlen = 16;
+
+ cdk_pk_get_fingerprint (pk, fpr);
+
+ return 0;
+}
+
+/**
+ * gnutls_openpgp_privkey_get_key_id - Gets the keyID
+ * @key: the structure that contains the OpenPGP secret key.
+ * @keyid: the buffer to save the keyid.
+ *
+ * Returns the 64-bit keyID of the OpenPGP key.
+ **/
+int
+gnutls_openpgp_privkey_get_key_id (gnutls_openpgp_privkey_t key, gnutls_openpgp_keyid_t* keyid)
+{
+ cdk_packet_t pkt;
+ uint32_t kid[2];
+
+ if (!key || !keyid)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY);
+ if (!pkt)
+ return GNUTLS_E_OPENPGP_GETKEY_FAILED;
+
+ cdk_sk_get_keyid (pkt->pkt.secret_key, kid);
+ _gnutls_write_uint32( kid[0], keyid->keyid);
+ _gnutls_write_uint32( kid[1], keyid->keyid+4);
+
+ return 0;
+}
+
+
+/**
+ * gnutls_openpgp_privkey_get_subkey_count - This function returns the number of subkeys
+ * @key: is an OpenPGP key
+ *
+ * This function will return the number of subkeys present in the given
+ * OpenPGP certificate.
+ *
+ * Returns then number of subkeys or a negative value on error.
+ *
+ **/
+int
+gnutls_openpgp_privkey_get_subkey_count (gnutls_openpgp_privkey_t key)
+{
+ cdk_kbnode_t p, ctx;
+ cdk_packet_t pkt;
+ int subkeys;
+
+ if (key == NULL)
+ {
+ gnutls_assert ();
+ return 0;
+ }
+
+ ctx = NULL;
+ subkeys = 0;
+ while ((p = cdk_kbnode_walk (key->knode, &ctx, 0)))
+ {
+ pkt = cdk_kbnode_get_packet (p);
+ if (pkt->pkttype == CDK_PKT_SECRET_SUBKEY)
+ subkeys++;
+ }
+
+ return subkeys;
+}
+
+/* returns the subkey with the given index */
+static cdk_packet_t _get_secret_subkey(gnutls_openpgp_privkey_t key, unsigned int indx)
+{
+ cdk_kbnode_t p, ctx;
+ cdk_packet_t pkt;
+ int subkeys;
+
+ ctx = NULL;
+ subkeys = 0;
+ while ((p = cdk_kbnode_walk (key->knode, &ctx, 0)))
+ {
+ pkt = cdk_kbnode_get_packet (p);
+ if (pkt->pkttype == CDK_PKT_SECRET_SUBKEY && indx == subkeys++)
+ return pkt;
+ }
+
+ return NULL;
+}
+
+/**
+ * gnutls_openpgp_privkey_get_subkey_revoked_ status - Gets the revoked status of the key
+ * @key: the structure that contains the OpenPGP public key.
+ * @idx: is the subkey index
+ *
+ * Returns the true (1) or false (0) based on whether this key has been revoked
+ * or not. A negative value indicates an error.
+ *
+ **/
+int
+gnutls_openpgp_privkey_get_subkey_revoked_status (gnutls_openpgp_privkey_t key, unsigned int idx)
+{
+ cdk_packet_t pkt;
+
+ if (!key)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ pkt = _get_secret_subkey( key, idx);
+ if (!pkt)
+ return GNUTLS_E_OPENPGP_GETKEY_FAILED;
+
+ if (pkt->pkt.secret_key->is_revoked != 0) return 1;
+ return 0;
+}
+
+/**
+ * gnutls_openpgp_privkey_get_subkey_pk_algorithm - This function returns the subkey's PublicKey algorithm
+ * @key: is an OpenPGP key
+ * @idx: is the subkey index
+ * @bits: if bits is non null it will hold the size of the parameters' in bits
+ *
+ * This function will return the public key algorithm of a subkey of an OpenPGP
+ * certificate.
+ *
+ * If bits is non null, it should have enough size to hold the parameters
+ * size in bits. For RSA the bits returned is the modulus.
+ * For DSA the bits returned are of the public exponent.
+ *
+ * Returns a member of the gnutls_pk_algorithm_t enumeration on success,
+ * or a negative value on error.
+ *
+ **/
+gnutls_pk_algorithm_t
+gnutls_openpgp_privkey_get_subkey_pk_algorithm (gnutls_openpgp_privkey_t key,
+ unsigned int idx, unsigned int *bits)
+{
+ cdk_packet_t pkt;
+ int algo;
+
+ if (!key)
+ return GNUTLS_PK_UNKNOWN;
+
+ pkt = _get_secret_subkey( key, idx);
+
+ algo = 0;
+ if (pkt)
+ {
+ if (bits)
+ *bits = cdk_pk_get_nbits (pkt->pkt.secret_key->pk);
+ algo = pkt->pkt.secret_key->pubkey_algo;
+ if (is_RSA (algo))
+ algo = GNUTLS_PK_RSA;
+ else if (is_DSA (algo))
+ algo = GNUTLS_PK_DSA;
+ else
+ algo = GNUTLS_E_UNKNOWN_PK_ALGORITHM;
+ }
+
+ return algo;
+}
+
+/**
+ * gnutls_openpgp_privkey_get_subkey_idx - Returns the subkey's index
+ * @key: the structure that contains the OpenPGP public key.
+ * @keyid: the keyid.
+ *
+ * Returns the index of the subkey or a negative error value.
+ *
+ **/
+int
+gnutls_openpgp_privkey_get_subkey_idx (gnutls_openpgp_privkey_t key, gnutls_openpgp_keyid_t keyid)
+{
+ cdk_packet_t pkt;
+ int ret;
+ uint32_t kid[2];
+
+ if (!key)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ KEYID_IMPORT( kid, keyid);
+ ret = _gnutls_openpgp_find_subkey_idx( key->knode, kid, 1);
+
+ if (ret < 0)
+ {
+ gnutls_assert();
+ }
+
+ return ret;
+}
+
+/**
+ * gnutls_openpgp_privkey_get_subkey_creation_time - Extract the timestamp
+ * @key: the structure that contains the OpenPGP public key.
+ * @idx: the subkey index
+ *
+ * Returns the timestamp when the OpenPGP key was created.
+ **/
+time_t
+gnutls_openpgp_privkey_get_subkey_creation_time (gnutls_openpgp_privkey_t key, unsigned int idx)
+{
+ cdk_packet_t pkt;
+ time_t timestamp;
+
+ if (!key)
+ return (time_t) - 1;
+
+ pkt = _get_secret_subkey( key, idx);
+ if (pkt)
+ timestamp = pkt->pkt.secret_key->pk->timestamp;
+ else
+ timestamp = 0;
+
+ return timestamp;
+}
+
+/**
+ * gnutls_openpgp_privkey_get_subkey_expiration_time - Extract the expire date
+ * @key: the structure that contains the OpenPGP public key.
+ * @idx: the subkey index
+ *
+ * Returns the time when the OpenPGP key expires. A value of '0' means
+ * that the key doesn't expire at all.
+ **/
+time_t
+gnutls_openpgp_privkey_get_subkey_expiration_time (gnutls_openpgp_privkey_t key, unsigned int idx)
+{
+ cdk_packet_t pkt;
+ time_t expiredate;
+
+ if (!key)
+ return (time_t) - 1;
+
+ pkt = _get_secret_subkey( key, idx);
+ if (pkt)
+ expiredate = pkt->pkt.secret_key->expiredate;
+ else
+ expiredate = 0;
+
+ return expiredate;
+}
+
+/**
+ * gnutls_openpgp_privkey_get_subkey_id - Gets the keyID
+ * @key: the structure that contains the OpenPGP secret key.
+ * @idx: the subkey index
+ * @keyid: the buffer to save the keyid.
+ *
+ * Returns the 64-bit keyID of the OpenPGP key.
+ **/
+int
+gnutls_openpgp_privkey_get_subkey_id (gnutls_openpgp_privkey_t key, unsigned int idx, gnutls_openpgp_keyid_t* keyid)
+{
+ cdk_packet_t pkt;
+ uint32_t kid[2];
+
+ if (!key || !keyid)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ pkt = _get_secret_subkey( key, idx);
+ if (!pkt)
+ return GNUTLS_E_OPENPGP_GETKEY_FAILED;
+
+ cdk_sk_get_keyid (pkt->pkt.secret_key, kid);
+ _gnutls_write_uint32( kid[0], keyid->keyid);
+ _gnutls_write_uint32( kid[1], keyid->keyid+4);
+
+ return 0;
+}
+
+/* Extracts DSA and RSA parameters from a certificate.
+ */
+int
+_gnutls_openpgp_privkey_get_mpis (gnutls_openpgp_privkey_t pkey, uint32_t keyid[2],
+ mpi_t * params, int *params_size)
+{
+ int result, i;
+ int pk_algorithm, local_params;
+ cdk_packet_t pkt;
+
+ /* Read the algorithm's OID
+ */
+ pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm (pkey, NULL);
+
+ switch (pk_algorithm)
+ {
+ case GNUTLS_PK_RSA:
+ local_params = RSA_PRIVATE_PARAMS;
+ break;
+ case GNUTLS_PK_DSA:
+ local_params = DSA_PRIVATE_PARAMS;
+ break;
+ default:
+ gnutls_assert ();
+ return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
+ }
+
+ if (*params_size < local_params)
+ {
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ *params_size = local_params;
+
+ pkt = _gnutls_openpgp_find_key( pkey->knode, keyid, 1);
+ if (pkt == NULL)
+ {
+ gnutls_assert();
+ return GNUTLS_E_OPENPGP_GETKEY_FAILED;
+ }
+
+ for (i = 0; i < local_params; i++)
+ {
+ result = _gnutls_read_pgp_mpi( pkt, 1, i, &params[i]);
+ if (result < 0)
+ {
+ gnutls_assert();
+ goto error;
+ }
+ }
+
+ return 0;
+
+error:
+ {
+ int j;
+ for (j=0;j<i;j++)
+ _gnutls_mpi_release( &params[j]);
+ }
+
+ return result;
+}