-/*****************************************************************************\
-* *
-* 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);