From f37dc531a52915c5d504bf1dc84d7bb8eb0932fd Mon Sep 17 00:00:00 2001 From: Chris Koeritz Date: Sat, 16 Jun 2012 16:08:21 -0400 Subject: [PATCH] updated to restore a couple logging points, and give the crypto libraries switchable 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 | 3 +- nucleus/library/crypto/blowfish_crypto.cpp | 49 ++++++++--- nucleus/library/crypto/rsa_crypto.cpp | 94 ++++++++++++++++------ nucleus/library/crypto/ssl_init.cpp | 29 +++++-- nucleus/library/makefile.tmp | 8 ++ 5 files changed, 138 insertions(+), 45 deletions(-) create mode 100644 nucleus/library/makefile.tmp diff --git a/nucleus/library/basis/mutex.cpp b/nucleus/library/basis/mutex.cpp index 0bf8b943..6a9af775 100644 --- a/nucleus/library/basis/mutex.cpp +++ b/nucleus/library/basis/mutex.cpp @@ -18,6 +18,7 @@ #include "mutex.h" +#include #include #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); diff --git a/nucleus/library/crypto/blowfish_crypto.cpp b/nucleus/library/crypto/blowfish_crypto.cpp index 1e8ee443..2a6d8282 100644 --- a/nucleus/library/crypto/blowfish_crypto.cpp +++ b/nucleus/library/crypto/blowfish_crypto.cpp @@ -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, diff --git a/nucleus/library/crypto/rsa_crypto.cpp b/nucleus/library/crypto/rsa_crypto.cpp index f50d3076..54416397 100644 --- a/nucleus/library/crypto/rsa_crypto.cpp +++ b/nucleus/library/crypto/rsa_crypto.cpp @@ -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 #include +#include #include #include +#include #include #include @@ -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); diff --git a/nucleus/library/crypto/ssl_init.cpp b/nucleus/library/crypto/ssl_init.cpp index 9a54f527..5a17dd34 100644 --- a/nucleus/library/crypto/ssl_init.cpp +++ b/nucleus/library/crypto/ssl_init.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -23,12 +24,23 @@ #include 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 index 00000000..6b7dfeee --- /dev/null +++ b/nucleus/library/makefile.tmp @@ -0,0 +1,8 @@ +include variables.def + +PROJECT = crypto_libraries +BUILD_BEFORE = crypto \ + tests_crypto + +include rules.def + -- 2.34.1