]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
*** empty log message ***
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Wed, 8 Mar 2000 10:48:49 +0000 (10:48 +0000)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Wed, 8 Mar 2000 10:48:49 +0000 (10:48 +0000)
18 files changed:
AUTHORS [new file with mode: 0644]
Makefile.am
acconfig.h
buildconf
configure.in
src/Makefile.am
src/debug.c [new file with mode: 0644]
src/debug.h [new file with mode: 0644]
src/defines.h [new file with mode: 0644]
src/gnutls.c [new file with mode: 0644]
src/gnutls.h [new file with mode: 0644]
src/gnutls_cipher.c [new file with mode: 0644]
src/gnutls_cipher.h [new file with mode: 0644]
src/gnutls_compress.c [new file with mode: 0644]
src/gnutls_compress.h [new file with mode: 0644]
src/gnutls_plaintext.c [new file with mode: 0644]
src/gnutls_plaintext.h [new file with mode: 0644]
src/test.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..e69de29
index 3bd3cb90728c4cd4fe609919e42cc15edf1395ea..9c3e050ebd70d4fd91502815dcea67d5d1c61cb3 100644 (file)
@@ -1,3 +1,4 @@
+## Process this file with automake to produce Makefile.in
 
-SUBDIRS = lib src
-
+SUBDIRS = src
\ No newline at end of file
index c864fca155bd45d22b20e7ab397c4ccaeaf0612d..2098c23e2d64da5306f59193620373dfe83bc779 100644 (file)
@@ -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
index 97c15bb34c62b08edf6e8d66f58d169ef0dd247a..052e8b75723b93cecbf9841e019d93feb2781a3e 100755 (executable)
--- 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 
index 6c097839bdf950fc496087ffba81ac06a6f6f9d1..b1d759566ae652fcc65f5168b8ff8ddb91b3483a 100644 (file)
-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])
index f36936bec513a5d21b307ecae51ec27e97f3228d..8010cac53909dfc1c24bd9ec5c3dc85378c5f2a8 100644 (file)
@@ -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 (file)
index 0000000..e6a0119
--- /dev/null
@@ -0,0 +1,89 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <defines.h>
+#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 (file)
index 0000000..3c19e39
--- /dev/null
@@ -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 (file)
index 0000000..917bc4f
--- /dev/null
@@ -0,0 +1,77 @@
+#include <config.h>
+
+
+
+#ifdef STDC_HEADERS
+# include <string.h>
+# include <stdlib.h>
+# include <stdio.h>
+#endif
+
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#include <time.h>
+
+
+/* for open */
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <gcrypt.h>
+
+#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 (file)
index 0000000..9f528d4
--- /dev/null
@@ -0,0 +1,386 @@
+#include <defines.h>
+#include "gnutls.h"
+#include "debug.h"
+#include "gnutls_compress.h"
+#include "gnutls_plaintext.h"
+#include "gnutls_cipher.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <mhash.h>
+
+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;i<times;i++) {
+               td2 = hmac_mhash_init( algorithm, secret, secret_size, mhash_get_hash_pblock(algorithm));
+
+               td1 = hmac_mhash_init( algorithm, secret, secret_size, mhash_get_hash_pblock(algorithm));
+               mhash( td1, A, seed_size);
+
+               A=hmac_mhash_end( td1);
+               
+               mhash( td2, A, mhash_get_block_size(algorithm));
+               mhash( td2, seed, seed_size);
+               final = hmac_mhash_end( td2);
+
+               copy_bytes=mhash_get_block_size(algorithm);
+               if ((i+1)*copy_bytes < total_bytes) {
+                       how = mhash_get_block_size(algorithm);
+               } else {
+                       how = total_bytes - (i)*copy_bytes;
+               }
+
+               if ( how>0) {
+                       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;i<total_bytes;i++) {
+               ret[i] = o1[i] ^ o2[i];
+       }
+
+       secure_free(o1);
+       secure_free(o2);
+
+       return ret;
+       
+}
+
+/* if  master_secret, client_random and server_random have been initialized,
+ * this functions creates the keys and stores them into state->cipher_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;i<iterations;i++) {
+               err = _gnutls_text2TLSPlaintext(type, &gtxt, &data[i*Size], 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);
+               
+               write( cd, &gcipher->type, 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, &gtxt, &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;i<iterations;i++) {
+               err = _gnutls_text2TLSPlaintext(type, &gtxt, &data[i*Size], 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);
+               
+               write( cd, &gcipher->type, 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, &gtxt, &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 (file)
index 0000000..896c60b
--- /dev/null
@@ -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 (file)
index 0000000..2001921
--- /dev/null
@@ -0,0 +1,442 @@
+#include <defines.h>
+#include "gnutls.h"
+#include "gnutls_compress.h"
+#include "gnutls_cipher.h"
+#include <mhash.h>
+
+#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 (file)
index 0000000..1ba32ed
--- /dev/null
@@ -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 (file)
index 0000000..253c0d6
--- /dev/null
@@ -0,0 +1,77 @@
+#include <defines.h>
+#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 (file)
index 0000000..ef15cac
--- /dev/null
@@ -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 (file)
index 0000000..25c8e05
--- /dev/null
@@ -0,0 +1,51 @@
+#include <defines.h>
+#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 (file)
index 0000000..9e3e931
--- /dev/null
@@ -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 (file)
index 0000000..e65ade7
--- /dev/null
@@ -0,0 +1,40 @@
+#include <defines.h>
+#include <gnutls.h>
+#include "gnutls_compress.h"
+#include "gnutls_plaintext.h"
+#include "gnutls_cipher.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+                     
+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;
+}