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.
#include "mutex.h"
+#include <stdio.h>
#include <stdlib.h>
#ifdef __UNIX__
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);
#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) \
: _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; }
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);
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();
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;
}
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;
}
"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;
}
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);
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;
}
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,
-/*****************************************************************************\
-* *
-* 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>
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)
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;
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.
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.
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.
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));
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);
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));
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);
#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.
// 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; }
--- /dev/null
+include variables.def
+
+PROJECT = crypto_libraries
+BUILD_BEFORE = crypto \
+ tests_crypto
+
+include rules.def
+