summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/auth_anon.c32
-rw-r--r--lib/auth_cert.c182
-rw-r--r--lib/auth_cert.h5
-rw-r--r--lib/auth_dhe.c24
-rw-r--r--lib/auth_rsa.c14
-rw-r--r--lib/auth_rsa_export.c2
-rw-r--r--lib/dh_compat.c4
-rw-r--r--lib/gnutls.h.in.in1
-rw-r--r--lib/gnutls_algorithms.c27
-rw-r--r--lib/gnutls_algorithms.h7
-rw-r--r--lib/gnutls_cert.c35
-rw-r--r--lib/gnutls_cert.h5
-rw-r--r--lib/gnutls_dh.h2
-rw-r--r--lib/gnutls_dh_primes.c69
-rw-r--r--lib/gnutls_handshake.c133
-rw-r--r--lib/gnutls_int.h9
-rw-r--r--lib/gnutls_kx.c4
-rw-r--r--lib/gnutls_rsa_export.c1
-rw-r--r--lib/gnutls_ui.c14
-rw-r--r--lib/libgnutls.vers2
-rw-r--r--lib/x509/common.c1
21 files changed, 306 insertions, 267 deletions
diff --git a/lib/auth_anon.c b/lib/auth_anon.c
index 65707806db..465dbdfb63 100644
--- a/lib/auth_anon.c
+++ b/lib/auth_anon.c
@@ -60,6 +60,7 @@ const MOD_AUTH_STRUCT anon_auth_struct = {
static int gen_anon_server_kx( gnutls_session session, opaque** data) {
GNUTLS_MPI g, p;
+ const GNUTLS_MPI *mpis;
int ret;
const gnutls_anon_server_credentials cred;
@@ -69,28 +70,27 @@ static int gen_anon_server_kx( gnutls_session session, opaque** data) {
return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
}
- if ( (ret=_gnutls_get_dh_params( cred->dh_params, &p, &g)) < 0) {
+ mpis = _gnutls_get_dh_params( cred->dh_params);
+ if (mpis == NULL) {
gnutls_assert();
- return ret;
+ return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
}
- if ( (ret=_gnutls_auth_info_set( session, GNUTLS_CRD_ANON, sizeof( ANON_SERVER_AUTH_INFO_INT), 1)) < 0) {
+ p = mpis[0];
+ g = mpis[1];
+
+ if ( (ret=_gnutls_auth_info_set( session, GNUTLS_CRD_ANON, sizeof( ANON_SERVER_AUTH_INFO_INT), 1)) < 0)
+ {
gnutls_assert();
- cleanup_gp:
- _gnutls_mpi_release(&g);
- _gnutls_mpi_release(&p);
return ret;
}
if ((ret=_gnutls_dh_set_prime_bits( session, _gnutls_mpi_get_nbits(p))) < 0) {
gnutls_assert();
- goto cleanup_gp;
+ return ret;
}
ret = _gnutls_dh_common_print_server_kx( session, g, p, data);
- _gnutls_mpi_release(&g);
- _gnutls_mpi_release(&p);
-
if (ret < 0) {
gnutls_assert();
}
@@ -105,6 +105,7 @@ const gnutls_anon_server_credentials cred;
int bits;
int ret;
GNUTLS_MPI p, g;
+const GNUTLS_MPI *mpis;
bits = _gnutls_dh_get_prime_bits( session);
@@ -114,16 +115,17 @@ GNUTLS_MPI p, g;
return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
}
- if ( (ret=_gnutls_get_dh_params( cred->dh_params, &p, &g)) < 0) {
+ mpis = _gnutls_get_dh_params( cred->dh_params);
+ if (mpis == NULL) {
gnutls_assert();
- return ret;
+ return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
}
+ p = mpis[0];
+ g = mpis[1];
+
ret = _gnutls_proc_dh_common_client_kx( session, data, _data_size, g, p);
- _gnutls_mpi_release(&g);
- _gnutls_mpi_release(&p);
-
return ret;
}
diff --git a/lib/auth_cert.c b/lib/auth_cert.c
index f289026e7d..9a99c3948b 100644
--- a/lib/auth_cert.c
+++ b/lib/auth_cert.c
@@ -44,10 +44,6 @@
#include <gnutls_extra.h>
#include "debug.h"
-static int _gnutls_server_find_cert_list_index(gnutls_session session,
- gnutls_pk_algorithm
- requested_algo);
-
/* Copies data from a internal certificate struct (gnutls_cert) to
* exported certificate struct (CERTIFICATE_AUTH_INFO)
*/
@@ -230,12 +226,9 @@ static int _find_openpgp_cert(const gnutls_certificate_credentials cred,
* 20020128: added ability to select a certificate depending on the SIGN
* algorithm (only in automatic mode).
*/
-static int _gnutls_find_acceptable_client_cert(gnutls_session session,
- opaque * _data,
- size_t _data_size, int *ind,
- gnutls_pk_algorithm *
- pk_algos,
- int pk_algos_length)
+static int _select_client_cert(gnutls_session session,
+ opaque * _data, size_t _data_size, int *ind,
+ gnutls_pk_algorithm *pk_algos, int pk_algos_length)
{
int result, size;
int indx = -1;
@@ -420,9 +413,9 @@ static int _gnutls_find_acceptable_client_cert(gnutls_session session,
else
indx = -1;
- if (my_certs) gnutls_afree(my_certs);
- if (ij_map) gnutls_afree(ij_map);
- if (issuers_dn) gnutls_afree(issuers_dn);
+ if (my_certs) { gnutls_afree(my_certs); }
+ if (ij_map) { gnutls_afree(ij_map); }
+ if (issuers_dn) { gnutls_afree(issuers_dn); }
}
*ind = indx;
@@ -450,7 +443,7 @@ int _gnutls_gen_x509_crt(gnutls_session session, opaque ** data)
/* find the appropriate certificate
*/
if ((ret =
- _gnutls_find_apr_cert(session, &apr_cert_list,
+ _gnutls_get_selected_cert(session, &apr_cert_list,
&apr_cert_list_length,
&apr_pkey)) < 0) {
gnutls_assert();
@@ -502,7 +495,7 @@ int _gnutls_gen_openpgp_certificate(gnutls_session session, opaque ** data)
/* find the appropriate certificate */
if ((ret =
- _gnutls_find_apr_cert(session, &apr_cert_list,
+ _gnutls_get_selected_cert(session, &apr_cert_list,
&apr_cert_list_length,
&apr_pkey)) < 0) {
gnutls_assert();
@@ -553,7 +546,7 @@ int _gnutls_gen_openpgp_certificate_fpr(gnutls_session session,
/* find the appropriate certificate */
if ((ret =
- _gnutls_find_apr_cert(session, &apr_cert_list,
+ _gnutls_get_selected_cert(session, &apr_cert_list,
&apr_cert_list_length,
&apr_pkey)) < 0) {
gnutls_assert();
@@ -1040,15 +1033,23 @@ int _gnutls_proc_cert_cert_req(gnutls_session session, opaque * data,
* he wants to use.
*/
if ((ret =
- _gnutls_find_acceptable_client_cert(session, p, size,
- &ind, pk_algos,
- pk_algos_length)) < 0) {
+ _select_client_cert(session, p, size,
+ &ind, pk_algos,
+ pk_algos_length)) < 0) {
gnutls_assert();
return ret;
}
/* put the index of the client certificate to use
*/
- session->internals.selected_cert_index = ind;
+ if (ind >= 0) {
+ session->internals.selected_cert_list_length = cred->cert_list_length[ind];
+ session->internals.selected_cert_list = &cred->cert_list[ind][0];
+ session->internals.selected_key = &cred->pkey[ind];
+ } else {
+ session->internals.selected_cert_list_length = 0;
+ session->internals.selected_cert_list = NULL;
+ session->internals.selected_key = NULL;
+ }
/* We should reply with a certificate message,
* even if we have no certificate to send.
@@ -1071,7 +1072,7 @@ int _gnutls_gen_cert_client_cert_vrfy(gnutls_session session,
/* find the appropriate certificate */
if ((ret =
- _gnutls_find_apr_cert(session, &apr_cert_list,
+ _gnutls_get_selected_cert(session, &apr_cert_list,
&apr_cert_list_length,
&apr_pkey)) < 0) {
gnutls_assert();
@@ -1230,103 +1231,40 @@ int _gnutls_gen_cert_server_cert_req(gnutls_session session,
* It is normal to return 0 with no certificates in client side.
*
*/
-int _gnutls_find_apr_cert(gnutls_session session,
+int _gnutls_get_selected_cert(gnutls_session session,
gnutls_cert ** apr_cert_list,
int *apr_cert_list_length,
gnutls_privkey ** apr_pkey)
{
- const gnutls_certificate_credentials cred;
- int ind;
-
- cred = _gnutls_get_cred(session->key, GNUTLS_CRD_CERTIFICATE, NULL);
+ if (session->security_parameters.entity == GNUTLS_SERVER) {
- if (cred == NULL) {
- gnutls_assert();
- *apr_cert_list = NULL;
- *apr_pkey = NULL;
- *apr_cert_list_length = 0;
- return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
- }
+ /* select_client_cert() has been called before.
+ */
- if (session->security_parameters.entity == GNUTLS_SERVER) {
+ *apr_cert_list = session->internals.selected_cert_list;
+ *apr_pkey = session->internals.selected_key;
+ *apr_cert_list_length = session->internals.selected_cert_list_length;
- if (cred->ncerts == 0) {
- *apr_cert_list = NULL;
- *apr_cert_list_length = 0;
- *apr_pkey = NULL;
- gnutls_assert(); /* this is not allowed */
+ if ( apr_cert_list_length == 0 || apr_pkey == NULL ||
+ apr_cert_list == NULL)
+ {
+ gnutls_assert();
return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
- } else {
- /* find_cert_list_index() has been called before.
- */
- ind = session->internals.selected_cert_index;
-
- if (ind < 0) {
- *apr_cert_list = NULL;
- *apr_cert_list_length = 0;
- *apr_pkey = NULL;
- gnutls_assert();
- return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
- } else {
- *apr_cert_list = cred->cert_list[ind];
- *apr_cert_list_length =
- cred->cert_list_length[ind];
- *apr_pkey = &cred->pkey[ind];
- }
- }
- } else { /* CLIENT SIDE */
- if (cred->ncerts == 0) {
- *apr_cert_list = NULL;
- *apr_cert_list_length = 0;
- *apr_pkey = NULL;
- /* it is allowed not to have a certificate
- */
- } else {
- /* we had already decided which certificate
- * to send.
- */
- ind = session->internals.selected_cert_index;
-
- if (ind < 0) {
- *apr_cert_list = NULL;
- *apr_cert_list_length = 0;
- *apr_pkey = NULL;
- } else {
- *apr_cert_list = cred->cert_list[ind];
- *apr_cert_list_length =
- cred->cert_list_length[ind];
- *apr_pkey = &cred->pkey[ind];
- }
}
- }
+ } else { /* CLIENT SIDE
+ */
- return 0;
-}
-
-/* finds the most appropriate certificate in the cert list.
- * The 'appropriate' is defined by the user.
- * (frontend to _gnutls_server_find_cert_index())
- */
-const gnutls_cert *_gnutls_server_find_cert(gnutls_session session,
- gnutls_pk_algorithm
- requested_algo)
-{
- int i;
- const gnutls_certificate_credentials x509_cred;
-
- x509_cred =
- _gnutls_get_cred(session->key, GNUTLS_CRD_CERTIFICATE, NULL);
-
- if (x509_cred == NULL)
- return NULL;
-
- i = _gnutls_server_find_cert_list_index(session, requested_algo);
+ /* we have already decided which certificate
+ * to send.
+ */
+ *apr_cert_list = session->internals.selected_cert_list;
+ *apr_cert_list_length = session->internals.selected_cert_list_length;
+ *apr_pkey = session->internals.selected_key;
- if (i < 0)
- return NULL;
+ }
- return &x509_cred->cert_list[i][0];
+ return 0;
}
/* finds the most appropriate certificate in the cert list.
@@ -1334,13 +1272,16 @@ const gnutls_cert *_gnutls_server_find_cert(gnutls_session session,
*
* requested_algo holds the parameters required by the peer (RSA, DSA
* or -1 for any).
+ *
+ * Returns 0 on success and a negative value on error. The
+ * selected certificate will be in session->internals.selected_*.
+ *
*/
-static int _gnutls_server_find_cert_list_index(gnutls_session session,
- gnutls_pk_algorithm
- requested_algo)
+int _gnutls_server_select_cert(gnutls_session session,
+ gnutls_pk_algorithm requested_algo)
{
uint i, j;
- int index;
+ int index, ret;
const gnutls_certificate_credentials cred;
int my_certs_length;
@@ -1351,10 +1292,12 @@ static int _gnutls_server_find_cert_list_index(gnutls_session session,
return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
}
+ ret = 0;
index = -1; /* default is use no certificate */
for (i = 0; i < cred->ncerts; i++) {
- /* find one compatible certificate */
+ /* find one compatible certificate
+ */
if (requested_algo == (gnutls_pk_algorithm) - 1 ||
requested_algo ==
cred->cert_list[i][0].subject_pk_algorithm) {
@@ -1377,13 +1320,18 @@ static int _gnutls_server_find_cert_list_index(gnutls_session session,
my_certs_length = cred->ncerts;
my_certs =
gnutls_malloc(my_certs_length * sizeof(gnutls_datum));
- if (my_certs == NULL)
+ if (my_certs == NULL) {
+ ret = GNUTLS_E_MEMORY_ERROR;
goto out;
+ }
/* put our certificate's issuer and dn into cdn, idn
*/
ij_map = gnutls_malloc(my_certs_length * sizeof(int));
- if (ij_map == NULL) goto cleanup_certs;
+ if (ij_map == NULL) {
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto cleanup_certs;
+ }
j = 0;
for (i = 0; i < cred->ncerts; i++) {
@@ -1412,6 +1360,7 @@ static int _gnutls_server_find_cert_list_index(gnutls_session session,
if (index != -1)
index = ij_map[index];
+ ret = 0;
gnutls_free(ij_map);
cleanup_certs:
@@ -1423,6 +1372,11 @@ static int _gnutls_server_find_cert_list_index(gnutls_session session,
/* store the index for future use, in the handshake.
* (This will allow not calling this callback again.)
*/
- session->internals.selected_cert_index = index;
- return index;
+ if (index >= 0 && ret == 0) {
+ session->internals.selected_cert_list = &cred->cert_list[index][0];
+ session->internals.selected_cert_list_length = cred->cert_list_length[index];
+ session->internals.selected_key = &cred->pkey[index];
+ }
+
+ return ret;
}
diff --git a/lib/auth_cert.h b/lib/auth_cert.h
index a9760ab0ec..8f58018cb9 100644
--- a/lib/auth_cert.h
+++ b/lib/auth_cert.h
@@ -89,8 +89,9 @@ int _gnutls_gen_cert_server_cert_req(gnutls_session, opaque **);
int _gnutls_proc_cert_cert_req(gnutls_session, opaque *, size_t);
int _gnutls_proc_cert_client_cert_vrfy(gnutls_session, opaque *, size_t);
int _gnutls_proc_cert_server_certificate(gnutls_session, opaque *, size_t);
-int _gnutls_find_apr_cert( gnutls_session session, gnutls_cert** apr_cert_list, int *apr_cert_list_length, gnutls_privkey** apr_pkey);
-const gnutls_cert * _gnutls_server_find_cert( struct gnutls_session_int*, gnutls_pk_algorithm);
+int _gnutls_get_selected_cert( gnutls_session session, gnutls_cert** apr_cert_list, int *apr_cert_list_length, gnutls_privkey** apr_pkey);
+
+int _gnutls_server_select_cert( struct gnutls_session_int*, gnutls_pk_algorithm);
#define _gnutls_proc_cert_client_certificate _gnutls_proc_cert_server_certificate
diff --git a/lib/auth_dhe.c b/lib/auth_dhe.c
index 8e255da02d..bf636df2d2 100644
--- a/lib/auth_dhe.c
+++ b/lib/auth_dhe.c
@@ -79,6 +79,7 @@ const MOD_AUTH_STRUCT dhe_dss_auth_struct = {
static int gen_dhe_server_kx(gnutls_session session, opaque ** data)
{
GNUTLS_MPI g, p;
+ const GNUTLS_MPI *mpis;
int ret = 0, data_size;
int bits;
gnutls_cert *apr_cert_list;
@@ -98,18 +99,22 @@ static int gen_dhe_server_kx(gnutls_session session, opaque ** data)
/* find the appropriate certificate */
if ((ret =
- _gnutls_find_apr_cert(session, &apr_cert_list,
+ _gnutls_get_selected_cert(session, &apr_cert_list,
&apr_cert_list_length,
&apr_pkey)) < 0) {
gnutls_assert();
return ret;
}
- if ( (ret=_gnutls_get_dh_params( cred->dh_params, &p, &g)) < 0) {
+ mpis = _gnutls_get_dh_params( cred->dh_params);
+ if (mpis == NULL) {
gnutls_assert();
- return ret;
+ return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
}
+ p = mpis[0];
+ g = mpis[1];
+
if ( (ret=_gnutls_auth_info_set( session, GNUTLS_CRD_CERTIFICATE,
sizeof( CERTIFICATE_AUTH_INFO_INT), 0)) < 0)
{
@@ -125,8 +130,6 @@ static int gen_dhe_server_kx(gnutls_session session, opaque ** data)
}
ret = _gnutls_dh_common_print_server_kx( session, g, p, data);
- _gnutls_mpi_release(&g);
- _gnutls_mpi_release(&p);
if (ret < 0) {
gnutls_assert();
@@ -256,6 +259,7 @@ int bits;
const gnutls_certificate_credentials cred;
int ret;
GNUTLS_MPI p, g;
+const GNUTLS_MPI *mpis;
bits = _gnutls_dh_get_prime_bits( session);
@@ -265,14 +269,16 @@ GNUTLS_MPI p, g;
return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
}
- if ( (ret=_gnutls_get_dh_params( cred->dh_params, &p, &g)) < 0) {
+ mpis = _gnutls_get_dh_params( cred->dh_params);
+ if (mpis == NULL) {
gnutls_assert();
- return ret;
+ return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
}
+ p = mpis[0];
+ g = mpis[1];
+
ret = _gnutls_proc_dh_common_client_kx( session, data, _data_size, g, p);
- _gnutls_mpi_release(&g);
- _gnutls_mpi_release(&p);
return ret;
diff --git a/lib/auth_rsa.c b/lib/auth_rsa.c
index ef8d0d6d5e..8dd219716e 100644
--- a/lib/auth_rsa.c
+++ b/lib/auth_rsa.c
@@ -156,7 +156,7 @@ int i;
*/
int _gnutls_get_private_rsa_params(gnutls_session session, GNUTLS_MPI **params, int* params_size)
{
-int index;
+int bits;
const gnutls_certificate_credentials cred;
cred = _gnutls_get_cred(session->key, GNUTLS_CRD_CERTIFICATE, NULL);
@@ -165,14 +165,16 @@ const gnutls_certificate_credentials cred;
return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
}
- if ( (index=session->internals.selected_cert_index) < 0) {
+ if (session->internals.selected_cert_list == NULL) {
gnutls_assert();
- return GNUTLS_E_INTERNAL_ERROR;
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
}
+ bits = _gnutls_mpi_get_nbits(session->internals.selected_cert_list[0].params[0]);
+
if ( _gnutls_cipher_suite_get_kx_algo(session->security_parameters.current_cipher_suite)
== GNUTLS_KX_RSA_EXPORT &&
- _gnutls_mpi_get_nbits(cred->cert_list[index][0].params[0]) > 512) {
+ bits > 512) {
/* EXPORT case: */
if (cred->rsa_params == NULL) {
@@ -192,8 +194,8 @@ const gnutls_certificate_credentials cred;
/* non export cipher suites. */
- *params_size = cred->pkey[index].params_size;
- *params = cred->pkey[index].params;
+ *params_size = session->internals.selected_key->params_size;
+ *params = session->internals.selected_key->params;
return 0;
}
diff --git a/lib/auth_rsa_export.c b/lib/auth_rsa_export.c
index 3ae0096690..9d61d63e6b 100644
--- a/lib/auth_rsa_export.c
+++ b/lib/auth_rsa_export.c
@@ -88,7 +88,7 @@ static int gen_rsa_export_server_kx(gnutls_session session, opaque ** data)
/* find the appropriate certificate */
if ((ret =
- _gnutls_find_apr_cert(session, &apr_cert_list,
+ _gnutls_get_selected_cert(session, &apr_cert_list,
&apr_cert_list_length,
&apr_pkey)) < 0) {
gnutls_assert();
diff --git a/lib/dh_compat.c b/lib/dh_compat.c
index f6f1f49a05..56f5d0e87b 100644
--- a/lib/dh_compat.c
+++ b/lib/dh_compat.c
@@ -67,8 +67,8 @@ int gnutls_dh_params_set(gnutls_dh_params dh_params, gnutls_datum prime,
/* copy the generated values to the structure
*/
- dh_params->_prime = tmp_prime;
- dh_params->_generator = tmp_g;
+ dh_params->params[0] = tmp_prime;
+ dh_params->params[1] = tmp_g;
return 0;
diff --git a/lib/gnutls.h.in.in b/lib/gnutls.h.in.in
index 1d89595bd1..b056d9db41 100644
--- a/lib/gnutls.h.in.in
+++ b/lib/gnutls.h.in.in
@@ -347,6 +347,7 @@ int gnutls_certificate_allocate_credentials( gnutls_certificate_credentials *sc)
void gnutls_certificate_free_keys(gnutls_certificate_credentials sc);
void gnutls_certificate_free_cas(gnutls_certificate_credentials sc);
+void gnutls_certificate_free_ca_names(gnutls_certificate_credentials sc);
void gnutls_certificate_free_crls(gnutls_certificate_credentials sc);
void gnutls_certificate_set_dh_params(gnutls_certificate_credentials res, gnutls_dh_params);
diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c
index eb55209b68..a713060bdf 100644
--- a/lib/gnutls_algorithms.c
+++ b/lib/gnutls_algorithms.c
@@ -219,16 +219,16 @@ const int _gnutls_kx_algorithms_size = MAX_KX_ALGOS;
gnutls_kx_algo_entry _gnutls_kx_algorithms[MAX_KX_ALGOS] = {
#ifdef ENABLE_ANON
- { "Anon DH", GNUTLS_KX_ANON_DH, &anon_auth_struct },
+ { "Anon DH", GNUTLS_KX_ANON_DH, &anon_auth_struct, 1, 0 },
#endif
- { "RSA", GNUTLS_KX_RSA, &rsa_auth_struct },
- { "RSA EXPORT", GNUTLS_KX_RSA_EXPORT, &rsa_export_auth_struct },
- { "DHE RSA", GNUTLS_KX_DHE_RSA, &dhe_rsa_auth_struct },
- { "DHE DSS", GNUTLS_KX_DHE_DSS, &dhe_dss_auth_struct },
+ { "RSA", GNUTLS_KX_RSA, &rsa_auth_struct, 0, 0 },
+ { "RSA EXPORT", GNUTLS_KX_RSA_EXPORT, &rsa_export_auth_struct, 0, 1 },
+ { "DHE RSA", GNUTLS_KX_DHE_RSA, &dhe_rsa_auth_struct, 1, 0 },
+ { "DHE DSS", GNUTLS_KX_DHE_DSS, &dhe_dss_auth_struct, 1, 0 },
/* other algorithms are appended here by gnutls-extra
* initialization function.
*/
- {0, 0, 0}
+ {0, 0, 0, 0, 0}
};
#define GNUTLS_KX_LOOP(b) \
@@ -776,6 +776,21 @@ int _gnutls_kx_is_ok(gnutls_kx_algorithm algorithm)
return ret;
}
+int _gnutls_kx_needs_rsa_params(gnutls_kx_algorithm algorithm)
+{
+ ssize_t ret = 0;
+ GNUTLS_KX_ALG_LOOP(ret = p->needs_rsa_params);
+ return ret;
+}
+
+int _gnutls_kx_needs_dh_params(gnutls_kx_algorithm algorithm)
+{
+ ssize_t ret = 0;
+ GNUTLS_KX_ALG_LOOP(ret = p->needs_dh_params);
+ return ret;
+}
+
+
/* Version */
int _gnutls_version_priority(gnutls_session session,
gnutls_protocol_version version)
diff --git a/lib/gnutls_algorithms.h b/lib/gnutls_algorithms.h
index cbfde6788f..db3789a00e 100644
--- a/lib/gnutls_algorithms.h
+++ b/lib/gnutls_algorithms.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000 Nikos Mavroyanopoulos
+ * Copyright (C) 2000,2003 Nikos Mavroyanopoulos
*
* This file is part of GNUTLS.
*
@@ -60,6 +60,9 @@ const char *gnutls_cipher_get_name(gnutls_cipher_algorithm algorithm);
/* functions for key exchange */
int _gnutls_kx_priority(gnutls_session session, gnutls_kx_algorithm algorithm);
+int _gnutls_kx_needs_dh_params(gnutls_kx_algorithm algorithm);
+int _gnutls_kx_needs_rsa_params(gnutls_kx_algorithm algorithm);
+
MOD_AUTH_STRUCT * _gnutls_kx_auth_struct(gnutls_kx_algorithm algorithm);
const char *gnutls_kx_get_name(gnutls_kx_algorithm algorithm);
@@ -91,6 +94,8 @@ struct gnutls_kx_algo_entry {
const char *name;
gnutls_kx_algorithm algorithm;
MOD_AUTH_STRUCT *auth_struct;
+ int needs_dh_params;
+ int needs_rsa_params;
};
typedef struct gnutls_kx_algo_entry gnutls_kx_algo_entry;
diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c
index b65789e524..e9ff2a8df6 100644
--- a/lib/gnutls_cert.c
+++ b/lib/gnutls_cert.c
@@ -86,7 +86,9 @@ void gnutls_certificate_free_keys(gnutls_certificate_credentials sc)
* @sc: is an &gnutls_certificate_credentials structure.
*
* This function will delete all the CAs associated
- * with the given credentials.
+ * with the given credentials. Servers that do not use
+ * gnutls_certificate_verify_peers() may call this to
+ * save some memory.
*
**/
void gnutls_certificate_free_cas(gnutls_certificate_credentials sc)
@@ -102,8 +104,23 @@ void gnutls_certificate_free_cas(gnutls_certificate_credentials sc)
gnutls_free( sc->x509_ca_list);
sc->x509_ca_list = NULL;
- _gnutls_free_datum( &sc->x509_rdn_sequence);
+}
+/**
+ * gnutls_certificate_free_ca_names - Used to free all the CA names from a gnutls_certificate_credentials structure
+ * @sc: is an &gnutls_certificate_credentials structure.
+ *
+ * This function will delete all the CA name in the
+ * given credentials. Clients may call this to save some memory
+ * since in client side the CA names are not used.
+ *
+ * CA names are used by servers to advertize the CAs they
+ * support to clients.
+ *
+ **/
+void gnutls_certificate_free_ca_names(gnutls_certificate_credentials sc)
+{
+ _gnutls_free_datum( &sc->x509_rdn_sequence);
}
/**
@@ -157,15 +174,25 @@ int gnutls_certificate_allocate_credentials(gnutls_certificate_credentials * res
* This function also uses the KeyUsage field of the certificate
* extensions in order to disable unneded algorithms.
*/
-int _gnutls_cert_supported_kx(const gnutls_cert* cert, gnutls_kx_algorithm ** alg,
+int _gnutls_selected_cert_supported_kx( gnutls_session session, gnutls_kx_algorithm ** alg,
int *alg_size)
{
gnutls_kx_algorithm kx;
- int i;
gnutls_pk_algorithm pk;
gnutls_kx_algorithm kxlist[MAX_ALGOS];
+ gnutls_cert * cert;
+ int i;
+
+ if (session->internals.selected_cert_list_length == 0) {
+ gnutls_assert();
+ *alg_size = 0;
+ *alg = NULL;
+ return 0;
+ }
+ cert = &session->internals.selected_cert_list[0];
i = 0;
+
for (kx = 0; kx < MAX_ALGOS; kx++) {
pk = _gnutls_map_pk_get_pk(kx);
if (pk == cert->subject_pk_algorithm) {
diff --git a/lib/gnutls_cert.h b/lib/gnutls_cert.h
index f12bc96274..3de12ef484 100644
--- a/lib/gnutls_cert.h
+++ b/lib/gnutls_cert.h
@@ -90,6 +90,7 @@ int _gnutls_cert_get_dn(gnutls_cert * cert, gnutls_datum * odn);
void _gnutls_privkey_deinit(gnutls_privkey *key);
-int _gnutls_cert_supported_kx( const gnutls_cert* cert, gnutls_kx_algorithm **alg, int *alg_size);
-
+int _gnutls_selected_cert_supported_kx(struct gnutls_session_int* session,
+ gnutls_kx_algorithm ** alg, int *alg_size);
+
#endif
diff --git a/lib/gnutls_dh.h b/lib/gnutls_dh.h
index 9385079470..f556dbee56 100644
--- a/lib/gnutls_dh.h
+++ b/lib/gnutls_dh.h
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
-int _gnutls_get_dh_params(gnutls_dh_params, GNUTLS_MPI *ret_p, GNUTLS_MPI* ret_g);
+const GNUTLS_MPI* _gnutls_get_dh_params(gnutls_dh_params);
GNUTLS_MPI gnutls_calc_dh_secret( GNUTLS_MPI *ret_x, GNUTLS_MPI g, GNUTLS_MPI prime );
GNUTLS_MPI gnutls_calc_dh_key( GNUTLS_MPI f, GNUTLS_MPI x, GNUTLS_MPI prime );
int _gnutls_dh_generate_prime(GNUTLS_MPI *ret_g, GNUTLS_MPI* ret_n, uint bits);
diff --git a/lib/gnutls_dh_primes.c b/lib/gnutls_dh_primes.c
index 6bbd179b8a..d0f22310af 100644
--- a/lib/gnutls_dh_primes.c
+++ b/lib/gnutls_dh_primes.c
@@ -31,34 +31,15 @@
/* returns the prime and the generator of DH params.
*/
-int _gnutls_get_dh_params(gnutls_dh_params dh_primes,
- GNUTLS_MPI * ret_p, GNUTLS_MPI * ret_g)
+const GNUTLS_MPI* _gnutls_get_dh_params(gnutls_dh_params dh_primes)
{
- if (dh_primes == NULL || dh_primes->_prime == NULL ||
- dh_primes->_generator == NULL)
+ if (dh_primes == NULL || dh_primes->params[1] == NULL ||
+ dh_primes->params[0] == NULL)
{
- gnutls_assert();
- return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
- }
-
- if (ret_p != NULL) { /* caller wants the prime */
- *ret_p = _gnutls_mpi_copy(dh_primes->_prime);
- if (*ret_p == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
+ return NULL;
}
- if (ret_g != NULL) { /* caller wants the generator */
- *ret_g = _gnutls_mpi_copy(dh_primes->_generator);
- if (*ret_g == NULL) {
- gnutls_assert();
- if (ret_p) _gnutls_mpi_release(ret_p);
- return GNUTLS_E_MEMORY_ERROR;
- }
- }
-
- return 0;
+ return dh_primes->params;
}
int _gnutls_dh_generate_prime(GNUTLS_MPI * ret_g, GNUTLS_MPI * ret_n,
@@ -184,8 +165,8 @@ int gnutls_dh_params_import_raw(gnutls_dh_params dh_params, const gnutls_datum *
/* store the generated values
*/
- dh_params->_prime = tmp_prime;
- dh_params->_generator = tmp_g;
+ dh_params->params[0] = tmp_prime;
+ dh_params->params[1] = tmp_g;
return 0;
@@ -223,8 +204,8 @@ void gnutls_dh_params_deinit(gnutls_dh_params dh_params)
if (dh_params == NULL)
return;
- _gnutls_mpi_release(&dh_params->_prime);
- _gnutls_mpi_release(&dh_params->_generator);
+ _gnutls_mpi_release(&dh_params->params[0]);
+ _gnutls_mpi_release(&dh_params->params[1]);
gnutls_free(dh_params);
@@ -250,8 +231,8 @@ int gnutls_dh_params_generate2(gnutls_dh_params params, unsigned int bits)
{
int ret;
- ret = _gnutls_dh_generate_prime(&params->_generator,
- &params->_prime, bits);
+ ret = _gnutls_dh_generate_prime(&params->params[1],
+ &params->params[0], bits);
if (ret < 0) {
gnutls_assert();
return ret;
@@ -334,7 +315,7 @@ int gnutls_dh_params_import_pkcs3(gnutls_dh_params params,
/* Read PRIME
*/
- result = _gnutls_x509_read_int( c2, "prime", &params->_prime);
+ result = _gnutls_x509_read_int( c2, "prime", &params->params[0]);
if ( result < 0) {
asn1_delete_structure(&c2);
gnutls_assert();
@@ -343,10 +324,10 @@ int gnutls_dh_params_import_pkcs3(gnutls_dh_params params,
/* read the generator
*/
- result = _gnutls_x509_read_int( c2, "base", &params->_generator);
+ result = _gnutls_x509_read_int( c2, "base", &params->params[1]);
if ( result < 0) {
asn1_delete_structure(&c2);
- _gnutls_mpi_release( &params->_prime);
+ _gnutls_mpi_release( &params->params[0]);
gnutls_assert();
return result;
}
@@ -385,8 +366,8 @@ int gnutls_dh_params_export_pkcs3( gnutls_dh_params params,
opaque * p_data, *g_data;
opaque * all_data;
- _gnutls_mpi_print( NULL, &g_size, params->_generator);
- _gnutls_mpi_print( NULL, &p_size, params->_prime);
+ _gnutls_mpi_print( NULL, &g_size, params->params[1]);
+ _gnutls_mpi_print( NULL, &p_size, params->params[0]);
all_data = gnutls_malloc( g_size + p_size);
if (all_data == NULL) {
@@ -397,8 +378,8 @@ int gnutls_dh_params_export_pkcs3( gnutls_dh_params params,
p_data = &all_data[0];
g_data = &all_data[p_size];
- _gnutls_mpi_print( p_data, &p_size, params->_prime);
- _gnutls_mpi_print( g_data, &g_size, params->_generator);
+ _gnutls_mpi_print( p_data, &p_size, params->params[0]);
+ _gnutls_mpi_print( g_data, &g_size, params->params[1]);
/* Ok. Now we have the data. Create the asn1 structures
*/
@@ -536,15 +517,15 @@ int gnutls_dh_params_export_raw(gnutls_dh_params params,
size_t size;
- if (params->_generator == NULL ||
- params->_prime == NULL)
+ if (params->params[1] == NULL ||
+ params->params[0] == NULL)
{
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;
}
size = 0;
- _gnutls_mpi_print(NULL, &size, params->_generator);
+ _gnutls_mpi_print(NULL, &size, params->params[1]);
generator->data = gnutls_malloc(size);
if (generator->data == NULL) {
@@ -552,11 +533,11 @@ int gnutls_dh_params_export_raw(gnutls_dh_params params,
}
generator->size = size;
- _gnutls_mpi_print(generator->data, &size, params->_generator);
+ _gnutls_mpi_print(generator->data, &size, params->params[1]);
size = 0;
- _gnutls_mpi_print(NULL, &size, params->_prime);
+ _gnutls_mpi_print(NULL, &size, params->params[0]);
prime->data = gnutls_malloc(size);
if (prime->data == NULL) {
@@ -564,10 +545,10 @@ int gnutls_dh_params_export_raw(gnutls_dh_params params,
return GNUTLS_E_MEMORY_ERROR;
}
prime->size = size;
- _gnutls_mpi_print(prime->data, &size, params->_prime);
+ _gnutls_mpi_print(prime->data, &size, params->params[0]);
if (bits)
- *bits = _gnutls_mpi_get_nbits( params->_prime);
+ *bits = _gnutls_mpi_get_nbits( params->params[0]);
return 0;
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
index 2ff75b491a..4265344c44 100644
--- a/lib/gnutls_handshake.c
+++ b/lib/gnutls_handshake.c
@@ -46,6 +46,8 @@
#include <gnutls_alert.h>
#include <gnutls_state.h>
#include <ext_srp.h>
+#include <gnutls_rsa_export.h> /* for gnutls_get_rsa_params() */
+#include <auth_anon.h> /* for gnutls_anon_server_credentials */
#ifdef HANDSHAKE_DEBUG
#define ERR(x, y) _gnutls_handshake_log( "HSK[%x]: %s (%d)\n", session, x,y)
@@ -568,7 +570,7 @@ int _gnutls_server_select_suite(gnutls_session session, opaque *data, int datale
memset(session->security_parameters.current_cipher_suite.CipherSuite, '\0', 2);
retval = GNUTLS_E_UNKNOWN_CIPHER_SUITE;
-
+
for (j = 0; j < datalen; j += 2) {
for (i = 0; i < x; i++) {
if (memcmp(ciphers[i].CipherSuite, &data[j], 2) ==
@@ -2332,6 +2334,72 @@ int _gnutls_recv_hello_request(gnutls_session session, void *data,
}
}
+/* Returns 1 if the given KX has not the corresponding parameters
+ * (DH or RSA) set up. Otherwise returns 0.
+ */
+inline static int check_server_params( gnutls_session session, gnutls_kx_algorithm kx,
+ gnutls_kx_algorithm* alg, int alg_size)
+{
+ int cred_type;
+ const gnutls_certificate_credentials x509_cred;
+ const gnutls_anon_server_credentials anon_cred;
+ gnutls_dh_params dh_params = NULL;
+ gnutls_rsa_params rsa_params = NULL;
+ int j, keep;
+
+ cred_type = _gnutls_map_kx_get_cred( kx, 1);
+
+ if (cred_type == GNUTLS_CRD_CERTIFICATE) {
+ x509_cred =
+ _gnutls_get_cred(session->key, cred_type, NULL);
+
+ if (x509_cred != NULL) {
+ dh_params = x509_cred->dh_params;
+ rsa_params = x509_cred->rsa_params;
+ }
+
+ /* Check also if the certificate supports the
+ * KX method.
+ */
+ keep = 1;
+ for (j = 0; j < alg_size; j++) {
+ if (alg[j] == kx) {
+ keep = 0;
+ break;
+ }
+ }
+
+ if (keep == 1) return 1;
+
+
+ } else if ( cred_type == GNUTLS_CRD_ANON) {
+ anon_cred =
+ _gnutls_get_cred(session->key, cred_type, NULL);
+
+ if (anon_cred != NULL) {
+ dh_params = anon_cred->dh_params;
+ }
+ } else return 0; /* no need for params */
+
+
+ /* If the key exchange method needs RSA or DH params,
+ * but they are not set then remove it.
+ */
+ if (_gnutls_kx_needs_rsa_params( kx) != 0) {
+ /* needs rsa params. */
+ if (_gnutls_get_rsa_params( rsa_params)==NULL)
+ return 1;
+ }
+
+ if (_gnutls_kx_needs_dh_params( kx) != 0) {
+ /* needs DH params. */
+ if (_gnutls_get_dh_params( dh_params)==NULL)
+ return 1;
+ }
+
+ return 0;
+}
+
/* This function will remove algorithms that are not supported by
* the requested authentication method. We remove an algorithm if
* we have a certificate with keyUsage bits set.
@@ -2347,13 +2415,12 @@ int _gnutls_remove_unwanted_ciphersuites(gnutls_session session,
int ret = 0;
GNUTLS_CipherSuite *newSuite, cs;
- int newSuiteSize = 0, i, j, keep;
+ int newSuiteSize = 0, i, keep;
const gnutls_certificate_credentials x509_cred;
- const gnutls_cert* cert = NULL;
- gnutls_kx_algorithm *alg;
- int alg_size;
gnutls_kx_algorithm kx;
int server = session->security_parameters.entity==GNUTLS_SERVER?1:0;
+ gnutls_kx_algorithm *alg;
+ int alg_size;
/* if we should use a specific certificate,
* we should remove all algorithms that are not supported
@@ -2367,28 +2434,24 @@ int _gnutls_remove_unwanted_ciphersuites(gnutls_session session,
/* if x509_cred==NULL we should remove all X509 ciphersuites
*/
- cert = NULL;
if (session->security_parameters.entity == GNUTLS_SERVER) {
- cert = _gnutls_server_find_cert(session, requested_pk_algo);
- }
-
- if (cert == NULL) {
- /* No certificate was found
- */
- alg_size = 0;
- alg = NULL;
- } else {
- /* get all the key exchange algorithms that are
- * supported by the X509 certificate parameters.
- */
- if ((ret =
- _gnutls_cert_supported_kx(cert, &alg,
- &alg_size)) < 0) {
+ ret = _gnutls_server_select_cert(session, requested_pk_algo);
+ if (ret < 0) {
gnutls_assert();
return ret;
}
}
+ /* get all the key exchange algorithms that are
+ * supported by the X509 certificate parameters.
+ */
+ if ((ret =
+ _gnutls_selected_cert_supported_kx(session, &alg,
+ &alg_size)) < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
newSuite =
gnutls_malloc(numCipherSuites * sizeof(GNUTLS_CipherSuite));
if (newSuite == NULL) {
@@ -2410,28 +2473,14 @@ int _gnutls_remove_unwanted_ciphersuites(gnutls_session session,
*/
if (_gnutls_get_kx_cred(session, kx, NULL) == NULL) {
keep = 1;
- } else
- /* If there was no credentials to use with the specified
- * key exchange method, then just remove it.
- */
- if (_gnutls_map_kx_get_cred(kx, server) == GNUTLS_CRD_CERTIFICATE) {
- keep = 1; /* do not keep */
-
- if (x509_cred != NULL) {
- if (server) {
- /* here we check if the KX algorithm
- * is compatible with the certificate.
- */
- for (j = 0; j < alg_size; j++) {
- if (alg[j] == kx) {
- keep = 0;
- break;
- }
- }
- } else /* CLIENT */
- keep = 0;
- }
+ } else {
+ keep = 0;
+
+ if (server)
+ keep = check_server_params( session, kx, alg, alg_size);
}
+
+
memcpy( &cs.CipherSuite, &(*cipherSuites)[i].CipherSuite, 2);
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 1b9e21dcfc..d61b7d5d36 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -576,7 +576,9 @@ typedef struct {
/* holds the index of the selected certificate.
* -1 if none.
*/
- int selected_cert_index;
+ gnutls_cert* selected_cert_list;
+ int selected_cert_list_length;
+ gnutls_privkey* selected_key;
/* holds the extensions we sent to the peer
* (in case of a client)
@@ -646,8 +648,9 @@ struct gnutls_session_int {
typedef struct gnutls_session_int *gnutls_session;
typedef struct {
- GNUTLS_MPI _prime;
- GNUTLS_MPI _generator;
+ /* [0] is the prime, [1] is the generator.
+ */
+ GNUTLS_MPI params[2];
} _gnutls_dh_params;
#define gnutls_dh_params _gnutls_dh_params*
diff --git a/lib/gnutls_kx.c b/lib/gnutls_kx.c
index 4d250084c3..6d83c2ad78 100644
--- a/lib/gnutls_kx.c
+++ b/lib/gnutls_kx.c
@@ -357,7 +357,7 @@ int _gnutls_send_client_certificate( gnutls_session session, int again)
if (again == 0) {
if (gnutls_protocol_get_version( session) != GNUTLS_SSL3 ||
- session->internals.selected_cert_index >= 0) {
+ session->internals.selected_cert_list_length > 0) {
/* TLS 1.0 or SSL 3.0 with a valid certificate
*/
data_size = session->internals.auth_struct->gnutls_generate_client_certificate( session, &data);
@@ -374,7 +374,7 @@ int _gnutls_send_client_certificate( gnutls_session session, int again)
* empty certificate.
*/
if (gnutls_protocol_get_version( session) == GNUTLS_SSL3 &&
- session->internals.selected_cert_index < 0)
+ session->internals.selected_cert_list_length == 0)
{
ret = gnutls_alert_send( session, GNUTLS_AL_WARNING, GNUTLS_A_SSL3_NO_CERTIFICATE);
diff --git a/lib/gnutls_rsa_export.c b/lib/gnutls_rsa_export.c
index bc7104fb92..e030da9658 100644
--- a/lib/gnutls_rsa_export.c
+++ b/lib/gnutls_rsa_export.c
@@ -43,7 +43,6 @@
const GNUTLS_MPI* _gnutls_get_rsa_params(gnutls_rsa_params rsa_params)
{
if (rsa_params == NULL) {
- gnutls_assert();
return NULL;
}
diff --git a/lib/gnutls_ui.c b/lib/gnutls_ui.c
index dc5207efe2..bf157596db 100644
--- a/lib/gnutls_ui.c
+++ b/lib/gnutls_ui.c
@@ -196,7 +196,6 @@ int gnutls_dh_get_peers_public_bits(gnutls_session session)
const gnutls_datum *gnutls_certificate_get_ours(gnutls_session session)
{
const gnutls_certificate_credentials cred;
- int index;
CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, NULL);
@@ -206,15 +205,10 @@ const gnutls_datum *gnutls_certificate_get_ours(gnutls_session session)
return NULL;
}
- index = session->internals.selected_cert_index;
- if (index < 0) {
- gnutls_assert();
- return NULL; /* no certificate */
- }
-
- if (cred->ncerts > (unsigned int) index)
- return &cred->cert_list[index][0].raw;
- return NULL;
+ if (session->internals.selected_cert_list == NULL)
+ return NULL;
+
+ return &session->internals.selected_cert_list[0].raw;
}
/**
diff --git a/lib/libgnutls.vers b/lib/libgnutls.vers
index 798c683500..48cb0fbc39 100644
--- a/lib/libgnutls.vers
+++ b/lib/libgnutls.vers
@@ -1,4 +1,4 @@
-GNUTLS_REL_1_0
+GNUTLS_1_1
{
global: _gnutls*; gnutls*; _E_*;
local: *;
diff --git a/lib/x509/common.c b/lib/x509/common.c
index 7af2a068f0..47ebd6314d 100644
--- a/lib/x509/common.c
+++ b/lib/x509/common.c
@@ -626,7 +626,6 @@ int _gnutls_x509_export_int( ASN1_TYPE asn1_data,
{
*output_data_size = len;
if (result == ASN1_MEM_ERROR) {
- gnutls_assert();
return GNUTLS_E_SHORT_MEMORY_BUFFER;
}
gnutls_assert();