summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos <nmav@crystal.(none)>2008-01-13 15:15:51 +0200
committerNikos <nmav@crystal.(none)>2008-01-13 15:15:51 +0200
commiteeef9f65970e7461bbf7bc132db9a9984ca09512 (patch)
tree38aa94dcb64b29edfd7cd273b7f421ffdac2da42
parent0aaecd8f619334d59612c9817048c412a95b5a48 (diff)
downloadgnutls_2_2_x_with_opencdk.tar.gz
Several additions to openpgp code. Now it correctly handles subkeys.gnutls_2_2_x_with_opencdk
-rw-r--r--includes/gnutls/openpgp.h37
-rw-r--r--lib/auth_cert.c55
-rw-r--r--lib/gnutls_cert.c25
-rw-r--r--lib/gnutls_cert.h4
-rw-r--r--lib/gnutls_openpgp.c433
-rw-r--r--lib/opencdk/kbnode.c5
-rw-r--r--lib/opencdk/keydb.c16
-rw-r--r--lib/opencdk/opencdk.h13
-rw-r--r--lib/opencdk/pubkey.c6
-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.c9
-rw-r--r--lib/openpgp/pgp.c1079
-rw-r--r--lib/openpgp/pgpverify.c144
-rw-r--r--lib/openpgp/privkey.c575
-rw-r--r--libextra/Makefile.am4
19 files changed, 2769 insertions, 311 deletions
diff --git a/includes/gnutls/openpgp.h b/includes/gnutls/openpgp.h
index 134ab0c6f5..850dfa08c5 100644
--- a/includes/gnutls/openpgp.h
+++ b/includes/gnutls/openpgp.h
@@ -37,6 +37,11 @@ extern "C"
#include <gnutls/gnutls.h>
#include <gnutls/extra.h>
+ typedef struct
+ {
+ unsigned char keyid[8];
+ } gnutls_openpgp_keyid_t;
+
/* gnutls_openpgp_cert_t should be defined in gnutls.h
*/
@@ -78,7 +83,7 @@ extern "C"
time_t gnutls_openpgp_crt_get_expiration_time (gnutls_openpgp_crt_t key);
int gnutls_openpgp_crt_get_id (gnutls_openpgp_crt_t key,
- unsigned char keyid[8]);
+ gnutls_openpgp_keyid_t* keyid);
int gnutls_openpgp_crt_check_hostname (gnutls_openpgp_crt_t key,
const char *hostname);
@@ -86,12 +91,13 @@ extern "C"
int gnutls_openpgp_crt_get_revoked_status (gnutls_openpgp_crt_t key);
int gnutls_openpgp_crt_get_subkey_count (gnutls_openpgp_crt_t key);
+ int gnutls_openpgp_crt_get_subkey_idx (gnutls_openpgp_crt_t key, gnutls_openpgp_keyid_t keyid);
int gnutls_openpgp_crt_get_subkey_revoked_status (gnutls_openpgp_crt_t key, unsigned int idx);
gnutls_pk_algorithm_t gnutls_openpgp_crt_get_subkey_pk_algorithm (gnutls_openpgp_crt_t key,
unsigned int idx, unsigned int *bits);
time_t gnutls_openpgp_crt_get_subkey_creation_time (gnutls_openpgp_crt_t key, unsigned int idx);
time_t gnutls_openpgp_crt_get_subkey_expiration_time (gnutls_openpgp_crt_t key, unsigned int idx);
- int gnutls_openpgp_crt_get_subkey_id (gnutls_openpgp_crt_t key, unsigned int idx, unsigned char keyid[8]);
+ int gnutls_openpgp_crt_get_subkey_id (gnutls_openpgp_crt_t key, unsigned int idx, gnutls_openpgp_keyid_t* keyid);
int gnutls_openpgp_crt_get_subkey_usage (gnutls_openpgp_crt_t key, unsigned int idx,
unsigned int *key_usage);
@@ -107,14 +113,33 @@ extern "C"
gnutls_openpgp_crt_fmt_t format,
const char *pass, unsigned int flags);
int gnutls_openpgp_privkey_sign_hash (gnutls_openpgp_privkey_t key,
- const gnutls_datum_t * hash,
- gnutls_datum_t * signature);
+ gnutls_openpgp_keyid_t subkeyid,
+ const gnutls_datum_t * hash,
+ gnutls_datum_t * signature);
+ int gnutls_openpgp_privkey_get_fingerprint (gnutls_openpgp_privkey_t key,
+ void *fpr, size_t * fprlen);
+ int gnutls_openpgp_privkey_get_key_id (gnutls_openpgp_privkey_t key, gnutls_openpgp_keyid_t* keyid);
+ int gnutls_openpgp_privkey_get_subkey_count (gnutls_openpgp_privkey_t key);
+ int gnutls_openpgp_privkey_get_subkey_idx (gnutls_openpgp_privkey_t key, gnutls_openpgp_keyid_t keyid);
+
+ int gnutls_openpgp_privkey_get_subkey_revoked_status (gnutls_openpgp_privkey_t key, unsigned int idx);
+
+ int gnutls_openpgp_privkey_get_revoked_status (gnutls_openpgp_privkey_t key);
+
+ gnutls_pk_algorithm_t gnutls_openpgp_privkey_get_subkey_pk_algorithm (gnutls_openpgp_privkey_t key,
+ unsigned int idx, unsigned int *bits);
+
+ time_t gnutls_openpgp_privkey_get_subkey_expiration_time (gnutls_openpgp_privkey_t key, unsigned int idx);
+
+ int gnutls_openpgp_privkey_get_subkey_id (gnutls_openpgp_privkey_t key, unsigned int idx, gnutls_openpgp_keyid_t* keyid);
+
+ time_t gnutls_openpgp_privkey_get_subkey_creation_time (gnutls_openpgp_privkey_t key, unsigned int idx);
/* Keyring stuff.
*/
struct gnutls_openpgp_keyring_int; /* object to hold (parsed) openpgp keyrings */
typedef struct gnutls_openpgp_keyring_int *gnutls_openpgp_keyring_t;
-
+
int gnutls_openpgp_keyring_init (gnutls_openpgp_keyring_t * keyring);
void gnutls_openpgp_keyring_deinit (gnutls_openpgp_keyring_t keyring);
@@ -123,7 +148,7 @@ extern "C"
gnutls_openpgp_crt_fmt_t format);
int gnutls_openpgp_keyring_check_id (gnutls_openpgp_keyring_t ring,
- const unsigned char keyid[8],
+ gnutls_openpgp_keyid_t keyid,
unsigned int flags);
diff --git a/lib/auth_cert.c b/lib/auth_cert.c
index c17b9df3ac..3f97b1e50f 100644
--- a/lib/auth_cert.c
+++ b/lib/auth_cert.c
@@ -48,9 +48,11 @@
#ifdef ENABLE_OPENPGP
# include "openpgp/gnutls_openpgp.h"
-static gnutls_cert *alloc_and_load_pgp_certs (gnutls_openpgp_crt_t cert);
-static gnutls_privkey *alloc_and_load_pgp_key (const gnutls_openpgp_privkey_t
- key);
+static gnutls_privkey *
+alloc_and_load_pgp_key (const gnutls_openpgp_privkey_t key, gnutls_openpgp_keyid_t keyid);
+static gnutls_cert *
+alloc_and_load_pgp_certs (gnutls_openpgp_crt_t cert, gnutls_openpgp_keyid_t* keyid);
+
#endif
static gnutls_cert *alloc_and_load_x509_certs (gnutls_x509_crt_t * certs,
@@ -445,8 +447,16 @@ call_get_cert_callback (gnutls_session_t session,
if (type == GNUTLS_CRT_X509)
{
local_certs = alloc_and_load_x509_certs (st.cert.x509, st.ncerts);
- if (local_certs != NULL)
- local_key = alloc_and_load_x509_key (st.key.x509);
+ if (local_certs != NULL)
+ {
+ local_key = alloc_and_load_x509_key (st.key.x509);
+ if (local_key == NULL)
+ {
+ gnutls_assert();
+ ret = GNUTLS_E_INTERNAL_ERROR;
+ goto cleanup;
+ }
+ }
}
else
@@ -459,9 +469,21 @@ call_get_cert_callback (gnutls_session_t session,
}
#ifdef ENABLE_OPENPGP
- local_certs = alloc_and_load_pgp_certs (st.cert.pgp);
- if (local_certs != NULL)
- local_key = alloc_and_load_pgp_key (st.key.pgp);
+ {
+ gnutls_openpgp_keyid_t selected_keyid;
+
+ local_certs = alloc_and_load_pgp_certs (st.cert.pgp, &selected_keyid);
+ if (local_certs != NULL)
+ {
+ local_key = alloc_and_load_pgp_key (st.key.pgp, selected_keyid);
+ if (local_key == NULL)
+ {
+ gnutls_assert();
+ ret = GNUTLS_E_INTERNAL_ERROR;
+ goto cleanup;
+ }
+ }
+ }
#endif
}
@@ -1102,7 +1124,7 @@ _gnutls_proc_openpgp_server_certificate (gnutls_session_t session,
peer_certificate_list_size);
if ((ret =
- _gnutls_openpgp_raw_key_to_gcert (&peer_certificate_list[0],
+ _gnutls_openpgp_raw_crt_to_gcert (&peer_certificate_list[0],
&tmp)) < 0)
{
gnutls_assert ();
@@ -1578,7 +1600,7 @@ alloc_and_load_x509_key (gnutls_x509_privkey_t key)
*/
#ifdef ENABLE_OPENPGP
static gnutls_cert *
-alloc_and_load_pgp_certs (gnutls_openpgp_crt_t cert)
+alloc_and_load_pgp_certs (gnutls_openpgp_crt_t cert, gnutls_openpgp_keyid_t* keyid)
{
gnutls_cert *local_certs;
int ret = 0;
@@ -1593,7 +1615,14 @@ alloc_and_load_pgp_certs (gnutls_openpgp_crt_t cert)
return NULL;
}
- ret = _gnutls_openpgp_crt_to_gcert (local_certs, cert);
+ ret = _gnutls_openpgp_find_valid_subkey( cert, keyid);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return NULL;
+ }
+
+ ret = _gnutls_openpgp_crt_to_gcert (local_certs, cert, *keyid);
if (ret < 0)
{
gnutls_assert ();
@@ -1615,7 +1644,7 @@ alloc_and_load_pgp_certs (gnutls_openpgp_crt_t cert)
* space for it.
*/
static gnutls_privkey *
-alloc_and_load_pgp_key (const gnutls_openpgp_privkey_t key)
+alloc_and_load_pgp_key (const gnutls_openpgp_privkey_t key, gnutls_openpgp_keyid_t keyid)
{
gnutls_privkey *local_key;
int ret = 0;
@@ -1630,7 +1659,7 @@ alloc_and_load_pgp_key (const gnutls_openpgp_privkey_t key)
return NULL;
}
- ret = _gnutls_openpgp_privkey_to_gkey (local_key, key);
+ ret = _gnutls_openpgp_privkey_to_gkey (local_key, key, keyid);
if (ret < 0)
{
gnutls_assert ();
diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c
index f0378f4fbb..669deb33cc 100644
--- a/lib/gnutls_cert.c
+++ b/lib/gnutls_cert.c
@@ -695,7 +695,7 @@ _gnutls_raw_cert_to_gcert (gnutls_cert * gcert,
return _gnutls_x509_raw_cert_to_gcert (gcert, raw_cert, flags);
#ifdef ENABLE_OPENPGP
case GNUTLS_CRT_OPENPGP:
- return _gnutls_openpgp_raw_key_to_gcert (gcert, raw_cert);
+ return _gnutls_openpgp_raw_crt_to_gcert (gcert, raw_cert);
#endif
default:
gnutls_assert ();
@@ -703,29 +703,6 @@ _gnutls_raw_cert_to_gcert (gnutls_cert * gcert,
}
}
-int
-_gnutls_raw_privkey_to_gkey (gnutls_privkey * key,
- gnutls_certificate_type_t type,
- const gnutls_datum_t * raw_key,
- int key_enc /* DER or PEM */ )
-{
- switch (type)
- {
- case GNUTLS_CRT_X509:
- return _gnutls_x509_raw_privkey_to_gkey (key, raw_key, key_enc);
-#ifdef ENABLE_OPENPGP
- case GNUTLS_CRT_OPENPGP:
- return _gnutls_openpgp_raw_privkey_to_gkey (key, raw_key,
- (gnutls_openpgp_crt_fmt_t)
- key_enc);
-#endif
- default:
- gnutls_assert ();
- return GNUTLS_E_INTERNAL_ERROR;
- }
-}
-
-
/* This function will convert a der certificate to a format
* (structure) that gnutls can understand and use. Actually the
* important thing on this function is that it extracts the
diff --git a/lib/gnutls_cert.h b/lib/gnutls_cert.h
index 6ce0847368..3101e6825c 100644
--- a/lib/gnutls_cert.h
+++ b/lib/gnutls_cert.h
@@ -124,9 +124,5 @@ int _gnutls_raw_cert_to_gcert (gnutls_cert * gcert,
gnutls_certificate_type_t type,
const gnutls_datum_t * raw_cert,
int flags /* OR of ConvFlags */ );
-int _gnutls_raw_privkey_to_gkey (gnutls_privkey * key,
- gnutls_certificate_type_t type,
- const gnutls_datum_t * raw_key,
- int key_enc /* DER or PEM */ );
#endif
diff --git a/lib/gnutls_openpgp.c b/lib/gnutls_openpgp.c
index 0584cb9804..8e95b53806 100644
--- a/lib/gnutls_openpgp.c
+++ b/lib/gnutls_openpgp.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation
*
- * Author: Timo Schulz
+ * Author: Timo Schulz, Nikos Mavrogiannopoulos
*
* This file is part of GNUTLS-EXTRA.
*
@@ -22,6 +22,7 @@
#include "gnutls_int.h"
#include "gnutls_errors.h"
#include "gnutls_mpi.h"
+#include "gnutls_num.h"
#include "gnutls_cert.h"
#include "gnutls_datum.h"
#include "gnutls_global.h"
@@ -34,8 +35,6 @@
#include <time.h>
#include <sys/stat.h>
-#define OPENPGP_NAME_SIZE 256
-
#define datum_append(x, y, z) _gnutls_datum_append_m (x, y, z, gnutls_realloc)
@@ -82,185 +81,53 @@ _gnutls_map_cdk_rc (int rc)
}
}
-
-static unsigned long
-buftou32 (const uint8_t * buf)
-{
- unsigned a;
- a = buf[0] << 24;
- a |= buf[1] << 16;
- a |= buf[2] << 8;
- a |= buf[3];
- return a;
-}
-
-static int
-openpgp_pk_to_gnutls_cert (gnutls_cert * cert, cdk_pkt_pubkey_t pk)
+/* Finds a subkey to use for authentication
+ */
+int _gnutls_openpgp_find_valid_subkey( gnutls_openpgp_crt_t crt, gnutls_openpgp_keyid_t* keyid)
{
- uint8_t buf[512+2];
- size_t nbytes;
- int algo, i;
- int rc = 0;
+ int ret, subkeys, i;
+ unsigned int usage;
- if (!cert || !pk)
+ subkeys = gnutls_openpgp_crt_get_subkey_count( crt);
+ if (subkeys <= 0)
{
- gnutls_assert ();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- /* GnuTLS OpenPGP does not support ELG keys */
- if (is_ELG (pk->pubkey_algo))
- return GNUTLS_E_UNWANTED_ALGORITHM;
-
- algo = is_DSA (pk->pubkey_algo) ? GNUTLS_PK_DSA : GNUTLS_PK_RSA;
- cert->subject_pk_algorithm = algo;
- cert->version = pk->version;
- cert->cert_type = GNUTLS_CRT_OPENPGP;
-
- cert->key_usage = 0;
- if (pk->pubkey_usage & CDK_KEY_USG_SIGN)
- cert->key_usage = KEY_DIGITAL_SIGNATURE;
- if (pk->pubkey_usage & CDK_KEY_USG_ENCR)
- cert->key_usage = KEY_KEY_ENCIPHERMENT;
- if (!cert->key_usage) /* Fallback code. */
- {
- if (pk->pubkey_algo == GCRY_PK_DSA || pk->pubkey_algo == GCRY_PK_RSA_S)
- cert->key_usage = KEY_DIGITAL_SIGNATURE;
- else if (pk->pubkey_algo == GCRY_PK_RSA_E)
- cert->key_usage = KEY_KEY_ENCIPHERMENT;
- else if (pk->pubkey_algo == GCRY_PK_RSA)
- cert->key_usage = KEY_DIGITAL_SIGNATURE | KEY_KEY_ENCIPHERMENT;
- }
-
- cert->params_size = cdk_pk_get_npkey (pk->pubkey_algo);
- for (i = 0; i < cert->params_size; i++)
- {
- nbytes = sizeof (buf) / sizeof (buf[0]);
- cdk_pk_get_mpi (pk, i, buf, nbytes, &nbytes, NULL);
- rc = _gnutls_mpi_scan_pgp (&cert->params[i], buf, &nbytes);
- if (rc)
- {
- rc = GNUTLS_E_MPI_SCAN_FAILED;
- break;
- }
+ gnutls_assert();
+ return GNUTLS_E_OPENPGP_SUBKEY_ERROR;
}
- if (rc)
- release_mpi_array (cert->params, i - 1);
- return rc;
-}
-
-/*-
- * _gnutls_openpgp_raw_privkey_to_gkey - Converts an OpenPGP secret key to GnuTLS
- * @pkey: the GnuTLS private key context to store the key.
- * @raw_key: the raw data which contains the whole key packets.
- * @format: the format of the key packets.
- *
- * The RFC2440 (OpenPGP Message Format) data is converted into the
- * GnuTLS specific data which is need to perform secret key operations.
- *
- * This function can read both BASE64 and RAW keys.
- *
- * FIXME: use the internal API
- -*/
-int
-_gnutls_openpgp_raw_privkey_to_gkey (gnutls_privkey * pkey,
- const gnutls_datum_t * raw_key,
- gnutls_openpgp_crt_fmt_t format)
-{
- cdk_kbnode_t snode = NULL;
- cdk_packet_t pkt;
- cdk_stream_t out;
- cdk_pkt_seckey_t sk = NULL;
- int pke_algo, i, j;
- size_t nbytes = 0;
- uint8_t buf[512];
- int rc = 0;
-
- if (!pkey || raw_key->size <= 0)
+ /* Try to find a subkey with the authentication flag set.
+ * if none exists use the last one found
+ */
+ for (i=0;i<subkeys;i++)
{
- gnutls_assert ();
- return GNUTLS_E_CERTIFICATE_ERROR;
- }
- rc = cdk_stream_tmp_new (&out);
- if (rc)
- return GNUTLS_E_CERTIFICATE_ERROR;
+ ret = gnutls_openpgp_crt_get_subkey_revoked_status(crt, i);
+ if (ret != 0) /* it is revoked. ignore it */
+ continue;
- if (format == GNUTLS_OPENPGP_FMT_BASE64)
- {
- rc = cdk_stream_set_armor_flag (out, 0);
- if (rc)
- {
- cdk_stream_close (out);
- rc = _gnutls_map_cdk_rc (rc);
- gnutls_assert ();
- goto leave;
- }
- }
+ ret = gnutls_openpgp_crt_get_subkey_id( crt, i, keyid);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
- cdk_stream_write (out, raw_key->data, raw_key->size);
- cdk_stream_seek (out, 0);
+ ret = gnutls_openpgp_crt_get_subkey_usage( crt, i, &usage);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
- rc = cdk_keydb_get_keyblock (out, &snode);
- cdk_stream_close (out);
- if (rc)
- {
- rc = GNUTLS_E_OPENPGP_GETKEY_FAILED;
- goto leave;
- }
-
- pkt = _gnutls_get_valid_subkey( snode, CDK_PKT_SECRET_SUBKEY);
- if (!pkt)
- {
- rc = GNUTLS_E_OPENPGP_SUBKEY_ERROR;
- goto leave;
- }
- sk = pkt->pkt.secret_key;
- pke_algo = sk->pk->pubkey_algo;
- pkey->params_size = cdk_pk_get_npkey (pke_algo);
- for (i = 0; i < pkey->params_size; i++)
- {
- nbytes = sizeof (buf) / sizeof (buf[0]);
- cdk_pk_get_mpi (sk->pk, i, buf, nbytes, &nbytes, NULL);
- rc = _gnutls_mpi_scan_pgp (&pkey->params[i], buf, &nbytes);
- if (rc)
- {
- rc = GNUTLS_E_MPI_SCAN_FAILED;
- release_mpi_array (pkey->params, i - 1);
- goto leave;
- }
- }
-
- pkey->params_size += cdk_pk_get_nskey (pke_algo);
- for (j = 0; j < cdk_pk_get_nskey (pke_algo); j++, i++)
- {
- nbytes = sizeof (buf) / sizeof (buf[0]);
- cdk_sk_get_mpi (sk, j, buf, nbytes, &nbytes, NULL);
- rc = _gnutls_mpi_scan_pgp (&pkey->params[i], buf, &nbytes);
- if (rc)
- {
- rc = GNUTLS_E_MPI_SCAN_FAILED;
- release_mpi_array (pkey->params, i - 1);
- goto leave;
- }
+ if (usage & GNUTLS_KEY_KEY_AGREEMENT)
+ break;
}
- if (is_ELG (pke_algo))
- return GNUTLS_E_UNWANTED_ALGORITHM;
- else if (is_DSA (pke_algo))
- pkey->pk_algorithm = GNUTLS_PK_DSA;
- else if (is_RSA (pke_algo))
- pkey->pk_algorithm = GNUTLS_PK_RSA;
-
-leave:
- cdk_kbnode_release (snode);
- return rc;
+ return 0;
}
-
/*-
- * _gnutls_openpgp_raw_key_to_gcert - Converts raw OpenPGP data to GnuTLS certs
+ * _gnutls_openpgp_raw_crt_to_gcert - Converts raw OpenPGP data to GnuTLS certs
* @cert: the certificate to store the data.
* @raw: the buffer which contains the whole OpenPGP key packets.
*
@@ -268,37 +135,40 @@ leave:
* specific certificate.
-*/
int
-_gnutls_openpgp_raw_key_to_gcert (gnutls_cert * cert,
+_gnutls_openpgp_raw_crt_to_gcert (gnutls_cert * gcert,
const gnutls_datum_t * raw)
{
- cdk_kbnode_t knode = NULL;
- cdk_packet_t pkt = NULL;
- int rc;
+ int ret;
+ gnutls_openpgp_crt_t pcrt;
+ gnutls_openpgp_keyid_t keyid;
- if (!cert)
+ ret = gnutls_openpgp_crt_init (&pcrt);
+ if (ret < 0)
{
gnutls_assert ();
- return GNUTLS_E_INVALID_REQUEST;
+ return ret;
}
- memset (cert, 0, sizeof *cert);
-
- rc = cdk_kbnode_read_from_mem (&knode, raw->data, raw->size);
- if (!(rc = _gnutls_map_cdk_rc (rc))) {
- pkt = _gnutls_get_valid_subkey( knode, CDK_PKT_PUBLIC_SUBKEY);
- }
- if (!pkt)
+ ret = gnutls_openpgp_crt_import (pcrt, raw, GNUTLS_OPENPGP_FMT_RAW);
+ if (ret < 0)
{
gnutls_assert ();
- rc = GNUTLS_E_OPENPGP_SUBKEY_ERROR;
+ gnutls_openpgp_crt_deinit (pcrt);
+ return ret;
}
- if (!rc)
- rc = _gnutls_set_datum (&cert->raw, raw->data, raw->size);
- if (!rc)
- rc = openpgp_pk_to_gnutls_cert (cert, pkt->pkt.public_key);
- cdk_kbnode_release (knode);
- return rc;
+ ret = _gnutls_openpgp_find_valid_subkey( pcrt, &keyid);
+
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+
+ ret = _gnutls_openpgp_crt_to_gcert (gcert, pcrt, keyid);
+ gnutls_openpgp_crt_deinit (pcrt);
+
+ return ret;
}
/**
@@ -319,6 +189,15 @@ gnutls_certificate_set_openpgp_key (gnutls_certificate_credentials_t
gnutls_openpgp_privkey_t pkey)
{
int ret;
+ gnutls_openpgp_keyid_t keyid;
+
+ ret = _gnutls_openpgp_find_valid_subkey( crt, &keyid);
+
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
/* this should be first */
@@ -331,7 +210,7 @@ gnutls_certificate_set_openpgp_key (gnutls_certificate_credentials_t
return GNUTLS_E_MEMORY_ERROR;
}
- ret = _gnutls_openpgp_privkey_to_gkey (&res->pkey[res->ncerts], pkey);
+ ret = _gnutls_openpgp_privkey_to_gkey (&res->pkey[res->ncerts], pkey, keyid);
if (ret < 0)
{
gnutls_assert ();
@@ -366,7 +245,7 @@ gnutls_certificate_set_openpgp_key (gnutls_certificate_credentials_t
res->cert_list_length[res->ncerts] = 1;
- ret = _gnutls_openpgp_crt_to_gcert (res->cert_list[res->ncerts], crt);
+ ret = _gnutls_openpgp_crt_to_gcert (res->cert_list[res->ncerts], crt, keyid);
if (ret < 0)
{
gnutls_assert ();
@@ -413,13 +292,13 @@ gnutls_openpgp_get_key (gnutls_datum_t * key,
if (by == KEY_ATTR_SHORT_KEYID)
{
- keyid[0] = buftou32 (pattern);
+ keyid[0] = _gnutls_read_uint32(pattern);
desc = keyid;
}
else if (by == KEY_ATTR_KEYID)
{
- keyid[0] = buftou32 (pattern);
- keyid[1] = buftou32 (pattern + 4);
+ keyid[0] = _gnutls_read_uint32(pattern);
+ keyid[1] = _gnutls_read_uint32(pattern + 4);
desc = keyid;
}
else
@@ -841,84 +720,123 @@ gnutls_openpgp_set_recv_key_function (gnutls_session_t session,
/* Copies a gnutls_openpgp_privkey_t to a gnutls_privkey structure. */
int
_gnutls_openpgp_privkey_to_gkey (gnutls_privkey * dest,
- gnutls_openpgp_privkey_t src)
+ gnutls_openpgp_privkey_t src, gnutls_openpgp_keyid_t keyid)
{
- int i, ret;
-
- memset (dest, 0, sizeof (gnutls_privkey));
-
- for (i = 0; i < src->pkey.params_size; i++)
+ int ret = 0, idx;
+ uint32_t kid32[2];
+
+ if (dest==NULL || src == NULL)
{
- dest->params[i] = _gnutls_mpi_copy (src->pkey.params[i]);
- if (dest->params[i] == NULL)
- {
- gnutls_assert ();
- ret = GNUTLS_E_MEMORY_ERROR;
- goto cleanup;
- }
+ gnutls_assert ();
+ return GNUTLS_E_CERTIFICATE_ERROR;
}
- dest->pk_algorithm = src->pkey.pk_algorithm;
- dest->params_size = src->pkey.params_size;
-
+ KEYID_IMPORT(kid32, keyid);
+
+ idx = gnutls_openpgp_privkey_get_subkey_idx( src, keyid);
+ if (idx < 0)
+ {
+ gnutls_assert();
+ return idx;
+ }
+
+ dest->pk_algorithm = gnutls_openpgp_privkey_get_subkey_pk_algorithm( src, idx, NULL);
+
+ dest->params_size = MAX_PRIV_PARAMS_SIZE;
+ ret = _gnutls_openpgp_privkey_get_mpis( src, kid32, dest->params, &dest->params_size);
+
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+
return 0;
-cleanup:
- for (i = 0; i < src->pkey.params_size; i++)
- _gnutls_mpi_release (&dest->params[i]);
- return ret;
}
/* Converts a parsed gnutls_openpgp_crt_t to a gnutls_cert structure.
*/
int
-_gnutls_openpgp_crt_to_gcert (gnutls_cert * gcert, gnutls_openpgp_crt_t cert)
+_gnutls_openpgp_crt_to_gcert (gnutls_cert * gcert, gnutls_openpgp_crt_t cert,
+ gnutls_openpgp_keyid_t keyid)
{
- opaque *der;
- size_t der_size = 0;
- gnutls_datum_t raw;
- int ret;
+ int ret, idx;
+ uint32_t kid32[2];
+
+ KEYID_IMPORT(kid32, keyid);
memset (gcert, 0, sizeof (gnutls_cert));
gcert->cert_type = GNUTLS_CRT_OPENPGP;
-
- ret = gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW,
- NULL, &der_size);
- if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
+ idx = gnutls_openpgp_crt_get_subkey_idx( cert, keyid);
+ if (idx < 0)
{
- gnutls_assert ();
- return ret;
+ gnutls_assert();
+ return idx;
}
- der = gnutls_malloc (der_size);
- if (der == NULL)
- {
- gnutls_assert ();
- return GNUTLS_E_MEMORY_ERROR;
- }
+ gcert->subject_pk_algorithm = gnutls_openpgp_crt_get_subkey_pk_algorithm( cert, idx, NULL);
+ gcert->version = gnutls_openpgp_crt_get_version( cert);
+
+ gnutls_openpgp_crt_get_subkey_usage( cert, idx, &gcert->key_usage);
- ret = gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW,
- der, &der_size);
+ gcert->params_size = MAX_PUBLIC_PARAMS_SIZE;
+ ret = _gnutls_openpgp_crt_get_mpis( cert, kid32, gcert->params, &gcert->params_size);
+
if (ret < 0)
{
- gnutls_assert ();
- gnutls_free (der);
+ gnutls_assert();
return ret;
}
- raw.data = der;
- raw.size = der_size;
+ { /* copy the raw certificate */
+#define SMALL_RAW 512
+ opaque *raw;
+ size_t raw_size = SMALL_RAW;
- ret = _gnutls_openpgp_raw_key_to_gcert (gcert, &raw);
- if (ret < 0)
- {
- gnutls_assert ();
- gnutls_free (der);
- return ret;
- }
+ /* initially allocate a bogus size, just in case the certificate
+ * fits in it. That way we minimize the DER encodings performed.
+ */
+ raw = gnutls_malloc (raw_size);
+ if (raw == NULL)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
- gnutls_free (der);
+ ret =
+ gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW, raw, &raw_size);
+ if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
+ {
+ gnutls_assert ();
+ gnutls_free (raw);
+ return ret;
+ }
+
+ if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
+ {
+ raw = gnutls_realloc (raw, raw_size);
+ if (raw == NULL)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ ret =
+ gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW, raw,
+ &raw_size);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ gnutls_free (raw);
+ return ret;
+ }
+ }
+
+ gcert->raw.data = raw;
+ gcert->raw.size = raw_size;
+ }
return 0;
@@ -928,20 +846,28 @@ _gnutls_openpgp_crt_to_gcert (gnutls_cert * gcert, gnutls_openpgp_crt_t cert)
/**
* gnutls_openpgp_privkey_sign_hash - This function will sign the given data using the private key params
* @key: Holds the key
+ * @src_keyid: Holds the keyid to be used
* @hash: holds the data to be signed
* @signature: will contain newly allocated signature
*
* This function will sign the given hash using the private key.
+ * You should use gnutls_openpgp_privkey_set_subkey() before calling this function
+ * to set the subkey to use.
*
* Return value: In case of failure a negative value will be returned,
* and 0 on success.
**/
int
gnutls_openpgp_privkey_sign_hash (gnutls_openpgp_privkey_t key,
+ gnutls_openpgp_keyid_t src_keyid,
const gnutls_datum_t * hash,
gnutls_datum_t * signature)
{
- int result;
+int result, i;
+uint32_t keyid[2];
+mpi_t params[MAX_PUBLIC_PARAMS_SIZE];
+int params_size = MAX_PUBLIC_PARAMS_SIZE;
+int pk_algorithm;
if (key == NULL)
{
@@ -949,8 +875,23 @@ gnutls_openpgp_privkey_sign_hash (gnutls_openpgp_privkey_t key,
return GNUTLS_E_INVALID_REQUEST;
}
- result = _gnutls_sign (key->pkey.pk_algorithm, key->pkey.params,
- key->pkey.params_size, hash, signature);
+ KEYID_IMPORT( keyid, src_keyid);
+
+ result = _gnutls_openpgp_privkey_get_mpis( key, keyid, params, &params_size);
+ if (result < 0)
+ {
+ gnutls_assert ();
+ return result;
+ }
+
+ pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm (key, NULL);
+
+ result = _gnutls_sign (pk_algorithm, params,
+ params_size, hash, signature);
+
+ for (i=0;i<params_size;i++)
+ _gnutls_mpi_release( &params[i]);
+
if (result < 0)
{
gnutls_assert ();
diff --git a/lib/opencdk/kbnode.c b/lib/opencdk/kbnode.c
index 9106356dbc..dd76fd74d5 100644
--- a/lib/opencdk/kbnode.c
+++ b/lib/opencdk/kbnode.c
@@ -529,7 +529,10 @@ cdk_kbnode_write_to_mem (cdk_kbnode_t node, byte *buf, size_t *r_nbytes)
return 0;
}
if (*r_nbytes < len)
- rc = CDK_Too_Short;
+ {
+ *r_nbytes = len;
+ rc = CDK_Too_Short;
+ }
if (!rc)
*r_nbytes = cdk_stream_read (s, buf, len);
cdk_stream_close (s);
diff --git a/lib/opencdk/keydb.c b/lib/opencdk/keydb.c
index 588c233ab7..79b7b89c5a 100644
--- a/lib/opencdk/keydb.c
+++ b/lib/opencdk/keydb.c
@@ -1504,12 +1504,20 @@ keydb_merge_selfsig (cdk_kbnode_t key, u32 *keyid)
s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_KEY_FLAGS);
if (s)
{
- if (s->d[0] & 0x03) /* cert + sign data */
- key_usage |= CDK_KEY_USG_SIGN;
- if (s->d[0] & 0x0C) /* encrypt comm. + storage */
- key_usage |= CDK_KEY_USG_ENCR;
+ if (s->d[0] & 0x01) /* cert + sign data */
+ key_usage |= CDK_KEY_USG_CERT_SIGN;
+ if (s->d[0] & 0x02) /* cert + sign data */
+ key_usage |= CDK_KEY_USG_DATA_SIGN;
+ if (s->d[0] & 0x04) /* encrypt comm. + storage */
+ key_usage |= CDK_KEY_USG_COMM_ENCR;
+ if (s->d[0] & 0x08) /* encrypt comm. + storage */
+ key_usage |= CDK_KEY_USG_STORAGE_ENCR;
+ if (s->d[0] & 0x10) /* encrypt comm. + storage */
+ key_usage |= CDK_KEY_USG_SPLIT_KEY;
if (s->d[0] & 0x20)
key_usage |= CDK_KEY_USG_AUTH;
+ if (s->d[0] & 0x80) /* encrypt comm. + storage */
+ key_usage |= CDK_KEY_USG_SHARED_KEY;
}
s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PREFS_SYM);
if (s)
diff --git a/lib/opencdk/opencdk.h b/lib/opencdk/opencdk.h
index 83ca487e91..da2a869f95 100644
--- a/lib/opencdk/opencdk.h
+++ b/lib/opencdk/opencdk.h
@@ -281,12 +281,17 @@ enum cdk_crypto_mode_t {
CDK_CRYPTYPE_IMPORT = 6
};
-
+#define CDK_KEY_USG_ENCR CDK_KEY_USG_COMM_ENCR|CDK_KEY_USG_STORAGE_ENCR
+#define CDK_KEY_USG_SIGN CDK_KEY_USG_DATA_SIGN|CDK_KEY_USG_CERT_SIGN
/* A list of valid public key usages. */
enum cdk_key_usage_t {
- CDK_KEY_USG_ENCR = 1, /* Key can be used for encryption. */
- CDK_KEY_USG_SIGN = 2, /* Key can be used for signing and certifying. */
- CDK_KEY_USG_AUTH = 4 /* Key can be used for authentication. */
+ CDK_KEY_USG_CERT_SIGN = 1,
+ CDK_KEY_USG_DATA_SIGN = 2,
+ CDK_KEY_USG_COMM_ENCR = 4,
+ CDK_KEY_USG_STORAGE_ENCR = 8,
+ CDK_KEY_USG_SPLIT_KEY = 16,
+ CDK_KEY_USG_AUTH = 32,
+ CDK_KEY_USG_SHARED_KEY = 128
};
diff --git a/lib/opencdk/pubkey.c b/lib/opencdk/pubkey.c
index ae6fac9269..5a072b56ba 100644
--- a/lib/opencdk/pubkey.c
+++ b/lib/opencdk/pubkey.c
@@ -605,14 +605,15 @@ _cdk_pk_algo_usage (int algo)
return usage;
}
-
+/* You can use a NULL buf to get the output size only
+ */
static cdk_error_t
mpi_to_buffer (gcry_mpi_t a, byte *buf, size_t buflen,
size_t *r_nwritten, size_t *r_nbits)
{
size_t nbits;
- if (!a || !buf || !r_nwritten)
+ if (!a || !r_nwritten)
return CDK_Inv_Value;
nbits = gcry_mpi_get_nbits (a);
@@ -621,6 +622,7 @@ mpi_to_buffer (gcry_mpi_t a, byte *buf, size_t buflen,
if ((nbits+7)/8+2 > buflen)
return CDK_Too_Short;
*r_nwritten = (nbits+7)/8+2;
+
if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf, buflen, r_nwritten, a))
return CDK_Wrong_Format;
return 0;
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
index bcfb5f7996..71b997133f 100644
--- a/lib/openpgp/output.c
+++ b/lib/openpgp/output.c
@@ -133,21 +133,20 @@ print_key_usage (gnutls_string * str, gnutls_openpgp_crt_t cert, unsigned int id
static void
print_key_id (gnutls_string * str, gnutls_openpgp_crt_t cert, int idx)
{
- char fpr[8];
- size_t fpr_size = sizeof (fpr);
+ gnutls_openpgp_keyid_t id;
int err;
if (idx < 0)
- err = gnutls_openpgp_crt_get_id (cert, fpr);
+ err = gnutls_openpgp_crt_get_id (cert, &id);
else
- err = gnutls_openpgp_crt_get_subkey_id( cert, idx, fpr);
+ 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, fpr, fpr_size);
+ hexprint (str, id.keyid, sizeof(id.keyid));
addf (str, "\n");
}
}
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;
+}
diff --git a/libextra/Makefile.am b/libextra/Makefile.am
index 2eebe2501f..33f9e6ba58 100644
--- a/libextra/Makefile.am
+++ b/libextra/Makefile.am
@@ -52,7 +52,7 @@ lib_LTLIBRARIES = libgnutls-extra.la
libgnutls_extra_la_SOURCES = gnutls_extra.c
-libgnutls_openssl_la_LDFLAGS = -no-undefined
+libgnutls_openssl_la_LDFLAGS = -no-undefined -L$(top_srcdir)/lib/.libs
# OpenSSL
@@ -82,7 +82,7 @@ endif
# OpenPGP
libgnutls_extra_la_LIBADD =
-libgnutls_extra_la_LDFLAGS = -no-undefined
+libgnutls_extra_la_LDFLAGS = -no-undefined -L$(top_srcdir)/lib/.libs
# TLS/IA