summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2001-10-08 18:38:04 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2001-10-08 18:38:04 +0000
commit44c0124aa768d83c93cb6242619047bc0877f716 (patch)
treeb584e48b07eb3ca8027fccda3d7d0d0d601612cf
parent767e33eba3d47cff204d1141453b64cac6bc7f82 (diff)
downloadgnutls-44c0124aa768d83c93cb6242619047bc0877f716.tar.gz
added DHE_RSA ciphersuites
-rw-r--r--NEWS4
-rw-r--r--THANKS2
-rw-r--r--configure.in2
-rw-r--r--doc/tex/ex3.tex53
-rw-r--r--lib/auth_anon.c10
-rw-r--r--lib/auth_dhe_rsa.c280
-rw-r--r--lib/auth_x509.c230
-rw-r--r--lib/auth_x509.h2
-rw-r--r--lib/gnutls_algorithms.c2
-rw-r--r--lib/gnutls_cert.c2
-rw-r--r--lib/gnutls_cert.h2
-rw-r--r--lib/gnutls_datum.c3
-rw-r--r--lib/gnutls_int.h2
-rw-r--r--lib/gnutls_record.c1
-rw-r--r--lib/gnutls_sig.c200
-rw-r--r--lib/gnutls_sig.h12
-rw-r--r--lib/x509_extensions.c2
-rw-r--r--src/cli.c23
-rw-r--r--src/serv.c33
19 files changed, 555 insertions, 310 deletions
diff --git a/NEWS b/NEWS
index 10e6e5f248..02b428301b 100644
--- a/NEWS
+++ b/NEWS
@@ -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
diff --git a/THANKS b/THANKS
index 43d70f6928..dd0ed46a98 100644
--- a/THANKS
+++ b/THANKS
@@ -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) {
diff --git a/src/cli.c b/src/cli.c
index c2e1d8a7df..29176821ce 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -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);
+ }
}
}
}