diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2001-10-08 18:38:04 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2001-10-08 18:38:04 +0000 |
commit | 44c0124aa768d83c93cb6242619047bc0877f716 (patch) | |
tree | b584e48b07eb3ca8027fccda3d7d0d0d601612cf | |
parent | 767e33eba3d47cff204d1141453b64cac6bc7f82 (diff) | |
download | gnutls-44c0124aa768d83c93cb6242619047bc0877f716.tar.gz |
added DHE_RSA ciphersuites
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | THANKS | 2 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | doc/tex/ex3.tex | 53 | ||||
-rw-r--r-- | lib/auth_anon.c | 10 | ||||
-rw-r--r-- | lib/auth_dhe_rsa.c | 280 | ||||
-rw-r--r-- | lib/auth_x509.c | 230 | ||||
-rw-r--r-- | lib/auth_x509.h | 2 | ||||
-rw-r--r-- | lib/gnutls_algorithms.c | 2 | ||||
-rw-r--r-- | lib/gnutls_cert.c | 2 | ||||
-rw-r--r-- | lib/gnutls_cert.h | 2 | ||||
-rw-r--r-- | lib/gnutls_datum.c | 3 | ||||
-rw-r--r-- | lib/gnutls_int.h | 2 | ||||
-rw-r--r-- | lib/gnutls_record.c | 1 | ||||
-rw-r--r-- | lib/gnutls_sig.c | 200 | ||||
-rw-r--r-- | lib/gnutls_sig.h | 12 | ||||
-rw-r--r-- | lib/x509_extensions.c | 2 | ||||
-rw-r--r-- | src/cli.c | 23 | ||||
-rw-r--r-- | src/serv.c | 33 |
19 files changed, 555 insertions, 310 deletions
@@ -1,3 +1,7 @@ +Version 0.2.4 +- Better handling of extensions +- Added DHE_RSA ciphersuites + Version 0.2.3 (19/09/2001) - Memory optimizations in gnutls_recv() - Fixed several memory leaks @@ -1,2 +1,4 @@ Tarun Upadhyay <tarun@poboxes.com> for his work on the initial ASN.1 DER parser. +Neil Spring <nspring@saavie.org> + diff --git a/configure.in b/configure.in index e9638000ea..bc4fdbeed3 100644 --- a/configure.in +++ b/configure.in @@ -11,7 +11,7 @@ AC_DEFINE_UNQUOTED(T_OS, "$target_os") GNUTLS_MAJOR_VERSION=0 GNUTLS_MINOR_VERSION=2 -GNUTLS_MICRO_VERSION=3 +GNUTLS_MICRO_VERSION=4 GNUTLS_VERSION=$GNUTLS_MAJOR_VERSION.$GNUTLS_MINOR_VERSION.$GNUTLS_MICRO_VERSION AC_DEFINE_UNQUOTED(GNUTLS_VERSION, "$GNUTLS_VERSION") diff --git a/doc/tex/ex3.tex b/doc/tex/ex3.tex index 243e45f564..af750d05d6 100644 --- a/doc/tex/ex3.tex +++ b/doc/tex/ex3.tex @@ -26,34 +26,37 @@ int print_info(GNUTLS_STATE state) if (gnutls_get_auth_info_type(state) == GNUTLS_X509PKI) { x509_info = gnutls_get_auth_info(state); if (x509_info != NULL) { - switch ( gnutls_x509pki_client_get_peer_certificate_status(x509_info)) { - case GNUTLS_CERT_NOT_TRUSTED: - printf("- Peer's X509 Certificate was NOT verified\n"); - break; - case GNUTLS_CERT_EXPIRED: - printf("- Peer's X509 Certificate was verified but is expired\n"); - break; - case GNUTLS_CERT_TRUSTED: - printf("- Peer's X509 Certificate was verified\n"); - break; - case GNUTLS_CERT_NONE: - printf("- Peer did not send any X509 Certificate.\n"); - break; - case GNUTLS_CERT_INVALID: - default: - printf("- Peer's X509 Certificate was invalid\n"); - break; - + CertificateStatus status = gnutls_x509pki_client_get_peer_certificate_status(x509_info); + switch( status) { + case GNUTLS_CERT_NOT_TRUSTED: + printf("- Peer's X509 Certificate was NOT verified\n"); + break; + case GNUTLS_CERT_EXPIRED: + printf("- Peer's X509 Certificate was verified but is expired\n"); + break; + case GNUTLS_CERT_TRUSTED: + printf("- Peer's X509 Certificate was verified\n"); + break; + case GNUTLS_CERT_NONE: + printf("- Peer did not send any certificate.\n"); + break; + case GNUTLS_CERT_INVALID: + printf("- Peer's X509 Certificate was invalid\n"); + break; } - printf(" - Certificate info:\n"); - printf(" - Certificate version: #%d\n", gnutls_x509pki_client_get_peer_certificate_version(x509_info)); + + if (status!=GNUTLS_CERT_NONE && status!=GNUTLS_CERT_INVALID) { + + printf(" - Certificate info:\n"); + printf(" - Certificate version: #%d\n", gnutls_x509pki_client_get_peer_certificate_version(x509_info)); - dn = gnutls_x509pki_client_get_peer_dn( x509_info); - PRINT_DN(dn); + dn = gnutls_x509pki_client_get_peer_dn( x509_info); + PRINT_DN(dn); - printf(" - Certificate Issuer's info:\n"); - dn = gnutls_x509pki_client_get_issuer_dn( x509_info); - PRINT_DN(dn); + printf(" - Certificate Issuer's info:\n"); + dn = gnutls_x509pki_client_get_issuer_dn( x509_info); + PRINT_DN(dn); + } } } diff --git a/lib/auth_anon.c b/lib/auth_anon.c index fa7c9a37cd..bea10be557 100644 --- a/lib/auth_anon.c +++ b/lib/auth_anon.c @@ -261,16 +261,6 @@ int proc_anon_client_kx( GNUTLS_STATE state, opaque* data, int data_size) { bits = cred->dh_bits; } -#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 - n_Y = READuint16( &data[0]); _n_Y = n_Y; diff --git a/lib/auth_dhe_rsa.c b/lib/auth_dhe_rsa.c index 8adfc52a50..68777f5e2c 100644 --- a/lib/auth_dhe_rsa.c +++ b/lib/auth_dhe_rsa.c @@ -18,21 +18,20 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -/* DHE_RSA is not really working. It is used as a template - * (it may work BUT it does not check certificates) - */ #include "gnutls_int.h" #include "gnutls_auth_int.h" #include "gnutls_errors.h" #include "gnutls_dh.h" #include "gnutls_num.h" +#include "gnutls_sig.h" +#include <gnutls_datum.h> #include <auth_x509.h> -static int gen_dhe_rsa_server_kx( GNUTLS_STATE , opaque**); -static int gen_dhe_rsa_client_kx( GNUTLS_STATE , opaque**); -static int proc_dhe_rsa_server_kx( GNUTLS_STATE , opaque*, int); -static int proc_dhe_rsa_client_kx( GNUTLS_STATE , opaque*, int); +static int gen_dhe_rsa_server_kx(GNUTLS_STATE, opaque **); +static int gen_dhe_rsa_client_kx(GNUTLS_STATE, opaque **); +static int proc_dhe_rsa_server_kx(GNUTLS_STATE, opaque *, int); +static int proc_dhe_rsa_client_kx(GNUTLS_STATE, opaque *, int); MOD_AUTH_STRUCT dhe_rsa_auth_struct = { "DHE_RSA", @@ -42,8 +41,8 @@ MOD_AUTH_STRUCT dhe_rsa_auth_struct = { NULL, NULL, gen_dhe_rsa_client_kx, - _gnutls_gen_x509_client_cert_vrfy, /* gen client cert vrfy */ - _gnutls_gen_x509_server_cert_req, /* server cert request */ + _gnutls_gen_x509_client_cert_vrfy, /* gen client cert vrfy */ + _gnutls_gen_x509_server_cert_req, /* server cert request */ _gnutls_proc_x509_server_certificate, _gnutls_proc_x509_client_certificate, @@ -51,43 +50,65 @@ MOD_AUTH_STRUCT dhe_rsa_auth_struct = { NULL, NULL, proc_dhe_rsa_client_kx, - _gnutls_proc_x509_client_cert_vrfy, /* proc client cert vrfy */ + _gnutls_proc_x509_client_cert_vrfy, /* proc client cert vrfy */ _gnutls_proc_x509_cert_req /* proc server cert request */ }; -static int gen_dhe_rsa_server_kx( GNUTLS_STATE state, opaque** data) { +static int gen_dhe_rsa_server_kx(GNUTLS_STATE state, opaque ** data) +{ MPI x, X, g, p; size_t n_X, n_g, n_p; uint8 *data_p; uint8 *data_g; uint8 *data_X; - int ret = 0; + int ret = 0, data_size; const X509PKI_CREDENTIALS cred; int bits; - - cred = _gnutls_get_kx_cred( state->gnutls_key, GNUTLS_X509PKI, NULL); - if (cred==NULL) { - bits = DEFAULT_BITS; /* default */ + gnutls_cert *apr_cert_list; + gnutls_private_key *apr_pkey; + int apr_cert_list_length; + gnutls_datum signature, ddata; + X509PKI_SERVER_AUTH_INFO info; + + cred = + _gnutls_get_kx_cred(state->gnutls_key, GNUTLS_X509PKI, NULL); + if (cred == NULL) { + bits = DEFAULT_BITS; /* default */ } else { bits = cred->dh_bits; } + /* find the appropriate certificate */ + if ((ret=_gnutls_find_apr_cert( state, &apr_cert_list, &apr_cert_list_length, &apr_pkey))<0) { + gnutls_assert(); + return ret; + } + g = gnutls_get_dh_params(&p, bits); - if (g==NULL) { + if (g == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } - state->gnutls_key->auth_info = gnutls_malloc(sizeof(X509PKI_SERVER_AUTH_INFO_INT)); - if (state->gnutls_key->auth_info==NULL) return GNUTLS_E_MEMORY_ERROR; + if ( state->gnutls_key->auth_info==NULL) { + state->gnutls_key->auth_info = + gnutls_calloc(1, sizeof(X509PKI_SERVER_AUTH_INFO_INT)); + if (state->gnutls_key->auth_info == NULL) + return GNUTLS_E_MEMORY_ERROR; - ((X509PKI_SERVER_AUTH_INFO)state->gnutls_key->auth_info)->dh_bits = gcry_mpi_get_nbits(p); - state->gnutls_key->auth_info_size = sizeof(X509PKI_SERVER_AUTH_INFO); + state->gnutls_key->auth_info_size = + sizeof(X509PKI_SERVER_AUTH_INFO_INT); + info = state->gnutls_key->auth_info; + info->dh_bits = gcry_mpi_get_nbits(p); + info->peer_certificate_status = GNUTLS_CERT_NONE; + } + info = state->gnutls_key->auth_info; + X = gnutls_calc_dh_secret(&x, g, p); - if (X==NULL) { - _gnutls_mpi_release( &g); - _gnutls_mpi_release( &p); + if (X == NULL) { + _gnutls_mpi_release(&g); + _gnutls_mpi_release(&p); gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } @@ -97,10 +118,10 @@ static int gen_dhe_rsa_server_kx( GNUTLS_STATE state, opaque** data) { gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &n_p, p); gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &n_X, X); (*data) = gnutls_malloc(n_g + n_p + n_X + 6); - if (*data==NULL) { - _gnutls_mpi_release( &X); - _gnutls_mpi_release( &g); - _gnutls_mpi_release( &p); + if (*data == NULL) { + _gnutls_mpi_release(&X); + _gnutls_mpi_release(&g); + _gnutls_mpi_release(&p); return GNUTLS_E_MEMORY_ERROR; } @@ -108,69 +129,126 @@ static int gen_dhe_rsa_server_kx( GNUTLS_STATE state, opaque** data) { gcry_mpi_print(GCRYMPI_FMT_USG, &data_p[2], &n_p, p); _gnutls_mpi_release(&p); - WRITEuint16( n_p, data_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); - WRITEuint16( n_g, data_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); - WRITEuint16( n_X, data_X); + WRITEuint16(n_X, data_X); - ret = n_p+n_g+n_X+6; + data_size = n_p + n_g + n_X + 6; - return ret; + + /* Generate the signature. */ + + /* If our certificate supports signing + */ + if (apr_cert_list != NULL) + if (apr_cert_list[0].keyUsage != 0) + if (! + (apr_cert_list[0]. + keyUsage & X509KEY_DIGITAL_SIGNATURE)) { + gnutls_assert(); + gnutls_free( *data); + return GNUTLS_E_X509_KEY_USAGE_VIOLATION; + } + + + ddata.data = *data; + ddata.size = data_size; + + if (apr_pkey != NULL) { + if ((ret = + _gnutls_generate_sig_params( + state, apr_pkey, &ddata, &signature)) < 0) { + gnutls_assert(); + gnutls_free( *data); + return ret; + } + } else { + gnutls_assert(); + return data_size; /* do not put a signature - ILLEGAL! */ + } + + *data = gnutls_realloc( *data, data_size+signature.size+2); + if (*data==NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + WRITEdatum16( &(*data)[data_size], signature); + data_size += signature.size+2; + + return data_size; } -static int gen_dhe_rsa_client_kx( GNUTLS_STATE state, opaque** data) { -MPI x, X; -size_t n_X; +static int gen_dhe_rsa_client_kx(GNUTLS_STATE state, opaque ** data) +{ + MPI x, X; + size_t n_X; + int ret; + + X = gnutls_calc_dh_secret(&x, state->gnutls_key->client_g, + state->gnutls_key->client_p); + if (X==NULL) + return GNUTLS_E_MEMORY_ERROR; - X = gnutls_calc_dh_secret(&x, state->gnutls_key->client_g, - state->gnutls_key->client_p); - gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &n_X, X); (*data) = gnutls_malloc(n_X + 2); - if (*data==NULL) + if (*data == NULL) return GNUTLS_E_MEMORY_ERROR; gcry_mpi_print(GCRYMPI_FMT_USG, &(*data)[2], &n_X, X); - (*data)[0] = 1; /* extern - explicit since we do not have + (*data)[0] = 1; /* extern - explicit since we do not have certificate */ _gnutls_mpi_release(&X); - - WRITEuint16( n_X, &(*data)[0]); - + + WRITEuint16(n_X, &(*data)[0]); + /* calculate the key after calculating the message */ - state->gnutls_key->KEY = gnutls_calc_dh_key(state->gnutls_key->client_Y, x, state->gnutls_key->client_p); + state->gnutls_key->KEY = + gnutls_calc_dh_key(state->gnutls_key->client_Y, x, + state->gnutls_key->client_p); + if (state->gnutls_key->KEY==NULL) + return GNUTLS_E_MEMORY_ERROR; + /* THESE SHOULD BE DISCARDED */ _gnutls_mpi_release(&state->gnutls_key->client_Y); _gnutls_mpi_release(&state->gnutls_key->client_p); _gnutls_mpi_release(&state->gnutls_key->client_g); - state->gnutls_key->client_Y = NULL; - state->gnutls_key->client_p = NULL; - state->gnutls_key->client_g = NULL; - return n_X+2; + ret = _gnutls_generate_key( state->gnutls_key); + _gnutls_mpi_release(&state->gnutls_key->KEY); + + if (ret < 0) { + return ret; + } + + return n_X + 2; } -static int proc_dhe_rsa_server_kx( GNUTLS_STATE state, opaque* data, int data_size) { +static int proc_dhe_rsa_server_kx(GNUTLS_STATE state, opaque * data, + int data_size) +{ uint16 n_Y, n_g, n_p; size_t _n_Y, _n_g, _n_p; uint8 *data_p; uint8 *data_g; uint8 *data_Y; - int i; - + int i, sigsize; + gnutls_datum vparams, signature; + int ret; i = 0; - n_p = READuint16( &data[i]); + n_p = READuint16(&data[i]); i += 2; data_p = &data[i]; @@ -179,8 +257,8 @@ static int proc_dhe_rsa_server_kx( GNUTLS_STATE state, opaque* data, int data_si gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - - n_g = READuint16( &data[i]); + + n_g = READuint16(&data[i]); i += 2; data_g = &data[i]; @@ -189,8 +267,8 @@ static int proc_dhe_rsa_server_kx( GNUTLS_STATE state, opaque* data, int data_si gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - - n_Y = READuint16( &data[i]); + + n_Y = READuint16(&data[i]); i += 2; data_Y = &data[i]; @@ -204,72 +282,104 @@ static int proc_dhe_rsa_server_kx( GNUTLS_STATE state, opaque* data, int data_si _n_p = n_p; if (gcry_mpi_scan(&state->gnutls_key->client_Y, - GCRYMPI_FMT_USG, data_Y, &_n_Y) != 0) { + GCRYMPI_FMT_USG, data_Y, &_n_Y) != 0) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } if (gcry_mpi_scan(&state->gnutls_key->client_g, - GCRYMPI_FMT_USG, data_g, &_n_g) != 0) { + GCRYMPI_FMT_USG, data_g, &_n_g) != 0) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } if (gcry_mpi_scan(&state->gnutls_key->client_p, - GCRYMPI_FMT_USG, data_p, &_n_p) != 0) { + GCRYMPI_FMT_USG, data_p, &_n_p) != 0) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } - /* We should check signature in non-anonymous KX - * this is anonymous however - */ - gnutls_free(data); - return 0; + /* VERIFY SIGNATURE */ + + vparams.size = n_Y + n_p + n_g + 6; + vparams.data = data; + + if (data_size-vparams.size-2 <= 0) { /* check if the peer sent enough data */ + gnutls_assert(); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + + sigsize = READuint16( &data[vparams.size]); + signature.data = &data[vparams.size+2]; + signature.size = GMIN(data_size-vparams.size-2, sigsize); + + if (state->gnutls_internals.peer_cert.version == 0) { /* this is the only way to check + * if it is initialized + */ + gnutls_assert(); + return GNUTLS_E_X509_CERTIFICATE_ERROR; + } + ret = _gnutls_verify_sig_params( state, &state->gnutls_internals.peer_cert, &vparams, &signature); + if (ret<0) { + gnutls_assert(); + return ret; + } + + return ret; } -static int proc_dhe_rsa_client_kx( GNUTLS_STATE state, opaque* data, int data_size) { +static int proc_dhe_rsa_client_kx(GNUTLS_STATE state, opaque * data, + int data_size) +{ uint16 n_Y; size_t _n_Y; MPI g, p; const X509PKI_CREDENTIALS cred; - int bits; - - cred = _gnutls_get_kx_cred( state->gnutls_key, GNUTLS_X509PKI, NULL); - if (cred==NULL) { - bits = DEFAULT_BITS; /* default */ + int bits, ret; + + cred = + _gnutls_get_kx_cred(state->gnutls_key, GNUTLS_X509PKI, NULL); + if (cred == NULL) { + bits = DEFAULT_BITS; /* default */ } else { bits = cred->dh_bits; } -#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 - n_Y = READuint16( &data[0]); + n_Y = READuint16(&data[0]); _n_Y = n_Y; if (gcry_mpi_scan(&state->gnutls_key->client_Y, - GCRYMPI_FMT_USG, &data[2], &_n_Y)) { + GCRYMPI_FMT_USG, &data[2], &_n_Y)) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } g = gnutls_get_dh_params(&p, bits); - state->gnutls_key->KEY = gnutls_calc_dh_key( state->gnutls_key->client_Y, state->gnutls_key->dh_secret, p); - + if (g==NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + state->gnutls_key->KEY = + gnutls_calc_dh_key(state->gnutls_key->client_Y, + state->gnutls_key->dh_secret, p); + if (state->gnutls_key->KEY==NULL) + return GNUTLS_E_MEMORY_ERROR; + + _gnutls_mpi_release(&g); _gnutls_mpi_release(&p); _gnutls_mpi_release(&state->gnutls_key->client_Y); _gnutls_mpi_release(&state->gnutls_key->dh_secret); - return 0; -} + ret = _gnutls_generate_key( state->gnutls_key); + _gnutls_mpi_release(&state->gnutls_key->KEY); + if (ret < 0) { + return ret; + } + return 0; +} diff --git a/lib/auth_x509.c b/lib/auth_x509.c index fbf6ff401d..f34268f22c 100644 --- a/lib/auth_x509.c +++ b/lib/auth_x509.c @@ -407,34 +407,17 @@ int data_size = _data_size; int _gnutls_gen_x509_client_certificate(GNUTLS_STATE state, opaque ** data) { - const X509PKI_CREDENTIALS cred; - int ret, i, ind, pdatasize; + int ret, i, pdatasize; opaque *pdata; gnutls_cert *apr_cert_list; gnutls_private_key *apr_pkey; int apr_cert_list_length; - cred = _gnutls_get_cred(state->gnutls_key, GNUTLS_X509PKI, NULL); - if (cred == NULL) { - gnutls_assert(); - return GNUTLS_E_INSUFICIENT_CRED; - } - if (cred->ncerts == 0) { - apr_cert_list = NULL; - apr_cert_list_length = 0; - apr_pkey = NULL; - } else { - ind = state->gnutls_internals.client_certificate_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]; - } + /* find the appropriate certificate */ + if ((ret=_gnutls_find_apr_cert( state, &apr_cert_list, &apr_cert_list_length, &apr_pkey))<0) { + gnutls_assert(); + return ret; } ret = 3; @@ -476,34 +459,15 @@ int _gnutls_gen_x509_client_certificate(GNUTLS_STATE state, opaque ** data) int _gnutls_gen_x509_server_certificate(GNUTLS_STATE state, opaque ** data) { - const X509PKI_CREDENTIALS cred; - int ret, i, ind, pdatasize; + int ret, i, pdatasize; opaque *pdata; gnutls_cert *apr_cert_list; gnutls_private_key *apr_pkey; int apr_cert_list_length; - cred = _gnutls_get_cred(state->gnutls_key, GNUTLS_X509PKI, NULL); - if (cred == NULL) { + if ((ret=_gnutls_find_apr_cert( state, &apr_cert_list, &apr_cert_list_length, &apr_pkey))<0) { gnutls_assert(); - return GNUTLS_E_INSUFICIENT_CRED; - } - if (cred->ncerts == 0) { - apr_cert_list = NULL; - apr_cert_list_length = 0; - apr_pkey = NULL; - } else { - ind = _gnutls_find_cert_list_index(cred->cert_list, cred->ncerts, state->security_parameters.extensions.dnsname); - - 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]; - } + return ret; } ret = 3; @@ -543,6 +507,7 @@ int _gnutls_gen_x509_server_certificate(GNUTLS_STATE state, opaque ** data) return pdatasize; } +#define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) gnutls_free_cert(peer_certificate_list[x]) int _gnutls_proc_x509_server_certificate(GNUTLS_STATE state, opaque * data, int data_size) { int size, len, ret; @@ -550,7 +515,7 @@ int _gnutls_proc_x509_server_certificate(GNUTLS_STATE state, opaque * data, int X509PKI_CLIENT_AUTH_INFO info; const X509PKI_CREDENTIALS cred; int dsize = data_size; - int i, j; + int i, j, x; gnutls_cert *peer_certificate_list; int peer_certificate_list_size = 0; gnutls_datum tmp; @@ -561,20 +526,23 @@ int _gnutls_proc_x509_server_certificate(GNUTLS_STATE state, opaque * data, int gnutls_assert(); return GNUTLS_E_INSUFICIENT_CRED; } - if (state->gnutls_key->auth_info == NULL) - state->gnutls_key->auth_info = gnutls_calloc(1, sizeof(X509PKI_CLIENT_AUTH_INFO_INT)); if (state->gnutls_key->auth_info == NULL) { - gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; + state->gnutls_key->auth_info = gnutls_calloc(1, sizeof(X509PKI_CLIENT_AUTH_INFO_INT)); + if (state->gnutls_key->auth_info == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + state->gnutls_key->auth_info_size = sizeof(X509PKI_CLIENT_AUTH_INFO_INT); + + info = state->gnutls_key->auth_info; + info->peer_certificate_status = GNUTLS_CERT_NONE; } - state->gnutls_key->auth_info_size = sizeof(X509PKI_CLIENT_AUTH_INFO_INT); + info = state->gnutls_key->auth_info; DECR_LEN(dsize, 3); size = READuint24(p); p += 3; - info = state->gnutls_key->auth_info; - info->peer_certificate_status = GNUTLS_CERT_INVALID; if (size == 0) { gnutls_assert(); @@ -601,13 +569,14 @@ int _gnutls_proc_x509_server_certificate(GNUTLS_STATE state, opaque * data, int dsize = data_size; i = dsize; peer_certificate_list = - gnutls_malloc(sizeof(gnutls_cert) * + gnutls_calloc(1, sizeof(gnutls_cert) * (peer_certificate_list_size)); if (peer_certificate_list == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } + p = data + 3; i = data_size - 3; j = 0; @@ -623,9 +592,22 @@ int _gnutls_proc_x509_server_certificate(GNUTLS_STATE state, opaque * data, int if ((ret = _gnutls_cert2gnutlsCert(&peer_certificate_list[j], tmp)) < 0) { gnutls_assert(); + CLEAR_CERTS; gnutls_free(peer_certificate_list); return ret; } + if (j==0) { /* Copy the first certificate in the chain - peer's certificate + * into the peer_cert. This is needed in order to access these + * parameters later. + */ + if ((ret = _gnutls_cert2gnutlsCert(&state->gnutls_internals.peer_cert, tmp)) < 0) { + gnutls_assert(); + CLEAR_CERTS; + gnutls_free(peer_certificate_list); + return ret; + } + } + p += len; i -= len + 3; j++; @@ -637,6 +619,7 @@ int _gnutls_proc_x509_server_certificate(GNUTLS_STATE state, opaque * data, int _gnutls_get_rsa_params(NULL, &state->gnutls_key->a, &state->gnutls_key->x, peer_certificate_list[0].raw)) < 0) { gnutls_assert(); + CLEAR_CERTS; gnutls_free(peer_certificate_list); return ret; } @@ -644,6 +627,12 @@ int _gnutls_proc_x509_server_certificate(GNUTLS_STATE state, opaque * data, int */ verify = gnutls_verify_certificate(peer_certificate_list, peer_certificate_list_size, cred->ca_list, cred->ncas, NULL, 0); + if (verify < 0) { + gnutls_assert(); + CLEAR_CERTS; + gnutls_free(peer_certificate_list); + return verify; + } /* keep the PK algorithm */ state->gnutls_internals.peer_pk_algorithm = peer_certificate_list[0].subject_pk_algorithm; @@ -655,10 +644,12 @@ int _gnutls_proc_x509_server_certificate(GNUTLS_STATE state, opaque * data, int if ( peer_certificate_list[0].keyUsage != 0) if ( !(peer_certificate_list[0].keyUsage & X509KEY_KEY_ENCIPHERMENT)) { gnutls_assert(); + CLEAR_CERTS; gnutls_free(peer_certificate_list); return GNUTLS_E_X509_KEY_USAGE_VIOLATION; } + CLEAR_CERTS; gnutls_free(peer_certificate_list); return 0; @@ -671,6 +662,7 @@ int _gnutls_proc_x509_cert_req(GNUTLS_STATE state, opaque * data, int data_size) int size, ret; opaque *p = data; const X509PKI_CREDENTIALS cred; + X509PKI_CLIENT_AUTH_INFO info; int dsize = data_size; int i; int found; @@ -683,14 +675,19 @@ int _gnutls_proc_x509_cert_req(GNUTLS_STATE state, opaque * data, int data_size) } state->gnutls_key->certificate_requested = 1; - if (state->gnutls_key->auth_info == NULL) - state->gnutls_key->auth_info = gnutls_calloc(1, sizeof(X509PKI_CLIENT_AUTH_INFO_INT)); if (state->gnutls_key->auth_info == NULL) { - gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; - } - state->gnutls_key->auth_info_size = sizeof(X509PKI_CLIENT_AUTH_INFO_INT); + state->gnutls_key->auth_info = gnutls_calloc(1, sizeof(X509PKI_CLIENT_AUTH_INFO_INT)); + if (state->gnutls_key->auth_info == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + state->gnutls_key->auth_info_size = sizeof(X509PKI_CLIENT_AUTH_INFO_INT); + info = state->gnutls_key->auth_info; + info->peer_certificate_status = GNUTLS_CERT_NONE; + } + info = state->gnutls_key->auth_info; + DECR_LEN(dsize, 1); size = p[0]; p += 1; @@ -730,8 +727,7 @@ int _gnutls_proc_x509_cert_req(GNUTLS_STATE state, opaque * data, int data_size) int _gnutls_gen_x509_client_cert_vrfy(GNUTLS_STATE state, opaque ** data) { - const X509PKI_CREDENTIALS cred; - int ret, ind; + int ret; gnutls_cert *apr_cert_list; gnutls_private_key *apr_pkey; int apr_cert_list_length, size; @@ -739,28 +735,12 @@ int _gnutls_gen_x509_client_cert_vrfy(GNUTLS_STATE state, opaque ** data) *data = NULL; - cred = _gnutls_get_cred(state->gnutls_key, GNUTLS_X509PKI, NULL); - if (cred == NULL) { + /* find the appropriate certificate */ + if ((ret=_gnutls_find_apr_cert( state, &apr_cert_list, &apr_cert_list_length, &apr_pkey))<0) { gnutls_assert(); - return GNUTLS_E_INSUFICIENT_CRED; - } - if (cred->ncerts == 0) { - apr_cert_list = NULL; - apr_cert_list_length = 0; - apr_pkey = NULL; - } else { - ind = state->gnutls_internals.client_certificate_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]; - } + return ret; } - + /* If our certificate supports signing */ if ( apr_cert_list != NULL) @@ -771,7 +751,7 @@ int _gnutls_gen_x509_client_cert_vrfy(GNUTLS_STATE state, opaque ** data) } if (apr_pkey != NULL) { - if ( (ret=_gnutls_generate_sig( state, apr_pkey, &signature)) < 0) { + if ( (ret=_gnutls_generate_sig_from_hdata( state, apr_pkey, &signature)) < 0) { gnutls_assert(); return ret; } @@ -800,7 +780,6 @@ int _gnutls_proc_x509_client_cert_vrfy(GNUTLS_STATE state, opaque * data, int da int size, ret; int dsize = data_size; opaque* pdata = data; -gnutls_cert cert; gnutls_datum sig; DECR_LEN(dsize, 2); @@ -815,23 +794,11 @@ gnutls_datum sig; sig.data = pdata; sig.size = size; - cert.params = gnutls_malloc( 2*sizeof(MPI)); - if (cert.params==NULL) { + if ( (ret=_gnutls_verify_sig_hdata( state, &state->gnutls_internals.peer_cert, &sig, data_size+HANDSHAKE_HEADER_SIZE))<0) { gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; - } - cert.params[0] = state->gnutls_key->x; - cert.params[1] = state->gnutls_key->a; - cert.subject_pk_algorithm = state->gnutls_internals.peer_pk_algorithm; - - if ( (ret=_gnutls_verify_sig( state, &cert, &sig, data_size+HANDSHAKE_HEADER_SIZE))<0) { - gnutls_assert(); - gnutls_free( cert.params); return ret; } - gnutls_free( cert.params); - return 0; } @@ -866,6 +833,9 @@ int _gnutls_gen_x509_server_cert_req(GNUTLS_STATE state, opaque ** data) } pdata[0] = CERTTYPE_SIZE - 1; +#ifdef DEBUG +# warning CHECK HERE FOR DSS +#endif pdata[1] = RSA_SIGN; /* only this for now */ pdata += CERTTYPE_SIZE; size = CERTTYPE_SIZE; @@ -890,3 +860,71 @@ int _gnutls_gen_x509_server_cert_req(GNUTLS_STATE state, opaque ** data) return size; } + + +/* This function will return the appropriate certificate to use. The return + * value depends on the side (client or server). + */ +int _gnutls_find_apr_cert( GNUTLS_STATE state, gnutls_cert** apr_cert_list, int *apr_cert_list_length, gnutls_private_key** apr_pkey) +{ + const X509PKI_CREDENTIALS cred; + int ind; + + cred = + _gnutls_get_kx_cred(state->gnutls_key, GNUTLS_X509PKI, NULL); + + if (cred==NULL) { + gnutls_assert(); + *apr_cert_list = NULL; + *apr_pkey= NULL; + *apr_cert_list_length = 0; + return GNUTLS_E_INSUFICIENT_CRED; + } + + if (state->security_parameters.entity == GNUTLS_SERVER) { + + if (cred->ncerts == 0) { + *apr_cert_list = NULL; + *apr_cert_list_length = 0; + *apr_pkey = NULL; + } else { + ind = + _gnutls_find_cert_list_index(cred->cert_list, + cred->ncerts, + state-> + security_parameters. + extensions.dnsname); + + 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 */ + if (cred->ncerts == 0) { + *apr_cert_list = NULL; + *apr_cert_list_length = 0; + *apr_pkey = NULL; + } else { + ind = state->gnutls_internals.client_certificate_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]; + } + } + + } + + return 0; +} diff --git a/lib/auth_x509.h b/lib/auth_x509.h index b72350d4cb..64657ba7dc 100644 --- a/lib/auth_x509.h +++ b/lib/auth_x509.h @@ -64,6 +64,8 @@ int _gnutls_gen_x509_server_cert_req(GNUTLS_STATE, opaque **); int _gnutls_proc_x509_cert_req(GNUTLS_STATE, opaque *, int); int _gnutls_proc_x509_client_cert_vrfy(GNUTLS_STATE, opaque *, int); int _gnutls_proc_x509_server_certificate(GNUTLS_STATE, opaque *, int); +int _gnutls_find_apr_cert( GNUTLS_STATE state, gnutls_cert** apr_cert_list, int *apr_cert_list_length, gnutls_private_key** apr_pkey); + #define _gnutls_proc_x509_client_certificate _gnutls_proc_x509_server_certificate #endif diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c index 79b74ec4c7..f22393ef7a 100644 --- a/lib/gnutls_algorithms.c +++ b/lib/gnutls_algorithms.c @@ -182,12 +182,14 @@ struct gnutls_kx_algo_entry { typedef struct gnutls_kx_algo_entry gnutls_kx_algo_entry; extern MOD_AUTH_STRUCT rsa_auth_struct; +extern MOD_AUTH_STRUCT dhe_rsa_auth_struct; extern MOD_AUTH_STRUCT anon_auth_struct; extern MOD_AUTH_STRUCT srp_auth_struct; static const gnutls_kx_algo_entry kx_algorithms[] = { GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_DH_ANON, &anon_auth_struct), GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_RSA, &rsa_auth_struct), + GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_DHE_RSA, &dhe_rsa_auth_struct), GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_SRP, &srp_auth_struct), {0} }; diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c index 0fa70aaacf..dac06a48ea 100644 --- a/lib/gnutls_cert.c +++ b/lib/gnutls_cert.c @@ -47,7 +47,7 @@ typedef struct { */ static const gnutls_pk_map pk_mappings[] = { {GNUTLS_KX_RSA, GNUTLS_PK_RSA}, -/* { GNUTLS_KX_DHE_RSA, GNUTLS_PK_RSA }, */ + { GNUTLS_KX_DHE_RSA, GNUTLS_PK_RSA }, {0} }; diff --git a/lib/gnutls_cert.h b/lib/gnutls_cert.h index 7c6939d48f..0d7d6aaf90 100644 --- a/lib/gnutls_cert.h +++ b/lib/gnutls_cert.h @@ -57,6 +57,6 @@ int _gnutls_find_cert_list_index(gnutls_cert ** cert_list, #define MAX_INT_DIGITS 4 void _gnutls_int2str(int k, char* data); int _gnutls_get_name_type( node_asn *rasn, char *root, gnutls_DN * dn); - +void gnutls_free_cert(gnutls_cert cert); #endif diff --git a/lib/gnutls_datum.c b/lib/gnutls_datum.c index 70f807ffae..c94144bc96 100644 --- a/lib/gnutls_datum.c +++ b/lib/gnutls_datum.c @@ -24,7 +24,8 @@ #include <gnutls_errors.h> /* contains functions that make it easier to - * write vectors of <size|data> + * write vectors of <size|data>. The destination size + * should be preallocated (datum.size+(bits/8)) */ void WRITEdatum16( opaque* dest, gnutls_datum dat) { diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 596a4aaf18..b3c534ab95 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -194,6 +194,7 @@ typedef struct GNUTLS_KEY_INT* GNUTLS_KEY; #include <gnutls_hash_int.h> #include <gnutls_cipher_int.h> +#include <gnutls_cert.h> typedef struct { uint8 CipherSuite[2]; @@ -374,6 +375,7 @@ typedef struct { * client certificates were found. */ int (*x509_client_cert_callback)(void*,void*,int, void*, int); + gnutls_cert peer_cert; } GNUTLS_INTERNALS; struct GNUTLS_STATE_INT { diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c index 9879b46dce..b1582e4a30 100644 --- a/lib/gnutls_record.c +++ b/lib/gnutls_record.c @@ -178,6 +178,7 @@ int gnutls_deinit(GNUTLS_STATE state) GNUTLS_FREE(state->gnutls_internals.CompressionMethodPriority.algorithm_priority); GNUTLS_FREE(state->gnutls_internals.db_name); + gnutls_free_cert( state->gnutls_internals.peer_cert); memset( state, 0, sizeof(struct GNUTLS_STATE_INT)); GNUTLS_FREE(state); diff --git a/lib/gnutls_sig.c b/lib/gnutls_sig.c index 9005f51b8d..053907f5d3 100644 --- a/lib/gnutls_sig.c +++ b/lib/gnutls_sig.c @@ -34,10 +34,13 @@ #include <gnutls_buffers.h> #include <gnutls_sig.h> -int _gnutls_generate_sig( GNUTLS_STATE state, gnutls_private_key *pkey, gnutls_datum *signature) { -opaque digest[20+16]; + + +/* Generates a signature of all the previous sended packets in the + * handshake procedure. + */ +int _gnutls_generate_sig_from_hdata( GNUTLS_STATE state, gnutls_private_key *pkey, gnutls_datum *signature) { gnutls_datum data; -GNUTLS_HASH_HANDLE td; int size = gnutls_getHashDataBufferSize( state); int ret; @@ -50,49 +53,94 @@ int ret; gnutls_readHashDataFromBuffer( state, data.data, data.size); + ret = _gnutls_pkcs1_rsa_generate_sig( pkey, &data, signature); + gnutls_free_datum( &data); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return ret; + +} + +/* Generates a signature of all the random data and the parameters. + * Used in DHE_* ciphersuites. + */ +int _gnutls_generate_sig_params( GNUTLS_STATE state, gnutls_private_key *pkey, gnutls_datum* params, gnutls_datum *signature) +{ + gnutls_datum sdata; + int size = 2*TLS_RANDOM_SIZE; + int ret; + + sdata.data = gnutls_malloc( size+params->size); + sdata.size = size + params->size; + if (sdata.data==NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + memcpy( sdata.data, state->security_parameters.client_random, TLS_RANDOM_SIZE); + memcpy( &sdata.data[TLS_RANDOM_SIZE], state->security_parameters.server_random, TLS_RANDOM_SIZE); + memcpy( &sdata.data[2*TLS_RANDOM_SIZE], params->data, params->size); + + ret = _gnutls_pkcs1_rsa_generate_sig( pkey, &sdata, signature); +fprintf(stderr, "GSIG[%d]: %s\n", signature->size, _gnutls_bin2hex(signature->data, signature->size)); +fprintf(stderr, "DATA[%d]: %s\n", sdata.size, _gnutls_bin2hex(sdata.data, sdata.size)); + + gnutls_free_datum( &sdata); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return ret; + +} + + +/* This will create a PKCS1 signature, as defined in the TLS protocol. + */ +int _gnutls_pkcs1_rsa_generate_sig( gnutls_private_key *pkey, const gnutls_datum *data, gnutls_datum *signature) +{ +int ret; +opaque digest[20+16]; +gnutls_datum tmpdata; +GNUTLS_HASH_HANDLE td; + switch(pkey->pk_algorithm) { case GNUTLS_PK_RSA: td = gnutls_hash_init( GNUTLS_MAC_MD5); if (td==NULL) { gnutls_assert(); - gnutls_free_datum( &data); return GNUTLS_E_MEMORY_ERROR; } - gnutls_hash( td, data.data, data.size); + gnutls_hash( td, data->data, data->size); gnutls_hash_deinit( td, digest); td = gnutls_hash_init( GNUTLS_MAC_SHA); if (td==NULL) { gnutls_assert(); - gnutls_free_datum( &data); return GNUTLS_E_MEMORY_ERROR; } - gnutls_hash( td, data.data, data.size); + gnutls_hash( td, data->data, data->size); gnutls_hash_deinit( td, &digest[16]); - gnutls_free_datum( &data); - data.data = digest; - data.size = 20+16; /* md5 + sha */ - ret = _gnutls_pkcs1_rsa_generate_sig( pkey, &data, signature); + tmpdata.data = digest; + tmpdata.size = 20+16; /* md5 + sha */ break; default: - gnutls_free_datum( &data); - ret = GNUTLS_E_UNIMPLEMENTED_FEATURE; + gnutls_assert(); + return GNUTLS_E_UNIMPLEMENTED_FEATURE; break; } - return ret; - -} - -int _gnutls_pkcs1_rsa_generate_sig( gnutls_private_key *pkey, const gnutls_datum *data, gnutls_datum *signature) { - int ret; /* encrypt der */ - if ( (ret=_gnutls_pkcs1_rsa_encrypt( signature, *data, pkey->params[0], pkey->params[1], 1)) < 0) { + if ( (ret=_gnutls_pkcs1_rsa_encrypt( signature, tmpdata, pkey->params[0], pkey->params[1], 1)) < 0) { gnutls_assert(); return ret; } @@ -102,20 +150,50 @@ int _gnutls_pkcs1_rsa_generate_sig( gnutls_private_key *pkey, const gnutls_datum int _gnutls_pkcs1_rsa_verify_sig( gnutls_cert *cert, const gnutls_datum *data, gnutls_datum *signature) { int ret; - gnutls_datum plain; + gnutls_datum plain, vdata; + opaque digest[20+16]; + GNUTLS_HASH_HANDLE td; + + switch(cert->subject_pk_algorithm) { + case GNUTLS_PK_RSA: + + td = gnutls_hash_init( GNUTLS_MAC_MD5); + if (td==NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + gnutls_hash( td, data->data, data->size); + gnutls_hash_deinit( td, digest); + + td = gnutls_hash_init( GNUTLS_MAC_SHA); + if (td==NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + gnutls_hash( td, data->data, data->size); + gnutls_hash_deinit( td, &digest[16]); + + vdata.data = digest; + vdata.size = 20+16; /* md5 + sha */ + + break; + default: + gnutls_assert(); + return GNUTLS_E_UNIMPLEMENTED_FEATURE; + } /* decrypt signature */ - if ( (ret=_gnutls_pkcs1_rsa_decrypt( &plain, *signature, cert->params[0], cert->params[1], 1)) < 0) { + if ( (ret=_gnutls_pkcs1_rsa_decrypt( &plain, *signature, cert->params[1], cert->params[0], 1)) < 0) { gnutls_assert(); return ret; } - if (plain.size != data->size) { + if (plain.size != vdata.size) { gnutls_assert(); return GNUTLS_E_PK_SIGNATURE_FAILED; } - if ( memcmp(plain.data, data->data, plain.size)!=0) { + if ( memcmp(plain.data, vdata.data, plain.size)!=0) { gnutls_assert(); return GNUTLS_E_PK_SIGNATURE_FAILED; } @@ -125,12 +203,11 @@ int _gnutls_pkcs1_rsa_verify_sig( gnutls_cert *cert, const gnutls_datum *data, g /* Verifies a TLS signature (like the one in the client certificate - * verify message). + * verify message). ubuffer_size is a buffer to remove from the hash buffer + * in order to avoid hashing the last message. */ -int _gnutls_verify_sig( GNUTLS_STATE state, gnutls_cert *cert, gnutls_datum* signature, int ubuffer_size) { -opaque digest[20+16]; +int _gnutls_verify_sig_hdata( GNUTLS_STATE state, gnutls_cert *cert, gnutls_datum* signature, int ubuffer_size) { gnutls_datum data; -GNUTLS_HASH_HANDLE td; int size = gnutls_getHashDataBufferSize( state) - ubuffer_size; /* do not get the last message */ int ret; @@ -143,46 +220,47 @@ int ret; gnutls_readHashDataFromBuffer( state, data.data, data.size); - switch(cert->subject_pk_algorithm) { - case GNUTLS_PK_RSA: - - td = gnutls_hash_init( GNUTLS_MAC_MD5); - if (td==NULL) { - gnutls_assert(); - gnutls_free_datum( &data); - return GNUTLS_E_MEMORY_ERROR; - } - gnutls_hash( td, data.data, data.size); - gnutls_hash_deinit( td, digest); - - td = gnutls_hash_init( GNUTLS_MAC_SHA); - if (td==NULL) { - gnutls_assert(); - gnutls_free_datum( &data); - return GNUTLS_E_MEMORY_ERROR; - } - gnutls_hash( td, data.data, data.size); - gnutls_hash_deinit( td, &digest[16]); - gnutls_free_datum( &data); - - - data.data = digest; - data.size = 20+16; /* md5 + sha */ - ret = _gnutls_pkcs1_rsa_verify_sig( cert, &data, signature); - - break; - default: - gnutls_assert(); - gnutls_free_datum( &data); - ret = GNUTLS_E_UNIMPLEMENTED_FEATURE; - break; + ret = _gnutls_pkcs1_rsa_verify_sig( cert, &data, signature); + if (ret < 0) { + gnutls_assert(); + return ret; } return ret; } +/* Generates a signature of all the random data and the parameters. + * Used in DHE_* ciphersuites. + */ +int _gnutls_verify_sig_params( GNUTLS_STATE state, gnutls_cert *cert, const gnutls_datum* params, gnutls_datum *signature) +{ + gnutls_datum sdata; + int size = 2*TLS_RANDOM_SIZE; + int ret; + + sdata.data = gnutls_malloc( size+params->size); + sdata.size = size + params->size; + if (sdata.data==NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + memcpy( sdata.data, state->security_parameters.client_random, TLS_RANDOM_SIZE); + memcpy( &sdata.data[TLS_RANDOM_SIZE], state->security_parameters.server_random, TLS_RANDOM_SIZE); + memcpy( &sdata.data[2*TLS_RANDOM_SIZE], params->data, params->size); +fprintf(stderr, "VSIG[%d]: %s\n", signature->size, _gnutls_bin2hex(signature->data, signature->size)); +fprintf(stderr, "DATA[%d]: %s\n", sdata.size, _gnutls_bin2hex(sdata.data, sdata.size)); + ret = _gnutls_pkcs1_rsa_verify_sig( cert, &sdata, signature); + gnutls_free_datum( &sdata); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return ret; + +} diff --git a/lib/gnutls_sig.h b/lib/gnutls_sig.h index 95725c222d..bb311c60d3 100644 --- a/lib/gnutls_sig.h +++ b/lib/gnutls_sig.h @@ -1,4 +1,12 @@ +#ifndef GNUTLS_SIG_H +# define GNUTLS_SIG_H +# include <auth_x509.h> + CertificateStatus gnutls_x509_verify_signature(gnutls_cert* cert, gnutls_cert* issuer); int _gnutls_pkcs1_rsa_generate_sig( gnutls_private_key *pkey, const gnutls_datum *data, gnutls_datum *signature); -int _gnutls_generate_sig( GNUTLS_STATE state, gnutls_private_key *pkey, gnutls_datum *signature); -int _gnutls_verify_sig( GNUTLS_STATE state, gnutls_cert *cert, gnutls_datum* signature, int ubuffer_size); +int _gnutls_generate_sig_from_hdata( GNUTLS_STATE state, gnutls_private_key *pkey, gnutls_datum *signature); +int _gnutls_generate_sig_params( GNUTLS_STATE state, gnutls_private_key *pkey, gnutls_datum* params, gnutls_datum *signature); +int _gnutls_verify_sig_hdata( GNUTLS_STATE state, gnutls_cert *cert, gnutls_datum* signature, int ubuffer_size); +int _gnutls_verify_sig_params( GNUTLS_STATE state, gnutls_cert *cert, const gnutls_datum* params, gnutls_datum* signature); + +#endif diff --git a/lib/x509_extensions.c b/lib/x509_extensions.c index 2424b9f971..92748b17af 100644 --- a/lib/x509_extensions.c +++ b/lib/x509_extensions.c @@ -263,7 +263,9 @@ int _gnutls_get_ext_type( node_asn *rasn, char *root, gnutls_cert *cert) if (result==ASN_ELEMENT_NOT_FOUND) break; else { if (result==ASN_MEM_ERROR && strcmp(critical, "FALSE")==0) { +#ifdef DEBUG _gnutls_log("Cannot parse extension: %s. Too small buffer.", extnID); +#endif continue; } if (result != ASN_OK) { @@ -78,7 +78,8 @@ const gnutls_DN* dn; if (gnutls_get_auth_info_type(state) == GNUTLS_X509PKI) { x509_info = gnutls_get_auth_info(state); if (x509_info != NULL) { - switch( gnutls_x509pki_client_get_peer_certificate_status(x509_info)) { + CertificateStatus status = gnutls_x509pki_client_get_peer_certificate_status(x509_info); + switch( status) { case GNUTLS_CERT_NOT_TRUSTED: printf("- Peer's X509 Certificate was NOT verified\n"); break; @@ -92,21 +93,21 @@ const gnutls_DN* dn; printf("- Peer did not send any X509 Certificate.\n"); break; case GNUTLS_CERT_INVALID: - default: printf("- Peer's X509 Certificate was invalid\n"); break; - } - printf(" - Certificate info:\n"); - printf(" - Certificate version: #%d\n", gnutls_x509pki_client_get_peer_certificate_version(x509_info)); + if (status!=GNUTLS_CERT_NONE && status!=GNUTLS_CERT_INVALID) { + printf(" - Certificate info:\n"); + printf(" - Certificate version: #%d\n", gnutls_x509pki_client_get_peer_certificate_version(x509_info)); - dn = gnutls_x509pki_client_get_peer_dn( x509_info); - PRINT_DN( dn); + dn = gnutls_x509pki_client_get_peer_dn( x509_info); + PRINT_DN( dn); - dn = gnutls_x509pki_client_get_issuer_dn( x509_info); - printf(" - Certificate Issuer's info:\n"); - PRINT_DN( dn); + dn = gnutls_x509pki_client_get_issuer_dn( x509_info); + printf(" - Certificate Issuer's info:\n"); + PRINT_DN( dn); + } } } @@ -218,7 +219,7 @@ int main(int argc, char** argv) gnutls_set_protocol_priority( state, GNUTLS_TLS1, GNUTLS_SSL3, 0); gnutls_set_cipher_priority( state, GNUTLS_3DES_CBC, GNUTLS_RIJNDAEL_CBC, 0); gnutls_set_compression_priority( state, GNUTLS_ZLIB, GNUTLS_NULL_COMPRESSION, 0); - gnutls_set_kx_priority( state, GNUTLS_KX_RSA, GNUTLS_KX_SRP, GNUTLS_KX_DH_ANON, 0); + gnutls_set_kx_priority( state, GNUTLS_KX_DHE_RSA, GNUTLS_KX_RSA, GNUTLS_KX_SRP, GNUTLS_KX_DH_ANON, 0); gnutls_set_mac_priority( state, GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0); gnutls_set_cred( state, GNUTLS_ANON, NULL); diff --git a/src/serv.c b/src/serv.c index 5cddf87155..f7878e0737 100644 --- a/src/serv.c +++ b/src/serv.c @@ -87,8 +87,7 @@ GNUTLS_STATE initialize_state() gnutls_set_cipher_priority(state, GNUTLS_NULL_CIPHER, GNUTLS_RIJNDAEL_CBC, GNUTLS_3DES_CBC, GNUTLS_ARCFOUR, 0); gnutls_set_compression_priority(state, GNUTLS_ZLIB, GNUTLS_NULL_COMPRESSION, 0); - gnutls_set_kx_priority(state, GNUTLS_KX_DHE_RSA, GNUTLS_KX_RSA, GNUTLS_KX_SRP, - GNUTLS_KX_DH_ANON, 0); + gnutls_set_kx_priority(state, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, 0); gnutls_set_protocol_priority( state, GNUTLS_TLS1, GNUTLS_SSL3, 0); gnutls_set_cred(state, GNUTLS_ANON, dh_cred); @@ -151,7 +150,8 @@ void print_info(GNUTLS_STATE state) if (gnutls_get_auth_info_type(state) == GNUTLS_X509PKI) { x509_info = gnutls_get_auth_info(state); if (x509_info != NULL) { - switch( gnutls_x509pki_client_get_peer_certificate_status(x509_info)) { + CertificateStatus status = gnutls_x509pki_client_get_peer_certificate_status(x509_info); + switch( status) { case GNUTLS_CERT_NOT_TRUSTED: printf("- Peer's X509 Certificate was NOT verified\n"); break; @@ -165,23 +165,24 @@ void print_info(GNUTLS_STATE state) printf("- Peer did not send any certificate.\n"); break; case GNUTLS_CERT_INVALID: - default: printf("- Peer's X509 Certificate was invalid\n"); break; } - - printf(" - Certificate info:\n"); - printf(" - Certificate version: #%d\n", gnutls_x509pki_client_get_peer_certificate_version(x509_info)); - - dn = gnutls_x509pki_client_get_peer_dn( x509_info); - if (dn!=NULL) - PRINT_DN( dn); - - dn = gnutls_x509pki_client_get_issuer_dn( x509_info); - if (dn!=NULL) { - printf(" - Certificate Issuer's info:\n"); - PRINT_DN( dn); + + if (status!=GNUTLS_CERT_NONE && status!=GNUTLS_CERT_INVALID) { + printf(" - Certificate info:\n"); + printf(" - Certificate version: #%d\n", gnutls_x509pki_client_get_peer_certificate_version(x509_info)); + + dn = gnutls_x509pki_client_get_peer_dn( x509_info); + if (dn!=NULL) + PRINT_DN( dn); + + dn = gnutls_x509pki_client_get_issuer_dn( x509_info); + if (dn!=NULL) { + printf(" - Certificate Issuer's info:\n"); + PRINT_DN( dn); + } } } } |