diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2003-12-20 18:49:13 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2003-12-20 18:49:13 +0000 |
commit | 452b9aa3d35b814d69036113e8c9f952c2b89883 (patch) | |
tree | a7bc8bc350ab507a0c66f05d81e3b0418add64ce | |
parent | 358b8b35f84a7523885f667c5d6a7dceadb92f87 (diff) | |
download | gnutls-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/TODO | 4 | ||||
-rw-r--r-- | includes/gnutls/compat8.h | 4 | ||||
-rw-r--r-- | includes/gnutls/openpgp.h | 17 | ||||
-rw-r--r-- | lib/auth_cert.c | 193 | ||||
-rw-r--r-- | lib/gnutls_cert.c | 2 | ||||
-rw-r--r-- | lib/gnutls_int.h | 23 | ||||
-rw-r--r-- | lib/gnutls_ui.h | 28 | ||||
-rw-r--r-- | lib/gnutls_x509.c | 6 | ||||
-rw-r--r-- | lib/gnutls_x509.h | 1 | ||||
-rw-r--r-- | libextra/Makefile.am | 2 | ||||
-rw-r--r-- | libextra/gnutls_extra.h | 2 | ||||
-rw-r--r-- | libextra/gnutls_openpgp.c | 164 | ||||
-rw-r--r-- | libextra/openpgp/Makefile.am | 2 | ||||
-rw-r--r-- | libextra/openpgp/gnutls_openpgp.h | 7 | ||||
-rw-r--r-- | libextra/openpgp/openpgp.c | 25 | ||||
-rw-r--r-- | libextra/openpgp/openpgp.h | 14 |
16 files changed, 391 insertions, 103 deletions
@@ -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 */ |