Author: bh
Date: 2007-07-18 16:10:27 +0200 (Wed, 18 Jul 2007)
New Revision: 272

Modified:
   trunk/openvas-server/ChangeLog
   trunk/openvas-server/openvasd/openvas-check-signature.c
Log:
* openvasd/openvas-check-signature.c: Use GnuTLS instead of
OpenSSL.  See comments in the file for things that could be done
better.
(print_tls_error, map_file, hexdecode): New.  Helper functions.
(generate_signature, verify_signature): Use GnuTLS instead of
OpenSSL.  Also, both functions now have an additional parameter
for the keyfile/certfile to use so that their filenames are no
longer hard wired.
(main): Add command line arguments to specifiy the key or
certificat to use when signing or verifying.  Pass those filenames
to generate_signature and verify_signature.


Modified: trunk/openvas-server/ChangeLog
===================================================================
--- trunk/openvas-server/ChangeLog      2007-07-17 19:06:10 UTC (rev 271)
+++ trunk/openvas-server/ChangeLog      2007-07-18 14:10:27 UTC (rev 272)
@@ -1,3 +1,17 @@
+2007-07-18  Bernhard Herzog  <[EMAIL PROTECTED]>
+
+       * openvasd/openvas-check-signature.c: Use GnuTLS instead of
+       OpenSSL.  See comments in the file for things that could be done
+       better.
+       (print_tls_error, map_file, hexdecode): New.  Helper functions.
+       (generate_signature, verify_signature): Use GnuTLS instead of
+       OpenSSL.  Also, both functions now have an additional parameter
+       for the keyfile/certfile to use so that their filenames are no
+       longer hard wired.
+       (main): Add command line arguments to specifiy the key or
+       certificat to use when signing or verifying.  Pass those filenames
+       to generate_signature and verify_signature.
+
 2007-07-04  Bernhard Herzog  <[EMAIL PROTECTED]>
 
        * openvasd/plugs_hash.c (plugins_hash): Handle errors from

Modified: trunk/openvas-server/openvasd/openvas-check-signature.c
===================================================================
--- trunk/openvas-server/openvasd/openvas-check-signature.c     2007-07-17 
19:06:10 UTC (rev 271)
+++ trunk/openvas-server/openvasd/openvas-check-signature.c     2007-07-18 
14:10:27 UTC (rev 272)
@@ -27,89 +27,159 @@
 *
 */
 
+/* FIXME: The code here is mostly a duplicate of code in
+ * openvas-libnasl/nasl/nasl_crypto2.c.  The main difference is that the
+ * signatures dealt with here are detached, whereas the signatures
+ * handled by nasl_crypto2.c are part of the signed file.
+ *
+ * Also, the original OpenSSL code in this file was probably better at
+ * handling larger files.  The new code read the file to sign or verify
+ * completely into memory which may be inefficient for large files.
+ *
+ * Before something is done about it, OpenVAS needs to decide how to
+ * deal with signed files in general.
+ */
+
 #include <includes.h>
-#ifdef HAVE_SSL
-#include <openssl/bn.h>
-#include <openssl/dh.h>
-#include <openssl/evp.h>
-#include <openssl/blowfish.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
 
 
-/* 
+void
+print_tls_error(char *txt, int err)
+{
+  fprintf(stderr, "%s: %s (%d)\n", txt, gnutls_strerror(err), err);
+}
+
+gnutls_datum_t
+map_file(const char * filename)
+{
+  FILE *f;
+  gnutls_datum loaded_file = { NULL, 0 };
+  long filelen;
+  void *ptr;
+
+  if (!(f = fopen(filename, "r"))
+      || fseek(f, 0, SEEK_END) != 0
+      || (filelen = ftell(f)) < 0
+      || fseek(f, 0, SEEK_SET) != 0
+      || !(ptr = emalloc((size_t) filelen))
+      || fread(ptr, 1, (size_t) filelen, f) < (size_t) filelen)
+    {
+      return loaded_file;
+    }
+
+  loaded_file.data = ptr;
+  loaded_file.size = (unsigned int) filelen;
+  return loaded_file;
+}
+
+static ptrdiff_t
+hexdecode(unsigned char *binary, const unsigned char *hex, size_t fromlen)
+{
+  char temp[3] = {0, 0, 0};
+  unsigned char * to = binary;
+  const unsigned char * from = hex;
+
+  while ((from - hex) < fromlen - 1)
+    {
+      temp[0] = from[0];
+      temp[1] = from[1];
+      *to = strtoul(temp, NULL, 16);
+      to += 1;
+      from += 2;
+    }
+
+  return to - binary;
+}
+
+
+/*
  * Signs a given file
  */
-int generate_signature(char * filename)
+static int
+generate_signature(char * keyfilename, char * filename)
 {
- RSA * rsa = NULL;
- FILE * fp = fopen(OPENVASD_STATEDIR "/openvas_org.priv.pem", "r");
- unsigned char  * result;
- unsigned int len;
- int i;
- unsigned char md[SHA_DIGEST_LENGTH+1];
- int be_len;
+  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;
 
- SHA_CTX ctx;
- int fd;
- int n;
- char buf[1024];
- struct stat st;
+  err = gnutls_x509_privkey_init(&privkey);
+  if (err)
+    {
+      print_tls_error("gnutls_x509_privkey_init", err);
+      goto fail;
+    }
 
+  pem = map_file(keyfilename);
+  if (!pem.data)
+    goto fail;
 
- SHA1_Init(&ctx);
+  err = gnutls_x509_privkey_import(privkey, &pem, GNUTLS_X509_FMT_PEM);
+  if (err)
+    {
+      print_tls_error("gnutls_x509_privkey_import", err);
+      goto fail;
+    }
 
- fd = open(filename, O_RDONLY);
- if ( fd < 0 ) 
- {
-  fprintf(stderr, "open(%s) : %s\n", filename, strerror(errno));
-  return -1;
- }
+  script = map_file(filename);
+  if (!script.data)
+    {
+      goto fail;
+    }
 
- fstat(fd, &st);
- bzero(buf, sizeof(buf));
- while ( ( n = read(fd, buf, sizeof(buf))) > 0 )
- {
-  SHA1_Update(&ctx, buf, n);
- } 
- /* Add the size of the file at the end of the message */
- be_len = htonl(st.st_size);
- SHA1_Update(&ctx, &be_len, sizeof(be_len));
- SHA1_Final(md, &ctx);
- close(fd);
- 
+  /* 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("gnutls_x509_privkey_sign_data", err);
+      goto fail;
+    }
 
- 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;
-       }
+  signature = emalloc(signature_size);
+  err = gnutls_x509_privkey_sign_data(privkey, GNUTLS_DIG_SHA1, 0, &script,
+                                     signature, &signature_size);
+  if (err)
+    {
+      print_tls_error("gnutls_x509_privkey_sign_data", err);
+      goto fail;
+    }
 
- len = RSA_size(rsa);
- result = emalloc(len);
-       
- RSA_sign(NID_sha1, md, SHA_DIGEST_LENGTH, result, &len, rsa);
- for ( i = 0 ; i < len ; i ++ )
- {
-  printf("%.2x", result[i]);
- }
- printf("\n");
- fflush(stdout);
- efree(&result);
- RSA_free(rsa);
- 
- return 0;
+  /* print the signature to stdout in hexadecimal */
+  for (i = 0; i < signature_size; i++)
+    {
+      printf("%.2x", signature[i]);
+    }
+  printf("\n");
+
+  result = 0;
+
+ fail:
+  efree(&pem.data);
+  efree(&script.data);
+  efree(&signature);
+  gnutls_x509_privkey_deinit(privkey);
+
+  return result;
 }
 
- 
-/* 
+
+/*
  * Verify an archive signature
  *
  * Returns :
@@ -117,128 +187,189 @@
  *      0 : if the signature matches
  *      1 : if the signature does NOT match
  */
-int verify_signature(char * filename, char * signature)
+static int
+verify_signature(char * certfilename, char * filename, char * sigfilename)
 {
- unsigned char md[SHA_DIGEST_LENGTH+1];
- RSA * rsa = NULL;
- FILE * fp = fopen(OPENVASD_STATEDIR "/openvas_org.pem", "r");
+  int be_len;
+  gnutls_x509_crt_t cert = NULL;
+  gnutls_datum_t pem = {NULL, 0};
+  gnutls_datum_t script = {NULL, 0};
+  gnutls_datum_t signature = {NULL, 0};
+  int result = -1;
+  int err;
 
- char sig[16384];
- unsigned char bin_sig[8192];
- int binsz = 0;
+  pem = map_file(certfilename);
+  if (!pem.data)
+    goto fail;
 
- int i, sig_len = 0, res = -1, be_len;
- FILE * sigfile = fopen(signature, "r");
+  err = gnutls_x509_crt_init(&cert);
+  if (err)
+    {
+      print_tls_error("gnutls_x509_crt_init", err);
+      goto fail;
+    }
 
- SHA_CTX ctx;
- struct stat st;
- int fd;
- char buf[1024];
- int n;
+  err = gnutls_x509_crt_import(cert, &pem, GNUTLS_X509_FMT_PEM);
+  if (err)
+    {
+      print_tls_error("gnutls_x509_crt_import", err);
+      goto fail;
+    }
 
+  script = map_file(filename);
+  if (!script.data)
+    {
+      goto fail;
+    }
 
- if ( fp == NULL )
- {
-  fprintf(stderr, "Open %s/openvas_org.pem : %s\n", OPENVASD_STATEDIR, 
strerror(errno));
-  return -1;
- }
+  /* Make room for the size of the file at the end of the script and
+   * append the size */
+  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);
 
- /* No signature - fail */
- if ( sigfile == NULL )
- {
-  fprintf(stderr, "Open %s : %s\n", signature, strerror(errno));
-  return 1;
- }
+  /* read and decode the hex signature.  Decoding can be done in place
+   * because the binary signature is always shorter than its hexadecimal
+   * representation. */
+  signature = map_file(sigfilename);
+  if (!signature.data)
+    {
+      goto fail;
+    }
+  signature.size = hexdecode(signature.data, signature.data, signature.size);
 
- fgets(sig, sizeof(sig) - 1, sigfile);
- fclose(sigfile);
- sig[sizeof(sig) - 1] = '\0';
+  err = gnutls_x509_crt_verify_data(cert, 0, &script, &signature);
+  if (err < 0)
+    {
+      print_tls_error("gnutls_x509_crt_verify_data", err);
+      goto fail;
+    }
 
+  result = err == 1 ? 0 : 1;
 
- fd = open(filename, O_RDONLY);
- if ( fd < 0 )
- {
-  fprintf(stderr, "open(%s) : %s\n", filename, strerror(errno));
-  return 1;
- } 
- 
+ fail:
+  gnutls_x509_crt_deinit(cert);
+  efree(&script.data);
+  efree(&signature.data);
+  efree(&pem);
 
- fstat(fd, &st);
- SHA1_Init(&ctx);
- bzero(buf, sizeof(buf));
- while ( ( n = read(fd, buf, sizeof(buf)) ) > 0 )
- {
-  SHA1_Update(&ctx, buf, n); 
- }
+  return result;
 
- be_len = htonl(st.st_size);
- SHA1_Update(&ctx, &be_len, sizeof(be_len));
- SHA1_Final(md, &ctx);
- close(fd);
+}
 
- rsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
- fclose(fp);
- if ( rsa == NULL ) return -1;
 
+int
+main(int argc, char ** argv)
+{
+  int do_sign = 0;
+  int do_print_usage = 0;
+  char * keyfile = NULL;
+  char * certfile = NULL;
+  int opt;
+  int option_index = 0;
+  struct option long_options[] =
+    {
+      {"help",         no_argument,       0, 'h'},
+      {"certificate",   required_argument, 0, 'c'},
+      {"key",           required_argument, 0, 'k'},
+      {"sign",         no_argument,       0, 's'},
+      {0, 0, 0, 0}
+    };
 
- sig_len = strlen(sig) - 1;
+  while ((opt = getopt_long(argc, argv, "c:hk:s", long_options, &option_index))
+        != -1)
+    {
+      switch (opt)
+       {
+       case 'c':
+         certfile = optarg;
+         break;
 
- 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 */
- }
- 
- 
+       case 'h':
+         do_print_usage = 1;
+         break;
 
- res = RSA_verify(NID_sha1, md, SHA_DIGEST_LENGTH, bin_sig, binsz, rsa);
- RSA_free(rsa);
- return res == 1 ? 0 : 1;
- 
-err:
-  RSA_free(rsa);
-  return -1;
- 
-}
+       case 'k':
+         keyfile = optarg;
+         break;
 
+       case 's':
+         do_sign = 1;
+         break;
 
-int main(int argc, char ** argv)
-{
- int do_sign = 0; 
- if ( argc != 3 )
- {
-  fprintf(stderr, "Usage: openvas-check-signature [-S] filename 
[signaturefile]\n");
-  exit(1);
- }
+       case '?':
+         fprintf(stderr, "unknown option or missing"
+                 " parameter for option '%c'\n", opt);
+         return 1;
 
- nessus_SSL_init(NULL);
+       default:
+         fprintf(stderr, "option '%c' not implemented\n", opt);
+         return 1;
+       }
+    }
 
- if ( strcmp(argv[1], "-S") == 0 )
-       do_sign ++;
+  if (do_print_usage)
+    {
+      fprintf(stderr,
+             "Usage: openvas-check-signature [options]"
+             " filename [signaturefile]\n");
+      fprintf(stderr, "Options:\n");
+      fprintf(stderr, " -h           Print this help message\n");
+      fprintf(stderr, " -k keyfile   File with private key for signature\n");
+      fprintf(stderr, " -c certfile  File with certificate for signature"
+             " verificationi\n");
+      return 0;
+    }
 
- if ( do_sign == 0 )
- {
-  if  ( verify_signature(argv[1], argv[2]) <= 0 )
-       exit(0);
+  nessus_SSL_init(NULL);
+
+  if (do_sign)
+    {
+      if (!keyfile)
+       {
+         fprintf(stderr, "Missing parameter -k required for"
+                 " signature generation\n");
+         return 1;
+       }
+      if (optind >= argc)
+       {
+         fprintf(stderr, "missing filename parameter\n");
+         return 1;
+       }
+
+      generate_signature(keyfile, argv[optind]);
+    }
   else
+    {
+      if (!certfile)
        {
-       printf("%s is not the valid signature for %s\n", argv[2], argv[1]);
-       exit(1);
+         fprintf(stderr, "Missing parameter -c required for"
+                 " signature verification\n");
+         return 1;
        }
- }
- else {
-       generate_signature(argv[2]);
+
+      if (optind + 1 >= argc)
+       {
+         fprintf(stderr, "for signature verification, a filename and the"
+                 " signature filename must be given\n");
+         return 1;
        }
- exit(0);
+      else
+       {
+         char * filename = argv[optind];
+         char * signaturefile = argv[optind + 1];
+
+         if (verify_signature(certfile, filename, signaturefile) == 0)
+           return 0;
+         else
+           {
+             fprintf(stderr, "%s is not the valid signature for %s\n",
+                     signaturefile, filename);
+             return 1;
+           }
+       }
+    }
+
+  return 0;
 }
-#else
-int main()
-{
- printf("openvas-check-signature: OpenSSL support has been disabled\n");
- exit(0);
-}
-#endif

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

Reply via email to