Commit 324b862d authored by johan's avatar johan

Improve RNG management

- crypto primitives exposes only what is really needed by the lib
- tests make direct usage of std::random_device
+ code cleaning: template parameter name consistency
parent b3a890ed
...@@ -46,7 +46,6 @@ namespace lime { ...@@ -46,7 +46,6 @@ namespace lime {
template class DSApair<C448>; template class DSApair<C448>;
#endif #endif
/***** Random Number Generator ********/ /***** Random Number Generator ********/
/** /**
* A wrapper around the bctoolbox Random Number Generator * A wrapper around the bctoolbox Random Number Generator
...@@ -55,8 +54,10 @@ class bctbx_RNG : public RNG { ...@@ -55,8 +54,10 @@ class bctbx_RNG : public RNG {
private : private :
bctbx_rng_context_t *m_context; // the bctoolbox RNG context bctbx_rng_context_t *m_context; // the bctoolbox RNG context
public: /* only bctbx_EDDSA and bctbx_ECDH needs a direct access to the actual RNG context */
/* accessor */ template <typename Curve> friend class bctbx_EDDSA;
template <typename Curve> friend class bctbx_ECDH;
/** /**
* @brief access internal RNG context * @brief access internal RNG context
* Used internally by the bctoolbox wrapper, is not exposed to the lime_crypto_primitive API. * Used internally by the bctoolbox wrapper, is not exposed to the lime_crypto_primitive API.
...@@ -67,23 +68,30 @@ class bctbx_RNG : public RNG { ...@@ -67,23 +68,30 @@ class bctbx_RNG : public RNG {
return m_context; return m_context;
} }
public:
/* accessor */
/** /**
* @brief fill given buffer with Random bytes * @brief fill the given RandomSeed buffer with Random bytes
* *
* @param[out] buffer point to the beginning of the buffer to be filled with random bytes * @param[in,out] buffer point to the beginning of the buffer to be filled with random bytes
* @param[in] size size of the buffer to be filled
*/ */
void randomize(uint8_t *buffer, const size_t size) override { void randomize(sBuffer<lime::settings::DRrandomSeedSize> &buffer) override {
bctbx_rng_get(m_context, buffer, size); bctbx_rng_get(m_context, buffer.data(), buffer.size());
}; };
/** /**
* @brief fill given buffer with Random bytes * @brief Generate a 32 bits unsigned integer(used to generate keys Id)
* The MSbit is forced to 0 to avoid dealing with DB misinterpreting unsigned values into signed one
* Our random number is actually on 31 bits.
* *
* @param[out] buffer vector to be filled with random bytes(based on original vector size) * @return a random 32 bits unsigned integer
*/ */
void randomize(std::vector<uint8_t> buffer) override { uint32_t randomize() override {
randomize(buffer.data(), buffer.size()); std::array<uint8_t, 4> buffer;
bctbx_rng_get(m_context, buffer.data(), buffer.size());
// buffer[0] is shifted by 23 instead of 24 to keep the MSb to 0.
return (static_cast<uint32_t>(buffer[0])<<23 | static_cast<uint32_t>(buffer[1])<<16 | static_cast<uint32_t>(buffer[2])<<8 | static_cast<uint32_t>(buffer[3]));
}; };
bctbx_RNG() { bctbx_RNG() {
...@@ -402,14 +410,14 @@ class bctbx_ECDH : public keyExchange<Curve> { ...@@ -402,14 +410,14 @@ class bctbx_ECDH : public keyExchange<Curve> {
/* Factory functions */ /* Factory functions */
template <typename Base> template <typename Curve>
std::shared_ptr<keyExchange<Base>> make_keyExchange() { std::shared_ptr<keyExchange<Curve>> make_keyExchange() {
return std::make_shared<bctbx_ECDH<Base>>(); return std::make_shared<bctbx_ECDH<Curve>>();
} }
template <typename Base> template <typename Curve>
std::shared_ptr<Signature<Base>> make_Signature() { std::shared_ptr<Signature<Curve>> make_Signature() {
return std::make_shared<bctbx_EDDSA<Base>>(); return std::make_shared<bctbx_EDDSA<Curve>>();
} }
/* HMAC templates */ /* HMAC templates */
......
This diff is collapsed.
...@@ -465,7 +465,7 @@ namespace lime { ...@@ -465,7 +465,7 @@ namespace lime {
// First generate a key and IV, use it to encrypt the given message, Associated Data are : sourceDeviceId || recipientUserId // First generate a key and IV, use it to encrypt the given message, Associated Data are : sourceDeviceId || recipientUserId
// generate the random seed // generate the random seed
auto RNG_context = make_RNG(); auto RNG_context = make_RNG();
RNG_context->randomize(randomSeed.data(), randomSeed.size()); RNG_context->randomize(randomSeed);
// expansion of randomSeed to 48 bytes: 32 bytes random key + 16 bytes nonce, use HKDF with empty salt // expansion of randomSeed to 48 bytes: 32 bytes random key + 16 bytes nonce, use HKDF with empty salt
std::vector<uint8_t> emptySalt; std::vector<uint8_t> emptySalt;
......
...@@ -659,11 +659,9 @@ void Lime<Curve>::X3DH_generate_SPk(X<Curve, lime::Xtype::publicKey> &publicSPk, ...@@ -659,11 +659,9 @@ void Lime<Curve>::X3DH_generate_SPk(X<Curve, lime::Xtype::publicKey> &publicSPk,
SPkSign->set_secret(m_Ik.privateKey()); SPkSign->set_secret(m_Ik.privateKey());
SPkSign->sign(publicSPk, SPk_sig); SPkSign->sign(publicSPk, SPk_sig);
// Generate a random SPk Id: Sqlite doesn't really support unsigned value. // Generate a random SPk Id
// Be sure the MSbit is set to zero to avoid problem as even if declared unsigned this Id will be treated by sqlite as signed(but still unsigned in this lib) // Sqlite doesn't really support unsigned value, the randomize function makes sure that the MSbit is set to 0 to not fall into strange bugs with that
std::array<uint8_t,4> randomId; SPk_id = m_RNG->randomize();
m_RNG->randomize(randomId.data(), randomId.size());
SPk_id = static_cast<uint32_t>(randomId[0])<<23 | static_cast<uint32_t>(randomId[1])<<16 | static_cast<uint32_t>(randomId[2])<<8 | static_cast<uint32_t>(randomId[3]);
// insert all this in DB // insert all this in DB
try { try {
...@@ -705,11 +703,9 @@ void Lime<Curve>::X3DH_generate_OPks(std::vector<X<Curve, lime::Xtype::publicKey ...@@ -705,11 +703,9 @@ void Lime<Curve>::X3DH_generate_OPks(std::vector<X<Curve, lime::Xtype::publicKey
// Generate a new ECDH Key pair // Generate a new ECDH Key pair
DH->createKeyPair(m_RNG); DH->createKeyPair(m_RNG);
// Generate a random OPk Id: Sqlite doesn't really support unsigned value. // Generate a random OPk Id
// Be sure the MSbit is set to zero to avoid problem as even if declared unsigned this Id will be treated by sqlite as signed(but still unsigned in this lib) // Sqlite doesn't really support unsigned value, the randomize function makes sure that the MSbit is set to 0 to not fall into strange bugs with that
std::array<uint8_t,4> randomId; OPk_id = m_RNG->randomize();
m_RNG->randomize(randomId.data(), randomId.size());
OPk_id = static_cast<uint32_t>(randomId[0])<<23 | static_cast<uint32_t>(randomId[1])<<16 | static_cast<uint32_t>(randomId[2])<<8 | static_cast<uint32_t>(randomId[3]);
// Insert in DB: store Public Key || Private Key // Insert in DB: store Public Key || Private Key
OPk.write(0, (const char *)(DH->get_selfPublic().data()), X<Curve, lime::Xtype::publicKey>::ssize()); OPk.write(0, (const char *)(DH->get_selfPublic().data()), X<Curve, lime::Xtype::publicKey>::ssize());
......
...@@ -35,6 +35,10 @@ using namespace::soci; ...@@ -35,6 +35,10 @@ using namespace::soci;
namespace lime_tester { namespace lime_tester {
/* for testing purpose RNG, no need to be good one */
std::random_device rd;
std::uniform_int_distribution<uint8_t> uniform_dist(0,255);
// default value for the timeout // default value for the timeout
int wait_for_timeout=4000; int wait_for_timeout=4000;
...@@ -154,6 +158,15 @@ std::vector<std::string> messages_pattern = { ...@@ -154,6 +158,15 @@ std::vector<std::string> messages_pattern = {
{"I have come here to chew bubble gum and kick ass, and I'm all out of bubble gum."} {"I have come here to chew bubble gum and kick ass, and I'm all out of bubble gum."}
}; };
/**
* @brief Simple RNG function, used to generate random values for testing purpose, they do not need to be real random
* so use directly std::random_device
*/
void randomize(uint8_t *buffer, const size_t size) {
for (size_t i=0; i<size; i++) {
buffer[i] = lime_tester::uniform_dist(rd);
}
}
/** /**
* @brief Create and initialise the two sessions given in parameter. Alice as sender session and Bob as receiver one * @brief Create and initialise the two sessions given in parameter. Alice as sender session and Bob as receiver one
* Alice must then send the first message, once bob got it, sessions are fully initialised * Alice must then send the first message, once bob got it, sessions are fully initialised
...@@ -177,8 +190,8 @@ void dr_sessionsInit(std::shared_ptr<DR<Curve>> &alice, std::shared_ptr<DR<Curve ...@@ -177,8 +190,8 @@ void dr_sessionsInit(std::shared_ptr<DR<Curve>> &alice, std::shared_ptr<DR<Curve
/* generate a shared secret and AD */ /* generate a shared secret and AD */
lime::DRChainKey SK; lime::DRChainKey SK;
lime::SharedADBuffer AD; lime::SharedADBuffer AD;
RNG_context->randomize(SK.data(), SK.size()); lime_tester::randomize(SK.data(), SK.size());
RNG_context->randomize(AD.data(), AD.size()); lime_tester::randomize(AD.data(), AD.size());
// insert the peer Device (with dummy datas in lime_PeerDevices and lime_LocalUsers tables, not used in the DR tests but needed to satisfy foreign key condition on session insertion) // insert the peer Device (with dummy datas in lime_PeerDevices and lime_LocalUsers tables, not used in the DR tests but needed to satisfy foreign key condition on session insertion)
long int aliceUid,bobUid,bobDid,aliceDid; long int aliceUid,bobUid,bobDid,aliceDid;
...@@ -495,13 +508,11 @@ const char charset[] = ...@@ -495,13 +508,11 @@ const char charset[] =
*/ */
std::shared_ptr<std::string> makeRandomDeviceName(const char *basename) { std::shared_ptr<std::string> makeRandomDeviceName(const char *basename) {
auto ret = make_shared<std::string>(basename); auto ret = make_shared<std::string>(basename);
bctbx_rng_context_t *RNG = bctbx_rng_context_new();
std::array<uint8_t,6> rnd; std::array<uint8_t,6> rnd;
bctbx_rng_get(RNG, rnd.data(), rnd.size()); lime_tester::randomize(rnd.data(), rnd.size());
for (auto x : rnd) { for (auto x : rnd) {
ret->append(1, charset[x%(sizeof(charset)-1)]); ret->append(1, charset[x%(sizeof(charset)-1)]);
} }
bctbx_rng_context_free(RNG);
return ret; return ret;
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "lime_crypto_primitives.hpp" #include "lime_crypto_primitives.hpp"
#include "soci/sqlite3/soci-sqlite3.h" #include "soci/sqlite3/soci-sqlite3.h"
#include <random>
using namespace::lime; using namespace::lime;
...@@ -44,6 +45,15 @@ extern int wait_for_timeout; ...@@ -44,6 +45,15 @@ extern int wait_for_timeout;
// default value for initial OPk batch size, keep it small so not too many OPks generated // default value for initial OPk batch size, keep it small so not too many OPks generated
extern uint16_t OPkInitialBatchSize; extern uint16_t OPkInitialBatchSize;
/**
* @brief Simple RNG function, used to generate random values for testing purpose, they do not need to be real random
* so use directly std::random_device
*
* @param[in] buffer pointer to the begining of the buffer to be filled
* @param[in] size how many random bytes you want
*/
void randomize(uint8_t *buffer, const size_t size);
/** /**
* @brief Create and initialise the two sessions given in parameter. Alice as sender session and Bob as receiver one * @brief Create and initialise the two sessions given in parameter. Alice as sender session and Bob as receiver one
* Alice must then send the first message, once bob got it, sessions are fully initialised * Alice must then send the first message, once bob got it, sessions are fully initialised
......
...@@ -321,7 +321,7 @@ static void hashMac_KDF_bench(uint64_t runTime_ms, size_t IKMsize) { ...@@ -321,7 +321,7 @@ static void hashMac_KDF_bench(uint64_t runTime_ms, size_t IKMsize) {
auto rng_source = make_RNG(); auto rng_source = make_RNG();
/* input lenght is the same used by X3DH */ /* input lenght is the same used by X3DH */
std::vector<uint8_t> IKM(IKMsize, 0); std::vector<uint8_t> IKM(IKMsize, 0);
rng_source->randomize(IKM.data(), IKM.size()); lime_tester::randomize(IKM.data(), IKM.size());
std::string info{"The lime tester info string"}; std::string info{"The lime tester info string"};
std::vector<uint8_t> salt(SHA512::ssize(), 0); // salt is the same used in X3DH std::vector<uint8_t> salt(SHA512::ssize(), 0); // salt is the same used in X3DH
std::array<uint8_t, 64> output; std::array<uint8_t, 64> output;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment