diff options
40 files changed, 683 insertions, 136 deletions
@@ -1,4 +1,13 @@ -Version 1.0.8 +Version 1.0.9 +- Added gnutls_certificate_set_params_function() and + gnutls_anon_set_params_function() that set the RSA or DH + parameters using a callback. +- Added functions gnutls_rsa_params_cpy(), gnutls_dh_params_cpy() + and gnutls_x509_privkey_cpy(). +- Corrected a compilation issue when opencdk was installed in a + non standard directory. + +Version 1.0.8 (28/02/2004) - Corrected bug in mutual certificate authentication in SSL 3.0. Version 1.0.7 (25/02/2004) diff --git a/configure.in b/configure.in index 859f667db3..518a6597bc 100644 --- a/configure.in +++ b/configure.in @@ -12,7 +12,7 @@ AC_DEFINE_UNQUOTED(T_OS, "$target_os", [OS name]) dnl Gnutls Version GNUTLS_MAJOR_VERSION=1 GNUTLS_MINOR_VERSION=0 -GNUTLS_MICRO_VERSION=8 +GNUTLS_MICRO_VERSION=9 GNUTLS_VERSION=$GNUTLS_MAJOR_VERSION.$GNUTLS_MINOR_VERSION.$GNUTLS_MICRO_VERSION AC_DEFINE_UNQUOTED(GNUTLS_VERSION, "$GNUTLS_VERSION", [version of gnutls]) @@ -30,7 +30,7 @@ AM_MAINTAINER_MODE dnl This is the library version GNUTLS_MOST_RECENT_INTERFACE=13 GNUTLS_CURRENT_INTERFACE_IMPLEMENTATION_NUMBER=$GNUTLS_MICRO_VERSION -GNUTLS_OLDEST_INTERFACE=10 +GNUTLS_OLDEST_INTERFACE=11 AC_SUBST(GNUTLS_MAJOR_VERSION) diff --git a/doc/examples/Makefile.am b/doc/examples/Makefile.am index 9b365b0f9f..c463d15043 100644 --- a/doc/examples/Makefile.am +++ b/doc/examples/Makefile.am @@ -1,4 +1,4 @@ EXTRA_DIST = ex-alert.c ex-client-resume.c ex-client-srp.c ex-client1.c \ ex-client2.c ex-x509-info.c ex-rfc2818.c ex-serv-export.c ex-serv-pgp.c \ - ex-serv-srp.c ex-serv1.c ex-pgp-keyserver.c ex-cert-select.c \ + ex-serv-srp.c ex-serv1.c ex-cert-select.c \ ex-crq.c ex-session-info.c ex-pkcs12.c diff --git a/doc/tex/Makefile.am b/doc/tex/Makefile.am index 7227d8a12c..53c37c1a90 100644 --- a/doc/tex/Makefile.am +++ b/doc/tex/Makefile.am @@ -7,7 +7,7 @@ EXTRA_DIST = gnutls.tex gnutls.ps \ EXAMPLE_OBJECTS = ex-alert.tex ex-client-srp.tex ex-serv-export.tex \ ex-client2.tex ex-x509-info.tex ex-rfc2818.tex \ ex-serv1.tex ex-client-resume.tex ex-serv-srp.tex \ - ex-serv-pgp.tex ex-pgp-keyserver.tex ex-cert-select.tex \ + ex-serv-pgp.tex ex-cert-select.tex \ ex-crq.tex ex-session-info.tex ex-pkcs12.tex TEX_OBJECTS = gnutls.tex ../../lib/gnutls-api.tex fdl.tex ../../lib/x509/x509-api.tex \ diff --git a/doc/tex/auth.tex b/doc/tex/auth.tex index 7a6f08a3ee..7e925ed62c 100644 --- a/doc/tex/auth.tex +++ b/doc/tex/auth.tex @@ -86,3 +86,65 @@ KX\_ANON\_DH & CRD\_ANON & CRD\_ANON \label{fig:kxcred} \end{figure} + + + +\section{Parameters stored in credentials} + +Several parameters such as the ones used for Diffie-Hellman authentication +are stored within the credentials structures, so all sessions can access +them. Those parameters are stored in structures such as {\bf gnutls\_dh\_params} +and {\bf gnutls\_rsa\_params}, and functions like +\printfunc{gnutls_certificate_set_dh_params}{gnutls\_certificate\_set\_dh\_params} +and +\printfunc{gnutls_certificate_set_rsa_export_params}{gnutls\_certificate\_set\_rsa\_export\_params} +can be used to associate those parameters with the given credentials structure. +\par +Since those parameters need to be renewed from time to time and a +global structure such as the credentials, may not be easy to modify +since it is accessible by all sessions, an alternative interface is +available using a callback function. +This can be set using the +\printfunc{gnutls_certificate_set_params_function}{gnutls\_certificate\_set\_params\_function}. +An example is shown below. + +\begin{verbatim} +#include <gnutls.h> + +gnutls_rsa_params rsa_params; +gnutls_dh_params dh_params; + +/* This function will be called once a session requests DH + * or RSA parameters. The parameters returned (if any) will + * be used for the first handshake only. + */ +static int get_params( gnutls_session session, gnutls_params_type type, + gnutls_params_st *st) +{ + if (type == GNUTLS_PARAMS_RSA_EXPORT) + st->params.rsa_export = rsa_params; + else if (type == GNUTLS_PARAMS_DH) + st->params.dh = dh_params; + else return -1; + + st->type = type; + /* do not deinitialize those parameters. + */ + st->deinit = 0; + + return 0; +} + +int main() +{ + gnutls_certificate_credentials cert_cred; + + initialize_params(); + + /* ... + */ + + gnutls_certificate_set_params_function( cert_cred, get_params); + +} +\end{verbatim} diff --git a/doc/tex/examples.tex b/doc/tex/examples.tex index 544b502616..940b2b66b7 100644 --- a/doc/tex/examples.tex +++ b/doc/tex/examples.tex @@ -90,13 +90,6 @@ is separate for simplicity. \section{Miscellaneous examples} -\subsection{A callback which\index{OpenPGP!Key retrieval} retrieves OpenPGP keys} -The following example is a callback function which retrieves {\bf OpenPGP} keys from -a public key server. This is useful when a client connected to an OpenPGP \tls{} server -and sent its key fingerprint instead of the whole key. With this callback the \tls{} -server can retrieve the key from a public key server. -\input{ex-pgp-keyserver} - \subsection{Checking for an alert} This is a function that checks if an alert has been received in the current session. diff --git a/doc/tex/preparation.tex b/doc/tex/preparation.tex index 7afeaf2c99..f356441705 100644 --- a/doc/tex/preparation.tex +++ b/doc/tex/preparation.tex @@ -69,3 +69,65 @@ specifying both options to `libgnutls-config': gcc -o foo foo.c `libgnutls-config --cflags --libs` \end{verbatim} + +\section{Multi-threaded applications} + +Although the \gnutls{} library is thread safe by design, some parts of the crypto +backend, such as the random generator, are not. Since \emph{libgcrypt 1.1.92} +there was an automatic detection of the thread library used by the +application, so most applications wouldn't need to do any changes to +ensure thread-safety. Due to the unportability of the automatic thread +detection, this was removed from later releases of \emph{libgcrypt}, so +applications have now to register callback functions to ensure proper locking +in sensitive parts of \emph{libgcrypt}. +\par +There are helper macros to help you properly initialize the libraries. +Examples are shown below. +\begin{itemize} + +\item POSIX threads +\begin{verbatim} +#include <gnutls.h> +#include <gcrypt.h> +#include <errno.h> +#include <pthread.h> +GCRY_THREAD_OPTION_PTHREAD_IMPL; + +int main() +{ + /* The order matters. + */ + gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); + gnutls_global_init(); +} +\end{verbatim} + +\item GNU PTH threads +\begin{verbatim} +#include <gnutls.h> +#include <gcrypt.h> +#include <errno.h> +#include <pth.h> +GCRY_THREAD_OPTION_PTH_IMPL; + +int main() +{ + gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); + gnutls_global_init(); +} +\end{verbatim} + +\item Other thread packages +\begin{verbatim} +/* The gcry_thread_cbs structure must have been + * initialized. + */ +static struct gcry_thread_cbs gcry_threads_other = { ... }; + +int main() +{ + gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_other); +} +\end{verbatim} +\end{itemize} + diff --git a/includes/gnutls/x509.h b/includes/gnutls/x509.h index ab8346d3c9..75a6647cf4 100644 --- a/includes/gnutls/x509.h +++ b/includes/gnutls/x509.h @@ -311,6 +311,7 @@ typedef enum gnutls_pkcs_encrypt_flags { int gnutls_x509_privkey_init(gnutls_x509_privkey * key); void gnutls_x509_privkey_deinit(gnutls_x509_privkey key); +int gnutls_x509_privkey_cpy(gnutls_x509_privkey dst, gnutls_x509_privkey src); int gnutls_x509_privkey_import(gnutls_x509_privkey key, const gnutls_datum * data, gnutls_x509_crt_fmt format); int gnutls_x509_privkey_import_pkcs8(gnutls_x509_privkey key, const gnutls_datum * data, diff --git a/lib/Makefile.am b/lib/Makefile.am index 9a55b33fc7..27e7daeb5e 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = -I../libextra -Iminitasn1/ -I../includes $(LIBGCRYPT_CFLAGS) +INCLUDES = -I../libextra -Iminitasn1/ -I../includes $(LIBOPENCDK_CFLAGS) $(LIBGCRYPT_CFLAGS) bin_SCRIPTS = libgnutls-config m4datadir = $(datadir)/aclocal diff --git a/lib/auth_anon.c b/lib/auth_anon.c index a49df2092c..9f6983a5b3 100644 --- a/lib/auth_anon.c +++ b/lib/auth_anon.c @@ -63,6 +63,7 @@ static int gen_anon_server_kx( gnutls_session session, opaque** data) { GNUTLS_MPI g, p; const GNUTLS_MPI *mpis; int ret; + gnutls_dh_params dh_params; const gnutls_anon_server_credentials cred; cred = _gnutls_get_cred(session->key, GNUTLS_CRD_ANON, NULL); @@ -71,7 +72,8 @@ static int gen_anon_server_kx( gnutls_session session, opaque** data) { return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } - mpis = _gnutls_get_dh_params( cred->dh_params); + dh_params = _gnutls_anon_get_dh_params( cred, session); + mpis = _gnutls_get_dh_params( dh_params); if (mpis == NULL) { gnutls_assert(); return GNUTLS_E_NO_TEMPORARY_DH_PARAMS; @@ -106,6 +108,7 @@ const gnutls_anon_server_credentials cred; int bits; int ret; GNUTLS_MPI p, g; +gnutls_dh_params dh_params; const GNUTLS_MPI *mpis; bits = _gnutls_dh_get_prime_bits( session); @@ -116,7 +119,8 @@ const GNUTLS_MPI *mpis; return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } - mpis = _gnutls_get_dh_params( cred->dh_params); + dh_params = _gnutls_anon_get_dh_params( cred, session); + mpis = _gnutls_get_dh_params( dh_params); if (mpis == NULL) { gnutls_assert(); return GNUTLS_E_NO_TEMPORARY_DH_PARAMS; diff --git a/lib/auth_anon.h b/lib/auth_anon.h index 2bfd0f53e5..29c4114338 100644 --- a/lib/auth_anon.h +++ b/lib/auth_anon.h @@ -3,6 +3,10 @@ typedef struct { gnutls_dh_params dh_params; + /* this callback is used to retrieve the DH or RSA + * parameters. + */ + gnutls_params_function * params_func; } ANON_SERVER_CREDENTIALS_INT; #define gnutls_anon_server_credentials ANON_SERVER_CREDENTIALS_INT* @@ -18,3 +22,6 @@ typedef ANON_CLIENT_AUTH_INFO ANON_SERVER_AUTH_INFO; typedef struct ANON_CLIENT_AUTH_INFO_INT ANON_CLIENT_AUTH_INFO_INT; typedef ANON_CLIENT_AUTH_INFO_INT ANON_SERVER_AUTH_INFO_INT; + +gnutls_dh_params _gnutls_anon_get_dh_params(const gnutls_anon_server_credentials sc, + gnutls_session session); diff --git a/lib/auth_cert.h b/lib/auth_cert.h index d99991a9b7..a27dbffc92 100644 --- a/lib/auth_cert.h +++ b/lib/auth_cert.h @@ -35,6 +35,10 @@ typedef int gnutls_certificate_server_retrieve_function( typedef struct { gnutls_dh_params dh_params; gnutls_rsa_params rsa_params; + /* this callback is used to retrieve the DH or RSA + * parameters. + */ + gnutls_params_function * params_func; gnutls_cert ** cert_list; /* contains a list of a list of certificates. @@ -127,5 +131,10 @@ void _gnutls_selected_certs_set( gnutls_session session, #define _gnutls_proc_cert_client_certificate _gnutls_proc_cert_server_certificate +gnutls_rsa_params _gnutls_certificate_get_rsa_params(const gnutls_certificate_credentials sc, + gnutls_session session); +gnutls_dh_params _gnutls_certificate_get_dh_params(const gnutls_certificate_credentials sc, + gnutls_session session); + #endif diff --git a/lib/auth_dhe.c b/lib/auth_dhe.c index 79f499156f..bc7eede562 100644 --- a/lib/auth_dhe.c +++ b/lib/auth_dhe.c @@ -89,6 +89,7 @@ static int gen_dhe_server_kx(gnutls_session session, opaque ** data) gnutls_datum signature, ddata; CERTIFICATE_AUTH_INFO info; const gnutls_certificate_credentials cred; + gnutls_dh_params dh_params; cred = _gnutls_get_cred(session->key, GNUTLS_CRD_CERTIFICATE, NULL); if (cred == NULL) { @@ -107,7 +108,8 @@ static int gen_dhe_server_kx(gnutls_session session, opaque ** data) return ret; } - mpis = _gnutls_get_dh_params( cred->dh_params); + dh_params = _gnutls_certificate_get_dh_params( cred, session); + mpis = _gnutls_get_dh_params( dh_params); if (mpis == NULL) { gnutls_assert(); return GNUTLS_E_NO_TEMPORARY_DH_PARAMS; @@ -237,6 +239,7 @@ const gnutls_certificate_credentials cred; int ret; GNUTLS_MPI p, g; const GNUTLS_MPI *mpis; +gnutls_dh_params dh_params; bits = _gnutls_dh_get_prime_bits( session); @@ -246,7 +249,8 @@ const GNUTLS_MPI *mpis; return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } - mpis = _gnutls_get_dh_params( cred->dh_params); + dh_params = _gnutls_certificate_get_dh_params( cred, session); + mpis = _gnutls_get_dh_params( dh_params); if (mpis == NULL) { gnutls_assert(); return GNUTLS_E_NO_TEMPORARY_DH_PARAMS; diff --git a/lib/auth_rsa.c b/lib/auth_rsa.c index 5931460274..6547651c34 100644 --- a/lib/auth_rsa.c +++ b/lib/auth_rsa.c @@ -137,6 +137,7 @@ int _gnutls_get_private_rsa_params(gnutls_session session, GNUTLS_MPI **params, { int bits; const gnutls_certificate_credentials cred; +gnutls_rsa_params rsa_params; cred = _gnutls_get_cred(session->key, GNUTLS_CRD_CERTIFICATE, NULL); if (cred == NULL) { @@ -155,8 +156,9 @@ const gnutls_certificate_credentials cred; == GNUTLS_KX_RSA_EXPORT && bits > 512) { + rsa_params = _gnutls_certificate_get_rsa_params( cred, session); /* EXPORT case: */ - if (cred->rsa_params == NULL) { + if (rsa_params == NULL) { gnutls_assert(); return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS; } @@ -166,7 +168,7 @@ const gnutls_certificate_credentials cred; * used to sign this temporary stuff. */ *params_size = RSA_PRIVATE_PARAMS; - *params = cred->rsa_params->params; + *params = rsa_params->params; return 0; } diff --git a/lib/auth_rsa_export.c b/lib/auth_rsa_export.c index 340c7e5aa3..84d09f36a6 100644 --- a/lib/auth_rsa_export.c +++ b/lib/auth_rsa_export.c @@ -67,7 +67,8 @@ const MOD_AUTH_STRUCT rsa_export_auth_struct = { static int gen_rsa_export_server_kx(gnutls_session session, opaque ** data) { - const GNUTLS_MPI *rsa_params; + gnutls_rsa_params rsa_params; + const GNUTLS_MPI *rsa_mpis; size_t n_e, n_m; uint8 *data_e, *data_m; int ret = 0, data_size; @@ -101,8 +102,9 @@ static int gen_rsa_export_server_kx(gnutls_session session, opaque ** data) return GNUTLS_E_INT_RET_0; } - rsa_params = _gnutls_get_rsa_params( cred->rsa_params); - if (rsa_params == NULL) { + rsa_params = _gnutls_certificate_get_rsa_params( cred, session); + rsa_mpis = _gnutls_get_rsa_params( rsa_params); + if (rsa_mpis == NULL) { gnutls_assert(); return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS; } @@ -114,14 +116,14 @@ static int gen_rsa_export_server_kx(gnutls_session session, opaque ** data) } info = _gnutls_get_auth_info( session); - ret=_gnutls_rsa_export_set_modulus_bits( session, _gnutls_mpi_get_nbits(rsa_params[0])); + ret=_gnutls_rsa_export_set_modulus_bits( session, _gnutls_mpi_get_nbits(rsa_mpis[0])); if (ret<0) { gnutls_assert(); return ret; } - _gnutls_mpi_print( NULL, &n_m, rsa_params[0]); - _gnutls_mpi_print( NULL, &n_e, rsa_params[1]); + _gnutls_mpi_print( NULL, &n_m, rsa_mpis[0]); + _gnutls_mpi_print( NULL, &n_e, rsa_mpis[1]); (*data) = gnutls_malloc(n_e + n_m + 4); if (*data == NULL) { @@ -129,12 +131,12 @@ static int gen_rsa_export_server_kx(gnutls_session session, opaque ** data) } data_m = &(*data)[0]; - _gnutls_mpi_print( &data_m[2], &n_m, rsa_params[0]); + _gnutls_mpi_print( &data_m[2], &n_m, rsa_mpis[0]); _gnutls_write_uint16(n_m, data_m); data_e = &data_m[2 + n_m]; - _gnutls_mpi_print( &data_e[2], &n_e, rsa_params[1]); + _gnutls_mpi_print( &data_e[2], &n_e, rsa_mpis[1]); _gnutls_write_uint16(n_e, data_e); diff --git a/lib/gnutls.h.in.in b/lib/gnutls.h.in.in index e4183ee103..c5682ea772 100644 --- a/lib/gnutls.h.in.in +++ b/lib/gnutls.h.in.in @@ -70,6 +70,10 @@ typedef enum gnutls_kx_algorithm { GNUTLS_KX_RSA=1, GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA_EXPORT, GNUTLS_KX_SRP_RSA, GNUTLS_KX_SRP_DSS } gnutls_kx_algorithm; +typedef enum gnutls_params_type { GNUTLS_PARAMS_RSA_EXPORT=1, + GNUTLS_PARAMS_DH +} gnutls_params_type; + typedef enum gnutls_credentials_type { GNUTLS_CRD_CERTIFICATE=1, GNUTLS_CRD_ANON, GNUTLS_CRD_SRP } gnutls_credentials_type; typedef enum gnutls_mac_algorithm { GNUTLS_MAC_NULL=1, @@ -436,12 +440,14 @@ int gnutls_dh_params_export_pkcs3( gnutls_dh_params params, gnutls_x509_crt_fmt format, unsigned char* params_data, size_t* params_data_size); int gnutls_dh_params_export_raw(gnutls_dh_params params, gnutls_datum * prime, gnutls_datum * generator, unsigned int *bits); +int gnutls_dh_params_cpy(gnutls_dh_params dst, gnutls_dh_params src); /* RSA params */ int gnutls_rsa_params_init(gnutls_rsa_params * rsa_params); void gnutls_rsa_params_deinit(gnutls_rsa_params rsa_params); +int gnutls_rsa_params_cpy(gnutls_rsa_params dst, gnutls_rsa_params src); int gnutls_rsa_params_import_raw(gnutls_rsa_params rsa_params, const gnutls_datum *m, const gnutls_datum *e, const gnutls_datum *d, const gnutls_datum *p, diff --git a/lib/gnutls_anon_cred.c b/lib/gnutls_anon_cred.c index 42b61bdf74..835c23ae18 100644 --- a/lib/gnutls_anon_cred.c +++ b/lib/gnutls_anon_cred.c @@ -40,11 +40,41 @@ static const int anon_dummy; * This structure is complex enough to manipulate directly thus * this helper function is provided in order to free (deallocate) it. **/ -void gnutls_anon_free_server_credentials( gnutls_anon_server_credentials sc) { +void gnutls_anon_free_server_credentials( gnutls_anon_server_credentials sc) +{ gnutls_free( sc); } +/*- + * _gnutls_anon_get_dh_params - Returns the DH parameters pointer + * @sc: is an &gnutls_certificate_credentials structure. + * + * This function will return the dh parameters pointer. + * + -*/ +gnutls_dh_params _gnutls_anon_get_dh_params(const gnutls_anon_server_credentials sc, + gnutls_session session) +{ +gnutls_params_st params; +int ret; + + if (session->internals.params.anon_dh_params) + return session->internals.params.anon_dh_params; + + if (sc->dh_params) { + session->internals.params.anon_dh_params = sc->dh_params; + } else if (sc->params_func) { + ret = sc->params_func( session, GNUTLS_PARAMS_DH, ¶ms); + if (ret == 0 && params.type == GNUTLS_PARAMS_DH) { + session->internals.params.anon_dh_params = params.params.dh; + session->internals.params.free_anon_dh_params = params.deinit; + } + } + + return session->internals.params.anon_dh_params; +} + /** * gnutls_anon_allocate_server_credentials - Used to allocate an gnutls_anon_server_credentials structure * @sc: is a pointer to an &gnutls_anon_server_credentials structure. diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c index a7a2297780..67d1520da2 100644 --- a/lib/gnutls_cert.c +++ b/lib/gnutls_cert.c @@ -124,6 +124,69 @@ void gnutls_certificate_free_ca_names(gnutls_certificate_credentials sc) _gnutls_free_datum( &sc->x509_rdn_sequence); } +/*- + * _gnutls_certificate_get_dh_params - Returns the DH parameters pointer + * @sc: is an &gnutls_certificate_credentials structure. + * + * This function will return the dh parameters pointer. This will read the + * credentials structure, and cache the output to the session, so later + * calls would not examine the credentials (or call a callback). + * + -*/ +gnutls_dh_params _gnutls_certificate_get_dh_params(const gnutls_certificate_credentials sc, + gnutls_session session) +{ +gnutls_params_st params; +int ret; + + if (session->internals.params.cert_dh_params) { + return session->internals.params.cert_dh_params; + } + + if (sc->dh_params) { + session->internals.params.cert_dh_params = sc->dh_params; + } else if (sc->params_func) { + ret = sc->params_func( session, GNUTLS_PARAMS_DH, ¶ms); + if (ret == 0 && params.type == GNUTLS_PARAMS_DH) { + session->internals.params.cert_dh_params = params.params.dh; + session->internals.params.free_cert_dh_params = params.deinit; + } + } + + return session->internals.params.cert_dh_params; +} + +/*- + * _gnutls_certificate_get_rsa_params - Returns the RSA parameters pointer + * @sc: is an &gnutls_certificate_credentials structure. + * + * This function will return the rsa parameters pointer. + * + -*/ +gnutls_rsa_params _gnutls_certificate_get_rsa_params(const gnutls_certificate_credentials sc, + gnutls_session session) +{ +gnutls_params_st params; +int ret; + + if (session->internals.params.rsa_params) { + return session->internals.params.rsa_params; + } + + if (sc->rsa_params) { + session->internals.params.rsa_params = sc->rsa_params; + } else if (sc->params_func) { + ret = sc->params_func( session, GNUTLS_PARAMS_RSA_EXPORT, ¶ms); + if (ret == 0 && params.type == GNUTLS_PARAMS_RSA_EXPORT) { + session->internals.params.rsa_params = params.params.rsa_export; + session->internals.params.free_rsa_params = params.deinit; + } + } + + return session->internals.params.rsa_params; +} + + /** * gnutls_certificate_free_credentials - Used to free an allocated gnutls_certificate_credentials structure * @sc: is an &gnutls_certificate_credentials structure. diff --git a/lib/gnutls_cert.h b/lib/gnutls_cert.h index 96218ff479..c1384f17b3 100644 --- a/lib/gnutls_cert.h +++ b/lib/gnutls_cert.h @@ -98,5 +98,5 @@ int _gnutls_raw_cert_to_gcert(gnutls_cert * gcert, gnutls_certificate_type type, const gnutls_datum *raw_cert, int flags /* OR of ConvFlags */); int _gnutls_raw_privkey_to_gkey(gnutls_privkey * key, gnutls_certificate_type type, const gnutls_datum *raw_key, int key_enc /* DER or PEM */); - + #endif diff --git a/lib/gnutls_dh.h b/lib/gnutls_dh.h index f556dbee56..3cf53c7881 100644 --- a/lib/gnutls_dh.h +++ b/lib/gnutls_dh.h @@ -22,3 +22,4 @@ 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); +void gnutls_dh_params_deinit(gnutls_dh_params dh_params); diff --git a/lib/gnutls_dh_primes.c b/lib/gnutls_dh_primes.c index 785b0b1fdc..b91a1cae0d 100644 --- a/lib/gnutls_dh_primes.c +++ b/lib/gnutls_dh_primes.c @@ -205,6 +205,30 @@ void gnutls_dh_params_deinit(gnutls_dh_params dh_params) } /** + * gnutls_dh_params_cpy - This function will copy a DH parameters structure + * @dst: Is the destination structure, which should be initialized. + * @src: Is the source structure + * + * This function will copy the DH parameters structure from source + * to destination. + * + **/ +int gnutls_dh_params_cpy(gnutls_dh_params dst, gnutls_dh_params src) +{ + if (src == NULL) + return GNUTLS_E_INVALID_REQUEST; + + dst->params[0] = _gnutls_mpi_copy(src->params[0]); + dst->params[1] = _gnutls_mpi_copy(src->params[1]); + + if (dst->params[0]==NULL || dst->params[1] == NULL) + return GNUTLS_E_MEMORY_ERROR; + + return 0; +} + + +/** * gnutls_dh_params_generate2 - This function will generate new DH parameters * @params: Is the structure that the DH parameters will be stored * @bits: is the prime's number of bits diff --git a/lib/gnutls_global.c b/lib/gnutls_global.c index 0c6bf8525a..9a5c98b1ab 100644 --- a/lib/gnutls_global.c +++ b/lib/gnutls_global.c @@ -168,8 +168,14 @@ int gnutls_global_init( void) _gnutls_init++; if (gcry_control( GCRYCTL_ANY_INITIALIZATION_P) == 0) { - if (gcry_check_version(GNUTLS_GCRYPT_VERSION)==NULL) { + const char* p; + p = strchr( GNUTLS_GCRYPT_VERSION, ':'); + if (p==NULL) p = GNUTLS_GCRYPT_VERSION; + else p++; + + if (gcry_check_version(p)==NULL) { gnutls_assert(); + _gnutls_debug_log("Checking for libgcrypt failed '%s'\n", p); return GNUTLS_E_INCOMPATIBLE_GCRYPT_LIBRARY; } diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 91c0e8585b..09d9f6faba 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -174,6 +174,10 @@ typedef enum gnutls_kx_algorithm { GNUTLS_KX_RSA=1, GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA_EXPORT, GNUTLS_KX_SRP_RSA, GNUTLS_KX_SRP_DSS } gnutls_kx_algorithm; +typedef enum gnutls_params_type { GNUTLS_PARAMS_RSA_EXPORT=1, + GNUTLS_PARAMS_DH +} gnutls_params_type; + typedef enum gnutls_mac_algorithm { GNUTLS_MAC_UNKNOWN=0, GNUTLS_MAC_NULL=1, GNUTLS_MAC_MD5, GNUTLS_MAC_SHA, GNUTLS_MAC_RMD160 } gnutls_mac_algorithm; @@ -427,6 +431,38 @@ typedef int certificate_server_select_func(struct gnutls_session_int*, typedef int srp_server_select_func(struct gnutls_session_int*, const char**, const char**, unsigned int); +/* DH and RSA parameters types. + */ +typedef struct { + /* [0] is the prime, [1] is the generator. + */ + GNUTLS_MPI params[2]; +} _gnutls_dh_params; + +#define gnutls_dh_params _gnutls_dh_params* + +#define gnutls_rsa_params gnutls_x509_privkey + +typedef struct gnutls_internal_params { + gnutls_dh_params anon_dh_params; + int free_anon_dh_params; + gnutls_dh_params cert_dh_params; + int free_cert_dh_params; + gnutls_rsa_params rsa_params; + int free_rsa_params; +} gnutls_internal_params; + +typedef struct gnutls_params_st { + gnutls_params_type type; + union params { + gnutls_dh_params dh; + gnutls_rsa_params rsa_export; + } params; + int deinit; +} gnutls_params_st; + + + typedef struct { opaque header[HANDSHAKE_HEADER_SIZE]; /* this holds the number of bytes in the handshake_header[] */ @@ -631,7 +667,7 @@ typedef struct { /* This is used to set an arbitary version in the RSA * PMS secret. Can be used by clients to test whether the - * server checks that version. + * server checks that version. (** only used in gnutls-cli-debug) */ opaque rsa_pms_version[2]; @@ -643,6 +679,12 @@ typedef struct { */ int handshake_restarted; + /* Here we cache the DH or RSA parameters got from the + * credentials structure, or from a callback. That is to + * minimize external calls. + */ + gnutls_internal_params params; + /* If you add anything here, check _gnutls_handshake_internal_state_clear(). */ } GNUTLS_INTERNALS; @@ -657,18 +699,10 @@ struct gnutls_session_int { typedef struct gnutls_session_int *gnutls_session; -typedef struct { - /* [0] is the prime, [1] is the generator. - */ - GNUTLS_MPI params[2]; -} _gnutls_dh_params; - -#define gnutls_dh_params _gnutls_dh_params* -#define gnutls_rsa_params gnutls_x509_privkey - -/* functions */ +/* functions + */ void _gnutls_set_current_version(gnutls_session session, gnutls_protocol_version version); gnutls_protocol_version gnutls_protocol_get_version(gnutls_session session); void _gnutls_free_auth_info( gnutls_session session); @@ -692,4 +726,7 @@ gnutls_protocol_version _gnutls_get_adv_version( gnutls_session); int gnutls_fingerprint(gnutls_digest_algorithm algo, const gnutls_datum* data, void* result, size_t* result_size); +typedef int gnutls_params_function(gnutls_session, gnutls_params_type, + gnutls_params_st*); + #endif /* GNUTLS_INT_H */ diff --git a/lib/gnutls_rsa_export.c b/lib/gnutls_rsa_export.c index 05e82535ef..fa1ed8b853 100644 --- a/lib/gnutls_rsa_export.c +++ b/lib/gnutls_rsa_export.c @@ -29,6 +29,7 @@ #include <gnutls_datum.h> #include <gnutls_rsa_export.h> #include "x509/x509.h" +#include "x509/privkey.h" #include "debug.h" /* This function takes a number of bits and returns a supported @@ -202,6 +203,20 @@ void gnutls_rsa_params_deinit(gnutls_rsa_params rsa_params) } /** + * gnutls_rsa_params_cpy - This function will copy an RSA parameters structure + * @dst: Is the destination structure, which should be initialized. + * @src: Is the source structure + * + * This function will copy the RSA parameters structure from source + * to destination. + * + **/ +int gnutls_rsa_params_cpy(gnutls_rsa_params dst, gnutls_rsa_params src) +{ + return gnutls_x509_privkey_cpy( dst, src); +} + +/** * gnutls_rsa_params_generate2 - This function will generate temporary RSA parameters * @params: The structure where the parameters will be stored * @bits: is the prime's number of bits diff --git a/lib/gnutls_rsa_export.h b/lib/gnutls_rsa_export.h index 57897d32bb..765610e1a7 100644 --- a/lib/gnutls_rsa_export.h +++ b/lib/gnutls_rsa_export.h @@ -21,4 +21,5 @@ const GNUTLS_MPI* _gnutls_get_rsa_params(gnutls_rsa_params); int _gnutls_peers_cert_less_512( gnutls_session session); int _gnutls_rsa_generate_params(GNUTLS_MPI* resarr, int* resarr_len, int bits); +void gnutls_rsa_params_deinit(gnutls_rsa_params rsa_params); diff --git a/lib/gnutls_sig.c b/lib/gnutls_sig.c index 1c6306f4c7..ab362df3b8 100644 --- a/lib/gnutls_sig.c +++ b/lib/gnutls_sig.c @@ -105,14 +105,16 @@ gnutls_protocol_version ver = gnutls_protocol_get_version( session); /* Generates a signature of all the random data and the parameters. * Used in DHE_* ciphersuites. */ -int _gnutls_tls_sign_params( gnutls_session session, gnutls_cert* cert, gnutls_privkey* pkey, gnutls_datum* params, gnutls_datum *signature) +int _gnutls_tls_sign_params( gnutls_session session, + gnutls_cert* cert, gnutls_privkey* pkey, + gnutls_datum* params, gnutls_datum *signature) { gnutls_datum dconcat; int ret; GNUTLS_MAC_HANDLE td_md5; GNUTLS_MAC_HANDLE td_sha; opaque concat[36]; - +gnutls_protocol_version ver = gnutls_protocol_get_version( session); td_sha = _gnutls_hash_init( GNUTLS_MAC_SHA); if (td_sha == NULL) { @@ -124,7 +126,16 @@ opaque concat[36]; _gnutls_hash( td_sha, session->security_parameters.server_random, TLS_RANDOM_SIZE); _gnutls_hash( td_sha, params->data, params->size); - _gnutls_hash_deinit(td_sha, &concat[16]); + if (ver == GNUTLS_SSL3) { + ret = _gnutls_generate_master( session, 1); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + _gnutls_mac_deinit_ssl3_handshake( td_sha, &concat[16], session->security_parameters.master_secret, TLS_MASTER_SIZE); + } else + _gnutls_hash_deinit(td_sha, &concat[16]); switch (cert->subject_pk_algorithm) { case GNUTLS_PK_RSA: @@ -333,9 +344,9 @@ gnutls_protocol_version ver = gnutls_protocol_get_version( session); } return ret; - } + /* Generates a signature of all the random data and the parameters. * Used in DHE_* ciphersuites. */ diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c index d63893d55b..a16172bbd1 100644 --- a/lib/gnutls_state.c +++ b/lib/gnutls_state.c @@ -40,13 +40,15 @@ #include <auth_cert.h> #include <auth_anon.h> #include <gnutls_algorithms.h> +#include <gnutls_rsa_export.h> #define CHECK_AUTH(auth, ret) if (gnutls_auth_get_type(session) != auth) { \ gnutls_assert(); \ return ret; \ } -void _gnutls_session_cert_type_set( gnutls_session session, gnutls_certificate_type ct) { +void _gnutls_session_cert_type_set( gnutls_session session, gnutls_certificate_type ct) +{ session->security_parameters.cert_type = ct; } @@ -68,7 +70,8 @@ gnutls_cipher_algorithm gnutls_cipher_get( gnutls_session session) { * is by default X.509, unless it is negotiated as a TLS extension. * **/ -gnutls_certificate_type gnutls_certificate_type_get( gnutls_session session) { +gnutls_certificate_type gnutls_certificate_type_get( gnutls_session session) +{ return session->security_parameters.cert_type; } @@ -78,7 +81,8 @@ gnutls_certificate_type gnutls_certificate_type_get( gnutls_session session) { * * Returns the key exchange algorithm used in the last handshake. **/ -gnutls_kx_algorithm gnutls_kx_get( gnutls_session session) { +gnutls_kx_algorithm gnutls_kx_get( gnutls_session session) +{ return session->security_parameters.kx_algorithm; } @@ -88,7 +92,8 @@ gnutls_kx_algorithm gnutls_kx_get( gnutls_session session) { * * Returns the currently used mac algorithm. **/ -gnutls_mac_algorithm gnutls_mac_get( gnutls_session session) { +gnutls_mac_algorithm gnutls_mac_get( gnutls_session session) +{ return session->security_parameters.read_mac_algorithm; } @@ -98,11 +103,14 @@ gnutls_mac_algorithm gnutls_mac_get( gnutls_session session) { * * Returns the currently used compression method. **/ -gnutls_compression_method gnutls_compression_get( gnutls_session session) { +gnutls_compression_method gnutls_compression_get( gnutls_session session) +{ return session->security_parameters.read_compression_algorithm; } -int _gnutls_session_cert_type_supported( gnutls_session session, gnutls_certificate_type cert_type) { +int _gnutls_session_cert_type_supported( gnutls_session session, + gnutls_certificate_type cert_type) +{ uint i; if (session->internals.cert_type_priority.algorithms==0 && cert_type == @@ -118,11 +126,30 @@ uint i; return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE; } +/* this function deinitializes all the internal parameters stored + * in a session struct. + */ +inline +static void deinit_internal_params( gnutls_session session) +{ + if (session->internals.params.free_anon_dh_params) + gnutls_dh_params_deinit( session->internals.params.anon_dh_params); + + if (session->internals.params.free_cert_dh_params) + gnutls_dh_params_deinit( session->internals.params.cert_dh_params); + + if (session->internals.params.rsa_params) + gnutls_rsa_params_deinit( session->internals.params.rsa_params); + + memset( &session->internals.params, 0, sizeof( session->internals.params)); +} + /* This function will clear all the variables in internals * structure within the session, which depend on the current handshake. * This is used to allow further handshakes. */ -void _gnutls_handshake_internal_state_clear( gnutls_session session) { +void _gnutls_handshake_internal_state_clear( gnutls_session session) +{ session->internals.extensions_sent_size = 0; /* by default no selected certificate */ @@ -145,6 +172,8 @@ void _gnutls_handshake_internal_state_clear( gnutls_session session) { session->internals.handshake_restarted = 0; session->internals.resumable = RESUME_TRUE; + + deinit_internal_params( session); } @@ -262,6 +291,7 @@ void _gnutls_deinit(gnutls_session session) /* remove auth info firstly */ _gnutls_free_auth_info(session ); + _gnutls_handshake_internal_state_clear( session); _gnutls_handshake_io_buffer_clear( session); _gnutls_free_datum(&session->connection_state.read_mac_secret); @@ -348,11 +378,13 @@ void gnutls_deinit(gnutls_session session) } -int _gnutls_dh_get_prime_bits( gnutls_session session) { +int _gnutls_dh_get_prime_bits( gnutls_session session) +{ return session->internals.dh_prime_bits; } -int _gnutls_dh_set_peer_public_bits( gnutls_session session, uint bits) { +int _gnutls_dh_set_peer_public_bits( gnutls_session session, uint bits) +{ switch( gnutls_auth_get_type( session)) { case GNUTLS_CRD_ANON: { ANON_SERVER_AUTH_INFO info; @@ -380,7 +412,8 @@ int _gnutls_dh_set_peer_public_bits( gnutls_session session, uint bits) { return 0; } -int _gnutls_dh_set_secret_bits( gnutls_session session, uint bits) { +int _gnutls_dh_set_secret_bits( gnutls_session session, uint bits) +{ switch( gnutls_auth_get_type( session)) { case GNUTLS_CRD_ANON: { ANON_SERVER_AUTH_INFO info; @@ -408,7 +441,8 @@ int _gnutls_dh_set_secret_bits( gnutls_session session, uint bits) { return 0; } -int _gnutls_rsa_export_set_modulus_bits( gnutls_session session, uint bits) { +int _gnutls_rsa_export_set_modulus_bits( gnutls_session session, uint bits) +{ CERTIFICATE_AUTH_INFO info; info = _gnutls_get_auth_info(session); @@ -462,7 +496,8 @@ int _gnutls_dh_set_prime_bits( gnutls_session session, uint bits) * server can obtain the client's key. * **/ -void gnutls_openpgp_send_key(gnutls_session session, gnutls_openpgp_key_status status) { +void gnutls_openpgp_send_key(gnutls_session session, gnutls_openpgp_key_status status) +{ session->internals.pgp_fingerprint = status; } @@ -480,11 +515,13 @@ void gnutls_openpgp_send_key(gnutls_session session, gnutls_openpgp_key_status s * certificate with X.509 certificates. * **/ -void gnutls_certificate_send_x509_rdn_sequence(gnutls_session session, int status) { +void gnutls_certificate_send_x509_rdn_sequence(gnutls_session session, int status) +{ session->internals.ignore_rdn_sequence = status; } -int _gnutls_openpgp_send_fingerprint(gnutls_session session) { +int _gnutls_openpgp_send_fingerprint(gnutls_session session) +{ return session->internals.pgp_fingerprint; } diff --git a/lib/gnutls_ui.c b/lib/gnutls_ui.c index f29eab87d8..1752c5c826 100644 --- a/lib/gnutls_ui.c +++ b/lib/gnutls_ui.c @@ -319,7 +319,8 @@ int gnutls_fingerprint(gnutls_digest_algorithm algo, const gnutls_datum* data, * cipher suites. * **/ -void gnutls_anon_set_server_dh_params( gnutls_anon_server_credentials res, gnutls_dh_params dh_params) { +void gnutls_anon_set_server_dh_params( gnutls_anon_server_credentials res, gnutls_dh_params dh_params) +{ res->dh_params = dh_params; } @@ -333,11 +334,45 @@ void gnutls_anon_set_server_dh_params( gnutls_anon_server_credentials res, gnutl * cipher suites. * **/ -void gnutls_certificate_set_dh_params(gnutls_certificate_credentials res, gnutls_dh_params dh_params) { +void gnutls_certificate_set_dh_params(gnutls_certificate_credentials res, gnutls_dh_params dh_params) +{ res->dh_params = dh_params; } /** + * gnutls_certificate_set_params_function - This function will set the DH or RSA parameters callback + * @res: is a gnutls_certificate_credentials structure + * @func: is the function to be called + * + * This function will set a callback in order for the server to get the + * diffie hellman or RSA parameters for certificate authentication. The callback + * should return zero on success. + * + **/ +void gnutls_certificate_set_params_function(gnutls_certificate_credentials res, + gnutls_params_function* func) +{ + res->params_func = func; +} + +/** + * gnutls_anon_set_params_function - This function will set the DH parameters callback + * @res: is a gnutls_certificate_credentials structure + * @func: is the function to be called + * + * This function will set a callback in order for the server to get the + * diffie hellman parameters for anonymous authentication. The callback should + * return zero on success. + * + **/ +void gnutls_anon_set_params_function(gnutls_anon_server_credentials res, + gnutls_params_function* func) +{ + res->params_func = func; +} + + +/** * gnutls_certificate_set_verify_flags - This function will set the flags to be used at certificate verification * @res: is a gnutls_certificate_credentials structure * @flags: are the flagsis a structure that holds diffie hellman parameters. diff --git a/lib/gnutls_ui.h b/lib/gnutls_ui.h index 8b7e0bd052..26a33345e4 100644 --- a/lib/gnutls_ui.h +++ b/lib/gnutls_ui.h @@ -131,6 +131,24 @@ int gnutls_pem_base64_decode_alloc(const char *header, #define GNUTLS_KEY_ENCIPHER_ONLY 1 #define GNUTLS_KEY_DECIPHER_ONLY 32768 +typedef struct gnutls_params_st { + gnutls_params_type type; + union params { + gnutls_dh_params dh; + gnutls_rsa_params rsa_export; + } params; + int deinit; +} gnutls_params_st; + +typedef int gnutls_params_function(gnutls_session, gnutls_params_type, + gnutls_params_st*); + +void gnutls_certificate_set_params_function(gnutls_certificate_credentials res, + gnutls_params_function* func); +void gnutls_anon_set_params_function(gnutls_certificate_credentials res, + gnutls_params_function* func); + + # endif /* LIBGNUTLS_VERSION */ diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c index 4798e221dd..70fe0ddc64 100644 --- a/lib/x509/privkey.c +++ b/lib/x509/privkey.c @@ -82,6 +82,51 @@ int i; gnutls_free(key); } +/** + * gnutls_x509_privkey_cpy - This function copies a private key + * @dst: The destination key, which should be initialized. + * @src: The source key + * + * This function will copy a private key from source to destination key. + * + **/ +int gnutls_x509_privkey_cpy(gnutls_x509_privkey dst, gnutls_x509_privkey src) +{ +int i, ret; + + if (!src || !dst) return GNUTLS_E_INVALID_REQUEST; + + for (i = 0; i < src->params_size; i++) { + dst->params[i] = _gnutls_mpi_copy( src->params[i]); + if (dst->params[i] == NULL) return GNUTLS_E_MEMORY_ERROR; + } + + dst->params_size = src->params_size; + dst->pk_algorithm = src->pk_algorithm; + + switch( dst->pk_algorithm) { + case GNUTLS_PK_DSA: + ret = _encode_dsa( &dst->key, dst->params); + if (ret < 0) { + gnutls_assert(); + return ret; + } + break; + case GNUTLS_PK_RSA: + ret = _encode_rsa( &dst->key, dst->params); + if (ret < 0) { + gnutls_assert(); + return ret; + } + break; + default: + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + return 0; +} + /* Converts an RSA PKCS#1 key to * an internal structure (gnutls_private_key) */ diff --git a/lib/x509/privkey.h b/lib/x509/privkey.h index 56dfd26190..b667326047 100644 --- a/lib/x509/privkey.h +++ b/lib/x509/privkey.h @@ -12,3 +12,4 @@ int gnutls_x509_privkey_import(gnutls_x509_privkey key, const gnutls_datum * dat gnutls_x509_crt_fmt format); ASN1_TYPE _gnutls_privkey_decode_pkcs1_rsa_key( const gnutls_datum *raw_key, gnutls_x509_privkey pkey); +int gnutls_x509_privkey_cpy(gnutls_x509_privkey dst, gnutls_x509_privkey src); diff --git a/libextra/openpgp/openpgp.c b/libextra/openpgp/openpgp.c index 5ebdab7625..3aac1bd6cf 100644 --- a/libextra/openpgp/openpgp.c +++ b/libextra/openpgp/openpgp.c @@ -449,7 +449,7 @@ gnutls_openpgp_key_get_id( gnutls_openpgp_key key, { cdk_packet_t pkt; cdk_pkt_pubkey_t pk = NULL; - unsigned long kid[2]; + unsigned int kid[2]; if( !key || !keyid ) { gnutls_assert( ); diff --git a/libextra/openpgp/xml.c b/libextra/openpgp/xml.c index d95e10e85a..251bd25b6d 100644 --- a/libextra/openpgp/xml.c +++ b/libextra/openpgp/xml.c @@ -140,7 +140,7 @@ xml_add_key( gnutls_string *xmlkey, int ext, cdk_pkt_pubkey_t pk, int sub ) const char *algo, *s; char keyid[16], fpr[41], tmp[32]; uint8 fingerpr[20]; - unsigned long kid[2]; + unsigned int kid[2]; int i = 0, rc = 0; if( !xmlkey || !pk ) { @@ -254,7 +254,7 @@ xml_add_sig( gnutls_string *xmlkey, int ext, cdk_pkt_signature_t sig ) { const char *algo, *s; char tmp[32], keyid[16]; - unsigned long kid[2]; + unsigned int kid[2]; int rc = 0; if( !xmlkey || !sig ) { diff --git a/libgcrypt.m4 b/libgcrypt.m4 index 0e8ab5803d..e5f2a43c06 100644 --- a/libgcrypt.m4 +++ b/libgcrypt.m4 @@ -1,5 +1,5 @@ dnl Autoconf macros for libgcrypt -dnl Copyright (C) 2002 Free Software Foundation, Inc. +dnl Copyright (C) 2002, 2004 Free Software Foundation, Inc. dnl dnl This file is free software; as a special exception the author gives dnl unlimited permission to copy and/or distribute it, with or without @@ -12,7 +12,13 @@ dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION, dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) -dnl Test for liblibgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS +dnl Test for libgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS. +dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed +dnl with the API version to also check the API compatibility. Example: +dnl a MINIMUN-VERSION of 1:1.2.5 won't pass the test unless the installed +dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1. Using +dnl this features allows to prevent build against newer versions of libgcrypt +dnl with a changed API. dnl AC_DEFUN(AM_PATH_LIBGCRYPT, [ AC_ARG_WITH(libgcrypt-prefix, @@ -26,7 +32,15 @@ AC_DEFUN(AM_PATH_LIBGCRYPT, fi AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config, no) - min_libgcrypt_version=ifelse([$1], ,0.4.4,$1) + tmp=ifelse([$1], ,1:1.2.0,$1) + if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then + req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` + min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` + else + req_libgcrypt_api=0 + min_libgcrypt_version="$tmp" + fi + AC_MSG_CHECKING(for LIBGCRYPT - version >= $min_libgcrypt_version) ok=no if test "$LIBGCRYPT_CONFIG" != "no" ; then @@ -36,7 +50,7 @@ AC_DEFUN(AM_PATH_LIBGCRYPT, sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` req_micro=`echo $min_libgcrypt_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` - libgcrypt_config_version=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --version` + libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version` major=`echo $libgcrypt_config_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` minor=`echo $libgcrypt_config_version | \ @@ -60,14 +74,33 @@ AC_DEFUN(AM_PATH_LIBGCRYPT, fi fi if test $ok = yes; then - LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --cflags` - LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG $libgcrypt_config_args --libs` AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + if test $ok = yes; then + # If we have a recent libgcrypt, we should also check that the + # API is compatible + if test "$req_libgcrypt_api" -gt 0 ; then + tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0` + if test "$tmp" -gt 0 ; then + AC_MSG_CHECKING([LIBGCRYPT API version]) + if test "$req_libgcrypt_api" -eq "$tmp" ; then + AC_MSG_RESULT(okay) + else + ok=no + AC_MSG_RESULT([does not match (want=$req_libgcrypt_api got=$tmp)]) + fi + fi + fi + fi + if test $ok = yes; then + LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags` + LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs` ifelse([$2], , :, [$2]) else LIBGCRYPT_CFLAGS="" LIBGCRYPT_LIBS="" - AC_MSG_RESULT(no) ifelse([$3], , :, [$3]) fi AC_SUBST(LIBGCRYPT_CFLAGS) diff --git a/src/Makefile.am b/src/Makefile.am index 4fc8d385be..78ecd3862c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,7 @@ EXTRA_DIST = common.h crypt.gaa crypt-gaa.h README.srpcrypt \ README cli.gaa cli-gaa.h serv-gaa.h serv.gaa tls_test.gaa \ tls_test-gaa.h tests.h gnutls-http-serv list.h certtool-gaa.h \ - certtool.gaa + certtool.gaa getpass.h SUBDIRS = srp x509 openpgp @@ -10,7 +10,7 @@ INCLUDES = -I../lib -I../libtasn1/lib -I../includes $(LIBOPENCDK_CFLAGS) bin_PROGRAMS = gnutls-serv gnutls-cli gnutls-srpcrypt gnutls-cli-debug certtool gnutls_serv_SOURCES = serv-gaa.c serv.c common.c gnutls_serv_LDADD = ../lib/libgnutls.la ../libextra/libgnutls-extra.la $(LIBGCRYPT_LIBS) $(LIBOPENCDK_LIBS) $(SERV_LIBS) -gnutls_srpcrypt_SOURCES = crypt-gaa.c crypt.c +gnutls_srpcrypt_SOURCES = crypt-gaa.c crypt.c getpass.c gnutls_srpcrypt_LDADD = ../lib/libgnutls.la ../libextra/libgnutls-extra.la $(LIBGCRYPT_LIBS) $(LIBOPENCDK_LIBS) gnutls_cli_SOURCES = cli-gaa.c cli.c common.c gnutls_cli_LDADD = ../lib/libgnutls.la ../libextra/libgnutls-extra.la $(LIBGCRYPT_LIBS) $(LIBOPENCDK_LIBS) $(SERV_LIBS) @@ -22,7 +22,7 @@ noinst_PROGRAMS = retcodes retcodes_SOURCES = retcodes.c retcodes_LDADD = ../lib/libgnutls.la $(LIBGCRYPT_LIBS) -certtool_SOURCES = certtool-gaa.c certtool.c prime.c +certtool_SOURCES = certtool-gaa.c certtool.c prime.c getpass.c certtool_LDADD = ../lib/libgnutls.la $(LIBGCRYPT_LIBS) diff --git a/src/certtool.c b/src/certtool.c index 6546765cb0..ec677f838c 100644 --- a/src/certtool.c +++ b/src/certtool.c @@ -32,6 +32,7 @@ #include "certtool-gaa.h" #include <gnutls/pkcs12.h> #include <unistd.h> +#include <getpass.h> static void print_crl_info( gnutls_x509_crl crl, FILE* out, int all); int generate_prime(int bits); @@ -138,33 +139,6 @@ int len; return input; } -static const char* read_pass( const char* input_str) -{ -#ifndef HAVE_GETPASS -static char input[128]; -#endif -const char* pass; - - if (info.pass) return info.pass; - -#ifndef HAVE_GETPASS - - fputs( input_str, stderr); - fgets( input, sizeof(input), stdin); - - input[strlen(input)-1] = 0; - - if (strlen(input)==0 || input[0]=='\n') return NULL; - - return input; -#else - pass = getpass(input_str); - if (pass == NULL || strlen(pass)==0 || pass[0]=='\n') return NULL; - - return pass; -#endif -} - static int read_yesno( const char* input_str) { char input[128]; @@ -742,14 +716,14 @@ int ret; if (info.outcert_format) out_cert_format = GNUTLS_X509_FMT_DER; else out_cert_format = GNUTLS_X509_FMT_PEM; + gnutls_global_set_log_function( tls_log_func); + gnutls_global_set_log_level(info.debug); + if ((ret=gnutls_global_init()) < 0) { fprintf(stderr, "global_init: %s\n", gnutls_strerror(ret)); exit(1); } - gnutls_global_set_log_function( tls_log_func); - gnutls_global_set_log_level(info.debug); - switch( info.action) { case 0: generate_self_signed(); diff --git a/src/crypt.c b/src/crypt.c index 893804f338..5fc86ef0aa 100644 --- a/src/crypt.c +++ b/src/crypt.c @@ -39,6 +39,7 @@ int main (int argc, char **argv) #include <gnutls/extra.h> #include <gcrypt.h> /* for randomize */ #include <crypt-gaa.h> +#include <getpass.h> #include <sys/types.h> #include <sys/stat.h> @@ -50,35 +51,16 @@ int main (int argc, char **argv) # include <windows.h> #endif -#ifdef _WIN32 - -# define getpass read_str - -static const char* read_str( const char* input_str) -{ -static char input[128]; - - fputs( input_str, stderr); - fgets( input, sizeof(input), stdin); - - input[strlen(input)-1] = 0; - - if (strlen(input)==0) return NULL; - - return input; -} -#endif - #define _MAX(x,y) (x>y?x:y) /* This may need some rewrite. A lot of stuff which should be here * are in the library, which is not good. */ -int crypt_int(char *username, char *passwd, int salt, +int crypt_int(const char *username, const char *passwd, int salt, char *tpasswd_conf, char *tpasswd, int uindex); static int read_conf_values(gnutls_datum * g, gnutls_datum * n, char *str); -static int _verify_passwd_int(char* username, char* passwd, char* verifier, char* salt, +static int _verify_passwd_int(const char* username, const char* passwd, char* verifier, char* salt, const gnutls_datum* g, const gnutls_datum* n); @@ -158,7 +140,7 @@ int generate_create_conf(char *tpasswd_conf) * * index is the index of the prime-generator pair in tpasswd.conf */ -static int _verify_passwd_int(char* username, char* passwd, char* verifier, +static int _verify_passwd_int(const char* username, const char* passwd, char* verifier, char* salt, const gnutls_datum* g, const gnutls_datum* n) { char _salt[1024]; @@ -278,7 +260,7 @@ unsigned int i; /* Parses the tpasswd files, in order to verify the given * username/password pair. */ -int verify_passwd(char *conffile, char *tpasswd, char *username, char *passwd) +int verify_passwd(char *conffile, char *tpasswd, char *username, const char *passwd) { FILE *fd; char line[5 * 1024]; @@ -368,7 +350,7 @@ int verify_passwd(char *conffile, char *tpasswd, char *username, char *passwd) int main(int argc, char **argv) { gaainfo info; - char *passwd; + const char *passwd; int salt, ret; struct passwd *pwd; @@ -417,7 +399,7 @@ int main(int argc, char **argv) salt = 16; - passwd = getpass("Enter password: "); + passwd = read_pass("Enter password: "); /* not ready yet */ if (info.verify != 0) { @@ -431,7 +413,7 @@ int main(int argc, char **argv) } -char* _srp_crypt( char* username, char* passwd, int salt_size, +char* _srp_crypt( const char* username, const char* passwd, int salt_size, const gnutls_datum* g, const gnutls_datum* n) { char salt[128]; @@ -481,7 +463,7 @@ gnutls_datum verifier, txt_verifier; } -int crypt_int(char *username, char *passwd, int salt_size, +int crypt_int(const char *username, const char *passwd, int salt_size, char *tpasswd_conf, char *tpasswd, int uindex) { FILE *fd; diff --git a/src/getpass.c b/src/getpass.c new file mode 100644 index 0000000000..6ce6dde4e4 --- /dev/null +++ b/src/getpass.c @@ -0,0 +1,52 @@ +#include <config.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#ifndef _WIN32 +# include <termios.h> +# include <unistd.h> +#endif + +#define OUT_STREAM stdout + +const char *read_pass(char *msg) +{ +#ifndef _WIN32 + struct termios old, new; +#endif + static char input[128]; + char *p; + + fputs(msg, stderr); + +#ifndef _WIN32 + /* Turn echoing off and fail if we can't. */ + if (tcgetattr(fileno(OUT_STREAM), &old) != 0) { + perror("tcgetattr"); + exit(1); + } + + new = old; + new.c_lflag &= ~ECHO; + if (tcsetattr(fileno(OUT_STREAM), TCSAFLUSH, &new) != 0) { + perror("tcsetattr"); + exit(1); + } +#endif + + /* Read the password. */ + p = fgets(input, sizeof(input), stdin); + +#ifndef _WIN32 + /* Restore terminal. */ + (void) tcsetattr(fileno(OUT_STREAM), TCSAFLUSH, &old); +#endif + + if (p == NULL || strlen(p) == 0 || p[0] == '\n') + return NULL; + + /* overwrite the newline */ + input[strlen(p) - 1] = 0; + + return p; +} diff --git a/src/getpass.h b/src/getpass.h new file mode 100644 index 0000000000..3562b688c1 --- /dev/null +++ b/src/getpass.h @@ -0,0 +1 @@ +const char* read_pass (char *msg); diff --git a/src/serv.c b/src/serv.c index 8128731074..6cfbd6ca02 100644 --- a/src/serv.c +++ b/src/serv.c @@ -156,8 +156,8 @@ static void listener_free(listener_item * j) * otherwise we should add them here. */ -gnutls_dh_params dh_params; -gnutls_rsa_params rsa_params; +gnutls_dh_params dh_params = NULL; +gnutls_rsa_params rsa_params = NULL; static int generate_dh_primes(void) { @@ -225,6 +225,22 @@ static void read_dh_params(void) } +static int get_params( gnutls_session session, gnutls_params_type type, + gnutls_params_st *st) +{ + + if (type == GNUTLS_PARAMS_RSA_EXPORT) + st->params.rsa_export = rsa_params; + else if (type == GNUTLS_PARAMS_DH) + st->params.dh = dh_params; + else return -1; + + st->type = type; + st->deinit = 0; + + return 0; +} + static int generate_rsa_params(void) { if (gnutls_rsa_params_init(&rsa_params) < 0) { @@ -666,8 +682,10 @@ int main(int argc, char **argv) } if (generate != 0 || read_dh_params != NULL) { - gnutls_certificate_set_dh_params(cert_cred, dh_params); - gnutls_certificate_set_rsa_export_params(cert_cred, rsa_params); + gnutls_certificate_set_params_function( cert_cred, get_params); +/* gnutls_certificate_set_dh_params(cert_cred, dh_params); + * gnutls_certificate_set_rsa_export_params(cert_cred, rsa_params); + */ } /* this is a password file (created with the included srpcrypt utility) @@ -691,7 +709,9 @@ int main(int argc, char **argv) #ifdef ENABLE_ANON gnutls_anon_allocate_server_credentials(&dh_cred); if (generate != 0) - gnutls_anon_set_server_dh_params(dh_cred, dh_params); + gnutls_anon_set_params_function( dh_cred, get_params); + +/* gnutls_anon_set_server_dh_params(dh_cred, dh_params); */ #endif h = listen_socket(name, port); |