diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2001-06-16 12:11:33 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2001-06-16 12:11:33 +0000 |
commit | 549279f8d2f32acd54699cccbf1e3ace9e0da515 (patch) | |
tree | b3561339427890dc10c7f761a5e6fc494c235a06 | |
parent | 780c45c9fcc8719cb13f6ff5abcc73b7725de5df (diff) | |
download | gnutls-549279f8d2f32acd54699cccbf1e3ace9e0da515.tar.gz |
more rsa fixes.
Added dnsname extension.
-rw-r--r-- | lib/Makefile.am | 6 | ||||
-rw-r--r-- | lib/auth_anon.c | 57 | ||||
-rw-r--r-- | lib/auth_dhe_dss.c | 18 | ||||
-rw-r--r-- | lib/auth_rsa.c | 94 | ||||
-rw-r--r-- | lib/auth_srp.c | 17 | ||||
-rw-r--r-- | lib/auth_x509.h | 30 | ||||
-rw-r--r-- | lib/defines.h | 4 | ||||
-rw-r--r-- | lib/ext_dnsname.c | 77 | ||||
-rw-r--r-- | lib/ext_dnsname.h | 2 | ||||
-rw-r--r-- | lib/gnutls.c | 2 | ||||
-rw-r--r-- | lib/gnutls.h.in | 18 | ||||
-rw-r--r-- | lib/gnutls_auth_int.h | 2 | ||||
-rw-r--r-- | lib/gnutls_dh.c | 17 | ||||
-rw-r--r-- | lib/gnutls_extensions.c | 2 | ||||
-rw-r--r-- | lib/gnutls_handshake.c | 55 | ||||
-rw-r--r-- | lib/gnutls_int.h | 31 | ||||
-rw-r--r-- | lib/gnutls_kx.c | 46 | ||||
-rw-r--r-- | lib/gnutls_kx.h | 1 | ||||
-rw-r--r-- | lib/gnutls_srp.c | 25 |
19 files changed, 343 insertions, 161 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 1e81f3857a..ae4a52eeb3 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -13,7 +13,8 @@ EXTRA_DIST = debug.h gnutls_compress.h defines.h gnutls_plaintext.h \ gnutls_auth_int.h crypt_bcrypt.h gnutls_random.h crypt_srpsha1.h \ cert_b64.h gnutls_srp.h auth_srp.h auth_srp_passwd.h gnutls_v2_compat.h \ crypt.h libgnutls-config.in libgnutls.m4 gnutls.h.in gnutls_errors_int.h \ - cert_asn1.h cert_der.h gnutls_datum.h auth_x509.c + cert_asn1.h cert_der.h gnutls_datum.h auth_x509.h gnutls_gcry.h \ + ext_dnsname.h lib_LTLIBRARIES = libgnutls.la libgnutls_la_SOURCES = gnutls.c gnutls_compress.c debug.c gnutls_plaintext.c \ gnutls_cipher.c gnutls_buffers.c gnutls_handshake.c gnutls_num.c \ @@ -23,6 +24,7 @@ libgnutls_la_SOURCES = gnutls.c gnutls_compress.c debug.c gnutls_plaintext.c \ auth_anon.c auth_dhe_dss.c gnutls_extensions.c ext_srp.c gnutls_auth.c \ crypt_bcrypt.c crypt.c gnutls_random.c crypt_srpsha1.c gnutls_srp.c \ auth_srp.c auth_srp_passwd.c gnutls_v2_compat.c auth_srp_sb64.c \ - cert_ASN.y cert_asn1.c cert_der.c gnutls_datum.c auth_rsa.c + cert_ASN.y cert_asn1.c cert_der.c gnutls_datum.c auth_rsa.c \ + gnutls_gcry.c ext_dnsname.c libgnutls_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) diff --git a/lib/auth_anon.c b/lib/auth_anon.c index 43dd30d7f8..1efd201d48 100644 --- a/lib/auth_anon.c +++ b/lib/auth_anon.c @@ -25,6 +25,7 @@ #include "gnutls_dh.h" #include "auth_anon.h" #include "gnutls_num.h" +#include "gnutls_gcry.h" #define DEFAULT_BITS 1024 @@ -50,6 +51,19 @@ MOD_AUTH_STRUCT anon_auth_struct = { NULL }; +/* this function will copy an MPI key to + * opaque data. + */ +int _gnutls_generate_key(GNUTLS_KEY key) { + gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &key->key.size, key->KEY); + key->key.data = secure_malloc( key->key.size); + if (key->key.data==NULL) { + return GNUTLS_E_MEMORY_ERROR; + } + gcry_mpi_print(GCRYMPI_FMT_USG, key->key.data, &key->key.size, key->KEY); + return 0; +} + int gen_anon_server_kx( GNUTLS_KEY key, opaque** data) { GNUTLS_MPI x, X, g, p; int bits; @@ -81,19 +95,19 @@ int gen_anon_server_kx( GNUTLS_KEY key, opaque** data) { (*data) = gnutls_malloc(n_g + n_p + n_X + 6); data_p = &(*data)[0]; gcry_mpi_print(GCRYMPI_FMT_USG, &data_p[2], &n_p, p); - gnutls_mpi_release(p); + _gnutls_mpi_release(&p); WRITEuint16( n_p, data_p); data_g = &data_p[2 + n_p]; gcry_mpi_print(GCRYMPI_FMT_USG, &data_g[2], &n_g, g); - gnutls_mpi_release(g); + _gnutls_mpi_release(&g); WRITEuint16( n_g, data_g); data_X = &data_g[2 + n_g]; gcry_mpi_print(GCRYMPI_FMT_USG, &data_X[2], &n_X, X); - gnutls_mpi_release(X); + _gnutls_mpi_release(&X); WRITEuint16( n_X, data_X); @@ -103,6 +117,7 @@ int gen_anon_server_kx( GNUTLS_KEY key, opaque** data) { int gen_anon_client_kx( GNUTLS_KEY key, opaque** data) { GNUTLS_MPI x, X; size_t n_X; +int ret; X = gnutls_calc_dh_secret(&x, key->client_g, key->client_p); @@ -113,7 +128,7 @@ size_t n_X; gcry_mpi_print(GCRYMPI_FMT_USG, &(*data)[2], &n_X, X); (*data)[0] = 1; /* extern - explicit since we do not have certificate */ - gnutls_mpi_release(X); + _gnutls_mpi_release(&X); WRITEuint16( n_X, &(*data)[0]); @@ -121,13 +136,16 @@ size_t n_X; key->KEY = gnutls_calc_dh_key(key->client_Y, x, key->client_p); /* THESE SHOULD BE DISCARDED */ - gnutls_mpi_release(key->client_Y); - gnutls_mpi_release(key->client_p); - gnutls_mpi_release(key->client_g); - key->client_Y = NULL; - key->client_p = NULL; - key->client_g = NULL; + _gnutls_mpi_release(&key->client_Y); + _gnutls_mpi_release(&key->client_p); + _gnutls_mpi_release(&key->client_g); + + ret = _gnutls_generate_key( key); + _gnutls_mpi_release(&key->KEY); + if (ret < 0) { + return ret; + } return n_X+2; } @@ -207,7 +225,7 @@ int proc_anon_client_kx( GNUTLS_KEY key, opaque* data, int data_size) { uint16 n_Y; size_t _n_Y; MPI g, p; - int bits; + int bits, ret; const ANON_SERVER_CREDENTIALS * cred; cred = _gnutls_get_cred( key, GNUTLS_ANON, NULL); @@ -238,12 +256,17 @@ int proc_anon_client_kx( GNUTLS_KEY key, opaque* data, int data_size) { g = gnutls_get_dh_params(&p, bits); key->KEY = gnutls_calc_dh_key( key->client_Y, key->dh_secret, p); - gnutls_mpi_release(key->client_Y); - gnutls_mpi_release(key->dh_secret); - gnutls_mpi_release(p); - gnutls_mpi_release(g); - key->client_Y = NULL; - key->dh_secret = NULL; + _gnutls_mpi_release(&key->client_Y); + _gnutls_mpi_release(&key->dh_secret); + _gnutls_mpi_release(&p); + _gnutls_mpi_release(&g); + + ret = _gnutls_generate_key( key); + _gnutls_mpi_release(&key->KEY); + + if (ret < 0) { + return ret; + } return 0; } diff --git a/lib/auth_dhe_dss.c b/lib/auth_dhe_dss.c index 24520ce9dc..dd008e3114 100644 --- a/lib/auth_dhe_dss.c +++ b/lib/auth_dhe_dss.c @@ -92,19 +92,19 @@ int gen_dhe_dss_server_kx( GNUTLS_KEY key, opaque** data) { (*data) = gnutls_malloc(n_g + n_p + n_X + 6); data_p = &(*data)[0]; gcry_mpi_print(GCRYMPI_FMT_USG, &data_p[2], &n_p, p); - gnutls_mpi_release(p); + _gnutls_mpi_release(p); WRITEuint16( n_p, data_p); data_g = &data_p[2 + n_p]; gcry_mpi_print(GCRYMPI_FMT_USG, &data_g[2], &n_g, g); - gnutls_mpi_release(g); + _gnutls_mpi_release(g); WRITEuint16( n_g, data_g); data_X = &data_g[2 + n_g]; gcry_mpi_print(GCRYMPI_FMT_USG, &data_X[2], &n_X, X); - gnutls_mpi_release(X); + _gnutls_mpi_release(X); WRITEuint16( n_X, data_X); @@ -126,7 +126,7 @@ size_t n_X; gcry_mpi_print(GCRYMPI_FMT_USG, &(*data)[2], &n_X, X); (*data)[0] = 1; /* extern - explicit since we do not have certificate */ - gnutls_mpi_release(X); + _gnutls_mpi_release(X); WRITEuint16( n_X, &(*data)[0]); @@ -134,9 +134,9 @@ size_t n_X; key->KEY = _gnutls_calc_dh_key(key->client_Y, x, key->client_p); /* THESE SHOULD BE DISCARDED */ - gnutls_mpi_release(key->client_Y); - gnutls_mpi_release(key->client_p); - gnutls_mpi_release(key->client_g); + _gnutls_mpi_release(key->client_Y); + _gnutls_mpi_release(key->client_p); + _gnutls_mpi_release(key->client_g); key->client_Y = NULL; key->client_p = NULL; key->client_g = NULL; @@ -248,8 +248,8 @@ int proc_dhe_dss_client_kx( GNUTLS_KEY key, opaque* data, int data_size) { mpi_release(g); mpi_release(p); - gnutls_mpi_release(key->client_Y); - gnutls_mpi_release(key->dh_secret); + _gnutls_mpi_release(key->client_Y); + _gnutls_mpi_release(key->dh_secret); key->client_Y = NULL; key->dh_secret = NULL; diff --git a/lib/auth_rsa.c b/lib/auth_rsa.c index 7d4c3aa3b5..9b72d9ceea 100644 --- a/lib/auth_rsa.c +++ b/lib/auth_rsa.c @@ -23,7 +23,6 @@ #include "gnutls_auth_int.h" #include "gnutls_errors.h" #include "gnutls_dh.h" -#include "auth_anon.h" #include "gnutls_num.h" #include "cert_asn1.h" #include "cert_der.h" @@ -106,7 +105,7 @@ int _gnutls_calc_rsa_signature( GNUTLS_KEY key, const opaque* data, int data_siz return ret; } - +#if 0 /* This function reads the RSA parameters from the given(?) certificate. */ static int _gnutls_get_rsa_params( GNUTLS_KEY key, RSA_Params * params, gnutls_datum cert) @@ -179,20 +178,20 @@ static int _gnutls_get_rsa_params( GNUTLS_KEY key, RSA_Params * params, gnutls_d gnutls_assert(); delete_structure("rsapublickey"); gnutls_free_datum(¶ms->rsa_modulus); - gcry_mpi_release(key->A); + _gnutls_mpi_release(&key->A); return GNUTLS_E_PARSING_ERROR; } if (gcry_mpi_scan(&key->B, GCRYMPI_FMT_USG, str, &len) != 0) { gnutls_assert(); - gcry_mpi_release(key->A); + _gnutls_mpi_release(&key->A); gnutls_free_datum(¶ms->rsa_modulus); delete_structure("rsapublickey"); return GNUTLS_E_MPI_SCAN_FAILED; } if (gnutls_set_datum(¶ms->rsa_exponent, str, len) < 0) { - gcry_mpi_release(key->A); + _gnutls_mpi_release(&key->A); gnutls_free_datum(¶ms->rsa_modulus); delete_structure("rsapublickey"); return GNUTLS_E_MEMORY_ERROR; @@ -206,6 +205,7 @@ static int _gnutls_get_rsa_params( GNUTLS_KEY key, RSA_Params * params, gnutls_d return ret; } +#endif /* This function reads the RSA parameters from the given private key * cert is not a certificate but a der structure containing the private @@ -246,7 +246,7 @@ static int _gnutls_get_private_rsa_params( GNUTLS_KEY key, gnutls_datum cert) if (result != ASN_OK) { gnutls_assert(); delete_structure("rsa_key"); - gcry_mpi_release(key->u); + _gnutls_mpi_release(&key->u); return GNUTLS_E_PARSING_ERROR; } @@ -254,7 +254,7 @@ static int _gnutls_get_private_rsa_params( GNUTLS_KEY key, gnutls_datum cert) GCRYMPI_FMT_USG, str, &len) != 0) { gnutls_assert(); delete_structure("rsa_key"); - gcry_mpi_release(key->u); + _gnutls_mpi_release(&key->u); return GNUTLS_E_MPI_SCAN_FAILED; } @@ -314,20 +314,33 @@ int gen_rsa_server_kx(GNUTLS_KEY key, opaque ** data) int gen_rsa_certificate(GNUTLS_KEY key, opaque ** data) { - RSA_Params params; const X509PKI_SERVER_CREDENTIALS *cred; int ret, i; opaque* pdata; - + gnutls_datum* apr_cert_list; + gnutls_datum apr_pkey; + int apr_cert_list_length; + cred = _gnutls_get_cred(key, GNUTLS_X509PKI, NULL); if (cred == NULL) { gnutls_assert(); return GNUTLS_E_INSUFICIENT_CRED; } + if (cred->ncerts==0) { + gnutls_assert(); + return GNUTLS_E_INSUFICIENT_CRED; + } + + /* FIXME: FIND APPROPRIATE CERTIFICATE - depending on hostname + */ + apr_cert_list = cred->cert_list[0]; + apr_cert_list_length = cred->cert_list_length[0]; + apr_pkey = cred->pkey[0]; + ret = 3; - for (i=0;i<cred->cert_list_size;i++) { - ret += cred->cert_list[i].size + 3; + for (i=0;i<apr_cert_list_length;i++) { + ret += apr_cert_list[i].size + 3; /* hold size * for uint24 */ } @@ -342,64 +355,35 @@ int gen_rsa_certificate(GNUTLS_KEY key, opaque ** data) WRITEuint24( ret-3, pdata); pdata+=3; - for (i=0;i<cred->cert_list_size;i++) { - WRITEdatum24( pdata, cred->cert_list[i]); - pdata += 3 + cred->cert_list[i].size; - } - - return ret; -} - - -int proc_anon_client_kx( GNUTLS_KEY key, opaque* data, int data_size) { - uint16 n_Y; - size_t _n_Y; - MPI g, p; - int bits; - const RSA_SERVER_CREDENTIALS * cred; - - cred = _gnutls_get_cred(key, GNUTLS_X509PKI, NULL); - if (cred == NULL) { - gnutls_assert(); - return GNUTLS_E_INSUFICIENT_CRED; + for (i=0;i<apr_cert_list_length;i++) { + WRITEdatum24( pdata, apr_cert_list[i]); + pdata += 3 + apr_cert_list[i].size; } + /* read the rsa parameters now, since later we will + * now know which certificate we used! + */ ret = - _gnutls_get_rsa_params(key, ¶ms, cred->cert_list[0]); + _gnutls_get_private_rsa_params(key, apr_pkey); if (ret < 0) { gnutls_assert(); return ret; } -#if 0 /* removed. I do not know why - maybe I didn't get the protocol, - * but openssl does not use that byte - */ - if (data[0] != 1) { - gnutls_assert(); - return GNUTLS_E_UNIMPLEMENTED_FEATURE; - } -#endif + return ret; +} + - n_Y = READuint16( &data[0]); +int proc_rsa_client_kx( GNUTLS_KEY key, opaque* data, int data_size) { + const X509PKI_SERVER_CREDENTIALS * cred; - _n_Y = n_Y; - if (gcry_mpi_scan(&key->client_Y, - GCRYMPI_FMT_USG, &data[2], &_n_Y)) { + cred = _gnutls_get_cred(key, GNUTLS_X509PKI, NULL); + if (cred == NULL) { gnutls_assert(); - return GNUTLS_E_MPI_SCAN_FAILED; + return GNUTLS_E_INSUFICIENT_CRED; } - g = gnutls_get_dh_params(&p, bits); - key->KEY = gnutls_calc_dh_key( key->client_Y, key->dh_secret, p); - - gnutls_mpi_release(key->client_Y); - gnutls_mpi_release(key->dh_secret); - gnutls_mpi_release(p); - gnutls_mpi_release(g); - key->client_Y = NULL; - key->dh_secret = NULL; - return 0; } diff --git a/lib/auth_srp.c b/lib/auth_srp.c index c8fd2cef6b..08d1d3b697 100644 --- a/lib/auth_srp.c +++ b/lib/auth_srp.c @@ -149,6 +149,7 @@ int gen_srp_server_kx(GNUTLS_KEY key, opaque ** data) /* send the second key exchange message */ int gen_srp_server_kx2(GNUTLS_KEY key, opaque ** data) { + int ret; size_t n_b; uint8 *data_b; @@ -179,6 +180,12 @@ int gen_srp_server_kx2(GNUTLS_KEY key, opaque ** data) mpi_release(key->u); mpi_release(B); + ret = _gnutls_generate_key( key); + _gnutls_mpi_release(&S); + + if (ret < 0) + return ret; + return n_b + 2; } @@ -330,7 +337,8 @@ int proc_srp_client_kx0(GNUTLS_KEY key, opaque * data, int data_size) int proc_srp_server_kx2(GNUTLS_KEY key, opaque * data, int data_size) { size_t _n_B; - + int ret; + _n_B = READuint16( &data[0]); if (gcry_mpi_scan(&B, GCRYMPI_FMT_USG, &data[2], &_n_B)) { @@ -349,6 +357,13 @@ int proc_srp_server_kx2(GNUTLS_KEY key, opaque * data, int data_size) mpi_release(V); mpi_release(key->u); mpi_release(B); + + ret = _gnutls_generate_key( key); + _gnutls_mpi_release(&S); + + if (ret < 0) + return ret; + return 0; } diff --git a/lib/auth_x509.h b/lib/auth_x509.h index a6f5550111..8cfd1aed89 100644 --- a/lib/auth_x509.h +++ b/lib/auth_x509.h @@ -1,12 +1,34 @@ /* this is not to be included by gnutls_anon.c */ extern MOD_AUTH_STRUCT x509pki_auth_struct; +/* This structure may be complex but, it's the only way to + * support a server that has multiple certificates + */ typedef struct { - gnutls_datum * cert_list; - int cert_list_size; - gnutls_datum pkey; /* private key */ + gnutls_datum ** cert_list; + /* contains a list of a list of certificates. + * eg: [0] certificate1, certificate11, certificate111 + * (if more than one, one certificate certifies the one before) + * [1] certificate2, certificate22, ... + */ + int * cert_list_length; + /* contains the number of the certificates in one + * row. + */ + int ncerts; /* contains the number of columns in cert_list. + */ + gnutls_datum * pkey; /* private keys. It contains ncerts private + * keys. pkey[i] corresponds to certificate in + * cert_list[i][0]. + */ } X509PKI_SERVER_CREDENTIALS; typedef struct { - int dh_bits; + opaque dnsname[256]; +} X509PKI_CLIENT_CREDENTIALS; + +typedef struct { + opaque dnsname[256]; /* the client may send us the + * hostname he thinks he connected to. + */ } X509PKI_AUTH_INFO; diff --git a/lib/defines.h b/lib/defines.h index 9a16d69774..cfbb8bbf4e 100644 --- a/lib/defines.h +++ b/lib/defines.h @@ -49,10 +49,6 @@ # include <gdbm.h> #endif -#ifdef USE_GCRYPT -# include <gcrypt.h> -#endif - #ifdef HAVE_SYS_STAT_H # include <sys/stat.h> #endif diff --git a/lib/ext_dnsname.c b/lib/ext_dnsname.c new file mode 100644 index 0000000000..4218877d59 --- /dev/null +++ b/lib/ext_dnsname.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2001 Nikos Mavroyanopoulos + * + * This file is part of GNUTLS. + * + * GNUTLS is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GNUTLS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <defines.h> +#include "gnutls_int.h" +#include "gnutls_auth_int.h" +#include "auth_x509.h" +#include "gnutls_errors.h" + +int _gnutls_dnsname_recv_params( GNUTLS_STATE state, const opaque* data, int data_size) { + uint8 len; + if (state->security_parameters.entity == GNUTLS_SERVER) { + if (data_size > 0) { + state->gnutls_key->auth_info = gnutls_calloc(1, sizeof(X509PKI_AUTH_INFO)); + if (state->gnutls_key->auth_info==NULL) return GNUTLS_E_MEMORY_ERROR; + + if (sizeof( ((X509PKI_AUTH_INFO*)state->gnutls_key->auth_info)->dnsname) > data_size) { + len = data[0]; + if (len > data_size) { + gnutls_assert(); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + memcpy( ((X509PKI_AUTH_INFO*)state->gnutls_key->auth_info)->dnsname, &data[1], len); + ((X509PKI_AUTH_INFO*)state->gnutls_key->auth_info)->dnsname[len]=0; /* null terminated */ + state->gnutls_key->auth_info_size = sizeof(X509PKI_AUTH_INFO); + } else { + state->gnutls_key->auth_info_size = 0; + gnutls_free(state->gnutls_key->auth_info); + state->gnutls_key->auth_info = NULL; + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + } + } + return 0; +} + +/* returns data_size or a negative number on failure + * data is allocated localy + */ +int _gnutls_dnsname_send_params( GNUTLS_STATE state, opaque** data) { + uint8 len; + /* this function sends the client extension data (dnsname) */ + if (state->security_parameters.entity == GNUTLS_CLIENT) { + const X509PKI_CLIENT_CREDENTIALS* cred = _gnutls_get_cred( state->gnutls_key, GNUTLS_X509PKI, NULL); + + (*data) = NULL; + + if (cred==NULL) return 0; + + if (cred->dnsname!=NULL) { /* send dnsname */ + len = strlen(cred->dnsname); + (*data) = gnutls_malloc(len+1); /* hold the size also */ + (*data)[0] = len; + memcpy( &(*data)[1], cred->dnsname, len); + return len + 1; + } + } + return 0; +} diff --git a/lib/ext_dnsname.h b/lib/ext_dnsname.h new file mode 100644 index 0000000000..89ae8bcfcc --- /dev/null +++ b/lib/ext_dnsname.h @@ -0,0 +1,2 @@ +int _gnutls_dnsname_recv_params( GNUTLS_STATE state, const opaque* data, int data_size); +int _gnutls_dnsname_send_params( GNUTLS_STATE state, opaque** data); diff --git a/lib/gnutls.c b/lib/gnutls.c index 07e6a69cad..71dd379ef3 100644 --- a/lib/gnutls.c +++ b/lib/gnutls.c @@ -50,6 +50,8 @@ GNUTLS_Version ver; void gnutls_set_current_version(GNUTLS_STATE state, GNUTLS_Version version) { state->connection_state.version = version; + state->gnutls_key->version.major = _gnutls_version_get_major(version); + state->gnutls_key->version.minor = _gnutls_version_get_minor(version); } int gnutls_is_secure_memory(const void* mem) { diff --git a/lib/gnutls.h.in b/lib/gnutls.h.in index 1e26a50282..90406998d1 100644 --- a/lib/gnutls.h.in +++ b/lib/gnutls.h.in @@ -142,9 +142,21 @@ typedef struct { } ANON_AUTH_INFO; typedef struct { - gnutls_datum * cert_list; - int cert_list_size; - gnutls_datum pkey; /* private key */ + gnutls_datum ** cert_list; + /* contains a list of a list of certificates. + * eg: [0] certificate1, certificate11, certificate111 + * (if more than one, one certificate certifies the one before) + * [1] certificate2, certificate22, ... + */ + int * cert_list_length; + /* contains the number of the certificates in one + * row. + */ + int ncerts; /* contains the number of columns in cert_list. + */ + gnutls_datum * pkey; /* private keys. It contains ncerts private + * keys. + */ } X509PKI_SERVER_CREDENTIALS; /* error codes appended here */ diff --git a/lib/gnutls_auth_int.h b/lib/gnutls_auth_int.h index 2b34b6160c..1deb4da09f 100644 --- a/lib/gnutls_auth_int.h +++ b/lib/gnutls_auth_int.h @@ -2,4 +2,4 @@ int gnutls_clear_creds( GNUTLS_STATE state); int gnutls_set_cred( GNUTLS_STATE state, CredType type, void* cred); const void *_gnutls_get_cred( GNUTLS_KEY key, CredType kx, int* err); const void *_gnutls_get_kx_cred( GNUTLS_KEY key, KXAlgorithm algo, int *err); - +int _gnutls_generate_key(GNUTLS_KEY key); diff --git a/lib/gnutls_dh.c b/lib/gnutls_dh.c index 3137de71c3..a66a1d4180 100644 --- a/lib/gnutls_dh.c +++ b/lib/gnutls_dh.c @@ -22,8 +22,7 @@ #include <defines.h> #include <gnutls_int.h> #include <gnutls_errors.h> - -/* Taken from gsti */ +#include <gnutls_gcry.h> #define DH_G_1024 2 #define DH_G_4096 5 @@ -235,8 +234,8 @@ const uint8 diffie_hellman_prime_2048[256] = { X = gnutls_calc_dh_secret(&x, g, p); // now we can calculate the shared secret key = gnutls_calc_dh_key(Y, x, g, p); - gnutls_mpi_release(x); - gnutls_mpi_release(g); + _gnutls_mpi_release(x); + _gnutls_mpi_release(g); */ @@ -266,7 +265,7 @@ MPI gnutls_calc_dh_secret(MPI * ret_x, MPI g, MPI prime) if (ret_x) *ret_x = x; else - gcry_mpi_release(x); + _gnutls_mpi_release(&x); return e; } @@ -299,7 +298,7 @@ MPI gnutls_get_dh_params(MPI * ret_p, int bits) if (ret_p) *ret_p = prime; else - gcry_mpi_release(prime); + _gnutls_mpi_release(&prime); return g; case 2048: n = sizeof diffie_hellman_prime_2048; @@ -315,7 +314,7 @@ MPI gnutls_get_dh_params(MPI * ret_p, int bits) if (ret_p) *ret_p = prime; else - gcry_mpi_release(prime); + _gnutls_mpi_release(&prime); return g; case 3072: n = sizeof diffie_hellman_prime_3072; @@ -331,7 +330,7 @@ MPI gnutls_get_dh_params(MPI * ret_p, int bits) if (ret_p) *ret_p = prime; else - gcry_mpi_release(prime); + _gnutls_mpi_release(&prime); return g; case 4096: n = sizeof diffie_hellman_prime_4096; @@ -347,7 +346,7 @@ MPI gnutls_get_dh_params(MPI * ret_p, int bits) if (ret_p) *ret_p = prime; else - gcry_mpi_release(prime); + _gnutls_mpi_release(&prime); return g; default: gnutls_assert(); diff --git a/lib/gnutls_extensions.c b/lib/gnutls_extensions.c index 026648afac..3f67464e65 100644 --- a/lib/gnutls_extensions.c +++ b/lib/gnutls_extensions.c @@ -23,6 +23,7 @@ #include "gnutls_extensions.h" #include "gnutls_errors.h" #include "ext_srp.h" +#include "ext_dnsname.h" #include "gnutls_num.h" /* Key Exchange Section */ @@ -39,6 +40,7 @@ typedef struct { #define MAX_EXT 20 /* maximum supported extension */ static gnutls_extension_entry extensions[] = { GNUTLS_EXTENSION_ENTRY(GNUTLS_EXTENSION_SRP, _gnutls_srp_recv_params, _gnutls_srp_send_params), + GNUTLS_EXTENSION_ENTRY(GNUTLS_EXTENSION_DNSNAME, _gnutls_dnsname_recv_params, _gnutls_dnsname_send_params), {0} }; diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index a05c6a9179..46cf3e663d 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -50,6 +50,15 @@ static int SelectSuite(GNUTLS_STATE state, opaque ret[2], char *data, int datalen); static int SelectCompMethod(GNUTLS_STATE state, CompressionMethod * ret, opaque * data, int datalen); +static void set_server_random( GNUTLS_STATE state, uint8* random) { + memcpy( state->security_parameters.server_random, random, 32); + memcpy( state->gnutls_key->server_random, random, 32); +} +static void set_client_random( GNUTLS_STATE state, uint8* random) { + memcpy( state->security_parameters.client_random, random, 32); + memcpy( state->gnutls_key->client_random, random, 32); +} + /* Calculate The SSL3 Finished message */ #define SSL3_CLIENT_MSG "CLNT" #define SSL3_SERVER_MSG "SRVR" @@ -144,6 +153,24 @@ void *_gnutls_finished(GNUTLS_STATE state, int type, int skip) return data; } +/* this function will produce 32 bytes of random data + * and put it to dst. + */ +static int create_random( opaque* dst) { +uint32 tim; +opaque* rand; + + tim = time(NULL); + /* generate server random value */ + WRITEuint32( tim, dst); + + rand = _gnutls_get_random(28, GNUTLS_STRONG_RANDOM); + memcpy( &dst[4], rand, 28); + + _gnutls_free_rand(rand); + + return 0; +} /* Read a client hello * client hello must be a known version client hello @@ -161,10 +188,10 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, int ret = 0; uint16 sizeOfSuites; GNUTLS_Version version; - char *rand; int len = datalen; int err; - + opaque random[32]; + if (state->gnutls_internals.v2_hello!=0) { /* version 2.0 */ return _gnutls_read_client_hello_v2(state, data, datalen); } @@ -189,15 +216,12 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, pos += 2; DECR_LEN(len, 32); - memcpy(state->security_parameters.client_random, &data[pos], 32); + set_client_random( state, &data[pos]); pos += 32; - /* generate server random value */ - WRITEuint32( time(NULL), state->security_parameters.server_random); + create_random( random); + set_server_random( state, random); - rand = _gnutls_get_random(28, GNUTLS_STRONG_RANDOM); - memcpy(&state->security_parameters.server_random[4], rand, 28); - _gnutls_free_rand(rand); state->security_parameters.timestamp = time(NULL); DECR_LEN(len, 1); @@ -761,8 +785,7 @@ static int _gnutls_read_server_hello( GNUTLS_STATE state, char *data, int datale pos += 2; DECR_LEN(len, 32); - memcpy(state->security_parameters.server_random, - &data[pos], 32); + set_server_random( state, &data[pos]); pos += 32; DECR_LEN(len, 1); @@ -902,7 +925,6 @@ static int _gnutls_read_server_hello( GNUTLS_STATE state, char *data, int datale int _gnutls_send_hello(int cd, GNUTLS_STATE state) { - char *rand; char *data = NULL; opaque *extdata; int extdatalen; @@ -912,6 +934,7 @@ int _gnutls_send_hello(int cd, GNUTLS_STATE state) uint8 *compression_methods; int i, datalen, ret = 0; uint16 x; + opaque random[32]; if (state->security_parameters.entity == GNUTLS_CLIENT) { opaque * SessionID = state->gnutls_internals.resumed_security_parameters.session_id; @@ -932,13 +955,9 @@ int _gnutls_send_hello(int cd, GNUTLS_STATE state) _gnutls_version_get_minor(state->connection_state. version); - WRITEuint32( time(NULL), state->security_parameters.client_random); - - rand = _gnutls_get_random(28, GNUTLS_STRONG_RANDOM); - memcpy(&state->security_parameters.client_random[4], rand, - 28); - _gnutls_free_rand(rand); - + create_random( random); + set_client_random( state, random); + state->security_parameters.timestamp = time(0); memcpy(&data[pos], diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 403cc1c208..8fac4a42e8 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -49,7 +49,11 @@ #define MAX_RECV_SIZE 18432+HEADER_SIZE /* 2^14+2048+HEADER_SIZE */ #ifdef USE_DMALLOC -#include <dmalloc.h> +# include <dmalloc.h> +#endif + +#ifdef USE_GCRYPT +# include <gnutls_gcry.h> #endif #define GNUTLS_MPI MPI @@ -106,7 +110,7 @@ typedef struct { /* STATE */ typedef enum ConnectionEnd { GNUTLS_SERVER, GNUTLS_CLIENT } ConnectionEnd; typedef enum BulkCipherAlgorithm { GNUTLS_NULL_CIPHER=1, GNUTLS_ARCFOUR, GNUTLS_3DES, GNUTLS_RIJNDAEL, GNUTLS_TWOFISH, GNUTLS_RIJNDAEL256 } BulkCipherAlgorithm; -typedef enum Extensions { GNUTLS_EXTENSION_SRP=7 } Extensions; +typedef enum Extensions { GNUTLS_EXTENSION_SRP=7, GNUTLS_EXTENSION_DNSNAME } Extensions; typedef enum KXAlgorithm { GNUTLS_KX_RSA=1, GNUTLS_KX_DHE_DSS, GNUTLS_KX_DHE_RSA, GNUTLS_KX_DH_DSS, GNUTLS_KX_DH_RSA, GNUTLS_KX_DH_ANON, GNUTLS_KX_SRP } KXAlgorithm; typedef enum CredType { GNUTLS_X509PKI=1, GNUTLS_ANON, GNUTLS_SRP } CredType; typedef enum CipherType { CIPHER_STREAM, CIPHER_BLOCK } CipherType; @@ -125,8 +129,15 @@ typedef struct { void* next; } AUTH_CRED; + +typedef struct { + uint8 major; + uint8 minor; +} ProtocolVersion; + typedef struct { /* For DH KX */ + gnutls_datum key; MPI KEY; MPI client_Y; MPI client_g; @@ -149,14 +160,15 @@ typedef struct { */ void* auth_info; int auth_info_size; /* needed in order to store to db for restoring */ - uint8 crypt_algo; - + /* These are needed in RSA and DH signature calculation */ opaque server_random[32]; opaque client_random[32]; - AUTH_CRED* cred; /* used in srp, etc */ + ProtocolVersion version; + + AUTH_CRED* cred; /* used to specify keys/certificates etc */ } GNUTLS_KEY_A; typedef GNUTLS_KEY_A* GNUTLS_KEY; @@ -278,11 +290,6 @@ typedef enum ContentType { GNUTLS_CHANGE_CIPHER_SPEC=20, GNUTLS_ALERT, GNUTLS_HA GNUTLS_APPLICATION_DATA } ContentType; typedef struct { - uint8 major; - uint8 minor; -} ProtocolVersion; - -typedef struct { uint8 type; ProtocolVersion version; uint16 length; @@ -321,8 +328,4 @@ int _gnutls_send_change_cipher_spec(int cd, GNUTLS_STATE state); int _gnutls_version_cmp(GNUTLS_Version ver1, GNUTLS_Version ver2); #define _gnutls_version_ssl3(x) _gnutls_version_cmp(x, GNUTLS_SSL3) -#ifndef gcry_mpi_alloc_like -# define gcry_mpi_alloc_like(x) gcry_mpi_new(gcry_mpi_get_nbits(x)) -#endif - #endif /* GNUTLS_INT_H */ diff --git a/lib/gnutls_kx.c b/lib/gnutls_kx.c index 9d6d0a26dd..fa5b7e1708 100644 --- a/lib/gnutls_kx.c +++ b/lib/gnutls_kx.c @@ -26,6 +26,7 @@ #include "gnutls_errors.h" #include "gnutls_algorithms.h" #include "debug.h" +#include "gnutls_gcry.h" #define MASTER_SECRET "master secret" @@ -43,13 +44,8 @@ char random[64]; memmove(&random[32], state->security_parameters.server_random, 32); /* generate premaster */ - gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &premaster_size, state->gnutls_key->KEY); - premaster = secure_malloc(premaster_size); - gcry_mpi_print(GCRYMPI_FMT_USG, premaster, &premaster_size, state->gnutls_key->KEY); - - /* THIS SHOULD BE DISCARDED */ - gnutls_mpi_release(state->gnutls_key->KEY); - state->gnutls_key->KEY = NULL; + premaster_size = state->gnutls_key->key.size; + premaster = state->gnutls_key->key.data; #ifdef HARD_DEBUG fprintf(stderr, "PREMASTER SECRET: "); @@ -69,6 +65,9 @@ char random[64]; random, 64, 48); } secure_free(premaster); + state->gnutls_key->key.size = 0; + state->gnutls_key->key.data = NULL; + #ifdef HARD_DEBUG fprintf(stderr, "MASTER SECRET: %s\n", _gnutls_bin2hex(master, 48)); #endif @@ -96,11 +95,6 @@ int _gnutls_send_server_kx_message(int cd, GNUTLS_STATE state) if (state->gnutls_internals.auth_struct->gnutls_generate_server_kx==NULL) return 0; - /* copy random bytes - some algorithms need that. - */ - memcpy( state->gnutls_key->server_random, state->security_parameters.server_random, 32); - memcpy( state->gnutls_key->client_random, state->security_parameters.client_random, 32); - data_size = state->gnutls_internals.auth_struct->gnutls_generate_server_kx( state->gnutls_key, &data); if (data_size < 0) { @@ -412,3 +406,31 @@ int _gnutls_recv_client_kx_message0(int cd, GNUTLS_STATE state) return ret; } +/* This is called when we want send our certificate + */ +int _gnutls_send_certificate(int cd, GNUTLS_STATE state) +{ + uint8 *data = NULL; + int data_size = 0; + int ret = 0; + +#ifdef HARD_DEBUG + fprintf(stderr, "Sending certificate message\n"); +#endif + + + if (state->gnutls_internals.auth_struct->gnutls_generate_certificate==NULL) + return 0; + + data_size = state->gnutls_internals.auth_struct->gnutls_generate_certificate( state->gnutls_key, &data); + + if (data_size < 0) { + gnutls_assert(); + return data_size; + } + + ret = _gnutls_send_handshake(cd, state, data, data_size, GNUTLS_CERTIFICATE); + gnutls_free(data); + + return data_size; +} diff --git a/lib/gnutls_kx.h b/lib/gnutls_kx.h index 325a7861f6..6408832a35 100644 --- a/lib/gnutls_kx.h +++ b/lib/gnutls_kx.h @@ -27,3 +27,4 @@ int _gnutls_recv_server_kx_message2(int cd, GNUTLS_STATE state); int _gnutls_recv_client_kx_message(int cd, GNUTLS_STATE state); int _gnutls_recv_client_kx_message0(int cd, GNUTLS_STATE state); int _gnutls_send_client_certificate_verify(int cd, GNUTLS_STATE state); +int _gnutls_send_certificate(int cd, GNUTLS_STATE state); diff --git a/lib/gnutls_srp.c b/lib/gnutls_srp.c index 31a269d3d2..8577c49262 100644 --- a/lib/gnutls_srp.c +++ b/lib/gnutls_srp.c @@ -24,6 +24,7 @@ #include <crypt_bcrypt.h> #include <gnutls_srp.h> #include <auth_srp_passwd.h> +#include <gnutls_gcry.h> #include "debug.h" /* These should be added in gcrypt.h */ @@ -111,8 +112,8 @@ int _gnutls_srp_gn(opaque ** ret_g, opaque ** ret_n, int bits) gnutls_free(tmp); } - gcry_mpi_release(g); - gcry_mpi_release(prime); + _gnutls_mpi_release(&g); + _gnutls_mpi_release(&prime); return 0; @@ -135,7 +136,7 @@ int _gnutls_srp_gx(opaque * text, int textsize, opaque ** result, MPI g, /* e = g^x mod prime (n) */ gcry_mpi_powm(e, g, x, prime); - gcry_mpi_release(x); + _gnutls_mpi_release(&x); gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &result_size, e); if (result != NULL) { @@ -143,7 +144,7 @@ int _gnutls_srp_gx(opaque * text, int textsize, opaque ** result, MPI g, gcry_mpi_print(GCRYMPI_FMT_USG, *result, &result_size, e); } - gcry_mpi_release(e); + _gnutls_mpi_release(&e); return result_size; @@ -170,12 +171,12 @@ MPI _gnutls_calc_srp_B(MPI * ret_b, MPI g, MPI n, MPI v) gcry_mpi_powm(tmpB, g, b, n); gcry_mpi_addm(B, v, tmpB, n); - gcry_mpi_release(tmpB); + _gnutls_mpi_release(&tmpB); if (ret_b) *ret_b = b; else - gcry_mpi_release(b); + _gnutls_mpi_release(&b); return B; } @@ -220,10 +221,10 @@ MPI _gnutls_calc_srp_S1(MPI A, MPI b, MPI u, MPI v, MPI n) gcry_mpi_powm(tmp1, v, u, n); gcry_mpi_mulm(tmp2, A, tmp1, n); - gcry_mpi_release(tmp1); + _gnutls_mpi_release(&tmp1); gcry_mpi_powm(S, tmp2, b, n); - gcry_mpi_release(tmp2); + _gnutls_mpi_release(&tmp2); return S; } @@ -247,7 +248,7 @@ MPI _gnutls_calc_srp_A(MPI * a, MPI g, MPI n) if (a != NULL) *a = tmpa; else - gcry_mpi_release(tmpa); + _gnutls_mpi_release(&tmpa); return A; } @@ -312,11 +313,11 @@ MPI _gnutls_calc_srp_S2(MPI B, MPI g, MPI x, MPI a, MPI u, MPI n) gcry_mpi_mul(tmp1, u, x); gcry_mpi_add(tmp4, a, tmp1); - gcry_mpi_release(tmp1); + _gnutls_mpi_release(&tmp1); gcry_mpi_powm(S, tmp2, tmp4, n); - gcry_mpi_release(tmp2); - gcry_mpi_release(tmp4); + _gnutls_mpi_release(&tmp2); + _gnutls_mpi_release(&tmp4); return S; } |