From: Nikos Mavrogiannopoulos Date: Wed, 8 Mar 2000 10:48:49 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: gnutls0-0-4~114 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4bcd577f7ad53e3b81d277adfbbe22eac0779083;p=thirdparty%2Fgnutls.git *** empty log message *** --- diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Makefile.am b/Makefile.am index 3bd3cb9072..9c3e050ebd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,4 @@ +## Process this file with automake to produce Makefile.in -SUBDIRS = lib src - +SUBDIRS = src + \ No newline at end of file diff --git a/acconfig.h b/acconfig.h index c864fca155..2098c23e2d 100644 --- a/acconfig.h +++ b/acconfig.h @@ -1,18 +1,16 @@ -/* acconfig.h - used by autoheader to make config.h.in - */ -#ifndef GPA_CONFIG_H -#define GPA_CONFIG_H +/* and the real names of the random devices */ +#undef NAME_OF_DEV_RANDOM +#undef NAME_OF_DEV_URANDOM +#undef HAVE_DEV_RANDOM -/* Need this, because some autoconf tests rely on this (e.g. stpcpy) - * and it should be used for new programs anyway. */ -#define _GNU_SOURCE 1 +#undef PACKAGE +#undef VERSION -@TOP@ +#undef T_CPU +#undef T_VENDOR +#undef T_OS -#undef HAVE_BYTE_TYPEDEF - - -@BOTTOM@ - - -#endif /*GPA_CONFIG_H*/ +LT_CURRENT +LT_REVISION +LT_AGE + \ No newline at end of file diff --git a/buildconf b/buildconf index 97c15bb34c..052e8b7572 100755 --- a/buildconf +++ b/buildconf @@ -1,7 +1,7 @@ #! /bin/sh aclocal && \ -libtoolize -c --force --ltdl && \ +libtoolize -c --force && \ autoheader && \ automake -a -c || automake -a -c autoconf diff --git a/configure.in b/configure.in index 6c097839bd..b1d759566a 100644 --- a/configure.in +++ b/configure.in @@ -1,81 +1,133 @@ -dnl -dnl Configure script source for GNUTLS -dnl -dnl (Process this file with autoconf to produce a configure script.) -AC_REVISION($Revision$)dnl -AC_PREREQ(2.13) - -AC_INIT(src/gnutls.c) -AM_CONFIG_HEADER(config.h) +dnl Process this file with autoconf to produce a configure script. +AC_INIT() +dnl AC_CONFIG_HEADER(config.h) -dnl -dnl The version number goes here -dnl -AM_INIT_AUTOMAKE(gnutls,0.0.0) +AC_PREFIX_DEFAULT(/usr/local) -dnl -dnl Setup some stuff depending on host/target. -dnl -case "${target}" in - *-*-mingw32) - # special stuff for Windoze NT - # Do we need to set cross_compiling here or is it sufficient - # to rely on AC_PROG_CC which is called later? - CC="${target}-gcc" - CPP="${target}-gcc -E" - RANLIB="${target}-ranlib" - ;; - *) - ;; -esac +AC_CANONICAL_SYSTEM +AC_DEFINE_UNQUOTED(T_CPU, "$target_cpu") +AC_DEFINE_UNQUOTED(T_VENDOR, "$target_vendor") +AC_DEFINE_UNQUOTED(T_OS, "$target_os") +GNUTLS_MAJOR_VERSION=0 +GNUTLS_MINOR_VERSION=0 +GNUTLS_MICRO_VERSION=1 +GNUTLS_VERSION=$GNUTLS_MAJOR_VERSION.$GNUTLS_MINOR_VERSION.$GNUTLS_MICRO_VERSION -AM_MAINTAINER_MODE -dnl -dnl Checks for programs -dnl -AC_PROG_CC -AC_STDC_HEADERS -AC_ARG_PROGRAM -AC_PROG_RANLIB +AM_INIT_AUTOMAKE(gnutls, $GNUTLS_VERSION) +AM_CONFIG_HEADER(config.h) -dnl -dnl Checks for libraries -dnl +GNUTLS_MOST_RECENT_INTERFACE=$GNUTLS_MINOR_VERSION +GNUTLS_CURRENT_INTERFACE_IMPLEMENTATION_NUMBER=$GNUTLS_MICRO_VERSION +GNUTLS_OLDEST_INTERFACE=0 +AC_SUBST(GNUTLS_MAJOR_VERSION) +AC_SUBST(GNUTLS_MINOR_VERSION) +AC_SUBST(GNUTLS_MICRO_VERSION) +AC_SUBST(GNUTLS_VERSION) -dnl -dnl Checks for header files -dnl +AC_SUBST(GNUTLS_MOST_RECENT_INTERFACE) +AC_SUBST(GNUTLS_CURRENT_INTERFACE_IMPLEMENTATION_NUMBER) +AC_SUBST(GNUTLS_OLDEST_INTERFACE) +LT_CURRENT=$GNUTLS_MOST_RECENT_INTERFACE +LT_REVISION=$GNUTLS_CURRENT_INTERFACE_IMPLEMENTATION_NUMBER +LT_AGE=`expr $GNUTLS_MOST_RECENT_INTERFACE - $GNUTLS_OLDEST_INTERFACE` +AC_SUBST(LT_CURRENT) +AC_SUBST(LT_REVISION) +AC_SUBST(LT_AGE) -dnl -dnl Checks for typedefs and structures -dnl -dnl -dnl Checks for compiler features -dnl +AC_PROG_CC + -dnl -dnl Checks for library functions -dnl +AC_C_CONST +dnl Checks for programs. +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PATH_PROG(RM,rm) +AC_PATH_PROG(MAKEINFO,makeinfo) +dnl AC_PATH_PROG(AR,ar) +dnl AC_PATH_PROG(RANLIB,ranlib) -dnl -dnl Checks for system services -dnl +dnl AC_PROG_MAKE_SET +dnl From GNUPG +AC_MSG_CHECKING([whether use of /dev/random is requested]) +AC_ARG_ENABLE(dev-random, +[ --disable-dev-random disable the use of dev random], + try_dev_random=$enableval, try_dev_random=yes) +AC_MSG_RESULT($try_dev_random) -AC_OUTPUT([ -Makefile -lib/Makefile -src/Makefile -]) +opt_maintainer_mode=no +AC_MSG_CHECKING([whether in maintanance mode]) +AC_ARG_ENABLE(maintainer-mode, +[ --enable-maintainer-mode enable maintainer mode], +opt_maintainer_mode=$enableval) +AC_MSG_RESULT($opt_maintainer_mode) +case "${target}" in + *-openbsd*) + NAME_OF_DEV_RANDOM="/dev/srandom" + NAME_OF_DEV_URANDOM="/dev/urandom" + ;; + *) + NAME_OF_DEV_RANDOM="/dev/random" + NAME_OF_DEV_URANDOM="/dev/urandom" + ;; +esac -dnl *-*wedit:notab*-* Please keep this as the last line. +AC_DEFINE_UNQUOTED(NAME_OF_DEV_RANDOM, "$NAME_OF_DEV_RANDOM") +AC_DEFINE_UNQUOTED(NAME_OF_DEV_URANDOM, "$NAME_OF_DEV_URANDOM") + +dnl check whether we have a random device +if test "$try_dev_random" = yes ; then +AC_CACHE_CHECK(for random device, ac_cv_have_dev_random, +[if test -c "/dev/random" && test -c "$NAME_OF_DEV_URANDOM" ; then + ac_cv_have_dev_random=yes; else ac_cv_have_dev_random=no; fi]) +if test "$ac_cv_have_dev_random" = yes; then + AC_DEFINE(HAVE_DEV_RANDOM) +else + AC_MSG_WARN(No random device found. No real random data can be used.) +fi +else + AC_MSG_CHECKING(for random device) + ac_cv_have_dev_random=no + AC_MSG_RESULT(has been disabled) + AC_MSG_WARN(Support for random device was disabled. No real random data can be used.) +fi + + +if test $ac_cv_prog_gcc = yes; then + CFLAGS="${CFLAGS} -ffast-math" + + if test $opt_maintainer_mode = yes; then + CFLAGS="${CFLAGS} -Wall -Wpointer-arith -pedantic" + fi +fi + +AC_HEADER_STDC +AC_CHECK_HEADERS(unistd.h pwd.h locale.h strings.h mcrypt.h) +AC_CHECK_HEADERS(sys/stat.h sys/types.h fcntl.h sys/wait.h) +AC_CHECK_HEADERS(utime.h signal.h) +AC_CHECK_HEADERS(termios.h termio.h sgtty.h) +AC_CHECK_FUNCS(bzero signal sigaction memset fcntl fsync siglongjmp,,) +AC_CHECK_FUNCS(lstat stat umask utime memmove bcopy getpwuid waitpid,,) + +dnl Checks for libraries. +AC_C_BIGENDIAN +AC_TYPE_SIGNAL +AC_CHECK_SIZEOF(unsigned long long, 8) +AC_CHECK_SIZEOF(unsigned long int, 4) +AC_CHECK_SIZEOF(unsigned int, 4) +AC_CHECK_SIZEOF(unsigned short int, 2) +AC_CHECK_SIZEOF(unsigned char, 1) + +AM_PROG_LIBTOOL + +AC_OUTPUT([Makefile src/Makefile]) diff --git a/src/Makefile.am b/src/Makefile.am index f36936bec5..8010cac539 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,8 +1,9 @@ -## Process this file with automake to produce Makefile.in - -bin_PROGRAMS = foo - - -foo_SOURCES = foo.c foo.h - +include_HEADERS = gnutls.h +EXTRA_DIST = debug.h gnutls_compress.h defines.h gnutls_plaintext.h gnutls_cipher.h +lib_LTLIBRARIES = libgnutls.la +libgnutls_la_SOURCES = gnutls.c gnutls_compress.c debug.c gnutls_plaintext.c gnutls_cipher.c +libgnutls_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) +bin_PROGRAMS = test +test_SOURCES = test.c +test_LDADD = libgnutls.la -lgcrypt -lmhash diff --git a/src/debug.c b/src/debug.c new file mode 100644 index 0000000000..e6a01194b5 --- /dev/null +++ b/src/debug.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include "gnutls.h" + + +static char hexconvtab[] = "0123456789abcdef"; + +char * bin2hex(const unsigned char *old, const size_t oldlen) +{ + unsigned char *new = NULL; + int i, j; + + new = malloc(oldlen * 2 * sizeof(char) + 1); + if (!new) + return (new); + + for (i = j = 0; i < oldlen; i++) { + new[j++] = hexconvtab[old[i] >> 4]; + new[j++] = hexconvtab[old[i] & 15]; + } + new[j] = '\0'; + + return (new); +} + + +void _print_state(GNUTLS_STATE state) +{ + + fprintf(stderr, "GNUTLS State:\n"); + fprintf(stderr, "Connection End: %d\n", + state->security_parameters.entity); + fprintf(stderr, "Cipher Algorithm: %d\n", + state->security_parameters.bulk_cipher_algorithm); + fprintf(stderr, "Cipher Type: %d\n", + state->security_parameters.cipher_type); + fprintf(stderr, "Key Size: %d\n", + state->security_parameters.key_size); + fprintf(stderr, "Key Material: %d\n", + state->security_parameters.key_material_length); + fprintf(stderr, "Exportable: %d\n", + state->security_parameters.is_exportable); + fprintf(stderr, "MAC algorithm: %d\n", + state->security_parameters.mac_algorithm); + fprintf(stderr, "Hash size: %d\n", + state->security_parameters.hash_size); + fprintf(stderr, "Compression Algorithm: %d\n", + state->security_parameters.compression_algorithm); + fprintf(stderr, "\n"); + +} + +void _print_TLSCompressed(GNUTLSCompressed * compressed) +{ + fprintf(stderr, "TLSCompressed packet:\n"); + fprintf(stderr, "type: %d\n", compressed->type); + fprintf(stderr, "version: %d,%d\n", compressed->version.major, + compressed->version.minor); + fprintf(stderr, "length: %d\n", compressed->length); + fprintf(stderr, "fragment: %s\n", bin2hex(compressed->fragment, compressed->length)); + fprintf(stderr, "\n"); +} + + +void _print_TLSPlaintext(GNUTLSPlaintext * plaintext) +{ + fprintf(stderr, "TLSPlaintext packet:\n"); + fprintf(stderr, "type: %d\n", plaintext->type); + fprintf(stderr, "version: %d,%d\n", plaintext->version.major, + plaintext->version.minor); + fprintf(stderr, "length: %d\n", plaintext->length); + fprintf(stderr, "fragment: %s\n", bin2hex(plaintext->fragment, plaintext->length)); + fprintf(stderr, "\n"); +} + + +void _print_TLSCiphertext( GNUTLSCiphertext * ciphertext) +{ + + fprintf(stderr, "TLSCiphertext packet:\n"); + fprintf(stderr, "type: %d\n", ciphertext->type); + fprintf(stderr, "version: %d,%d\n", ciphertext->version.major, + ciphertext->version.minor); + fprintf(stderr, "length: %d\n", ciphertext->length); + + fprintf(stderr, "fragment: %s\n", bin2hex(ciphertext->fragment, ciphertext->length)); + fprintf(stderr, "\n"); +} diff --git a/src/debug.h b/src/debug.h new file mode 100644 index 0000000000..3c19e39e8d --- /dev/null +++ b/src/debug.h @@ -0,0 +1,5 @@ +void _print_state(GNUTLS_STATE state); +void _print_TLSCompressed(GNUTLSCompressed * compressed); +void _print_TLSPlaintext(GNUTLSPlaintext * plaintext); +void _print_TLSCiphertext( GNUTLSCiphertext *); +char * bin2hex(const unsigned char *old, const size_t oldlen); diff --git a/src/defines.h b/src/defines.h new file mode 100644 index 0000000000..917bc4f1a9 --- /dev/null +++ b/src/defines.h @@ -0,0 +1,77 @@ +#include + + + +#ifdef STDC_HEADERS +# include +# include +# include +#endif + +#ifdef HAVE_STRINGS_H +# include +#endif + +#include + + +/* for open */ +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_SYS_STAT_H +# include +#endif + +#ifdef HAVE_UNISTD_H +# include +#endif + +#include + +#if SIZEOF_UNSIGNED_LONG_INT == 8 + typedef unsigned long int uint64; + typedef signed long int sint64; +#elif SIZEOF_UNSIGNED_LONG_LONG == 8 + typedef unsigned long long uint64; + typedef signed long long sint64; +#else +# error "Cannot find a 64 bit integer in your system, sorry." +#endif + + +#if SIZEOF_UNSIGNED_LONG_INT == 4 + typedef unsigned long int uint32; + typedef signed long int sint32; +#elif SIZEOF_UNSIGNED_INT == 4 + typedef unsigned int uint32; + typedef signed int sint32; +#else +# error "Cannot find a 32 bit integer in your system, sorry." +#endif + +#if SIZEOF_UNSIGNED_INT == 2 + typedef unsigned int uint16; + typedef signed int sint16; +#elif SIZEOF_UNSIGNED_SHORT_INT == 2 + typedef unsigned short int uint16; + typedef signed short int sint16; +#else +# error "Cannot find a 16 bit integer in your system, sorry." +#endif + +#if SIZEOF_UNSIGNED_CHAR == 1 + typedef unsigned char uint8; + typedef signed char int8; +#else +# error "Cannot find an 8 bit char in your system, sorry." +#endif + +#ifndef HAVE_MEMMOVE +# ifdef HAVE_BCOPY +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# else +# error "Neither memmove nor bcopy exists on your system." +# endif +#endif diff --git a/src/gnutls.c b/src/gnutls.c new file mode 100644 index 0000000000..9f528d43ee --- /dev/null +++ b/src/gnutls.c @@ -0,0 +1,386 @@ +#include +#include "gnutls.h" +#include "debug.h" +#include "gnutls_compress.h" +#include "gnutls_plaintext.h" +#include "gnutls_cipher.h" +#include +#include +#include + +int gnutls_init(GNUTLS_STATE * state, ConnectionEnd con_end) +{ + *state = gnutls_calloc(1, sizeof(GNUTLS_STATE_INT)); + memset(*state, 0, sizeof(GNUTLS_STATE)); + (*state)->security_parameters.entity = con_end; + +/* Set the defaults (only to remind me that they should be allocated ) */ + (*state)->security_parameters.bulk_cipher_algorithm = CIPHER_NULL; + (*state)->security_parameters.mac_algorithm = MAC_NULL; + (*state)->security_parameters.compression_algorithm = COMPRESSION_NULL; + + (*state)->connection_state.compression_state = NULL; + (*state)->connection_state.mac_secret = NULL; + + (*state)->cipher_specs.server_write_mac_secret = NULL; + (*state)->cipher_specs.client_write_mac_secret = NULL; + (*state)->cipher_specs.server_write_IV = NULL; + (*state)->cipher_specs.client_write_IV = NULL; + (*state)->cipher_specs.server_write_key = NULL; + (*state)->cipher_specs.client_write_key = NULL; + +} + +int gnutls_deinit(GNUTLS_STATE * state) +{ + gnutls_free((*state)->connection_state.compression_state); + gnutls_free((*state)->connection_state.mac_secret); + + secure_free((*state)->cipher_specs.server_write_mac_secret); + secure_free((*state)->cipher_specs.client_write_mac_secret); + secure_free((*state)->cipher_specs.server_write_IV); + secure_free((*state)->cipher_specs.client_write_IV); + secure_free((*state)->cipher_specs.server_write_key); + secure_free((*state)->cipher_specs.client_write_key); + + + gnutls_free(*state); +} + +/* Produces "total_bytes" bytes using the hash algorithm specified. + * (used in the PRF function) + */ +svoid* gnutls_P_hash( hashid algorithm, opaque* secret, int secret_size, + opaque* seed, int seed_size, int total_bytes) { + + MHASH td1, td2; + char* ret=secure_malloc(total_bytes); + void* A; + int i=0, times, copy_bytes=0, how; + void *final; + + do { + i += mhash_get_block_size(algorithm); + } while( i < total_bytes); + + A = seed; + times = i / mhash_get_block_size(algorithm); + + for (i=0;i0) { + memmove( &ret[i*copy_bytes], final, how); + } + free(final); + if (i>0) free(A); + } + + return ret; +} + + +/* The PRF function expands a given secret */ +svoid *gnutls_PRF( opaque* secret, int secret_size, uint8* label, int label_size, + opaque* seed, int seed_size, int total_bytes) +{ + int l_s1, l_s2, i, s_seed_size; + char* o1, *o2; + char* s1, *s2; + char* ret; + char* s_seed; + + /* label+seed = s_seed */ + s_seed_size = seed_size+label_size; + s_seed=gnutls_malloc(s_seed_size); + memmove( s_seed, label, label_size); + memmove( &s_seed[label_size], seed, seed_size); + + + if (secret_size%2 == 0) { + l_s1 = l_s2 = secret_size/2; + s1 = &secret[0]; + s2 = &secret[l_s1+1]; + } else { + l_s1 = l_s2 = (secret_size/2) + 1; + s1 = &secret[0]; + s2 = &secret[l_s1]; + } + + o1 = gnutls_P_hash( MHASH_MD5, s1, l_s1, s_seed, s_seed_size, total_bytes); + o2 = gnutls_P_hash( MHASH_SHA1, s2, l_s2, s_seed, s_seed_size, total_bytes); + + ret = secure_malloc( total_bytes); + gnutls_free( s_seed); + for (i=0;icipher_specs + */ +int _gnutls_set_keys( GNUTLS_STATE state) { + char* key_block; + char keyexp[]="key expansion"; + char* random = gnutls_malloc(64); + int hash_size; + int IV_size; + int key_size; + + hash_size = state->security_parameters.hash_size; + IV_size = state->security_parameters.IV_size; + key_size = state->security_parameters.key_material_length; + + memmove(random, state->security_parameters.server_random, 32); + memmove(&random[32], state->security_parameters.client_random, 32); + + key_block = gnutls_PRF( state->security_parameters.master_secret, 48, + keyexp, strlen(keyexp), + random, 64, + 2*hash_size + + 2*key_size + + 2*IV_size); + + state->cipher_specs.client_write_mac_secret = secure_malloc( hash_size); + memmove( state->cipher_specs.client_write_mac_secret, &key_block[0], hash_size); + + state->cipher_specs.server_write_mac_secret = secure_malloc( hash_size); + memmove( state->cipher_specs.server_write_mac_secret, &key_block[hash_size], hash_size); + + state->cipher_specs.client_write_key = secure_malloc( key_size); + memmove( state->cipher_specs.client_write_key, &key_block[2*hash_size], key_size); + + state->cipher_specs.server_write_key = secure_malloc( key_size); + memmove( state->cipher_specs.server_write_key, &key_block[2*hash_size+key_size], key_size); + + state->cipher_specs.client_write_IV = secure_malloc( IV_size); + memmove( state->cipher_specs.client_write_IV, &key_block[2*key_size+2*hash_size], IV_size); + + state->cipher_specs.server_write_IV = secure_malloc( IV_size); + memmove( state->cipher_specs.server_write_IV, &key_block[2*hash_size+2*key_size+IV_size], IV_size); + + secure_free( key_block); + return 0; +} + +int gnutls_send_int(int cd, GNUTLS_STATE state, ContentType type, char* data, int sizeofdata) { + GNUTLSPlaintext *gtxt; + GNUTLSCompressed *gcomp; + GNUTLSCiphertext *gcipher; + int iterations, i, err; + uint16 length; + int ret=0, Size; + + if (sizeofdata==0) return 0; + + if (sizeofdata<16384) { + iterations=1; + Size=sizeofdata; + } else { + iterations = sizeofdata/16384; + Size = 16384; + } + for (i=0;itype, sizeof(ContentType)); + write( cd, &gcipher->version.major, 1); + write( cd, &gcipher->version.minor, 1); +#ifdef WORDS_BIGENDIAN + length=gcipher->length; +#else + length=byteswap16(gcipher->length); +#endif + write( cd, &length, sizeof(uint16)); + _print_TLSCiphertext( gcipher); + write( cd, gcipher->fragment, gcipher->length); + state->connection_state.write_sequence_number++; + ret += Size; + + _gnutls_freeTLSCiphertext(gcipher); + } + /* rest data */ + if (iterations>1) { + Size=sizeofdata%16384; + err = _gnutls_text2TLSPlaintext(type, >xt, &data[ret], Size); + if (err<0) { + /*gnutls_perror(err);*/ + return err; + } + + err = _gnutls_TLSPlaintext2TLSCompressed(state, &gcomp, gtxt); + if (err<0) { + /*gnutls_perror(err);*/ + return err; + } + + _gnutls_freeTLSPlaintext(gtxt); + + err = _gnutls_TLSCompressed2TLSCiphertext( state, &gcipher, gcomp); + if (err<0) { + /*gnutls_perror(err);*/ + return err; + } + _gnutls_freeTLSCompressed(gcomp); +#ifdef WORDS_BIGENDIAN + length=gcipher->length; +#else + length=byteswap16(gcipher->length); +#endif + write( cd, &gcipher->type, sizeof(ContentType)); + write( cd, &gcipher->version.major, 1); + write( cd, &gcipher->version.minor, 1); + write( cd, &length, sizeof(uint16)); + write( cd, gcipher->fragment, gcipher->length); + state->connection_state.write_sequence_number++; + ret += Size; + + _gnutls_freeTLSCiphertext(gcipher); + } + + return ret; +} + + +#if 0 +int gnutls_recv_int(int cd, GNUTLS_STATE state, ContentType type, char* data, int sizeofdata) { + GNUTLSPlaintext *gtxt; + GNUTLSCompressed *gcomp; + GNUTLSCiphertext *gcipher; + int iterations, i, err; + uint16 length; + int ret=0, Size; + + if (sizeofdata==0) return 0; + + if (sizeofdata<16384) { + iterations=1; + Size=sizeofdata; + } else { + iterations = sizeofdata/16384; + Size = 16384; + } + for (i=0;itype, sizeof(ContentType)); + write( cd, &gcipher->version.major, 1); + write( cd, &gcipher->version.minor, 1); +#ifdef WORDS_BIGENDIAN + length=gcipher->length; +#else + length=byteswap16(gcipher->length); +#endif + write( cd, &length, sizeof(uint16)); + _print_TLSCiphertext( gcipher); + write( cd, gcipher->fragment, gcipher->length); + state->connection_state.write_sequence_number++; + ret += Size; + + _gnutls_freeTLSCiphertext(gcipher); + } + /* rest data */ + if (iterations>1) { + Size=sizeofdata%16384; + err = _gnutls_text2TLSPlaintext(type, >xt, &data[ret], Size); + if (err<0) { + /*gnutls_perror(err);*/ + return err; + } + + err = _gnutls_TLSPlaintext2TLSCompressed(state, &gcomp, gtxt); + if (err<0) { + /*gnutls_perror(err);*/ + return err; + } + + _gnutls_freeTLSPlaintext(gtxt); + + err = _gnutls_TLSCompressed2TLSCiphertext( state, &gcipher, gcomp); + if (err<0) { + /*gnutls_perror(err);*/ + return err; + } + _gnutls_freeTLSCompressed(gcomp); +#ifdef WORDS_BIGENDIAN + length=gcipher->length; +#else + length=byteswap16(gcipher->length); +#endif + write( cd, &gcipher->type, sizeof(ContentType)); + write( cd, &gcipher->version.major, 1); + write( cd, &gcipher->version.minor, 1); + write( cd, &length, sizeof(uint16)); + write( cd, gcipher->fragment, gcipher->length); + state->connection_state.write_sequence_number++; + ret += Size; + + _gnutls_freeTLSCiphertext(gcipher); + } + + return ret; +} +#endif diff --git a/src/gnutls.h b/src/gnutls.h new file mode 100644 index 0000000000..896c60b00f --- /dev/null +++ b/src/gnutls.h @@ -0,0 +1,146 @@ +#define svoid void /* for functions that allocate using secure_free */ +#define secure_free free +#define secure_malloc malloc +#define secure_realloc realloc +#define secure_calloc calloc +#define gnutls_malloc malloc +#define gnutls_realloc realloc +#define gnutls_calloc calloc +#define gnutls_free free + +#define rotl64(x,n) (((x) << ((uint16)(n))) | ((x) >> (64 - (uint16)(n)))) +#define rotr64(x,n) (((x) >> ((uint16)(n))) | ((x) << (64 - (uint16)(n)))) +#define rotl32(x,n) (((x) << ((uint16)(n))) | ((x) >> (32 - (uint16)(n)))) +#define rotr32(x,n) (((x) >> ((uint16)(n))) | ((x) << (32 - (uint16)(n)))) +#define rotl16(x,n) (((x) << ((uint16)(n))) | ((x) >> (16 - (uint16)(n)))) +#define rotr16(x,n) (((x) >> ((uint16)(n))) | ((x) << (16 - (uint16)(n)))) + +#define byteswap16(x) ((rotl16(x, 8) & 0x00ff) | (rotr16(x, 8) & 0xff00)) +#define byteswap32(x) ((rotl32(x, 8) & 0x00ff00ff) | (rotr32(x, 8) & 0xff00ff00)) +#define byteswap64(x) ((rotl64(x, 8) & 0x00ff00ff00ff00ff) | (rotr64(x, 8) & 0xff00ff00ff00ff00)) + +typedef unsigned char opaque; + +/* STATE */ +enum ConnectionEnd { GNUTLS_SERVER, GNUTLS_CLIENT }; +enum BulkCipherAlgorithm { CIPHER_NULL, CIPHER_3DES = 4 }; +enum CipherType { CIPHER_STREAM, CIPHER_BLOCK }; +enum IsExportable { EXPORTABLE_TRUE, EXPORTABLE_FALSE }; +enum MACAlgorithm { MAC_NULL, MAC_MD5, MAC_SHA }; +enum CompressionMethod { COMPRESSION_NULL }; + + +typedef enum ConnectionEnd ConnectionEnd; +typedef enum BulkCipherAlgorithm BulkCipherAlgorithm; +typedef enum CipherType CipherType; +typedef enum IsExportable IsExportable; +typedef enum MACAlgorithm MACAlgorithm; +typedef enum CompressionMethod CompressionMethod; + +typedef struct { + ConnectionEnd entity; + BulkCipherAlgorithm bulk_cipher_algorithm; + CipherType cipher_type; + uint8 IV_size; /* not specified in the protocol, but later it + * uses it */ + uint8 key_size; + uint8 key_material_length; + IsExportable is_exportable; + MACAlgorithm mac_algorithm; + uint8 hash_size; + CompressionMethod compression_algorithm; + opaque master_secret[48]; + opaque client_random[32]; + opaque server_random[32]; +} SecurityParameters; + +typedef struct { + opaque* server_write_mac_secret; + opaque* client_write_mac_secret; + opaque* server_write_IV; + opaque* client_write_IV; + opaque* server_write_key; + opaque* client_write_key; +} CipherSpecs; + +typedef struct { + opaque* compression_state; + GCRY_CIPHER_HD cipher_state; + opaque* mac_secret; + uint8 mac_secret_size; + uint64 read_sequence_number; + uint64 write_sequence_number; +} ConnectionState; + +typedef struct { + SecurityParameters security_parameters; + CipherSpecs cipher_specs; + ConnectionState connection_state; +} GNUTLS_STATE_INT; + +typedef GNUTLS_STATE_INT *GNUTLS_STATE; + + +/* Record Protocol */ +enum ContentType { GNUTLS_CHANGE_CIPHER_SPEC=20, GNUTLS_ALERT, GNUTLS_HANDSHAKE, + GNUTLS_APPLICATION_DATA }; +typedef enum ContentType ContentType; + +#define GNUTLS_VERSION_MAJOR 3 +#define GNUTLS_VERSION_MINOR 1 + +typedef struct { + uint8 major; + uint8 minor; +} ProtocolVersion; + +typedef struct { + ContentType type; + ProtocolVersion version; + uint16 length; + opaque* fragment; +} GNUTLSPlaintext; + +typedef struct { + ContentType type; + ProtocolVersion version; + uint16 length; + opaque* fragment; +} GNUTLSCompressed; + +/* This is used for both block ciphers and stream ciphers. In stream ciphers + * the padding is just ignored. + */ +typedef struct { + opaque* content; + opaque* MAC; + uint8* padding; + uint8 padding_length; +} GNUTLS_GenericBlockCipher; + +typedef struct { + opaque* content; + opaque* MAC; +} GNUTLS_GenericStreamCipher; + +typedef struct { + ContentType type; + ProtocolVersion version; + uint16 length; + void* fragment; /* points GenericStreamCipher + * or GenericBlockCipher + */ +} GNUTLSCiphertext; + + +int gnutls_send_int(int cd, GNUTLS_STATE state, ContentType type, char* data, int sizeofdata); +#define gnutls_send( x, y, z, w) gnutls_send_int( x, y, GNUTLS_APPLICATION_DATA, z, w) + +#define GNUTLS_E_MAC_FAILED -1 +#define GNUTLS_E_UNKNOWN_CIPHER -2 +#define GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM -3 +#define GNUTLS_E_UNKNOWN_MAC_ALGORITHM -4 +#define GNUTLS_E_UNKNOWN_ERROR -5 +#define GNUTLS_E_UNKNOWN_CIPHER_TYPE -6 +#define GNUTLS_E_LARGE_PACKET -7 + diff --git a/src/gnutls_cipher.c b/src/gnutls_cipher.c new file mode 100644 index 0000000000..2001921b46 --- /dev/null +++ b/src/gnutls_cipher.c @@ -0,0 +1,442 @@ +#include +#include "gnutls.h" +#include "gnutls_compress.h" +#include "gnutls_cipher.h" +#include + +#define TDES_BLOCKLEN 8 +#define TDES_KEYLEN 24 +#define MD5_DIGEST 16 +#define SHA_DIGEST 20 + +/* Sets the specified cipher into the state */ +int _gnutls_set_cipher( GNUTLS_STATE state, BulkCipherAlgorithm algo) { + + switch (algo) { + case CIPHER_NULL: + state->security_parameters.bulk_cipher_algorithm=CIPHER_NULL; + state->security_parameters.cipher_type=CIPHER_STREAM; + state->security_parameters.is_exportable=EXPORTABLE_TRUE; + state->security_parameters.key_material_length = + state->security_parameters.key_size = 0; + break; + + case CIPHER_3DES: + state->security_parameters.bulk_cipher_algorithm=CIPHER_3DES; + state->security_parameters.cipher_type=CIPHER_BLOCK; + state->security_parameters.is_exportable=EXPORTABLE_FALSE; + state->security_parameters.key_material_length = + state->security_parameters.key_size = TDES_KEYLEN; + state->security_parameters.IV_size = TDES_BLOCKLEN; + break; + default: + return GNUTLS_E_UNKNOWN_CIPHER; + } + + + return 0; + +} + +/* Sets the specified algorithm into compression state */ +int _gnutls_set_compression( GNUTLS_STATE state, CompressionMethod algo) { + + switch (algo) { + case COMPRESSION_NULL: + break; + + default: + return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM; + } + return 0; + +} + + +int _gnutls_set_mac( GNUTLS_STATE state, MACAlgorithm algo) { + + switch (algo) { + case MAC_NULL: + state->security_parameters.mac_algorithm=MAC_NULL; + state->security_parameters.hash_size=0; + break; + + case MAC_MD5: + state->security_parameters.mac_algorithm=MAC_MD5; + state->security_parameters.hash_size=MD5_DIGEST; + break; + + case MAC_SHA: + state->security_parameters.mac_algorithm=MAC_SHA; + state->security_parameters.hash_size=SHA_DIGEST; + break; + + default: + return GNUTLS_E_UNKNOWN_MAC_ALGORITHM; + } + + return 0; + +} + +/* Sets the current connection state to conform with the + * Security parameters, and initializes encryption. + */ +int _gnutls_connection_state_init(GNUTLS_STATE state) { + int rc; + + gnutls_free( state->connection_state.mac_secret); + if ( state->connection_state.cipher_state != NULL) + gcry_cipher_close( state->connection_state.cipher_state); + gnutls_free( state->connection_state.compression_state); + + switch ( state->security_parameters.compression_algorithm) { + case COMPRESSION_NULL: + state->connection_state.compression_state=NULL; + break; + default: + return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM; + } + + switch ( state->security_parameters.mac_algorithm) { + case MAC_NULL: + state->connection_state.mac_secret = NULL; + state->connection_state.mac_secret_size = 0; + break; + case MAC_MD5: + state->connection_state.mac_secret = gnutls_malloc(MD5_DIGEST); + state->connection_state.mac_secret_size = MD5_DIGEST; + break; + case MAC_SHA: + state->connection_state.mac_secret = gnutls_malloc(SHA_DIGEST); + state->connection_state.mac_secret_size = SHA_DIGEST; + break; + default: + return GNUTLS_E_UNKNOWN_MAC_ALGORITHM; + } + + switch ( state->security_parameters.bulk_cipher_algorithm) { + case CIPHER_NULL: + state->connection_state.cipher_state = NULL; + break; + case CIPHER_3DES: + state->connection_state.cipher_state = gcry_cipher_open(GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0); + break; + default: + return GNUTLS_E_UNKNOWN_CIPHER; + } + + + switch (state->security_parameters.entity) { + case GNUTLS_SERVER: + if (state->connection_state.cipher_state!=NULL) { + rc = gcry_cipher_setkey( state->connection_state.cipher_state, state->cipher_specs.server_write_key, state->security_parameters.key_size); + gcry_cipher_setiv( state->connection_state.cipher_state, state->cipher_specs.server_write_IV, state->security_parameters.IV_size); + } + if (state->connection_state.mac_secret_size>0) + memmove( state->connection_state.mac_secret, state->cipher_specs.server_write_mac_secret, state->connection_state.mac_secret_size); + break; + case GNUTLS_CLIENT: + if (state->connection_state.cipher_state!=NULL) { + gcry_cipher_setiv( state->connection_state.cipher_state, state->cipher_specs.client_write_IV, state->security_parameters.IV_size); + rc = gcry_cipher_setkey( state->connection_state.cipher_state, state->cipher_specs.client_write_key, state->security_parameters.key_size); + } + if (state->connection_state.mac_secret_size>0) + memmove( state->connection_state.mac_secret, state->cipher_specs.client_write_mac_secret, state->connection_state.mac_secret_size); + break; + default: + return GNUTLS_E_UNKNOWN_ERROR; + } + + return 0; +} + +int _gnutls_TLSCompressed2TLSCiphertext(GNUTLS_STATE state, + GNUTLSCiphertext** + cipher, + GNUTLSCompressed * + compressed) +{ + GNUTLSCiphertext *ciphertext; + uint8 *padding, *content, *MAC; + uint8 padding_length; + uint16 c_length; + int rc; + uint8* data; + uint8 *macpointer; + uint8 pad; + uint8 *rand; + uint64 seq_num; + int length; + int td; + + + content = + gnutls_malloc(compressed->length); + memmove(content, compressed->fragment, compressed->length); + +/* if (state->connection_state.mac_secret_size>0) { + MAC = gnutls_malloc(state->connection_state.mac_secret_size); + }*/ + + *cipher = gnutls_malloc(sizeof(GNUTLSCiphertext)); + ciphertext = *cipher; + + switch (state->security_parameters.mac_algorithm) { + case MAC_NULL: + td = -1; + break; + case MAC_SHA: + td = hmac_mhash_init( MHASH_SHA1, state->connection_state.mac_secret, state->connection_state.mac_secret_size, mhash_get_hash_pblock(MHASH_SHA1)); + break; + case MAC_MD5: + td = hmac_mhash_init( MHASH_MD5, state->connection_state.mac_secret, state->connection_state.mac_secret_size, mhash_get_hash_pblock(MHASH_MD5)); + break; + default: + gnutls_free(*cipher); + gnutls_free(content); + return GNUTLS_E_UNKNOWN_MAC_ALGORITHM; + } + +#ifdef WORDS_BIGENDIAN + seq_num = state->connection_state.write_sequence_number; + c_length = compressed->length; +#else + seq_num = byteswap64(state->connection_state.write_sequence_number); + c_length = byteswap16(compressed->length); +#endif + if (td>=0) { + mhash( td, &seq_num, 8); + mhash( td, &compressed->type, 1); + mhash( td, &compressed->version.major, 1); + mhash( td, &compressed->version.minor, 1); + mhash( td, &c_length, 2); + mhash( td, &compressed->fragment, compressed->length); + MAC = hmac_mhash_end( td); + } + switch (state->security_parameters.cipher_type) { + case CIPHER_STREAM: + switch (state->security_parameters.bulk_cipher_algorithm) { + case CIPHER_NULL: + length = compressed->length+state->connection_state.mac_secret_size; + data = gnutls_malloc( length); + memmove( data, content, compressed->length); + memmove( &data[compressed->length], MAC, state->connection_state.mac_secret_size); + ciphertext->fragment = data; + ciphertext->length = length; + ciphertext->type = compressed->type; + ciphertext->version.major = + compressed->version.major; + ciphertext->version.minor = + compressed->version.minor; + break; + default: + gnutls_free(*cipher); + gnutls_free(content); + return GNUTLS_E_UNKNOWN_CIPHER; + + } + break; + case CIPHER_BLOCK: + switch (state->security_parameters.bulk_cipher_algorithm) { + case CIPHER_3DES: + + rand = gcry_random_bytes(1, GCRY_STRONG_RANDOM); + length = compressed->length + state->connection_state.mac_secret_size + + rand[0] + 1; + length = (length / TDES_BLOCKLEN) * TDES_BLOCKLEN; + pad = length - compressed->length - state->connection_state.mac_secret_size - 1; + + /* set pad bytes pad */ + padding = gnutls_malloc( pad); + memset(padding, pad, pad); + padding_length=pad; + + data = gnutls_malloc( length); + memmove( data, content, compressed->length); + memmove( &data[compressed->length], MAC, state->connection_state.mac_secret_size); + memmove( &data[state->connection_state.mac_secret_size+compressed->length], padding, pad); + memmove( &data[pad+state->connection_state.mac_secret_size+compressed->length], &padding_length, 1); + + gnutls_free( padding); + + gcry_cipher_encrypt( state->connection_state.cipher_state, + data, length, + data, length); + + ciphertext->fragment = data; + ciphertext->length = length; + ciphertext->type = compressed->type; + ciphertext->version.major = + compressed->version.major; + ciphertext->version.minor = + compressed->version.minor; + + gcry_free(rand); + break; + default: + gnutls_free(*cipher); + gnutls_free(content); + return GNUTLS_E_UNKNOWN_CIPHER; + } + break; + default: + gnutls_free(*cipher); + gnutls_free(content); + return GNUTLS_E_UNKNOWN_CIPHER_TYPE; + } + +// gnutls_free( MAC); + if (td>=0) free( MAC); + gnutls_free( content); + + return 0; +} + +int _gnutls_TLSCiphertext2TLSCompressed(GNUTLS_STATE state, + GNUTLSCompressed** + compress, + GNUTLSCiphertext * + ciphertext) +{ + GNUTLSCompressed *compressed; + uint8 *content, *MAC; + uint16 c_length; + int rc; + uint8* data; + uint8 *macpointer; + uint8 pad; + uint64 seq_num; + int length; + int td; + + + content = + gnutls_malloc(ciphertext->length); + memmove(content, ciphertext->fragment, ciphertext->length); + +/* if (state->connection_state.mac_secret_size>0) { + MAC = gnutls_malloc(state->connection_state.mac_secret_size); + }*/ + + *compress = gnutls_malloc(sizeof(GNUTLSCompressed)); + compressed = *compress; + + + switch (state->security_parameters.mac_algorithm) { + case MAC_NULL: + td = -1; + break; + case MAC_SHA: + td = hmac_mhash_init( MHASH_SHA1, state->connection_state.mac_secret, state->connection_state.mac_secret_size, mhash_get_hash_pblock(MHASH_SHA1)); + break; + case MAC_MD5: + td = hmac_mhash_init( MHASH_MD5, state->connection_state.mac_secret, state->connection_state.mac_secret_size, mhash_get_hash_pblock(MHASH_MD5)); + break; + default: + gnutls_free(*compress); + gnutls_free(content); + return GNUTLS_E_UNKNOWN_MAC_ALGORITHM; + } + +#ifdef WORDS_BIGENDIAN + seq_num = state->connection_state.read_sequence_number; + c_length = ciphertext->length; +#else + seq_num = byteswap64(state->connection_state.read_sequence_number); + c_length = byteswap16(ciphertext->length); +#endif + if (td>=0) { + mhash( td, &seq_num, 8); + mhash( td, &ciphertext->type, 1); + mhash( td, &ciphertext->version.major, 1); + mhash( td, &ciphertext->version.minor, 1); + mhash( td, &c_length, 2); + mhash( td, &ciphertext->fragment, ciphertext->length); + MAC = hmac_mhash_end( td); + } + switch (state->security_parameters.cipher_type) { + case CIPHER_STREAM: + switch (state->security_parameters.bulk_cipher_algorithm) { + case CIPHER_NULL: + length = ciphertext->length-state->connection_state.mac_secret_size; + data = gnutls_malloc( length); + memmove( data, content, length); + + /* HMAC was not the same. */ + if (memcmp(MAC, &data[length], state->connection_state.mac_secret_size)!=0) return GNUTLS_E_MAC_FAILED; + + compressed->fragment = data; + compressed->length = length; + compressed->type = ciphertext->type; + compressed->version.major = + ciphertext->version.major; + compressed->version.minor = + ciphertext->version.minor; + break; + default: + gnutls_free(*compress); + gnutls_free(content); + return GNUTLS_E_UNKNOWN_CIPHER; + + } + break; + case CIPHER_BLOCK: + switch (state->security_parameters.bulk_cipher_algorithm) { + case CIPHER_3DES: + + gcry_cipher_decrypt( state->connection_state.cipher_state, + content, ciphertext->length, + content, ciphertext->length); + + pad = content[ciphertext->length-1]; /* pad */ + length = ciphertext->length - state->connection_state.mac_secret_size + - pad - 1; + + /* HMAC was not the same. */ + if (memcmp(MAC, &data[length], state->connection_state.mac_secret_size)!=0) return GNUTLS_E_MAC_FAILED; + + data = gnutls_malloc( length); + memmove( data, content, length); + + compressed->fragment = data; + compressed->length = length; + compressed->type = ciphertext->type; + compressed->version.major = + ciphertext->version.major; + compressed->version.minor = + ciphertext->version.minor; + + break; + default: + gnutls_free(*compress); + gnutls_free(content); + return GNUTLS_E_UNKNOWN_CIPHER; + } + break; + default: + gnutls_free(*compress); + gnutls_free(content); + return GNUTLS_E_UNKNOWN_CIPHER_TYPE; + } + +// gnutls_free( MAC); + free( MAC); + gnutls_free( content); + + return 0; +} + + + + +int _gnutls_freeTLSCiphertext(GNUTLSCiphertext * ciphertext) +{ + if (ciphertext == NULL) + return 0; + + gnutls_free(ciphertext->fragment); + gnutls_free(ciphertext); + + return 0; +} diff --git a/src/gnutls_cipher.h b/src/gnutls_cipher.h new file mode 100644 index 0000000000..1ba32edab2 --- /dev/null +++ b/src/gnutls_cipher.h @@ -0,0 +1,15 @@ +int _gnutls_TLSCompressed2TLSCiphertext(GNUTLS_STATE state, + GNUTLSCiphertext** + cipher, + GNUTLSCompressed * + compressed); +int _gnutls_freeTLSCiphertext(GNUTLSCiphertext * ciphertext); +int _gnutls_set_cipher( GNUTLS_STATE state, BulkCipherAlgorithm algo); +int _gnutls_set_mac( GNUTLS_STATE state, MACAlgorithm algo); +int _gnutls_set_compression( GNUTLS_STATE state, CompressionMethod algo); +int _gnutls_connection_state_init(GNUTLS_STATE state); +int _gnutls_TLSCiphertext2TLSCompressed(GNUTLS_STATE state, + GNUTLSCompressed** + compress, + GNUTLSCiphertext * + ciphertext); diff --git a/src/gnutls_compress.c b/src/gnutls_compress.c new file mode 100644 index 0000000000..253c0d6e16 --- /dev/null +++ b/src/gnutls_compress.c @@ -0,0 +1,77 @@ +#include +#include "gnutls.h" +#include "gnutls_compress.h" + +int _gnutls_TLSPlaintext2TLSCompressed(GNUTLS_STATE state, + GNUTLSCompressed ** + compress, + GNUTLSPlaintext * + plaintext) +{ + GNUTLSCompressed *compressed; + + *compress = gnutls_malloc(sizeof(GNUTLSCompressed)); + compressed = *compress; + + switch (state->security_parameters.compression_algorithm) { + case COMPRESSION_NULL: + + compressed->fragment = gnutls_malloc(plaintext->length); + + memmove(compressed->fragment, plaintext->fragment, + plaintext->length); + compressed->length = plaintext->length; + compressed->type = plaintext->type; + compressed->version.major = plaintext->version.major; + compressed->version.minor = plaintext->version.minor; + break; + default: + gnutls_free(*compress); + return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM; + } + + return 0; +} + +int _gnutls_TLSCompressed2TLSPlaintext(GNUTLS_STATE state, + GNUTLSPlaintext** + plain, + GNUTLSCompressed * + compressed) +{ + GNUTLSPlaintext *plaintext; + + *plain = gnutls_malloc(sizeof(GNUTLSPlaintext)); + plaintext = *plain; + + switch (state->security_parameters.compression_algorithm) { + case COMPRESSION_NULL: + plaintext->fragment = gnutls_malloc(compressed->length); + memmove(plaintext->fragment, compressed->fragment, + compressed->length); + plaintext->length = compressed->length; + plaintext->type = compressed->type; + plaintext->version.major = compressed->version.major; + plaintext->version.minor = compressed->version.minor; + break; + default: + gnutls_free(*plain); + return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM; + } + + return 0; +} + + + + +int _gnutls_freeTLSCompressed(GNUTLSCompressed * compressed) +{ + if (compressed == NULL) + return 0; + + gnutls_free(compressed->fragment); + gnutls_free(compressed); + + return 0; +} diff --git a/src/gnutls_compress.h b/src/gnutls_compress.h new file mode 100644 index 0000000000..ef15cac254 --- /dev/null +++ b/src/gnutls_compress.h @@ -0,0 +1,11 @@ +int _gnutls_freeTLSCompressed(GNUTLSCompressed * compressed); +int _gnutls_TLSPlaintext2TLSCompressed(GNUTLS_STATE state, + GNUTLSCompressed ** + compress, + GNUTLSPlaintext * + plaintext); +int _gnutls_TLSCompressed2TLSPlaintext(GNUTLS_STATE state, + GNUTLSPlaintext** + plain, + GNUTLSCompressed * + compressed); diff --git a/src/gnutls_plaintext.c b/src/gnutls_plaintext.c new file mode 100644 index 0000000000..25c8e0588c --- /dev/null +++ b/src/gnutls_plaintext.c @@ -0,0 +1,51 @@ +#include +#include "gnutls.h" + + + +/* Plaintext Handling */ +int _gnutls_text2TLSPlaintext(ContentType type, GNUTLSPlaintext** plain, char *text, uint16 length) +{ + GNUTLSPlaintext *plaintext; + + if (length > 16384) + return GNUTLS_E_LARGE_PACKET; + + *plain = gnutls_malloc(sizeof(GNUTLSPlaintext)); + plaintext = *plain; + + plaintext->fragment = gnutls_malloc(length); + memmove(plaintext->fragment, text, length); + plaintext->length = length; + plaintext->type = type; + plaintext->version.major = GNUTLS_VERSION_MAJOR; + plaintext->version.minor = GNUTLS_VERSION_MINOR; + + return 0; +} + +int _gnutls_TLSPlaintext2text( char** txt, GNUTLSPlaintext* plaintext) +{ + char *text; + + if (plaintext->length > 16384) + return GNUTLS_E_LARGE_PACKET; + + *txt = gnutls_malloc(plaintext->length); + text = *txt; + + memmove(text, plaintext->fragment, plaintext->length); + + return 0; +} + +int _gnutls_freeTLSPlaintext(GNUTLSPlaintext * plaintext) +{ + if (plaintext == NULL) + return 0; + + gnutls_free(plaintext->fragment); + gnutls_free(plaintext); + + return 0; +} diff --git a/src/gnutls_plaintext.h b/src/gnutls_plaintext.h new file mode 100644 index 0000000000..9e3e931de3 --- /dev/null +++ b/src/gnutls_plaintext.h @@ -0,0 +1,3 @@ +int _gnutls_text2TLSPlaintext(ContentType type, GNUTLSPlaintext**, char *text, uint16 length); +int _gnutls_freeTLSPlaintext(GNUTLSPlaintext* plaintext); +int _gnutls_TLSPlaintext2text( char**, GNUTLSPlaintext* plaintext); diff --git a/src/test.c b/src/test.c new file mode 100644 index 0000000000..e65ade73cb --- /dev/null +++ b/src/test.c @@ -0,0 +1,40 @@ +#include +#include +#include "gnutls_compress.h" +#include "gnutls_plaintext.h" +#include "gnutls_cipher.h" +#include +#include +#include +#include +#include + + +int main() +{ + GNUTLS_STATE state; + char text[] = "ena xelidoni sto bouno\n"; + GNUTLSPlaintext *gtxt; + GNUTLSCompressed *gcomp; + GNUTLSCiphertext *gcipher; + int cd; + + + gnutls_init(&state, GNUTLS_CLIENT); + _gnutls_set_cipher(state, CIPHER_3DES); + _gnutls_set_compression( state, COMPRESSION_NULL); + _gnutls_set_mac(state, MAC_NULL); + _print_state(state); + + _gnutls_set_keys( state); + _gnutls_connection_state_init( state); + + remove("ciphertext"); + cd = open( "ciphertext", O_WRONLY|O_CREAT, S_IRWXU); + + gnutls_send( cd, state, text, strlen(text)); + + close(cd); + gnutls_deinit(&state); + return 0; +}