Commit f1d5572d authored by johan's avatar johan

Cleaning in tests

parent bc655178
......@@ -511,7 +511,7 @@ namespace lime {
return nullptr; // no session correctly deciphered
}
/* template instanciations for DHKeyX25519 and DHKeyX448 encryption/decryption functions */
/* template instanciations for C25519 and C448 encryption/decryption functions */
#ifdef EC25519_ENABLED
template void encryptMessage<C255>(std::vector<recipientInfos<C255>>& recipients, const std::vector<uint8_t>& plaintext, const std::string& recipientUserId, const std::string& sourceDeviceId, std::vector<uint8_t>& cipherMessage);
template std::shared_ptr<DR<C255>> decryptMessage<C255>(const std::string& sourceId, const std::string& recipientDeviceId, const std::string& recipientUserId, std::vector<std::shared_ptr<DR<C255>>>& DRSessions, const std::vector<uint8_t>& cipherHeader, const std::vector<uint8_t>& cipherMessage, std::vector<uint8_t>& plaintext);
......
......@@ -167,13 +167,11 @@ namespace lime {
extern template class DR<C255>;
extern template void encryptMessage<C255>(std::vector<recipientInfos<C255>>& recipients, const std::vector<uint8_t>& plaintext, const std::string& recipientUserId, const std::string& sourceDeviceId, std::vector<uint8_t>& cipherMessage);
extern template std::shared_ptr<DR<C255>> decryptMessage<C255>(const std::string& sourceDeviceId, const std::string& recipientDeviceId, const std::string& recipientUserId, std::vector<std::shared_ptr<DR<C255>>>& DRSessions, const std::vector<uint8_t>& cipherHeader, const std::vector<uint8_t>& cipherMessage, std::vector<uint8_t>& plaintext);
extern template bool get_X3DH_initMessage<C255>(const std::vector<uint8_t> &header, std::vector<uint8_t> &X3DH_initMessage);
#endif
#ifdef EC448_ENABLED
extern template class DR<C448>;
extern template void encryptMessage<C448>(std::vector<recipientInfos<C448>>& recipients, const std::vector<uint8_t>& plaintext, const std::string& recipientUserId, const std::string& sourceDeviceId, std::vector<uint8_t>& cipherMessage);
extern template std::shared_ptr<DR<C448>> decryptMessage<C448>(const std::string& sourceDeviceId, const std::string& recipientDeviceId, const std::string& recipientUserId, std::vector<std::shared_ptr<DR<C448>>>& DRSessions, const std::vector<uint8_t>& cipherHeader, const std::vector<uint8_t>& cipherMessage, std::vector<uint8_t>& plaintext);
extern template bool get_X3DH_initMessage<C448>(const std::vector<uint8_t> &header, std::vector<uint8_t> &X3DH_initMessage);
#endif
}
......
......@@ -29,6 +29,7 @@
#include "lime_keys.hpp"
#include "lime_double_ratchet_protocol.hpp"
#include "bctoolbox/exception.hh"
#include "lime-tester-utils.hpp"
#include "soci/soci.h"
#include "soci/sqlite3/soci-sqlite3.h"
......@@ -141,6 +142,111 @@ std::vector<std::string> lime_messages_pattern = {
{"I have come here to chew bubble gum and kick ass, and I'm all out of bubble gum."}
};
/**
* @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
* if fileName doesn't exists as a DB, it will be created, caller shall then delete it if needed
*/
template <typename Curve>
void dr_sessionsInit(std::shared_ptr<DR<Curve>> &alice, std::shared_ptr<DR<Curve>> &bob, std::shared_ptr<lime::Db> &localStorageAlice, std::shared_ptr<lime::Db> &localStorageBob, std::string dbFilenameAlice, std::string dbFilenameBob, bool initStorage) {
if (initStorage==true) {
// create or load Db
localStorageAlice = std::make_shared<lime::Db>(dbFilenameAlice);
localStorageBob = std::make_shared<lime::Db>(dbFilenameBob);
}
// create and init a RNG needed for shared secret generation
bctbx_rng_context_t *RNG = bctbx_rng_context_new();
/* generate key pair for bob */
bctbx_ECDHContext_t *tempECDH = ECDHInit<Curve>();
bctbx_ECDHCreateKeyPair(tempECDH, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, RNG);
KeyPair<X<Curve>> bobKeyPair{tempECDH->selfPublic, tempECDH->secret};
bctbx_DestroyECDHContext(tempECDH);
/* generate a shared secret and AD */
lime::DRChainKey SK;
lime::SharedADBuffer AD;
bctbx_rng_get(RNG, SK.data(), SK.size());
bctbx_rng_get(RNG, AD.data(), AD.size());
bctbx_rng_context_free(RNG);
// 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;
localStorageAlice->sql<<"INSERT INTO lime_LocalUsers(UserId, Ik, server) VALUES ('dummy', 1, 'dummy')";
localStorageAlice->sql<<"select last_insert_rowid()",soci::into(aliceUid);
localStorageAlice->sql<<"INSERT INTO lime_PeerDevices(DeviceId, Uid, Ik) VALUES ('dummy', :Uid, 1)", soci::use(aliceUid);
localStorageAlice->sql<<"select last_insert_rowid()",soci::into(aliceDid);
localStorageBob->sql<<"INSERT INTO lime_LocalUsers(UserId, Ik, server) VALUES ('dummy', 1, 'dummy')";
localStorageBob->sql<<"select last_insert_rowid()",soci::into(bobUid);
localStorageBob->sql<<"INSERT INTO lime_PeerDevices(DeviceId, Uid, Ik) VALUES ('dummy', :Uid, 1)", soci::use(bobUid);
localStorageBob->sql<<"select last_insert_rowid()",soci::into(bobDid);
// create DR sessions
std::vector<uint8_t> X3DH_initMessage{};
alice = std::make_shared<DR<Curve>>(localStorageAlice.get(), SK, AD, bobKeyPair.publicKey(), aliceDid, X3DH_initMessage);
bob = std::make_shared<DR<Curve>>(localStorageBob.get(), SK, AD, bobKeyPair, bobDid);
}
/**
* @brief Create and initialise all requested DR sessions for specified number of devices between two or more users
* users is a vector of users(already sized to correct size, matching usernames size), each one holds a vector of devices(already sized for each device)
* This function will create and instanciate in each device a vector of vector of DR sessions towards all other devices: each device vector holds a bidimentionnal array indexed by userId and deviceId.
* Session init is done considering as initial sender the lowest id user and in it the lowest id device
* createdDBfiles is filled with all filenames of DB created to allow easy deletion
*/
template <typename Curve>
void dr_devicesInit(std::string dbBaseFilename, std::vector<std::vector<std::vector<std::vector<sessionDetails<Curve>>>>> &users, std::vector<std::string> &usernames, std::vector<std::string> &createdDBfiles) {
createdDBfiles.clear();
/* each device must have a db, produce filename for them from provided base name and given username */
for (size_t i=0; i<users.size(); i++) { // loop on users
for (size_t j=0; j<users[i].size(); j++) { // loop on devices
// create the db for this device, filename would be <dbBaseFilename>.<username>.<dev><deviceIndex>.sqlite3
std::string dbFilename{dbBaseFilename};
dbFilename.append(".").append(usernames[i]).append(".dev").append(std::to_string(j)).append(".sqlite3");
remove(dbFilename.data());
createdDBfiles.push_back(dbFilename);
std::shared_ptr<lime::Db> localStorage = std::make_shared<lime::Db>(dbFilename);
users[i][j].resize(users.size()); // each device holds a vector towards all users, dimension it
// instanciate the session details for all needed sessions
for (size_t i_fw=0; i_fw<users.size(); i_fw++) { // loop on the rest of users
users[i][j][i_fw].resize(users[i_fw].size()); // [i][j][i_fw] holds a vector of sessions toward user i_fw devices
for (size_t j_fw=0; j_fw<users[i].size(); j_fw++) { // loop on the rest of devices
if (!((i_fw==i) && (j_fw==j))) { // no session towards ourself
/* create session details with self and peer userId, user and device index */
sessionDetails<Curve> sessionDetail{usernames[i], i, j, usernames[i_fw], i_fw, j_fw};
sessionDetail.localStorage = localStorage;
users[i][j][i_fw][j_fw]=std::move(sessionDetail);
}
}
}
}
}
/* users is a vector of users, each of them has a vector of devices, each device hold a vector of sessions */
/* sessions init are done by users[i] to all users[>i] (same thing intra device) */
for (size_t i=0; i<users.size(); i++) { // loop on users
for (size_t j=0; j<users[i].size(); j++) { // loop on devices
for (size_t j_fw=j+1; j_fw<users[i].size(); j_fw++) { // loop on the rest of our devices
dr_sessionsInit(users[i][j][i][j_fw].DRSession, users[i][j_fw][i][j].DRSession, users[i][j][i][j_fw].localStorage, users[i][j_fw][i][j].localStorage, " ", " ", false);
}
for (size_t i_fw=i+1; i_fw<users.size(); i_fw++) { // loop on the rest of users
for (size_t j_fw=0; j_fw<users[i].size(); j_fw++) { // loop on the rest of devices
dr_sessionsInit(users[i][j][i_fw][j_fw].DRSession, users[i_fw][j_fw][i][j].DRSession, users[i][j][i_fw][j_fw].localStorage, users[i_fw][j_fw][i][j].localStorage, " ", " ", false);
}
}
}
}
}
bool DR_message_holdsX3DHInit(std::vector<uint8_t> &message) {
// checks on length
if (message.size()<4) return false;
......@@ -253,5 +359,16 @@ std::shared_ptr<std::string> makeRandomDeviceName(const char *basename) {
return ret;
}
// template instanciation
#ifdef EC25519_ENABLED
template void dr_sessionsInit<C255>(std::shared_ptr<DR<C255>> &alice, std::shared_ptr<DR<C255>> &bob, std::shared_ptr<lime::Db> &localStorageAlice, std::shared_ptr<lime::Db> &localStorageBob, std::string dbFilenameAlice, std::string dbFilenameBob, bool initStorage);
template void dr_devicesInit<C255>(std::string dbBaseFilename, std::vector<std::vector<std::vector<std::vector<sessionDetails<C255>>>>> &users, std::vector<std::string> &usernames, std::vector<std::string> &createdDBfiles);
#endif
#ifdef EC448_ENABLED
template void dr_sessionsInit<C448>(std::shared_ptr<DR<C448>> &alice, std::shared_ptr<DR<C448>> &bob, std::shared_ptr<lime::Db> &localStorageAlice, std::shared_ptr<lime::Db> &localStorageBob, std::string dbFilenameAlice, std::string dbFilenameBob, bool initStorage);
template void dr_devicesInit<C448>(std::string dbBaseFilename, std::vector<std::vector<std::vector<std::vector<sessionDetails<C448>>>>> &users, std::vector<std::string> &usernames, std::vector<std::string> &createdDBfiles);
#endif
} // namespace lime
......@@ -35,46 +35,8 @@ extern std::vector<std::string> lime_messages_pattern;
* if fileName doesn't exists as a DB, it will be created, caller shall then delete it if needed
*/
template <typename Curve>
void dr_sessionsInit(std::shared_ptr<DR<Curve>> &alice, std::shared_ptr<DR<Curve>> &bob, std::shared_ptr<lime::Db> &localStorageAlice, std::shared_ptr<lime::Db> &localStorageBob, std::string dbFilenameAlice, std::string dbFilenameBob, bool initStorage=true) {
if (initStorage==true) {
// create or load Db
localStorageAlice = std::make_shared<lime::Db>(dbFilenameAlice);
localStorageBob = std::make_shared<lime::Db>(dbFilenameBob);
}
// create and init a RNG needed for shared secret generation
bctbx_rng_context_t *RNG = bctbx_rng_context_new();
/* generate key pair for bob */
bctbx_ECDHContext_t *tempECDH = ECDHInit<Curve>();
bctbx_ECDHCreateKeyPair(tempECDH, (int (*)(void *, uint8_t *, size_t))bctbx_rng_get, RNG);
KeyPair<X<Curve>> bobKeyPair{tempECDH->selfPublic, tempECDH->secret};
bctbx_DestroyECDHContext(tempECDH);
/* generate a shared secret and AD */
lime::DRChainKey SK;
lime::SharedADBuffer AD;
bctbx_rng_get(RNG, SK.data(), SK.size());
bctbx_rng_get(RNG, AD.data(), AD.size());
bctbx_rng_context_free(RNG);
// 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;
localStorageAlice->sql<<"INSERT INTO lime_LocalUsers(UserId, Ik, server) VALUES ('dummy', 1, 'dummy')";
localStorageAlice->sql<<"select last_insert_rowid()",soci::into(aliceUid);
localStorageAlice->sql<<"INSERT INTO lime_PeerDevices(DeviceId, Uid, Ik) VALUES ('dummy', :Uid, 1)", soci::use(aliceUid);
localStorageAlice->sql<<"select last_insert_rowid()",soci::into(aliceDid);
localStorageBob->sql<<"INSERT INTO lime_LocalUsers(UserId, Ik, server) VALUES ('dummy', 1, 'dummy')";
localStorageBob->sql<<"select last_insert_rowid()",soci::into(bobUid);
localStorageBob->sql<<"INSERT INTO lime_PeerDevices(DeviceId, Uid, Ik) VALUES ('dummy', :Uid, 1)", soci::use(bobUid);
localStorageBob->sql<<"select last_insert_rowid()",soci::into(bobDid);
// create DR sessions
std::vector<uint8_t> X3DH_initMessage{};
alice = std::make_shared<DR<Curve>>(localStorageAlice.get(), SK, AD, bobKeyPair.publicKey(), aliceDid, X3DH_initMessage);
bob = std::make_shared<DR<Curve>>(localStorageBob.get(), SK, AD, bobKeyPair, bobDid);
}
void dr_sessionsInit(std::shared_ptr<DR<Curve>> &alice, std::shared_ptr<DR<Curve>> &bob, std::shared_ptr<lime::Db> &localStorageAlice, std::shared_ptr<lime::Db> &localStorageBob, std::string dbFilenameAlice, std::string dbFilenameBob, bool initStorage=true);
/* non efficient but used friendly structure to store all details about a session */
/* the self_xx are redundants but it's for testing purpose */
......@@ -98,53 +60,10 @@ struct sessionDetails {
* users is a vector of users(already sized to correct size, matching usernames size), each one holds a vector of devices(already sized for each device)
* This function will create and instanciate in each device a vector of vector of DR sessions towards all other devices: each device vector holds a bidimentionnal array indexed by userId and deviceId.
* Session init is done considering as initial sender the lowest id user and in it the lowest id device
* createdDBfiles is filled with all filenames of DB created to allow easy deletion
*/
template <typename Curve>
void dr_devicesInit(std::string dbBaseFilename, std::vector<std::vector<std::vector<std::vector<sessionDetails<Curve>>>>> &users, std::vector<std::string> &usernames) {
/* each device must have a db, produce filename for them from provided base name and given username */
for (size_t i=0; i<users.size(); i++) { // loop on users
for (size_t j=0; j<users[i].size(); j++) { // loop on devices
// create the db for this device, filename would be <dbBaseFilename>.<username>.<dev><deviceIndex>.sqlite3
std::string dbFilename{dbBaseFilename};
dbFilename.append(".").append(usernames[i]).append(".dev").append(std::to_string(j)).append(".sqlite3");
remove(dbFilename.data());
std::shared_ptr<lime::Db> localStorage = std::make_shared<lime::Db>(dbFilename);
users[i][j].resize(users.size()); // each device holds a vector towards all users, dimension it
// instanciate the session details for all needed sessions
for (size_t i_fw=0; i_fw<users.size(); i_fw++) { // loop on the rest of users
users[i][j][i_fw].resize(users[i_fw].size()); // [i][j][i_fw] holds a vector of sessions toward user i_fw devices
for (size_t j_fw=0; j_fw<users[i].size(); j_fw++) { // loop on the rest of devices
if (!((i_fw==i) && (j_fw==j))) { // no session towards ourself
/* create session details with self and peer userId, user and device index */
sessionDetails<Curve> sessionDetail{usernames[i], i, j, usernames[i_fw], i_fw, j_fw};
sessionDetail.localStorage = localStorage;
users[i][j][i_fw][j_fw]=std::move(sessionDetail);
}
}
}
}
}
/* users is a vector of users, each of them has a vector of devices, each device hold a vector of sessions */
/* sessions init are done by users[i] to all users[>i] (same thing intra device) */
for (size_t i=0; i<users.size(); i++) { // loop on users
for (size_t j=0; j<users[i].size(); j++) { // loop on devices
for (size_t j_fw=j+1; j_fw<users[i].size(); j_fw++) { // loop on the rest of our devices
dr_sessionsInit(users[i][j][i][j_fw].DRSession, users[i][j_fw][i][j].DRSession, users[i][j][i][j_fw].localStorage, users[i][j_fw][i][j].localStorage, " ", " ", false);
}
for (size_t i_fw=i+1; i_fw<users.size(); i_fw++) { // loop on the rest of users
for (size_t j_fw=0; j_fw<users[i].size(); j_fw++) { // loop on the rest of devices
dr_sessionsInit(users[i][j][i_fw][j_fw].DRSession, users[i_fw][j_fw][i][j].DRSession, users[i][j][i_fw][j_fw].localStorage, users[i_fw][j_fw][i][j].localStorage, " ", " ", false);
}
}
}
}
}
void dr_devicesInit(std::string dbBaseFilename, std::vector<std::vector<std::vector<std::vector<sessionDetails<Curve>>>>> &users, std::vector<std::string> &usernames, std::vector<std::string> &createdDBfiles);
/* return true if the message buffer is a valid DR message holding a X3DH init one in its header */
bool DR_message_holdsX3DHInit(std::vector<uint8_t> &message);
......@@ -166,6 +85,15 @@ long int get_DRsessionsId(const std::string &dbFilename, const std::string &self
*/
std::shared_ptr<std::string> makeRandomDeviceName(const char *basename);
// template instanciation are done in lime-tester-utils.cpp
#ifdef EC25519_ENABLED
extern template void dr_sessionsInit<C255>(std::shared_ptr<DR<C255>> &alice, std::shared_ptr<DR<C255>> &bob, std::shared_ptr<lime::Db> &localStorageAlice, std::shared_ptr<lime::Db> &localStorageBob, std::string dbFilenameAlice, std::string dbFilenameBob, bool initStorage);
extern template void dr_devicesInit<C255>(std::string dbBaseFilename, std::vector<std::vector<std::vector<std::vector<sessionDetails<C255>>>>> &users, std::vector<std::string> &usernames, std::vector<std::string> &createdDBfiles);
#endif
#ifdef EC448_ENABLED
extern template void dr_sessionsInit<C448>(std::shared_ptr<DR<C448>> &alice, std::shared_ptr<DR<C448>> &bob, std::shared_ptr<lime::Db> &localStorageAlice, std::shared_ptr<lime::Db> &localStorageBob, std::string dbFilenameAlice, std::string dbFilenameBob, bool initStorage);
extern template void dr_devicesInit<C448>(std::string dbBaseFilename, std::vector<std::vector<std::vector<std::vector<sessionDetails<C448>>>>> &users, std::vector<std::string> &usernames, std::vector<std::string> &createdDBfiles);
#endif
} // namespace lime
#endif
......@@ -27,6 +27,7 @@
static FILE * log_file = NULL;
static const char *log_domain = "lime";
bool cleanDatabase = true;
// settings used in lime suite
extern std::string test_x3dh_server_url;
......@@ -93,7 +94,7 @@ int lime_tester_set_log_file(const char *filename) {
static const char* lime_helper =
"\t\t\t--verbose\n"
"\t\t\t--silent\n"
"\t\t\t--x3dh-server-url <url without protocol prefix nor port>, default : localhost\n\t\t\t a test instance shall be running on sip5.linphone.org\n"
"\t\t\t--x3dh-server-name <server name (without protocol prefix nor port)>, default : localhost\n\t\t\t a test instance shall be running on sip5.linphone.org\n"
#ifdef EC25519_ENABLED
"\t\t\t--c255-x3dh-server-port <port to use on x3dh server for instance running on curve25519>, default : 25519\n"
#endif
......@@ -101,6 +102,7 @@ static const char* lime_helper =
"\t\t\t--c448-x3dh-server-port <port to use on x3dh server for instance running on curve448>, default : 25520\n"
#endif
"\t\t\t--operation-timeout <delay in ms to complete basic operations involving server>, default : 4000, you may want to increase this if you are not using a local X3DH server\n"
"\t\t\t--keep-tmp-db, when set don't delete temporary db files created by tests, usefull for debug\n"
"\t\t\t--log-file <output log file path>\n";
......@@ -141,6 +143,8 @@ int main(int argc, char *argv[]) {
} else if (strcmp(argv[i],"--operation-timeout")==0){
CHECK_ARG("--operation-timeout", ++i, argc);
wait_for_timeout=std::atoi(argv[i]);
} else if (strcmp(argv[i],"--keep-tmp-db")==0){
cleanDatabase=false;
}else {
int ret = bc_tester_parse_args(argc, argv, i);
if (ret>0) {
......
......@@ -27,7 +27,7 @@
#include <iostream>
extern "C" {
extern bool cleanDatabase;
extern test_suite_t lime_double_ratchet_test_suite;
extern test_suite_t lime_lime_test_suite;
......
......@@ -193,7 +193,11 @@ static void dr_skippedMessages_basic_test(const uint8_t period=1, const uint8_t
for (size_t i=0; i<lime_messages_pattern.size(); i++) {
BC_ASSERT_TRUE(plainMessage[i] == lime_messages_pattern[i]);
}
bctbx_debug("End of skip test\n\n");
if (cleanDatabase) {
remove(aliceFilename.data());
remove(bobFilename.data());
}
}
static void dr_skippedMessages_basic(void) {
......@@ -276,9 +280,11 @@ static void dr_long_exchange_test(uint8_t period=1, std::string db_filename="dr_
}
}
// remove temporary db file
remove(aliceFilename.data());
remove(bobFilename.data());
if (cleanDatabase) {
// remove temporary db file
remove(aliceFilename.data());
remove(bobFilename.data());
}
}
static void dr_long_exchange1(void) {
#ifdef EC25519_ENABLED
......@@ -363,6 +369,11 @@ static void dr_basic_test(std::string db_filename) {
remove(bobFilename.data());
dr_simple_exchange(alice, bob, localStorageAlice, localStorageBob, aliceFilename, bobFilename);
if (cleanDatabase) {
remove(aliceFilename.data());
remove(bobFilename.data());
}
}
static void dr_basic(void) {
......@@ -386,7 +397,8 @@ static void dr_multidevice_basic_test(std::string db_filename) {
for (auto &user : users) user.resize(3);
/* init and instanciate, session will be then found in a 4 dimensional vector indexed this way : [self user id][self device id][peer user id][peer device id] */
dr_devicesInit(db_filename, users, usernames);
std::vector<std::string> created_db_files{};
dr_devicesInit(db_filename, users, usernames, created_db_files);
/* Send a message from alice.dev0 to all bob device(and copy to alice devices too) */
std::vector<recipientInfos<Curve>> recipients;
......@@ -432,6 +444,12 @@ static void dr_multidevice_basic_test(std::string db_filename) {
}
}
}
if (cleanDatabase) {
for (auto &filename : created_db_files) {
remove(filename.data());
}
}
}
static void dr_multidevice_basic(void) {
......@@ -547,6 +565,11 @@ static void dr_skip_too_much_test(std::string db_filename) {
recipientDRSessions.push_back(bob);
plainBuffer.clear();
BC_ASSERT_TRUE (decryptMessage("alice", "bob", "bob", recipientDRSessions, lostRecipients[0].cipherHeader, aliceCipher, plainBuffer) == nullptr); // decrypt must fail without throwing any exception
if (cleanDatabase) {
remove(aliceFilename.data());
remove(bobFilename.data());
}
}
static void dr_skip_too_much(void) {
......
This diff is collapsed.
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