From 8fa8ed88631f45c133308f6db731520830713fb9 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sun, 5 Aug 2001 20:40:11 +0000 Subject: several cleanups and updates in the handshake protocol implementation iolaiiiiiCVS: ---------------------------------------------------------------------- --- lib/auth_anon.c | 75 +++++------ lib/auth_anon.h | 2 +- lib/auth_rsa.c | 195 +++++++++++++++++++---------- lib/auth_srp.c | 66 +++++----- lib/auth_srp.h | 7 +- lib/auth_x509.h | 5 +- lib/ext_srp.c | 4 +- lib/gnutls_algorithms.c | 16 +-- lib/gnutls_auth.h | 34 ++--- lib/gnutls_cert.c | 24 +++- lib/gnutls_cert.h | 2 + lib/gnutls_handshake.c | 324 +++++++++++++++++++----------------------------- lib/gnutls_int.h | 39 +++--- lib/gnutls_kx.c | 58 ++++++--- lib/gnutls_kx.h | 1 + lib/gnutls_record.c | 11 +- lib/gnutls_ui.c | 13 ++ 17 files changed, 463 insertions(+), 413 deletions(-) diff --git a/lib/auth_anon.c b/lib/auth_anon.c index 18eaf5afaf..e195d347cb 100644 --- a/lib/auth_anon.c +++ b/lib/auth_anon.c @@ -28,10 +28,10 @@ #define DEFAULT_BITS 1024 -int gen_anon_server_kx( GNUTLS_KEY, opaque**); -int gen_anon_client_kx( GNUTLS_KEY, opaque**); -int proc_anon_server_kx( GNUTLS_KEY, opaque*, int); -int proc_anon_client_kx( GNUTLS_KEY, opaque*, int); +int gen_anon_server_kx( GNUTLS_STATE, opaque**); +int gen_anon_client_kx( GNUTLS_STATE, opaque**); +int proc_anon_server_kx( GNUTLS_STATE, opaque*, int); +int proc_anon_client_kx( GNUTLS_STATE, opaque*, int); MOD_AUTH_STRUCT anon_auth_struct = { "ANON", @@ -42,6 +42,7 @@ MOD_AUTH_STRUCT anon_auth_struct = { gen_anon_client_kx, NULL, NULL, + NULL, /* certificate */ proc_anon_server_kx, NULL, @@ -57,14 +58,14 @@ MOD_AUTH_STRUCT anon_auth_struct = { 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) { + 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) { +int gen_anon_server_kx( GNUTLS_STATE state, opaque** data) { MPI x, X, g, p; int bits; size_t n_X, n_g, n_p; @@ -73,7 +74,7 @@ int gen_anon_server_kx( GNUTLS_KEY key, opaque** data) { uint8 *data_X; const ANON_SERVER_CREDENTIALS cred; - cred = _gnutls_get_cred( key, GNUTLS_ANON, NULL); + cred = _gnutls_get_cred( state->gnutls_key, GNUTLS_ANON, NULL); if (cred==NULL) { bits = DEFAULT_BITS; /* default */ } else { @@ -82,13 +83,13 @@ int gen_anon_server_kx( GNUTLS_KEY key, opaque** data) { g = gnutls_get_dh_params(&p, bits); - key->auth_info = gnutls_malloc(sizeof(ANON_SERVER_AUTH_INFO)); - if (key->auth_info==NULL) return GNUTLS_E_MEMORY_ERROR; - ((ANON_SERVER_AUTH_INFO*)key->auth_info)->dh_bits = gcry_mpi_get_nbits(p); - key->auth_info_size = sizeof(ANON_SERVER_AUTH_INFO); + state->gnutls_key->auth_info = gnutls_malloc(sizeof(ANON_SERVER_AUTH_INFO)); + if (state->gnutls_key->auth_info==NULL) return GNUTLS_E_MEMORY_ERROR; + ((ANON_SERVER_AUTH_INFO*)state->gnutls_key->auth_info)->dh_bits = gcry_mpi_get_nbits(p); + state->gnutls_key->auth_info_size = sizeof(ANON_SERVER_AUTH_INFO); X = gnutls_calc_dh_secret(&x, g, p); - key->dh_secret = x; + state->gnutls_key->dh_secret = x; gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &n_g, g); gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &n_p, p); gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &n_X, X); @@ -114,13 +115,13 @@ int gen_anon_server_kx( GNUTLS_KEY key, opaque** data) { return n_p+n_g+n_X+6; } -int gen_anon_client_kx( GNUTLS_KEY key, opaque** data) { +int gen_anon_client_kx( GNUTLS_STATE state, opaque** data) { MPI x, X; size_t n_X; int ret; - X = gnutls_calc_dh_secret(&x, key->client_g, - key->client_p); + 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); @@ -133,15 +134,15 @@ int ret; WRITEuint16( n_X, &(*data)[0]); /* calculate the key after calculating the message */ - key->KEY = gnutls_calc_dh_key(key->client_Y, x, key->client_p); + state->gnutls_key->KEY = gnutls_calc_dh_key(state->gnutls_key->client_Y, x, state->gnutls_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(&state->gnutls_key->client_Y); + _gnutls_mpi_release(&state->gnutls_key->client_p); + _gnutls_mpi_release(&state->gnutls_key->client_g); - ret = _gnutls_generate_key( key); - _gnutls_mpi_release(&key->KEY); + ret = _gnutls_generate_key( state->gnutls_key); + _gnutls_mpi_release(&state->gnutls_key->KEY); if (ret < 0) { return ret; @@ -149,7 +150,7 @@ int ret; return n_X+2; } -int proc_anon_server_kx( GNUTLS_KEY key, opaque* data, int data_size) { +int proc_anon_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; @@ -191,28 +192,28 @@ int proc_anon_server_kx( GNUTLS_KEY key, opaque* data, int data_size) { _n_g = n_g; _n_p = n_p; - if (gcry_mpi_scan(&key->client_Y, + if (gcry_mpi_scan(&state->gnutls_key->client_Y, GCRYMPI_FMT_USG, data_Y, &_n_Y) != 0) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } - if (gcry_mpi_scan(&key->client_g, + if (gcry_mpi_scan(&state->gnutls_key->client_g, GCRYMPI_FMT_USG, data_g, &_n_g) != 0) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } - if (gcry_mpi_scan(&key->client_p, + if (gcry_mpi_scan(&state->gnutls_key->client_p, GCRYMPI_FMT_USG, data_p, &_n_p) != 0) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } /* set auth_info */ - key->auth_info = gnutls_malloc(sizeof(ANON_CLIENT_AUTH_INFO)); - if (key->auth_info==NULL) return GNUTLS_E_MEMORY_ERROR; - ((ANON_CLIENT_AUTH_INFO*)key->auth_info)->dh_bits = gcry_mpi_get_nbits(key->client_p); - key->auth_info_size = sizeof(ANON_CLIENT_AUTH_INFO); + state->gnutls_key->auth_info = gnutls_malloc(sizeof(ANON_CLIENT_AUTH_INFO)); + if (state->gnutls_key->auth_info==NULL) return GNUTLS_E_MEMORY_ERROR; + ((ANON_CLIENT_AUTH_INFO*)state->gnutls_key->auth_info)->dh_bits = gcry_mpi_get_nbits(state->gnutls_key->client_p); + state->gnutls_key->auth_info_size = sizeof(ANON_CLIENT_AUTH_INFO); /* We should check signature in non-anonymous KX * this is anonymous however @@ -221,14 +222,14 @@ int proc_anon_server_kx( GNUTLS_KEY key, opaque* data, int data_size) { return 0; } -int proc_anon_client_kx( GNUTLS_KEY key, opaque* data, int data_size) { +int proc_anon_client_kx( GNUTLS_STATE state, opaque* data, int data_size) { uint16 n_Y; size_t _n_Y; MPI g, p; int bits, ret; const ANON_SERVER_CREDENTIALS cred; - cred = _gnutls_get_cred( key, GNUTLS_ANON, NULL); + cred = _gnutls_get_cred( state->gnutls_key, GNUTLS_ANON, NULL); if (cred==NULL) { bits = DEFAULT_BITS; /* default */ } else { @@ -247,22 +248,22 @@ int proc_anon_client_kx( GNUTLS_KEY key, opaque* data, int data_size) { n_Y = READuint16( &data[0]); _n_Y = n_Y; - if (gcry_mpi_scan(&key->client_Y, + if (gcry_mpi_scan(&state->gnutls_key->client_Y, GCRYMPI_FMT_USG, &data[2], &_n_Y)) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } g = gnutls_get_dh_params(&p, bits); - key->KEY = gnutls_calc_dh_key( key->client_Y, key->dh_secret, p); + state->gnutls_key->KEY = gnutls_calc_dh_key( state->gnutls_key->client_Y, state->gnutls_key->dh_secret, p); - _gnutls_mpi_release(&key->client_Y); - _gnutls_mpi_release(&key->dh_secret); + _gnutls_mpi_release(&state->gnutls_key->client_Y); + _gnutls_mpi_release(&state->gnutls_key->dh_secret); _gnutls_mpi_release(&p); _gnutls_mpi_release(&g); - ret = _gnutls_generate_key( key); - _gnutls_mpi_release(&key->KEY); + ret = _gnutls_generate_key( state->gnutls_key); + _gnutls_mpi_release(&state->gnutls_key->KEY); if (ret < 0) { return ret; diff --git a/lib/auth_anon.h b/lib/auth_anon.h index d127b35740..ef29ddee82 100644 --- a/lib/auth_anon.h +++ b/lib/auth_anon.h @@ -1,5 +1,5 @@ /* this is not to be included by gnutls_anon.c */ -extern MOD_AUTH_STRUCT anon_auth_struct; +#include typedef struct { int dh_bits; diff --git a/lib/auth_rsa.c b/lib/auth_rsa.c index 87b3f2bbc3..ee80b6cea4 100644 --- a/lib/auth_rsa.c +++ b/lib/auth_rsa.c @@ -34,10 +34,11 @@ #include #include "debug.h" -int gen_rsa_certificate(GNUTLS_KEY, opaque **); -int gen_rsa_client_kx(GNUTLS_KEY, opaque **); -int proc_rsa_client_kx(GNUTLS_KEY, opaque *, int); -int proc_rsa_certificate(GNUTLS_KEY, opaque *, int); +int gen_rsa_certificate(GNUTLS_STATE, opaque **); +int proc_rsa_cert_req(GNUTLS_STATE, opaque *, int); +int gen_rsa_client_kx(GNUTLS_STATE, opaque **); +int proc_rsa_client_kx(GNUTLS_STATE, opaque *, int); +int proc_rsa_certificate(GNUTLS_STATE, opaque *, int); MOD_AUTH_STRUCT rsa_auth_struct = { "RSA", @@ -47,14 +48,15 @@ MOD_AUTH_STRUCT rsa_auth_struct = { NULL, /* gen client kx0 */ gen_rsa_client_kx, NULL, /* gen client cert vrfy */ - NULL, /* gen server cert vrfy */ + NULL, + proc_rsa_certificate, NULL, /* proc server kx */ NULL, /* proc server kx2 */ NULL, /* proc client kx0 */ proc_rsa_client_kx, /* proc client kx */ NULL, /* proc client cert vrfy */ - NULL /* proc server cert vrfy */ + proc_rsa_cert_req /* proc server cert request */ }; typedef struct { @@ -65,7 +67,7 @@ typedef struct { /* This function extracts the RSA parameters from the given(?) certificate. */ -static int _gnutls_get_rsa_params(GNUTLS_KEY key, RSA_Params * params, +static int _gnutls_get_rsa_params( RSA_Params * params, MPI * mod, MPI * exp, gnutls_datum cert) { int ret = 0, result; @@ -212,44 +214,42 @@ static int _gnutls_get_rsa_params(GNUTLS_KEY key, RSA_Params * params, * to the gnutls_private_key structure. */ static int _gnutls_get_private_rsa_params(GNUTLS_KEY key, - gnutls_private_key pkey) + gnutls_private_key *pkey) { - key->u = gcry_mpi_copy(pkey.params[0]); - key->A = gcry_mpi_copy(pkey.params[1]); + key->u = gcry_mpi_copy(pkey->params[0]); + key->A = gcry_mpi_copy(pkey->params[1]); return 0; } -int gen_rsa_certificate(GNUTLS_KEY key, opaque ** data) +int gen_rsa_certificate(GNUTLS_STATE state, opaque ** data) { const X509PKI_CREDENTIALS cred; - int ret, i, pdatasize; + int ret, i, ind, pdatasize; opaque *pdata; gnutls_cert *apr_cert_list; - gnutls_private_key apr_pkey; + gnutls_private_key *apr_pkey; int apr_cert_list_length; - /* FIXME: This does not work for clients - yet - */ - cred = _gnutls_get_cred(key, GNUTLS_X509PKI, NULL); + cred = _gnutls_get_cred(state->gnutls_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; + 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); + apr_cert_list = cred->cert_list[ind]; + apr_cert_list_length = cred->cert_list_length[ind]; + apr_pkey = &cred->pkey[ind]; } - /* 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 < apr_cert_list_length; i++) { ret += apr_cert_list[i].raw.size + 3; @@ -274,10 +274,13 @@ int gen_rsa_certificate(GNUTLS_KEY key, opaque ** data) pdatasize = ret; /* read the rsa parameters now, since later we will - * now know which certificate we used! + * not know which certificate we used! */ - ret = _gnutls_get_private_rsa_params(key, apr_pkey); - + if (i!=0) /* if we parsed at least one certificate */ + ret = _gnutls_get_private_rsa_params(state->gnutls_key, apr_pkey); + else + ret = 0; + if (ret < 0) { gnutls_assert(); return ret; @@ -292,15 +295,13 @@ int gen_rsa_certificate(GNUTLS_KEY key, opaque ** data) return GNUTLS_E_MEMORY_ERROR; \ } -int proc_rsa_client_kx(GNUTLS_KEY key, opaque * data, int data_size) +int proc_rsa_client_kx(GNUTLS_STATE state, opaque * data, int data_size) { gnutls_sdatum plaintext; gnutls_datum ciphertext; int ret, dsize; - if (_gnutls_version_ssl3 - (_gnutls_version_get(key->version.major, key->version.minor)) - == 0) { + if (_gnutls_version_ssl3( gnutls_get_current_version( state)) == 0) { /* SSL 3.0 */ ciphertext.data = data; ciphertext.size = data_size; @@ -310,8 +311,8 @@ int proc_rsa_client_kx(GNUTLS_KEY key, opaque * data, int data_size) ciphertext.size = GMIN(dsize, data_size); } ret = - _gnutls_pkcs1_rsa_decrypt(&plaintext, ciphertext, key->u, - key->A, 2); /* btype==2 */ + _gnutls_pkcs1_rsa_decrypt(&plaintext, ciphertext, state->gnutls_key->u, + state->gnutls_key->A, 2); /* btype==2 */ if (ret < 0) { /* in case decryption fails then don't inform @@ -319,36 +320,40 @@ int proc_rsa_client_kx(GNUTLS_KEY key, opaque * data, int data_size) * attack against pkcs-1 formating). */ gnutls_assert(); - RANDOMIZE_KEY(key->key, secure_malloc); + RANDOMIZE_KEY(state->gnutls_key->key, secure_malloc); } else { ret = 0; if (plaintext.size != TLS_MASTER_SIZE) { /* WOW */ - RANDOMIZE_KEY(key->key, secure_malloc); + RANDOMIZE_KEY(state->gnutls_key->key, secure_malloc); } else { - if (key->version.major != plaintext.data[0]) + GNUTLS_Version ver; + + ver = gnutls_get_current_version( state); + + if ( _gnutls_version_get_major( ver) != plaintext.data[0]) ret = GNUTLS_E_DECRYPTION_FAILED; - if (key->version.minor != plaintext.data[1]) + if ( _gnutls_version_get_minor( ver) != plaintext.data[1]) ret = GNUTLS_E_DECRYPTION_FAILED; if (ret != 0) { - _gnutls_mpi_release(&key->B); - _gnutls_mpi_release(&key->u); - _gnutls_mpi_release(&key->A); + _gnutls_mpi_release(&state->gnutls_key->B); + _gnutls_mpi_release(&state->gnutls_key->u); + _gnutls_mpi_release(&state->gnutls_key->A); gnutls_assert(); return ret; } - key->key.data = plaintext.data; - key->key.size = plaintext.size; + state->gnutls_key->key.data = plaintext.data; + state->gnutls_key->key.size = plaintext.size; } } - _gnutls_mpi_release(&key->A); - _gnutls_mpi_release(&key->B); - _gnutls_mpi_release(&key->u); + _gnutls_mpi_release(&state->gnutls_key->A); + _gnutls_mpi_release(&state->gnutls_key->B); + _gnutls_mpi_release(&state->gnutls_key->u); return 0; } -int proc_rsa_certificate(GNUTLS_KEY key, opaque * data, int data_size) +int proc_rsa_certificate(GNUTLS_STATE state, opaque * data, int data_size) { int size, len, ret; opaque *p = data; @@ -361,18 +366,19 @@ int proc_rsa_certificate(GNUTLS_KEY key, opaque * data, int data_size) gnutls_datum tmp; CertificateStatus verify; - cred = _gnutls_get_cred(key, GNUTLS_X509PKI, NULL); + cred = _gnutls_get_cred(state->gnutls_key, GNUTLS_X509PKI, NULL); if (cred == NULL) { gnutls_assert(); return GNUTLS_E_INSUFICIENT_CRED; } - key->auth_info = gnutls_calloc(1, sizeof(X509PKI_CLIENT_AUTH_INFO)); - if (key->auth_info == NULL) { + if (state->gnutls_key->auth_info==NULL) + state->gnutls_key->auth_info = gnutls_calloc(1, sizeof(X509PKI_CLIENT_AUTH_INFO)); + if (state->gnutls_key->auth_info == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } - key->auth_info_size = sizeof(X509PKI_CLIENT_AUTH_INFO); + state->gnutls_key->auth_info_size = sizeof(X509PKI_CLIENT_AUTH_INFO); DECR_LEN(dsize, 3); size = READuint24(p); @@ -383,7 +389,7 @@ int proc_rsa_certificate(GNUTLS_KEY key, opaque * data, int data_size) return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - info = key->auth_info; + info = state->gnutls_key->auth_info; i = dsize; len = READuint24(p); @@ -440,7 +446,7 @@ int proc_rsa_certificate(GNUTLS_KEY key, opaque * data, int data_size) /* store the required parameters for the handshake */ if ((ret = - _gnutls_get_rsa_params(key, NULL, &key->A, &key->u, + _gnutls_get_rsa_params( NULL, &state->gnutls_key->A, &state->gnutls_key->u, peer_certificate_list[0].raw)) < 0) { gnutls_assert(); gnutls_free( peer_certificate_list); @@ -463,13 +469,14 @@ int proc_rsa_certificate(GNUTLS_KEY key, opaque * data, int data_size) /* return RSA(random) using the peers public key */ -int gen_rsa_client_kx(GNUTLS_KEY key, opaque ** data) +int gen_rsa_client_kx(GNUTLS_STATE state, opaque ** data) { - X509PKI_CLIENT_AUTH_INFO *auth = key->auth_info; + X509PKI_CLIENT_AUTH_INFO *auth = state->gnutls_key->auth_info; gnutls_datum sdata; /* data to send */ MPI pkey, n; int ret; - + GNUTLS_Version ver; + if (auth == NULL) { /* this shouldn't have happened. The proc_certificate * function should have detected that. @@ -478,24 +485,25 @@ int gen_rsa_client_kx(GNUTLS_KEY key, opaque ** data) return GNUTLS_E_INSUFICIENT_CRED; } - RANDOMIZE_KEY(key->key, secure_malloc); - key->key.data[0] = key->version.major; - key->key.data[1] = key->version.minor; + RANDOMIZE_KEY(state->gnutls_key->key, secure_malloc); + + ver = gnutls_get_current_version( state); + + state->gnutls_key->key.data[0] = _gnutls_version_get_major( ver); + state->gnutls_key->key.data[1] = _gnutls_version_get_minor( ver); if ((ret = - _gnutls_pkcs1_rsa_encrypt(&sdata, key->key, key->u, key->A, 2)) < 0) { + _gnutls_pkcs1_rsa_encrypt(&sdata, state->gnutls_key->key, state->gnutls_key->u, state->gnutls_key->A, 2)) < 0) { gnutls_assert(); _gnutls_mpi_release(&pkey); _gnutls_mpi_release(&n); return ret; } - _gnutls_mpi_release(&key->A); - _gnutls_mpi_release(&key->u); + _gnutls_mpi_release(&state->gnutls_key->A); + _gnutls_mpi_release(&state->gnutls_key->u); - if (_gnutls_version_ssl3 - (_gnutls_version_get(key->version.major, key->version.minor)) - == 0) { + if (_gnutls_version_ssl3( ver) == 0) { /* SSL 3.0 */ *data = sdata.data; return sdata.size; @@ -513,3 +521,62 @@ int gen_rsa_client_kx(GNUTLS_KEY key, opaque ** data) } } + +#define RSA_SIGN 1 + +int proc_rsa_cert_req(GNUTLS_STATE state, opaque * data, int data_size) +{ + int size; + opaque *p = data; + const X509PKI_CREDENTIALS cred; + int dsize = data_size; + int i; + int found; + + cred = _gnutls_get_cred(state->gnutls_key, GNUTLS_X509PKI, NULL); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFICIENT_CRED; + } + + 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)); + 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); + + DECR_LEN(dsize, 1); + size = p[0]; + p += 1; + + found = 0; + for (i=0;ib -#define B key->B -#define _a key->a -#define A key->A -#define N key->client_p -#define G key->client_g -#define V key->x -#define S key->KEY +#define _b state->gnutls_key->b +#define B state->gnutls_key->B +#define _a state->gnutls_key->a +#define A state->gnutls_key->A +#define N state->gnutls_key->client_p +#define G state->gnutls_key->client_g +#define V state->gnutls_key->x +#define S state->gnutls_key->KEY /* Send the first key exchange message ( g, n, s) and append the verifier algorithm number */ -int gen_srp_server_hello(GNUTLS_KEY key, opaque ** data) +int gen_srp_server_hello(GNUTLS_STATE state, opaque ** data) { size_t n_g, n_n, n_s; size_t ret; @@ -72,11 +74,11 @@ int gen_srp_server_hello(GNUTLS_KEY key, opaque ** data) GNUTLS_SRP_PWD_ENTRY *pwd_entry; int err; - if (key->auth_info == NULL) { + if (state->gnutls_key->auth_info == NULL) { return GNUTLS_E_INSUFICIENT_CRED; } - pwd_entry = _gnutls_srp_pwd_read_entry( key, ((SRP_SERVER_AUTH_INFO*)key->auth_info)->username, &err); + pwd_entry = _gnutls_srp_pwd_read_entry( state->gnutls_key, ((SRP_SERVER_AUTH_INFO*)state->gnutls_key->auth_info)->username, &err); if (pwd_entry == NULL) { if (err==0) @@ -151,7 +153,7 @@ int gen_srp_server_hello(GNUTLS_KEY key, opaque ** data) } /* send the second key exchange message */ -int gen_srp_server_kx2(GNUTLS_KEY key, opaque ** data) +int gen_srp_server_kx2(GNUTLS_STATE state, opaque ** data) { int ret; size_t n_b; @@ -173,18 +175,18 @@ int gen_srp_server_kx2(GNUTLS_KEY key, opaque ** data) WRITEuint16( n_b, data_b); /* calculate u */ - key->u = _gnutls_calc_srp_u(B); + state->gnutls_key->u = _gnutls_calc_srp_u(B); /* S = (A * v^u) ^ b % N */ - S = _gnutls_calc_srp_S1( A, _b, key->u, V, N); + S = _gnutls_calc_srp_S1( A, _b, state->gnutls_key->u, V, N); mpi_release(A); mpi_release(_b); mpi_release(V); - mpi_release(key->u); + mpi_release(state->gnutls_key->u); mpi_release(B); - ret = _gnutls_generate_key( key); + ret = _gnutls_generate_key( state->gnutls_key); _gnutls_mpi_release( &S); if (ret < 0) @@ -195,14 +197,14 @@ int gen_srp_server_kx2(GNUTLS_KEY key, opaque ** data) /* return A = g^a % N */ -int gen_srp_client_kx0(GNUTLS_KEY key, opaque ** data) +int gen_srp_client_kx0(GNUTLS_STATE state, opaque ** data) { size_t n_a; uint8 *data_a; char *username; char *password; const SRP_CLIENT_CREDENTIALS cred = - _gnutls_get_cred(key, GNUTLS_SRP, NULL); + _gnutls_get_cred(state->gnutls_key, GNUTLS_SRP, NULL); if (cred == NULL) return GNUTLS_E_INSUFICIENT_CRED; @@ -232,7 +234,7 @@ int gen_srp_client_kx0(GNUTLS_KEY key, opaque ** data) } /* receive the first key exchange message ( g, n, s) */ -int proc_srp_server_hello(GNUTLS_KEY key, const opaque * data, int data_size) +int proc_srp_server_hello(GNUTLS_STATE state, const opaque * data, int data_size) { uint16 n_s, n_g, n_n; size_t _n_s, _n_g, _n_n; @@ -245,7 +247,7 @@ int proc_srp_server_hello(GNUTLS_KEY key, const opaque * data, int data_size) char *username; char *password; const SRP_CLIENT_CREDENTIALS cred = - _gnutls_get_cred(key, GNUTLS_SRP, NULL); + _gnutls_get_cred(state->gnutls_key, GNUTLS_SRP, NULL); if (cred == NULL) return GNUTLS_E_INSUFICIENT_CRED; @@ -310,7 +312,7 @@ int proc_srp_server_hello(GNUTLS_KEY key, const opaque * data, int data_size) */ _gnutls_calc_srp_x( username, password, (opaque*)data_s, n_s, pwd_algo, &_n_g, hd); - if (gcry_mpi_scan(&key->x, GCRYMPI_FMT_USG, hd, &_n_g) != 0) { + if (gcry_mpi_scan(&state->gnutls_key->x, GCRYMPI_FMT_USG, hd, &_n_g) != 0) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } @@ -319,7 +321,7 @@ int proc_srp_server_hello(GNUTLS_KEY key, const opaque * data, int data_size) } /* just read A and put it to state */ -int proc_srp_client_kx0(GNUTLS_KEY key, opaque * data, int data_size) +int proc_srp_client_kx0(GNUTLS_STATE state, opaque * data, int data_size) { size_t _n_A; @@ -334,7 +336,7 @@ 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) +int proc_srp_server_kx2(GNUTLS_STATE state, opaque * data, int data_size) { size_t _n_B; int ret; @@ -347,18 +349,18 @@ int proc_srp_server_kx2(GNUTLS_KEY key, opaque * data, int data_size) } /* calculate u */ - key->u = _gnutls_calc_srp_u( B); + state->gnutls_key->u = _gnutls_calc_srp_u( B); /* S = (B - g^x) ^ (a + u * x) % N */ - S = _gnutls_calc_srp_S2( B, G, key->x, _a, key->u, N); + S = _gnutls_calc_srp_S2( B, G, state->gnutls_key->x, _a, state->gnutls_key->u, N); mpi_release(A); mpi_release(_b); mpi_release(V); - mpi_release(key->u); + mpi_release(state->gnutls_key->u); mpi_release(B); - ret = _gnutls_generate_key( key); + ret = _gnutls_generate_key( state->gnutls_key); _gnutls_mpi_release(&S); if (ret < 0) diff --git a/lib/auth_srp.h b/lib/auth_srp.h index ea7e683fe0..0d182daa78 100644 --- a/lib/auth_srp.h +++ b/lib/auth_srp.h @@ -1,5 +1,4 @@ -/* this is not to be included by gnutls_anon.c */ -extern MOD_AUTH_STRUCT srp_auth_struct; +#include typedef struct { char* username; @@ -20,5 +19,5 @@ typedef struct { char username[256]; } SRP_SERVER_AUTH_INFO; -int gen_srp_server_hello(GNUTLS_KEY, opaque **); -int proc_srp_server_hello(GNUTLS_KEY, const opaque *, int); +int proc_srp_server_hello(GNUTLS_STATE state, const opaque * data, int data_size); +int gen_srp_server_hello(GNUTLS_STATE state, opaque ** data); diff --git a/lib/auth_x509.h b/lib/auth_x509.h index e8e139caab..80d7d2efc7 100644 --- a/lib/auth_x509.h +++ b/lib/auth_x509.h @@ -1,9 +1,7 @@ #ifndef AUTH_X509_H # define AUTH_X509_H # include "gnutls_cert.h" - -/* this is not to be included by gnutls_anon.c */ -extern MOD_AUTH_STRUCT rsa_auth_struct; +# include "gnutls_auth.h" /* This structure may be complex but, it's the only way to * support a server that has multiple certificates @@ -42,6 +40,7 @@ typedef struct { time_t peer_certificate_expiration_time; char subjectAltName[X509_CN_SIZE]; unsigned char keyUsage; + int certificate_requested; } X509PKI_CLIENT_AUTH_INFO; void _gnutls_copy_x509_client_auth_info( X509PKI_CLIENT_AUTH_INFO* info, gnutls_cert* cert, CertificateStatus verify); diff --git a/lib/ext_srp.c b/lib/ext_srp.c index 50dc7e8bb7..be2034bc0e 100644 --- a/lib/ext_srp.c +++ b/lib/ext_srp.c @@ -58,7 +58,7 @@ int _gnutls_srp_recv_params( GNUTLS_STATE state, const opaque* data, int data_si } } else { /* client side reading server hello extensions */ if (state->gnutls_internals.resumed==RESUME_FALSE) - return proc_srp_server_hello( state->gnutls_key, data, data_size); + return proc_srp_server_hello( state, data, data_size); else /* we do not need to process this if * we are resuming. */ @@ -95,7 +95,7 @@ int _gnutls_srp_send_params( GNUTLS_STATE state, opaque** data) { return 0; /* no data to send */ if (state->gnutls_internals.resumed==RESUME_FALSE) - return gen_srp_server_hello( state->gnutls_key, data); + return gen_srp_server_hello( state, data); else return 0; } diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c index 66331682e5..8163801ffb 100644 --- a/lib/gnutls_algorithms.c +++ b/lib/gnutls_algorithms.c @@ -23,12 +23,6 @@ #include "gnutls_errors.h" #include "gnutls_cert.h" -/* include all the kx handler's definitions */ -#include "auth_anon.h" -/* #include "auth_dhe_dss.h" */ -#include "auth_srp.h" -#include "auth_x509.h" - #define MAX_CIPHER 256 #define MAX_MAC 256 #define MAX_KX 256 @@ -187,6 +181,10 @@ 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 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), @@ -787,12 +785,6 @@ int _gnutls_version_get_major(GNUTLS_Version version) } /* Version Functions */ -int _gnutls_version_cmp(GNUTLS_Version ver1, GNUTLS_Version ver2) -{ - if (ver1 != ver2) - return 1; - return 0; -} int _gnutls_version_is_supported(GNUTLS_STATE state, diff --git a/lib/gnutls_auth.h b/lib/gnutls_auth.h index bffd973ff5..8017c50eb8 100644 --- a/lib/gnutls_auth.h +++ b/lib/gnutls_auth.h @@ -1,23 +1,23 @@ #ifndef GNUTLS_AUTH_H - #define GNUTLS_AUTH_H -typedef struct { +# define GNUTLS_AUTH_H + +typedef struct MOD_AUTH_STRUCT_INT { char* name; /* null terminated */ - int (*gnutls_generate_certificate)( GNUTLS_KEY, opaque**); - int (*gnutls_generate_server_kx)( GNUTLS_KEY, opaque**); - int (*gnutls_generate_server_kx2)( GNUTLS_KEY, opaque**); /* used in SRP */ - int (*gnutls_generate_client_kx0)( GNUTLS_KEY, opaque**); - int (*gnutls_generate_client_kx)( GNUTLS_KEY, opaque**); /* used in SRP */ - int (*gnutls_generate_client_cert_vrfy) ( GNUTLS_KEY, opaque**); - int (*gnutls_generate_server_cert_vrfy) ( GNUTLS_KEY, opaque**); + int (*gnutls_generate_certificate)( GNUTLS_STATE, opaque**); + int (*gnutls_generate_server_kx)( GNUTLS_STATE, opaque**); + int (*gnutls_generate_server_kx2)( GNUTLS_STATE, opaque**); /* used in SRP */ + int (*gnutls_generate_client_kx0)( GNUTLS_STATE, opaque**); + int (*gnutls_generate_client_kx)( GNUTLS_STATE, opaque**); /* used in SRP */ + int (*gnutls_generate_client_cert_vrfy) ( GNUTLS_STATE, opaque**); + int (*gnutls_generate_server_certificate_request) ( GNUTLS_STATE, opaque**); - int (*gnutls_process_certificate)( GNUTLS_KEY, opaque*, int); - int (*gnutls_process_server_kx)( GNUTLS_KEY, opaque*, int); - int (*gnutls_process_server_kx2)( GNUTLS_KEY, opaque*, int); - int (*gnutls_process_client_kx0)( GNUTLS_KEY, opaque*, int); - int (*gnutls_process_client_kx)( GNUTLS_KEY, opaque*, int); - int (*gnutls_process_client_cert_vrfy) ( GNUTLS_KEY, opaque*, int); - int (*gnutls_process_server_cert_vrfy) ( GNUTLS_KEY, opaque*, int); + int (*gnutls_process_certificate)( GNUTLS_STATE, opaque*, int); + int (*gnutls_process_server_kx)( GNUTLS_STATE, opaque*, int); + int (*gnutls_process_server_kx2)( GNUTLS_STATE, opaque*, int); + int (*gnutls_process_client_kx0)( GNUTLS_STATE, opaque*, int); + int (*gnutls_process_client_kx)( GNUTLS_STATE, opaque*, int); + int (*gnutls_process_client_cert_vrfy) ( GNUTLS_STATE, opaque*, int); + int (*gnutls_process_server_certificate_request) ( GNUTLS_STATE, opaque*, int); } MOD_AUTH_STRUCT; - #endif diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c index 8a66fb4528..81604fa1ac 100644 --- a/lib/gnutls_cert.c +++ b/lib/gnutls_cert.c @@ -825,7 +825,7 @@ int _gnutls_cert_supported_kx(gnutls_cert * cert, KXAlgorithm ** alg, return 0; } -/* finds a certificate in the cert list that contains +/* finds a certificate in the cert lists that contains * common_name (or subjectAltName) field similar to name */ gnutls_cert *_gnutls_find_cert(gnutls_cert ** cert_list, @@ -835,7 +835,7 @@ gnutls_cert *_gnutls_find_cert(gnutls_cert ** cert_list, int i; for (i = 0; i < cert_list_length; i++) { - if (cert_list[i][0].cert_info.common_name[0] != 0) { + if (cert_list[i][0].cert_info.common_name[0] != 0 || cert_list[i][0].subjectAltName[0]!=0) { if (strcasecmp(cert_list[i][0].cert_info.common_name, name) == 0 || strcasecmp(cert_list[i][0].subjectAltName, name) == 0) { cert = &cert_list[i][0]; break; @@ -845,3 +845,23 @@ gnutls_cert *_gnutls_find_cert(gnutls_cert ** cert_list, return cert; } +/* finds the index of a certificate in the cert lists that contains + * common_name (or subjectAltName) field similar to name + */ +int _gnutls_find_cert_list_index(gnutls_cert ** cert_list, + int cert_list_length, char *name) +{ + int index = 0; + int i; + + for (i = 0; i < cert_list_length; i++) { + if (cert_list[i][0].cert_info.common_name[0] != 0 || cert_list[i][0].subjectAltName[0]!=0) { + if (strcasecmp(cert_list[i][0].cert_info.common_name, name) == 0 || strcasecmp(cert_list[i][0].subjectAltName, name) == 0) { + index = i; + break; + } + } + } + return index; +} + diff --git a/lib/gnutls_cert.h b/lib/gnutls_cert.h index 41057f94ae..b0bd67ab0b 100644 --- a/lib/gnutls_cert.h +++ b/lib/gnutls_cert.h @@ -51,6 +51,8 @@ int _gnutls_cert_supported_kx(gnutls_cert* cert, KXAlgorithm **alg, int *alg_siz PKAlgorithm _gnutls_map_pk_get_pk(KXAlgorithm kx_algorithm); int _gnutls_cert2gnutlsCert(gnutls_cert * gCert, gnutls_datum derCert); gnutls_cert* _gnutls_find_cert( gnutls_cert** cert_list, int cert_list_length, char* name); +int _gnutls_find_cert_list_index(gnutls_cert ** cert_list, + int cert_list_length, char *name); #define MAX_INT_DIGITS 4 void _gnutls_int2str(int k, char* data); diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index 317bca45c8..f934a1b470 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -51,7 +51,7 @@ static int _gnutls_server_SelectSuite(GNUTLS_STATE state, opaque ret[2], char *data, int datalen); int _gnutls_server_SelectCompMethod(GNUTLS_STATE state, - CompressionMethod * ret, opaque * data, + CompressionMethod * ret, opaque * data, int datalen); /* this will copy the required values for resuming to @@ -79,12 +79,12 @@ static void resume_copy_required_values(GNUTLS_STATE state) state->gnutls_internals.compression_method = state->gnutls_internals.resumed_security_parameters. - read_compression_algorithm; /* or write_compression_algorithm - * they are the same - */ + read_compression_algorithm; /* or write_compression_algorithm + * they are the same + */ state->security_parameters.entity = state->gnutls_internals.resumed_security_parameters.entity; - + memcpy(state->security_parameters.session_id, state->gnutls_internals.resumed_security_parameters. session_id, sizeof(state->security_parameters.session_id)); @@ -99,18 +99,12 @@ void _gnutls_set_server_random(GNUTLS_STATE state, uint8 * random) { memcpy(state->security_parameters.server_random, random, TLS_RANDOM_SIZE); - if (state->gnutls_key != NULL) - memcpy(state->gnutls_key->server_random, random, - TLS_RANDOM_SIZE); } void _gnutls_set_client_random(GNUTLS_STATE state, uint8 * random) { memcpy(state->security_parameters.client_random, random, TLS_RANDOM_SIZE); - if (state->gnutls_key != NULL) - memcpy(state->gnutls_key->client_random, random, - TLS_RANDOM_SIZE); } /* Calculate The SSL3 Finished message */ @@ -248,12 +242,11 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, if (state->gnutls_internals.v2_hello != 0) { /* version 2.0 */ return _gnutls_read_client_hello_v2(state, data, datalen); } - DECR_LEN(len, 2); #ifdef HANDSHAKE_DEBUG - _gnutls_log( "Client's version: %d.%d\n", data[pos], - data[pos + 1]); + _gnutls_log("Client's version: %d.%d\n", data[pos], + data[pos + 1]); #endif version = _gnutls_version_get(data[pos], data[pos + 1]); @@ -263,7 +256,7 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, /* If he requested something we do not support * then we send him the lowest we support. */ - ver = _gnutls_version_lowest( state); + ver = _gnutls_version_lowest(state); } else { ver = version; } @@ -271,11 +264,10 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, /* he should have send us the highest version * he supports. */ - if (ver==GNUTLS_VERSION_UNKNOWN || ver > version) { + if (ver == GNUTLS_VERSION_UNKNOWN || ver > version) { gnutls_assert(); return GNUTLS_E_UNSUPPORTED_VERSION_PACKET; } - _gnutls_set_current_version(state, ver); pos += 2; @@ -297,7 +289,6 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - DECR_LEN(len, session_id_len); ret = _gnutls_server_restore_session(state, &data[pos], @@ -332,8 +323,6 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, gnutls_assert(); return ret; } - - /* check if the credentials (username, public key etc. are ok) */ if (_gnutls_get_kx_cred @@ -344,7 +333,6 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, gnutls_assert(); return GNUTLS_E_INSUFICIENT_CRED; } - /* set the MOD_AUTH_STRUCT to the appropriate struct * according to the KX algorithm. This is needed since all the * handshake functions are read from there; @@ -356,12 +344,11 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, if (state->gnutls_internals.auth_struct == NULL) { #ifdef HANDSHAKE_DEBUG _gnutls_log( - "Cannot find the appropriate handler for the KX algorithm\n"); + "Cannot find the appropriate handler for the KX algorithm\n"); #endif gnutls_assert(); return GNUTLS_E_UNKNOWN_CIPHER_TYPE; } - DECR_LEN(len, 1); memcpy(&z, &data[pos++], 1); /* z is the number of compression methods */ @@ -371,9 +358,9 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, compression_method, &data[pos], z); #ifdef HANDSHAKE_DEBUG - _gnutls_log( "Selected Compression Method: %s\n", - gnutls_compression_get_name(state->gnutls_internals. - compression_method)); + _gnutls_log("Selected Compression Method: %s\n", + gnutls_compression_get_name(state->gnutls_internals. + compression_method)); #endif pos += z; @@ -381,13 +368,11 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, gnutls_assert(); return ret; } - - ret = _gnutls_parse_extensions(state, &data[pos], len); /* len is the rest of the parsed length */ + ret = _gnutls_parse_extensions(state, &data[pos], len); /* len is the rest of the parsed length */ if (ret < 0) { gnutls_assert(); return ret; } - return ret; } @@ -411,7 +396,7 @@ int _gnutls_send_finished(SOCKET cd, GNUTLS_STATE state) } else { /* TLS 1.0 */ data = _gnutls_finished(state, - state->security_parameters.entity, 0); + state->security_parameters.entity, 0); data_size = 12; } @@ -444,7 +429,6 @@ int _gnutls_recv_finished(SOCKET cd, GNUTLS_STATE state) gnutls_assert(); return ret; } - if (_gnutls_version_ssl3(state->connection_state.version) == 0) { data_size = 36; } else { @@ -455,7 +439,6 @@ int _gnutls_recv_finished(SOCKET cd, GNUTLS_STATE state) gnutls_assert(); return GNUTLS_E_ERROR_IN_FINISHED_PACKET; } - if (_gnutls_version_ssl3(state->connection_state.version) == 0) { /* skip the bytes from the last message */ data = @@ -476,7 +459,6 @@ int _gnutls_recv_finished(SOCKET cd, GNUTLS_STATE state) gnutls_assert(); ret = GNUTLS_E_ERROR_IN_FINISHED_PACKET; } - gnutls_free(data); gnutls_free(vrfy); @@ -501,16 +483,16 @@ static int _gnutls_server_SelectSuite(GNUTLS_STATE state, opaque ret[2], x = _gnutls_remove_unwanted_ciphersuites(state, &ciphers, x); #ifdef HANDSHAKE_DEBUG - _gnutls_log( "Requested cipher suites: \n"); + _gnutls_log("Requested cipher suites: \n"); for (j = 0; j < datalen; j += 2) - _gnutls_log( "\t%s\n", - _gnutls_cipher_suite_get_name(* - ((GNUTLS_CipherSuite - *) & data[j]))); - _gnutls_log( "Supported cipher suites: \n"); + _gnutls_log("\t%s\n", + _gnutls_cipher_suite_get_name(* + ((GNUTLS_CipherSuite + *) & data[j]))); + _gnutls_log("Supported cipher suites: \n"); for (j = 0; j < x; j++) - _gnutls_log( "\t%s\n", - _gnutls_cipher_suite_get_name(ciphers[j])); + _gnutls_log("\t%s\n", + _gnutls_cipher_suite_get_name(ciphers[j])); #endif memset(ret, '\0', 2); @@ -519,10 +501,10 @@ static int _gnutls_server_SelectSuite(GNUTLS_STATE state, opaque ret[2], if (memcmp(ciphers[i].CipherSuite, &data[j], 2) == 0) { #ifdef HANDSHAKE_DEBUG - _gnutls_log( "Selected cipher suite: "); - _gnutls_log( "%s\n", - _gnutls_cipher_suite_get_name(* - ((GNUTLS_CipherSuite *) & data[j]))); + _gnutls_log("Selected cipher suite: "); + _gnutls_log("%s\n", + _gnutls_cipher_suite_get_name(* + ((GNUTLS_CipherSuite *) & data[j]))); #endif memcpy(ret, ciphers[i].CipherSuite, 2); gnutls_free(ciphers); @@ -542,7 +524,7 @@ static int _gnutls_server_SelectSuite(GNUTLS_STATE state, opaque ret[2], /* This selects the best supported compression method from the ones provided */ int _gnutls_server_SelectCompMethod(GNUTLS_STATE state, - CompressionMethod * ret, opaque * data, + CompressionMethod * ret, opaque * data, int datalen) { int x, i, j; @@ -592,8 +574,8 @@ int _gnutls_send_handshake(SOCKET cd, GNUTLS_STATE state, void *i_data, memcpy(&data[pos], i_data, i_datasize - 4); #ifdef HANDSHAKE_DEBUG - _gnutls_log( "Handshake: %s was send [%ld bytes]\n", - _gnutls_handshake2str(type), i_datasize); + _gnutls_log("Handshake: %s was send [%ld bytes]\n", + _gnutls_handshake2str(type), i_datasize); #endif /* Here we keep the handshake messages in order to hash them later! @@ -633,14 +615,13 @@ int _gnutls_recv_handshake(SOCKET cd, GNUTLS_STATE state, uint8 ** data, if (ret <= 0) { gnutls_assert(); gnutls_free(dataptr); - return (ret < 0)?ret:GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + return (ret < 0) ? ret : GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } if (ret != SSL2_HEADERS) { gnutls_assert(); gnutls_free(dataptr); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - if (state->gnutls_internals.v2_hello == 0 || type != GNUTLS_CLIENT_HELLO) { @@ -652,14 +633,13 @@ int _gnutls_recv_handshake(SOCKET cd, GNUTLS_STATE state, uint8 ** data, if (ret <= 0) { gnutls_assert(); gnutls_free(dataptr); - return (ret<0)?ret:GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + return (ret < 0) ? ret : GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } if (ret != HANDSHAKE_HEADERS_SIZE - SSL2_HEADERS) { gnutls_assert(); gnutls_free(dataptr); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - recv_type = dataptr[0]; if (recv_type != type) { @@ -667,13 +647,12 @@ int _gnutls_recv_handshake(SOCKET cd, GNUTLS_STATE state, uint8 ** data, gnutls_free(dataptr); return GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET; } - length32 = READuint24(&dataptr[1]); #ifdef HANDSHAKE_DEBUG - _gnutls_log( "Handshake: %s was received [%ld bytes]\n", - _gnutls_handshake2str(dataptr[0]), - length32 + HANDSHAKE_HEADERS_SIZE); + _gnutls_log("Handshake: %s was received [%ld bytes]\n", + _gnutls_handshake2str(dataptr[0]), + length32 + HANDSHAKE_HEADERS_SIZE); #endif @@ -685,12 +664,12 @@ int _gnutls_recv_handshake(SOCKET cd, GNUTLS_STATE state, uint8 ** data, recv_type = dataptr[0]; #ifdef HANDSHAKE_DEBUG _gnutls_log( - "Handshake: %s(v2) was received [%ld bytes]\n", - _gnutls_handshake2str(recv_type), - length32 + handshake_headers); + "Handshake: %s(v2) was received [%ld bytes]\n", + _gnutls_handshake2str(recv_type), + length32 + handshake_headers); #endif - if (recv_type != GNUTLS_CLIENT_HELLO) { /* it should be one or nothing */ + if (recv_type != GNUTLS_CLIENT_HELLO) { /* it should be one or nothing */ gnutls_assert(); return GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET; } @@ -701,7 +680,6 @@ int _gnutls_recv_handshake(SOCKET cd, GNUTLS_STATE state, uint8 ** data, gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } - if (length32 > 0 && data != NULL) *data = gnutls_malloc(length32); @@ -757,12 +735,8 @@ int _gnutls_recv_handshake(SOCKET cd, GNUTLS_STATE state, uint8 ** data, break; case GNUTLS_CERTIFICATE_REQUEST: #ifdef HANDSHAKE_DEBUG - _gnutls_log( "Requested Client Certificate!\n"); + _gnutls_log("Requested Client Certificate!\n"); #endif - /* FIXME: just ignore that message for the time being - * we have to parse it and the store the needed information - */ - state->gnutls_internals.certificate_requested = 1; ret = length32; break; default: @@ -800,7 +774,6 @@ int gnutls_rehandshake(SOCKET cd, GNUTLS_STATE state) gnutls_assert(); return ret; } - /* begin handshake procedure again */ ret = gnutls_handshake(cd, state); @@ -825,8 +798,7 @@ static int _gnutls_read_server_hello(GNUTLS_STATE state, char *data, return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } #ifdef HANDSHAKE_DEBUG - _gnutls_log( "Server's version: %d.%d\n", data[pos], - data[pos + 1]); + _gnutls_log("Server's version: %d.%d\n", data[pos], data[pos + 1]); #endif DECR_LEN(len, 2); version = _gnutls_version_get(data[pos], data[pos + 1]); @@ -849,13 +821,12 @@ static int _gnutls_read_server_hello(GNUTLS_STATE state, char *data, gnutls_assert(); return GNUTLS_E_UNSUPPORTED_VERSION_PACKET; } - DECR_LEN(len, session_id_len); #ifdef HANDSHAKE_DEBUG - _gnutls_log( "SessionID length: %d\n", session_id_len); - _gnutls_log( "SessionID: %s\n", - _gnutls_bin2hex(&data[pos], session_id_len)); + _gnutls_log("SessionID length: %d\n", session_id_len); + _gnutls_log("SessionID: %s\n", + _gnutls_bin2hex(&data[pos], session_id_len)); #endif if ((state->gnutls_internals.resumed_security_parameters. session_id_size > 0) @@ -877,7 +848,7 @@ static int _gnutls_read_server_hello(GNUTLS_STATE state, char *data, return 0; } else { /* keep the new session id */ - state->gnutls_internals.resumed = RESUME_FALSE; /* we are not resuming */ + state->gnutls_internals.resumed = RESUME_FALSE; /* we are not resuming */ state->security_parameters.session_id_size = session_id_len; memcpy(state->security_parameters.session_id, @@ -901,17 +872,16 @@ static int _gnutls_read_server_hello(GNUTLS_STATE state, char *data, gnutls_assert(); return GNUTLS_E_UNKNOWN_CIPHER_TYPE; } - memcpy(state->security_parameters. current_cipher_suite.CipherSuite, cipher_suite.CipherSuite, 2); #ifdef HANDSHAKE_DEBUG - _gnutls_log( "Selected cipher suite: "); - _gnutls_log( "%s\n", - _gnutls_cipher_suite_get_name(state-> - security_parameters. - current_cipher_suite)); + _gnutls_log("Selected cipher suite: "); + _gnutls_log("%s\n", + _gnutls_cipher_suite_get_name(state-> + security_parameters. + current_cipher_suite)); #endif /* check if the credentials (username, public key etc. are ok). @@ -926,7 +896,6 @@ static int _gnutls_read_server_hello(GNUTLS_STATE state, char *data, gnutls_assert(); return GNUTLS_E_INSUFICIENT_CRED; } - /* set the MOD_AUTH_STRUCT to the appropriate struct * according to the KX algorithm. This is needed since all the * handshake functions are read from there; @@ -937,13 +906,11 @@ static int _gnutls_read_server_hello(GNUTLS_STATE state, char *data, if (state->gnutls_internals.auth_struct == NULL) { #ifdef HANDSHAKE_DEBUG _gnutls_log( - "Cannot find the appropriate handler for the KX algorithm\n"); + "Cannot find the appropriate handler for the KX algorithm\n"); #endif gnutls_assert(); return GNUTLS_E_UNKNOWN_CIPHER_TYPE; } - - /* move to compression */ z = 1; DECR_LEN(len, 1); @@ -969,18 +936,16 @@ static int _gnutls_read_server_hello(GNUTLS_STATE state, char *data, gnutls_free(cipher_suites); gnutls_free(compression_methods); - ret = _gnutls_parse_extensions(state, &data[pos], len); /* len is the rest of the parsed length */ + ret = _gnutls_parse_extensions(state, &data[pos], len); /* len is the rest of the parsed length */ if (ret < 0) { gnutls_assert(); return ret; } - return ret; } -static int _gnutls_send_client_hello(SOCKET cd, GNUTLS_STATE state) -{ +static int _gnutls_send_client_hello(SOCKET cd, GNUTLS_STATE state) { char *data = NULL; opaque *extdata; int extdatalen; @@ -994,10 +959,10 @@ static int _gnutls_send_client_hello(SOCKET cd, GNUTLS_STATE state) GNUTLS_Version hver; opaque *SessionID = - state->gnutls_internals.resumed_security_parameters.session_id; + state->gnutls_internals.resumed_security_parameters.session_id; uint8 session_id_len = - state->gnutls_internals.resumed_security_parameters. - session_id_size; + state->gnutls_internals.resumed_security_parameters. + session_id_size; if (SessionID == NULL) session_id_len = 0; @@ -1010,9 +975,9 @@ static int _gnutls_send_client_hello(SOCKET cd, GNUTLS_STATE state) hver = _gnutls_version_max(state); data[pos++] = - _gnutls_version_get_major( hver); + _gnutls_version_get_major(hver); data[pos++] = - _gnutls_version_get_minor( hver); + _gnutls_version_get_minor(hver); _gnutls_create_random(random); _gnutls_set_client_random(state, random); @@ -1066,7 +1031,6 @@ static int _gnutls_send_client_hello(SOCKET cd, GNUTLS_STATE state) memcpy(&data[pos], extdata, extdatalen); gnutls_free(extdata); } - ret = _gnutls_send_handshake(cd, state, data, datalen, GNUTLS_CLIENT_HELLO); @@ -1077,8 +1041,7 @@ static int _gnutls_send_client_hello(SOCKET cd, GNUTLS_STATE state) return ret; } -static int _gnutls_send_server_hello(SOCKET cd, GNUTLS_STATE state) -{ +static int _gnutls_send_server_hello(SOCKET cd, GNUTLS_STATE state) { char *data = NULL; opaque *extdata; int extdatalen; @@ -1110,8 +1073,8 @@ static int _gnutls_send_server_hello(SOCKET cd, GNUTLS_STATE state) pos += session_id_len; #ifdef HANDSHAKE_DEBUG - _gnutls_log( "Handshake: SessionID: %s\n", - _gnutls_bin2hex(SessionID, session_id_len)); + _gnutls_log("Handshake: SessionID: %s\n", + _gnutls_bin2hex(SessionID, session_id_len)); #endif datalen += 2; @@ -1137,7 +1100,6 @@ static int _gnutls_send_server_hello(SOCKET cd, GNUTLS_STATE state) memcpy(&data[pos], extdata, extdatalen); gnutls_free(extdata); } - ret = _gnutls_send_handshake(cd, state, data, datalen, GNUTLS_SERVER_HELLO); @@ -1147,8 +1109,7 @@ static int _gnutls_send_server_hello(SOCKET cd, GNUTLS_STATE state) return ret; } -int _gnutls_send_hello(SOCKET cd, GNUTLS_STATE state) -{ +int _gnutls_send_hello(SOCKET cd, GNUTLS_STATE state) { int ret; if (state->security_parameters.entity == GNUTLS_CLIENT) { @@ -1166,8 +1127,7 @@ int _gnutls_send_hello(SOCKET cd, GNUTLS_STATE state) * and gnutls_internals.compression_method. */ int _gnutls_recv_hello(SOCKET cd, GNUTLS_STATE state, char *data, - int datalen) -{ + int datalen) { int ret; if (state->security_parameters.entity == GNUTLS_CLIENT) { @@ -1191,7 +1151,7 @@ int _gnutls_recv_hello(SOCKET cd, GNUTLS_STATE state, char *data, } /* The packets in gnutls_handshake - * + * Client Server * * ClientHello --------> @@ -1213,7 +1173,7 @@ int _gnutls_recv_hello(SOCKET cd, GNUTLS_STATE state, char *data, * <-------- Finished * */ - + /** * gnutls_handshake - This the main function in the handshake protocol. * @cd: is a connection descriptor, as returned by socket(). @@ -1225,8 +1185,7 @@ int _gnutls_recv_hello(SOCKET cd, GNUTLS_STATE state, char *data, * This function will fail if any problem is encountered, * and the connection should be terminated. **/ -int gnutls_handshake(SOCKET cd, GNUTLS_STATE state) -{ +int gnutls_handshake(SOCKET cd, GNUTLS_STATE state) { int ret; ret = gnutls_handshake_begin(cd, state); @@ -1256,21 +1215,20 @@ int gnutls_handshake(SOCKET cd, GNUTLS_STATE state) * continue the handshake - eg. even if the certificate cannot * be verified- by calling gnutls_handshake_finish(). */ -int gnutls_handshake_begin(SOCKET cd, GNUTLS_STATE state) -{ +int gnutls_handshake_begin(SOCKET cd, GNUTLS_STATE state) { int ret; if (state->security_parameters.entity == GNUTLS_CLIENT) { #ifdef HANDSHAKE_DEBUG if (state->gnutls_internals.resumed_security_parameters. session_id_size > 0) - _gnutls_log( "Ask to resume: %s\n", - _gnutls_bin2hex(state->gnutls_internals. - resumed_security_parameters. - session_id, - state->gnutls_internals. - resumed_security_parameters. - session_id_size)); + _gnutls_log("Ask to resume: %s\n", + _gnutls_bin2hex(state->gnutls_internals. + resumed_security_parameters. + session_id, + state->gnutls_internals. + resumed_security_parameters. + session_id_size)); #endif ret = _gnutls_send_hello(cd, state); if (ret < 0) { @@ -1279,7 +1237,6 @@ int gnutls_handshake_begin(SOCKET cd, GNUTLS_STATE state) gnutls_clearHashDataBuffer(state); return ret; } - /* receive the server hello */ ret = _gnutls_recv_handshake(cd, state, NULL, NULL, @@ -1290,7 +1247,6 @@ int gnutls_handshake_begin(SOCKET cd, GNUTLS_STATE state) gnutls_clearHashDataBuffer(state); return ret; } - /* RECV CERTIFICATE */ if (state->gnutls_internals.resumed == RESUME_FALSE) /* if we are not resuming */ ret = _gnutls_recv_certificate(cd, state); @@ -1312,7 +1268,6 @@ int gnutls_handshake_begin(SOCKET cd, GNUTLS_STATE state) gnutls_clearHashDataBuffer(state); return ret; } - ret = _gnutls_send_hello(cd, state); if (ret < 0) { ERR("send hello", ret); @@ -1320,7 +1275,6 @@ int gnutls_handshake_begin(SOCKET cd, GNUTLS_STATE state) gnutls_clearHashDataBuffer(state); return ret; } - /* NOTE: these should not be send if we are resuming */ /* SEND CERTIFICATE + KEYEXCHANGE + CERTIFICATE_REQUEST */ @@ -1333,8 +1287,6 @@ int gnutls_handshake_begin(SOCKET cd, GNUTLS_STATE state) gnutls_clearHashDataBuffer(state); return ret; } - - /* send server key exchange (A) */ if (state->gnutls_internals.resumed == RESUME_FALSE) ret = _gnutls_send_server_kx_message(cd, state); @@ -1344,7 +1296,6 @@ int gnutls_handshake_begin(SOCKET cd, GNUTLS_STATE state) gnutls_clearHashDataBuffer(state); return ret; } - /* FIXME: Send certificate request */ /* Added for SRP which uses a different handshake */ @@ -1357,7 +1308,6 @@ int gnutls_handshake_begin(SOCKET cd, GNUTLS_STATE state) gnutls_clearHashDataBuffer(state); return ret; } - /* send server key exchange (B) */ if (state->gnutls_internals.resumed == RESUME_FALSE) ret = _gnutls_send_server_kx_message2(cd, state); @@ -1367,7 +1317,6 @@ int gnutls_handshake_begin(SOCKET cd, GNUTLS_STATE state) gnutls_clearHashDataBuffer(state); return ret; } - /* FIXME: request - and get - a client certificate */ return 0; } @@ -1376,35 +1325,29 @@ int gnutls_handshake_begin(SOCKET cd, GNUTLS_STATE state) /* This function sends the final handshake packets and initializes connection */ static int _gnutls_send_handshake_final(SOCKET cd, GNUTLS_STATE state, - int init) -{ + int init) { int ret = 0; /* Send the CHANGE CIPHER SPEC PACKET */ - ret = _gnutls_send_change_cipher_spec(cd, state); + ret = _gnutls_send_change_cipher_spec(cd, state); if (ret < 0) { ERR("send ChangeCipherSpec", ret); gnutls_assert(); return ret; } - /* Initialize the connection state (start encryption) - in case of client - */ - if (init == TRUE) { + */ if (init == TRUE) { ret = _gnutls_connection_state_init(state); if (ret < 0) { gnutls_assert(); return ret; } } - ret = _gnutls_write_connection_state_init(state); if (ret < 0) { gnutls_assert(); return ret; } - - /* send the finished message */ ret = _gnutls_send_finished(cd, state); if (ret < 0) { @@ -1418,35 +1361,30 @@ static int _gnutls_send_handshake_final(SOCKET cd, GNUTLS_STATE state, /* This function receives the final handshake packets */ static int _gnutls_recv_handshake_final(SOCKET cd, GNUTLS_STATE state, - int init) -{ + int init) { int ret = 0; char ch; - ret = - gnutls_recv_int(cd, state, GNUTLS_CHANGE_CIPHER_SPEC, -1, - &ch, 1, 0); + ret = + gnutls_recv_int(cd, state, GNUTLS_CHANGE_CIPHER_SPEC, -1, + &ch, 1, 0); if (ret <= 0) { ERR("recv ChangeCipherSpec", ret); gnutls_assert(); - return (ret<0)?ret:GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + return (ret < 0) ? ret : GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - - /* Initialize the connection state (start encryption) - in case of server */ - if (init == TRUE) { + /* Initialize the connection state (start encryption) - in case of server */ if (init == TRUE) { ret = _gnutls_connection_state_init(state); if (ret < 0) { gnutls_assert(); return ret; } } - ret = _gnutls_read_connection_state_init(state); if (ret < 0) { gnutls_assert(); return ret; } - ret = _gnutls_recv_finished(cd, state); if (ret < 0) { ERR("recv finished", ret); @@ -1466,8 +1404,7 @@ static int _gnutls_recv_handshake_final(SOCKET cd, GNUTLS_STATE state, * you have somehow verified the identity of the peer. * This function will fail if any problem is encountered. */ -int gnutls_handshake_finish(SOCKET cd, GNUTLS_STATE state) -{ +int gnutls_handshake_finish(SOCKET cd, GNUTLS_STATE state) { int ret = 0; if (state->security_parameters.entity == GNUTLS_CLIENT) { @@ -1482,10 +1419,9 @@ int gnutls_handshake_finish(SOCKET cd, GNUTLS_STATE state) return ret; } - - /* Added for SRP */ - - /* send the client key exchange for SRP */ + /* Added for SRP, + * send the client key exchange for SRP + */ if (state->gnutls_internals.resumed == RESUME_FALSE) /* if we are not resuming */ ret = _gnutls_send_client_kx_message0(cd, state); if (ret < 0) { @@ -1495,6 +1431,17 @@ int gnutls_handshake_finish(SOCKET cd, GNUTLS_STATE state) return ret; } +#warning "FIX THIS REQUEST" + /* receive the server certificate request */ + if (state->gnutls_internals.resumed == RESUME_FALSE) /* if we are not resuming */ + ret = _gnutls_recv_server_certificate_request(cd, state); + if (ret < 0) { + gnutls_assert(); + ERR("recv server certificate request message", ret); + gnutls_clearHashDataBuffer(state); + return ret; + } + /* receive the server key exchange (B) (SRP only) */ if (state->gnutls_internals.resumed == RESUME_FALSE) /* if we are not resuming */ ret = _gnutls_recv_server_kx_message2(cd, state); @@ -1504,22 +1451,19 @@ int gnutls_handshake_finish(SOCKET cd, GNUTLS_STATE state) gnutls_clearHashDataBuffer(state); return ret; } - - /* FIXME: receive certificate request */ /* receive the server hello done */ if (state->gnutls_internals.resumed == RESUME_FALSE) /* if we are not resuming */ ret = _gnutls_recv_handshake(cd, state, NULL, NULL, - GNUTLS_SERVER_HELLO_DONE); + GNUTLS_SERVER_HELLO_DONE); if (ret < 0) { gnutls_assert(); ERR("recv server hello done", ret); gnutls_clearHashDataBuffer(state); return ret; } - /* send our certificate - if any */ if (state->gnutls_internals.resumed == RESUME_FALSE) /* if we are not resuming */ @@ -1530,7 +1474,6 @@ int gnutls_handshake_finish(SOCKET cd, GNUTLS_STATE state) gnutls_clearHashDataBuffer(state); return ret; } - if (state->gnutls_internals.resumed == RESUME_FALSE) /* if we are not resuming */ ret = _gnutls_send_client_kx_message(cd, state); if (ret < 0) { @@ -1539,7 +1482,6 @@ int gnutls_handshake_finish(SOCKET cd, GNUTLS_STATE state) gnutls_clearHashDataBuffer(state); return ret; } - /* send client certificate verify */ if (state->gnutls_internals.resumed == RESUME_FALSE) /* if we are not resuming */ ret = @@ -1551,21 +1493,19 @@ int gnutls_handshake_finish(SOCKET cd, GNUTLS_STATE state) gnutls_clearHashDataBuffer(state); return ret; } - } else { /* SERVER SIDE */ /* send the server hello done */ if (state->gnutls_internals.resumed == RESUME_FALSE) /* if we are not resuming */ ret = _gnutls_send_handshake(cd, state, NULL, 0, - GNUTLS_SERVER_HELLO_DONE); + GNUTLS_SERVER_HELLO_DONE); if (ret < 0) { gnutls_assert(); ERR("send server hello done", ret); gnutls_clearHashDataBuffer(state); return ret; } - /* RECV CERTIFICATE + KEYEXCHANGE + CERTIFICATE_VERIFY */ /* receive the client key exchange message */ @@ -1577,8 +1517,6 @@ int gnutls_handshake_finish(SOCKET cd, GNUTLS_STATE state) gnutls_clearHashDataBuffer(state); return ret; } - - } /* send and recv the change cipher spec and finished messages */ @@ -1598,7 +1536,6 @@ int gnutls_handshake_finish(SOCKET cd, GNUTLS_STATE state) return GNUTLS_E_AUTH_FAILED; return ret; } - ret = _gnutls_send_handshake_final(cd, state, FALSE); if (ret < 0) { gnutls_assert(); @@ -1613,7 +1550,6 @@ int gnutls_handshake_finish(SOCKET cd, GNUTLS_STATE state) gnutls_clearHashDataBuffer(state); return ret; } - ret = _gnutls_recv_handshake_final(cd, state, FALSE); if (ret < 0) { gnutls_assert(); @@ -1630,47 +1566,43 @@ int gnutls_handshake_finish(SOCKET cd, GNUTLS_STATE state) /* in order to support session resuming */ _gnutls_server_register_current_session(state); } - /* clear handshake buffer */ gnutls_clearHashDataBuffer(state); return ret; } -int _gnutls_generate_session_id(char *session_id, uint8 * len) -{ +int _gnutls_generate_session_id(char *session_id, uint8 * len) { opaque rand[TLS_RANDOM_SIZE]; if (_gnutls_get_random(rand, TLS_RANDOM_SIZE, GNUTLS_WEAK_RANDOM) < 0) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } - memcpy(session_id, rand, TLS_RANDOM_SIZE); *len = TLS_RANDOM_SIZE; #ifdef HANDSHAKE_DEBUG - _gnutls_log( "Generated SessionID: %s\n", - _gnutls_bin2hex(session_id, TLS_RANDOM_SIZE)); + _gnutls_log("Generated SessionID: %s\n", + _gnutls_bin2hex(session_id, TLS_RANDOM_SIZE)); #endif return 0; } #define RENEGOTIATE int _gnutls_recv_hello_request(SOCKET cd, GNUTLS_STATE state, void *data, - uint32 data_size) -{ + uint32 data_size) { #ifndef RENEGOTIATE int ret; /* only client should receive that */ if (state->security_parameters.entity == GNUTLS_SERVER) - return GNUTLS_E_UNEXPECTED_PACKET; + return GNUTLS_E_UNEXPECTED_PACKET; /* just return an alert that we don't like that */ - ret = - gnutls_send_alert(cd, state, GNUTLS_WARNING, - GNUTLS_NO_RENEGOTIATION); + ret = + gnutls_send_alert(cd, state, GNUTLS_WARNING, + GNUTLS_NO_RENEGOTIATION); if (ret < 0) { gnutls_assert(); return ret; @@ -1684,12 +1616,10 @@ int _gnutls_recv_hello_request(SOCKET cd, GNUTLS_STATE state, void *data, gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET; } - if (data_size < 1) { gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - type = ((uint8 *) data)[0]; if (type == GNUTLS_HELLO_REQUEST) return gnutls_handshake(cd, state); @@ -1703,17 +1633,18 @@ int _gnutls_recv_hello_request(SOCKET cd, GNUTLS_STATE state, void *data, /* This function will remove algorithms that are not supported by * the requested authentication method. We only remove algorithm if * we receive client hello extensions (dnsname). + * + * or if we have a certificate with keyUsage bits (not ready yet) */ int _gnutls_remove_unwanted_ciphersuites(GNUTLS_STATE state, GNUTLS_CipherSuite ** - cipherSuites, int numCipherSuites) -{ + cipherSuites, int numCipherSuites) { int ret = 0; GNUTLS_CipherSuite *newSuite; int newSuiteSize = 0, i, j, keep; const X509PKI_CREDENTIALS x509_cred; - gnutls_cert *cert=NULL; + gnutls_cert *cert = NULL; KXAlgorithm *alg; int alg_size; KXAlgorithm kx; @@ -1724,9 +1655,9 @@ int _gnutls_remove_unwanted_ciphersuites(GNUTLS_STATE state, * we've got a sign-only key... (ok we need to check * it more than that). */ - + if (state->security_parameters.entity == GNUTLS_CLIENT) - return 0; + return 0; /* if we should use a specific certificate, * we should remove all algorithms that are not supported @@ -1748,13 +1679,11 @@ int _gnutls_remove_unwanted_ciphersuites(GNUTLS_STATE state, cert = (gnutls_cert *) _gnutls_find_cert(x509_cred->cert_list, x509_cred->ncerts, - state->security_parameters. + state->security_parameters. extensions.dnsname); } - - - if (cert == NULL && x509_cred->cert_list!=NULL) { /* if no such cert, use the first in the list - */ + if (cert == NULL && x509_cred->cert_list != NULL) { /* if no such cert, use the first in the list + */ cert = &x509_cred->cert_list[0][0]; /* get all the key exchange algorithms that are @@ -1764,12 +1693,11 @@ int _gnutls_remove_unwanted_ciphersuites(GNUTLS_STATE state, gnutls_assert(); return ret; } - } else { - /* No certificate was found - */ - alg_size = 0; - alg = NULL; + /* No certificate was found + */ + alg_size = 0; + alg = NULL; } @@ -1780,7 +1708,7 @@ int _gnutls_remove_unwanted_ciphersuites(GNUTLS_STATE state, kx = _gnutls_cipher_suite_get_kx_algo((*cipherSuites)[i]); keep = 0; - if (_gnutls_map_kx_get_cred( kx) == GNUTLS_X509PKI) { + if (_gnutls_map_kx_get_cred(kx) == GNUTLS_X509PKI) { keep = 1; /* do not keep */ if (x509_cred != NULL) for (j = 0; j < alg_size; j++) { @@ -1789,10 +1717,10 @@ int _gnutls_remove_unwanted_ciphersuites(GNUTLS_STATE state, break; } } - } else /* if it is defined but had no credentials - */ - if ( _gnutls_get_kx_cred( state->gnutls_key, kx, NULL)==NULL) - keep = 1; + } else + /* if it is defined but had no credentials + */ if (_gnutls_get_kx_cred(state->gnutls_key, kx, NULL) == NULL) + keep = 1; if (keep == 0) { memcpy(newSuite[newSuiteSize].CipherSuite, diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index e3860ab844..5497cde7da 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -30,9 +30,9 @@ #define HARD_DEBUG #define BUFFERS_DEBUG #define RECORD_DEBUG -#define HANDSHAKE_DEBUG +#define HANDSHAKE_DEBUG*/ #define DEBUG -*/ + #define SOCKET int #define LIST ... @@ -71,6 +71,7 @@ #endif #include +#include #define DECR_LEN(len, x) len-=x; if (len<0) {gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;} @@ -141,7 +142,7 @@ typedef struct { uint8 minor; } ProtocolVersion; -typedef struct { +struct GNUTLS_KEY_INT { /* For DH KX */ gnutls_datum key; MPI KEY; @@ -172,22 +173,24 @@ typedef struct { */ uint8 crypt_algo; - /* These are needed in RSA and DH signature calculation - */ - opaque server_random[TLS_RANDOM_SIZE]; - opaque client_random[TLS_RANDOM_SIZE]; - ProtocolVersion version; - AUTH_CRED* cred; /* used to specify keys/certificates etc */ -} GNUTLS_KEY_A; -typedef GNUTLS_KEY_A* GNUTLS_KEY; + + int certificate_requested; + /* some ciphersuites use this + * to provide client authentication. + * 1 if client auth was requested + * by the peer, 0 otherwise + */ +}; +typedef struct GNUTLS_KEY_INT* GNUTLS_KEY; /* STATE (cont) */ #include #include -#include + +//#include typedef struct { uint8 CipherSuite[2]; @@ -305,28 +308,27 @@ typedef struct { ResumableSession resumed; /* TRUE or FALSE - if we are resuming a session */ SecurityParameters resumed_security_parameters; - int certificate_requested; /* non zero if client certificate was requested */ /* sockets internals */ int lowat; /* gdbm */ char* db_name; int expire_time; - MOD_AUTH_STRUCT* auth_struct; /* used in handshake packets and KX algorithms */ + struct MOD_AUTH_STRUCT_INT* auth_struct; /* used in handshake packets and KX algorithms */ int v2_hello; /* set 0 normally - 1 if v2 hello was received - server side only */ #ifdef HAVE_LIBGDBM GDBM_FILE db_reader; #endif } GNUTLS_INTERNALS; -typedef struct { +struct GNUTLS_STATE_INT { SecurityParameters security_parameters; CipherSpecs cipher_specs; ConnectionState connection_state; GNUTLS_INTERNALS gnutls_internals; GNUTLS_KEY gnutls_key; -} GNUTLS_STATE_INT; +}; -typedef GNUTLS_STATE_INT *GNUTLS_STATE; +typedef struct GNUTLS_STATE_INT *GNUTLS_STATE; /* Record Protocol */ @@ -345,7 +347,8 @@ GNUTLS_Version gnutls_get_current_version(GNUTLS_STATE state); ssize_t gnutls_send_int(SOCKET cd, GNUTLS_STATE state, ContentType type, HandshakeType htype, const void* data, size_t sizeofdata, int flags); ssize_t gnutls_recv_int(SOCKET cd, GNUTLS_STATE state, ContentType type, HandshakeType, char* data, size_t sizeofdata, int flags); int _gnutls_send_change_cipher_spec(SOCKET cd, GNUTLS_STATE state); -int _gnutls_version_cmp(GNUTLS_Version ver1, GNUTLS_Version ver2); + +#define _gnutls_version_cmp( ver1, ver2) ver1==ver2?0:1 #define _gnutls_version_ssl3(x) _gnutls_version_cmp(x, GNUTLS_SSL3) #endif /* GNUTLS_INT_H */ diff --git a/lib/gnutls_kx.c b/lib/gnutls_kx.c index 30b8f666ac..1963ed9786 100644 --- a/lib/gnutls_kx.c +++ b/lib/gnutls_kx.c @@ -102,7 +102,7 @@ int _gnutls_send_server_kx_message(SOCKET cd, GNUTLS_STATE state) #endif - data_size = state->gnutls_internals.auth_struct->gnutls_generate_server_kx( state->gnutls_key, &data); + data_size = state->gnutls_internals.auth_struct->gnutls_generate_server_kx( state, &data); if (data_size < 0) { gnutls_assert(); @@ -127,7 +127,7 @@ int _gnutls_send_server_kx_message2(SOCKET cd, GNUTLS_STATE state) int ret = 0; if (state->gnutls_internals.auth_struct->gnutls_generate_server_kx2 != NULL) { - data_size = state->gnutls_internals.auth_struct->gnutls_generate_server_kx2( state->gnutls_key, &data); + data_size = state->gnutls_internals.auth_struct->gnutls_generate_server_kx2( state, &data); #ifdef HANDSHAKE_DEBUG _gnutls_log( "Sending server KX message2\n"); @@ -165,7 +165,7 @@ int _gnutls_send_client_kx_message(SOCKET cd, GNUTLS_STATE state) _gnutls_log( "Sending client KX message\n"); #endif - data_size = state->gnutls_internals.auth_struct->gnutls_generate_client_kx( state->gnutls_key, &data); + data_size = state->gnutls_internals.auth_struct->gnutls_generate_client_kx( state, &data); if (data_size < 0) { gnutls_assert(); return data_size; @@ -197,7 +197,7 @@ int _gnutls_send_client_kx_message0(SOCKET cd, GNUTLS_STATE state) _gnutls_log( "Sending client KX message0\n"); #endif - data_size = state->gnutls_internals.auth_struct->gnutls_generate_client_kx0( state->gnutls_key, &data); + data_size = state->gnutls_internals.auth_struct->gnutls_generate_client_kx0( state, &data); if (data_size < 0) { gnutls_assert(); return data_size; @@ -212,8 +212,6 @@ int _gnutls_send_client_kx_message0(SOCKET cd, GNUTLS_STATE state) /* This is the function for the client to send the certificate * verify message - * FIXME: this function does almost nothing except sending garbage to - * peer. */ int _gnutls_send_client_certificate_verify(SOCKET cd, GNUTLS_STATE state) { @@ -227,7 +225,7 @@ int _gnutls_send_client_certificate_verify(SOCKET cd, GNUTLS_STATE state) /* if certificate verify is not needed just exit */ - if (state->gnutls_internals.certificate_requested==0) return 0; + if (state->gnutls_key->certificate_requested==0) return 0; if (state->gnutls_internals.auth_struct->gnutls_generate_client_cert_vrfy==NULL) { return 0; /* this algorithm does not support cli_cert_vrfy @@ -237,7 +235,7 @@ int _gnutls_send_client_certificate_verify(SOCKET cd, GNUTLS_STATE state) #ifdef HANDSHAKE_DEBUG _gnutls_log( "Sending client certificate verify message\n"); #endif - data_size = state->gnutls_internals.auth_struct->gnutls_generate_client_cert_vrfy( state->gnutls_key, &data); + data_size = state->gnutls_internals.auth_struct->gnutls_generate_client_cert_vrfy( state, &data); if (data_size < 0) return data_size; ret = @@ -270,7 +268,36 @@ int _gnutls_recv_server_kx_message(SOCKET cd, GNUTLS_STATE state) return ret; - ret = state->gnutls_internals.auth_struct->gnutls_process_server_kx( state->gnutls_key, data, datasize); + ret = state->gnutls_internals.auth_struct->gnutls_process_server_kx( state, data, datasize); + gnutls_free(data); + if (ret < 0) + return ret; + + } + return ret; +} + +int _gnutls_recv_server_certificate_request(SOCKET cd, GNUTLS_STATE state) +{ + uint8 *data; + int datasize; + int ret = 0; + + if (state->gnutls_internals.auth_struct->gnutls_process_server_certificate_request!=NULL) { + +#ifdef HANDSHAKE_DEBUG + _gnutls_log( "Receiving Server Certificate request message\n"); +#endif + + ret = + _gnutls_recv_handshake(cd, state, &data, + &datasize, + GNUTLS_CERTIFICATE_REQUEST); + if (ret <= 0) + return ret; + + + ret = state->gnutls_internals.auth_struct->gnutls_process_server_certificate_request( state, data, datasize); gnutls_free(data); if (ret < 0) return ret; @@ -300,7 +327,7 @@ int _gnutls_recv_server_kx_message2(SOCKET cd, GNUTLS_STATE state) return ret; - ret = state->gnutls_internals.auth_struct->gnutls_process_server_kx2( state->gnutls_key, data, datasize); + ret = state->gnutls_internals.auth_struct->gnutls_process_server_kx2( state, data, datasize); gnutls_free(data); if (ret < 0) return ret; @@ -330,7 +357,7 @@ int _gnutls_recv_client_kx_message(SOCKET cd, GNUTLS_STATE state) if (ret < 0) return ret; - ret = state->gnutls_internals.auth_struct->gnutls_process_client_kx( state->gnutls_key, data, datasize); + ret = state->gnutls_internals.auth_struct->gnutls_process_client_kx( state, data, datasize); gnutls_free(data); if (ret < 0) return ret; @@ -361,7 +388,7 @@ int _gnutls_recv_client_kx_message0(SOCKET cd, GNUTLS_STATE state) if (ret < 0) return ret; - ret = state->gnutls_internals.auth_struct->gnutls_process_client_kx0( state->gnutls_key, data, datasize); + ret = state->gnutls_internals.auth_struct->gnutls_process_client_kx0( state, data, datasize); gnutls_free(data); if (ret < 0) return ret; @@ -386,8 +413,7 @@ int _gnutls_send_certificate(SOCKET cd, GNUTLS_STATE state) _gnutls_log( "Sending certificate message\n"); #endif - - data_size = state->gnutls_internals.auth_struct->gnutls_generate_certificate( state->gnutls_key, &data); + data_size = state->gnutls_internals.auth_struct->gnutls_generate_certificate( state, &data); if (data_size < 0) { gnutls_assert(); @@ -422,7 +448,7 @@ int _gnutls_recv_certificate(SOCKET cd, GNUTLS_STATE state) return ret; } - ret = state->gnutls_internals.auth_struct->gnutls_process_certificate( state->gnutls_key, data, datasize); + ret = state->gnutls_internals.auth_struct->gnutls_process_certificate( state, data, datasize); gnutls_free(data); if (ret < 0) { gnutls_assert(); @@ -436,7 +462,7 @@ int _gnutls_recv_certificate(SOCKET cd, GNUTLS_STATE state) int _gnutls_send_client_certificate(SOCKET cd, GNUTLS_STATE state) { - if (state->gnutls_internals.certificate_requested == 0) + if (state->gnutls_key->certificate_requested == 0) return 0; #ifdef HANDSHAKE_DEBUG diff --git a/lib/gnutls_kx.h b/lib/gnutls_kx.h index 122a50dce6..010d528d5a 100644 --- a/lib/gnutls_kx.h +++ b/lib/gnutls_kx.h @@ -31,4 +31,5 @@ int _gnutls_send_certificate(int cd, GNUTLS_STATE state); int _gnutls_generate_master( GNUTLS_STATE state); int _gnutls_recv_certificate(SOCKET cd, GNUTLS_STATE state); int _gnutls_send_client_certificate(SOCKET cd, GNUTLS_STATE state); +int _gnutls_recv_server_certificate_request(SOCKET cd, GNUTLS_STATE state); diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c index 160a6916ca..8e14630c69 100644 --- a/lib/gnutls_record.c +++ b/lib/gnutls_record.c @@ -51,10 +51,6 @@ GNUTLS_Version ver; void _gnutls_set_current_version(GNUTLS_STATE state, GNUTLS_Version version) { state->connection_state.version = version; - if (state->gnutls_key!=NULL) { - state->gnutls_key->version.major = _gnutls_version_get_major(version); - state->gnutls_key->version.minor = _gnutls_version_get_minor(version); - } } /** @@ -86,7 +82,7 @@ int gnutls_set_lowat(GNUTLS_STATE state, int num) { int gnutls_init(GNUTLS_STATE * state, ConnectionEnd con_end) { - *state = gnutls_calloc(1, sizeof(GNUTLS_STATE_INT)); + *state = gnutls_calloc(1, sizeof(struct GNUTLS_STATE_INT)); (*state)->security_parameters.entity = con_end; @@ -104,7 +100,7 @@ int gnutls_init(GNUTLS_STATE * state, ConnectionEnd con_end) gnutls_set_protocol_priority( *state, GNUTLS_TLS1, 0); /* default */ - (*state)->gnutls_key = gnutls_calloc(1, sizeof(GNUTLS_KEY_A)); + (*state)->gnutls_key = gnutls_calloc(1, sizeof(struct GNUTLS_KEY_INT)); (*state)->gnutls_internals.resumed = RESUME_FALSE; @@ -187,7 +183,7 @@ int gnutls_deinit(GNUTLS_STATE state) GNUTLS_FREE(state->gnutls_internals.db_name); - memset( state, 0, sizeof(GNUTLS_STATE_INT)); + memset( state, 0, sizeof(struct GNUTLS_STATE_INT)); GNUTLS_FREE(state); return 0; } @@ -452,6 +448,7 @@ ssize_t gnutls_send_int(SOCKET cd, GNUTLS_STATE state, ContentType type, Handsha WRITEuint16( cipher_size, &headers[3]); +#warning "CHECK if the double write breaks other implementations" if (_gnutls_Write(cd, headers, HEADER_SIZE, flags) != HEADER_SIZE) { state->gnutls_internals.valid_connection = VALID_FALSE; state->gnutls_internals.resumable = RESUME_FALSE; diff --git a/lib/gnutls_ui.c b/lib/gnutls_ui.c index d9ff103488..33efe099d7 100644 --- a/lib/gnutls_ui.c +++ b/lib/gnutls_ui.c @@ -162,6 +162,19 @@ unsigned char gnutls_x509pki_client_get_key_usage( const X509PKI_CLIENT_AUTH_INF return info->keyUsage; } +/** + * gnutls_x509pki_client_get_certificate_request_status - This function returns the certificate request status + * @info: is an X509PKI_CLIENT_AUTH_INFO structure + * + * This function will return 0 if the peer (server) did not requested client + * authentication or 1 otherwise. + * + **/ +unsigned char gnutls_x509pki_client_get_certificate_request_status( const X509PKI_CLIENT_AUTH_INFO* info) { + if (info==NULL) return GNUTLS_E_UNKNOWN_ERROR; + return info->certificate_requested; +} + /** * gnutls_x509pki_client_get_subject_alt_name - This function returns the peer's alternative name -- cgit v1.2.1