From: Nikos Mavrogiannopoulos Date: Sun, 17 Jun 2001 11:26:56 +0000 (+0000) Subject: several additions for RSA (mostly unstable) X-Git-Tag: gnutls_0_1_4~18 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c7dc6cd5d3a4a2cb643e5ebec227a753fc2ff0ee;p=thirdparty%2Fgnutls.git several additions for RSA (mostly unstable) --- diff --git a/lib/Makefile.am b/lib/Makefile.am index ae4a52eeb3..11432f7841 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -14,9 +14,9 @@ EXTRA_DIST = debug.h gnutls_compress.h defines.h gnutls_plaintext.h \ cert_b64.h gnutls_srp.h auth_srp.h auth_srp_passwd.h gnutls_v2_compat.h \ crypt.h libgnutls-config.in libgnutls.m4 gnutls.h.in gnutls_errors_int.h \ cert_asn1.h cert_der.h gnutls_datum.h auth_x509.h gnutls_gcry.h \ - ext_dnsname.h + ext_dnsname.h gnutls_pk.h lib_LTLIBRARIES = libgnutls.la -libgnutls_la_SOURCES = gnutls.c gnutls_compress.c debug.c gnutls_plaintext.c \ +libgnutls_la_SOURCES = gnutls_record.c gnutls_compress.c debug.c gnutls_plaintext.c \ gnutls_cipher.c gnutls_buffers.c gnutls_handshake.c gnutls_num.c \ gnutls_errors.c gnutls_algorithms.c gnutls_dh.c gnutls_kx.c \ gnutls_priority.c gnutls_hash_int.c gnutls_cipher_int.c \ @@ -25,6 +25,6 @@ libgnutls_la_SOURCES = gnutls.c gnutls_compress.c debug.c gnutls_plaintext.c \ crypt_bcrypt.c crypt.c gnutls_random.c crypt_srpsha1.c gnutls_srp.c \ auth_srp.c auth_srp_passwd.c gnutls_v2_compat.c auth_srp_sb64.c \ cert_ASN.y cert_asn1.c cert_der.c gnutls_datum.c auth_rsa.c \ - gnutls_gcry.c ext_dnsname.c + gnutls_gcry.c ext_dnsname.c gnutls_pk.c gnutls_cert.c libgnutls_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) diff --git a/lib/auth_rsa.c b/lib/auth_rsa.c index 9b72d9ceea..d92622f514 100644 --- a/lib/auth_rsa.c +++ b/lib/auth_rsa.c @@ -28,6 +28,8 @@ #include "cert_der.h" #include "gnutls_datum.h" #include "auth_x509.h" +#include +#include #if 0 int gen_rsa_server_kx(GNUTLS_KEY, opaque **); @@ -114,7 +116,10 @@ static int _gnutls_get_rsa_params( GNUTLS_KEY key, RSA_Params * params, gnutls_d opaque str[5*1024]; int len = sizeof(str); - create_structure("certificate2", "PKIX1Explicit88.Certificate"); + if (create_structure("certificate2", "PKIX1Explicit88.Certificate")!=ASN_OK) { + gnutls_assert(); + return GNUTLS_E_PARSING_ERROR; + } result = get_der("certificate2", cert.data, cert.size); if (result != ASN_OK) { @@ -143,7 +148,11 @@ static int _gnutls_get_rsa_params( GNUTLS_KEY key, RSA_Params * params, gnutls_d return GNUTLS_E_PARSING_ERROR; } - create_structure("rsapublickey", "PKIX1Explicit88.RSAPublicKey"); + if (create_structure("rsapublickey", "PKIX1Explicit88.RSAPublicKey")!=ASN_OK) { + gnutls_assert(); + return GNUTLS_E_PARSING_ERROR; + } + result = get_der("rsapublickey", str, len); if (result != ASN_OK) { gnutls_assert(); @@ -217,35 +226,38 @@ static int _gnutls_get_private_rsa_params( GNUTLS_KEY key, gnutls_datum cert) opaque str[5*1024]; int len = sizeof(str); - create_structure("rsa_key", "PKCS-1"); + if (create_structure("rsakey", "PKCS-1.RSAPrivateKey")!=ASN_OK) { + gnutls_assert(); + return GNUTLS_E_PARSING_ERROR; + } - result = get_der("rsa_key", cert.data, cert.size); + result = get_der("rsakey", cert.data, cert.size); if (result != ASN_OK) { gnutls_assert(); return GNUTLS_E_PARSING_ERROR; } result = - read_value("rsa_key.RSAPrivateKey.privateExponent", str, &len); + read_value("rsakey.privateExponent", str, &len); if (result != ASN_OK) { gnutls_assert(); - delete_structure("rsa_key"); + delete_structure("rsakey"); return GNUTLS_E_PARSING_ERROR; } if (gcry_mpi_scan(&key->u, GCRYMPI_FMT_USG, str, &len) != 0) { gnutls_assert(); - delete_structure("rsa_key"); + delete_structure("rsakey"); return GNUTLS_E_MPI_SCAN_FAILED; } len = sizeof(str); result = - read_value("rsa_key.modulus", str, &len); + read_value("rsakey.modulus", str, &len); if (result != ASN_OK) { gnutls_assert(); - delete_structure("rsa_key"); + delete_structure("rsakey"); _gnutls_mpi_release(&key->u); return GNUTLS_E_PARSING_ERROR; } @@ -253,12 +265,12 @@ static int _gnutls_get_private_rsa_params( GNUTLS_KEY key, gnutls_datum cert) if (gcry_mpi_scan(&key->A, GCRYMPI_FMT_USG, str, &len) != 0) { gnutls_assert(); - delete_structure("rsa_key"); + delete_structure("rsakey"); _gnutls_mpi_release(&key->u); return GNUTLS_E_MPI_SCAN_FAILED; } - delete_structure("rsa_key"); + delete_structure("rsakey"); return ret; } @@ -315,7 +327,7 @@ int gen_rsa_server_kx(GNUTLS_KEY key, opaque ** data) int gen_rsa_certificate(GNUTLS_KEY key, opaque ** data) { const X509PKI_SERVER_CREDENTIALS *cred; - int ret, i; + int ret, i, pdatasize; opaque* pdata; gnutls_datum* apr_cert_list; gnutls_datum apr_pkey; @@ -359,7 +371,8 @@ int gen_rsa_certificate(GNUTLS_KEY key, opaque ** data) WRITEdatum24( pdata, apr_cert_list[i]); pdata += 3 + apr_cert_list[i].size; } - + pdatasize = ret; + /* read the rsa parameters now, since later we will * now know which certificate we used! */ @@ -371,19 +384,44 @@ int gen_rsa_certificate(GNUTLS_KEY key, opaque ** data) return ret; } - return ret; + return pdatasize; } +#define RANDOMIZE_X(x) x.size=48; x.data=gnutls_malloc(x.size); \ + if (x.data==NULL) return GNUTLS_E_MEMORY_ERROR; \ + if (_gnutls_get_random( key->key.data, key->key.size, GNUTLS_WEAK_RANDOM) < 0) { \ + return GNUTLS_E_MEMORY_ERROR; \ + } int proc_rsa_client_kx( GNUTLS_KEY key, opaque* data, int data_size) { - const X509PKI_SERVER_CREDENTIALS * cred; - - cred = _gnutls_get_cred(key, GNUTLS_X509PKI, NULL); - if (cred == NULL) { + gnutls_datum plaintext; + gnutls_datum ciphertext; + int ret, dsize; + + ciphertext.data = &data[2]; + dsize = READuint16(data); + ciphertext.size = GMIN(dsize, data_size); + + ret = _gnutls_pkcs1_rsa_decrypt(&plaintext, ciphertext, key->u, key->A); + if ( ret < 0) { + /* in case decryption fails then don't inform + * the peer. Just use a random key. (in order to avoid + * attack against pkcs-1 formating). + */ gnutls_assert(); - return GNUTLS_E_INSUFICIENT_CRED; + RANDOMIZE_X(key->key); + } else { + if (plaintext.size != 48) { /* WOW */ + RANDOMIZE_X(key->key); + } else { + key->key.data = plaintext.data; + key->key.size = plaintext.size; + } } + _gnutls_mpi_release( &key->A); + _gnutls_mpi_release( &key->B); + _gnutls_mpi_release( &key->u); return 0; } diff --git a/lib/auth_srp.c b/lib/auth_srp.c index 08d1d3b697..5a15f7cec5 100644 --- a/lib/auth_srp.c +++ b/lib/auth_srp.c @@ -103,9 +103,9 @@ int gen_srp_server_kx(GNUTLS_KEY key, opaque ** data) N = gcry_mpi_alloc_like(pwd_entry->n); V = gcry_mpi_alloc_like(pwd_entry->v); - mpi_set(G, pwd_entry->g); - mpi_set(N, pwd_entry->n); - mpi_set(V, pwd_entry->v); + gcry_mpi_set(G, pwd_entry->g); + gcry_mpi_set(N, pwd_entry->n); + gcry_mpi_set(V, pwd_entry->v); (*data) = gnutls_malloc(n_n + n_g + pwd_entry->salt_size + 6 + 1); diff --git a/lib/auth_srp_passwd.c b/lib/auth_srp_passwd.c index 78483043ff..d63a76f1e2 100644 --- a/lib/auth_srp_passwd.c +++ b/lib/auth_srp_passwd.c @@ -283,7 +283,6 @@ GNUTLS_SRP_PWD_ENTRY *_gnutls_srp_pwd_read_entry( GNUTLS_KEY key, char* username GNUTLS_SRP_PWD_ENTRY* _gnutls_randomize_pwd_entry() { GNUTLS_SRP_PWD_ENTRY * pwd_entry = gnutls_malloc(sizeof(GNUTLS_SRP_PWD_ENTRY)); size_t n = sizeof diffie_hellman_group1_prime; - opaque * rand; pwd_entry->username = gnutls_malloc(strlen(RNDUSER)+1); strcpy( pwd_entry->username, RNDUSER); @@ -299,10 +298,12 @@ GNUTLS_SRP_PWD_ENTRY* _gnutls_randomize_pwd_entry() { } pwd_entry->salt_size = RND_SALT_SIZE; - rand = _gnutls_get_random(RND_SALT_SIZE, GNUTLS_WEAK_RANDOM); + pwd_entry->salt = gnutls_malloc(RND_SALT_SIZE); - memcpy( pwd_entry->salt, rand, RND_SALT_SIZE); - _gnutls_free_rand( rand); + if (_gnutls_get_random(pwd_entry->salt, RND_SALT_SIZE, GNUTLS_WEAK_RANDOM) < 0) { + gnutls_assert(); + return NULL; + } pwd_entry->algorithm = 0; diff --git a/lib/auth_x509.h b/lib/auth_x509.h index 8cfd1aed89..a0c477cbaf 100644 --- a/lib/auth_x509.h +++ b/lib/auth_x509.h @@ -1,5 +1,5 @@ /* this is not to be included by gnutls_anon.c */ -extern MOD_AUTH_STRUCT x509pki_auth_struct; +extern MOD_AUTH_STRUCT rsa_auth_struct; /* This structure may be complex but, it's the only way to * support a server that has multiple certificates @@ -12,7 +12,7 @@ typedef struct { * [1] certificate2, certificate22, ... */ int * cert_list_length; - /* contains the number of the certificates in one + /* contains the number of the certificates in a * row. */ int ncerts; /* contains the number of columns in cert_list. diff --git a/lib/cert_asn1.h b/lib/cert_asn1.h index a1d8354294..6d8be13f2e 100755 --- a/lib/cert_asn1.h +++ b/lib/cert_asn1.h @@ -173,5 +173,7 @@ create_structure(char *dest_name,char *source_name); int delete_structure(char *root_name); +int parser_asn1(char *file_name); + #endif diff --git a/lib/cert_b64.c b/lib/cert_b64.c index 9e05b65ee0..d593f256be 100644 --- a/lib/cert_b64.c +++ b/lib/cert_b64.c @@ -20,6 +20,7 @@ #include "defines.h" #include "gnutls_int.h" +#include "gnutls_errors.h" const static uint8 b64table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; @@ -296,12 +297,13 @@ inline static int cpydata(uint8 * data, int data_size, uint8 ** result) /* decodes data and puts the result into result (localy alocated) * The result_size is the return value + * FIXME: This function is a mess */ -int _gnutls_fbase64_decode(char *msg, uint8 * data, int data_size, +#define ENDSTR "-----\n" +int _gnutls_fbase64_decode( uint8 * data, int data_size, uint8 ** result) { - int i, ret, tmp, j; - uint8 tmpres[3]; + int i, ret; char top[80]; char bottom[80]; uint8 *rdata; @@ -310,59 +312,52 @@ int _gnutls_fbase64_decode(char *msg, uint8 * data, int data_size, int kdata_size; strcpy(top, "-----BEGIN "); - strcat(top, msg); - strcat(top, "-----"); strcpy(bottom, "\n-----END "); - strcat(bottom, msg); - strcat(bottom, "-----"); i = 0; do { rdata = &data[i]; - data_size -= i; + data_size --; i++; } while (data_size > 0 && strncmp(rdata, top, strlen(top)) != 0); - if (data_size < 4 + strlen(bottom)) + if (data_size < 4 + strlen(bottom)) { + gnutls_assert(); return -1; - data_size -= strlen(top); - rdata += strlen(top); + } + + do { + data_size--; + rdata++; + } while( ( strncmp( rdata, ENDSTR, strlen(ENDSTR)) != 0) && data_size > 0) ; + + data_size -= strlen(ENDSTR); + rdata += strlen(ENDSTR); rdata_size = 0; do { rdata_size++; } while (rdata_size < data_size - && strncmp(&rdata[rdata_size], bottom, - strlen(bottom)) != 0); + && strncmp(&rdata[rdata_size], bottom, strlen(bottom)) != 0); - if (rdata_size < 4) + if (rdata_size < 4) { + gnutls_assert(); return -1; + } kdata_size = cpydata(rdata, rdata_size, &kdata); - if (kdata_size < 4) + if (kdata_size < 4) { + gnutls_assert(); return -1; - - kdata_size /= 4; - kdata_size *= 4; - - ret = (kdata_size / 4) * 3; - (*result) = gnutls_malloc(ret); - if ((*result) == NULL) - return -1; - - for (i = j = 0; i < kdata_size; i += 4) { - tmp = decode(tmpres, &kdata[i]); - if (tmp < 0) { - gnutls_free( *result); - return tmp; - } - memcpy(&(*result)[j], tmpres, tmp); - if (tmp < 3) - ret -= (3 - tmp); - j += 3; } + + if ((ret = _gnutls_base64_decode( kdata, kdata_size, result)) < 0) { + gnutls_assert(); + gnutls_free(kdata); + return GNUTLS_E_PARSING_ERROR; + } gnutls_free(kdata); return ret; } diff --git a/lib/cert_b64.h b/lib/cert_b64.h index 58d4353044..94a546c2f1 100644 --- a/lib/cert_b64.h +++ b/lib/cert_b64.h @@ -2,5 +2,5 @@ int _gnutls_base64_encode(uint8 * data, int data_size, uint8 ** result); int _gnutls_fbase64_encode(char *msg, uint8 * data, int data_size, uint8 ** result); int _gnutls_base64_decode(uint8 * data, int data_size, uint8 ** result); -int _gnutls_fbase64_decode(char *msg, uint8 * data, int data_size, +int _gnutls_fbase64_decode( uint8 * data, int data_size, uint8 ** result); diff --git a/lib/crypt_bcrypt.c b/lib/crypt_bcrypt.c index 029fa8526a..b472c8993d 100644 --- a/lib/crypt_bcrypt.c +++ b/lib/crypt_bcrypt.c @@ -686,11 +686,14 @@ char *crypt_bcrypt_wrapper(const char* username, const char *pass_new, int cost, { opaque *result; char *tcp; - uint8 *rand; + uint8 rand[17]; char *e = NULL; int result_size; - rand = _gnutls_get_random(17, GNUTLS_WEAK_RANDOM); + if (_gnutls_get_random(&rand[1], 17, GNUTLS_WEAK_RANDOM) < 0 ) { + gnutls_assert(); + return NULL; + } /* cost should be <32 and >6 */ if (cost >= 32) cost = 31; @@ -698,11 +701,7 @@ char *crypt_bcrypt_wrapper(const char* username, const char *pass_new, int cost, cost = 1; rand[0] = (uint8) cost; - result_size = _gnutls_sbase64_encode( &rand[0], 17, &result); - - _gnutls_free_rand(rand); - - _gnutls_sbase64_decode( result, strlen(result), &rand); + result_size = _gnutls_sbase64_encode( rand, 17, &result); if (result_size < 0) { gnutls_assert(); diff --git a/lib/crypt_srpsha1.c b/lib/crypt_srpsha1.c index 46cade81ed..91ea1704a2 100644 --- a/lib/crypt_srpsha1.c +++ b/lib/crypt_srpsha1.c @@ -116,18 +116,22 @@ char *crypt_srpsha1_wrapper(const char *username, const char *pass_new, { unsigned char *result; char *tcp; - unsigned char *rand; + opaque *rand; char *e = NULL; int result_size; if (salt > 50 || salt <= 0) return NULL; /* wow that's pretty long salt */ - rand = _gnutls_get_random(salt, GNUTLS_WEAK_RANDOM); + rand = gnutls_malloc(salt); + if (rand==NULL || _gnutls_get_random(rand, salt, GNUTLS_WEAK_RANDOM) < 0) { + gnutls_assert(); + return NULL; + } result_size = _gnutls_sbase64_encode(rand, salt, &result); if (result_size < 0) { - _gnutls_free_rand(rand); + gnutls_free(rand); gnutls_assert(); return NULL; } @@ -136,7 +140,7 @@ char *crypt_srpsha1_wrapper(const char *username, const char *pass_new, sprintf(tcp, ":%s", result); gnutls_free(result); - _gnutls_free_rand(rand); + gnutls_free(rand); /* no longer need cleartext */ e = crypt_srpsha1(username, pass_new, (const char *) tcp, g, n); diff --git a/lib/gnutls.h.in b/lib/gnutls.h.in index 90406998d1..98bc6acd54 100644 --- a/lib/gnutls.h.in +++ b/lib/gnutls.h.in @@ -159,4 +159,10 @@ typedef struct { */ } X509PKI_SERVER_CREDENTIALS; +/* CERTFILE is an x509 certificate in PEM form. + * KEYFILE is a pkcs-1 private key in PEM form. + */ +int gnutls_read_certs(X509PKI_SERVER_CREDENTIALS * res, char *CERTFILE, + char *KEYFILE); + /* error codes appended here */ diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c index e1542bc323..d132c723ec 100644 --- a/lib/gnutls_algorithms.c +++ b/lib/gnutls_algorithms.c @@ -191,7 +191,7 @@ 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, &x509pki_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),*/ @@ -1093,6 +1093,7 @@ _gnutls_qsort(GNUTLS_STATE state, void *_base, size_t nmemb, size_t size, #ifdef DEBUG if (size > MAX_ELEM_SIZE) { gnutls_assert(); + fprintf(stderr, "QSORT BUG\n"); exit(1); } #endif @@ -1232,6 +1233,7 @@ _gnutls_supported_ciphersuites_sorted(GNUTLS_STATE state, for (i = 0; i < j; i++) fprintf(stderr, "\t%d: %s\n", i, _gnutls_cipher_suite_get_name((*ciphers)[i])); + fprintf(stderr, "SORT BUG\n"); exit(0); #endif diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c new file mode 100644 index 0000000000..9d7b39d00a --- /dev/null +++ b/lib/gnutls_cert.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2001 Nikos Mavroyanopoulos + * + * This file is part of GNUTLS. + * + * GNUTLS is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GNUTLS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include +#include +#include + +/* FIXME: this function is a mess + */ +int gnutls_read_certs(X509PKI_SERVER_CREDENTIALS * res, char *CERTFILE, + char *KEYFILE) +{ + FILE *fd1, *fd2; + char x[100 * 1024]; + int siz; + opaque *b64; + + fd1 = fopen(CERTFILE, "r"); + if (fd1 == NULL) + return GNUTLS_E_UNKNOWN_ERROR; + + fd2 = fopen(KEYFILE, "r"); + if (fd2 == NULL) { + fclose(fd1); + return GNUTLS_E_UNKNOWN_ERROR; + } + + siz = fread(x, 1, sizeof(x), fd1); + siz = _gnutls_fbase64_decode(x, siz, &b64); + + if (siz < 0) { + gnutls_assert(); + return GNUTLS_E_PARSING_ERROR; + } + + res->cert_list = (gnutls_datum**) gnutls_malloc(1*sizeof(gnutls_datum*)); + if (res->cert_list == NULL) + return GNUTLS_E_MEMORY_ERROR; + + res->cert_list[0] = (gnutls_datum*) gnutls_malloc(1*sizeof(gnutls_datum)); + if (res->cert_list[0] == NULL) + return GNUTLS_E_MEMORY_ERROR; + + res->cert_list_length = (int*) gnutls_malloc(1*sizeof(int*)); + if (res->cert_list_length == NULL) + return GNUTLS_E_MEMORY_ERROR; + + res->ncerts = 1; + + res->cert_list_length[0] = 1; + + res->cert_list[0][0].data = b64; + res->cert_list[0][0].size = siz; + + fclose(fd1); + + + + +/* second file */ + + siz = fread(x, 1, sizeof(x), fd2); + siz = _gnutls_fbase64_decode(x, siz, &b64); + + if (siz < 0) { + gnutls_assert(); + return GNUTLS_E_PARSING_ERROR; + } + + res->pkey = gnutls_malloc(1*sizeof(gnutls_datum)); + if (res->pkey == NULL) + return GNUTLS_E_MEMORY_ERROR; + + res->pkey[0].data = b64; + res->pkey[0].size = siz; + + fclose(fd2); + + return 0; +} diff --git a/lib/gnutls_cipher.c b/lib/gnutls_cipher.c index f250b8fbe9..2c9b24eeb5 100644 --- a/lib/gnutls_cipher.c +++ b/lib/gnutls_cipher.c @@ -435,7 +435,7 @@ int _gnutls_TLSCompressed2TLSCiphertext(GNUTLS_STATE state, uint16 c_length; uint8 *data; uint8 pad; - uint8 *rand; + uint8 rand; uint64 seq_num; int length; GNUTLS_MAC_HANDLE td; @@ -515,24 +515,27 @@ int _gnutls_TLSCompressed2TLSCiphertext(GNUTLS_STATE state, break; case CIPHER_BLOCK: - rand = _gnutls_get_random(1, GNUTLS_WEAK_RANDOM); + if (_gnutls_get_random(&rand, 1, GNUTLS_WEAK_RANDOM) < 0) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } /* make rand a multiple of blocksize */ if (_gnutls_version_ssl3(state->connection_state.version) == 0) { - rand[0] = 0; + rand = 0; } else { - rand[0] = (rand[0] / blocksize) * blocksize; + rand = (rand / blocksize) * blocksize; /* added to avoid the case of pad calculated 0 * seen below for pad calculation. */ - if (rand[0] > blocksize) rand[0]-=blocksize; + if (rand > blocksize) rand-=blocksize; } length = compressed->length + state->security_parameters.hash_size; - pad = (uint8) (blocksize - (length % blocksize)) + rand[0]; + pad = (uint8) (blocksize - (length % blocksize)) + rand; length += pad; data = gnutls_malloc(length); @@ -551,7 +554,6 @@ int _gnutls_TLSCompressed2TLSCiphertext(GNUTLS_STATE state, ciphertext->version.major = compressed->version.major; ciphertext->version.minor = compressed->version.minor; - _gnutls_free_rand(rand); break; default: gnutls_free(*cipher); diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c index c2657ca75b..7f92b2c45a 100644 --- a/lib/gnutls_errors.c +++ b/lib/gnutls_errors.c @@ -59,6 +59,7 @@ static gnutls_error_entry error_algorithms[] = { GNUTLS_ERROR_ENTRY( GNUTLS_E_MPI_SCAN_FAILED, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_MPI_PRINT_FAILED, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_DECRYPTION_FAILED, 1), + GNUTLS_ERROR_ENTRY( GNUTLS_E_ENCRYPTION_FAILED, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_DECOMPRESSION_FAILED, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_COMPRESSION_FAILED, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_MEMORY_ERROR, 1), diff --git a/lib/gnutls_errors_int.h b/lib/gnutls_errors_int.h index 4b97c7c58a..ed98646485 100644 --- a/lib/gnutls_errors_int.h +++ b/lib/gnutls_errors_int.h @@ -37,4 +37,5 @@ #define GNUTLS_E_GOT_HELLO_REQUEST -37 #define GNUTLS_E_GOT_APPLICATION_DATA -38 #define GNUTLS_E_RECORD_LIMIT_REACHED -39 +#define GNUTLS_E_ENCRYPTION_FAILED -40 #define GNUTLS_E_UNIMPLEMENTED_FEATURE -50 diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index 46cf3e663d..83f8a3cb5e 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -50,13 +50,15 @@ static int SelectSuite(GNUTLS_STATE state, opaque ret[2], char *data, int datalen); static int SelectCompMethod(GNUTLS_STATE state, CompressionMethod * ret, opaque * data, int datalen); -static void set_server_random( GNUTLS_STATE state, uint8* random) { +void _gnutls_set_server_random( GNUTLS_STATE state, uint8* random) { memcpy( state->security_parameters.server_random, random, 32); - memcpy( state->gnutls_key->server_random, random, 32); + if (state->gnutls_key!=NULL) + memcpy( state->gnutls_key->server_random, random, 32); } -static void set_client_random( GNUTLS_STATE state, uint8* random) { +void _gnutls_set_client_random( GNUTLS_STATE state, uint8* random) { memcpy( state->security_parameters.client_random, random, 32); - memcpy( state->gnutls_key->client_random, random, 32); + if (state->gnutls_key!=NULL) + memcpy( state->gnutls_key->client_random, random, 32); } /* Calculate The SSL3 Finished message */ @@ -156,19 +158,20 @@ void *_gnutls_finished(GNUTLS_STATE state, int type, int skip) /* this function will produce 32 bytes of random data * and put it to dst. */ -static int create_random( opaque* dst) { +int _gnutls_create_random( opaque* dst) { uint32 tim; -opaque* rand; +opaque rand[28]; tim = time(NULL); /* generate server random value */ WRITEuint32( tim, dst); - rand = _gnutls_get_random(28, GNUTLS_STRONG_RANDOM); + if (_gnutls_get_random(rand, 28, GNUTLS_STRONG_RANDOM) < 0) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } memcpy( &dst[4], rand, 28); - _gnutls_free_rand(rand); - return 0; } @@ -216,11 +219,11 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, pos += 2; DECR_LEN(len, 32); - set_client_random( state, &data[pos]); + _gnutls_set_client_random( state, &data[pos]); pos += 32; - create_random( random); - set_server_random( state, random); + _gnutls_create_random( random); + _gnutls_set_server_random( state, random); state->security_parameters.timestamp = time(NULL); @@ -228,9 +231,11 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, memcpy(&session_id_len, &data[pos++], 1); /* RESUME SESSION */ - if (session_id_len > 32) + if (session_id_len > 32) { + gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; - + } + DECR_LEN(len, session_id_len); ret = _gnutls_server_restore_session(state, &data[pos], @@ -253,9 +258,9 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, session_id, &state->security_parameters. session_id_size); + state->gnutls_internals.resumed = RESUME_FALSE; } - /* Select a ciphersuite */ DECR_LEN(len, 2); sizeOfSuites = READuint16( &data[pos]); @@ -267,8 +272,10 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, sizeOfSuites); pos += sizeOfSuites; - if (ret < 0) + if (ret < 0) { + gnutls_assert(); return ret; + } /* check if the credentials (username, public key etc. are ok) @@ -282,6 +289,7 @@ int _gnutls_read_client_hello(GNUTLS_STATE state, opaque * data, 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; @@ -372,6 +380,7 @@ int _gnutls_recv_finished(int cd, GNUTLS_STATE state) GNUTLS_FINISHED); if (ret < 0) { ERR("recv finished int", ret); + gnutls_assert(); return ret; } @@ -439,7 +448,7 @@ static int SelectSuite(GNUTLS_STATE state, opaque ret[2], char *data, for (j = 0; j < datalen; j += 2) { for (i = 0; i < x; i++) { - if (memcmp(&ciphers[i].CipherSuite, &data[j], 2) == + if (memcmp(ciphers[i].CipherSuite, &data[j], 2) == 0) { #ifdef HARD_DEBUG fprintf(stderr, "Selected cipher suite: "); @@ -447,7 +456,7 @@ static int SelectSuite(GNUTLS_STATE state, opaque ret[2], char *data, _gnutls_cipher_suite_get_name(* ((GNUTLS_CipherSuite *) & data[j]))); #endif - memcpy(ret, &ciphers[i].CipherSuite, 2); + memcpy(ret, ciphers[i].CipherSuite, 2); gnutls_free(ciphers); return 0; @@ -785,7 +794,7 @@ static int _gnutls_read_server_hello( GNUTLS_STATE state, char *data, int datale pos += 2; DECR_LEN(len, 32); - set_server_random( state, &data[pos]); + _gnutls_set_server_random( state, &data[pos]); pos += 32; DECR_LEN(len, 1); @@ -955,8 +964,8 @@ int _gnutls_send_hello(int cd, GNUTLS_STATE state) _gnutls_version_get_minor(state->connection_state. version); - create_random( random); - set_client_random( state, random); + _gnutls_create_random( random); + _gnutls_set_client_random( state, random); state->security_parameters.timestamp = time(0); @@ -1551,15 +1560,17 @@ int gnutls_handshake_finish(int cd, GNUTLS_STATE state) int _gnutls_generate_session_id(char *session_id, uint8 * len) { - char *rand; - rand = _gnutls_get_random(32, GNUTLS_WEAK_RANDOM); + opaque rand[32]; + if (_gnutls_get_random(rand, 32, GNUTLS_WEAK_RANDOM) < 0) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } memcpy(session_id, rand, 32); - _gnutls_free_rand(rand); *len = 32; #ifdef HARD_DEBUG - fprintf(stderr, "SessionID: %s\n", + fprintf(stderr, "Generated SessionID: %s\n", _gnutls_bin2hex(session_id, 32)); #endif return 0; diff --git a/lib/gnutls_handshake.h b/lib/gnutls_handshake.h index 625b80fef2..cbdbf5def0 100644 --- a/lib/gnutls_handshake.h +++ b/lib/gnutls_handshake.h @@ -29,3 +29,6 @@ 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); +void _gnutls_set_client_random( GNUTLS_STATE state, uint8* random); +int _gnutls_create_random( opaque* dst); diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 8fac4a42e8..b581b6126c 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -27,9 +27,9 @@ #define WRITE_DEBUG #define BUFFERS_DEBUG #define HANDSHAKE_DEBUG +*/ #define HARD_DEBUG #define DEBUG -*/ #define LIST ... diff --git a/lib/gnutls_kx.c b/lib/gnutls_kx.c index fa5b7e1708..6108926c8b 100644 --- a/lib/gnutls_kx.c +++ b/lib/gnutls_kx.c @@ -104,7 +104,11 @@ int _gnutls_send_server_kx_message(int cd, GNUTLS_STATE state) ret = _gnutls_send_handshake(cd, state, data, data_size, GNUTLS_SERVER_KEY_EXCHANGE); gnutls_free(data); - + + if (ret < 0) { + gnutls_assert(); + return ret; + } return data_size; } @@ -118,13 +122,14 @@ int _gnutls_send_server_kx_message2(int cd, GNUTLS_STATE state) _gnutls_cipher_suite_get_kx_algo (state->gnutls_internals.current_cipher_suite); -#ifdef HARD_DEBUG - fprintf(stderr, "Sending server KX message2\n"); -#endif if (_gnutls_kx_server_key_exchange2(algorithm) != 0) { data_size = state->gnutls_internals.auth_struct->gnutls_generate_server_kx2( state->gnutls_key, &data); +#ifdef HARD_DEBUG + fprintf(stderr, "Sending server KX message2\n"); +#endif + if (data_size<0) { gnutls_assert(); return data_size; @@ -177,6 +182,11 @@ int _gnutls_send_client_kx_message(int cd, GNUTLS_STATE state) ret = _gnutls_send_handshake(cd, state, data, data_size, GNUTLS_CLIENT_KEY_EXCHANGE); gnutls_free(data); + if (ret<0) { + gnutls_assert(); + return ret; + } + ret = generate_master( state); if (ret<0) { gnutls_assert(); @@ -432,5 +442,10 @@ int _gnutls_send_certificate(int cd, GNUTLS_STATE state) ret = _gnutls_send_handshake(cd, state, data, data_size, GNUTLS_CERTIFICATE); gnutls_free(data); + if (ret<0) { + gnutls_assert(); + return ret; + } + return data_size; } diff --git a/lib/gnutls_num.h b/lib/gnutls_num.h index eaa1519979..125ac949d8 100644 --- a/lib/gnutls_num.h +++ b/lib/gnutls_num.h @@ -20,6 +20,9 @@ #include +#define GMIN(x,y) (xy)?x:y + uint32 uint24touint32( uint24 num); uint24 uint32touint24( uint32 num); uint32 READuint32( const opaque* data); diff --git a/lib/gnutls_pk.c b/lib/gnutls_pk.c index 716139890b..7cd01ab86f 100644 --- a/lib/gnutls_pk.c +++ b/lib/gnutls_pk.c @@ -23,15 +23,177 @@ #include #include #include +#include +#include + +/* Do PKCS-1 RSA encryption. + * pkey is the public key and n the modulus. + */ + +int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, gnutls_datum plaintext, + MPI pkey, MPI n) +{ + int k, psize, i, ret; + MPI m, res; + opaque *edata, *ps; + MPI *_pkey[2]; + + k = gcry_mpi_get_nbits(n) / 8; + + if (plaintext.size > k - 11) { + gnutls_assert(); + return GNUTLS_E_ENCRYPTION_FAILED; + } + + edata = gnutls_malloc(k); + if (edata == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + /* EB = 00||BT||PS||00||D + * (use block type 2) + */ + + edata[0] = 0; + edata[1] = 2; + psize = k - 3 - plaintext.size; + + ps = &edata[2]; + _gnutls_get_random(ps, psize, GNUTLS_WEAK_RANDOM); + for (i = 0; i < psize; i++) { + if (ps[i] == 0) + ps[i] = 0xff; + } + ps[psize] = 0; + memcpy(&ps[psize + 1], plaintext.data, plaintext.size); + + if (gcry_mpi_scan(&m, GCRYMPI_FMT_USG, edata, &k) != 0) { + gnutls_assert(); + gnutls_free(edata); + return GNUTLS_E_MPI_SCAN_FAILED; + } + gnutls_free(edata); + + _pkey[0] = &n; + _pkey[1] = &pkey; + ret = _gnutls_pk_encrypt(GCRY_PK_RSA, &res, m, _pkey); + gcry_mpi_release(m); + + if (ret < 0) { + gnutls_assert(); + return ret; + } + + gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &psize, res); + ciphertext->data = gnutls_malloc(psize); + if (ciphertext->data == NULL) { + gnutls_assert(); + gcry_mpi_release(res); + return GNUTLS_E_MEMORY_ERROR; + } + gcry_mpi_print(GCRYMPI_FMT_USG, ciphertext->data, &psize, res); + ciphertext->size = psize; + + gcry_mpi_release(res); + + return 0; +} + + +/* Do PKCS-1 RSA decryption. + * pkey is the private key and n the modulus. + */ + +int _gnutls_pkcs1_rsa_decrypt(gnutls_datum * plaintext, gnutls_datum ciphertext, + MPI pkey, MPI n) +{ + int k, esize, i, ret; + MPI c, res; + opaque *edata; + MPI *_pkey[2]; + + k = gcry_mpi_get_nbits(n) / 8; + + esize = ciphertext.size; + + if (esize!=k) { + gnutls_assert(); + return GNUTLS_E_DECRYPTION_FAILED; + } + + if (gcry_mpi_scan(&c, GCRYMPI_FMT_USG, ciphertext.data, &esize) != 0) { + gnutls_assert(); + gnutls_free(edata); + return GNUTLS_E_MPI_SCAN_FAILED; + } + + _pkey[0] = &n; + _pkey[1] = &pkey; + + ret = _gnutls_pk_encrypt(GCRY_PK_RSA, &res, c, _pkey); + gcry_mpi_release(c); + + if (ret < 0) { + gnutls_assert(); + return ret; + } + + gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &esize, res); + edata = gnutls_malloc(esize); + if (edata == NULL) { + gnutls_assert(); + gcry_mpi_release(res); + return GNUTLS_E_MEMORY_ERROR; + } + gcry_mpi_print(GCRYMPI_FMT_USG, edata, &esize, res); + + gcry_mpi_release(res); + + /* EB = 00||BT||PS||00||D + * (use block type 2) + */ + + if (edata[0] != 0 || edata[1] != 2) { + gnutls_assert(); + gnutls_free(edata); + return GNUTLS_E_DECRYPTION_FAILED; + } + + ret = GNUTLS_E_DECRYPTION_FAILED; + for (i=2;i +#include +#include +#include #ifndef USE_GCRYPT # include # include @@ -29,15 +30,14 @@ # include #endif -char *_gnutls_get_random(int bytes, int dev) +int _gnutls_get_random(opaque * res, int bytes, int dev) { #ifndef USE_GCRYPT int fd; struct timeval tv; char prand[16]; - char * buf = gnutls_malloc(bytes); char *device; - + switch(dev) { case 1: device = "/dev/random"; @@ -54,25 +54,28 @@ char *_gnutls_get_random(int bytes, int dev) memcpy(&prand[8], &fd, sizeof(fd)); fd = clock(); memcpy(&prand[12], &fd, sizeof(fd)); - memset(buf, 0, bytes); + memset(res, 0, bytes); if (bytes > 16) bytes = 16; - memcpy(buf, prand, bytes); + memcpy(res, prand, bytes); } else { - read(fd, buf, bytes); + read(fd, res, bytes); close(fd); } - return buf; + return 0; #else /* using gcrypt */ - return gcry_random_bytes(bytes, dev); + char* buf; + buf = gcry_random_bytes(bytes, dev); + if (buf==NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + memcpy( res, buf, bytes); + gnutls_free(buf); + + return 0; #endif } -void _gnutls_free_rand(void* rand) { -#ifndef USE_GCRYPT - gnutls_free(rand); -#else - gcry_free(rand); -#endif -} \ No newline at end of file diff --git a/lib/gnutls_random.h b/lib/gnutls_random.h index b226900e93..7d55822e56 100644 --- a/lib/gnutls_random.h +++ b/lib/gnutls_random.h @@ -8,5 +8,4 @@ # define GNUTLS_STRONG_RANDOM GCRY_STRONG_RANDOM #endif -char *_gnutls_get_random(int bytes, int); -void _gnutls_free_rand(void* rand); +int _gnutls_get_random(opaque* res, int bytes, int); diff --git a/lib/gnutls.c b/lib/gnutls_record.c similarity index 96% rename from lib/gnutls.c rename to lib/gnutls_record.c index 71dd379ef3..08da041031 100644 --- a/lib/gnutls.c +++ b/lib/gnutls_record.c @@ -50,8 +50,10 @@ GNUTLS_Version ver; void gnutls_set_current_version(GNUTLS_STATE state, GNUTLS_Version version) { state->connection_state.version = version; - state->gnutls_key->version.major = _gnutls_version_get_major(version); - state->gnutls_key->version.minor = _gnutls_version_get_minor(version); + 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); + } } int gnutls_is_secure_memory(const void* mem) { @@ -426,6 +428,19 @@ int gnutls_bye(int cd, GNUTLS_STATE state) return ret; } +/* This function will check the input buffer for + * any pending alert. + */ +int _gnutls_check_for_pending_alert(int cd, GNUTLS_STATE state) +{ + int ret; + + /* receive the closure alert */ + ret = gnutls_recv_int(cd, state, GNUTLS_ALERT, NULL, 0, 0|MSG_DONTWAIT); + + return ret; +} + int gnutls_close_nowait(int cd, GNUTLS_STATE state) { int ret; @@ -457,7 +472,12 @@ ssize_t gnutls_send_int(int cd, GNUTLS_STATE state, ContentType type, const void if (state->gnutls_internals.valid_connection == VALID_FALSE) { return GNUTLS_E_INVALID_SESSION; } - + + if (type==GNUTLS_HANDSHAKE) { + if ((ret = _gnutls_check_for_pending_alert(cd, state)) < 0) + return ret; + } + if (sizeofdata < MAX_ENC_LEN) { iterations = 1; Size = sizeofdata; @@ -637,6 +657,14 @@ ssize_t gnutls_recv_int(int cd, GNUTLS_STATE state, ContentType type, char *data * must be set to non blocking mode */ if ( _gnutls_Read(cd, headers, HEADER_SIZE, MSG_PEEK|flags) != HEADER_SIZE) { + if (type==GNUTLS_ALERT && flags==MSG_DONTWAIT) + return 0; /* we expected an alert + * but nothing came thus success. + * we only wait for an alert + * in check_pending_alert(). + */ + /* How do we handle errno in a multithread environment? + */ if (errno==EAGAIN) return GNUTLS_E_AGAIN; state->gnutls_internals.valid_connection = VALID_FALSE; if (type==GNUTLS_ALERT) return 0; /* we were expecting close notify */ @@ -653,10 +681,11 @@ ssize_t gnutls_recv_int(int cd, GNUTLS_STATE state, ContentType type, char *data /* if msb set and expecting handshake message * it should be SSL 2 hello */ - version = GNUTLS_SSL3; /* assume ssl 3.0 */ + version = GNUTLS_SSL3; /* assume ssl 3.0 - not really needed */ length = (((headers[0] & 0x7f) << 8)) | headers[1]; header_size = 2; - recv_type = GNUTLS_HANDSHAKE; /* only v2 client hello we accept */ + recv_type = GNUTLS_HANDSHAKE; /* we accept only v2 client hello + */ state->gnutls_internals.v2_hello = length; #ifdef DEBUG fprintf(stderr, "Record: V2 packet received. Length: %d\n", length); @@ -671,7 +700,7 @@ ssize_t gnutls_recv_int(int cd, GNUTLS_STATE state, ContentType type, char *data length = READuint16( &headers[3]); } - if ( gnutls_get_current_version(state) != version) { + if ( gnutls_get_current_version(state) != version && recv_type != GNUTLS_HANDSHAKE) { #ifdef DEBUG fprintf(stderr, "Record: INVALID VERSION PACKET: (%d) %d.%d\n", headers[0], headers[1], headers[2]); #endif diff --git a/lib/gnutls_srp.c b/lib/gnutls_srp.c index 8577c49262..d3f022662c 100644 --- a/lib/gnutls_srp.c +++ b/lib/gnutls_srp.c @@ -90,6 +90,8 @@ int _gnutls_srp_gn(opaque ** ret_g, opaque ** ret_n, int bits) gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &siz, g); if (ret_g != NULL) { tmp = gnutls_malloc(siz); + if (tmp==NULL) return GNUTLS_E_MEMORY_ERROR; + gcry_mpi_print(GCRYMPI_FMT_USG, tmp, &siz, g); if (_gnutls_sbase64_encode(tmp, siz, ret_g) < 0) { @@ -103,6 +105,8 @@ int _gnutls_srp_gn(opaque ** ret_g, opaque ** ret_n, int bits) gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &siz, prime); if (ret_n != NULL) { tmp = gnutls_malloc(siz); + if (tmp==NULL) return GNUTLS_E_MEMORY_ERROR; + gcry_mpi_print(GCRYMPI_FMT_USG, tmp, &siz, prime); if (_gnutls_sbase64_encode(tmp, siz, ret_n) < 0) { gnutls_free(tmp); @@ -141,6 +145,8 @@ int _gnutls_srp_gx(opaque * text, int textsize, opaque ** result, MPI g, gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &result_size, e); if (result != NULL) { *result = gnutls_malloc(result_size); + if ((*result)==NULL) return GNUTLS_E_MEMORY_ERROR; + gcry_mpi_print(GCRYMPI_FMT_USG, *result, &result_size, e); } @@ -191,11 +197,17 @@ MPI _gnutls_calc_srp_u(MPI B) gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &b_size, B); b_holder = gnutls_malloc(b_size); + if (b_holder==NULL) return NULL; gcry_mpi_print(GCRYMPI_FMT_USG, b_holder, &b_size, B); td = gnutls_hash_init(GNUTLS_MAC_SHA); + if (td==NULL) { + gnutls_free(b_holder); + gnutls_assert(); + return NULL; + } gnutls_hash(td, b_holder, b_size); hd = gnutls_hash_deinit(td); memcpy(&u, hd, sizeof(u)); diff --git a/lib/gnutls_v2_compat.c b/lib/gnutls_v2_compat.c index ac678ffd1b..ce4e2b5921 100644 --- a/lib/gnutls_v2_compat.c +++ b/lib/gnutls_v2_compat.c @@ -48,12 +48,11 @@ static int SelectSuite_v2(GNUTLS_STATE state, opaque ret[2], char *data, x = _gnutls_supported_ciphersuites(state, &ciphers); #ifdef HARD_DEBUG fprintf(stderr, "Requested cipher suites: \n"); - for (j = 0; j < datalen; j += 2) { + for (j = 0; j < datalen; j += 3) { if (data[j] == 0) { /* only print if in v2 compat mode */ - j++; fprintf(stderr, "\t%s\n", _gnutls_cipher_suite_get_name(* - ((GNUTLS_CipherSuite *) & data[j]))); + ((GNUTLS_CipherSuite *) & data[j+1]))); } } fprintf(stderr, "Supported cipher suites: \n"); @@ -61,13 +60,12 @@ static int SelectSuite_v2(GNUTLS_STATE state, opaque ret[2], char *data, fprintf(stderr, "\t%s\n", _gnutls_cipher_suite_get_name(ciphers[j])); #endif - memset(ret, '\0', sizeof(GNUTLS_CipherSuite)); + memset(ret, '\0', 2); - for (j = 0; j < datalen; j += 2) { + for (j = 0; j < datalen; j += 3) { for (i = 0; i < x; i++) { - if (data[j++] == 0) - if (memcmp - (&ciphers[i].CipherSuite, &data[j], + if (data[j] == 0) + if ( memcmp(ciphers[i].CipherSuite, &data[j+1], 2) == 0) { #ifdef HARD_DEBUG fprintf(stderr, @@ -76,10 +74,10 @@ static int SelectSuite_v2(GNUTLS_STATE state, opaque ret[2], char *data, _gnutls_cipher_suite_get_name (* ((GNUTLS_CipherSuite *) & - data[j]))); + data[j+1]))); #endif memmove(ret, - &ciphers[i].CipherSuite, + ciphers[i].CipherSuite, 2); gnutls_free(ciphers); @@ -109,7 +107,7 @@ int _gnutls_read_client_hello_v2(GNUTLS_STATE state, opaque * data, int ret = 0; uint16 sizeOfSuites; GNUTLS_Version version; - char *rand; + opaque random[32]; int len = datalen; int err; uint16 challenge; @@ -149,9 +147,10 @@ int _gnutls_read_client_hello_v2(GNUTLS_STATE state, opaque * data, session_id_len = READuint16( &data[pos]); pos += 2; - if (session_id_len > 32) + if (session_id_len > 32) { + gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; - + } /* read challenge length */ DECR_LEN(len, 2); @@ -172,9 +171,10 @@ int _gnutls_read_client_hello_v2(GNUTLS_STATE state, opaque * data, &data[pos], sizeOfSuites); pos += sizeOfSuites; - if (ret < 0) + if (ret < 0) { + gnutls_assert(); return ret; - + } /* check if the credentials (username, public key etc. are ok) */ @@ -207,17 +207,17 @@ int _gnutls_read_client_hello_v2(GNUTLS_STATE state, opaque * data, pos+=session_id_len; DECR_LEN(len, challenge); - memset( state->security_parameters.client_random, 0, 32); + memset( random, 0, 32); + memcpy( random, &data[challenge > 32 ? (pos+challenge-32) : pos], challenge < 32 ? challenge : 32); /* read the last 32 bytes */ - memcpy( state->security_parameters.client_random, &data[challenge > 32 ? (pos+challenge-32) : pos], challenge < 32 ? challenge : 32); + _gnutls_set_client_random( state, random); /* generate server random value */ - WRITEuint32( time(NULL), state->security_parameters.server_random); - rand = _gnutls_get_random(28, GNUTLS_STRONG_RANDOM); - memmove(&state->security_parameters.server_random[4], rand, 28); - _gnutls_free_rand(rand); + _gnutls_create_random( random); + _gnutls_set_server_random( state, random); + state->security_parameters.timestamp = time(NULL); @@ -249,5 +249,5 @@ int _gnutls_read_client_hello_v2(GNUTLS_STATE state, opaque * data, state->gnutls_internals.resumed = RESUME_FALSE; } - return ret; + return 0; }