updated to restore a couple logging points, and give the crypto libraries switchable
authorChris Koeritz <fred@gruntose.com>
Sat, 16 Jun 2012 20:08:21 +0000 (16:08 -0400)
committerChris Koeritz <fred@gruntose.com>
Sat, 16 Jun 2012 20:08:21 +0000 (16:08 -0400)
logging based on DEBUG_X flags.  also fixed bug; turns out the rsa libraries are not
the slightest bit thread safe.  has that problem always been there???  they have in the
past occasionally crashed, but hopefully they will no longer do this.  and since i had
turned on the ssl debugging, they were kind of always crashing in the threaded tests,
so that was a bit of a signal.

nucleus/library/basis/mutex.cpp
nucleus/library/crypto/blowfish_crypto.cpp
nucleus/library/crypto/rsa_crypto.cpp
nucleus/library/crypto/ssl_init.cpp
nucleus/library/makefile.tmp [new file with mode: 0644]

index 0bf8b94372382a70ec13c4365e7c1551e269778a..6a9af775879059f5e4730c69ea3d874f26ccd1e3 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "mutex.h"
 
+#include <stdio.h>
 #include <stdlib.h>
 
 #ifdef __UNIX__
@@ -53,7 +54,7 @@ void mutex::construct()
   ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
 #endif
   if (ret != 0) {
-//printf("failed to initialize mutex attributes!\n"); fflush(NIL);
+    printf("failed to initialize mutex attributes!\n"); fflush(NIL);
   }
   c_os_mutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
   pthread_mutex_init((pthread_mutex_t *)c_os_mutex, &attr);
index 1e8ee443c562e7fc36f25f68a4645ea1e53580e7..2a6d8282d9868c3ec658ab99f8967330822e4c7d 100644 (file)
@@ -41,12 +41,17 @@ const int FUDGE = 128;
 #undef set_key
   // get rid of a macro we don't want.
 
-#undef LOG
-#define LOG(t) CLASS_EMERGENCY_LOG(program_wide_logger::get(), t)
-
 //#define DEBUG_BLOWFISH
   // uncomment for noisier version.
 
+#ifdef DEBUG_BLOWFISH
+  #undef LOG
+  #define LOG(t) CLASS_EMERGENCY_LOG(program_wide_logger::get(), t)
+#else
+  #undef LOG
+  #define LOG(t) 
+#endif
+
 #ifdef DEBUG_BLOWFISH
   // this macro checks on the validity of the key sizes (in bits).
   #define DISCUSS_KEY_SIZE(key_size) \
@@ -78,37 +83,51 @@ blowfish_crypto::blowfish_crypto(int key_size)
 : _key_size(key_size),
   _key(new byte_array)
 {
-//  FUNCDEF("constructor [int]");
+  FUNCDEF("ctor(int)");
   static_ssl_initializer();
+  LOG("prior to key size discuss");
   DISCUSS_KEY_SIZE(key_size);
   if (key_size < minimum_key_size())
     _key_size = minimum_key_size();
   if (key_size > maximum_key_size())
     _key_size = maximum_key_size();
+  LOG("prior to generate key");
   generate_key(_key_size, *_key);
+  LOG("after generate key");
 }
 
 blowfish_crypto::blowfish_crypto(const byte_array &key, int key_size)
 : _key_size(key_size),
   _key(new byte_array(key))
 {
-//  FUNCDEF("constructor [byte_array/int]");
+  FUNCDEF("ctor(byte_array,int)");
   // any problems with the key provided are horrid.  they will yield a
   // non-working blowfish object.
+  LOG("prior to key size discuss");
   DISCUSS_KEY_SIZE(key_size);
+  LOG("prior to provided key discuss");
   DISCUSS_PROVIDED_KEY(key_size, key);
+  LOG("prior to ssl static init");
   static_ssl_initializer();
+  LOG("after ssl static init");
 }
 
 blowfish_crypto::blowfish_crypto(const blowfish_crypto &to_copy)
 : root_object(),
   _key_size(to_copy._key_size),
   _key(new byte_array(*to_copy._key))
-{ static_ssl_initializer(); }
+{
+  FUNCDEF("copy ctor");
+  static_ssl_initializer(); 
+  LOG("after ssl static init");
+}
 
 blowfish_crypto::~blowfish_crypto()
 {
+  FUNCDEF("dtor");
+  LOG("prior to key whack");
   WHACK(_key);
+  LOG("after key whack");
 }
 
 int blowfish_crypto::key_size() const { return _key_size; }
@@ -129,7 +148,7 @@ blowfish_crypto &blowfish_crypto::operator = (const blowfish_crypto &to_copy)
 
 bool blowfish_crypto::set_key(const byte_array &new_key, int key_size)
 {
-//  FUNCDEF("set_key");
+  FUNCDEF("set_key");
   if (!new_key.length()) return false;
   DISCUSS_KEY_SIZE(key_size);
   DISCUSS_PROVIDED_KEY(key_size, new_key);
@@ -143,7 +162,7 @@ bool blowfish_crypto::set_key(const byte_array &new_key, int key_size)
 
 void blowfish_crypto::generate_key(int size, byte_array &new_key)
 {
-//  FUNCDEF("generate_key");
+  FUNCDEF("generate_key");
   DISCUSS_KEY_SIZE(size);
   if (size < minimum_key_size())
     size = minimum_key_size();
@@ -160,14 +179,18 @@ SAFE_STATIC(mutex, __vector_init_lock, )
 
 const byte_array &blowfish_crypto::init_vector()
 {
+  FUNCDEF("init_vector");
   auto_synchronizer locking(__vector_init_lock());
   static byte_array to_return(EVP_MAX_IV_LENGTH);
   static bool initted = false;
+  LOG("prior to initted check");
   if (!initted) {
+    LOG("actually doing init");
     for (int i = 0; i < EVP_MAX_IV_LENGTH; i++)
       to_return[i] = 214 - i;
     initted = true;
   }
+  LOG("leaving init check");
   return to_return;
 }
 
@@ -199,7 +222,7 @@ bool blowfish_crypto::encrypt(const byte_array &source,
     to_return = false;
   } else {
     // chop any extra space off.
-//    LOG(a_sprintf("encrypting bytes %d to %d.\n", i, edge));
+    LOG(a_sprintf("chopping bytes %d to %d.\n", encoded_len, encoded.last()));
     encoded.zap(encoded_len, encoded.last());
     target = encoded;
   }
@@ -215,7 +238,7 @@ bool blowfish_crypto::encrypt(const byte_array &source,
           "failed, result=%d.", enc_ret));
       to_return = false;
     } else {
-//      LOG(a_sprintf("padding added %d bytes.\n", pad_len));
+      LOG(a_sprintf("padding added %d bytes.\n", pad_len));
       encoded.zap(pad_len, encoded.last());
       target += encoded;
     }
@@ -234,7 +257,7 @@ bool blowfish_crypto::decrypt(const byte_array &source,
   bool to_return = true;
   EVP_CIPHER_CTX session;
   EVP_CIPHER_CTX_init(&session);
-//LOG(a_sprintf("key size %d bits.\n", BITS_PER_BYTE * _key->length()));
+  LOG(a_sprintf("key size %d bits.\n", BITS_PER_BYTE * _key->length()));
   EVP_DecryptInit_ex(&session, EVP_bf_cbc(), NIL, _key->observe(),
       init_vector().observe());
   EVP_CIPHER_CTX_set_key_length(&session, _key_size);
@@ -249,7 +272,7 @@ bool blowfish_crypto::decrypt(const byte_array &source,
     continuable_error(class_name(), func, "decryption failed.");
     to_return = false;
   } else {
-//    LOG(a_sprintf("  decrypted size in bytes is %d.\n", decoded_len));
+    LOG(a_sprintf("  decrypted size in bytes is %d.\n", decoded_len));
     decoded.zap(decoded_len, decoded.last());
     target = decoded;
   }
@@ -259,7 +282,7 @@ bool blowfish_crypto::decrypt(const byte_array &source,
     decoded.reset(FUDGE);  // reinflate for padding.
     int pad_len = 0;
     dec_ret = EVP_DecryptFinal_ex(&session, decoded.access(), &pad_len);
-//    LOG(a_sprintf("padding added %d bytes.\n", pad_len));
+    LOG(a_sprintf("padding added %d bytes.\n", pad_len));
     if (dec_ret != 1) {
       continuable_error(class_name(), func, a_sprintf("finalizing decryption "
           "failed, result=%d, padlen=%d, target had %d bytes.", dec_ret,
index f50d3076f75c7ba976272d78f48be26be6ca9bec..54416397b303964578553b500cb2a3a69a2bda16 100644 (file)
@@ -1,29 +1,34 @@
-/*****************************************************************************\
-*                                                                             *
-*  Name   : RSA public key encryption                                         *
-*  Author : Chris Koeritz                                                     *
-*                                                                             *
-*  Purpose:                                                                   *
-*                                                                             *
-*    Supports public (and private) key encryption and decryption using the    *
-*  OpenSSL package's support for RSA encryption.                              *
-*                                                                             *
-*******************************************************************************
+/*
+*  Name   : RSA public key encryption
+*  Author : Chris Koeritz
+*  Purpose:
+*    Supports public (and private) key encryption and decryption using the
+*    OpenSSL package's support for RSA encryption.
+****
 * Copyright (c) 2005-$now By Author.  This program is free software; you can  *
 * redistribute it and/or modify it under the terms of the GNU General Public  *
 * License as published by the Free Software Foundation; either version 2 of   *
 * the License or (at your option) any later version.  This is online at:      *
 *     http://www.fsf.org/copyleft/gpl.html                                    *
 * Please send any updates to: fred@gruntose.com                               *
-\*****************************************************************************/
+*/
+
+//note: rsa crypto provides a nice printing method...  RSA_print_fp(stdout, private_key, 0);
+
+// notes from openssl docs: length to be encrypted in a chunk must be less than
+// RSA_size(rsa) - 11 for the PKCS #1 v1.5 based padding modes, less than
+// RSA_size(rsa) - 41 for RSA_PKCS1_OAEP_PADDING and exactly RSA_size(rsa)
+// for RSA_NO_PADDING.
 
 #include "rsa_crypto.h"
 #include "ssl_init.h"
 
 #include <basis/functions.h>
 #include <loggers/critical_events.h>
+#include <loggers/program_wide_logger.h>
 #include <mathematics/chaos.h>
 #include <structures/object_packers.h>
+#include <structures/static_memory_gremlin.h>
 
 #include <openssl/bn.h>
 #include <openssl/rsa.h>
@@ -35,48 +40,68 @@ using namespace structures;
 
 namespace crypto {
 
-// notes from openssl docs: length to be encrypted in a chunk must be less than
-// RSA_size(rsa) - 11 for the PKCS #1 v1.5 based padding modes, less than
-// RSA_size(rsa) - 41 for RSA_PKCS1_OAEP_PADDING and exactly RSA_size(rsa)
-// for RSA_NO_PADDING.
+//#define DEBUG_RSA_CRYPTO
+  // uncomment for noisier version.
 
-#undef LOG
-#define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
+#ifdef DEBUG_RSA_CRYPTO
+  #undef LOG
+  #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
+#else
+  #undef LOG
+  #define LOG(s)
+#endif
 
-//nice printing method...  RSA_print_fp(stdout, private_key, 0);
+SAFE_STATIC(mutex, __single_stepper, )
+  // protects unsafe areas of rsa crypto from access by multiple threads at once.
 
 rsa_crypto::rsa_crypto(int key_size)
 : _key(NIL)
 {
+  FUNCDEF("ctor(int)");
+  LOG("prior to generating key");
   _key = generate_key(key_size);  // generate_key initializes ssl for us.
+  LOG("after generating key");
 }
 
 rsa_crypto::rsa_crypto(const byte_array &key)
 : _key(NIL)
 {
+  FUNCDEF("ctor(byte_array)");
   static_ssl_initializer();
   byte_array key_copy = key;
+  LOG("prior to set key");
   set_key(key_copy);
+  LOG("after set key");
 }
 
 rsa_crypto::rsa_crypto(rsa_st *key)
 : _key(NIL)
 {
+  FUNCDEF("ctor(rsa_st)");
   static_ssl_initializer();
+  LOG("prior to set key");
   set_key(key);
+  LOG("after set key");
 }
 
 rsa_crypto::rsa_crypto(const rsa_crypto &to_copy)
 : root_object(),
   _key(NIL)
 {
+  FUNCDEF("copy ctor");
   static_ssl_initializer();
+  LOG("prior to set key");
   set_key(to_copy._key);
+  LOG("after set key");
 }
 
 rsa_crypto::~rsa_crypto()
 {
+  FUNCDEF("dtor");
+  LOG("prior to rsa free");
+  auto_synchronizer mutt(__single_stepper());
   RSA_free(_key);
+  LOG("after rsa free");
 }
 
 const rsa_crypto &rsa_crypto::operator = (const rsa_crypto &to_copy)
@@ -91,20 +116,28 @@ rsa_st *rsa_crypto::generate_key(int key_size)
   FUNCDEF("generate_key");
   if (key_size < 4) key_size = 4;  // laughable lower default.
   static_ssl_initializer();
+  LOG("prior to generate key");
+  auto_synchronizer mutt(__single_stepper());
   rsa_st *to_return = RSA_generate_key(key_size, 65537, NIL, NIL);
   if (!to_return) {
     continuable_error(static_class_name(), func,
         a_sprintf("failed to generate a key of %d bits.", key_size));
   }
+  LOG("after generate key");
   return to_return;
 }
 
-bool rsa_crypto::check_key(rsa_st *key) { return RSA_check_key(key) == 1; }
+bool rsa_crypto::check_key(rsa_st *key)
+{
+  auto_synchronizer mutt(__single_stepper());
+  return RSA_check_key(key) == 1;
+}
 
 bool rsa_crypto::set_key(byte_array &key)
 {
   FUNCDEF("set_key [byte_array]");
   if (!key.length()) return false;
+  auto_synchronizer mutt(__single_stepper());
   if (_key) RSA_free(_key);
   _key = RSA_new();
   abyte type;
@@ -161,6 +194,7 @@ bool rsa_crypto::set_key(rsa_st *key)
   FUNCDEF("set_key [rsa_st]");
   if (!key) return NIL;
   // test the incoming key.
+  auto_synchronizer mutt(__single_stepper());
   int check = RSA_check_key(key);
   if (check != 1) return false;
   // clean out the old key.
@@ -176,7 +210,7 @@ bool rsa_crypto::set_key(rsa_st *key)
 
 bool rsa_crypto::public_key(byte_array &pubkey) const
 {
-//  FUNCDEF("public_key");
+  FUNCDEF("public_key");
   if (!_key) return false;
   structures::attach(pubkey, abyte('u'));  // signal a public key.
   // convert the two public portions into binary.
@@ -192,7 +226,7 @@ bool rsa_crypto::public_key(byte_array &pubkey) const
 
 bool rsa_crypto::private_key(byte_array &privkey) const
 {
-//  FUNCDEF("private_key");
+  FUNCDEF("private_key");
   if (!_key) return false;
   int posn = privkey.length();
   bool worked = public_key(privkey);  // get the public pieces first.
@@ -224,9 +258,11 @@ bool rsa_crypto::private_key(byte_array &privkey) const
 bool rsa_crypto::public_encrypt(const byte_array &source,
     byte_array &target) const
 {
-//  FUNCDEF("public_encrypt");
+  FUNCDEF("public_encrypt");
   target.reset();
   if (!source.length()) return false;
+
+  auto_synchronizer mutt(__single_stepper());
   const int max_chunk = RSA_size(_key) - 12;
 
   byte_array encoded(RSA_size(_key));
@@ -245,9 +281,11 @@ bool rsa_crypto::public_encrypt(const byte_array &source,
 bool rsa_crypto::private_decrypt(const byte_array &source,
     byte_array &target) const
 {
-//  FUNCDEF("private_decrypt");
+  FUNCDEF("private_decrypt");
   target.reset();
   if (!source.length()) return false;
+
+  auto_synchronizer mutt(__single_stepper());
   const int max_chunk = RSA_size(_key);
 
   byte_array decoded(max_chunk);
@@ -269,9 +307,11 @@ bool rsa_crypto::private_decrypt(const byte_array &source,
 bool rsa_crypto::private_encrypt(const byte_array &source,
     byte_array &target) const
 {
-//  FUNCDEF("private_encrypt");
+  FUNCDEF("private_encrypt");
   target.reset();
   if (!source.length()) return false;
+
+  auto_synchronizer mutt(__single_stepper());
   const int max_chunk = RSA_size(_key) - 12;
 
   byte_array encoded(RSA_size(_key));
@@ -290,9 +330,11 @@ bool rsa_crypto::private_encrypt(const byte_array &source,
 bool rsa_crypto::public_decrypt(const byte_array &source,
     byte_array &target) const
 {
-//  FUNCDEF("public_decrypt");
+  FUNCDEF("public_decrypt");
   target.reset();
   if (!source.length()) return false;
+
+  auto_synchronizer mutt(__single_stepper());
   const int max_chunk = RSA_size(_key);
 
   byte_array decoded(max_chunk);
index 9a54f5274a79c79928fbc7cdb5579cd52af03224..5a17dd3499b19f53929f9ea8e287a71579dec6de 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <basis/functions.h>
 #include <basis/mutex.h>
+#include <loggers/program_wide_logger.h>
 #include <structures/static_memory_gremlin.h>
 
 #include <openssl/crypto.h>
 #include <openssl/rand.h>
 
 using namespace basis;
+using namespace loggers;
 using namespace mathematics;
 using namespace structures;
 
 namespace crypto {
 
-#define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
+//#define DEBUG_SSL
+  // uncomment to cause more debugging information to be generated, plus
+  // more checking to be performed in the SSL support.
+
+#ifdef DEBUG_SSL
+  #undef LOG
+  #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
+#else
+  #undef LOG
+  #define LOG(s)
+#endif
 
 const int SEED_SIZE = 100;
   // the size of the random seed that we'll use.
@@ -36,26 +48,33 @@ const int SEED_SIZE = 100;
 // our global initialization object.
 SAFE_STATIC_CONST(ssl_init, static_ssl_initializer, )
 
-#define DEBUG_SSL
-  // uncomment to cause more debugging information to be generated, plus
-  // more checking to be performed in the SSL support.
-
 ssl_init::ssl_init()
 : c_rando()
 {
+  FUNCDEF("ctor");
 #ifdef DEBUG_SSL
+  LOG("prior to crypto debug init");
   CRYPTO_malloc_debug_init();
+  LOG("prior to dbg set options");
   CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
+  LOG("prior to mem ctrl");
   CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
 #endif
+  LOG("prior to rand seed");
   RAND_seed(random_bytes(SEED_SIZE).observe(), SEED_SIZE);
+  LOG("after rand seed");
 }
 
 ssl_init::~ssl_init()
 {
+  FUNCDEF("dtor");
+  LOG("prior to crypto cleanup");
   CRYPTO_cleanup_all_ex_data();
+  LOG("prior to err remove state");
   ERR_remove_state(0);
+  LOG("prior to mem leaks fp");
   CRYPTO_mem_leaks_fp(stderr);
+  LOG("after mem leaks fp");
 }
 
 const chaos &ssl_init::randomizer() const { return c_rando; }
diff --git a/nucleus/library/makefile.tmp b/nucleus/library/makefile.tmp
new file mode 100644 (file)
index 0000000..6b7dfee
--- /dev/null
@@ -0,0 +1,8 @@
+include variables.def
+
+PROJECT = crypto_libraries
+BUILD_BEFORE = crypto \
+  tests_crypto 
+
+include rules.def
+