lime-tester-utils.hpp 8.45 KB
Newer Older
johan's avatar
johan committed
1 2
/*
	lime-tester-utils.hpp
johan's avatar
johan committed
3 4
	@author Johan Pascal
	@copyright 	Copyright (C) 2017  Belledonne Communications SARL
johan's avatar
johan committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

	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 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef lime_tester_utils_hpp
#define lime_tester_utils_hpp

#include "bctoolbox/crypto.h"
#include "lime_double_ratchet.hpp"
#include "lime_localStorage.hpp"
26
#include "belle-sip/belle-sip.h"
johan's avatar
johan committed
27 28 29

#include "soci/sqlite3/soci-sqlite3.h"

30
using namespace::lime;
johan's avatar
johan committed
31

32 33 34 35 36 37
namespace lime_tester {

extern std::vector<std::string> messages_pattern;

// default value for the timeout
extern int wait_for_timeout;
johan's avatar
johan committed
38

johan's avatar
johan committed
39 40 41
// default value for initial OPk batch size, keep it small so not too many OPks generated
extern uint16_t OPkInitialBatchSize;

johan's avatar
johan committed
42 43 44 45 46 47
/**
 * @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>
48
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, bctbx_rng_context_t *RNG_context);
johan's avatar
johan committed
49

johan's avatar
johan committed
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72

/* non efficient but used friendly structure to store all details about a session */
/* the self_xx are redundants but it's for testing purpose */
template <typename Curve>
struct sessionDetails {
	std::string self_userId;
	std::size_t self_userIndex;
	std::size_t self_deviceIndex;
	std::string peer_userId;
	std::size_t peer_userIndex;
	std::size_t peer_deviceIndex;
	std::shared_ptr<DR<Curve>> DRSession; // Session to reach recipient
	std::shared_ptr<lime::Db> localStorage; // db linked to device
	sessionDetails() : self_userId{}, self_userIndex{0}, self_deviceIndex{0}, peer_userId{}, peer_userIndex{0}, peer_deviceIndex{0}, DRSession{}, localStorage{} {};
	sessionDetails(std::string &s_userId, size_t s_userIndex, size_t s_deviceIndex, std::string &p_userId, size_t p_userIndex, size_t p_deviceIndex)
		: self_userId{s_userId}, self_userIndex{s_userIndex}, self_deviceIndex{s_deviceIndex}, peer_userId{p_userId}, peer_userIndex{p_userIndex}, peer_deviceIndex{p_deviceIndex}, DRSession{}, localStorage{} {};
};

/**
 * @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
johan's avatar
johan committed
73
 * createdDBfiles is filled with all filenames of DB created to allow easy deletion
johan's avatar
johan committed
74 75
 */
template <typename Curve>
76
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, bctbx_rng_context_t *RNG_context);
johan's avatar
johan committed
77 78 79

/* 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);
80 81
/* this version will set the OPk status in the given bool if a packet is found */
bool DR_message_holdsX3DHInit(std::vector<uint8_t> &message, bool &haveOPk);
johan's avatar
johan committed
82 83 84 85

/* return true if the message buffer is a valid DR message holding a X3DH init one in its header and copy the X3DH init message in the provided buffer */
bool DR_message_extractX3DHInit(std::vector<uint8_t> &message, std::vector<uint8_t> &X3DH_initMessage);

johan's avatar
johan committed
86 87 88
/* return true if the message buffer is a valid DR message holding an X3DH init message, copy its SPk id in the given parameter */
bool DR_message_extractX3DHInit_SPkId(std::vector<uint8_t> &message, uint32_t &SPkId);

johan's avatar
johan committed
89 90 91
/* Open provided DB and look for DRSessions established between selfDevice and peerDevice
 * Populate the sessionsId vector with the Ids of sessions found
 * return the id of the active session if one is found, 0 otherwise */
92 93 94 95 96 97 98 99
long int get_DRsessionsId(const std::string &dbFilename, const std::string &selfDeviceId, const std::string &peerDeviceId, std::vector<long int> &sessionsId) noexcept;


/* Open provided DB, look for DRSessions established between selfDevice and peerDevice, count the stored message keys in all these sessions
 * return 0 if no sessions found or no user found
 */
unsigned int get_StoredMessageKeyCount(const std::string &dbFilename, const std::string &selfDeviceId, const std::string &peerDeviceId) noexcept;

johan's avatar
johan committed
100 101 102 103 104
/* For the given deviceId, count the number of associated SPk and return the Id of the active one(if any)
 * return true if an active one was found
 */
bool get_SPks(const std::string &dbFilename, const std::string &selfDeviceId, size_t &count, uint32_t &activeId) noexcept;

105 106 107 108
/* For the given deviceId, count the number of associated OPk
 */
size_t get_OPks(const std::string &dbFilename, const std::string &selfDeviceId) noexcept;

109 110 111 112
/* Move back in time all timeStamps by the given amout of days
 * DB holds timeStamps in DR_sessions and X3DH_SPK tables
 */
void forwardTime(const std::string &dbFilename, int days) noexcept;
johan's avatar
johan committed
113 114 115 116 117 118 119 120 121 122

/**
 * @brief append a random suffix to user name to avoid collision if test server is user by several tests runs
 *
 * @param[in] basename
 *
 * @return a shared ptr towards a string holding name+ 6 chars random suffix
 */
std::shared_ptr<std::string> makeRandomDeviceName(const char *basename);

johan's avatar
johan committed
123 124 125 126 127 128 129 130 131 132 133 134 135

// wait for a counter to reach a value or timeout to occur, gives ticks to the belle-sip stack every SLEEP_TIME
// structure used by callbacks to register events
struct events_counters_t {
	int operation_success;
	int operation_failed;
	events_counters_t() : operation_success{0}, operation_failed{0} {};
	bool operator==(const events_counters_t &b) const {return this->operation_success==b.operation_success && this->operation_failed==b.operation_failed;}
};

// wait for a counter to reach a value or timeout to occur, gives ticks to the belle-sip stack every SLEEP_TIME
int wait_for(belle_sip_stack_t*s1,int* counter,int value,int timeout);

johan's avatar
johan committed
136 137
// template instanciation are done in lime-tester-utils.cpp
#ifdef EC25519_ENABLED
138 139
	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, bctbx_rng_context_t *RNG_context); 
	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,  bctbx_rng_context_t *RNG_context);
johan's avatar
johan committed
140 141
#endif
#ifdef EC448_ENABLED
142 143
	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,  bctbx_rng_context_t *RNG_context); 
	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,  bctbx_rng_context_t *RNG_context);
johan's avatar
johan committed
144
#endif
145 146 147 148 149 150

// the test server has only one user registered but accept commands from any users using this credentials
// a real server would obviously not do that and execute commands based on the username given as credentials
// not based on the From field of HTPP packets
const std::string test_server_user_name{"alice"};
const std::string test_server_user_password{"you see the problem is this"};
151

152
} // namespace lime_tester
johan's avatar
johan committed
153 154

#endif