summaryrefslogtreecommitdiff
path: root/lib
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 /lib
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.
Diffstat (limited to 'lib')
-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
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);