diff options
-rw-r--r-- | doc/TODO | 3 | ||||
-rw-r--r-- | lib/auth_anon.c | 5 | ||||
-rw-r--r-- | lib/auth_rsa.c | 207 | ||||
-rw-r--r-- | lib/auth_srp.c | 1 | ||||
-rw-r--r-- | lib/auth_x509.h | 5 | ||||
-rw-r--r-- | lib/gnutls.h.in | 12 | ||||
-rw-r--r-- | lib/gnutls_algorithms.c | 156 | ||||
-rw-r--r-- | lib/gnutls_algorithms.h | 15 | ||||
-rw-r--r-- | lib/gnutls_auth.h | 1 | ||||
-rw-r--r-- | lib/gnutls_handshake.c | 75 | ||||
-rw-r--r-- | lib/gnutls_handshake.h | 1 | ||||
-rw-r--r-- | lib/gnutls_int.h | 12 | ||||
-rw-r--r-- | lib/gnutls_kx.c | 123 | ||||
-rw-r--r-- | lib/gnutls_kx.h | 1 | ||||
-rw-r--r-- | lib/gnutls_v2_compat.c | 2 | ||||
-rw-r--r-- | src/cli.c | 15 | ||||
-rw-r--r-- | src/serv.c | 37 |
17 files changed, 264 insertions, 407 deletions
@@ -8,3 +8,6 @@ only one parse of the der structures. * Create global variables that hold read/write and initialize the ASN.1 parser's structures. +* Create certificate verify function(s) +* Add client side of RSA auth. + diff --git a/lib/auth_anon.c b/lib/auth_anon.c index 1efd201d48..0f84020112 100644 --- a/lib/auth_anon.c +++ b/lib/auth_anon.c @@ -43,6 +43,7 @@ MOD_AUTH_STRUCT anon_auth_struct = { gen_anon_client_kx, NULL, NULL, + NULL, /* certificate */ proc_anon_server_kx, NULL, NULL, @@ -65,7 +66,7 @@ int _gnutls_generate_key(GNUTLS_KEY key) { } int gen_anon_server_kx( GNUTLS_KEY key, opaque** data) { - GNUTLS_MPI x, X, g, p; + MPI x, X, g, p; int bits; size_t n_X, n_g, n_p; uint8 *data_p; @@ -115,7 +116,7 @@ int gen_anon_server_kx( GNUTLS_KEY key, opaque** data) { } int gen_anon_client_kx( GNUTLS_KEY key, opaque** data) { -GNUTLS_MPI x, X; +MPI x, X; size_t n_X; int ret; diff --git a/lib/auth_rsa.c b/lib/auth_rsa.c index 5259359980..59a3219240 100644 --- a/lib/auth_rsa.c +++ b/lib/auth_rsa.c @@ -36,23 +36,26 @@ int gen_rsa_server_kx(GNUTLS_KEY, opaque **); #endif 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); MOD_AUTH_STRUCT rsa_auth_struct = { "RSA", gen_rsa_certificate, -/* not needed!!! gen_rsa_server_kx, */ NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - proc_rsa_client_kx, - NULL, - NULL + NULL, /* gen server kx */ + NULL, /* gen server kx2 */ + NULL, /* gen client kx0 */ + gen_rsa_client_kx, + NULL, /* gen client cert vrfy */ + NULL, /* gen server cert vrfy */ + 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 */ }; typedef struct { @@ -60,6 +63,7 @@ typedef struct { gnutls_datum rsa_exponent; } RSA_Params; +#if 0 /* This function will calculate the SHA/MD5 signature in server kx. * This is needed by the protocol. */ @@ -107,45 +111,47 @@ int _gnutls_calc_rsa_signature( GNUTLS_KEY key, const opaque* data, int data_siz return ret; } +#endif -#if 0 -/* This function reads the RSA parameters from the given(?) certificate. +/* This function extracts the RSA parameters from the given(?) certificate. */ -static int _gnutls_get_rsa_params( GNUTLS_KEY key, RSA_Params * params, gnutls_datum cert) +static int _gnutls_get_rsa_params( GNUTLS_KEY key, RSA_Params * params, MPI* mod, MPI* exp, gnutls_datum cert) { int ret = 0, result; opaque str[5*1024]; int len = sizeof(str); - if (create_structure("certificate2", "PKIX1Explicit88.Certificate")!=ASN_OK) { + if (create_structure("rsa_params", "PKIX1Explicit88.Certificate")!=ASN_OK) { gnutls_assert(); return GNUTLS_E_PARSING_ERROR; } - result = get_der("certificate2", cert.data, cert.size); + result = get_der("rsa_params", cert.data, cert.size); if (result != ASN_OK) { + /* couldn't decode DER */ gnutls_assert(); return GNUTLS_E_PARSING_ERROR; } - /* Verify sign */ + result = - read_value("certificate2.tbsCertificate.subjectPublicKeyInfo.algorithm", str, &len); + read_value("rsa_params.tbsCertificate.subjectPublicKeyInfo.algorithm", str, &len); if (result != ASN_OK) { +fprintf(stderr, "resut: %d\n", result); gnutls_assert(); - delete_structure("certificate2"); + delete_structure("rsa_params"); return GNUTLS_E_PARSING_ERROR; } if (!strcmp(str, "1 2 840 113549 1 1 1")) { /* pkix-1 1 - RSA */ len = sizeof(str); result = - read_value("certificate2.tbsCertificate.subjectPublicKeyInfo.parameters", str, &len); - delete_structure("certificate2"); + read_value("rsa_params.tbsCertificate.subjectPublicKeyInfo.parameters", str, &len); + delete_structure("rsa_params"); if (result != ASN_OK) { gnutls_assert(); - delete_structure("certificate2"); + delete_structure("rsa_params"); return GNUTLS_E_PARSING_ERROR; } @@ -169,17 +175,19 @@ static int _gnutls_get_rsa_params( GNUTLS_KEY key, RSA_Params * params, gnutls_d return GNUTLS_E_PARSING_ERROR; } - if (gcry_mpi_scan(&key->A, + if (gcry_mpi_scan(mod, GCRYMPI_FMT_USG, str, &len) != 0) { gnutls_assert(); delete_structure("rsapublickey"); return GNUTLS_E_MPI_SCAN_FAILED; } - if (gnutls_set_datum(¶ms->rsa_modulus, str, len) < 0) { - gnutls_assert(); - delete_structure("rsapublickey"); - return GNUTLS_E_MEMORY_ERROR; - } + + if (params!=NULL) + if (gnutls_set_datum(¶ms->rsa_modulus, str, len) < 0) { + gnutls_assert(); + delete_structure("rsapublickey"); + return GNUTLS_E_MEMORY_ERROR; + } len = sizeof(str); result = @@ -187,22 +195,23 @@ static int _gnutls_get_rsa_params( GNUTLS_KEY key, RSA_Params * params, gnutls_d if (result != ASN_OK) { gnutls_assert(); delete_structure("rsapublickey"); - gnutls_free_datum(¶ms->rsa_modulus); - _gnutls_mpi_release(&key->A); + if (params!=NULL) gnutls_free_datum(¶ms->rsa_modulus); + _gnutls_mpi_release(mod); return GNUTLS_E_PARSING_ERROR; } - if (gcry_mpi_scan(&key->B, + if (gcry_mpi_scan(exp, GCRYMPI_FMT_USG, str, &len) != 0) { gnutls_assert(); - _gnutls_mpi_release(&key->A); - gnutls_free_datum(¶ms->rsa_modulus); + _gnutls_mpi_release(mod); + if (params!=NULL) gnutls_free_datum(¶ms->rsa_modulus); delete_structure("rsapublickey"); return GNUTLS_E_MPI_SCAN_FAILED; } if (gnutls_set_datum(¶ms->rsa_exponent, str, len) < 0) { - _gnutls_mpi_release(&key->A); - gnutls_free_datum(¶ms->rsa_modulus); + _gnutls_mpi_release(mod); + _gnutls_mpi_release(exp); + if (params!=NULL) gnutls_free_datum(¶ms->rsa_modulus); delete_structure("rsapublickey"); return GNUTLS_E_MEMORY_ERROR; } @@ -211,11 +220,10 @@ static int _gnutls_get_rsa_params( GNUTLS_KEY key, RSA_Params * params, gnutls_d } - delete_structure("certificate2"); + delete_structure("rsa_params"); return ret; } -#endif /* This function reads the RSA parameters from the given private key * cert is not a certificate but a der structure containing the private @@ -442,3 +450,126 @@ int proc_rsa_client_kx( GNUTLS_KEY key, opaque* data, int data_size) { return 0; } +int proc_rsa_certificate( GNUTLS_KEY key, opaque* data, int data_size) { +int size, len; +opaque* p = data; +X509PKI_AUTH_INFO* info; +int dsize = data_size; +int i, j; + + key->auth_info = gnutls_calloc(1, sizeof(X509PKI_AUTH_INFO)); + if (key->auth_info==NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + key->auth_info_size = sizeof(X509PKI_AUTH_INFO); + + DECR_LEN( dsize, 3); + size = READuint24( p); + p+=3; + + if (size==0) { + gnutls_assert(); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + + info = key->auth_info; + i = dsize; + + len=READuint24(p); p+=3; + + for(; i > 0; len=READuint24(p),p+=3) { + DECR_LEN(dsize, (len+3)); + info->peer_certificate_list_size++; + p+=len; + i-=len+3; + } + + if (info->peer_certificate_list_size==0) { + gnutls_assert(); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + + dsize = data_size; + i = dsize; + info->peer_certificate_list = gnutls_malloc(sizeof(gnutls_datum)*(info->peer_certificate_list_size)); + if (info->peer_certificate_list==NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + p = data+3; + i = data_size - 3; + j = 0; + + len=READuint24(p); p+=3; + for(; i > 0; len=READuint24(p), p+=3) { + if ( j >= info->peer_certificate_list_size) break; + + info->peer_certificate_list[j].size = len; + info->peer_certificate_list[j].data = gnutls_malloc(len); + if (info->peer_certificate_list[j].data==NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + memcpy( info->peer_certificate_list[j].data, p, len); + p+=len; + i-=len+3; + j++; + } + + +#warning "WE DO NOT VERIFY RSA CERTIFICATES" + /* FIXME: Verify certificate + */ + info->peer_certificate_status = GNUTLS_NOT_VERIFIED; + + return 0; +} + +/* return RSA(random) using the peers public key + */ +int gen_rsa_client_kx(GNUTLS_KEY key, opaque ** data) +{ + X509PKI_AUTH_INFO *auth = key->auth_info; + svoid *rand; + gnutls_datum sdata; /* data to send */ + gnutls_datum edata; /* data to encrypt */ + MPI pkey, n; + int ret; + + if (auth == NULL) { + /* this shouldn't have happened. The proc_certificate + * function should have detected that. + */ + gnutls_assert(); + return GNUTLS_E_INSUFICIENT_CRED; + } + + rand = secure_malloc( TLS_MASTER_SIZE); + if (rand==NULL) + return GNUTLS_E_MEMORY_ERROR; + + _gnutls_get_random( rand, TLS_MASTER_SIZE, GNUTLS_STRONG_RANDOM); + + key->key.data = rand; + key->key.size = TLS_MASTER_SIZE; + + edata.data = rand; + edata.size = TLS_MASTER_SIZE; + + if ( (ret=_gnutls_get_rsa_params( key, NULL, &n, &pkey, auth->peer_certificate_list[0])) < 0 ) { + gnutls_assert(); + return ret; + } + + _gnutls_pkcs1_rsa_encrypt( &sdata, edata, pkey, n); + + secure_free(rand); + _gnutls_mpi_release(&pkey); + _gnutls_mpi_release(&n); + + *data = sdata.data; + return sdata.size; +} diff --git a/lib/auth_srp.c b/lib/auth_srp.c index 5a15f7cec5..ee1ff3a8ff 100644 --- a/lib/auth_srp.c +++ b/lib/auth_srp.c @@ -45,6 +45,7 @@ MOD_AUTH_STRUCT srp_auth_struct = { NULL, NULL, NULL, + NULL, /* certificate */ proc_srp_server_kx, proc_srp_server_kx2, proc_srp_client_kx0, diff --git a/lib/auth_x509.h b/lib/auth_x509.h index 7f68294067..981cc0348c 100644 --- a/lib/auth_x509.h +++ b/lib/auth_x509.h @@ -27,6 +27,9 @@ typedef struct { int ne; } X509PKI_CLIENT_CREDENTIALS; + typedef struct { - int ne; + gnutls_datum *peer_certificate_list; /* In DER format */ + int peer_certificate_list_size; + CertificateStatus peer_certificate_status; } X509PKI_AUTH_INFO; diff --git a/lib/gnutls.h.in b/lib/gnutls.h.in index 9283d26f0f..93b9a365d3 100644 --- a/lib/gnutls.h.in +++ b/lib/gnutls.h.in @@ -145,6 +145,18 @@ typedef struct { int dh_bits; } ANON_AUTH_INFO; +typedef enum verified { GNUTLS_VERIFIED, GNUTLS_NOT_VERIFIED, GNUTLS_EXPIRED, GNUTLS_INVALID } CertificateStatus; + +typedef struct { + gnutls_datum *peer_certificate_list; /* In DER format */ + int peer_certificate_list_size; + CertificateStatus peer_certificate_status; +} X509PKI_AUTH_INFO; + +typedef struct { + int ne; /* nothing of interest here */ +} X509PKI_CLIENT_CREDENTIALS; + typedef struct { gnutls_datum ** cert_list; /* contains a list of a list of certificates. diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c index e9314f39ae..790d869743 100644 --- a/lib/gnutls_algorithms.c +++ b/lib/gnutls_algorithms.c @@ -174,30 +174,20 @@ static const gnutls_compression_entry compression_algorithms[] = { /* Key Exchange Section */ -#define GNUTLS_KX_ALGO_ENTRY(name, server_cert, client_cert, RSA_premaster, DH_public_value, auth_struct) \ - { #name, name, server_cert, client_cert, RSA_premaster, DH_public_value, auth_struct } +#define GNUTLS_KX_ALGO_ENTRY(name, auth_struct) \ + { #name, name, auth_struct } struct gnutls_kx_algo_entry { char *name; KXAlgorithm algorithm; - int server_cert; - int client_cert; - int RSA_premaster; - int DH_public_value; MOD_AUTH_STRUCT *auth_struct; }; typedef struct gnutls_kx_algo_entry gnutls_kx_algo_entry; static const gnutls_kx_algo_entry kx_algorithms[] = { - GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_DH_ANON, 0, 0, 0, 1, - &anon_auth_struct), - GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_RSA, 1, 1, 1, 0, &rsa_auth_struct), -/* GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_DHE_DSS, 1, 1, 0, 0, - &dhe_dss_auth_struct),*/ -/* GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_DHE_RSA, 1, 1, 0, 0, NULL),*/ -/* GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_DH_DSS, 1, 1, 0, 0, NULL),*/ -/* GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_DH_RSA, 1, 1, 0, 0, NULL),*/ - GNUTLS_KX_ALGO_ENTRY(GNUTLS_KX_SRP, 0, 0, 0, 0, &srp_auth_struct), + 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_SRP, &srp_auth_struct), {0} }; @@ -688,14 +678,6 @@ int _gnutls_cipher_is_ok(BulkCipherAlgorithm algorithm) /* Key EXCHANGE functions */ -int _gnutls_kx_server_certificate(KXAlgorithm algorithm) -{ - size_t ret = 0; - GNUTLS_KX_ALG_LOOP(ret = p->server_cert); - return ret; - -} - MOD_AUTH_STRUCT *_gnutls_kx_auth_struct(KXAlgorithm algorithm) { MOD_AUTH_STRUCT *ret = NULL; @@ -717,134 +699,6 @@ inline int _gnutls_kx_priority(GNUTLS_STATE state, KXAlgorithm algorithm) return -1; } -int _gnutls_kx_server_key_exchange(KXAlgorithm algorithm) -{ - size_t ret = 0; - void *ret2 = NULL; - - /* if the auth algorithm does not have a null value - * for the kx2 generation then it supports it! - */ - GNUTLS_KX_ALG_LOOP(ret2 = - p->auth_struct->gnutls_generate_server_kx); - if (ret2 != NULL) - ret = 1; - - return ret; - -} - -int _gnutls_kx_server_key_exchange2(KXAlgorithm algorithm) -{ - size_t ret = 0; - void *ret2 = NULL; - - /* if the auth algorithm does not have a null value - * for the kx2 generation then it supports it! - */ - GNUTLS_KX_ALG_LOOP(ret2 = - p->auth_struct->gnutls_generate_server_kx2); - if (ret2 != NULL) - ret = 1; - - return ret; - -} - -int _gnutls_kx_client_key_exchange0(KXAlgorithm algorithm) -{ - size_t ret = 0; - void *ret2 = NULL; - - /* if the auth algorithm does not have a null value - * for the kx0 generation then it supports it! - */ - GNUTLS_KX_ALG_LOOP(ret2 = - p->auth_struct->gnutls_process_client_kx0); - if (ret2 != NULL) - ret = 1; - - return ret; - -} - -int _gnutls_kx_client_key_exchange(KXAlgorithm algorithm) -{ - size_t ret = 0; - void *ret2 = NULL; - - /* if the auth algorithm does not have a null value - * for the kx0 generation then it supports it! - */ - GNUTLS_KX_ALG_LOOP(ret2 = - p->auth_struct->gnutls_process_client_kx); - if (ret2 != NULL) - ret = 1; - return ret; - -} - - -int _gnutls_kx_client_cert_vrfy(KXAlgorithm algorithm) -{ - size_t ret = 0; - void *ret2 = NULL; - - /* if the auth algorithm does not have a null value - * for the cert_vrfy function then it supports it! - */ - GNUTLS_KX_ALG_LOOP(ret2 = - p->auth_struct-> - gnutls_generate_client_cert_vrfy); - if (ret2 != NULL) - ret = 1; - - return ret; - -} - -int _gnutls_kx_server_cert_vrfy(KXAlgorithm algorithm) -{ - size_t ret = 0; - void *ret2 = NULL; - - /* if the auth algorithm does not have a null value - * for the cert_vrfy function then it supports it! - */ - GNUTLS_KX_ALG_LOOP(ret2 = - p->auth_struct-> - gnutls_generate_server_cert_vrfy); - if (ret2 != NULL) - ret = 1; - - return ret; - -} - -int _gnutls_kx_client_certificate(KXAlgorithm algorithm) -{ /* In bytes */ - size_t ret = 0; - GNUTLS_KX_ALG_LOOP(ret = p->client_cert); - return ret; - -} - -int _gnutls_kx_RSA_premaster(KXAlgorithm algorithm) -{ /* In bytes */ - size_t ret = 0; - GNUTLS_KX_ALG_LOOP(ret = p->RSA_premaster); - return ret; - -} - -int _gnutls_kx_DH_public_value(KXAlgorithm algorithm) -{ /* In bytes */ - size_t ret = 0; - GNUTLS_KX_ALG_LOOP(ret = p->DH_public_value); - return ret; - -} - /** * gnutls_kx_get_name - Returns a string with the name of the specified key exchange algorithm * @algorithm: is a key exchange algorithm diff --git a/lib/gnutls_algorithms.h b/lib/gnutls_algorithms.h index a0186eb837..ec1014c099 100644 --- a/lib/gnutls_algorithms.h +++ b/lib/gnutls_algorithms.h @@ -58,21 +58,6 @@ char *gnutls_cipher_get_name(BulkCipherAlgorithm algorithm); /* functions for key exchange */ int _gnutls_kx_priority(GNUTLS_STATE state, KXAlgorithm algorithm); -int _gnutls_kx_server_certificate(KXAlgorithm algorithm); - -/* key exchange */ -int _gnutls_kx_server_key_exchange(KXAlgorithm algorithm); -int _gnutls_kx_server_key_exchange2(KXAlgorithm algorithm); -int _gnutls_kx_client_key_exchange(KXAlgorithm algorithm); -int _gnutls_kx_client_key_exchange0(KXAlgorithm algorithm); -/* client certificate */ -int _gnutls_kx_client_certificate(KXAlgorithm algorithm); -int _gnutls_kx_RSA_premaster(KXAlgorithm algorithm); -int _gnutls_kx_DH_public_value(KXAlgorithm algorithm); - -/* cert vrfy */ -int _gnutls_kx_client_cert_vrfy(KXAlgorithm algorithm); -int _gnutls_kx_server_cert_vrfy(KXAlgorithm algorithm); MOD_AUTH_STRUCT * _gnutls_kx_auth_struct(KXAlgorithm algorithm); char *gnutls_kx_get_name(KXAlgorithm algorithm); diff --git a/lib/gnutls_auth.h b/lib/gnutls_auth.h index c673e2598b..bffd973ff5 100644 --- a/lib/gnutls_auth.h +++ b/lib/gnutls_auth.h @@ -10,6 +10,7 @@ typedef struct { int (*gnutls_generate_client_cert_vrfy) ( GNUTLS_KEY, opaque**); int (*gnutls_generate_server_cert_vrfy) ( GNUTLS_KEY, 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); diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index f268270941..0c15b74a4a 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -227,8 +227,6 @@ int _gnutls_create_random(opaque * dst) * since SSL version 2.0 is not supported). */ -#define DECR_LEN(len, x) len-=x; if (len<0) {gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;} - int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, int datalen) { @@ -600,23 +598,6 @@ int _gnutls_recv_handshake(SOCKET cd, GNUTLS_STATE state, uint8 ** data, int handshake_headers = HANDSHAKE_HEADERS_SIZE; HandshakeType recv_type; - if (type == GNUTLS_CERTIFICATE) { - /* If the ciphersuite does not support certificate just quit */ - if (state->security_parameters.entity == GNUTLS_CLIENT) { - if (_gnutls_kx_server_certificate - (_gnutls_cipher_suite_get_kx_algo - (state->security_parameters. - current_cipher_suite)) == 0) - return 0; - } else { /* server */ - if (_gnutls_kx_client_certificate - (_gnutls_cipher_suite_get_kx_algo - (state->security_parameters. - current_cipher_suite)) == 0) - return 0; - } - } - dataptr = gnutls_malloc(HANDSHAKE_HEADERS_SIZE); ret = @@ -728,11 +709,7 @@ int _gnutls_recv_handshake(SOCKET cd, GNUTLS_STATE state, uint8 ** data, length32); break; case GNUTLS_CERTIFICATE: - ret = - _gnutls_recv_certificate(cd, state, - &dataptr - [HANDSHAKE_HEADERS_SIZE], - length32); + ret = length32; break; case GNUTLS_SERVER_HELLO_DONE: ret = 0; @@ -929,7 +906,8 @@ static int _gnutls_read_server_hello(GNUTLS_STATE state, char *data, current_cipher_suite)); #endif - /* check if the credentials (username, public key etc. are ok - actually check if they exist) + /* check if the credentials (username, public key etc. are ok). + * Actually checks if they exist. */ if (_gnutls_get_kx_cred (state->gnutls_key, @@ -1202,48 +1180,6 @@ int _gnutls_recv_hello(SOCKET cd, GNUTLS_STATE state, char *data, return ret; } -int _gnutls_recv_certificate(SOCKET cd, GNUTLS_STATE state, char *data, - int datalen) -{ - int pos = 0; - char *certificate_list; - int ret = 0; - uint32 sizeOfCert; - - if (state->security_parameters.entity == GNUTLS_CLIENT) { - if (datalen < 2) { - gnutls_assert(); - return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; - } - - sizeOfCert = READuint24(&data[pos]); - pos += 3; - - if (sizeOfCert > MAX24) { - gnutls_assert(); - return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; - } - certificate_list = gnutls_malloc(sizeOfCert); - - memcpy(certificate_list, &data[pos], sizeOfCert); - - /* Verify certificates !!! */ - - gnutls_free(certificate_list); /* oooops! */ - - } else { /* Server side reading a client certificate */ - /* actually this is not complete */ - if (datalen < 1) { - gnutls_assert(); - return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; - } - - ret = 0; - } - - return ret; -} - /** * gnutls_handshake - This the main function in the handshake protocol. @@ -1322,10 +1258,9 @@ int gnutls_handshake_begin(SOCKET cd, GNUTLS_STATE state) /* RECV CERTIFICATE */ if (state->gnutls_internals.resumed == RESUME_FALSE) /* if we are not resuming */ - ret = - _gnutls_recv_handshake(cd, state, NULL, NULL, - GNUTLS_CERTIFICATE); + ret = _gnutls_recv_certificate( cd, state); if (ret < 0) { + gnutls_assert(); ERR("recv server certificate", ret); gnutls_clearHashDataBuffer(state); return ret; diff --git a/lib/gnutls_handshake.h b/lib/gnutls_handshake.h index cbdbf5def0..81c041d1ec 100644 --- a/lib/gnutls_handshake.h +++ b/lib/gnutls_handshake.h @@ -26,7 +26,6 @@ int _gnutls_recv_hello(int cd, GNUTLS_STATE state, char* data, int datalen); int gnutls_handshake(int cd, GNUTLS_STATE state); int _gnutls_recv_handshake( int cd, GNUTLS_STATE state, uint8**, int*, HandshakeType); int _gnutls_generate_session_id( char* session_id, uint8* len); -int _gnutls_recv_certificate(int cd, GNUTLS_STATE state, char *data, int datalen); int gnutls_handshake_begin(int cd, GNUTLS_STATE state); int gnutls_handshake_finish(int cd, GNUTLS_STATE state); void _gnutls_set_server_random( GNUTLS_STATE state, uint8* random); diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 7c25b6d3cf..b1e24ac9ad 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -27,11 +27,11 @@ #define READ_DEBUG #define WRITE_DEBUG #define BUFFERS_DEBUG -#define HANDSHAKE_DEBUG #define RECORD_DEBUG #define HARD_DEBUG -#define DEBUG +#define HANDSHAKE_DEBUG */ +#define DEBUG #define SOCKET int #define LIST ... @@ -63,9 +63,6 @@ # include <gnutls_gcry.h> #endif -#define GNUTLS_MPI MPI -#define gnutls_mpi_release mpi_release - #define svoid void /* for functions that allocate using secure_free */ #define secure_free gnutls_free #define secure_malloc malloc @@ -76,6 +73,8 @@ #define gnutls_calloc calloc #define gnutls_free free +#define DECR_LEN(len, x) len-=x; if (len<0) {gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;} + typedef unsigned char opaque; typedef struct { opaque pint[3]; } uint24; @@ -91,7 +90,8 @@ typedef enum AlertDescription { GNUTLS_CLOSE_NOTIFY, GNUTLS_UNEXPECTED_MESSAGE=1 GNUTLS_INSUFFICIENT_SECURITY, GNUTLS_INTERNAL_ERROR=80, GNUTLS_USER_CANCELED=90, GNUTLS_NO_RENEGOTIATION=100 } AlertDescription; - +typedef enum CertificateStatus { GNUTLS_VERIFIED, GNUTLS_NOT_VERIFIED, GNUTLS_EXPIRED, GNUTLS_INVALID } CertificateStatus; + typedef enum HandshakeType { GNUTLS_HELLO_REQUEST, GNUTLS_CLIENT_HELLO, GNUTLS_SERVER_HELLO, GNUTLS_CERTIFICATE=11, GNUTLS_SERVER_KEY_EXCHANGE, GNUTLS_CERTIFICATE_REQUEST, GNUTLS_SERVER_HELLO_DONE, diff --git a/lib/gnutls_kx.c b/lib/gnutls_kx.c index 261ece77d1..406075302f 100644 --- a/lib/gnutls_kx.c +++ b/lib/gnutls_kx.c @@ -30,7 +30,6 @@ #define MASTER_SECRET "master secret" static int generate_normal_master( GNUTLS_STATE state); -static int generate_resumed_master( GNUTLS_STATE state); int _gnutls_generate_master( GNUTLS_STATE state) { if (state->gnutls_internals.resumed==RESUME_FALSE) @@ -85,50 +84,6 @@ char random[2*TLS_RANDOM_SIZE]; return ret; } -static int generate_resumed_master( GNUTLS_STATE state) { -int premaster_size; -#ifdef HARD_DEBUG -int i; -#endif -opaque* premaster, *master; -int ret = 0; -char random[2*TLS_RANDOM_SIZE]; - - memmove(random, state->security_parameters.client_random, TLS_RANDOM_SIZE); - memmove(&random[TLS_RANDOM_SIZE], state->security_parameters.server_random, TLS_RANDOM_SIZE); - - /* generate premaster */ - premaster_size = sizeof(state->security_parameters.master_secret); - premaster = state->security_parameters.master_secret; - -#ifdef HARD_DEBUG - fprintf(stderr, "RESUME...\n"); - fprintf(stderr, "PREMASTER SECRET[%d]: %s\n", premaster_size, _gnutls_bin2hex(premaster, premaster_size)); - fprintf(stderr, "CLIENT RANDOM[%d]: %s\n", 32, _gnutls_bin2hex(state->security_parameters.client_random,32)); - fprintf(stderr, "SERVER RANDOM[%d]: %s\n", 32, _gnutls_bin2hex(state->security_parameters.server_random,32)); -#endif - - if (_gnutls_version_ssl3(state->connection_state.version) == 0) { - master = - gnutls_ssl3_generate_random( premaster, premaster_size, - random, 2*TLS_RANDOM_SIZE, TLS_MASTER_SIZE); - - } else { - master = - gnutls_PRF( premaster, premaster_size, - MASTER_SECRET, strlen(MASTER_SECRET), - random, 2*TLS_RANDOM_SIZE, TLS_MASTER_SIZE); - } - -#ifdef HARD_DEBUG - fprintf(stderr, "MASTER SECRET: %s\n", _gnutls_bin2hex(master, TLS_MASTER_SIZE)); -#endif - if (master==NULL) return GNUTLS_E_MEMORY_ERROR; - - memmove(state->security_parameters.master_secret, master, TLS_MASTER_SIZE); - secure_free(master); - return ret; -} /* This is called when we want to receive the key exchange message of the * server. It does nothing if this type of message is not required @@ -171,12 +126,8 @@ int _gnutls_send_server_kx_message2(SOCKET cd, GNUTLS_STATE state) uint8 *data = NULL; int data_size = 0; int ret = 0; - KXAlgorithm algorithm = - _gnutls_cipher_suite_get_kx_algo - (state->security_parameters.current_cipher_suite); - - if (_gnutls_kx_server_key_exchange2(algorithm) != 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); #ifdef HARD_DEBUG @@ -207,11 +158,9 @@ int _gnutls_send_client_kx_message(SOCKET cd, GNUTLS_STATE state) uint8 *data; int data_size; int ret = 0; - KXAlgorithm algorithm = - _gnutls_cipher_suite_get_kx_algo - (state->security_parameters.current_cipher_suite); - if (_gnutls_kx_client_key_exchange(algorithm) == 0) return 0; + if (state->gnutls_internals.auth_struct->gnutls_generate_client_kx==NULL) + return 0; #ifdef HARD_DEBUG { @@ -220,7 +169,6 @@ int _gnutls_send_client_kx_message(SOCKET cd, GNUTLS_STATE state) } #endif - data_size = state->gnutls_internals.auth_struct->gnutls_generate_client_kx( state->gnutls_key, &data); if (data_size < 0) { gnutls_assert(); @@ -245,11 +193,9 @@ int _gnutls_send_client_kx_message0(SOCKET cd, GNUTLS_STATE state) uint8 *data; int data_size; int ret = 0; - KXAlgorithm algorithm = - _gnutls_cipher_suite_get_kx_algo - (state->security_parameters.current_cipher_suite); - if (_gnutls_kx_client_key_exchange0(algorithm) == 0) return 0; + if ( state->gnutls_internals.auth_struct->gnutls_generate_client_kx0 == NULL) + return 0; #ifdef HARD_DEBUG { @@ -281,14 +227,11 @@ int _gnutls_send_client_certificate_verify(SOCKET cd, GNUTLS_STATE state) uint8 *data; int ret = 0; int data_size; - KXAlgorithm algorithm = - _gnutls_cipher_suite_get_kx_algo - (state->security_parameters.current_cipher_suite); /* if certificate verify is not needed just exit */ if (state->gnutls_internals.certificate_verify_needed==0) return 0; - if (_gnutls_kx_client_cert_vrfy(algorithm)==0) { + if (state->gnutls_internals.auth_struct->gnutls_generate_client_cert_vrfy==NULL) { return 0; /* this algorithm does not support cli_cert_vrfy */ } @@ -310,7 +253,6 @@ int _gnutls_send_client_certificate_verify(SOCKET cd, GNUTLS_STATE state) int _gnutls_recv_server_kx_message(SOCKET cd, GNUTLS_STATE state) { - KXAlgorithm algorithm; uint8 *data; int datasize; int ret = 0; @@ -318,11 +260,8 @@ int _gnutls_recv_server_kx_message(SOCKET cd, GNUTLS_STATE state) #ifdef HARD_DEBUG fprintf(stderr, "Receiving Server KX message\n"); #endif - algorithm = - _gnutls_cipher_suite_get_kx_algo - (state->security_parameters.current_cipher_suite); - if (_gnutls_kx_server_key_exchange(algorithm) != 0) { + if (state->gnutls_internals.auth_struct->gnutls_process_server_kx!=NULL) { ret = _gnutls_recv_handshake(cd, state, &data, &datasize, @@ -342,7 +281,6 @@ int _gnutls_recv_server_kx_message(SOCKET cd, GNUTLS_STATE state) int _gnutls_recv_server_kx_message2(SOCKET cd, GNUTLS_STATE state) { - KXAlgorithm algorithm; uint8 *data; int datasize; int ret = 0; @@ -350,11 +288,8 @@ int _gnutls_recv_server_kx_message2(SOCKET cd, GNUTLS_STATE state) #ifdef HARD_DEBUG fprintf(stderr, "Receiving Server KX message2\n"); #endif - algorithm = - _gnutls_cipher_suite_get_kx_algo - (state->security_parameters.current_cipher_suite); - if (_gnutls_kx_server_key_exchange2(algorithm) != 0) { + if (state->gnutls_internals.auth_struct->gnutls_process_server_kx2 != NULL) { ret = _gnutls_recv_handshake(cd, state, &data, &datasize, @@ -374,7 +309,6 @@ int _gnutls_recv_server_kx_message2(SOCKET cd, GNUTLS_STATE state) int _gnutls_recv_client_kx_message(SOCKET cd, GNUTLS_STATE state) { - KXAlgorithm algorithm; uint8 *data; #ifdef HARD_DEBUG int i; @@ -386,12 +320,8 @@ int _gnutls_recv_client_kx_message(SOCKET cd, GNUTLS_STATE state) fprintf(stderr, "Receiving client KX message\n"); #endif - algorithm = - _gnutls_cipher_suite_get_kx_algo - (state->security_parameters.current_cipher_suite); - /* Do key exchange only if the algorithm permits it */ - if (_gnutls_kx_client_key_exchange(algorithm) != 0) { + if (state->gnutls_internals.auth_struct->gnutls_process_client_kx != NULL) { ret = _gnutls_recv_handshake(cd, state, &data, @@ -413,7 +343,6 @@ int _gnutls_recv_client_kx_message(SOCKET cd, GNUTLS_STATE state) /* only used in SRP */ int _gnutls_recv_client_kx_message0(SOCKET cd, GNUTLS_STATE state) { - KXAlgorithm algorithm; uint8 *data; #ifdef HARD_DEBUG int i; @@ -425,12 +354,8 @@ int _gnutls_recv_client_kx_message0(SOCKET cd, GNUTLS_STATE state) fprintf(stderr, "Receiving client KX message0\n"); #endif - algorithm = - _gnutls_cipher_suite_get_kx_algo - (state->security_parameters.current_cipher_suite); - /* Do key exchange only if the algorithm permits it */ - if (_gnutls_kx_client_key_exchange0(algorithm) != 0) { + if (state->gnutls_internals.auth_struct->gnutls_process_client_kx0 != NULL) { ret = _gnutls_recv_handshake(cd, state, &data, @@ -481,3 +406,31 @@ int _gnutls_send_certificate(SOCKET cd, GNUTLS_STATE state) return data_size; } + +int _gnutls_recv_certificate(SOCKET cd, GNUTLS_STATE state) +{ + int datasize; + opaque * data; + int ret = 0; + + if (state->gnutls_internals.auth_struct->gnutls_process_certificate!=NULL) { + + ret = + _gnutls_recv_handshake(cd, state, &data, + &datasize, + GNUTLS_CERTIFICATE); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = state->gnutls_internals.auth_struct->gnutls_process_certificate( state->gnutls_key, data, datasize); + gnutls_free(data); + if (ret < 0) { + gnutls_assert(); + return ret; + } + } + + return ret; +} diff --git a/lib/gnutls_kx.h b/lib/gnutls_kx.h index 68ab4a3b9e..3a3b2e54b8 100644 --- a/lib/gnutls_kx.h +++ b/lib/gnutls_kx.h @@ -29,3 +29,4 @@ int _gnutls_recv_client_kx_message0(int cd, GNUTLS_STATE state); int _gnutls_send_client_certificate_verify(int cd, GNUTLS_STATE state); int _gnutls_send_certificate(int cd, GNUTLS_STATE state); int _gnutls_generate_master( GNUTLS_STATE state); +int _gnutls_recv_certificate(SOCKET cd, GNUTLS_STATE state); diff --git a/lib/gnutls_v2_compat.c b/lib/gnutls_v2_compat.c index f441baee8c..d4c4bfe098 100644 --- a/lib/gnutls_v2_compat.c +++ b/lib/gnutls_v2_compat.c @@ -94,8 +94,6 @@ static int SelectSuite_v2(GNUTLS_STATE state, opaque ret[2], char *data, } -#define DECR_LEN(len, x) len-=x; if (len<0) {gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;} - /* Read a v2 client hello. Some browsers still use that beast! * However they set their version to 3.0 or 3.1. */ @@ -40,6 +40,8 @@ #define MAX(X,Y) (X >= Y ? X : Y); +#include "pk.h" + static int print_info( GNUTLS_STATE state) { char *tmp; const ANON_AUTH_INFO *dh_info; @@ -87,11 +89,14 @@ int main() struct timeval tv; int user_term = 0; SRP_CLIENT_CREDENTIALS cred; - + X509PKI_CLIENT_CREDENTIALS xcred; + + PARSE(); + cred.username = "test"; cred.password = "test"; -// signal(SIGPIPE, SIG_IGN); + signal(SIGPIPE, SIG_IGN); sd = socket(AF_INET, SOCK_STREAM, 0); ERR(sd, "socket"); @@ -110,9 +115,10 @@ int main() gnutls_set_cipher_priority( state, GNUTLS_3DES_CBC, GNUTLS_ARCFOUR, GNUTLS_RIJNDAEL_CBC, 0); gnutls_set_compression_priority( state, GNUTLS_ZLIB, GNUTLS_NULL_COMPRESSION, 0); - gnutls_set_kx_priority( state, GNUTLS_KX_SRP, GNUTLS_KX_DH_ANON, 0); + gnutls_set_kx_priority( state, GNUTLS_KX_RSA, GNUTLS_KX_SRP, GNUTLS_KX_DH_ANON, 0); gnutls_set_cred( state, GNUTLS_ANON, NULL); gnutls_set_cred( state, GNUTLS_SRP, &cred); + gnutls_set_cred( state, GNUTLS_X509PKI, &xcred); gnutls_set_mac_priority( state, GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0); ret = gnutls_handshake(sd, state); @@ -158,9 +164,10 @@ int main() gnutls_set_cipher_priority( state, GNUTLS_3DES_CBC, GNUTLS_TWOFISH_CBC, GNUTLS_RIJNDAEL_CBC, GNUTLS_ARCFOUR, 0); gnutls_set_compression_priority( state, GNUTLS_NULL_COMPRESSION, 0); - gnutls_set_kx_priority( state, GNUTLS_KX_SRP, GNUTLS_KX_DH_ANON, 0); + gnutls_set_kx_priority( state, GNUTLS_KX_RSA, GNUTLS_KX_SRP, GNUTLS_KX_DH_ANON, 0); gnutls_set_cred( state, GNUTLS_ANON, NULL); gnutls_set_cred( state, GNUTLS_SRP, &cred); + gnutls_set_cred( state, GNUTLS_X509PKI, &xcred); gnutls_set_mac_priority( state, GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0); diff --git a/src/serv.c b/src/serv.c index 24091ac960..8cfb019fe8 100644 --- a/src/serv.c +++ b/src/serv.c @@ -30,9 +30,8 @@ #include "../lib/gnutls.h" #include <port.h> #include <signal.h> +#include "pk.h" -#define PKIX "pkix.asn" -#define PKCS "pkcs1.asn" #define KEYFILE "key.pem" #define CERTFILE "cert.pem" @@ -46,32 +45,6 @@ static char http_buffer[16*1024]; * command line is present */ -void PARSE() -{ - /* this is to be moved to gnutls */ - int result = parser_asn1(PKIX); - - signal( SIGPIPE, SIG_IGN); - - if (result == ASN_SYNTAX_ERROR) { - printf("%s: PARSE ERROR\n", PKIX); - return; - } else if (result == ASN_IDENTIFIER_NOT_FOUND) { - printf("%s: IDENTIFIER NOT FOUND\n", PKIX); - return; - } - - result = parser_asn1(PKCS); - - if (result == ASN_SYNTAX_ERROR) { - printf("%s: PARSE ERROR\n", PKCS); - return; - } else if (result == ASN_IDENTIFIER_NOT_FOUND) { - printf("%s: IDENTIFIER NOT FOUND\n", PKCS); - return; - } - -} #define SA struct sockaddr #define ERR(err,s) if(err==-1) {perror(s);return(1);} @@ -114,12 +87,12 @@ GNUTLS_STATE initialize_state() gnutls_init(&state, GNUTLS_SERVER); if ((ret = gnutls_set_db_name(state, "gnutls-rsm.db")) < 0) - fprintf(stderr, "*** DB error (%d)\n", ret); + fprintf(stderr, "*** DB error (%d)\n\n", ret); /* null cipher is here only for debuging * purposes. */ - gnutls_set_cipher_priority(state, GNUTLS_NULL_CIPHER, GNUTLS_ARCFOUR, + gnutls_set_cipher_priority(state, GNUTLS_NULL_CIPHER, GNUTLS_RIJNDAEL_CBC, GNUTLS_3DES_CBC, 0); gnutls_set_compression_priority(state, GNUTLS_ZLIB, GNUTLS_NULL_COMPRESSION, 0); gnutls_set_kx_priority(state, GNUTLS_KX_RSA, GNUTLS_KX_SRP, @@ -349,7 +322,7 @@ int main(int argc, char **argv) close(sd); gnutls_deinit(state); tmp = gnutls_strerror(ret); - fprintf(stderr, "*** Handshake has failed (%s)\n", + fprintf(stderr, "*** Handshake has failed (%s)\n\n", tmp); free(tmp); continue; @@ -370,7 +343,7 @@ int main(int argc, char **argv) break; } else { fprintf(stderr, - "\n*** Received corrupted data(%d). Closing the connection.\n", + "\n*** Received corrupted data(%d). Closing the connection.\n\n", ret); break; } |