summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2003-12-20 18:49:13 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2003-12-20 18:49:13 +0000
commit452b9aa3d35b814d69036113e8c9f952c2b89883 (patch)
treea7bc8bc350ab507a0c66f05d81e3b0418add64ce
parent358b8b35f84a7523885f667c5d6a7dceadb92f87 (diff)
downloadgnutls-452b9aa3d35b814d69036113e8c9f952c2b89883.tar.gz
Improved gnutls_certificate_client_retrieve_function() and gnutls_certificate_server_retrieve_function() so that the parsing time spent within them is minimized. Also added gnutls_openpgp_privkey struct. No testing yet.
-rw-r--r--doc/TODO4
-rw-r--r--includes/gnutls/compat8.h4
-rw-r--r--includes/gnutls/openpgp.h17
-rw-r--r--lib/auth_cert.c193
-rw-r--r--lib/gnutls_cert.c2
-rw-r--r--lib/gnutls_int.h23
-rw-r--r--lib/gnutls_ui.h28
-rw-r--r--lib/gnutls_x509.c6
-rw-r--r--lib/gnutls_x509.h1
-rw-r--r--libextra/Makefile.am2
-rw-r--r--libextra/gnutls_extra.h2
-rw-r--r--libextra/gnutls_openpgp.c164
-rw-r--r--libextra/openpgp/Makefile.am2
-rw-r--r--libextra/openpgp/gnutls_openpgp.h7
-rw-r--r--libextra/openpgp/openpgp.c25
-rw-r--r--libextra/openpgp/openpgp.h14
16 files changed, 391 insertions, 103 deletions
diff --git a/doc/TODO b/doc/TODO
index eff10d9c50..327b069819 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -3,8 +3,8 @@ anything), contact the developer's mailing list (gnutls-dev@lists.gnupg.org),
in order to avoid having people working on the same thing.
Current list:
-* Add gnutls_certificate_set_openpgp_key() and gnutls_certificate_set_openpgp_keyring()
- functions, similar to gnutls_certificate_set_x509_key().
+* Add gnutls_certificate_set_openpgp_keyring()
+ functions, similar to gnutls_certificate_set_openpgp_key().
* Add gnutls_openpgp_key_get_key_usage().
* Use subkeys with the 0x20 flag in openpgp keys (if present),
instead of the main key.
diff --git a/includes/gnutls/compat8.h b/includes/gnutls/compat8.h
index 3b34f449d3..77ca494f5f 100644
--- a/includes/gnutls/compat8.h
+++ b/includes/gnutls/compat8.h
@@ -53,8 +53,8 @@ int gnutls_x509_extract_certificate_dn_string(char *buf, unsigned int sizeof_buf
int gnutls_x509_extract_certificate_issuer_dn( const gnutls_datum*, gnutls_x509_dn *) DEPRECATED;
int gnutls_x509_extract_certificate_version( const gnutls_datum*) DEPRECATED;
int gnutls_x509_extract_certificate_serial(const gnutls_datum * cert, char* result, int* result_size) DEPRECATED;
-time_t gnutls_x509_extract_certificate_activation_time( const gnutls_datum*) DEPRECATED;
-time_t gnutls_x509_extract_certificate_expiration_time( const gnutls_datum*) DEPRECATED;
+time_t gnutls_x509_extract_certificate_activation_time( const gnutls_datum*);
+time_t gnutls_x509_extract_certificate_expiration_time( const gnutls_datum*);
int gnutls_x509_extract_certificate_subject_alt_name( const gnutls_datum*, int seq, char*, int*) DEPRECATED;
int gnutls_x509_pkcs7_extract_certificate(const gnutls_datum * pkcs7_struct, int indx, char* certificate, int* certificate_size) DEPRECATED;
int gnutls_x509_extract_certificate_pk_algorithm( const gnutls_datum * cert, int* bits) DEPRECATED;
diff --git a/includes/gnutls/openpgp.h b/includes/gnutls/openpgp.h
index 208050da54..8778213bdd 100644
--- a/includes/gnutls/openpgp.h
+++ b/includes/gnutls/openpgp.h
@@ -35,6 +35,9 @@ extern "C" {
struct gnutls_openpgp_key_int; /* object to hold (parsed) openpgp keys */
typedef struct gnutls_openpgp_key_int* gnutls_openpgp_key;
+struct gnutls_openpgp_privkey_int; /* object to hold (parsed) openpgp private keys */
+typedef struct gnutls_openpgp_privkey_int* gnutls_openpgp_privkey;
+
typedef enum gnutls_openpgp_key_fmt { GNUTLS_OPENPGP_FMT_RAW,
GNUTLS_OPENPGP_FMT_BASE64 } gnutls_openpgp_key_fmt;
@@ -68,6 +71,15 @@ int gnutls_openpgp_key_check_hostname( gnutls_openpgp_key key, const char *hostn
int gnutls_openpgp_key_to_xml( gnutls_openpgp_key key, gnutls_datum *xmlkey,
int ext);
+/* privkey stuff.
+ */
+int gnutls_openpgp_privkey_init(gnutls_openpgp_privkey * key);
+void gnutls_openpgp_privkey_deinit(gnutls_openpgp_privkey key);
+int gnutls_openpgp_privkey_get_pk_algorithm( gnutls_openpgp_privkey key, unsigned int *bits);
+int gnutls_openpgp_privkey_import(gnutls_openpgp_privkey key,
+ const gnutls_datum * data, gnutls_openpgp_key_fmt format,
+ const char* pass, unsigned int flags);
+
/* Keyring stuff.
*/
struct gnutls_openpgp_keyring_int; /* object to hold (parsed) openpgp keyrings */
@@ -107,6 +119,11 @@ int gnutls_openpgp_key_verify_trustdb(
unsigned int * verify /* the output of the verification */);
+/* certificate authentication stuff.
+ */
+int gnutls_certificate_set_openpgp_key(gnutls_certificate_credentials res,
+ gnutls_openpgp_key key, gnutls_openpgp_privkey pkey)
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/auth_cert.c b/lib/auth_cert.c
index 403ac2bb52..20a95a31be 100644
--- a/lib/auth_cert.c
+++ b/lib/auth_cert.c
@@ -44,10 +44,10 @@
#include <gnutls_extra.h>
#include "debug.h"
-static gnutls_cert *alloc_and_load_certs(const gnutls_datum * certs,
- uint ncerts, gnutls_certificate_type type);
-static gnutls_privkey *alloc_and_load_key(const gnutls_datum * raw_key,
- gnutls_certificate_type type);
+static gnutls_cert *alloc_and_load_x509_certs(gnutls_x509_crt * certs, uint);
+static gnutls_privkey *alloc_and_load_x509_key(gnutls_x509_privkey key);
+static gnutls_cert *alloc_and_load_pgp_certs(gnutls_openpgp_key cert);
+static gnutls_privkey *alloc_and_load_pgp_key(const gnutls_openpgp_privkey key);
/* Copies data from a internal certificate struct (gnutls_cert) to
@@ -400,39 +400,80 @@ static int call_client_cert_callback(gnutls_session session,
/* Calls the client get callback.
*/
-static int call_client_get_cert_callback( gnutls_session session,
+static int call_get_cert_callback( gnutls_session session,
gnutls_datum* issuers_dn, int issuers_dn_length)
{
-gnutls_datum *certs, key;
-uint ncerts, i;
-gnutls_certificate_type type =
- gnutls_certificate_type_get(session);
+uint i;
gnutls_cert *local_certs = NULL;
gnutls_privkey *local_key = NULL;
+retr_st st;
int ret;
+gnutls_certificate_type type =
+ gnutls_certificate_type_get(session);
+
+ memset( &st, 0, sizeof(st));
+
+ if (session->security_parameters.entity == GNUTLS_SERVER) {
+ ret =
+ session->internals.server_get_cert_callback(session, &st);
+ } else { /* CLIENT */
+ ret =
+ session->internals.client_get_cert_callback(session,
+ issuers_dn, issuers_dn_length,
+ &st);
+ }
- ret =
- session->internals.client_get_cert_callback(session,
- issuers_dn, issuers_dn_length,
- &certs, &ncerts, &key);
if (ret < 0) {
gnutls_assert();
return GNUTLS_E_INTERNAL_ERROR;
}
+
+ if (type != st.type) {
+ gnutls_assert();
+ ret = GNUTLS_E_INVALID_REQUEST;
+ goto cleanup;
+ }
- local_certs = alloc_and_load_certs(certs, ncerts, type);
- if (local_certs != NULL)
- local_key = alloc_and_load_key(&key, type);
+ 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);
+
+ } else { /* PGP */
+ if (st.ncerts != 1) {
+ gnutls_assert();
+ ret = GNUTLS_E_INVALID_REQUEST;
+ goto cleanup;
+ }
+
+ local_certs = alloc_and_load_pgp_certs(st.cert.pgp);
+ if (local_certs != NULL)
+ local_key = alloc_and_load_pgp_key(st.key.pgp);
- for (i = 0; i < ncerts; i++) {
- _gnutls_free_datum(&certs[i]);
}
- _gnutls_free_datum(&key);
- _gnutls_selected_certs_set(session, local_certs, ncerts,
+ _gnutls_selected_certs_set(session, local_certs, st.ncerts,
local_key, 1);
- return 0;
+ ret = 0;
+
+cleanup:
+
+ if (st.type == GNUTLS_CRT_X509) {
+ if (st.deinit_all_keys) {
+ for (i = 0; i < st.ncerts; i++) {
+ gnutls_x509_crt_deinit(st.cert.x509[i]);
+ }
+ gnutls_x509_privkey_deinit(st.key.x509);
+ }
+ } else {
+ if (st.deinit_all_keys) {
+ gnutls_openpgp_key_deinit(st.cert.pgp);
+ gnutls_openpgp_privkey_deinit(st.key.pgp);
+ }
+ }
+
+ return ret;
}
/* Finds the appropriate certificate depending on the cA Distinguished name
@@ -488,7 +529,7 @@ static int _select_client_cert(gnutls_session session,
}
if (session->internals.client_get_cert_callback) {
- result = call_client_get_cert_callback( session, issuers_dn, issuers_dn_length);
+ result = call_get_cert_callback( session, issuers_dn, issuers_dn_length);
goto cleanup;
}
@@ -1368,12 +1409,11 @@ int _gnutls_get_selected_cert(gnutls_session session,
return 0;
}
-/* converts the given raw certificate to gnutls_cert* and allocates
+/* converts the given x509 certificate to gnutls_cert* and allocates
* space for them.
*/
-static gnutls_cert *alloc_and_load_certs(const gnutls_datum * certs,
- uint ncerts,
- gnutls_certificate_type type)
+static gnutls_cert *alloc_and_load_x509_certs(gnutls_x509_crt * certs,
+ uint ncerts)
{
gnutls_cert *local_certs;
int ret = 0;
@@ -1386,8 +1426,8 @@ static gnutls_cert *alloc_and_load_certs(const gnutls_datum * certs,
}
for (i = 0; i < ncerts; i++) {
- ret = _gnutls_cert2gnutls_cert(&local_certs[i], type,
- &certs[i], 0);
+ ret = _gnutls_x509_crt2gnutls_cert(&local_certs[i],
+ certs[i], 0);
if (ret < 0)
break;
}
@@ -1404,11 +1444,70 @@ static gnutls_cert *alloc_and_load_certs(const gnutls_datum * certs,
return local_certs;
}
+/* converts the given x509 key to gnutls_privkey* and allocates
+ * space for it.
+ */
+static gnutls_privkey *alloc_and_load_x509_key(gnutls_x509_privkey key)
+{
+ gnutls_privkey *local_key;
+ int ret = 0;
+
+ local_key = gnutls_malloc(sizeof(gnutls_privkey));
+ if (local_key == NULL) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ ret =
+ _gnutls_x509_privkey2gnutls_key(local_key, key);
+ if (ret < 0) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ return local_key;
+}
+
+
+
+
+/* converts the given pgp certificate to gnutls_cert* and allocates
+ * space for them.
+ */
+static gnutls_cert *alloc_and_load_pgp_certs(gnutls_openpgp_key cert)
+{
+ gnutls_cert *local_certs;
+ int ret = 0;
+ uint i, j;
+
+ local_certs = gnutls_malloc(sizeof(gnutls_cert));
+ if (local_certs == NULL) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ ret = _gnutls_openpgp_key2gnutls_cert(&local_certs[i], cert);
+ if (ret < 0) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ if (ret < 0) {
+ gnutls_assert();
+ for (j = 0; j < i; j++) {
+ _gnutls_cert_deinit(&local_certs[j]);
+ }
+ gnutls_free(local_certs);
+ return NULL;
+ }
+
+ return local_certs;
+}
+
/* converts the given raw key to gnutls_privkey* and allocates
* space for it.
*/
-static gnutls_privkey *alloc_and_load_key(const gnutls_datum * raw_key,
- gnutls_certificate_type type)
+static gnutls_privkey *alloc_and_load_pgp_key(const gnutls_openpgp_privkey key)
{
gnutls_privkey *local_key;
int ret = 0;
@@ -1420,8 +1519,7 @@ static gnutls_privkey *alloc_and_load_key(const gnutls_datum * raw_key,
}
ret =
- _gnutls_key2gnutls_key(local_key, type, raw_key,
- GNUTLS_X509_FMT_DER);
+ _gnutls_openpgp_privkey2gnutls_key(local_key, key);
if (ret < 0) {
gnutls_assert();
return NULL;
@@ -1430,6 +1528,7 @@ static gnutls_privkey *alloc_and_load_key(const gnutls_datum * raw_key,
return local_key;
}
+
void _gnutls_selected_certs_deinit(gnutls_session session)
{
if (session->internals.selected_need_free != 0) {
@@ -1512,36 +1611,8 @@ int _gnutls_server_select_cert(gnutls_session session,
* set use it.
*/
if (session->internals.server_get_cert_callback != NULL) {
- gnutls_datum *certs, key;
- uint ncerts;
- gnutls_certificate_type type =
- gnutls_certificate_type_get(session);
- gnutls_cert *local_certs = NULL;
- gnutls_privkey *local_key = NULL;
-
- ret =
- session->internals.server_get_cert_callback(session,
- &certs,
- &ncerts,
- &key);
- if (ret < 0) {
- gnutls_assert();
- return GNUTLS_E_INTERNAL_ERROR;
- }
- local_certs = alloc_and_load_certs(certs, ncerts, type);
- if (local_certs != NULL)
- local_key = alloc_and_load_key(&key, type);
-
- for (i = 0; i < ncerts; i++) {
- _gnutls_free_datum(&certs[i]);
- }
- _gnutls_free_datum(&key);
-
- _gnutls_selected_certs_set(session, local_certs, ncerts,
- local_key, 1);
-
- return 0;
+ return call_get_cert_callback( session, NULL, 0);
} else if (session->internals.server_cert_callback != NULL
&& cred->ncerts > 0) {
diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c
index 26d2ad3ae6..22784f2d62 100644
--- a/lib/gnutls_cert.c
+++ b/lib/gnutls_cert.c
@@ -606,7 +606,7 @@ int _gnutls_key2gnutls_key(gnutls_privkey * key, gnutls_certificate_type type,
return GNUTLS_E_INIT_LIBEXTRA;
}
return
- _E_gnutls_openpgp_key2gnutls_key( key, raw_key);
+ _E_gnutls_openpgp_key2gnutls_key( key, raw_key, key_enc);
default:
gnutls_assert();
return GNUTLS_E_INTERNAL_ERROR;
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 89d1fa61c7..cb396180fe 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -422,13 +422,30 @@ typedef int srp_server_select_func(struct gnutls_session_int*,
/* authentication function definitions:
*/
+#include "../libextra/openpgp/openpgp.h"
+
+typedef struct retr_st {
+ gnutls_certificate_type type;
+ union cert {
+ gnutls_x509_crt* x509;
+ gnutls_openpgp_key pgp;
+ } cert;
+ uint ncerts;
+
+ union key {
+ gnutls_x509_privkey x509;
+ gnutls_openpgp_privkey pgp;
+ } key;
+
+ uint deinit_all_keys;
+} retr_st;
+
typedef int gnutls_certificate_client_retrieve_function(
struct gnutls_session_int*, const gnutls_datum* req_ca_cert, int nreqs,
- gnutls_datum** certs, unsigned int* ncerts, gnutls_datum* key);
+ retr_st*);
typedef int gnutls_certificate_server_retrieve_function(
- struct gnutls_session_int*, gnutls_datum **server_certs, unsigned int* ncerts,
- gnutls_datum* key);
+ struct gnutls_session_int*, retr_st*);
typedef struct {
opaque header[HANDSHAKE_HEADER_SIZE];
diff --git a/lib/gnutls_ui.h b/lib/gnutls_ui.h
index 8dcfd32d20..bff8ed8a31 100644
--- a/lib/gnutls_ui.h
+++ b/lib/gnutls_ui.h
@@ -17,12 +17,34 @@ typedef int gnutls_certificate_client_select_function(
typedef int gnutls_certificate_server_select_function(
gnutls_session, const gnutls_datum *server_certs, int ncerts);
+
+struct gnutls_openpgp_key_int;
+typedef struct gnutls_openpgp_key_int* gnutls_openpgp_key;
+
+struct gnutls_openpgp_privkey_int;
+typedef struct gnutls_openpgp_privkey_int* gnutls_openpgp_privkey;
+
+typedef struct gnutls_retr_st {
+ gnutls_certificate_type type;
+ union cert {
+ gnutls_x509_crt *x509;
+ gnutls_openpgp_key pgp;
+ } cert;
+ uint ncerts; /* one for pgp keys */
+
+ union key {
+ gnutls_x509_privkey x509;
+ gnutls_openpgp_privkey pgp;
+ } key;
+
+ uint deinit_all_keys; /* if non zero all keys will be deinited */
+} gnutls_retr_st;
+
typedef int gnutls_certificate_client_retrieve_function(
gnutls_session, const gnutls_datum* req_ca_cert, int nreqs,
- gnutls_datum** certs, unsigned int* ncerts, gnutls_datum* key);
+ gnutls_retr_st*);
typedef int gnutls_certificate_server_retrieve_function(
- gnutls_session, gnutls_datum **server_certs, unsigned int* ncerts,
- gnutls_datum* key);
+ gnutls_session, gnutls_retr_st*);
/* Functions that allow AUTH_INFO structures handling
diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c
index eaca68d83e..ac96dc8840 100644
--- a/lib/gnutls_x509.c
+++ b/lib/gnutls_x509.c
@@ -519,7 +519,7 @@ int read_cert_mem(gnutls_certificate_credentials res, const void *cert, int cert
}
-static int privkey_cpy( gnutls_privkey* dest, gnutls_x509_privkey src)
+int _gnutls_x509_privkey2gnutls_key( gnutls_privkey* dest, gnutls_x509_privkey src)
{
int i, ret;
@@ -576,7 +576,7 @@ int ret;
return ret;
}
- ret = privkey_cpy( privkey, tmpkey);
+ ret = _gnutls_x509_privkey2gnutls_key( privkey, tmpkey);
if (ret < 0) {
gnutls_assert();
gnutls_x509_privkey_deinit( tmpkey);
@@ -839,7 +839,7 @@ int gnutls_certificate_set_x509_key(gnutls_certificate_credentials res,
return GNUTLS_E_MEMORY_ERROR;
}
- ret = privkey_cpy( &res->pkey[res->ncerts], key);
+ ret = _gnutls_x509_privkey2gnutls_key( &res->pkey[res->ncerts], key);
if (ret < 0) {
gnutls_assert();
return ret;
diff --git a/lib/gnutls_x509.h b/lib/gnutls_x509.h
index 81379dbe19..be5ea36a81 100644
--- a/lib/gnutls_x509.h
+++ b/lib/gnutls_x509.h
@@ -18,3 +18,4 @@ int _gnutls_x509_read_dsa_pubkey(opaque * der, int dersize, GNUTLS_MPI * params)
int _gnutls_x509_key2gnutls_key( gnutls_privkey* privkey, const gnutls_datum* raw_key,
gnutls_x509_crt_fmt type);
+int _gnutls_x509_privkey2gnutls_key( gnutls_privkey* privkey, gnutls_x509_privkey);
diff --git a/libextra/Makefile.am b/libextra/Makefile.am
index 0a28bb78b2..41c5f9df92 100644
--- a/libextra/Makefile.am
+++ b/libextra/Makefile.am
@@ -43,7 +43,7 @@ libgnutls_extra_la_DEPENDENCIES = $(LZO_OBJECTS)
libgnutls_extra_la_SOURCES = $(COBJECTS_EXTRA)
libgnutls_extra_la_LIBADD = $(LZO_OBJECTS) \
- openpgp/openpgp.lo openpgp/xml.lo \
+ openpgp/openpgp.lo openpgp/xml.lo privkey.lo \
openpgp/extras.lo openpgp/verify.lo openpgp/compat.lo \
../lib/libgnutls.la
diff --git a/libextra/gnutls_extra.h b/libextra/gnutls_extra.h
index 5da0886bc2..7c6eb11cab 100644
--- a/libextra/gnutls_extra.h
+++ b/libextra/gnutls_extra.h
@@ -8,4 +8,4 @@ typedef int (*OPENPGP_KEY_REQUEST)(gnutls_session, gnutls_datum*,
const gnutls_certificate_credentials, opaque*,int);
typedef int (*OPENPGP_FINGERPRINT)(const gnutls_datum*, unsigned char*, size_t*);
typedef int (*OPENPGP_CERT2GNUTLS_CERT)(gnutls_cert*, const gnutls_datum*);
-typedef int (*OPENPGP_KEY2GNUTLS_KEY)(gnutls_privkey*, const gnutls_datum*);
+typedef int (*OPENPGP_KEY2GNUTLS_KEY)(gnutls_privkey*, const gnutls_datum*, gnutls_openpgp_key_fmt);
diff --git a/libextra/gnutls_openpgp.c b/libextra/gnutls_openpgp.c
index 97fc9ac3bd..be48591884 100644
--- a/libextra/gnutls_openpgp.c
+++ b/libextra/gnutls_openpgp.c
@@ -24,7 +24,7 @@
#include "gnutls_cert.h"
#include "gnutls_datum.h"
#include "gnutls_global.h"
-#include "auth_cert.h"
+//#include "auth_cert.h"
#include <openpgp/gnutls_openpgp.h>
#ifdef HAVE_LIBOPENCDK
@@ -292,7 +292,8 @@ openpgp_pk_to_gnutls_cert( gnutls_cert *cert, cdk_pkt_pubkey_t pk )
-*/
int
_gnutls_openpgp_key2gnutls_key( gnutls_privkey *pkey,
- const gnutls_datum *raw_key )
+ const gnutls_datum *raw_key,
+ gnutls_openpgp_key_fmt format)
{
cdk_kbnode_t snode;
CDK_PACKET *pkt;
@@ -311,6 +312,16 @@ _gnutls_openpgp_key2gnutls_key( gnutls_privkey *pkey,
out = cdk_stream_tmp( );
if( !out )
return GNUTLS_E_CERTIFICATE_ERROR;
+
+ if (format == GNUTLS_OPENPGP_FMT_BASE64) {
+ rc = cdk_stream_set_armor_flag( out, 0);
+ if (rc) {
+ rc = _gnutls_map_cdk_rc( rc);
+ gnutls_assert();
+ return rc;
+ }
+ }
+
cdk_stream_write( out, raw_key->data, raw_key->size );
cdk_stream_seek( out, 0 );
@@ -519,8 +530,7 @@ stream_to_datum( cdk_stream_t inp, gnutls_datum *raw )
**/
int
gnutls_certificate_set_openpgp_key_mem( gnutls_certificate_credentials res,
- const gnutls_datum *cert,
- const gnutls_datum *key )
+ const gnutls_datum *cert, const gnutls_datum *key )
{
gnutls_datum raw;
cdk_kbnode_t knode = NULL, ctx = NULL, p;
@@ -528,6 +538,7 @@ gnutls_certificate_set_openpgp_key_mem( gnutls_certificate_credentials res,
int i = 0;
int rc = 0;
cdk_stream_t inp = NULL;
+ gnutls_openpgp_key_fmt format;
if ( !res || !key || !cert ) {
gnutls_assert( );
@@ -540,8 +551,12 @@ gnutls_certificate_set_openpgp_key_mem( gnutls_certificate_credentials res,
return GNUTLS_E_INTERNAL_ERROR;
}
- if( cdk_armor_filter_use( inp ) )
+ if( cdk_armor_filter_use( inp ) ) {
+ format = GNUTLS_OPENPGP_FMT_BASE64;
cdk_stream_set_armor_flag( inp, 0 );
+ } else {
+ format = GNUTLS_OPENPGP_FMT_RAW;
+ }
res->cert_list = gnutls_realloc_fast(res->cert_list,
(1+res->ncerts)*sizeof(gnutls_cert*));
@@ -626,7 +641,7 @@ gnutls_certificate_set_openpgp_key_mem( gnutls_certificate_credentials res,
}
cdk_stream_close( inp );
- rc = _gnutls_openpgp_key2gnutls_key( &res->pkey[res->ncerts-1], &raw );
+ rc = _gnutls_openpgp_key2gnutls_key( &res->pkey[res->ncerts-1], &raw, format);
if (rc) {
gnutls_assert();
}
@@ -1006,5 +1021,142 @@ void gnutls_openpgp_set_recv_key_function( gnutls_session session,
session->internals.openpgp_recv_key_func = func;
}
+/* Copies a gnutls_openpgp_privkey to a gnutls_privkey structure.
+ */
+int _gnutls_openpgp_privkey2gnutls_key( gnutls_privkey* dest, gnutls_openpgp_privkey src)
+{
+int i, ret;
+
+ memset( dest, 0, sizeof(gnutls_privkey));
+
+ for(i=0;i<src->pkey.params_size;i++) {
+ dest->params[i] = _gnutls_mpi_copy( src->pkey.params[i]);
+ if (dest->params[i] == NULL) {
+ gnutls_assert();
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto cleanup;
+ }
+ }
+
+ dest->pk_algorithm = src->pkey.pk_algorithm;
+ dest->params_size = src->pkey.params_size;
+
+ 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_key to a gnutls_cert structure.
+ */
+int _gnutls_openpgp_key2gnutls_cert(gnutls_cert * gcert, gnutls_openpgp_key cert)
+{
+ int ret = 0;
+ opaque* der;
+ size_t der_size = 0;
+ gnutls_datum raw;
+
+ memset(gcert, 0, sizeof(gnutls_cert));
+ gcert->cert_type = GNUTLS_CRT_OPENPGP;
+
+
+ ret = gnutls_openpgp_key_export( cert, GNUTLS_OPENPGP_FMT_RAW, NULL, &der_size);
+ if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
+ gnutls_assert();
+ return ret;
+ }
+
+ der = gnutls_malloc( der_size);
+ if (der == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ ret = gnutls_openpgp_key_export( cert, GNUTLS_OPENPGP_FMT_RAW, der, &der_size);
+ if (ret < 0) {
+ gnutls_assert();
+ gnutls_free(der);
+ return ret;
+ }
+
+ raw.data = der;
+ raw.size = der_size;
+
+ ret = _gnutls_openpgp_cert2gnutls_cert( gcert, &raw);
+
+ gnutls_free(der);
+
+ return 0;
+
+}
+
+/**
+ * gnutls_certificate_set_openpgp_key - Used to set keys in a gnutls_certificate_credentials structure
+ * @res: is an &gnutls_certificate_credentials structure.
+ * @key: contains an openpgp public key
+ * @pkey: is an openpgp private key
+ *
+ * This function sets a certificate/private key pair in the
+ * gnutls_certificate_credentials structure. This function may be called
+ * more than once (in case multiple keys/certificates exist for the
+ * server).
+ *
+ **/
+int gnutls_certificate_set_openpgp_key(gnutls_certificate_credentials res,
+ gnutls_openpgp_key key,
+ gnutls_openpgp_privkey pkey)
+{
+ int ret;
+
+ /* this should be first
+ */
+
+ res->pkey = gnutls_realloc_fast( res->pkey, (res->ncerts+1)*sizeof(gnutls_privkey));
+ if (res->pkey==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ ret = _gnutls_openpgp_privkey2gnutls_key( &res->pkey[res->ncerts], pkey);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ res->cert_list = gnutls_realloc_fast( res->cert_list,
+ (1+ res->ncerts)*sizeof(gnutls_cert*));
+ if ( res->cert_list==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ res->cert_list_length = gnutls_realloc_fast( res->cert_list_length,
+ (1+ res->ncerts)*sizeof(int));
+ if (res->cert_list_length==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ res->cert_list[res->ncerts] = NULL; /* for realloc */
+ res->cert_list_length[res->ncerts] = 1;
+
+ ret = _gnutls_openpgp_key2gnutls_cert( res->cert_list[res->ncerts], key);
+ if ( ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ res->ncerts++;
+
+ /* FIXME: Check if they match.
+ */
+
+ return 0;
+}
+
+
#endif /* HAVE_LIBOPENCDK */
diff --git a/libextra/openpgp/Makefile.am b/libextra/openpgp/Makefile.am
index 174cd01262..aa7f7440c0 100644
--- a/libextra/openpgp/Makefile.am
+++ b/libextra/openpgp/Makefile.am
@@ -3,7 +3,7 @@ EXTRA_DIST = openpgp.h gnutls_openpgp.h
noinst_LTLIBRARIES = libpgp.la
-COBJECTS = openpgp.c xml.c verify.c extras.c compat.c
+COBJECTS = openpgp.c xml.c verify.c extras.c compat.c privkey.c
libpgp_la_SOURCES = $(COBJECTS)
diff --git a/libextra/openpgp/gnutls_openpgp.h b/libextra/openpgp/gnutls_openpgp.h
index eabb52e97c..e8e4a76355 100644
--- a/libextra/openpgp/gnutls_openpgp.h
+++ b/libextra/openpgp/gnutls_openpgp.h
@@ -74,7 +74,8 @@ int _gnutls_openpgp_cert2gnutls_cert(
int
_gnutls_openpgp_key2gnutls_key( gnutls_privkey *pkey,
- const gnutls_datum *raw_key);
+ const gnutls_datum *raw_key,
+ gnutls_openpgp_key_fmt format);
int
_gnutls_openpgp_request_key(
@@ -97,10 +98,6 @@ int gnutls_openpgp_fingerprint(const gnutls_datum * cert,
time_t gnutls_openpgp_extract_key_creation_time(const gnutls_datum * cert);
time_t gnutls_openpgp_extract_key_expiration_time(const gnutls_datum * cert);
-int
-_gnutls_openpgp_key2gnutls_key( gnutls_privkey *pkey,
- const gnutls_datum *raw_key);
-
#endif /*GNUTLS_OPENPGP_H*/
#endif /*HAVE_LIBOPENCDK*/
diff --git a/libextra/openpgp/openpgp.c b/libextra/openpgp/openpgp.c
index 4813424fbf..3eec67b817 100644
--- a/libextra/openpgp/openpgp.c
+++ b/libextra/openpgp/openpgp.c
@@ -2,22 +2,21 @@
* Copyright (C) 2002 Timo Schulz
* Portions Copyright (C) 2003 Nikos Mavroyanopoulos
*
- * This file is part of GNUTLS-EXTRA.
+ * 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.
+ * 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
/* Functions on OpenPGP key parsing
diff --git a/libextra/openpgp/openpgp.h b/libextra/openpgp/openpgp.h
index 1f9127f85e..e6a2fbc06b 100644
--- a/libextra/openpgp/openpgp.h
+++ b/libextra/openpgp/openpgp.h
@@ -15,6 +15,10 @@ typedef struct gnutls_openpgp_key_int {
cdk_stream_t inp;
} gnutls_openpgp_key_int;
+typedef struct gnutls_openpgp_privkey_int {
+ gnutls_privkey pkey;
+} gnutls_openpgp_privkey_int;
+
typedef struct gnutls_openpgp_keyring_int {
cdk_keydb_hd_t hd;
} gnutls_openpgp_keyring_int;
@@ -24,6 +28,7 @@ typedef struct gnutls_openpgp_trustdb_int {
} gnutls_openpgp_trustdb_int;
typedef struct gnutls_openpgp_key_int *gnutls_openpgp_key;
+typedef struct gnutls_openpgp_privkey_int *gnutls_openpgp_privkey;
typedef struct gnutls_openpgp_keyring_int *gnutls_openpgp_keyring;
typedef struct gnutls_openpgp_trustdb_int *gnutls_openpgp_trustdb;
@@ -46,7 +51,9 @@ int gnutls_openpgp_key_init(gnutls_openpgp_key * key);
void gnutls_openpgp_key_deinit(gnutls_openpgp_key key);
int gnutls_openpgp_key_import(gnutls_openpgp_key key,
const gnutls_datum * data, gnutls_openpgp_key_fmt format);
-
+int gnutls_openpgp_key_export(gnutls_openpgp_key key,
+ gnutls_openpgp_key_fmt format, void* output_data,
+ size_t* output_data_size);
void gnutls_openpgp_keyring_deinit(gnutls_openpgp_keyring keyring);
int gnutls_openpgp_keyring_init(gnutls_openpgp_keyring * keyring);
@@ -70,6 +77,11 @@ int gnutls_openpgp_key_verify_trustdb( gnutls_openpgp_key key,
int gnutls_openpgp_key_verify_self( gnutls_openpgp_key key,
unsigned int flags, unsigned int *verify);
+int _gnutls_openpgp_key2gnutls_cert(gnutls_cert * gcert, gnutls_openpgp_key cert);
+int _gnutls_openpgp_privkey2gnutls_key( gnutls_privkey* dest, gnutls_openpgp_privkey src);
+
+void gnutls_openpgp_privkey_deinit(gnutls_openpgp_privkey key);
+
#endif
#endif /* HAVE_LIBOPENCDK */