diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/auth_anon.c | 32 | ||||
-rw-r--r-- | lib/auth_cert.c | 182 | ||||
-rw-r--r-- | lib/auth_cert.h | 5 | ||||
-rw-r--r-- | lib/auth_dhe.c | 24 | ||||
-rw-r--r-- | lib/auth_rsa.c | 14 | ||||
-rw-r--r-- | lib/auth_rsa_export.c | 2 | ||||
-rw-r--r-- | lib/dh_compat.c | 4 | ||||
-rw-r--r-- | lib/gnutls.h.in.in | 1 | ||||
-rw-r--r-- | lib/gnutls_algorithms.c | 27 | ||||
-rw-r--r-- | lib/gnutls_algorithms.h | 7 | ||||
-rw-r--r-- | lib/gnutls_cert.c | 35 | ||||
-rw-r--r-- | lib/gnutls_cert.h | 5 | ||||
-rw-r--r-- | lib/gnutls_dh.h | 2 | ||||
-rw-r--r-- | lib/gnutls_dh_primes.c | 69 | ||||
-rw-r--r-- | lib/gnutls_handshake.c | 133 | ||||
-rw-r--r-- | lib/gnutls_int.h | 9 | ||||
-rw-r--r-- | lib/gnutls_kx.c | 4 | ||||
-rw-r--r-- | lib/gnutls_rsa_export.c | 1 | ||||
-rw-r--r-- | lib/gnutls_ui.c | 14 | ||||
-rw-r--r-- | lib/libgnutls.vers | 2 | ||||
-rw-r--r-- | lib/x509/common.c | 1 |
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(¶ms->_generator, - ¶ms->_prime, bits); + ret = _gnutls_dh_generate_prime(¶ms->params[1], + ¶ms->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", ¶ms->_prime); + result = _gnutls_x509_read_int( c2, "prime", ¶ms->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", ¶ms->_generator); + result = _gnutls_x509_read_int( c2, "base", ¶ms->params[1]); if ( result < 0) { asn1_delete_structure(&c2); - _gnutls_mpi_release( ¶ms->_prime); + _gnutls_mpi_release( ¶ms->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(); |