gnutls-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU gnutls branch, new, updated. gnutls_2_9_10-52-g0627fb6


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, new, updated. gnutls_2_9_10-52-g0627fb6
Date: Fri, 21 May 2010 15:04:46 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU gnutls".

http://git.savannah.gnu.org/cgit/gnutls.git/commit/?id=0627fb68a819799119d46134623d59911ee4b936

The branch, new has been updated
       via  0627fb68a819799119d46134623d59911ee4b936 (commit)
      from  b94f9dc069ffd9143c6dfba453f2431f7f432c34 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 0627fb68a819799119d46134623d59911ee4b936
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Fri May 21 17:00:01 2010 +0200

    Added support for libnettle backend. This uses gmp for big number 
operations.
    It is not currently completed. It lacks RSA blinding as well as 
optimizations.

-----------------------------------------------------------------------

Summary of changes:
 configure.ac                                |    3 +-
 doc/examples/ex-serv-export.c               |    5 -
 doc/examples/ex-serv-psk.c                  |    5 -
 doc/examples/ex-serv1.c                     |    5 -
 lib/Makefile.am                             |   19 +-
 lib/auth_srp.c                              |    4 +-
 lib/configure.ac                            |    6 +-
 lib/{opencdk => gcrypt}/Makefile.am         |   13 +-
 lib/{cipher-libgcrypt.c => gcrypt/cipher.c} |    0
 lib/{mac-libgcrypt.c => gcrypt/mac.c}       |    0
 lib/{mpi-libgcrypt.c => gcrypt/mpi.c}       |    7 +-
 lib/{pk-libgcrypt.c => gcrypt/pk.c}         |    0
 lib/{rnd-libgcrypt.c => gcrypt/rnd.c}       |    0
 lib/gnutls_global.c                         |    5 +-
 lib/gnutls_mpi.c                            |    2 +-
 lib/gnutls_srp.c                            |   13 +-
 lib/m4/hooks.m4                             |   31 ++-
 lib/{opencdk => nettle}/Makefile.am         |   13 +-
 lib/nettle/cipher.c                         |  208 ++++++++++
 lib/nettle/mac.c                            |  290 ++++++++++++++
 lib/nettle/mpi.c                            |  551 +++++++++++++++++++++++++++
 lib/nettle/pk.c                             |  469 +++++++++++++++++++++++
 lib/nettle/rnd.c                            |  210 ++++++++++
 src/certtool.c                              |   19 -
 src/cli.c                                   |   19 -
 src/serv.c                                  |   16 -
 tests/chainverify.c                         |    2 +-
 27 files changed, 1808 insertions(+), 107 deletions(-)
 copy lib/{opencdk => gcrypt}/Makefile.am (73%)
 rename lib/{cipher-libgcrypt.c => gcrypt/cipher.c} (100%)
 rename lib/{mac-libgcrypt.c => gcrypt/mac.c} (100%)
 rename lib/{mpi-libgcrypt.c => gcrypt/mpi.c} (98%)
 rename lib/{pk-libgcrypt.c => gcrypt/pk.c} (100%)
 rename lib/{rnd-libgcrypt.c => gcrypt/rnd.c} (100%)
 copy lib/{opencdk => nettle}/Makefile.am (73%)
 create mode 100644 lib/nettle/cipher.c
 create mode 100644 lib/nettle/mac.c
 create mode 100644 lib/nettle/mpi.c
 create mode 100644 lib/nettle/pk.c
 create mode 100644 lib/nettle/rnd.c

diff --git a/configure.ac b/configure.ac
index ce4b4eb..2256081 100644
--- a/configure.ac
+++ b/configure.ac
@@ -74,7 +74,7 @@ AC_DEFINE([HAVE_CTYPE_H], 1, [Hard-code for src/cfg/.])
 AC_DEFINE([HAVE_ERRNO_H], 1, [Hard-code for src/cfg/.])
 
 # No fork on MinGW, disable some self-tests until we fix them.
-AC_CHECK_FUNCS(fork,,)
+AC_CHECK_FUNCS(fork getrusage,,)
 AM_CONDITIONAL(HAVE_FORK, test "$ac_cv_func_fork" != "no")
 
 sj_VALGRIND
@@ -307,4 +307,5 @@ AC_MSG_NOTICE([summary of build options:
   C++ library:      $use_cxx
   OpenSSL library:  $enable_openssl
   /dev/crypto:      $enable_cryptodev
+  Crypto library:   $cryptolib
 ])
diff --git a/doc/examples/ex-serv-export.c b/doc/examples/ex-serv-export.c
index 33b6d0a..b79ad55 100644
--- a/doc/examples/ex-serv-export.c
+++ b/doc/examples/ex-serv-export.c
@@ -14,7 +14,6 @@
 #include <string.h>
 #include <unistd.h>
 #include <gnutls/gnutls.h>
-#include <gcrypt.h>            /* for gcry_control */
 
 #define KEYFILE "key.pem"
 #define CERTFILE "cert.pem"
@@ -132,10 +131,6 @@ main (void)
 
   strcpy (name, "Echo Server");
 
-  /* to disallow usage of the blocking /dev/random 
-   */
-  gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
-
   /* this must be called once in the program
    */
   gnutls_global_init ();
diff --git a/doc/examples/ex-serv-psk.c b/doc/examples/ex-serv-psk.c
index f661ff9..0c4c575 100644
--- a/doc/examples/ex-serv-psk.c
+++ b/doc/examples/ex-serv-psk.c
@@ -14,7 +14,6 @@
 #include <string.h>
 #include <unistd.h>
 #include <gnutls/gnutls.h>
-#include <gcrypt.h>            /* for gcry_control */
 
 #define KEYFILE "key.pem"
 #define CERTFILE "cert.pem"
@@ -101,10 +100,6 @@ main (void)
   char buffer[MAX_BUF + 1];
   int optval = 1;
 
-  /* to disallow usage of the blocking /dev/random 
-   */
-  gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
-
   /* this must be called once in the program
    */
   gnutls_global_init ();
diff --git a/doc/examples/ex-serv1.c b/doc/examples/ex-serv1.c
index 755bf8d..55af0ae 100644
--- a/doc/examples/ex-serv1.c
+++ b/doc/examples/ex-serv1.c
@@ -14,7 +14,6 @@
 #include <string.h>
 #include <unistd.h>
 #include <gnutls/gnutls.h>
-#include <gcrypt.h>            /* for gcry_control */
 
 #define KEYFILE "key.pem"
 #define CERTFILE "cert.pem"
@@ -90,10 +89,6 @@ main (void)
   char buffer[MAX_BUF + 1];
   int optval = 1;
 
-  /* to disallow usage of the blocking /dev/random 
-   */
-  gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
-
   /* this must be called once in the program
    */
   gnutls_global_init ();
diff --git a/lib/Makefile.am b/lib/Makefile.am
index b80467e..51137ed 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -80,11 +80,16 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c 
gnutls_cipher.c        \
        gnutls_str.c gnutls_state.c gnutls_x509.c ext_cert_type.c       \
        gnutls_rsa_export.c auth_rsa_export.c ext_server_name.c         \
        auth_dh_common.c gnutls_helper.c gnutls_supplemental.c          \
-       crypto.c random.c pk-libgcrypt.c mpi-libgcrypt.c cryptodev.c    \
-       rnd-libgcrypt.c cipher-libgcrypt.c mac-libgcrypt.c ext_signature.c \
+       crypto.c random.c  ext_signature.c cryptodev.c \
        crypto-api.c ext_safe_renegotiation.c gnutls_privkey.c \
        pkcs11.c pkcs11_privkey.c
 
+if ENABLE_NETTLE
+SUBDIRS += nettle
+else
+SUBDIRS += gcrypt
+endif
+
 if ENABLE_OPRFI
 COBJECTS += $(OPRFI_COBJECTS)
 endif
@@ -116,7 +121,7 @@ libgnutls_la_LDFLAGS = -no-undefined \
        -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
 
 libgnutls_la_LIBADD = gl/liblgnu.la x509/libgnutls_x509.la \
-       $(LTLIBZ) $(LTLIBGCRYPT) $(LTLIBINTL) $(LIBSOCKET)
+       $(LTLIBZ)  $(LTLIBINTL) $(LIBSOCKET)
 
 if ENABLE_OPENPGP
 libgnutls_la_LIBADD += openpgp/libgnutls_openpgp.la
@@ -139,6 +144,14 @@ if ENABLE_PAKCHOIS
 libgnutls_la_LDFLAGS += $(LTLIBPAKCHOIS)
 endif
 
+if ENABLE_NETTLE
+libgnutls_la_LDFLAGS += $(LTLIBNETTLE) -lgmp -lpthread -lhogweed
+libgnutls_la_LIBADD += nettle/libcrypto.la
+else
+libgnutls_la_LDFLAGS += $(LTLIBGCRYPT)
+libgnutls_la_LIBADD += gcrypt/libcrypto.la
+endif
+
 if HAVE_LD_OUTPUT_DEF
 libgnutls_la_LDFLAGS += -Wl,--output-def,libgnutls-$(DLL_VERSION).def
 defexecdir = $(bindir)
diff --git a/lib/auth_srp.c b/lib/auth_srp.c
index 9a45fa4..26f728a 100644
--- a/lib/auth_srp.c
+++ b/lib/auth_srp.c
@@ -196,7 +196,7 @@ _gnutls_gen_srp_server_kx (gnutls_session_t session, opaque 
** data)
       return GNUTLS_E_MEMORY_ERROR;
     }
 
-  if (_gnutls_mpi_print (B, NULL, &n_b) != 0)
+  if (_gnutls_mpi_print (B, NULL, &n_b) != GNUTLS_E_SHORT_MEMORY_BUFFER)
     {
       gnutls_assert ();
       return GNUTLS_E_MPI_PRINT_FAILED;
@@ -344,7 +344,7 @@ _gnutls_gen_srp_client_kx (gnutls_session_t session, opaque 
** data)
       return ret;
     }
 
-  if (_gnutls_mpi_print (A, NULL, &n_a) != 0)
+  if (_gnutls_mpi_print (A, NULL, &n_a) != GNUTLS_E_SHORT_MEMORY_BUFFER)
     {
       gnutls_assert ();
       return GNUTLS_E_MPI_PRINT_FAILED;
diff --git a/lib/configure.ac b/lib/configure.ac
index 60a2fd1..a8592cb 100644
--- a/lib/configure.ac
+++ b/lib/configure.ac
@@ -87,9 +87,9 @@ if test x$ac_pakchois != xno; then
  AC_MSG_RESULT(yes)
  AC_LIB_HAVE_LINKFLAGS(pakchois,, [#include <pakchois/pakchois.h>], 
[pakchois_module_load(0,0);])
  if test "$ac_cv_libpakchois" != yes; then
-   AC_MSG_WARN(
+   AC_MSG_ERROR(
 *** 
-*** Pakchois was not found. You will not be able to use PKCS11 support.)
+*** Pakchois was not found. This is required for PKCS11 support.)
  fi
 else
  AC_MSG_RESULT(no)
@@ -124,5 +124,7 @@ AC_CONFIG_FILES([
   openpgp/Makefile
   po/Makefile.in
   x509/Makefile
+  gcrypt/Makefile
+  nettle/Makefile
 ])
 AC_OUTPUT
diff --git a/lib/opencdk/Makefile.am b/lib/gcrypt/Makefile.am
similarity index 73%
copy from lib/opencdk/Makefile.am
copy to lib/gcrypt/Makefile.am
index 8d9913f..e55459c 100644
--- a/lib/opencdk/Makefile.am
+++ b/lib/gcrypt/Makefile.am
@@ -28,15 +28,6 @@ AM_CPPFLAGS = \
        -I$(builddir)/../includes       \
        -I$(srcdir)/..
 
-if ENABLE_MINITASN1
-AM_CPPFLAGS += -I$(srcdir)/../minitasn1
-endif
+noinst_LTLIBRARIES = libcrypto.la
 
-noinst_LTLIBRARIES = libminiopencdk.la
-
-libminiopencdk_la_SOURCES = armor.c filters.h keydb.h main.c types.h   \
-       kbnode.c main.h packet.h dummy.c sig-check.c verify.c hash.c \
-       keydb.c pubkey.c stream.c write-packet.c misc.c seskey.c \
-       context.h literal.c new-packet.c read-packet.c stream.h opencdk.h
-
-EXTRA_DIST = README
+libcrypto_la_SOURCES = pk.c mpi.c mac.c cipher.c rnd.c
diff --git a/lib/cipher-libgcrypt.c b/lib/gcrypt/cipher.c
similarity index 100%
rename from lib/cipher-libgcrypt.c
rename to lib/gcrypt/cipher.c
diff --git a/lib/mac-libgcrypt.c b/lib/gcrypt/mac.c
similarity index 100%
rename from lib/mac-libgcrypt.c
rename to lib/gcrypt/mac.c
diff --git a/lib/mpi-libgcrypt.c b/lib/gcrypt/mpi.c
similarity index 98%
rename from lib/mpi-libgcrypt.c
rename to lib/gcrypt/mpi.c
index 0781dbf..8fb4f50 100644
--- a/lib/mpi-libgcrypt.c
+++ b/lib/gcrypt/mpi.c
@@ -68,6 +68,7 @@ wrap_gcry_mpi_print (const bigint_t a, void *buffer, size_t * 
nbytes,
                     gnutls_bigint_format_t format)
 {
   int ret;
+  size_t init_bytes = *nbytes;
 
   format = _format_conv (format);
 
@@ -75,8 +76,12 @@ wrap_gcry_mpi_print (const bigint_t a, void *buffer, size_t 
* nbytes,
     return GNUTLS_E_INVALID_REQUEST;
 
   ret = gcry_mpi_print (format, buffer, *nbytes, nbytes, a);
-  if (!ret)
+  if (!ret) {
+    if (buffer==NULL || init_bytes < *nbytes) {
+      return GNUTLS_E_SHORT_MEMORY_BUFFER;
+    }
     return 0;
+  }
 
   return GNUTLS_E_MPI_PRINT_FAILED;
 }
diff --git a/lib/pk-libgcrypt.c b/lib/gcrypt/pk.c
similarity index 100%
rename from lib/pk-libgcrypt.c
rename to lib/gcrypt/pk.c
diff --git a/lib/rnd-libgcrypt.c b/lib/gcrypt/rnd.c
similarity index 100%
rename from lib/rnd-libgcrypt.c
rename to lib/gcrypt/rnd.c
diff --git a/lib/gnutls_global.c b/lib/gnutls_global.c
index 5dd90b1..9100b0a 100644
--- a/lib/gnutls_global.c
+++ b/lib/gnutls_global.c
@@ -28,7 +28,9 @@
 #include <libtasn1.h>
 #include <gnutls_dh.h>
 #include <random.h>
+#ifndef HAVE_LIBNETTLE
 #include <gcrypt.h>
+#endif
 #include <gnutls/pkcs11.h>
 
 #include <gnutls_extensions.h> /* for _gnutls_ext_init */
@@ -184,6 +186,7 @@ gnutls_global_init (void)
 
   bindtextdomain (PACKAGE, LOCALEDIR);
 
+#ifndef HAVE_LIBNETTLE
   /* Initialize libgcrypt if it hasn't already been initialized. */
   if (gcry_control (GCRYCTL_ANY_INITIALIZATION_P) == 0)
     {
@@ -205,7 +208,7 @@ gnutls_global_init (void)
 
       gcry_control (GCRYCTL_INITIALIZATION_FINISHED, NULL, 0);
     }
-
+#endif
   /* initialize ASN.1 parser
    * This should not deal with files in the final
    * version.
diff --git a/lib/gnutls_mpi.c b/lib/gnutls_mpi.c
index 76a93a0..bca9456 100644
--- a/lib/gnutls_mpi.c
+++ b/lib/gnutls_mpi.c
@@ -343,7 +343,7 @@ _gnutls_x509_write_int (ASN1_TYPE node, const char *value, 
bigint_t mpi,
   else
     result = _gnutls_mpi_print (mpi, NULL, &s_len);
 
-  if (result != 0)
+  if (result != GNUTLS_E_SHORT_MEMORY_BUFFER)
     {
       gnutls_assert ();
       return result;
diff --git a/lib/gnutls_srp.c b/lib/gnutls_srp.c
index 3b9a858..cadc8d3 100644
--- a/lib/gnutls_srp.c
+++ b/lib/gnutls_srp.c
@@ -48,6 +48,7 @@ _gnutls_srp_gx (opaque * text, size_t textsize, opaque ** 
result,
 {
   bigint_t x, e;
   size_t result_size;
+  int ret;
 
   if (_gnutls_mpi_scan_nz (&x, text, textsize))
     {
@@ -67,19 +68,25 @@ _gnutls_srp_gx (opaque * text, size_t textsize, opaque ** 
result,
   _gnutls_mpi_powm (e, g, x, prime);
   _gnutls_mpi_release (&x);
 
-  _gnutls_mpi_print (e, NULL, &result_size);
-  if (result != NULL)
+  ret = _gnutls_mpi_print (e, NULL, &result_size);
+  if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
     {
       *result = galloc_func (result_size);
       if ((*result) == NULL)
        return GNUTLS_E_MEMORY_ERROR;
 
       _gnutls_mpi_print (e, *result, &result_size);
+      ret = result_size;
+    }
+  else
+    {
+      gnutls_assert();
+      ret = GNUTLS_E_MPI_PRINT_FAILED;
     }
 
   _gnutls_mpi_release (&e);
 
-  return result_size;
+  return ret;
 
 }
 
diff --git a/lib/m4/hooks.m4 b/lib/m4/hooks.m4
index 4a0029b..2582b7d 100644
--- a/lib/m4/hooks.m4
+++ b/lib/m4/hooks.m4
@@ -34,7 +34,30 @@ AC_DEFUN([LIBGNUTLS_HOOKS],
   DLL_VERSION=`expr ${LT_CURRENT} - ${LT_AGE}`
   AC_SUBST(DLL_VERSION)
 
-  AC_LIB_HAVE_LINKFLAGS([gcrypt], [gpg-error], [#include <gcrypt.h>],
+  cryptolib="nettle (unsupported)"
+  AC_ARG_WITH(nettle,
+    AS_HELP_STRING([--with-nettle], [use libnettle 2.x as crypto library]),
+      nettle=$withval,
+      nettle=no)
+    if test "$nettle" = "yes"; then
+    AC_LIB_HAVE_LINKFLAGS([nettle],, [#include <nettle/aes.h>],
+                          [aes_set_key (0, 0, 0)])
+    if test "$ac_cv_libnettle" != yes; then
+      nettle=yes
+      AC_MSG_WARN([[
+  *** 
+  *** Libnettle was not found. 
+  ]])
+    fi
+  fi
+
+  AC_MSG_CHECKING([whether to use nettle])
+  AC_MSG_RESULT($nettle)
+  AM_CONDITIONAL(ENABLE_NETTLE, test "$nettle" = "yes")
+
+  if test "$nettle" != "yes";then
+       cryptolib=libgcrypt
+       AC_LIB_HAVE_LINKFLAGS([gcrypt], [gpg-error], [#include <gcrypt.h>],
     [enum gcry_cipher_algos i = GCRY_CIPHER_CAMELLIA128])
   if test "$ac_cv_libgcrypt" != yes; then
     AC_MSG_ERROR([[
@@ -44,6 +67,7 @@ AC_DEFUN([LIBGNUTLS_HOOKS],
 ***
     ]])
   fi
+  fi
 
   AC_ARG_WITH(included-libtasn1,
     AS_HELP_STRING([--with-included-libtasn1], [use the included libtasn1]),
@@ -174,9 +198,14 @@ AC_DEFUN([LIBGNUTLS_HOOKS],
   AM_CONDITIONAL(ENABLE_ANON, test "$ac_enable_anon" != "no")
   
   # Allow disabling Camellia
+  if test "$nettle" != "yes";then
   AC_ARG_ENABLE(camellia,
     AS_HELP_STRING([--disable-camellia], [disable Camellia cipher]),
     enable_camellia=$enableval, enable_camellia=yes)
+  else
+    enable_camellia=no
+  fi
+
   AC_MSG_CHECKING([whether to disable Camellia cipher])
   if test "$enable_camellia" != "no"; then
    AC_MSG_RESULT([no])
diff --git a/lib/opencdk/Makefile.am b/lib/nettle/Makefile.am
similarity index 73%
copy from lib/opencdk/Makefile.am
copy to lib/nettle/Makefile.am
index 8d9913f..e55459c 100644
--- a/lib/opencdk/Makefile.am
+++ b/lib/nettle/Makefile.am
@@ -28,15 +28,6 @@ AM_CPPFLAGS = \
        -I$(builddir)/../includes       \
        -I$(srcdir)/..
 
-if ENABLE_MINITASN1
-AM_CPPFLAGS += -I$(srcdir)/../minitasn1
-endif
+noinst_LTLIBRARIES = libcrypto.la
 
-noinst_LTLIBRARIES = libminiopencdk.la
-
-libminiopencdk_la_SOURCES = armor.c filters.h keydb.h main.c types.h   \
-       kbnode.c main.h packet.h dummy.c sig-check.c verify.c hash.c \
-       keydb.c pubkey.c stream.c write-packet.c misc.c seskey.c \
-       context.h literal.c new-packet.c read-packet.c stream.h opencdk.h
-
-EXTRA_DIST = README
+libcrypto_la_SOURCES = pk.c mpi.c mac.c cipher.c rnd.c
diff --git a/lib/nettle/cipher.c b/lib/nettle/cipher.c
new file mode 100644
index 0000000..1c56a39
--- /dev/null
+++ b/lib/nettle/cipher.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Here lie nettle's wrappers for cipher support.
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_cipher_int.h>
+#include <nettle/aes.h>
+#include <nettle/arcfour.h>
+#include <nettle/arctwo.h>
+#include <nettle/des.h>
+#include <nettle/nettle-meta.h>
+#include <nettle/cbc.h>
+
+/* Functions that refer to the libgcrypt library.
+ */
+
+#define MAX_BLOCK_SIZE 32
+
+typedef void (*encrypt_func)(void*, nettle_crypt_func, unsigned, uint8_t*, 
unsigned, uint8_t *, const uint8_t *);
+typedef void (*decrypt_func)(void*, nettle_crypt_func, unsigned, uint8_t*, 
unsigned, uint8_t *, const uint8_t *);
+typedef void (*setkey_func)(void*, unsigned, const uint8_t*);
+
+static void stream_encrypt (void* ctx, nettle_crypt_func func, unsigned 
block_size, uint8_t* iv, unsigned length, uint8_t * dst, const uint8_t * src)
+{
+       func(ctx, length, dst, src);
+}
+
+struct nettle_cipher_ctx {
+    union {
+               struct aes_ctx aes;
+               struct arcfour_ctx arcfour;
+               struct arctwo_ctx arctwo;
+               struct des3_ctx des3;
+               struct des_ctx des;
+    } ctx;
+    void *ctx_ptr;
+    uint8_t iv[MAX_BLOCK_SIZE];
+    gnutls_cipher_algorithm_t algo;
+    size_t block_size;
+    nettle_crypt_func* i_encrypt;
+    nettle_crypt_func* i_decrypt;
+    encrypt_func encrypt;
+    decrypt_func decrypt;
+    setkey_func setkey;
+};
+
+
+
+static int
+wrap_nettle_cipher_init (gnutls_cipher_algorithm_t algo, void **_ctx)
+{
+       struct nettle_cipher_ctx* ctx;
+
+    ctx = gnutls_calloc(1, sizeof(struct nettle_cipher_ctx));
+    if (ctx == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_MEMORY_ERROR;
+    }
+
+    ctx->algo = algo;
+
+    switch (algo) {
+    case GNUTLS_CIPHER_AES_128_CBC:
+    case GNUTLS_CIPHER_AES_192_CBC:
+    case GNUTLS_CIPHER_AES_256_CBC:
+               ctx->encrypt = cbc_encrypt;
+               ctx->decrypt = cbc_decrypt;
+               ctx->i_encrypt = (nettle_crypt_func*)aes_encrypt;
+               ctx->i_decrypt = (nettle_crypt_func*)aes_decrypt;
+               ctx->setkey = (setkey_func)aes_set_key;
+               ctx->ctx_ptr = &ctx->ctx.aes;
+               ctx->block_size = AES_BLOCK_SIZE;
+               break;
+    case GNUTLS_CIPHER_3DES_CBC:
+               ctx->encrypt = cbc_encrypt;
+               ctx->decrypt = cbc_decrypt;
+               ctx->i_encrypt = (nettle_crypt_func*)des3_encrypt;
+               ctx->i_decrypt = (nettle_crypt_func*)des3_decrypt;
+               ctx->setkey = (setkey_func)des3_set_key2;
+               ctx->ctx_ptr = &ctx->ctx.des3;
+               ctx->block_size = DES3_BLOCK_SIZE;
+               break;
+    case GNUTLS_CIPHER_DES_CBC:
+               ctx->encrypt = cbc_encrypt;
+               ctx->decrypt = cbc_decrypt;
+               ctx->i_encrypt = (nettle_crypt_func*)des_encrypt;
+               ctx->i_decrypt = (nettle_crypt_func*)des_decrypt;
+               ctx->setkey = (setkey_func)des_set_key2;
+               ctx->ctx_ptr = &ctx->ctx.des;
+               ctx->block_size = DES_BLOCK_SIZE;
+               break;
+    case GNUTLS_CIPHER_ARCFOUR_128:
+    case GNUTLS_CIPHER_ARCFOUR_40:
+               ctx->encrypt = stream_encrypt;
+               ctx->decrypt = stream_encrypt;
+               ctx->i_encrypt = (nettle_crypt_func*)arcfour_crypt;
+               ctx->i_decrypt = (nettle_crypt_func*)arcfour_crypt;
+               ctx->setkey = (setkey_func)arcfour_set_key;
+               ctx->ctx_ptr = &ctx->ctx.arcfour;
+               ctx->block_size = 1;
+               break;
+    case GNUTLS_CIPHER_RC2_40_CBC:
+               ctx->encrypt = cbc_encrypt;
+               ctx->decrypt = cbc_decrypt;
+               ctx->i_encrypt = (nettle_crypt_func*)arctwo_encrypt;
+               ctx->i_decrypt = (nettle_crypt_func*)arctwo_decrypt;
+               ctx->setkey = (setkey_func)arctwo_set_key;
+               ctx->ctx_ptr = &ctx->ctx.arctwo;
+               ctx->block_size = ARCTWO_BLOCK_SIZE;
+               break;
+       /* FIXME: Camellia? */
+    default:
+      gnutls_assert ();
+      return GNUTLS_E_INVALID_REQUEST;
+    }
+       
+       *_ctx = ctx;
+
+       return 0;
+}
+
+static int
+wrap_nettle_cipher_setkey (void *_ctx, const void *key, size_t keysize)
+{
+       struct nettle_cipher_ctx* ctx = _ctx;
+       
+       ctx->setkey(ctx->ctx_ptr, keysize, key);
+       
+       return 0;
+}
+
+static int
+wrap_nettle_cipher_setiv (void *_ctx, const void *iv, size_t ivsize)
+{
+       struct nettle_cipher_ctx* ctx = _ctx;
+
+       if (ivsize > ctx->block_size) {
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+       }
+       memcpy(ctx->iv, iv, ivsize);
+
+       return 0;
+}
+
+static int
+wrap_nettle_cipher_decrypt (void *_ctx, const void *encr, size_t encrsize,
+                         void *plain, size_t plainsize)
+{
+       struct nettle_cipher_ctx* ctx = _ctx;
+
+       ctx->decrypt(ctx->ctx_ptr, ctx->i_decrypt, ctx->block_size, ctx->iv, 
encrsize, plain, encr);
+       
+       return 0;
+}
+
+static int
+wrap_nettle_cipher_encrypt (void *_ctx, const void *plain, size_t plainsize,
+                         void *encr, size_t encrsize)
+{
+       struct nettle_cipher_ctx* ctx = _ctx;
+
+       ctx->encrypt(ctx->ctx_ptr, ctx->i_encrypt, ctx->block_size, ctx->iv, 
plainsize, encr, plain);
+       
+       return 0;
+}
+
+static void
+wrap_nettle_cipher_close (void *h)
+{
+       gnutls_free(h);
+}
+
+
+int crypto_cipher_prio = INT_MAX;
+
+gnutls_crypto_cipher_st _gnutls_cipher_ops = {
+  .init = wrap_nettle_cipher_init,
+  .setkey = wrap_nettle_cipher_setkey,
+  .setiv = wrap_nettle_cipher_setiv,
+  .encrypt = wrap_nettle_cipher_encrypt,
+  .decrypt = wrap_nettle_cipher_decrypt,
+  .deinit = wrap_nettle_cipher_close,
+};
diff --git a/lib/nettle/mac.c b/lib/nettle/mac.c
new file mode 100644
index 0000000..5821843
--- /dev/null
+++ b/lib/nettle/mac.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2008, 2010 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* This file provides is the backend hash/mac API for libgcrypt.
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_hash_int.h>
+#include <gnutls_errors.h>
+#include <nettle/md5.h>
+#include <nettle/md2.h>
+#include <nettle/sha.h>
+#include <nettle/hmac.h>
+
+typedef void (*update_func) (void *, unsigned, const uint8_t *);
+typedef void (*digest_func) (void *, unsigned, uint8_t *);
+typedef void (*set_key_func) (void *, unsigned, const uint8_t *);
+
+static int wrap_nettle_hash_init(gnutls_mac_algorithm_t algo, void **_ctx);
+
+struct nettle_hash_ctx {
+    union {
+               struct md5_ctx md5;
+               struct md2_ctx md2;
+               struct sha256_ctx sha256;
+               struct sha1_ctx sha1;
+    } ctx;
+    void *ctx_ptr;
+    gnutls_mac_algorithm_t algo;
+    size_t length;
+    update_func update;
+    digest_func digest;
+};
+
+struct nettle_hmac_ctx {
+    union {
+               struct hmac_md5_ctx md5;
+               struct hmac_sha256_ctx sha256;
+               struct hmac_sha1_ctx sha1;
+    } ctx;
+    void *ctx_ptr;
+    gnutls_mac_algorithm_t algo;
+    size_t length;
+    update_func update;
+    digest_func digest;
+    set_key_func setkey;
+};
+
+static int wrap_nettle_hmac_init(gnutls_mac_algorithm_t algo, void **_ctx)
+{
+       struct nettle_hmac_ctx* ctx;
+
+    ctx = gnutls_malloc(sizeof(struct nettle_hmac_ctx));
+    if (ctx == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_MEMORY_ERROR;
+    }
+
+    ctx->algo = algo;
+
+    switch (algo) {
+    case GNUTLS_MAC_MD5:
+               ctx->update = (update_func)hmac_md5_update;
+               ctx->digest = (digest_func)hmac_md5_digest;
+               ctx->setkey = (set_key_func)hmac_md5_set_key;
+               ctx->ctx_ptr = &ctx->ctx.md5;
+               ctx->length = MD5_DIGEST_SIZE;
+               break;
+    case GNUTLS_MAC_SHA1:
+               ctx->update = (update_func)hmac_sha1_update;
+               ctx->digest = (digest_func)hmac_sha1_digest;
+               ctx->setkey = (set_key_func)hmac_sha1_set_key;
+               ctx->ctx_ptr = &ctx->ctx.sha1;
+               ctx->length = SHA1_DIGEST_SIZE;
+               break;
+    case GNUTLS_MAC_SHA256:
+               ctx->update = (update_func)hmac_sha256_update;
+               ctx->digest = (digest_func)hmac_sha256_digest;
+               ctx->setkey = (set_key_func)hmac_sha256_set_key;
+               ctx->ctx_ptr = &ctx->ctx.sha256;
+               ctx->length = SHA256_DIGEST_SIZE;
+               break;
+       /* FIXME: SHA512/384/224? */
+    default:
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+    }
+
+       *_ctx = ctx;
+
+    return 0;
+}
+
+static int wrap_nettle_hmac_setkey(void *_ctx, const void *key, size_t keylen)
+{
+    struct nettle_hmac_ctx *ctx = _ctx;
+    
+       ctx->setkey(ctx->ctx_ptr, keylen, key);
+
+    return GNUTLS_E_SUCCESS;
+}
+
+static int
+wrap_nettle_hmac_update(void *_ctx, const void *text, size_t textsize)
+{
+    struct nettle_hmac_ctx *ctx = _ctx;
+
+    ctx->update(ctx->ctx_ptr, textsize, text);
+
+    return GNUTLS_E_SUCCESS;
+}
+
+static int
+wrap_nettle_hash_update(void *_ctx, const void *text, size_t textsize)
+{
+    struct nettle_hash_ctx *ctx = _ctx;
+
+    ctx->update(ctx->ctx_ptr, textsize, text);
+
+    return GNUTLS_E_SUCCESS;
+}
+
+static int wrap_nettle_hash_copy(void **bhd, void *ahd)
+{
+       struct nettle_hash_ctx *ctx = ahd;
+       struct nettle_hash_ctx *dst_ctx;
+       int ret;
+
+       ret = wrap_nettle_hash_init(ctx->algo, bhd);
+       if (ret < 0) {
+               gnutls_assert();
+               return ret;
+       }
+       
+       dst_ctx = *bhd;
+       
+       memcpy(&dst_ctx->ctx, &ctx->ctx, sizeof(ctx->ctx));
+
+       return 0;
+}
+
+static int wrap_nettle_hmac_copy(void **bhd, void *ahd)
+{
+       struct nettle_hmac_ctx *ctx = ahd;
+       struct nettle_hmac_ctx *dst_ctx;
+       int ret;
+
+       ret = wrap_nettle_hmac_init(ctx->algo, bhd);
+       if (ret < 0) {
+               gnutls_assert();
+               return ret;
+       }
+       
+       dst_ctx = *bhd;
+
+       memcpy(&dst_ctx->ctx, &ctx->ctx, sizeof(ctx->ctx));
+       
+       return 0;
+}
+
+static void wrap_nettle_md_close(void *hd)
+{
+    gnutls_free(hd);
+}
+
+static int wrap_nettle_hash_init(gnutls_mac_algorithm_t algo, void **_ctx)
+{
+       struct nettle_hash_ctx* ctx;
+
+    ctx = gnutls_malloc(sizeof(struct nettle_hash_ctx));
+    if (ctx == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_MEMORY_ERROR;
+    }
+
+    ctx->algo = algo;
+
+    switch (algo) {
+    case GNUTLS_DIG_MD5:
+               md5_init(&ctx->ctx.md5);
+               ctx->update = (update_func)md5_update;
+               ctx->digest = (digest_func)md5_digest;
+               ctx->ctx_ptr = &ctx->ctx.md5;
+               ctx->length = MD5_DIGEST_SIZE;
+               break;
+    case GNUTLS_DIG_SHA1:
+               sha1_init(&ctx->ctx.sha1);
+               ctx->update = (update_func)sha1_update;
+               ctx->digest = (digest_func)sha1_digest;
+               ctx->ctx_ptr = &ctx->ctx.sha1;
+               ctx->length = SHA1_DIGEST_SIZE;
+               break;
+    case GNUTLS_DIG_MD2:
+               md2_init(&ctx->ctx.md2);
+               ctx->update = (update_func)md2_update;
+               ctx->digest = (digest_func)md2_digest;
+               ctx->ctx_ptr = &ctx->ctx.md2;
+               ctx->length = MD2_DIGEST_SIZE;
+               break;
+    case GNUTLS_DIG_SHA256:
+               sha256_init(&ctx->ctx.sha256);
+               ctx->update = (update_func)sha256_update;
+               ctx->digest = (digest_func)sha256_digest;
+               ctx->ctx_ptr = &ctx->ctx.sha256;
+               ctx->length = SHA256_DIGEST_SIZE;
+               break;
+       /* FIXME: SHA512/384/224? */
+    default:
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+    }
+       
+       *_ctx = ctx;
+
+    return 0;
+}
+
+static int
+wrap_nettle_hash_output(void *src_ctx, void *digest, size_t digestsize)
+{
+    struct nettle_hash_ctx *ctx;
+    ctx = src_ctx;
+
+    if (digestsize < ctx->length) {
+               gnutls_assert();
+               return GNUTLS_E_SHORT_MEMORY_BUFFER;
+    }
+
+    ctx->digest(ctx->ctx_ptr, digestsize, digest);
+
+       return 0;
+}
+
+static int
+wrap_nettle_hmac_output(void *src_ctx, void *digest, size_t digestsize)
+{
+    struct nettle_hmac_ctx *ctx;
+    ctx = src_ctx;
+
+    if (digestsize < ctx->length) {
+               gnutls_assert();
+               return GNUTLS_E_SHORT_MEMORY_BUFFER;
+    }
+
+    ctx->digest(ctx->ctx_ptr, digestsize, digest);
+
+       return 0;
+}
+
+int crypto_mac_prio = INT_MAX;
+
+gnutls_crypto_mac_st _gnutls_mac_ops = {
+    .init = wrap_nettle_hmac_init,
+    .setkey = wrap_nettle_hmac_setkey,
+    .hash = wrap_nettle_hmac_update,
+    .copy = wrap_nettle_hmac_copy,
+    .output = wrap_nettle_hmac_output,
+    .deinit = wrap_nettle_md_close,
+};
+
+int crypto_digest_prio = INT_MAX;
+
+gnutls_crypto_digest_st _gnutls_digest_ops = {
+    .init = wrap_nettle_hash_init,
+    .hash = wrap_nettle_hash_update,
+    .copy = wrap_nettle_hash_copy,
+    .output = wrap_nettle_hash_output,
+    .deinit = wrap_nettle_md_close,
+};
diff --git a/lib/nettle/mpi.c b/lib/nettle/mpi.c
new file mode 100644
index 0000000..2bac5b7
--- /dev/null
+++ b/lib/nettle/mpi.c
@@ -0,0 +1,551 @@
+/*
+ * Copyright (C) 2010 Free
+ * Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Here lie everything that has to do with large numbers, gmp.
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_num.h>
+#include <gnutls_mpi.h>
+#include <gmp.h>
+#include <nettle/bignum.h>
+#include <random.h>
+
+static int
+wrap_nettle_mpi_print(const bigint_t a, void *buffer, size_t * nbytes,
+                   gnutls_bigint_format_t format)
+{
+       unsigned int size;
+       mpz_t *p = (void*)a;
+
+       if (format == GNUTLS_MPI_FORMAT_USG) {
+               size =  nettle_mpz_sizeinbase_256_u(*p);
+       } else {
+               size =  nettle_mpz_sizeinbase_256_s(*p);
+       }
+
+       if (buffer==NULL || size > *nbytes) {
+               *nbytes=size;
+               return GNUTLS_E_SHORT_MEMORY_BUFFER;
+       }
+       
+       nettle_mpz_get_str_256(size, buffer, *p);
+       *nbytes=size;
+
+       return 0;
+}
+
+static bigint_t wrap_nettle_mpi_new(int nbits)
+{
+       mpz_t *p;
+
+       p = gnutls_malloc(sizeof(*p));
+       if (p == NULL) {
+               gnutls_assert();
+               return NULL;
+       }
+       mpz_init2(*p, nbits);
+
+       return p;
+}
+
+static bigint_t
+wrap_nettle_mpi_scan(const void *buffer, size_t nbytes,
+                  gnutls_bigint_format_t format)
+{
+       bigint_t r = wrap_nettle_mpi_new(nbytes*8);
+       
+       if (r==NULL) {
+               gnutls_assert();
+               return r;
+       }
+
+       if (format == GNUTLS_MPI_FORMAT_USG) {
+               nettle_mpz_set_str_256_u(*((mpz_t*)r), nbytes, buffer);
+       } else {
+               nettle_mpz_set_str_256_s(*((mpz_t*)r), nbytes, buffer);
+       }
+       
+       return r;
+}
+
+static int wrap_nettle_mpi_cmp(const bigint_t u, const bigint_t v)
+{
+       mpz_t *i1 = u, *i2 = v;
+
+       return mpz_cmp(*i1, *i2);
+}
+
+static int wrap_nettle_mpi_cmp_ui(const bigint_t u, unsigned long v)
+{
+       mpz_t *i1 = u;
+
+       return mpz_cmp_ui(*i1, v);
+}
+
+static bigint_t wrap_nettle_mpi_set(bigint_t w, const bigint_t u)
+{
+       mpz_t *i1, *i2 = u;
+
+       if (w == NULL)
+               w = _gnutls_mpi_alloc_like(u);
+       i1 = w;
+
+       mpz_set(*i1, *i2);
+       
+       return i1;
+}
+
+static bigint_t wrap_nettle_mpi_set_ui(bigint_t w, unsigned long u)
+{
+       mpz_t *i1;
+
+       if (w == NULL)
+               w = wrap_nettle_mpi_new(32);
+
+       i1 = w;
+
+       mpz_set_ui(*i1, u);
+       
+       return i1;
+}
+
+static unsigned int wrap_nettle_mpi_get_nbits(bigint_t a)
+{
+       return mpz_sizeinbase(*((mpz_t *) a), 2);
+}
+
+static void wrap_nettle_mpi_release(bigint_t a)
+{
+       mpz_clear(*((mpz_t *) a));
+       gnutls_free(a);
+}
+
+static bigint_t wrap_nettle_mpi_mod(const bigint_t a, const bigint_t b)
+{
+       bigint_t r = wrap_nettle_mpi_new(wrap_nettle_mpi_get_nbits(b));
+
+       if (r == NULL)
+               return NULL;
+
+       mpz_mod(*((mpz_t *) r), *((mpz_t *) a), *((mpz_t *) b));
+
+       return r;
+}
+
+static bigint_t
+wrap_nettle_mpi_powm(bigint_t w, const bigint_t b, const bigint_t e,
+                  const bigint_t m)
+{
+       if (w == NULL)
+               w = wrap_nettle_mpi_new(wrap_nettle_mpi_get_nbits(m));
+
+       if (w == NULL)
+               return NULL;
+
+       mpz_powm(*((mpz_t *) w), *((mpz_t *) b), *((mpz_t *) e),
+                *((mpz_t *) m));
+
+       return w;
+}
+
+static bigint_t
+wrap_nettle_mpi_addm(bigint_t w, const bigint_t a, const bigint_t b,
+                  const bigint_t m)
+{
+       if (w == NULL)
+               w = wrap_nettle_mpi_new(wrap_nettle_mpi_get_nbits(a));
+
+       if (w == NULL)
+               return NULL;
+
+       mpz_add(*((mpz_t *) w), *((mpz_t *) b), *((mpz_t *) a));
+       mpz_fdiv_r(*((mpz_t *) w), *((mpz_t *) w), *((mpz_t *) m));
+
+       return w;
+}
+
+static bigint_t
+wrap_nettle_mpi_subm(bigint_t w, const bigint_t a, const bigint_t b,
+                  const bigint_t m)
+{
+       if (w == NULL)
+               w = wrap_nettle_mpi_new(wrap_nettle_mpi_get_nbits(a));
+
+       if (w == NULL)
+               return NULL;
+
+       mpz_sub(*((mpz_t *) w), *((mpz_t *) a), *((mpz_t *) b));
+       mpz_fdiv_r(*((mpz_t *) w), *((mpz_t *) w), *((mpz_t *) m));
+
+       return w;
+}
+
+static bigint_t
+wrap_nettle_mpi_mulm(bigint_t w, const bigint_t a, const bigint_t b,
+                  const bigint_t m)
+{
+       if (w == NULL)
+               w = wrap_nettle_mpi_new(wrap_nettle_mpi_get_nbits(m));
+
+       if (w == NULL)
+               return NULL;
+
+       mpz_mul(*((mpz_t *) w), *((mpz_t *) a), *((mpz_t *) b));
+       mpz_fdiv_r(*((mpz_t *) w), *((mpz_t *) w), *((mpz_t *) m));
+
+       return w;
+}
+
+static bigint_t
+wrap_nettle_mpi_add(bigint_t w, const bigint_t a, const bigint_t b)
+{
+       if (w == NULL)
+               w = wrap_nettle_mpi_new(wrap_nettle_mpi_get_nbits(b));
+
+       if (w == NULL)
+               return NULL;
+
+       mpz_add(*((mpz_t *) w), *((mpz_t *) a), *((mpz_t *) b));
+
+       return w;
+}
+
+static bigint_t
+wrap_nettle_mpi_sub(bigint_t w, const bigint_t a, const bigint_t b)
+{
+       if (w == NULL)
+               w = wrap_nettle_mpi_new(wrap_nettle_mpi_get_nbits(a));
+
+       if (w == NULL)
+               return NULL;
+
+       mpz_sub(*((mpz_t *) w), *((mpz_t *) a), *((mpz_t *) b));
+
+       return w;
+}
+
+static bigint_t
+wrap_nettle_mpi_mul(bigint_t w, const bigint_t a, const bigint_t b)
+{
+       if (w == NULL)
+               w = wrap_nettle_mpi_new(wrap_nettle_mpi_get_nbits(a));
+
+       if (w == NULL)
+               return NULL;
+
+       mpz_mul(*((mpz_t *) w), *((mpz_t *) a), *((mpz_t *) b));
+
+       return w;
+}
+
+/* q = a / b */
+static bigint_t
+wrap_nettle_mpi_div(bigint_t q, const bigint_t a, const bigint_t b)
+{
+       if (q == NULL)
+               q = wrap_nettle_mpi_new(wrap_nettle_mpi_get_nbits(a));
+
+       if (q == NULL)
+               return NULL;
+
+       mpz_cdiv_q(*((mpz_t *) q), *((mpz_t *) a), *((mpz_t *) b));
+
+       return q;
+}
+
+static bigint_t
+wrap_nettle_mpi_add_ui(bigint_t w, const bigint_t a, unsigned long b)
+{
+       if (w == NULL)
+               w = wrap_nettle_mpi_new(wrap_nettle_mpi_get_nbits(a));
+
+       if (w == NULL)
+               return NULL;
+
+       mpz_add_ui(*((mpz_t *) w), *((mpz_t *) a), b);
+
+       return w;
+}
+
+static bigint_t
+wrap_nettle_mpi_sub_ui(bigint_t w, const bigint_t a, unsigned long b)
+{
+       if (w == NULL)
+               w = wrap_nettle_mpi_new(wrap_nettle_mpi_get_nbits(a));
+
+       if (w == NULL)
+               return NULL;
+
+       mpz_sub_ui(*((mpz_t *) w), *((mpz_t *) a), b);
+
+       return w;
+
+}
+
+static bigint_t
+wrap_nettle_mpi_mul_ui(bigint_t w, const bigint_t a, unsigned long b)
+{
+       if (w == NULL)
+               w = wrap_nettle_mpi_new(wrap_nettle_mpi_get_nbits(a));
+
+       if (w == NULL)
+               return NULL;
+
+       mpz_mul_ui(*((mpz_t *) w), *((mpz_t *) a), b);
+
+       return w;
+
+}
+
+#define PRIME_CHECK_PARAM 18
+static int wrap_nettle_prime_check(bigint_t pp)
+{
+       int ret;
+       ret = mpz_probab_prime_p(*((mpz_t *) pp), PRIME_CHECK_PARAM);
+
+       if (ret > 0) {
+               return 0;
+       }
+
+       return GNUTLS_E_INTERNAL_ERROR; /* ignored */
+}
+
+
+/* generate a prime of the form p=2qw+1
+ * The algorithm is simple but probably it has to be modified to gcrypt's
+ * since it is really really slow. Nature did not want 2qw+1 to be prime.
+ */
+inline static int gen_group (mpz_t *prime, mpz_t* generator, unsigned int 
nbits)
+{
+       mpz_t q, w;
+       unsigned int p_bytes = nbits/8;
+       opaque *buffer= NULL;
+       unsigned int q_bytes, w_bytes, r_bytes, w_bits;
+       int ret;
+
+       mpz_init(*prime);
+       mpz_init(*generator);
+
+       /* security level enforcement. "Check Fine-tuned implementation of an
+        * efficient secure profile matching protocol", p.61, El-gamal key 
generation.
+        */
+       if (nbits <= 1024) {
+               q_bytes = 160/8;
+       } else if (nbits <=2644) {
+               q_bytes = 256/8;
+       } else if (nbits <= 6897) {
+               q_bytes = 384/8;
+       } else {
+               q_bytes = 512/8;
+       }
+       
+       if (nbits%8 != 0)
+               p_bytes++;
+       
+       _gnutls_debug_log("Generating group of prime of %u bits and format of 
2wq+1. q_size=%u bits\n", nbits, q_bytes*8);
+       buffer = gnutls_malloc(p_bytes); /* p_bytes > q_bytes */
+       if (buffer == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_MEMORY_ERROR;
+       }
+
+       mpz_init2(*prime, nbits);
+       mpz_init(*generator);
+       mpz_init(q);
+       mpz_init(w);
+
+       /* search for a prime. We are not that unlucky so search
+        * forever.
+        */
+       for (;;) {
+               ret = _gnutls_rnd(GNUTLS_RND_RANDOM, buffer, q_bytes);
+               if (ret < 0) {
+                       gnutls_assert();
+                       goto fail;
+               }
+               
+               nettle_mpz_set_str_256_u(q, q_bytes, buffer);
+               /* always odd */
+               mpz_setbit(q, 0);
+               
+               ret = mpz_probab_prime_p(q, PRIME_CHECK_PARAM);
+               if (ret > 0) {
+                       break;
+               }
+       }
+       
+       /* now generate w of size p_bytes - q_bytes */
+
+       w_bits = nbits - wrap_nettle_mpi_get_nbits(&q);
+
+       _gnutls_debug_log("Found prime q of %u bits. Will look for w of %u 
bits...\n", wrap_nettle_mpi_get_nbits(&q), w_bits);
+
+       w_bytes = w_bits/8;
+       if (w_bits % 8 != 0)
+               w_bytes++;
+
+       for (;;) {
+               ret = _gnutls_rnd(GNUTLS_RND_RANDOM, buffer, w_bytes);
+               if (ret < 0) {
+                       gnutls_assert();
+                       return ret;
+               }
+               
+               nettle_mpz_set_str_256_u(w, w_bytes, buffer);
+               /* always odd */
+               mpz_setbit(w, 0);
+               
+               ret = mpz_probab_prime_p(w, PRIME_CHECK_PARAM);
+               if (ret == 0) {
+                       continue;
+               }
+               
+               /* check if 2wq+1 is prime */
+               mpz_mul_ui(*prime, w, 2);
+               mpz_mul(*prime, *prime, q);
+               mpz_add_ui(*prime, *prime, 1);
+
+               ret = mpz_probab_prime_p(*prime, PRIME_CHECK_PARAM);
+               if (ret > 0) {
+                       break;
+               }
+       }
+       
+       _gnutls_debug_log("Found prime w of %u bits. Looking for 
generator...\n", wrap_nettle_mpi_get_nbits(&w));
+
+       /* finally a prime! Let calculate generator
+        */
+       
+       /* c = r^((p-1)/q), r == random
+        * c = r^(2w)
+        * if c!=1 c is the generator for the group of the prime
+        * 
+        * (here we reuse q as r)
+        */
+       r_bytes = p_bytes;
+
+       mpz_mul_ui(w, w, 2); /* w = w*2 */
+       mpz_fdiv_r(w, w, *prime);
+
+       for (;;) {
+               ret = _gnutls_rnd(GNUTLS_RND_RANDOM, buffer, r_bytes);
+               if (ret < 0) {
+                       gnutls_assert();
+                       return ret;
+               }
+               
+               nettle_mpz_set_str_256_u(q, r_bytes, buffer);
+               mpz_fdiv_r(q, q, *prime);
+
+               /* check if r^w mod n != 1 mod n */
+               mpz_powm(*generator, q, w, *prime);
+               
+               if (mpz_cmp_ui(*generator,1)==0)
+                       continue;
+               else break;
+       }
+       
+       _gnutls_debug_log("Found generator g of %u bits\n", 
wrap_nettle_mpi_get_nbits(generator));
+       _gnutls_debug_log("Prime n is of %u bits\n", 
wrap_nettle_mpi_get_nbits(prime));
+
+       mpz_clear(q);
+       mpz_clear(w);
+       gnutls_free(buffer);
+       
+       return 0;
+
+fail:
+       mpz_clear(q);
+       mpz_clear(w);
+       mpz_clear(*prime);
+       mpz_clear(*generator);
+       gnutls_free(buffer);
+       
+       return ret;
+}
+
+static int
+wrap_nettle_generate_group(gnutls_group_st * group, unsigned int bits)
+{
+int ret;
+bigint_t p = wrap_nettle_mpi_new(bits);
+bigint_t g;
+
+       if (p == NULL) {
+               gnutls_assert();
+               return GNUTLS_E_MEMORY_ERROR;
+       }
+
+       g = wrap_nettle_mpi_new(bits);
+       if (g == NULL) {
+               gnutls_assert();
+               _gnutls_mpi_release(&p);
+               return GNUTLS_E_MEMORY_ERROR;
+       }
+       
+       ret = gen_group(p, g, bits);
+       if (ret < 0) {
+               _gnutls_mpi_release(&g);
+               _gnutls_mpi_release(&p);
+               gnutls_assert();
+               return ret;
+       }
+       
+       group->p = p;
+       group->g = g;
+       
+       return 0;
+}
+
+
+int crypto_bigint_prio = INT_MAX;
+
+gnutls_crypto_bigint_st _gnutls_mpi_ops = {
+       .bigint_new = wrap_nettle_mpi_new,
+       .bigint_cmp = wrap_nettle_mpi_cmp,
+       .bigint_cmp_ui = wrap_nettle_mpi_cmp_ui,
+       .bigint_mod = wrap_nettle_mpi_mod,
+       .bigint_set = wrap_nettle_mpi_set,
+       .bigint_set_ui = wrap_nettle_mpi_set_ui,
+       .bigint_get_nbits = wrap_nettle_mpi_get_nbits,
+       .bigint_powm = wrap_nettle_mpi_powm,
+       .bigint_addm = wrap_nettle_mpi_addm,
+       .bigint_subm = wrap_nettle_mpi_subm,
+       .bigint_add = wrap_nettle_mpi_add,
+       .bigint_sub = wrap_nettle_mpi_sub,
+       .bigint_add_ui = wrap_nettle_mpi_add_ui,
+       .bigint_sub_ui = wrap_nettle_mpi_sub_ui,
+       .bigint_mul = wrap_nettle_mpi_mul,
+       .bigint_mulm = wrap_nettle_mpi_mulm,
+       .bigint_mul_ui = wrap_nettle_mpi_mul_ui,
+       .bigint_div = wrap_nettle_mpi_div,
+       .bigint_prime_check = wrap_nettle_prime_check,
+       .bigint_release = wrap_nettle_mpi_release,
+       .bigint_print = wrap_nettle_mpi_print,
+       .bigint_scan = wrap_nettle_mpi_scan,
+       .bigint_generate_group = wrap_nettle_generate_group
+};
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
new file mode 100644
index 0000000..081c08c
--- /dev/null
+++ b/lib/nettle/pk.c
@@ -0,0 +1,469 @@
+/*
+ * Copyright (C) 2010
+ * Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* This file contains the functions needed for RSA/DSA public key
+ * encryption and signatures. 
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_mpi.h>
+#include <gnutls_pk.h>
+#include <gnutls_errors.h>
+#include <gnutls_datum.h>
+#include <gnutls_global.h>
+#include <gnutls_num.h>
+#include <x509/x509_int.h>
+#include <x509/common.h>
+#include <random.h>
+#include <gnutls_pk.h>
+#include <nettle/dsa.h>
+#include <nettle/rsa.h>
+#include <random.h>
+#include <gnutls/crypto.h>
+
+#define TOMPZ(x) (*((mpz_t*)(x)))
+
+static void rnd_func(void *_ctx, unsigned length, uint8_t * data)
+{
+       _gnutls_rnd(GNUTLS_RND_RANDOM, data, length);
+}
+
+static void _dsa_params_to_pubkey(const gnutls_pk_params_st * pk_params, 
struct dsa_public_key *pub)
+{
+       memcpy(&pub->p, pk_params->params[0], sizeof(mpz_t));
+       memcpy(&pub->q, pk_params->params[1], sizeof(mpz_t));
+       memcpy(&pub->g, pk_params->params[2], sizeof(mpz_t));
+       memcpy(&pub->y, pk_params->params[3], sizeof(mpz_t));
+}
+
+static void _dsa_params_to_privkey(const gnutls_pk_params_st * pk_params, 
struct  dsa_private_key *pub)
+{
+       memcpy(&pub->x, pk_params->params[4], sizeof(mpz_t));
+}
+
+static void _rsa_params_to_privkey(const gnutls_pk_params_st * pk_params, 
struct rsa_private_key *priv)
+{
+mpz_t q_1;
+
+       memcpy(&priv->d, pk_params->params[2], sizeof(mpz_t));
+       memcpy(&priv->p, pk_params->params[3], sizeof(mpz_t));
+       memcpy(&priv->q, pk_params->params[4], sizeof(mpz_t));
+       memcpy(&priv->c, pk_params->params[5], sizeof(mpz_t));
+
+       /* FIXME: possibly move it to fixup to avoid those calculations here */ 
+       
+       /* b = d % q-1 */
+       mpz_init(q_1);
+       mpz_sub_ui(q_1, priv->q, 1);
+       
+       mpz_fdiv_r(priv->b, priv->d, q_1);
+
+       /* a = d % p-1 */
+       mpz_sub_ui(q_1, priv->p, 1);
+       mpz_fdiv_r(priv->a, priv->d, q_1);
+}
+
+static int
+_wrap_nettle_pk_encrypt(gnutls_pk_algorithm_t algo,
+                       gnutls_datum_t * ciphertext,
+                       const gnutls_datum_t * plaintext,
+                       const gnutls_pk_params_st * pk_params)
+{
+       int ret;
+
+       /* make a sexp from pkey */
+       switch (algo) {
+       case GNUTLS_PK_RSA: {
+               bigint_t p;
+               
+               if (_gnutls_mpi_scan_nz(&p, plaintext->data, plaintext->size) 
!= 0) {
+                       gnutls_assert();
+                       return GNUTLS_E_MPI_SCAN_FAILED;
+               }
+
+               mpz_powm(p, p, TOMPZ(pk_params->params[1]), 
TOMPZ(pk_params->params[0]));
+
+               ret = _gnutls_mpi_dprint(p, ciphertext);
+               _gnutls_mpi_release(&p);
+
+               if (ret < 0) {
+                       gnutls_assert();
+                       goto cleanup;
+               }
+
+               break;
+       }
+       default:
+               gnutls_assert();
+               ret = GNUTLS_E_INTERNAL_ERROR;
+               goto cleanup;
+       }
+
+       ret = 0;
+
+cleanup:
+
+       return ret;
+}
+
+static int
+_wrap_nettle_pk_decrypt(gnutls_pk_algorithm_t algo,
+                       gnutls_datum_t * plaintext,
+                       const gnutls_datum_t * ciphertext,
+                       const gnutls_pk_params_st * pk_params)
+{
+       int ret;
+
+       /* make a sexp from pkey */
+       switch (algo) {
+       case GNUTLS_PK_RSA: {
+               struct rsa_private_key priv;
+               bigint_t c;
+               
+               if (_gnutls_mpi_scan_nz(&c, ciphertext->data, ciphertext->size) 
!= 0) {
+                       gnutls_assert();
+                       return GNUTLS_E_MPI_SCAN_FAILED;
+               }
+
+               /* FIXME: implement blinding */
+
+               rsa_private_key_init(&priv);
+               _rsa_params_to_privkey(pk_params, &priv);
+
+               rsa_compute_root(&priv, TOMPZ(c), TOMPZ(c));
+
+               ret = _gnutls_mpi_dprint(c, plaintext);
+               _gnutls_mpi_release(&c);
+               mpz_clear(priv.a);
+               mpz_clear(priv.b);
+
+               if (ret < 0) {
+                       gnutls_assert();
+                       goto cleanup;
+               }
+
+               break;
+       }
+       default:
+               gnutls_assert();
+               ret = GNUTLS_E_INTERNAL_ERROR;
+               goto cleanup;
+       }
+
+       ret = 0;
+
+cleanup:
+
+       return ret;
+}
+
+/* in case of DSA puts into data, r,s
+ */
+static int
+_wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+                    gnutls_datum_t * signature,
+                    const gnutls_datum_t * vdata,
+                    const gnutls_pk_params_st * pk_params)
+{
+       int ret;
+
+       switch (algo) {
+
+       case GNUTLS_PK_DSA: {
+               struct dsa_public_key pub;
+               struct dsa_private_key priv;
+               struct dsa_signature sig;
+                               
+               dsa_public_key_init(&pub);
+               dsa_private_key_init(&priv);
+               _dsa_params_to_pubkey(pk_params, &pub);
+               _dsa_params_to_privkey(pk_params, &priv);
+
+               dsa_signature_init(&sig);
+
+               dsa_sign_digest(&pub, &priv, NULL, rnd_func, vdata->data, &sig);
+
+               ret =
+                       _gnutls_encode_ber_rs(signature, &sig.r,
+                                         &sig.s);
+                                         
+               dsa_signature_clear(&sig);
+
+               if (ret < 0) {
+                       gnutls_assert();
+                       goto cleanup;
+               }
+               break;
+       }
+       case GNUTLS_PK_RSA: {
+               struct rsa_private_key priv;
+               bigint_t hash;
+               
+               if (_gnutls_mpi_scan_nz(&hash, vdata->data, vdata->size) != 0) {
+                       gnutls_assert();
+                       return GNUTLS_E_MPI_SCAN_FAILED;
+               }
+
+               rsa_private_key_init(&priv);
+               _rsa_params_to_privkey(pk_params, &priv);
+
+               rsa_compute_root(&priv, TOMPZ(hash), TOMPZ(hash));
+
+               ret = _gnutls_mpi_dprint(hash, signature);
+               _gnutls_mpi_release(&hash);
+               mpz_clear(priv.a);
+               mpz_clear(priv.b);
+
+               if (ret < 0) {
+                       gnutls_assert();
+                       goto cleanup;
+               }
+
+               break;
+       }
+       default:
+               gnutls_assert();
+               ret = GNUTLS_E_INTERNAL_ERROR;
+               goto cleanup;
+       }
+
+       ret = 0;
+
+cleanup:
+
+       return ret;
+}
+
+static int
+_int_rsa_verify(const gnutls_pk_params_st * pk_params,
+            bigint_t m,
+            bigint_t s)
+{
+  int res;
+
+  mpz_t m1;
+
+  if ( (mpz_sgn(TOMPZ(s)) <= 0)
+       || (mpz_cmp(TOMPZ(s), TOMPZ(pk_params->params[0])) >= 0) )
+    return GNUTLS_E_PK_SIG_VERIFY_FAILED;
+
+  mpz_init(m1);
+
+  mpz_powm(m1, TOMPZ(s), TOMPZ(pk_params->params[1]), 
TOMPZ(pk_params->params[0]));
+
+  res = !mpz_cmp(TOMPZ(m), m1);
+
+  mpz_clear(m1);
+
+  if (res == 0)
+       res = GNUTLS_E_PK_SIG_VERIFY_FAILED;
+  else res = 0;
+  
+  return res;
+}
+
+static int
+_wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo,
+                      const gnutls_datum_t * vdata,
+                      const gnutls_datum_t * signature,
+                      const gnutls_pk_params_st * pk_params)
+{
+       int ret;
+       bigint_t tmp[2] = { NULL, NULL };
+
+       switch (algo) {
+       case GNUTLS_PK_DSA: {
+               struct dsa_public_key pub;
+               struct dsa_signature sig;
+                               
+               ret = _gnutls_decode_ber_rs(signature, &tmp[0], &tmp[1]);
+               if (ret < 0) {
+                       gnutls_assert();
+                       goto cleanup;
+               }
+               dsa_public_key_init(&pub);
+               _dsa_params_to_pubkey(pk_params, &pub);
+               memcpy(&sig.r, tmp[0], sizeof(sig.r));
+               memcpy(&sig.s, tmp[1], sizeof(sig.s));
+
+               ret = dsa_verify_digest(&pub, vdata->data, &sig);
+               if (ret == 0)
+                       ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
+               else
+                       ret = 0;
+
+               _gnutls_mpi_release(&tmp[0]);
+               _gnutls_mpi_release(&tmp[1]);
+               break;
+       }
+       case GNUTLS_PK_RSA: {
+               bigint_t hash;
+               
+               if (_gnutls_mpi_scan_nz(&hash, vdata->data, vdata->size) != 0) {
+                       gnutls_assert();
+                       return GNUTLS_E_MPI_SCAN_FAILED;
+               }
+
+               ret =
+                   _gnutls_mpi_scan_nz(&tmp[0], signature->data,
+                                       signature->size);
+               if (ret < 0) {
+                       gnutls_assert();
+                       goto cleanup;
+               }
+
+               ret = _int_rsa_verify(pk_params, hash, tmp[0]);
+               _gnutls_mpi_release(&tmp[0]);
+               _gnutls_mpi_release(&hash);
+               break;
+       }
+       default:
+               gnutls_assert();
+               ret = GNUTLS_E_INTERNAL_ERROR;
+               goto cleanup;
+       }
+
+cleanup:
+
+       return ret;
+}
+
+static int
+wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo,
+                              unsigned int level /*bits */ ,
+                              gnutls_pk_params_st * params)
+{
+int ret, i;
+
+       switch (algo) {
+
+       case GNUTLS_PK_DSA: {
+               struct dsa_public_key pub;
+               struct dsa_private_key priv;
+       
+               dsa_public_key_init(&pub);
+               dsa_private_key_init(&priv);
+
+               ret = dsa_generate_keypair (&pub, &priv, NULL, rnd_func, NULL, 
NULL, level);
+               if (ret != 1) {
+                       gnutls_assert();
+                       return GNUTLS_E_INTERNAL_ERROR;
+               }
+               
+               params->params_nr = 0;
+               for (i=0;i<DSA_PRIVATE_PARAMS;i++) {
+                       params->params[i] = _gnutls_mpi_alloc_like(&pub.p);
+                       if (params->params[i] == NULL) {
+                               ret = GNUTLS_E_MEMORY_ERROR;
+                               dsa_private_key_clear(&priv);
+                               dsa_public_key_clear(&pub);
+                               goto fail;
+                       }
+                       params->params_nr++;
+               }
+               _gnutls_mpi_set(params->params[0], pub.p);
+               _gnutls_mpi_set(params->params[1], pub.q);
+               _gnutls_mpi_set(params->params[2], pub.g);
+               _gnutls_mpi_set(params->params[3], pub.y);
+               _gnutls_mpi_set(params->params[4], priv.x);
+
+               dsa_private_key_clear(&priv);
+               dsa_public_key_clear(&pub);
+  
+               break;
+       }
+       case GNUTLS_PK_RSA: {
+               struct rsa_public_key pub;
+               struct rsa_private_key priv;
+       
+               rsa_public_key_init(&pub);
+               rsa_private_key_init(&priv);
+
+               ret = rsa_generate_keypair (&pub, &priv, NULL, rnd_func, NULL, 
NULL, level, 64);
+               if (ret != 1) {
+                       gnutls_assert();
+                       return GNUTLS_E_INTERNAL_ERROR;
+               }
+               
+               params->params_nr = 0;
+               for (i=0;i<RSA_PRIVATE_PARAMS;i++) {
+                       params->params[i] = _gnutls_mpi_alloc_like(&pub.n);
+                       if (params->params[i] == NULL) {
+                               ret = GNUTLS_E_MEMORY_ERROR;
+                               rsa_private_key_clear(&priv);
+                               rsa_public_key_clear(&pub);
+                               goto fail;
+                       }
+                       params->params_nr++;
+                       
+               }
+               _gnutls_mpi_set(params->params[0], pub.n);
+               _gnutls_mpi_set(params->params[1], pub.e);
+               _gnutls_mpi_set(params->params[2], priv.d);
+               _gnutls_mpi_set(params->params[3], priv.p);
+               _gnutls_mpi_set(params->params[4], priv.q);
+               _gnutls_mpi_set(params->params[5], priv.c);
+
+               rsa_private_key_clear(&priv);
+               rsa_public_key_clear(&pub);
+               
+               break;
+       }
+       default:
+               gnutls_assert();
+               return GNUTLS_E_INVALID_REQUEST;
+       }
+       
+       return 0;
+
+fail:
+
+       for (i=0;i<params->params_nr;i++) {
+               _gnutls_mpi_release(&params->params[i]);
+       }
+       params->params_nr=0;
+       
+       return ret;
+}
+
+
+static int
+wrap_nettle_pk_fixup(gnutls_pk_algorithm_t algo,
+                    gnutls_direction_t direction,
+                    gnutls_pk_params_st * params)
+{
+       return 0;
+}
+
+int crypto_pk_prio = INT_MAX;
+
+gnutls_crypto_pk_st _gnutls_pk_ops = {
+       .encrypt = _wrap_nettle_pk_encrypt,
+       .decrypt = _wrap_nettle_pk_decrypt,
+       .sign = _wrap_nettle_pk_sign,
+       .verify = _wrap_nettle_pk_verify,
+       .generate = wrap_nettle_pk_generate_params,
+       .pk_fixup_private_params = wrap_nettle_pk_fixup,
+};
diff --git a/lib/nettle/rnd.c b/lib/nettle/rnd.c
new file mode 100644
index 0000000..0a1066f
--- /dev/null
+++ b/lib/nettle/rnd.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2008, 2010 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Here is the libgcrypt random generator layer.
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_num.h>
+#include <nettle/yarrow.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+
+#include <pthread.h>
+
+#define SOURCES 2
+
+static pthread_mutex_t rnd_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+#define RND_LOCK_INIT
+#define RND_LOCK if (pthread_mutex_lock(&rnd_mutex)!=0) abort()
+#define RND_UNLOCK if (pthread_mutex_unlock(&rnd_mutex)!=0) abort()
+
+enum {
+       RANDOM_SOURCE_TRIVIA=0,
+       RANDOM_SOURCE_DEVICE,
+};
+
+static struct yarrow256_ctx yctx;
+static struct yarrow_source ysources[SOURCES];
+static time_t device_last_read = 0;
+static int device_fd;
+
+static time_t trivia_previous_time = 0;
+static time_t trivia_time_count = 0;
+
+static int do_trivia_source(int init)
+{
+    struct {
+               struct timeval now;
+#ifdef HAVE_GETRUSAGE
+               struct rusage rusage;
+#endif
+               unsigned count;
+               pid_t pid;
+    } event;
+
+    unsigned entropy = 0;
+
+    if (gettimeofday(&event.now, NULL) < 0) {
+               _gnutls_debug_log("gettimeofday failed: %s\n", strerror(errno));
+               abort();
+       }
+#ifdef HAVE_GETRUSAGE
+    if (getrusage(RUSAGE_SELF, &event.rusage) < 0) {
+               _gnutls_debug_log("getrusage failed: %s\n", strerror(errno));
+               abort();
+       }
+#endif
+
+    event.count = 0;
+    if (init) {
+               trivia_time_count = 0;
+    } else {
+               event.count = trivia_time_count++;
+
+               if (event.now.tv_sec != trivia_previous_time) {
+                       /* Count one bit of entropy if we either have more than 
two
+                        * invocations in one second, or more than two seconds
+                        * between invocations. */
+                       if ((trivia_time_count > 2)
+                       || ((event.now.tv_sec - trivia_previous_time) > 2))
+                               entropy++;
+
+                       trivia_time_count = 0;
+               }
+    }
+    trivia_previous_time = event.now.tv_sec;
+    event.pid = getpid();
+
+    return yarrow256_update(&yctx, RANDOM_SOURCE_TRIVIA, entropy,
+                           sizeof(event), (const uint8_t *) &event);
+}
+
+#define DEVICE_READ_SIZE 16
+#define DEVICE_READ_SIZE_MAX 32
+#define DEVICE_READ_INTERVAL 360
+static int do_device_source(int init)
+{
+    time_t now = time(NULL);
+       int read_size = DEVICE_READ_SIZE;
+
+    if (init) {
+               int old;
+               
+               device_fd = open("/dev/urandom", O_RDONLY);
+               if (device_fd < 0) {
+                       _gnutls_debug_log("Cannot open urandom!\n");
+                       abort();
+               }
+
+               old = fcntl(device_fd, F_GETFD);
+               fcntl(device_fd, F_SETFD, old | 1);
+               device_last_read = now;
+               
+               read_size = DEVICE_READ_SIZE_MAX; /* initially read more data */
+    }
+
+    if ((device_fd > 0)
+               && (init || ((now - device_last_read) > DEVICE_READ_INTERVAL))) 
{
+
+               /* More than a minute since we last read the device */
+               uint8_t buf[DEVICE_READ_SIZE_MAX];
+               uint32_t done;
+
+               for (done = 0; done < read_size;) {
+                       int res;
+                       do
+                       res =
+                               read(device_fd, buf + done, sizeof(buf) - done);
+                       while (res < 0 && errno == EINTR);
+
+                       if (res <= 0) {
+                               if (res < 0) {
+                                       _gnutls_debug_log("Failed to read 
/dev/urandom: %s\n",
+                                                         strerror(errno));
+                               } else {
+                                       _gnutls_debug_log
+                                       ("Failed to read /dev/urandom: end of 
file\n");
+                               }
+
+                               return 0;
+                       }
+
+                       done += res;
+               }
+
+               device_last_read = now;
+               return yarrow256_update(&yctx, RANDOM_SOURCE_DEVICE, 
read_size*8/3 /* be more conservative */,
+                                       read_size, buf);
+    }
+    return 0;
+}
+
+static void wrap_nettle_rnd_deinit(void* ctx)
+{
+       RND_LOCK;
+       close(device_fd);
+       RND_UNLOCK;
+}
+
+static int wrap_nettle_rnd_init(void **ctx)
+{
+       RND_LOCK_INIT;
+       
+    yarrow256_init(&yctx, SOURCES, ysources);
+       do_device_source(1);
+       do_trivia_source(1);
+
+       yarrow256_slow_reseed(&yctx);
+
+    return 0;
+}
+
+
+
+static int
+wrap_nettle_rnd(void *_ctx, int level, void *data, size_t datasize)
+{
+       RND_LOCK;
+       do_trivia_source( 0);
+       do_device_source( 0);
+
+    yarrow256_random(&yctx, datasize, data);
+       RND_UNLOCK;
+       return 0;
+}
+
+int crypto_rnd_prio = INT_MAX;
+
+gnutls_crypto_rnd_st _gnutls_rnd_ops = {
+    .init = wrap_nettle_rnd_init,
+    .deinit = wrap_nettle_rnd_deinit,
+    .rnd = wrap_nettle_rnd,
+};
diff --git a/src/certtool.c b/src/certtool.c
index 2b6a729..dca3e3f 100644
--- a/src/certtool.c
+++ b/src/certtool.c
@@ -172,9 +172,6 @@ generate_private_key_int (void)
   if (info.dsa)
     {
       key_type = GNUTLS_PK_DSA;
-      /* FIXME: Remove me once we depend on 1.3.x */
-      if (info.bits > 1024 && gcry_check_version ("1.3.1") == NULL)
-       info.bits = 1024;
     }
   else
     key_type = GNUTLS_PK_RSA;
@@ -921,19 +918,6 @@ gaa_parser (int argc, char **argv)
       template_parse (info.template);
     }
 
-#ifdef gcry_fips_mode_active
-  /* Libgcrypt manual says that gcry_version_check must be called
-     before calling gcry_fips_mode_active. */
-  gcry_check_version (NULL);
-  if (gcry_fips_mode_active ())
-    {
-      ret = gnutls_register_md5_handler ();
-      if (ret)
-       fprintf (stderr, "gnutls_register_md5_handler: %s\n",
-                gnutls_strerror (ret));
-    }
-#endif
-
   gnutls_global_set_log_function (tls_log_func);
   gnutls_global_set_log_level (info.debug);
   if (info.debug > 1)
@@ -964,9 +948,6 @@ gaa_parser (int argc, char **argv)
   if ((ret = gnutls_global_init_extra ()) < 0)
     error (EXIT_FAILURE, 0, "global_init_extra: %s", gnutls_strerror (ret));
 
-  if (info.quick_random != 0)
-    gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
-
   switch (info.action)
     {
     case ACTION_SELF_SIGNED:
diff --git a/src/cli.c b/src/cli.c
index 2d76ec8..4185b33 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -38,7 +38,6 @@
 #include <gnutls/x509.h>
 #include <gnutls/openpgp.h>
 #include <gnutls/pkcs11.h>
-#include <gcrypt.h>
 
 /* Gnulib portability files. */
 #include <progname.h>
@@ -700,21 +699,6 @@ main (int argc, char **argv)
 
   set_program_name (argv[0]);
 
-  gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
-
-#ifdef gcry_fips_mode_active
-  /* Libgcrypt manual says that gcry_version_check must be called
-     before calling gcry_fips_mode_active. */
-  gcry_check_version (NULL);
-  if (gcry_fips_mode_active ())
-    {
-      ret = gnutls_register_md5_handler ();
-      if (ret)
-       fprintf (stderr, "gnutls_register_md5_handler: %s\n",
-                gnutls_strerror (ret));
-    }
-#endif
-
   if ((ret = gnutls_global_init ()) < 0)
     {
       fprintf (stderr, "global_init: %s\n", gnutls_strerror (ret));
@@ -958,9 +942,6 @@ after_handshake:
        }
     }
 
-  if (info.debug)
-    gcry_control (GCRYCTL_DUMP_RANDOM_STATS);
-
   if (user_term != 0)
     socket_bye (&hd);
   else
diff --git a/src/serv.c b/src/serv.c
index e2cf665..06c4cc1 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -34,7 +34,6 @@
 #include <sys/types.h>
 #include <string.h>
 #include <gnutls/gnutls.h>
-#include <gcrypt.h>
 #include <gnutls/extra.h>
 #include <gnutls/openpgp.h>
 #include <sys/time.h>
@@ -865,19 +864,6 @@ main (int argc, char **argv)
 
   set_program_name (argv[0]);
 
-#ifdef gcry_fips_mode_active
-  /* Libgcrypt manual says that gcry_version_check must be called
-     before calling gcry_fips_mode_active. */
-  gcry_check_version (NULL);
-  if (gcry_fips_mode_active ())
-    {
-      ret = gnutls_register_md5_handler ();
-      if (ret)
-       fprintf (stderr, "gnutls_register_md5_handler: %s\n",
-                gnutls_strerror (ret));
-    }
-#endif
-
 #ifndef _WIN32
   signal (SIGPIPE, SIG_IGN);
   signal (SIGHUP, SIG_IGN);
@@ -902,8 +888,6 @@ main (int argc, char **argv)
       strcpy (name, "Echo Server");
     }
 
-  gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
-
   if ((ret = gnutls_global_init ()) < 0)
     {
       fprintf (stderr, "global_init: %s\n", gnutls_strerror (ret));
diff --git a/tests/chainverify.c b/tests/chainverify.c
index 6a31220..bdacc9b 100644
--- a/tests/chainverify.c
+++ b/tests/chainverify.c
@@ -848,7 +848,7 @@ doit (void)
 
       if (verify_status != chains[i].expected_verify_result)
        {
-         fail ("verify_status: %d expected: %d",
+         fail ("verify_status: %d expected: %d\n",
                verify_status, chains[i].expected_verify_result);
 
          if (debug)


hooks/post-receive
-- 
GNU gnutls



reply via email to

[Prev in Thread] Current Thread [Next in Thread]