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 {
template class DSApair<C448>;
#endif
/***** Random Number Generator ********/
/**
* A wrapper around the bctoolbox Random Number Generator
......@@ -55,8 +54,10 @@ class bctbx_RNG : public RNG {
private :
bctbx_rng_context_t *m_context; // the bctoolbox RNG context
public:
/* accessor */
/* only bctbx_EDDSA and bctbx_ECDH needs a direct access to the actual RNG context */
template <typename Curve> friend class bctbx_EDDSA;
template <typename Curve> friend class bctbx_ECDH;
/**
* @brief access internal RNG context
* Used internally by the bctoolbox wrapper, is not exposed to the lime_crypto_primitive API.
......@@ -67,23 +68,30 @@ class bctbx_RNG : public RNG {
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] size size of the buffer to be filled
* @param[in,out] buffer point to the beginning of the buffer to be filled with random bytes
*/
void randomize(uint8_t *buffer, const size_t size) override {
bctbx_rng_get(m_context, buffer, size);
void randomize(sBuffer<lime::settings::DRrandomSeedSize> &buffer) override {
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 {
randomize(buffer.data(), buffer.size());
uint32_t randomize() override {
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() {
......@@ -402,14 +410,14 @@ class bctbx_ECDH : public keyExchange<Curve> {
/* Factory functions */
template <typename Base>
std::shared_ptr<keyExchange<Base>> make_keyExchange() {
return std::make_shared<bctbx_ECDH<Base>>();
template <typename Curve>
std::shared_ptr<keyExchange<Curve>> make_keyExchange() {
return std::make_shared<bctbx_ECDH<Curve>>();
}
template <typename Base>
std::shared_ptr<Signature<Base>> make_Signature() {
return std::make_shared<bctbx_EDDSA<Base>>();
template <typename Curve>
std::shared_ptr<Signature<Curve>> make_Signature() {
return std::make_shared<bctbx_EDDSA<Curve>>();
}
/* HMAC templates */
......
This diff is collapsed.
......@@ -465,7 +465,7 @@ namespace lime {
// First generate a key and IV, use it to encrypt the given message, Associated Data are : sourceDeviceId || recipientUserId
// generate the random seed
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
std::vector<uint8_t> emptySalt;
......
......@@ -659,11 +659,9 @@ void Lime<Curve>::X3DH_generate_SPk(X<Curve, lime::Xtype::publicKey> &publicSPk,
SPkSign->set_secret(m_Ik.privateKey());
SPkSign->sign(publicSPk, SPk_sig);
// Generate a random SPk Id: Sqlite doesn't really support unsigned value.
// 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)
std::array<uint8_t,4> randomId;
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]);
// Generate a random SPk Id
// 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
SPk_id = m_RNG->randomize();
// insert all this in DB
try {
......@@ -705,11 +703,9 @@ void Lime<Curve>::X3DH_generate_OPks(std::vector<X<Curve, lime::Xtype::publicKey
// Generate a new ECDH Key pair
DH->createKeyPair(m_RNG);
// Generate a random OPk Id: Sqlite doesn't really support unsigned value.
// 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)
std::array<uint8_t,4> randomId;
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]);
// Generate a random OPk Id
// 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
OPk_id = m_RNG->randomize();
// Insert in DB: store Public Key || Private Key
OPk.write(0, (const char *)(DH->get_selfPublic().data()), X<Curve, lime::Xtype::publicKey>::ssize());
......
......@@ -35,6 +35,10 @@ using namespace::soci;
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
int wait_for_timeout=4000;
......@@ -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."}
};
/**
* @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
* 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
/* generate a shared secret and AD */
lime::DRChainKey SK;
lime::SharedADBuffer AD;
RNG_context->randomize(SK.data(), SK.size());
RNG_context->randomize(AD.data(), AD.size());
lime_tester::randomize(SK.data(), SK.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)
long int aliceUid,bobUid,bobDid,aliceDid;
......@@ -495,13 +508,11 @@ const char charset[] =
*/
std::shared_ptr<std::string> makeRandomDeviceName(const char *basename) {
auto ret = make_shared<std::string>(basename);
bctbx_rng_context_t *RNG = bctbx_rng_context_new();
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) {
ret->append(1, charset[x%(sizeof(charset)-1)]);
}
bctbx_rng_context_free(RNG);
return ret;
}
......
......@@ -27,6 +27,7 @@
#include "lime_crypto_primitives.hpp"
#include "soci/sqlite3/soci-sqlite3.h"
#include <random>
using namespace::lime;
......@@ -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
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
* 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) {
auto rng_source = make_RNG();
/* input lenght is the same used by X3DH */
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::vector<uint8_t> salt(SHA512::ssize(), 0); // salt is the same used in X3DH
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