Author: bh
Date: 2007-07-17 15:53:45 +0200 (Tue, 17 Jul 2007)
New Revision: 267

Modified:
   trunk/openvas-libnasl/ChangeLog
   trunk/openvas-libnasl/nasl/nasl_crypto2.c
Log:

* nasl/nasl_crypto2.c: Use GnuTLS/libgcrypt instead of OpenSSL.
Note the incompatible changes in rsa_sign and
verify_script_signature.
(print_tls_error, print_gcrypt_error): New.  Helper functions to
print error messages.
(mpi_from_string, mpi_from_named_parameter, set_mpi_retc): New.
Helper functions to handle MPIs
(extract_mpi_from_sexp, set_retc_from_sexp): New. Helper functions
to handle gcrypt s-expressions.
(nasl_load_privkey_param, nasl_sexp_from_privkey): New. Helper
functions to handle private keys.
(calc_dh_public, calc_dh_key): New.  Helper functions for
diffie-hellman
(hexdecode): New.  Helper function to decode a hex string.
(nasl_bn_cmp, nasl_bn_random, nasl_pem_to)
(nasl_dh_generate_key, nasl_dh_compute_key)
(nasl_rsa_public_decrypt, nasl_rsa_sign, nasl_dsa_do_verify)
(nasl_dsa_do_sign, nasl_bf_cbc): Use GnuTLS/libgcrypt instead of
OpenSSL.  nasl_rsa_sign has different parameters now (see comments
in the code).
(nasl_bf_cbc_encrypt, nasl_bf_cbc_decrypt): Adapt to changes in
nasl_bf_cbc
(map_file): Return the data as a gnutls_datum_t.
(generate_signed_script, verify_script_signature): Use
GnuTLS/libgcrypt instead of OpenSSL.  verify_script_signature now
requires an x509 certificate instead of just an RSA key.


Modified: trunk/openvas-libnasl/ChangeLog
===================================================================
--- trunk/openvas-libnasl/ChangeLog     2007-07-12 19:26:09 UTC (rev 266)
+++ trunk/openvas-libnasl/ChangeLog     2007-07-17 13:53:45 UTC (rev 267)
@@ -1,3 +1,32 @@
+2007-07-17  Bernhard Herzog  <[EMAIL PROTECTED]>
+
+       * nasl/nasl_crypto2.c: Use GnuTLS/libgcrypt instead of OpenSSL.
+       Note the incompatible changes in rsa_sign and
+       verify_script_signature.
+       (print_tls_error, print_gcrypt_error): New.  Helper functions to
+       print error messages.
+       (mpi_from_string, mpi_from_named_parameter, set_mpi_retc): New.
+       Helper functions to handle MPIs
+       (extract_mpi_from_sexp, set_retc_from_sexp): New. Helper functions
+       to handle gcrypt s-expressions.
+       (nasl_load_privkey_param, nasl_sexp_from_privkey): New. Helper
+       functions to handle private keys.
+       (calc_dh_public, calc_dh_key): New.  Helper functions for
+       diffie-hellman
+       (hexdecode): New.  Helper function to decode a hex string.
+       (nasl_bn_cmp, nasl_bn_random, nasl_pem_to)
+       (nasl_dh_generate_key, nasl_dh_compute_key)
+       (nasl_rsa_public_decrypt, nasl_rsa_sign, nasl_dsa_do_verify)
+       (nasl_dsa_do_sign, nasl_bf_cbc): Use GnuTLS/libgcrypt instead of
+       OpenSSL.  nasl_rsa_sign has different parameters now (see comments
+       in the code).
+       (nasl_bf_cbc_encrypt, nasl_bf_cbc_decrypt): Adapt to changes in
+       nasl_bf_cbc
+       (map_file): Return the data as a gnutls_datum_t.
+       (generate_signed_script, verify_script_signature): Use
+       GnuTLS/libgcrypt instead of OpenSSL.  verify_script_signature now
+       requires an x509 certificate instead of just an RSA key.
+
 2007-07-09  Bernhard Herzog  <[EMAIL PROTECTED]>
 
        * nasl/nasl_crypto.c (nasl_gcrypt_hash, nasl_hash): New.  Helper

Modified: trunk/openvas-libnasl/nasl/nasl_crypto2.c
===================================================================
--- trunk/openvas-libnasl/nasl/nasl_crypto2.c   2007-07-12 19:26:09 UTC (rev 
266)
+++ trunk/openvas-libnasl/nasl/nasl_crypto2.c   2007-07-17 13:53:45 UTC (rev 
267)
@@ -17,10 +17,14 @@
  *
  *
  */
+
  /*
-  * This file contains all the call to OpenSSL functions needed by SSH protocol
+  * This file contains all the crypto functionality needed by the SSH protocol
   */
 #include <includes.h>
+#include <gcrypt.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
 
 #include "nasl_tree.h"
 #include "nasl_global_ctxt.h"
@@ -39,520 +43,1054 @@
 #define MAP_FAILED (void*)(-1)
 #endif
 
-#ifdef HAVE_SSL
 
-#include <openssl/bn.h>
-#include <openssl/dh.h>
-#include <openssl/evp.h>
-
-#include <openssl/blowfish.h>
-
 #define INTBLOB_LEN    20
 #define SIGBLOB_LEN    (2*INTBLOB_LEN)
 
-tree_cell * nasl_bn_cmp(lex_ctxt* lexic)
+/* prints a GnuTLS error.  The parameter err should be the GnuTLS error
+ * code */
+void
+print_tls_error(lex_ctxt * lexic, char *txt, int err)
 {
-  char         *s1 = NULL,*s2 = NULL;
-  tree_cell    *retc = NULL;
-  BIGNUM *key1 = NULL, *key2 = NULL;
-  int vn;
-  long sz1, sz2;
+  nasl_perror(lexic, "%s: %s (%d)\n", txt, gnutls_strerror(err), err);
+}
 
+/* prints a libgcrypt error.  The parameter err should be the libgcrypt
+ * error code */
+void
+print_gcrypt_error(lex_ctxt * lexic, char *function, int err)
+{
+  nasl_perror(lexic,
+             "%s failed: %s/%s\n",
+             function, gcry_strsource(err), gcry_strerror(err));
+}
+
+/* Converts a string to a gcry_mpi_t.  The string of len bytes at data
+ * should contain the MPI as an unsigned int in bigendian form
+ * (libgcrypt's GCRYMPI_FMT_USG).  The new MPI object is stored in dest.
+ * The parameters function and parameter are used in error messages to
+ * indicate the nasl function and nasl parameter name of the MPI.  The
+ * lexic parameter is passed through to the error reporting functions.
+ *
+ * The function return 0 on success and -1 on failure.
+ */
+static int
+mpi_from_string(lex_ctxt* lexic, gcry_mpi_t *dest, void *data, size_t len,
+               const char *parameter, const char* function)
+{
+  gcry_error_t err;
+  unsigned char* buffer = data;
+
+  if (len < 0)
+    return -1;
+
+  err = gcry_mpi_scan(dest, GCRYMPI_FMT_USG, buffer, len, NULL);
+
+  if (err)
+    {
+      nasl_perror(lexic,
+                 "%s(): gcry_mpi_scan failed for %s: %s/%s\n",
+                 function, parameter, gcry_strsource(err), gcry_strerror(err));
+      return -1;
+    }
+
+  return 0;
+}
+
+/* Converts a named nasl parameter to a gcry_mpi_t.  The new MPI object
+ * is stored in dest.  The parameter parameter is the name of the
+ * parameter to be taken from lexic.  The parameter function is used in
+ * error messages to indicate the name of the nasl function.
+ *
+ * The function return 0 on success and -1 on failure.
+ */
+static int
+mpi_from_named_parameter(lex_ctxt* lexic, gcry_mpi_t *dest,
+                        const char* parameter, const char *function)
+{
+  long size;
+  char *s;
+
+  s = get_str_local_var_by_name(lexic, parameter);
+  size = get_var_size_by_name(lexic, parameter);
+
+  if (!s)
+    return -1;
+
+  return mpi_from_string(lexic, dest, s, size, parameter, function);
+}
+
+/* Sets the return value in retc from the MPI mpi.  The MPI is converted
+ * to a byte string as an unsigned int in bigendian form (libgcrypts
+ * GCRYMPI_FMT_USG format).  If first byte in the string has it's most
+ * significant bit set, i.e. if it would be considered negative when
+ * interpreted as two's-complement representation, a null-byte is
+ * prepended to make sure the number is always considered positive.
+ *
+ * The function return 0 on success and -1 on failure.
+ */
+static int
+set_mpi_retc(tree_cell *retc, gcry_mpi_t mpi)
+{
+  unsigned char *buffer = NULL;
+  size_t size;
+  int extra;
+
+  gcry_mpi_aprint(GCRYMPI_FMT_USG, &buffer, &size, mpi);
+  if (!buffer)
+    return -1;
+
+  if (buffer[0] & 0x80)
+    extra = 1;
+  else
+    extra = 0;
+
+  retc->x.str_val = emalloc(size + extra);
+  retc->x.str_val[0] = '\0';
+  memcpy(retc->x.str_val + extra, buffer, size);
+  retc->size = size + extra;
+
+  gcry_free(buffer);
+
+  return 0;
+}
+
+/* nasl function
+ *
+ *   bn_cmp(key1:MPI1, key2:MPI2)
+ *
+ * Compares the MPIs key1 and key2 (given as binary strings).  Returns
+ * -1 if key1 < key2, 0 if key1 == key2 and +1 if key1 > key2.
+ */
+tree_cell *
+nasl_bn_cmp(lex_ctxt* lexic)
+{
+  tree_cell *retc = NULL;
+  gcry_mpi_t key1 = NULL, key2 = NULL;
+
   retc = emalloc(sizeof(tree_cell));
   retc->ref_count = 1;
   retc->type = CONST_INT;
   retc->x.i_val = 1;
 
-  vn = array_max_index(&lexic->ctx_vars);
-  /* key1 */
-  s1 = get_str_local_var_by_name(lexic, "key1");
-  sz1 = get_var_size_by_name(lexic, "key1");
+  if (mpi_from_named_parameter(lexic, &key1, "key1", "nasl_bn_cmp") < 0)
+    goto fail;
+  if (mpi_from_named_parameter(lexic, &key2, "key2", "nasl_bn_cmp") < 0)
+    goto fail;
 
-  /* key2 */
-  s2 = get_str_local_var_by_name(lexic, "key2");
-  sz2 = get_var_size_by_name(lexic, "key2");
+  retc->x.i_val = gcry_mpi_cmp(key1, key2);
 
- if ( s1 == NULL || s2 == NULL )
-   goto fail;
-  
-  key1 = BN_new();
-  key2 = BN_new();
+  /* make sure the return value is one of -1, 0, +1 */
+  if (retc->x.i_val > 0)
+    retc->x.i_val = 1;
+  if (retc->x.i_val < 0)
+    retc->x.i_val = -1;
 
-  if (BN_bin2bn((const unsigned char*)s1, sz1, key1) == 0)
-    goto fail;
-  if (BN_bin2bn((const unsigned char*)s2, sz2, key2) == 0)
-    goto fail;
-
-  retc->x.i_val = BN_cmp(key1,key2);
-  
  fail:
-  BN_free(key1);
-  BN_free(key2);
+  gcry_mpi_release(key1);
+  gcry_mpi_release(key2);
   return retc;
 }
 
-
-tree_cell * nasl_bn_random(lex_ctxt* lexic)
+/* nasl function
+ *
+ *   bn_random(need:numBits)
+ *
+ * Returns an MPI as a string with need bits of random data.
+ */
+tree_cell *
+nasl_bn_random(lex_ctxt* lexic)
 {
-  char         *s1 = NULL;
-  tree_cell    *retc = NULL;
-  BIGNUM *key = NULL;
-  long need, needlen, s1len;
-  int len;
+  tree_cell *retc = NULL;
+  gcry_mpi_t key = NULL;
+  long need;
 
   retc = alloc_tree_cell(0, NULL);
   retc->type = CONST_DATA;
- 
-  /* p bignum */
+
+  /* number of random bits */
   need = get_int_local_var_by_name(lexic, "need", 0);
-  needlen = get_var_size_by_name(lexic, "need");
 
-  key = BN_new();
+  key = gcry_mpi_new(0);
   if (!key)
     goto fail;
-  
-  if (!BN_rand(key, need, 0, 0))
-    goto fail;
 
-  s1len = BN_num_bytes(key);
-  s1 = emalloc(s1len);
-  if (s1 == NULL)
-     goto fail;
+  gcry_mpi_randomize(key, need, GCRY_STRONG_RANDOM);
 
-  BN_bn2bin(key, (unsigned char*)s1);
+  if (set_mpi_retc(retc, key) >= 0)
+    goto ret;
 
-  if (s1[0] & 0x80)
-    len = 1;
-  else 
-    len = 0;
-  retc->x.str_val = emalloc (s1len+len);
-  retc->x.str_val[0] = '\0';
-  memcpy(retc->x.str_val+len, s1, s1len);
-  retc->size = s1len + len;
-
-  goto ret;
-  
-fail:
+ fail:
   retc->size = 0;
   retc->x.str_val = emalloc(0);
-ret:
-  BN_free(key);
+ ret:
+  gcry_mpi_release(key);
   return retc;
-  
 }
 
+/* Loads a private key from a string.  The string is taken from the nasl
+ * parameter whose name is given by priv_name.  The passphrase_name is
+ * the name of the parameter holding the passphrase if any.  The string
+ * with the key must be in PEM format.
+ *
+ * The function returns the GnuTLS private key object on success, NULL
+ * on failure.
+ */
+static gnutls_x509_privkey_t
+nasl_load_privkey_param(lex_ctxt* lexic, const char * priv_name,
+                       const char* passphrase_name)
+{
+  char *priv = NULL, *passphrase = NULL;
+  long privlen, passphraselen;
+  gnutls_x509_privkey_t privkey = NULL;
+  gnutls_datum_t pem;
+  int err;
 
-tree_cell * nasl_pem_to(lex_ctxt* lexic, int type)
+  /* PEM encoded privkey */
+  priv = get_str_local_var_by_name(lexic, priv_name);
+  privlen = get_var_size_by_name(lexic, priv_name);
+
+  /* passphrase */
+  passphrase = get_str_local_var_by_name(lexic, passphrase_name);
+  passphraselen = get_var_size_by_name(lexic, passphrase_name);
+
+  pem.data = (unsigned char*)priv;
+  pem.size = privlen;
+
+  err = gnutls_x509_privkey_init(&privkey);
+  if (err)
+    {
+      print_tls_error(lexic, "gnutls_x509_privkey_init", err);
+      goto fail;
+    }
+
+  if (passphraselen == 0 || passphrase[0] == 0)
+    {
+      err = gnutls_x509_privkey_import(privkey, &pem, GNUTLS_X509_FMT_PEM);
+      if (err)
+       {
+         print_tls_error(lexic, "gnutls_x509_privkey_import", err);
+         goto fail;
+       }
+    }
+  else
+    {
+      err = gnutls_x509_privkey_import_pkcs8(privkey, &pem, 
GNUTLS_X509_FMT_PEM,
+                                            passphrase, 0);
+      if (err)
+       {
+         print_tls_error(lexic, "gnutls_x509_privkey_import_pkcs8", err);
+         goto fail;
+       }
+    }
+
+
+  return privkey;
+
+ fail:
+  gnutls_x509_privkey_deinit(privkey);
+  return NULL;
+}
+
+/* Implements the nasl functions pem_to_rsa and pem_to_dsa. */
+tree_cell *
+nasl_pem_to(lex_ctxt* lexic, int type)
 {
-  char         *s1 = NULL, *priv = NULL, *passphrase = NULL;
-  tree_cell    *retc = NULL;
-  RSA * rsa = NULL;
-  DSA * dsa = NULL;
-  BIGNUM * key = NULL;
-  BIO * bio = NULL;
-  long privlen, plen, s1len;
-  int len;
+  tree_cell *retc = NULL;
+  gnutls_x509_privkey_t privkey = NULL;
+  gcry_mpi_t key = NULL;
+  int err;
 
-  if ( check_authenticated(lexic) < 0 ) return FAKE_CELL;
+  if (check_authenticated(lexic) < 0)
+    return FAKE_CELL;
 
   retc = alloc_tree_cell(0, NULL);
   retc->type = CONST_DATA;
- 
-  /* priv bignum */
-  priv = get_str_local_var_by_name(lexic, "priv");
-  privlen = get_var_size_by_name(lexic, "priv");
 
-  if ( priv == NULL )
-       goto fail;
-  
-  /* priv bignum */
-  passphrase = get_str_local_var_by_name(lexic, "passphrase");
-  plen = get_var_size_by_name(lexic, "passphrase");
+  privkey = nasl_load_privkey_param(lexic, "priv", "passphrase");
+  if (!privkey)
+    goto fail;
 
-  bio = BIO_new_mem_buf(priv, privlen);
-  if (!bio)
-    goto fail;
-  
   if (!type)
     {
-      rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, passphrase);
-      if (!rsa)
-        goto fail;
-      key = rsa->d;
+      gnutls_datum_t m, e, d, p, q, u;
+      err = gnutls_x509_privkey_export_rsa_raw(privkey, &m, &e, &d, &p, &q, 
&u);
+      if (err)
+       {
+         print_tls_error(lexic, "gnutls_x509_privkey_export_rsa_raw", err);
+         goto fail;
+       }
+
+      err = mpi_from_string(lexic, &key, d.data, d.size, "rsa d",
+                           "nasl_pem_to");
+      gnutls_free(m.data);
+      gnutls_free(e.data);
+      gnutls_free(d.data);
+      gnutls_free(p.data);
+      gnutls_free(q.data);
+      gnutls_free(u.data);
+
+      if (err < 0)
+       goto fail;
     }
   else
     {
-      dsa = PEM_read_bio_DSAPrivateKey(bio, NULL, NULL, passphrase);
-      if (!dsa)
-        goto fail;
-      key = dsa->priv_key;
+      gnutls_datum_t p, q, g, y, x;
+      err = gnutls_x509_privkey_export_dsa_raw(privkey, &p, &q, &g, &y, &x);
+      if (err)
+       {
+         print_tls_error(lexic, "gnutls_x509_privkey_export_dsa_raw", err);
+         goto fail;
+       }
+
+      err = mpi_from_string(lexic, &key, x.data, x.size, "dsa x",
+                           "nasl_pem_to");
+
+      gnutls_free(p.data);
+      gnutls_free(q.data);
+      gnutls_free(g.data);
+      gnutls_free(y.data);
+      gnutls_free(x.data);
+
+      if (err < 0)
+       goto fail;
     }
-  
-  s1len = BN_num_bytes(key);
-  s1 = emalloc(s1len);
-  if (s1 == NULL)
-     goto fail;
 
-  BN_bn2bin(key, (unsigned char*)s1);
-  
-  if (s1[0] & 0x80)
-    len = 1;
-  else 
-    len = 0;
-  retc->x.str_val = emalloc (s1len+len);
-  retc->x.str_val[0] = '\0';
-  memcpy(retc->x.str_val+len, s1, s1len);
-  retc->size = s1len + len;
+  if (set_mpi_retc(retc, key) >= 0)
+    goto ret;
 
-  goto ret;
-  
 fail:
   retc->size = 0;
   retc->x.str_val = emalloc(0);
 ret:
-  BIO_free(bio);
-  RSA_free(rsa);
-  DSA_free(dsa);
+  gcry_mpi_release(key);
+  gnutls_x509_privkey_deinit(privkey);
   return retc;
-  
 }
 
 
-tree_cell * nasl_pem_to_rsa(lex_ctxt* lexic)
+/* nasl function
+ *
+ *   pem_to_rsa(priv:PEM, passphrase:PASSPHRASE)
+ *
+ * Reads the private key from the string priv which contains a private
+ * RSA key in PEM format.  Passphrase is the passphrase needed to
+ * decrypt the private key.  The function returns the parameter "d" of
+ * the RSA key as an MPI.
+ */
+tree_cell *
+nasl_pem_to_rsa(lex_ctxt* lexic)
 {
   return nasl_pem_to(lexic, 0);
 }
 
 
-
-tree_cell * nasl_pem_to_dsa(lex_ctxt* lexic)
+/* nasl function
+ *
+ *   pem_to_dsa(priv:PEM, passphrase:PASSPHRASE)
+ *
+ * Reads the private key from the string priv which contains a private
+ * DSA key in PEM format.  Passphrase is the passphrase needed to
+ * decrypt the private key.  The function returns the parameter "x" of
+ * the DSA key as an MPI.
+ */
+tree_cell *
+nasl_pem_to_dsa(lex_ctxt* lexic)
 {
   return nasl_pem_to(lexic, 1);
 }
 
 
-tree_cell * nasl_dh_generate_key(lex_ctxt* lexic)
+/* compute the diffie hellman public key.  Neither GnuTLS nor Libgcrypt
+ * contain a direct counterpart to OpenSSL's DH_generate_key, so we
+ * implement it ourselves.  This function was copied from from gnutls
+ * and adapted to use gcrypt directly and to use a private key given as
+ * parameter to the function.
+ *
+ * The function returns the key on success and NULL on failure.
+ */
+static gcry_mpi_t
+calc_dh_public(gcry_mpi_t g, gcry_mpi_t prime, gcry_mpi_t priv)
 {
-  char         *s1 = NULL,*s2 = NULL,*s3 = NULL,*pub = NULL;
-  tree_cell    *retc = NULL;
-  DH *dh = NULL;
-  long sz1, sz2, sz3, pubsize;
-  int len;
+  gcry_mpi_t e;
 
-  retc = alloc_tree_cell(0, NULL);
-  retc->type = CONST_DATA;
- 
-  /* p bignum */
-  s1 = get_str_local_var_by_name(lexic, "p");
-  sz1 = get_var_size_by_name(lexic, "p");
-  
-  /* g bignum */
-  s2 = get_str_local_var_by_name(lexic, "g");
-  sz2 = get_var_size_by_name(lexic, "g");
+  e = gcry_mpi_new(gcry_mpi_get_nbits(prime));
+  if (e == NULL)
+    {
+      return NULL;
+    }
 
-  /* priv key bignum */
-  s3 = get_str_local_var_by_name(lexic, "priv");
-  sz3 = get_var_size_by_name(lexic, "priv");
+  gcry_mpi_powm(e, g, priv, prime);
 
-  if ( s1 == NULL || s2 == NULL || s3 == NULL )
-     goto fail;
+  return e;
+}
 
-  if ((dh = DH_new()) == NULL)
-     goto fail;
- 
-  dh->p = BN_new();
-  dh->g = BN_new();
-  dh->priv_key = BN_new();
-  
+/* compute the diffie hellman shared secret key.  Neither GnuTLS nor
+ * libgcrypt contain a direct counterpart to OpenSSL's DH_compute_key,
+ * so we implement it ourselves.  This function was copied from from
+ * gnutls and adapted to use gcrypt directly and to use a private key
+ * given as parameter to the function.
+ *
+ * The function returns the key on success and NULL on failure.
+ */
+static gcry_mpi_t
+calc_dh_key(gcry_mpi_t pub, gcry_mpi_t prime, gcry_mpi_t priv)
+{
+  gcry_mpi_t e;
 
-  if (BN_bin2bn((const unsigned char*)s1, sz1, dh->p) == 0)
-     goto fail;
-  if (BN_bin2bn((const unsigned char*)s2, sz2, dh->g) == 0)
-     goto fail;
-  if (BN_bin2bn((const unsigned char*)s3, sz3, dh->priv_key) == 0)
-     goto fail;
+  e = gcry_mpi_new(gcry_mpi_get_nbits(prime));
+  if (e == NULL)
+    {
+      return NULL;
+    }
 
-  if (dh->p == NULL)
-    goto fail;
+  gcry_mpi_powm(e, pub, priv, prime);
 
-  if (DH_generate_key(dh) == 0)
-      goto fail;
+  return e;
+}
 
-  pubsize = BN_num_bytes(dh->pub_key);
-  pub = emalloc(pubsize); 
-  if (pub == NULL)
-     goto fail;
-  BN_bn2bin(dh->pub_key, (unsigned char*)pub);
+/* nasl function
+ *
+ *    dh_generate_key(p:mpi_p, g:mpi_g, priv:mpi_priv)
+ *
+ * Generates a Diffie-Hellman public key from the shared parameters p
+ * and g and the private parameter priv.  The return value is the public
+ * key as an MPI.
+ */
+tree_cell *
+nasl_dh_generate_key(lex_ctxt* lexic)
+{
+  tree_cell *retc = NULL;
+  gcry_mpi_t p = NULL, g = NULL, priv = NULL, pub_mpi = NULL;
 
-  if (pub[0] & 0x80)
-    len = 1;
-  else 
-    len = 0;
-  retc->x.str_val = emalloc (pubsize+len);
-  retc->x.str_val[0] = '\0';
-  memcpy(retc->x.str_val+len, pub, pubsize);
-  retc->size = pubsize + len;
+  retc = alloc_tree_cell(0, NULL);
+  retc->type = CONST_DATA;
 
-  goto ret;
+  if (mpi_from_named_parameter(lexic, &p, "p", "nasl_dh_generate_key") < 0)
+    goto fail;
+  if (mpi_from_named_parameter(lexic, &g, "g", "nasl_dh_generate_key") < 0)
+    goto fail;
+  if (mpi_from_named_parameter(lexic, &priv, "priv", "nasl_dh_generate_key") 
<0)
+    goto fail;
 
+  pub_mpi = calc_dh_public(g, p, priv);
+  if (pub_mpi == NULL)
+    goto fail;
+
+  if (set_mpi_retc(retc, pub_mpi) >= 0)
+    goto ret;
+
 fail:
   retc->x.str_val = emalloc(0);
   retc->size = 0;
 ret:
-  DH_free(dh);
-  free(pub);
+  gcry_mpi_release(p);
+  gcry_mpi_release(g);
+  gcry_mpi_release(priv);
+  gcry_mpi_release(pub_mpi);
   return retc;
 }
 
-
-tree_cell * nasl_dh_compute_key(lex_ctxt* lexic)
+/* nasl function
+ *
+ *    DH_compute_key(p:mpi_p, g:mpi_g, dh_server_pub:mpi_server_pub,
+ *                   pub_key:mpi_client_pub, priv_key:mpi_client_priv)
+ *
+ * Computes the Diffie-Hellman shared secret key from the shared
+ * parameters p and g, the server's public key dh_server_pub and the
+ * client's public and private keys pub_key an priv_key.  The return
+ * value is the shared secret key as an MPI.
+ */
+tree_cell *
+nasl_dh_compute_key(lex_ctxt* lexic)
 {
-  char *s1 = NULL,*s2 = NULL,*s3 = NULL,*s4 = NULL,*s5 = NULL;
-  char *kbuf;
-  tree_cell    *retc = NULL;
-  BIGNUM *dh_server_pub = NULL;
-  DH *dh = NULL;
-  int kout,klen,len;
-  long sz1, sz2, sz3, sz4, sz5;
+  tree_cell *retc = NULL;
+  gcry_mpi_t p = NULL, g = NULL, dh_server_pub = NULL;
+  gcry_mpi_t pub_key = NULL, priv_key = NULL;
+  gcry_mpi_t shared = NULL;
 
   retc = alloc_tree_cell(0, NULL);
   retc->type = CONST_DATA;
- 
-  /* p bignum */
-  s1 = get_str_local_var_by_name(lexic, "p");
-  sz1 = get_var_size_by_name(lexic, "p");
-  
-  /* g bignum */
-  s2 = get_str_local_var_by_name(lexic, "g");
-  sz2 = get_var_size_by_name(lexic, "g");
 
-  /* dh_server_pub bignum */
-  s3 = get_str_local_var_by_name(lexic, "dh_server_pub");
-  sz3 = get_var_size_by_name(lexic, "dh_server_pub");
+  if (mpi_from_named_parameter(lexic, &p, "p", "nasl_dh_compute_key") < 0)
+    goto fail;
+  if (mpi_from_named_parameter(lexic, &g, "g", "nasl_dh_compute_key") < 0)
+    goto fail;
+  if (mpi_from_named_parameter(lexic, &dh_server_pub, "dh_server_pub",
+                              "nasl_dh_compute_key") < 0)
+    goto fail;
+  if (mpi_from_named_parameter(lexic, &pub_key, "pub_key",
+                              "nasl_dh_compute_key") < 0)
+    goto fail;
+  if (mpi_from_named_parameter(lexic, &priv_key, "priv_key",
+                              "nasl_dh_compute_key") < 0)
+    goto fail;
 
-  /* public key bignum */
-  s4 = get_str_local_var_by_name(lexic, "pub_key");
-  sz4 = get_var_size_by_name(lexic, "pub_key");
+  shared = calc_dh_key(dh_server_pub, p, priv_key);
 
-  /* private key bignum */
-  s5 = get_str_local_var_by_name(lexic, "priv_key");
-  sz5 = get_var_size_by_name(lexic, "priv_key");
+  if (set_mpi_retc(retc, shared) >= 0)
+    goto ret;
 
+fail:
+  retc->size = 0;
+  retc->x.str_val = emalloc(0);
+ret:
+  gcry_mpi_release(p);
+  gcry_mpi_release(g);
+  gcry_mpi_release(dh_server_pub);
+  gcry_mpi_release(priv_key);
+  gcry_mpi_release(pub_key);
+  gcry_mpi_release(shared);
+  return retc;
+}
 
-  if ( s1 == NULL || s2 == NULL || s3 == NULL || s4 == NULL || s5 == NULL )
-     goto fail;
+/*
+ * Extracts an MPI value from a libgcryt s-expression.  The return value
+ * is the cadr of the subexpression whose car is given by token.  The
+ * function returns NULL if the token doesn't occur in the expression or
+ * on other errors.
+ */
+static gcry_mpi_t
+extract_mpi_from_sexp(gcry_sexp_t sexp, const char * token)
+{
+  gcry_sexp_t child = NULL;
+  gcry_mpi_t mpi = NULL;
 
-  if ((dh = DH_new()) == NULL)
-     goto fail;
- 
-  dh->p = BN_new();
-  dh->g = BN_new();
-  dh->pub_key = BN_new();
-  dh->priv_key = BN_new();
-  dh_server_pub = BN_new();
+  child = gcry_sexp_find_token(sexp, token, strlen(token));
+  if (!child)
+    {
+      fprintf(stderr, "set_retc_from_sexp: no subexpression with token <%s>\n",
+             token);
+    }
+  else
+    {
+      mpi = gcry_sexp_nth_mpi(child, 1, GCRYMPI_FMT_USG);
+    }
 
-  if (BN_bin2bn((const unsigned char*)s1, sz1, dh->p) == 0)
-     goto fail;
-  if (BN_bin2bn((const unsigned char*)s2, sz2, dh->g) == 0)
-     goto fail;
-  if (BN_bin2bn((const unsigned char*)s3, sz3, dh_server_pub) == 0)
-     goto fail;
-  if (BN_bin2bn((const unsigned char*)s4, sz4, dh->pub_key) == 0)
-     goto fail;
-  if (BN_bin2bn((const unsigned char*)s5, sz5, dh->priv_key) == 0)
-     goto fail;
+  gcry_sexp_release(child);
 
-  klen = DH_size(dh);
-  kbuf = emalloc(klen);
-  kout = DH_compute_key((unsigned char*)kbuf, dh_server_pub, dh);
+  return mpi;
+}
+
+/*
+ * Sets the return value in retc from an sexpression.  The function uses
+ * extract_mpi_from_sexp to extract an MPI from the sexpression sexp and
+ * the subexpression given by token.  The function return 1 on success
+ * and 0 on failure.
+ */
+static int
+set_retc_from_sexp(tree_cell *retc, gcry_sexp_t sexp, const char * token)
+{
+  int ret = 0;
+  gcry_mpi_t mpi = extract_mpi_from_sexp(sexp, token);
+  if (mpi)
+    {
+      ret = set_mpi_retc(retc, mpi);
+
+      gcry_mpi_release(mpi);
+    }
+
+  return ret;
+}
+
+/* nasl function
+ *
+ *   rsa_public_decrypt(sig:signature, e:mpi_e, n:mpi_n)
+ *
+ * Decrypt the data in signature (usually an rsa-encrypted hash) with
+ * the public RSA key given by its parameters e and n.  The return value
+ * is the decrypted data.
+ */
+tree_cell *
+nasl_rsa_public_decrypt(lex_ctxt* lexic)
+{
+  char *s1 = NULL;
+  tree_cell *retc = NULL;
+  long sz1;
+  gcry_mpi_t e = NULL, n = NULL;
+  gcry_sexp_t key = NULL, sig = NULL, decrypted = NULL;
+  gcry_error_t err;
+
+  retc = alloc_tree_cell(0, NULL);
+  retc->type = CONST_DATA;
+
+  /* encrypted data */
+  s1 = get_str_local_var_by_name(lexic, "sig");
+  sz1 = get_var_size_by_name(lexic, "sig");
+
+  if (mpi_from_named_parameter(lexic, &e, "e", "nasl_rsa_public_decrypt") < 0)
+    goto fail;
+  if (mpi_from_named_parameter(lexic, &n, "n", "nasl_rsa_public_decrypt") < 0)
+    goto fail;
+
+  err = gcry_sexp_build(&key, NULL, "(public-key (rsa (n %m) (e %m)))", n, e);
+  if (err)
+    {
+      print_gcrypt_error(lexic, "gcry_sexp_build pubkey", err);
+      goto fail;
+    }
+  err = gcry_sexp_build(&sig, NULL, "(data (value %b))", sz1, s1);
+  if (err)
+    {
+      print_gcrypt_error(lexic, "gcry_sexp_build sig", err);
+      goto fail;
+    }
  
-  if (kbuf[0] & 0x80)
-    len = 1;
-  else 
-    len = 0;
-  retc->x.str_val = emalloc (kout+len);
-  retc->x.str_val[0] = '\0';
-  memcpy(retc->x.str_val+len, kbuf, kout);
-  retc->size = kout + len;
-  goto ret;
+  /* gcry_pk_encrypt is equivalent to the public key decryption at least
+   * for RSA keys. */
+  err = gcry_pk_encrypt(&decrypted, sig, key);
+  if (err)
+    {
+      print_gcrypt_error(lexic, "gcry_pk_encrypt", err);
+      goto fail;
+    }
 
+  if (set_retc_from_sexp(retc, decrypted, "a") >= 0)
+    goto ret;
+
 fail:
   retc->size = 0;
   retc->x.str_val = emalloc(0);
 ret:
-  DH_free(dh);
-  BN_free(dh_server_pub);
+  gcry_sexp_release(decrypted);
+  gcry_sexp_release(key);
+  gcry_sexp_release(sig);
+  gcry_mpi_release(e);
+  gcry_mpi_release(n);
   return retc;
 }
 
+/* Creates a libgcryt s-expression from a GnuTLS private RSA key.
+ */
+#define NUM_RSA_PARAMS 6
+static gcry_sexp_t
+nasl_sexp_from_privkey(lex_ctxt* lexic, gnutls_x509_privkey_t privkey)
+{
+  gnutls_datum_t datums[NUM_RSA_PARAMS]; /* m/n, e, d, p, q, u */
+  gcry_mpi_t mpis[NUM_RSA_PARAMS]; /* m/n, e, d, p, q, u */
+  gcry_sexp_t key = NULL;
+  int err;
+  gcry_error_t gerr;
+  int i;
 
-tree_cell * nasl_rsa_public_decrypt(lex_ctxt* lexic)
+  for (i = 0; i < NUM_RSA_PARAMS; i++)
+    {
+      datums[i].data = NULL;
+      mpis[i] = NULL;
+    }
+
+  err = gnutls_x509_privkey_export_rsa_raw(privkey,
+                                          datums + 0, datums + 1,
+                                          datums + 2, datums + 3,
+                                          datums + 4, datums + 5);
+  if (err)
+    {
+      print_tls_error(lexic, "gnutls_x509_privkey_export_rsa_raw", err);
+      goto fail;
+    }
+
+  for (i = 0; i < NUM_RSA_PARAMS; i++)
+    {
+      err = mpi_from_string(lexic, mpis + i,
+                           datums[i].data, datums[i].size,
+                           "rsa parameter", "nasl_sexp_from_privkey");
+      if (err < 0)
+       goto fail;
+    }
+
+  /* make sure that p < q. libgcrypt requires this. */
+  if (gcry_mpi_cmp(mpis[3], mpis[4]) > 0)
+    {
+      gcry_mpi_swap(mpis[3], mpis[4]);
+    }
+
+  gerr = gcry_sexp_build(&key, NULL,
+                       "(private-key (rsa (n %m) (e %m) (d %m)"
+                                        " (p %m) (q %m) (u %m)))",
+                       mpis[0], mpis[1], mpis[2],
+                       mpis[3], mpis[4], mpis[5]);
+  if (gerr)
+    {
+      print_gcrypt_error(lexic, "gcry_sexp_build", gerr);
+      goto fail;
+    }
+
+ fail:
+  for (i = 0; i < NUM_RSA_PARAMS; i++)
+    {
+      gnutls_free(datums[i].data);
+      gcry_mpi_release(mpis[i]);
+    }
+
+  return key;
+}
+
+
+/* nasl function
+ *
+ *   rsa_sign(data:hash, priv:pem, passphrase:passphrase)
+ *
+ * Signs the data with the private RSA key priv given in PEM format.
+ * The passphrase is the passphrase needed to decrypt the private key.
+ * Returns the signed data.
+ *
+ * In the OpenSSL based nasl, the key was not given in PEM form and with
+ * a passphrase.  Instead it was given as the RSA parameters e, n and d.
+ * libgcrypt always requires all the parameters (including p, g, and u),
+ * so this function was changed to simply accept the full private key in
+ * PEM form.  The one place where it was called had that the key
+ * available in that form.
+ */
+tree_cell *
+nasl_rsa_sign(lex_ctxt* lexic)
 {
-  char *s1 = NULL,*s2 = NULL,*s3 = NULL, *decrypted = NULL;
-  tree_cell    *retc = NULL;
-  RSA *rsa = NULL;
-  int len;
-  long sz1, sz2, sz3;
+  tree_cell *retc = NULL;
+  char * data;
+  int data_size;
+  gcry_sexp_t ssig = NULL, sdata = NULL, skey = NULL;
+  gnutls_x509_privkey_t priv_key = NULL;
+  gcry_error_t err;
 
+  if (check_authenticated(lexic) < 0)
+    return FAKE_CELL;
+
   retc = alloc_tree_cell(0, NULL);
   retc->type = CONST_DATA;
- 
-  /* sig bignum */
-  s1 = get_str_local_var_by_name(lexic, "sig");
-  sz1 = get_var_size_by_name(lexic, "sig");
-  
-  /* e bignum */
-  s2 = get_str_local_var_by_name(lexic, "e");
-  sz2 = get_var_size_by_name(lexic, "e");
 
-  /* n bignum */
-  s3 = get_str_local_var_by_name(lexic, "n");
-  sz3 = get_var_size_by_name(lexic, "n");
-
-  if ( s1 == NULL || s2 == NULL || s3 == NULL ) 
+  data = get_str_local_var_by_name(lexic, "data");
+  data_size = get_var_size_by_name(lexic, "data");
+  if (!data)
     goto fail;
 
-  if ((rsa = RSA_new()) == NULL)
+  priv_key = nasl_load_privkey_param(lexic, "priv", "passphrase");
+  if (!priv_key)
     goto fail;
- 
 
-  rsa->e = BN_new();
-  rsa->n = BN_new();
+  err = gcry_sexp_build(&sdata, NULL, "(data (flags pkcs1) (hash sha1 %b))",
+                       data_size, data);
+  if (err)
+    {
+      print_gcrypt_error(lexic, "gcry_sexp_build for data", err);
+      goto fail;
+    }
 
-  if (BN_bin2bn((const unsigned char*)s3, sz3, rsa->n) == 0)
+  skey = nasl_sexp_from_privkey(lexic, priv_key);
+  if (!skey)
     goto fail;
-  if (BN_bin2bn((const unsigned char*)s2, sz2, rsa->e) == 0)
-    goto fail;
 
-  decrypted = emalloc(sz1);
-  if (!decrypted)
-    goto fail;
 
-  if ((len = RSA_public_decrypt(sz1, (unsigned char*)s1, (unsigned 
char*)decrypted, rsa,
-           RSA_PKCS1_PADDING)) < 0)
-    goto fail;
+  err = gcry_pk_sign(&ssig, sdata, skey);
+  if (err)
+    {
+      print_gcrypt_error(lexic, "gcry_pk_sign", err);
+      goto fail;
+    }
 
-  retc->size = len;
-  retc->x.str_val = decrypted;
-  goto ret;
+  if (set_retc_from_sexp(retc, ssig, "s") >= 0)
+    goto ret;
 
 fail:
   retc->size = 0;
   retc->x.str_val = emalloc(0);
 ret:
-  RSA_free(rsa);
+  gcry_sexp_release(ssig);
+  gcry_sexp_release(sdata);
+  gcry_sexp_release(skey);
+  gnutls_x509_privkey_deinit(priv_key);
   return retc;
 }
 
 
-tree_cell * nasl_rsa_sign(lex_ctxt* lexic)
+/* nasl function
+ *
+ *   dsa_do_verify(p:mpi_p, g:mpi_g, q:mpi_q, pub:mpi_pub,
+ *                 r:mpi_r, s:mpi_s, data:hash)
+ *
+ * Verify that the DSA signature given by r and s matches the hash given
+ * in data using the public DSA key given by p, g, q and pub.  Returns 1
+ * if the signature is valid and 0 if it's invalid.
+ */
+tree_cell *
+nasl_dsa_do_verify(lex_ctxt* lexic)
 {
-  char *s1 = NULL,*s2 = NULL,*s3 = NULL, *s4 = NULL, *sig = NULL, *signature = 
NULL;
   tree_cell    *retc = NULL;
-  RSA *rsa = NULL;
-  int ok;
-  long sz1, sz2, sz3, sz4, slen;
-  unsigned int len;
+  gcry_mpi_t p = NULL, g = NULL, q = NULL, pub = NULL, data = NULL;
+  gcry_mpi_t r = NULL, s = NULL;
+  gcry_sexp_t ssig = NULL, skey = NULL, sdata = NULL;
+  gcry_error_t err;
 
-  if ( check_authenticated(lexic) < 0 ) return FAKE_CELL;
+  retc = emalloc(sizeof(tree_cell));
+  retc->ref_count = 1;
+  retc->type = CONST_INT;
+  retc->x.i_val = 0;
 
-  retc = alloc_tree_cell(0, NULL);
-  retc->type = CONST_DATA;
- 
-  /* sig bignum */
-  s1 = get_str_local_var_by_name(lexic, "data");
-  sz1 = get_var_size_by_name(lexic, "data");
-  
-  /* e bignum */
-  s2 = get_str_local_var_by_name(lexic, "e");
-  sz2 = get_var_size_by_name(lexic, "e");
+  if (mpi_from_named_parameter(lexic, &p, "p", "nasl_dsa_do_sign") < 0)
+    goto fail;
+  if (mpi_from_named_parameter(lexic, &g, "g", "nasl_dsa_do_sign") < 0)
+    goto fail;
+  if (mpi_from_named_parameter(lexic, &q, "q", "nasl_dsa_do_sign") < 0)
+    goto fail;
+  if (mpi_from_named_parameter(lexic, &pub, "pub", "nasl_dsa_do_sign") < 0)
+    goto fail;
+  if (mpi_from_named_parameter(lexic, &r, "r", "nasl_dsa_do_sign") < 0)
+    goto fail;
+  if (mpi_from_named_parameter(lexic, &s, "s", "nasl_dsa_do_sign") < 0)
+    goto fail;
+  if (mpi_from_named_parameter(lexic, &data, "data", "nasl_dsa_do_sign") < 0)
+    goto fail;
 
-  /* n bignum */
-  s3 = get_str_local_var_by_name(lexic, "n");
-  sz3 = get_var_size_by_name(lexic, "n");
+  err = gcry_sexp_build(&sdata, NULL, "(data (flags raw) (value %m))", data);
+  if (err)
+    {
+      print_gcrypt_error(lexic, "gcry_sexp_build for data", err);
+      goto fail;
+    }
 
-  /* d bignum */
-  s4 = get_str_local_var_by_name(lexic, "d");
-  sz4 = get_var_size_by_name(lexic, "d");
+  err = gcry_sexp_build(&skey, NULL,
+                       "(public-key (dsa (p %m) (q %m) (g %m) (y %m)))",
+                       p, q, g, pub);
+  if (err)
+    {
+      print_gcrypt_error(lexic, "gcry_sexp_build for private key", err);
+      goto fail;
+    }
 
-  if ( s1 == NULL || s2 == NULL || s3 == NULL || s4 == NULL )
-    goto fail;
+  err = gcry_sexp_build(&ssig, NULL, "(sig-val (dsa (r %m) (s %m)))", r, s);
+  if (err)
+    {
+      print_gcrypt_error(lexic, "gcry_sexp_build for signature", err);
+      goto fail;
+    }
 
-  if ((rsa = RSA_new()) == NULL)
-    goto fail;
- 
-  rsa->e = BN_new();
-  rsa->n = BN_new();
-  rsa->d = BN_new();
+  err = gcry_pk_verify(ssig, sdata, skey);
+  if (err == 0)
+    retc->x.i_val = 1;
+  else if (gcry_err_code(err) == GPG_ERR_BAD_SIGNATURE)
+    retc->x.i_val = 0;
+  else
+    {
+      print_gcrypt_error(lexic, "gcry_pk_sign", err);
+      goto fail;
+    }
 
-  if (BN_bin2bn((const unsigned char*)s3, sz3, rsa->n) == 0)
+fail:
+  gcry_mpi_release(p);
+  gcry_mpi_release(g);
+  gcry_mpi_release(q);
+  gcry_mpi_release(pub);
+  gcry_mpi_release(r);
+  gcry_mpi_release(s);
+  gcry_mpi_release(data);
+  gcry_sexp_release(ssig);
+  gcry_sexp_release(skey);
+  gcry_sexp_release(sdata);
+
+  return retc;
+}
+
+/* nasl function
+ *
+ *   dsa_do_sign(p:mpi_p, g:mpi_g, q:mpi_q, pub:mpi_pub, priv:mpi_priv,
+ *               data:hash)
+ *
+ * Computes the DSA signature of the hash in data using the private DSA
+ * key given by p, g, q, pub and priv.  The return value is a 40 byte
+ * string encoding the two MPIs r and s of the DSA signature.  The first
+ * 20 bytes are the value of r and the last 20 bytes are the value of s.
+ */
+tree_cell *
+nasl_dsa_do_sign(lex_ctxt* lexic)
+{
+  tree_cell *retc = NULL;
+  gcry_mpi_t p = NULL, g = NULL, q = NULL, pub = NULL, priv = NULL, data = 
NULL;
+  gcry_mpi_t r = NULL, s = NULL;
+  gcry_sexp_t ssig = NULL, skey = NULL, sdata = NULL;
+  long rlen, slen;
+  unsigned char * sigblob = NULL;
+  gcry_error_t err;
+
+  if (check_authenticated(lexic) < 0)
+    return FAKE_CELL;
+
+  retc = emalloc(sizeof(tree_cell));
+  retc->ref_count = 1;
+  retc->type = CONST_DATA;
+  retc->x.i_val = 0;
+
+  if (mpi_from_named_parameter(lexic, &p, "p", "nasl_dsa_do_sign") < 0)
     goto fail;
-  if (BN_bin2bn((const unsigned char*)s2, sz2, rsa->e) == 0)
+  if (mpi_from_named_parameter(lexic, &g, "g", "nasl_dsa_do_sign") < 0)
     goto fail;
-  if (BN_bin2bn((const unsigned char*)s4, sz4, rsa->d) == 0)
+  if (mpi_from_named_parameter(lexic, &q, "q", "nasl_dsa_do_sign") < 0)
     goto fail;
-
-  slen = RSA_size(rsa);
-  sig = emalloc(slen);
-  if (!sig)
+  if (mpi_from_named_parameter(lexic, &pub, "pub", "nasl_dsa_do_sign") < 0)
     goto fail;
-
-  ok = RSA_sign(NID_sha1, (unsigned char*)s1, sz1, (unsigned char*)sig, &len, 
rsa);
-  if (!ok || len > slen)
+  if (mpi_from_named_parameter(lexic, &priv, "priv", "nasl_dsa_do_sign") < 0)
     goto fail;
-  
-  signature = emalloc(len);
-  if (!signature)
+  if (mpi_from_named_parameter(lexic, &data, "data", "nasl_dsa_do_sign") < 0)
     goto fail;
-  
-  memcpy(signature,sig,len);
-  retc->size = len;
-  retc->x.str_val = signature;
-  goto ret;
 
+  err = gcry_sexp_build(&sdata, NULL, "(data (flags raw) (value %m))", data);
+  if (err)
+    {
+      print_gcrypt_error(lexic, "gcry_sexp_build for data", err);
+      goto fail;
+    }
+
+  err = gcry_sexp_build(&skey, NULL,
+                      "(private-key (dsa (p %m) (q %m) (g %m) (y %m) (x %m)))",
+                       p, q, g, pub, priv);
+  if (err)
+    {
+      print_gcrypt_error(lexic, "gcry_sexp_build for private-key", err);
+      goto fail;
+    }
+
+  err = gcry_pk_sign(&ssig, sdata, skey);
+  if (err)
+    {
+      print_gcrypt_error(lexic, "gcry_pk_sign", err);
+      goto fail;
+    }
+
+  r = extract_mpi_from_sexp(ssig, "r");
+  s = extract_mpi_from_sexp(ssig, "s");
+  if (!r || !s)
+    goto fail;
+
+  rlen = (gcry_mpi_get_nbits(r) + 7) / 8;
+  slen = (gcry_mpi_get_nbits(s) + 7) / 8;
+  if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN)
+    {
+      nasl_perror(lexic, "rlen (%d) or slen (%d) > INTBLOB_LEN (%d)\n",
+                 rlen, slen, INTBLOB_LEN);
+      goto fail;
+    }
+
+  sigblob = emalloc(SIGBLOB_LEN);
+  memset(sigblob, 0, SIGBLOB_LEN);
+
+  err = gcry_mpi_print(GCRYMPI_FMT_USG,
+                      (unsigned char*)(sigblob + SIGBLOB_LEN - INTBLOB_LEN - 
rlen),
+                      rlen, NULL, r);
+  if (err)
+    {
+      print_gcrypt_error(lexic, "gcry_mpi_print(r)", err);
+      goto fail;
+    }
+  err = gcry_mpi_print(GCRYMPI_FMT_USG,
+                      (unsigned char*)(sigblob+ SIGBLOB_LEN - slen),
+                      rlen, NULL, s);
+  if (err)
+    {
+      print_gcrypt_error(lexic, "gcry_mpi_print(s)", err);
+      goto fail;
+    }
+
+  retc->x.str_val = (char*)sigblob;
+  sigblob = NULL;
+  retc->size = SIGBLOB_LEN;
+
 fail:
-  retc->size = 0;
-  retc->x.str_val = emalloc(0);
-ret:
-  RSA_free(rsa);
-  free(sig);
+  gcry_mpi_release(p);
+  gcry_mpi_release(g);
+  gcry_mpi_release(q);
+  gcry_mpi_release(pub);
+  gcry_mpi_release(priv);
+  gcry_mpi_release(data);
+  gcry_mpi_release(r);
+  gcry_mpi_release(s);
+  gcry_sexp_release(ssig);
+  gcry_sexp_release(skey);
+  gcry_sexp_release(sdata);
+  efree(&sigblob);
+
   return retc;
 }
 
-
-tree_cell * nasl_bf_cbc(lex_ctxt* lexic, int enc)
+/* Implements the nasl functions bf_cbc_encrypt and bf_cbc_decrypt. */
+tree_cell *
+nasl_bf_cbc(lex_ctxt* lexic, int enc)
 {
-  char *enckey = NULL,*iv = NULL,*data = NULL,*out = NULL;
-  tree_cell    *retc = NULL;
+  tree_cell *retc = NULL;
+  char *enckey = NULL, *iv = NULL, *data = NULL, *out = NULL;
   long enckeylen, ivlen, datalen;
-  BF_KEY key;
+  gcry_cipher_hd_t hd = NULL;
   anon_nasl_var        v;
   nasl_array   *a;
+  gcry_error_t err;
 
   retc = alloc_tree_cell(0, NULL);
   retc->type = CONST_DATA;
- 
-  /* sig bignum */
+
+  /* key */
   enckey = get_str_local_var_by_name(lexic, "key");
   enckeylen = get_var_size_by_name(lexic, "key");
 
+  /* initialization vector */
   iv = get_str_local_var_by_name(lexic, "iv");
   ivlen = get_var_size_by_name(lexic, "iv");
 
+  /* data to decrypt/encrypt*/
   data = get_str_local_var_by_name(lexic, "data");
   datalen = get_var_size_by_name(lexic, "data");
 
   if ( enckey == NULL || data == NULL || iv == NULL )
        goto fail;
+  if (enckeylen != 16)
+    {
+      /* key length must be 16 for compatibility with libnasl code from
+       * before the OpenSSL -> GnuTLS migration */
+      nasl_perror(lexic, "nasl_bf_cbc: unexpected enckeylen = %d; must be 
16\n",
+                 enckeylen);
+      goto fail;
+    }
+  if (ivlen < 8)
+    {
+      nasl_perror(lexic, "nasl_bf_cbc: unexpected ivlen = %d; must >= 8\n",
+                 ivlen);
+      goto fail;
+    }
+  if (datalen < 8)
+    {
+      nasl_perror(lexic, "nasl_bf_cbc: unexpected datalen = %d; must >= 8\n",
+                 datalen);
+      goto fail;
+    }
 
-  /* key len = 16 : { "blowfish-cbc",  SSH_CIPHER_SSH2, 8, 16, EVP_bf_cbc }*/
-  BF_set_key(&key, 16, (unsigned char*)enckey);
+  err = gcry_cipher_open(&hd, GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC, 0);
+  if (err)
+    {
+      print_gcrypt_error(lexic, "gcry_cipher_open", err);
+      goto fail;
+    }
 
+  err = gcry_cipher_setkey(hd, enckey, enckeylen);
+  if (err)
+    {
+      print_gcrypt_error(lexic, "gcry_cipher_setkey", err);
+      goto fail;
+    }
+  err = gcry_cipher_setiv(hd, iv, ivlen);
+  if (err)
+    {
+      print_gcrypt_error(lexic, "gcry_cipher_setiv", err);
+      goto fail;
+    }
+
   out = emalloc(datalen);
   if (!out)
     goto fail;
 
-  BF_cbc_encrypt((unsigned char*)data, (unsigned char*)out, datalen, &key, 
(unsigned char*)iv, enc);
+  if (enc)
+    err = gcry_cipher_encrypt(hd, out, datalen, data, datalen);
+  else
+    err = gcry_cipher_decrypt(hd, out, datalen, data, datalen);
+  if (err)
+    {
+      print_gcrypt_error(lexic, "gcry_cipher_encrypt", err);
+      goto fail;
+    }
 
   retc->type = DYN_ARRAY;
   retc->x.ref_val = a = emalloc(sizeof(nasl_array));
@@ -562,395 +1100,308 @@
   v.v.v_str.s_siz = datalen;
   v.v.v_str.s_val = (unsigned char*)out;
   (void) add_var_to_list(a, 0, &v);
-  free(out);
 
   /* second iv */
+  /* the iv to use to for the next part of the data is always the last
+   * eight bytes of the cipher text.  When encrypting the cipher text is
+   * in out when decrypting it's in data.
+   */
   v.var_type = VAR2_DATA;
-  v.v.v_str.s_siz = ivlen;
-  v.v.v_str.s_val = (unsigned char*)iv;
+  v.v.v_str.s_siz = 8;
+  v.v.v_str.s_val = (unsigned char*)((enc ? out : data) + datalen - 8);
   (void) add_var_to_list(a, 1, &v);
 
   goto ret;
 
-fail:
+ fail:
   retc->type = CONST_DATA;
   retc->x.str_val = emalloc(0);
   retc->size = 0;
-ret:
+
+ ret:
+  efree(&out);
+  gcry_cipher_close(hd);
+
   return retc;
 }
 
 
-tree_cell * nasl_dsa_do_verify(lex_ctxt* lexic)
+/* nasl function
+ *
+ *   bf_cbc_encrypt(key:key, iv:iv, data:data)
+ *
+ * Encrypt the plain text data using the blowfish algorithm in CBC mode
+ * with the key key and the initialization vector iv.  The key must be
+ * 16 bytes long.  The iv must be at least 8 bytes long.  data must be a
+ * multiple of 8 bytes long.
+ *
+ * The return value is an array a with a[0] being the encrypted data and
+ * a[1] the new initialization vector to use for the next part of the
+ * data.
+ */
+tree_cell *
+nasl_bf_cbc_encrypt(lex_ctxt* lexic)
 {
-  char *p = NULL,*g = NULL,*q = NULL, *pub = NULL,*r = NULL,*s = NULL;
-  char * data = NULL;
-  tree_cell    *retc = NULL;
-  DSA *dsa = NULL;
-  DSA_SIG * sig = NULL;
-  long plen, glen, qlen, publen, rlen, slen, datalen;
-
-  retc = emalloc(sizeof(tree_cell));
-  retc->ref_count = 1;
-  retc->type = CONST_INT;
-  retc->x.i_val = 0;
- 
-  /* p bignum */
-  p = get_str_local_var_by_name(lexic, "p");
-  plen = get_var_size_by_name(lexic, "p");
-  
-  /* g bignum */
-  g = get_str_local_var_by_name(lexic, "g");
-  glen = get_var_size_by_name(lexic, "g");
-
-  /* q bignum */
-  q = get_str_local_var_by_name(lexic, "q");
-  qlen = get_var_size_by_name(lexic, "q");
-
-  /* pub bignum */
-  pub = get_str_local_var_by_name(lexic, "pub");
-  publen = get_var_size_by_name(lexic, "pub");
-
-  /* r bignum */
-  r = get_str_local_var_by_name(lexic, "r");
-  rlen = get_var_size_by_name(lexic, "r");
-
-  /* s bignum */
-  s = get_str_local_var_by_name(lexic, "s");
-  slen = get_var_size_by_name(lexic, "s");
-
-  /* data */
-  data = get_str_local_var_by_name(lexic, "data");
-  datalen = get_var_size_by_name(lexic, "data");
-  if  ( p == NULL || g == NULL || q == NULL || pub == NULL || r == NULL || s 
== NULL )
-       goto fail;
-
-  if ((dsa = DSA_new()) == NULL)
-    goto fail;
-  
-  if ((sig = DSA_SIG_new()) == NULL)
-    goto fail;
-  
-  if (BN_bin2bn((const unsigned char*)p, plen, dsa->p) == 0)
-     goto fail;
-  if (BN_bin2bn((const unsigned char*)g, glen, dsa->g) == 0)
-     goto fail;
-  if (BN_bin2bn((const unsigned char*)q, qlen, dsa->q) == 0)
-     goto fail;
-  if (BN_bin2bn((const unsigned char*)pub, publen, dsa->pub_key) == 0)
-     goto fail;
-  if (BN_bin2bn((const unsigned char*)r, rlen, sig->r) == 0)
-     goto fail;
-  if (BN_bin2bn((const unsigned char*)s, slen, sig->s) == 0)
-     goto fail;
-
-  if (DSA_do_verify((unsigned char*)data, datalen, sig, dsa))
-     retc->x.i_val = 1;
-  
-fail:
-  DSA_free(dsa);
-  DSA_SIG_free(sig);
-  return retc;
+  return nasl_bf_cbc(lexic, 1);
 }
 
 
-tree_cell * nasl_dsa_do_sign(lex_ctxt* lexic)
+/* nasl function
+ *
+ *   bf_cbc_decrypt(key:key, iv:iv, data:data)
+ *
+ * Decrypt the cipher text data using the blowfish algorithm in CBC mode
+ * with the key key and the initialization vector iv.  The key must be
+ * 16 bytes long.  The iv must be at least 8 bytes long.  data must be a
+ * multiple of 8 bytes long.
+ *
+ * The return value is an array a with a[0] being the plain text data
+ * and a[1] the new initialization vector to use for the next part of
+ * the data.
+ */
+tree_cell *
+nasl_bf_cbc_decrypt(lex_ctxt* lexic)
 {
-  char *p = NULL,*g = NULL,*q = NULL, *pub = NULL,*priv = NULL;
-  char * data = NULL;
-  tree_cell    *retc = NULL;
-  DSA *dsa = NULL;
-  DSA_SIG * sig = NULL;
-  char *sigblob;
-  long plen, glen, qlen, publen, privlen, rlen, slen, datalen;
+  return nasl_bf_cbc(lexic, 0);
+}
 
 
-  if ( check_authenticated(lexic) < 0 ) return FAKE_CELL;
+/*--------------------------------------------------------------*/
 
-  retc = emalloc(sizeof(tree_cell));
-  retc->ref_count = 1;
-  retc->type = CONST_DATA;
-  retc->x.i_val = 0;
- 
-  /* p bignum */
-  p = get_str_local_var_by_name(lexic, "p");
-  plen = get_var_size_by_name(lexic, "p");
-  
-  /* g bignum */
-  g = get_str_local_var_by_name(lexic, "g");
-  glen = get_var_size_by_name(lexic, "g");
+/* Reads the contents of the file given by filename into memory and
+ * returns it as a gnutls_datum_t.  If an error occurs the
+ * gnutls_datum_t's data field is NULL.
+ */
+gnutls_datum_t
+map_file(const char * filename)
+{
+  struct stat st;
+  int fd = -1;
+  char * map;
+  gnutls_datum_t contents = {NULL, 0};
 
-  /* q bignum */
-  q = get_str_local_var_by_name(lexic, "q");
-  qlen = get_var_size_by_name(lexic, "q");
-
-  /* pub bignum */
-  pub = get_str_local_var_by_name(lexic, "pub");
-  publen = get_var_size_by_name(lexic, "pub");
-
-  /* r bignum */
-  priv = get_str_local_var_by_name(lexic, "priv");
-  privlen = get_var_size_by_name(lexic, "priv");
-
-  /* data */
-  data = get_str_local_var_by_name(lexic, "data");
-  datalen = get_var_size_by_name(lexic, "data");
-
-  if ( p == NULL || g == NULL || q == NULL || pub == NULL || priv == NULL || 
data == NULL )
-       goto fail;
-
-  if ((dsa = DSA_new()) == NULL)
+  fd = open(filename, O_RDONLY);
+  if (fd < 0)
     goto fail;
-  
-  if ((sig = DSA_SIG_new()) == NULL)
+  if (fstat(fd, &st) < 0)
     goto fail;
 
-  dsa->p = BN_new();
-  dsa->g = BN_new();
-  dsa->q = BN_new();
-  dsa->pub_key = BN_new();
-  dsa->priv_key = BN_new();
-  
-  if (BN_bin2bn((const unsigned char*)p, plen, dsa->p) == 0)
-     goto fail;
-  if (BN_bin2bn((const unsigned char*)g, glen, dsa->g) == 0)
-     goto fail;
-  if (BN_bin2bn((const unsigned char*)q, qlen, dsa->q) == 0)
-     goto fail;
-  if (BN_bin2bn((const unsigned char*)pub, publen, dsa->pub_key) == 0)
-     goto fail;
-  if (BN_bin2bn((const unsigned char*)priv, privlen, dsa->priv_key) == 0)
-     goto fail;
+  map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+  if (map == NULL || map == MAP_FAILED)
+    goto fail;
 
-  sig = DSA_do_sign((unsigned char*)data, datalen, dsa);
-  if (!sig)
-    goto fail;  
+  contents.data = (unsigned char*)nasl_strndup(map, st.st_size);
+  contents.size = st.st_size;
+  munmap(map, st.st_size);
 
-  sigblob = emalloc(SIGBLOB_LEN);
-  memset(sigblob, 0, SIGBLOB_LEN);
-  rlen = BN_num_bytes(sig->r);
-  slen = BN_num_bytes(sig->s);
-
-  if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN)
-    goto fail;
-
-  BN_bn2bin(sig->r, (unsigned char*)(sigblob+ SIGBLOB_LEN - INTBLOB_LEN - 
rlen));
-  BN_bn2bin(sig->s, (unsigned char*)(sigblob+ SIGBLOB_LEN - slen));
-  
-  retc->x.str_val = sigblob;
-  retc->size = SIGBLOB_LEN;
-  
-fail:
-  DSA_free(dsa);
-  DSA_SIG_free(sig);
-  return retc;
+ fail:
+  if (fd >= 0)
+    close(fd);
+  return contents;
 }
 
 
-tree_cell * nasl_bf_cbc_encrypt(lex_ctxt* lexic)
-{
-  return nasl_bf_cbc(lexic, BF_ENCRYPT);
-}
+/*----------------------------- Script signature management 
------------------------------------------*/
 
-
-tree_cell * nasl_bf_cbc_decrypt(lex_ctxt* lexic)
+/* 
+ * Signs a given script
+ */
+int
+generate_signed_script(char * filename)
 {
-  return nasl_bf_cbc(lexic, BF_DECRYPT);
-}
+  const char * pemfilename = NESSUS_STATE_DIR "/openvas/openvas_org.priv.pem";
+  int result = -1;
+  int i;
+  int be_len;
+  gnutls_datum_t pem = {NULL, 0};
+  gnutls_datum_t script = {NULL, 0};
+  gnutls_x509_privkey_t privkey = NULL;
+  unsigned char* signature = NULL;
+  size_t signature_size = 0;
+  int err;
 
+  err = gnutls_x509_privkey_init(&privkey);
+  if (err)
+    {
+      print_tls_error(NULL, "gnutls_x509_privkey_init", err);
+      goto fail;
+    }
 
-/*--------------------------------------------------------------*/
+  pem = map_file(pemfilename);
+  if (!pem.data)
+    goto fail;
 
-char * map_file(char * filename, int * len) 
-{
- struct stat st;
- int fd;
- char * map, * ret;
+  err = gnutls_x509_privkey_import(privkey, &pem, GNUTLS_X509_FMT_PEM);
+  if (err)
+    {
+      print_tls_error(NULL, "gnutls_x509_privkey_import", err);
+      goto fail;
+    }
 
- fd = open(filename, O_RDONLY);
- if ( fd < 0 ) return NULL;
- if ( fstat(fd, &st) < 0 )
- {
-  close(fd);
-  return NULL;
- }
+  script = map_file(filename);
+  if (!script.data)
+    {
+      goto fail;
+    }
 
- map = mmap ( NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0 );
- if ( map == NULL || map == MAP_FAILED ) 
-       {
-       close(fd);
-       return NULL;
-       }
+  /* append the size of the file at the end of the script */
+  script.data = erealloc(script.data, script.size + sizeof(be_len));
+  be_len = htonl(script.size);
+  memcpy(script.data + script.size, &be_len, sizeof(be_len));
+  script.size += sizeof(be_len);
 
+  /* call gnutls_x509_privkey_sign_data twice: once to determine the
+   * size of the signature and then again to actually create the
+   * signature */
+  err = gnutls_x509_privkey_sign_data(privkey, GNUTLS_DIG_SHA1, 0, &script,
+                                     signature, &signature_size);
+  if (err != GNUTLS_E_SHORT_MEMORY_BUFFER)
+    {
+      print_tls_error(NULL, "gnutls_x509_privkey_sign_data", err);
+      goto fail;
+    }
 
- ret = nasl_strndup(map, st.st_size);
- munmap(map, st.st_size);
- close(fd);
- *len = st.st_size;
- return ret;
-}
+  signature = emalloc(signature_size);
+  err = gnutls_x509_privkey_sign_data(privkey, GNUTLS_DIG_SHA1, 0, &script,
+                                     signature, &signature_size);
+  if (err)
+    {
+      print_tls_error(NULL, "gnutls_x509_privkey_sign_data", err);
+      goto fail;
+    }
 
+  /* print the header with the signature */
+  printf("#TRUSTED ");
+  for (i = 0; i < signature_size; i++)
+    {
+      printf("%.2x", signature[i]);
+    }
+  printf("\n");
 
-/*----------------------------- Script signature management 
------------------------------------------*/
+  /* strip the size from the end of the script again */
+  script.size -= sizeof(be_len);
+  memset(script.data + script.size, 0, sizeof(be_len));
 
-/* 
- * Signs a given script
- */
-int generate_signed_script(char * filename)
-{
- RSA * rsa = NULL;
- FILE * fp = fopen(NESSUS_STATE_DIR "/nessus/nessus_org.priv.pem", "r");
- unsigned char  * result;
- unsigned int len;
- int i;
- char md[SHA_DIGEST_LENGTH+1];
- int be_len;
+  /* print the script itself */
+  printf("%s", script.data);
+  fflush(stdout);
 
- char * msg;
- int  msg_len;
+  result = 0;
 
+ fail:
+  efree(&pem.data);
+  efree(&script.data);
+  efree(&signature);
+  gnutls_x509_privkey_deinit(privkey);
 
- msg = map_file(filename, &msg_len);
- if ( msg == NULL ) {
-       perror("mmap ");
-       exit(0);
-       }
+  return result;
+}
 
- /* Append the size of the file at the end of the message */
- msg = erealloc(msg, msg_len + sizeof(msg_len));
- be_len = htonl(msg_len);
- memcpy(msg + msg_len, &be_len, sizeof(msg_len));
+/* Decodes a sequence of hexadecimal numbers. */
+static ptrdiff_t
+hexdecode(unsigned char *to, const unsigned char * from)
+{
+  char temp[3] = {0, 0, 0};
+  unsigned char * start = to;
 
+  while (from[0] && from[1])
+    {
+      temp[0] = from[0];
+      temp[1] = from[1];
+      *to = strtoul(temp, NULL, 16);
+      to += 1;
+      from += 2;
+    }
 
-
- SHA1((unsigned char*)msg, msg_len + sizeof(msg_len), (unsigned char*)md);
- if ( fp == NULL ) 
-       {
-       perror("open ");
-       return -1;
-       }
- 
- rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
- fclose(fp);
- if ( rsa == NULL ) 
-       {
-       fprintf(stderr, "PEM_read_RSAPrivateKey() failed\n");
-       return -1;
-       }
-
- len = RSA_size(rsa);
- result = emalloc(len);
-       
- RSA_sign(NID_sha1, (unsigned char*)md, SHA_DIGEST_LENGTH, (unsigned 
char*)result, &len, rsa);
- printf("#TRUSTED ");
- for ( i = 0 ; i < len ; i ++ )
- {
-  printf("%.2x", result[i]);
- }
- printf("\n", len);
- memset(msg + msg_len, 0, sizeof(msg_len));
- printf("%s", msg);
- fflush(stdout);
- efree(&msg);
- efree(&result);
- RSA_free(rsa);
- 
- return 0;
+  return to - start;
 }
 
- 
-/* 
+/*
  * Verify a script signature
  *
+ * In the original OpenSSL based code the public key was stored in a
+ * format that GnuTLS cannot read.  The new code requires a real x509
+ * certificate.
+ *
  * Returns :
  *     -1 : if an error occured
  *      0 : if the signature matches
  *      1 : if the signature does NOT match
  */
-int verify_script_signature(char * filename)
+int
+verify_script_signature(char * filename)
 {
- char * msg;
- int msg_len;
- char * t;
- unsigned char md[SHA_DIGEST_LENGTH+1];
- RSA * rsa = NULL;
- FILE * fp = fopen(NESSUS_STATE_DIR "/nessus/nessus_org.pem", "r");
- char sig[16384];
- unsigned char bin_sig[8192];
- int binsz = 0;
- int i;
- int sig_len = 0;
- int res = -1;
- int be_len;
+  const char * pemfilename = NESSUS_STATE_DIR "/openvas/openvas_org.pem";
+  char * t;
+  int be_len;
+  gnutls_x509_crt_t cert = NULL;
+  gnutls_datum_t pem = {NULL, 0};
+  gnutls_datum_t script = {NULL, 0};
+  gnutls_datum_t data_to_hash;
+  gnutls_datum_t signature;
+  int result = -1;
+  int err;
 
+  pem = map_file(pemfilename);
+  if (!pem.data)
+    goto fail;
 
- if ( fp == NULL )
- {
-  fprintf(stderr, "Open %s/nessus/nessus_org.pem : %s\n", NESSUS_STATE_DIR, 
strerror(errno));
-  return -1;
- }
+  err = gnutls_x509_crt_init(&cert);
+  if (err)
+    {
+      print_tls_error(NULL, "gnutls_x509_crt_init", err);
+      goto fail;
+    }
 
+  err = gnutls_x509_crt_import(cert, &pem, GNUTLS_X509_FMT_PEM);
+  if (err)
+    {
+      print_tls_error(NULL, "gnutls_x509_crt_import", err);
+      goto fail;
+    }
 
- rsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
- fclose(fp);
- if ( rsa == NULL ) return -1;
+    script = map_file(filename);
+  if (!script.data)
+    {
+      goto fail;
+    }
 
- msg = map_file(filename, &msg_len);
- if ( msg == NULL ) return -1;
+  /* Make room for the size of the file at the end of the script */
+  script.data = erealloc(script.data, script.size + sizeof(be_len));
 
- msg = erealloc(msg, msg_len + sizeof(msg_len));
- 
- t = strchr(msg, '\n');
- if ( t == NULL ) goto err; 
- t[0] = '\0'; t ++;
- strncpy(sig, msg + strlen("#TRUSTED "), sizeof(sig) - 1 );
- sig[sizeof(sig) - 1] = '\0'; 
+  /* split the script into the signature (first line) and the rest */
+  t = strchr((char*)script.data, '\n');
+  if (t == NULL)
+    goto fail;
+  t[0] = '\0'; t++;
 
- /* Append the size of the message at the end of it */
- msg_len = msg_len - ( (int)t - (int)msg);
- be_len = htonl(msg_len);
- memcpy(t + msg_len, &be_len, sizeof(msg_len));
+  /* The data to hash is the rest with the size of the rest appended */
+  data_to_hash.data = (unsigned char*)t;
+  data_to_hash.size = script.size - (data_to_hash.data - script.data);
+  be_len = htonl(data_to_hash.size);
+  memcpy(data_to_hash.data + data_to_hash.size, &be_len, sizeof(be_len));
+  data_to_hash.size += sizeof(be_len);
 
- SHA1((unsigned char*)t, msg_len + sizeof(msg_len), md);
+  /* decode the hex signature.  We can do it in place because the binary
+   * signature is always shorter than it's hexadecimal
+   * representation. Also, the caller has already checked that the
+   * script starts with "#TRUSTED", so we can simply skip it here */
+  signature.data = script.data;
+  signature.size = hexdecode(signature.data, script.data + strlen("#TRUSTED 
"));
 
- sig_len = strlen(sig);
+  err = gnutls_x509_crt_verify_data(cert, 0, &data_to_hash, &signature);
+  if (err < 0)
+    {
+      print_tls_error(NULL, "gnutls_x509_crt_verify_data", err);
+      goto fail;
+    }
 
- for ( i = 0 ; i < sig_len ; i += 2 )
- {
-  char t[3];
-  strncpy(t, sig + i, 2);
-  t[2] = '\0';
-  bin_sig[binsz] = strtoul(t, NULL, 16);
-  binsz ++; 
-  if ( binsz >= sizeof(bin_sig) ) goto err; /* Too long signature */
- }
- 
- 
+  result = err == 1 ? 0 : 1;
 
- res = RSA_verify(NID_sha1, md, SHA_DIGEST_LENGTH, bin_sig, binsz, rsa);
- RSA_free(rsa);
- efree(&msg);
- return res == 1 ? 0 : 1;
- 
-err:
-  RSA_free(rsa);
-  efree(&msg);
-  return -1;
- 
-}
+ fail:
+  gnutls_x509_crt_deinit(cert);
+  efree(&script.data);
+  efree(&pem);
 
-#else
-
-int generate_signed_script( char * filename ) 
-{
- fprintf(stderr, "generate_script_signature() called without OpenSSL support 
!\n");
- return -1;
+  return result;
 }
-
-
-int verify_script_signature( char * filename ) 
-{
- fprintf(stderr, "verify_script_signature() called without OpenSSL support 
!\n");
- return -1;
-}
-#endif

_______________________________________________
Openvas-commits mailing list
[email protected]
http://lists.wald.intevation.org/mailman/listinfo/openvas-commits

Reply via email to