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 \
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)
#include "cert_der.h"
#include "gnutls_datum.h"
#include "auth_x509.h"
+#include <gnutls_random.h>
+#include <gnutls_pk.h>
#if 0
int gen_rsa_server_kx(GNUTLS_KEY, opaque **);
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) {
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();
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;
}
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;
}
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;
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!
*/
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;
}
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);
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);
}
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;
/* 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
* [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.
int
delete_structure(char *root_name);
+int parser_asn1(char *file_name);
+
#endif
#include "defines.h"
#include "gnutls_int.h"
+#include "gnutls_errors.h"
const static uint8 b64table[64] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/* 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;
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;
}
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);
{
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;
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();
{
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;
}
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);
*/
} 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 */
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),*/
#ifdef DEBUG
if (size > MAX_ELEM_SIZE) {
gnutls_assert();
+ fprintf(stderr, "QSORT BUG\n");
exit(1);
}
#endif
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
--- /dev/null
+/*
+ * 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 <defines.h>
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <cert_b64.h>
+#include <auth_x509.h>
+
+/* 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;
+}
uint16 c_length;
uint8 *data;
uint8 pad;
- uint8 *rand;
+ uint8 rand;
uint64 seq_num;
int length;
GNUTLS_MAC_HANDLE td;
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);
ciphertext->version.major = compressed->version.major;
ciphertext->version.minor = compressed->version.minor;
- _gnutls_free_rand(rand);
break;
default:
gnutls_free(*cipher);
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),
#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
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 */
/* 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;
}
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);
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],
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]);
sizeOfSuites);
pos += sizeOfSuites;
- if (ret < 0)
+ if (ret < 0) {
+ gnutls_assert();
return ret;
+ }
/* check if the credentials (username, public key etc. are ok)
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;
GNUTLS_FINISHED);
if (ret < 0) {
ERR("recv finished int", ret);
+ gnutls_assert();
return ret;
}
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: ");
_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;
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);
_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);
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;
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);
#define WRITE_DEBUG
#define BUFFERS_DEBUG
#define HANDSHAKE_DEBUG
+*/
#define HARD_DEBUG
#define DEBUG
-*/
#define LIST ...
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;
}
_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;
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();
ret = _gnutls_send_handshake(cd, state, data, data_size, GNUTLS_CERTIFICATE);
gnutls_free(data);
+ if (ret<0) {
+ gnutls_assert();
+ return ret;
+ }
+
return data_size;
}
#include <gnutls_int.h>
+#define GMIN(x,y) (x<y)?x:y
+#define GMAX(x,y) (x>y)?x:y
+
uint32 uint24touint32( uint24 num);
uint24 uint32touint24( uint32 num);
uint32 READuint32( const opaque* data);
#include <gnutls_gcry.h>
#include <gnutls_pk.h>
#include <gnutls_errors.h>
+#include <gnutls_random.h>
+#include <gnutls_datum.h>
+
+/* 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<esize;i++) {
+ if (edata[i]==0) {
+ ret = 0;
+ break;
+ }
+ }
+ i++;
+
+ if (ret < 0) {
+ gnutls_assert();
+ gnutls_free(edata);
+ return GNUTLS_E_DECRYPTION_FAILED;
+ }
+
+ if (gnutls_set_datum( plaintext, &edata[i], esize - i) < 0) {
+ gnutls_assert();
+ gnutls_free(edata);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ gnutls_free(edata);
+
+ return 0;
+}
/* this is taken from gnupg
*/
-
+
/****************
* Emulate our old PK interface here - sometime in the future we might
* change the internal design to directly fit to libgcrypt.
*/
-int _gnutls_pk_encrypt(enum gcry_pk_algos algo, MPI * resarr, MPI data, MPI * pkey)
+int _gnutls_pk_encrypt(int algo, MPI * resarr, MPI data, MPI **pkey)
{
GCRY_SEXP s_ciph, s_data, s_pkey;
int rc;
/* make a sexp from pkey */
if (algo == GCRY_PK_RSA) {
rc = gcry_sexp_build(&s_pkey, NULL,
- "(public-key(rsa(p%m)(e%m)))",
- pkey[0], pkey[1] );
+ "(public-key(rsa(p%m)(e%m)))",
+ *pkey[0], *pkey[1]);
} else {
gnutls_assert();
return GNUTLS_E_UNKNOWN_KX_ALGORITHM;
}
- if (rc!=0) {
+ if (rc != 0) {
gnutls_assert();
return GNUTLS_E_UNKNOWN_ERROR;
}
gcry_sexp_release(s_data);
gcry_sexp_release(s_pkey);
- if (rc);
- else { /* add better error handling or make gnupg use S-Exp directly */
+ if (rc != 0) {
+ gnutls_assert();
+ return GNUTLS_E_UNKNOWN_ERROR;
+
+ } else { /* add better error handling or make gnupg use S-Exp directly */
GCRY_SEXP list = gcry_sexp_find_token(s_ciph, "a", 0);
- /* assert(list); */
+ if (list == NULL) {
+ gnutls_assert();
+ gcry_sexp_release(s_ciph);
+ return GNUTLS_E_UNKNOWN_ERROR;
+ }
+
resarr[0] = gcry_sexp_nth_mpi(list, 1, 0);
- /* assert(resarr[0]); */
gcry_sexp_release(list);
+ if (resarr[0] == NULL) {
+ gnutls_assert();
+ gcry_sexp_release(s_ciph);
+ return GNUTLS_E_UNKNOWN_ERROR;
+ }
}
gcry_sexp_release(s_ciph);
-int _gnutls_pk_encrypt(enum gcry_pk_algos algo, MPI * resarr, MPI data, MPI * pkey);
-
+int _gnutls_pk_encrypt(int algo, MPI * resarr, MPI data, MPI ** pkey);
+int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, gnutls_datum plaintext,
+ MPI pkey, MPI n);
+int _gnutls_pkcs1_rsa_decrypt(gnutls_datum * plaintext, gnutls_datum ciphertext,
+ MPI pkey, MPI n);
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
-#include "defines.h"
-#include "gnutls_int.h"
-#include "gnutls_random.h"
+#include <defines.h>
+#include <gnutls_int.h>
+#include <gnutls_random.h>
+#include <gnutls_errors.h>
#ifndef USE_GCRYPT
# include <unistd.h>
# include <sys/types.h>
# include <sys/time.h>
#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";
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
# 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);
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) {
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;
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;
* 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 */
/* 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);
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
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) {
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);
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);
}
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));
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");
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,
_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);
int ret = 0;
uint16 sizeOfSuites;
GNUTLS_Version version;
- char *rand;
+ opaque random[32];
int len = datalen;
int err;
uint16 challenge;
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);
&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)
*/
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);
state->gnutls_internals.resumed = RESUME_FALSE;
}
- return ret;
+ return 0;
}