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 /lib | |
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.
Diffstat (limited to 'lib')
-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 |
6 files changed, 182 insertions, 71 deletions
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); |