Commit 35c220d1 authored by johan's avatar johan
Browse files

Improve the peer device status management

- improve the set_peerDeviceStatus
- add a delete_peerDevice function
parent 867e55f4
......@@ -248,9 +248,25 @@ namespace lime {
* @param[in] status value of flag to set: accepted values are trusted, untrusted, unsafe
*
* throw an exception if given key doesn't match the one present in local storage
* throw an exception if the status flag value is unexpected (not one of trusted, untrusted, unsafe)
* if the status flag value is unexpected (not one of trusted, untrusted, unsafe), ignore the call
* if the status flag is unsafe or untrusted, ignore the value of Ik and call the version of this function without it
*
* if peer Device is not present in local storage and status is trusted or unsafe, it is added, if status is untrusted, it is just ignored
*
* General algorithm followed by the set_peerDeviceStatus functions
* - Status is valid? (not one of trusted, untrusted, unsafe)? No: return
* - status is trusted
* - We have Ik? -> No: return
* - Device is already in storage but Ik differs from the given one : exception
* - Insert/update in local storage
* - status is untrusted
* - Ik is ignored
* - Device already in storage? No: return
* - Device already in storage but current status is unsafe? Yes: return
* - update in local storage
* -status is unsafe
* - ignore Ik
* - insert/update the status. If inserted, insert an invalid Ik
*/
void set_peerDeviceStatus(const std::string &peerDeviceId, const std::vector<uint8_t> &Ik, lime::PeerDeviceStatus status);
......@@ -261,9 +277,11 @@ namespace lime {
* @param[in] peerDeviceId The device Id of peer, shall be its GRUU
* @param[in] status value of flag to set: accepted values are untrusted or unsafe
*
* throw an exception if the status flag value is unexpected (not one of untrusted, unsafe)
* if the status flag value is unexpected (not one of untrusted, unsafe), ignore the call
*
* if peer Device is not present in local storage, it is just ignored
* if peer Device is not present in local storage, it is inserted if status is unsafe and call is ignored if status is untrusted
* if the status is untrusted but the current status in local storage is unsafe, ignore the call
* Any call to the other form of the function with a status to unsafe or untrusted is rerouted to this function
*/
void set_peerDeviceStatus(const std::string &peerDeviceId, lime::PeerDeviceStatus status);
......@@ -276,6 +294,15 @@ namespace lime {
*/
lime::PeerDeviceStatus get_peerDeviceStatus(const std::string &peerDeviceId);
/**
* @delete a peerDevice from local storage
*
* @param[in] peerDeviceId The device Id to be removed from local storage, shall be its GRUU
*
* Call is silently ignored if the device is not found in local storage
*/
void delete_peerDevice(const std::string &peerDeviceId);
LimeManager() = delete; // no manager without Database and http provider
LimeManager(const LimeManager&) = delete; // no copy constructor
LimeManager operator=(const LimeManager &) = delete; // nor copy operator
......
......@@ -117,6 +117,11 @@ namespace lime {
postToX3DHServer(userData, X3DHmessage);
}
template <typename Curve>
void Lime<Curve>::delete_peerDevice(const std::string &peerDeviceId) {
m_DR_sessions_cache.erase(peerDeviceId); // remove session from cache if any
}
template <typename Curve>
void Lime<Curve>::update_SPk(const limeCallback &callback) {
// Do we need to update the SPk
......
......@@ -106,6 +106,7 @@ namespace lime {
void publish_user(const limeCallback &callback, const uint16_t OPkInitialBatchSize) override;
void delete_user(const limeCallback &callback) override;
void delete_peerDevice(const std::string &peerDeviceId) override;
/**
* @brief Check if the current SPk needs to be updated, if yes, generate a new one and publish it on server
......
......@@ -97,6 +97,13 @@ namespace lime {
*/
virtual void delete_user(const limeCallback &callback) = 0;
/**
* @brief Purge cached sessions for a given peer Device (used when a peer device is being deleted)
*
* @param[in] peerDeviceId The peer device to remove from cache
*/
virtual void delete_peerDevice(const std::string &peerDeviceId) = 0;
// User keys management
......
......@@ -163,6 +163,10 @@ Db::Db(std::string filename) : sql{sqlite3, filename}{
* The mapping is done in lime.hpp by the PeerDeviceStatus enum class definition
*
* Note: peer device information is shared by all local device, hence they are not linked to particular local devices from lime_LocalUsers table
*
* Note2: The Ik field should be able to be NULL but it is not for historical reason.
* When a peer device is inserted without Ik(through the set_peerDeviceStatus with a unsafe status is the only way to do that)
* it will be given an Ik set to invalid_Ik (one byte at 0x00) with the purpose of being unable to match a real Ik as NULL would have done
*/
sql<<"CREATE TABLE lime_PeerDevices( \
Did INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, \
......@@ -289,16 +293,37 @@ void Db::get_allLocalDevices(std::vector<std::string> &deviceIds) {
* @param[in] status value of flag to set: accepted values are trusted, untrusted, unsafe
*
* throw an exception if given key doesn't match the one present in local storage
* throw an exception if the status flag value is unexpected (not one of trusted, untrusted, unsafe)
* if the status flag value is unexpected (not one of trusted, untrusted, unsafe), ignore the call
* if the status flag is unsafe or untrusted, ignore the value of Ik and call the version of this function without it
*
* if peer Device is not present in local storage and status is trusted or unsafe, it is added, if status is untrusted, it is just ignored
*
* General algorithm followed by the set_peerDeviceStatus functions
* - Status is valid? (not one of trusted, untrusted, unsafe)? No: return
* - status is trusted
* - We have Ik? -> No: return
* - Device is already in storage but Ik differs from the given one : exception
* - Insert/update in local storage
* - status is untrusted
* - Ik is ignored
* - Device already in storage? No: return
* - Device already in storage but current status is unsafe? Yes: return
* - update in local storage
* -status is unsafe
* - ignore Ik
* - insert/update the status. If inserted, insert an invalid Ik
*/
void Db::set_peerDeviceStatus(const std::string &peerDeviceId, const std::vector<uint8_t> &Ik, lime::PeerDeviceStatus status) {
// Check the status flag value, accepted values are: trusted, untrusted, unsafe
if (status != lime::PeerDeviceStatus::unsafe
&& status != lime::PeerDeviceStatus::untrusted
&& status != lime::PeerDeviceStatus::trusted) {
throw BCTBX_EXCEPTION << "Trying to set a status for peer device "<<peerDeviceId<<" which is not acceptable (differs from unsafe, untrusted or trusted)";
// if status is unsafe or untrusted, call the variant without Ik
if (status == lime::PeerDeviceStatus::unsafe || status == lime::PeerDeviceStatus::untrusted) {
this->set_peerDeviceStatus(peerDeviceId, status);
return;
}
// Check the status flag value, accepted values are: trusted (unsafe and untrusted are already managed)
if (status != lime::PeerDeviceStatus::trusted) {
LIME_LOGE<< "Trying to set a status for peer device "<<peerDeviceId<<" which is not acceptable (differs from unsafe, untrusted or trusted), ignore that";
return;
}
uint8_t statusInteger = static_cast<uint8_t>(status);
......@@ -334,24 +359,52 @@ void Db::set_peerDeviceStatus(const std::string &peerDeviceId, const std::vector
* @param[in] peerDeviceId The device Id of peer, shall be its GRUU
* @param[in] status value of flag to set: accepted values are untrusted or unsafe
*
* throw an exception if the status flag value is unexpected (not one of untrusted, unsafe)
* if the status flag value is unexpected (not one of untrusted, unsafe), ignore the call
*
* if peer Device is not present in local storage, it is just ignored
* if peer Device is not present in local storage, it is inserted if status is unsafe and call is ignored if status is untrusted
* if the status is untrusted but the current status in local storage is unsafe, ignore the call
* Any call to the other form of the function with a status to unsafe or untrusted is rerouted to this function
*/
void Db::set_peerDeviceStatus(const std::string &peerDeviceId, lime::PeerDeviceStatus status) {
// Check the status flag value, accepted values are: untrusted, unsafe
if (status != lime::PeerDeviceStatus::unsafe
&& status != lime::PeerDeviceStatus::untrusted) {
throw BCTBX_EXCEPTION << "Trying to set a status for peer device "<<peerDeviceId<<" without providing a Ik which is not acceptable (differs from unsafe or untrusted)";
LIME_LOGE << "Trying to set a status for peer device "<<peerDeviceId<<" without providing a Ik which is not acceptable (differs from unsafe or untrusted)";
return;
}
uint8_t statusInteger = static_cast<uint8_t>(status);
// Do we have this peerDevice in lime_PeerDevices
// is this peerDevice already in local storage?
bool inLocalStorage = false;
long long id;
sql<<"SELECT Did FROM Lime_PeerDevices WHERE DeviceId = :peerDeviceId;", into(id), use(peerDeviceId);
if (sql.got_data()) { // Found it
int currentStatus;
sql<<"SELECT Did, Status FROM Lime_PeerDevices WHERE DeviceId = :peerDeviceId;", into(id), into(currentStatus), use(peerDeviceId);
inLocalStorage = sql.got_data();
// if status is untrusted
if (status == lime::PeerDeviceStatus::untrusted) {
// and we do not already have that device in local storage -> log it and ignore the call
if (!inLocalStorage) {
LIME_LOGW << "Trying to set a status untrusted for peer device "<<peerDeviceId<<" not present in local storage, ignore that call)";
return;
}
// and the current status in local storage is unsafe, keep unsafe
if (currentStatus == static_cast<uint8_t>(lime::PeerDeviceStatus::unsafe)) {
LIME_LOGW << "Trying to set a status untrusted for peer device "<<peerDeviceId<<" but its current status is unsafe, ignore that call)";
return;
}
}
// update or insert
if (inLocalStorage) {
sql<<"UPDATE Lime_PeerDevices SET Status = :Status WHERE Did = :id;", use(statusInteger), use(id);
} else {
// this constant is set into lime_peerDevices table, Ik field when it is not provided by set_peerDeviceStatus as this field can't be set to NULL in older version of the database
constexpr uint8_t invalid_Ik = 0x00;
blob Ik_insert_blob(sql);
Ik_insert_blob.write(0, (char *)(&invalid_Ik), sizeof(invalid_Ik));
sql<<"INSERT INTO Lime_PeerDevices(DeviceId, Ik, Status) VALUES(:peerDeviceId, :Ik, :Status);", use(peerDeviceId), use(Ik_insert_blob), use(statusInteger);
}
}
......@@ -382,6 +435,17 @@ lime::PeerDeviceStatus Db::get_peerDeviceStatus(const std::string &peerDeviceId)
return lime::PeerDeviceStatus::unknown;
}
/**
* @delete a peerDevice from local storage
*
* @param[in] peerDeviceId The device Id to be removed from local storage, shall be its GRUU
*
* Call is silently ignored if the device is not found in local storage
*/
void Db::delete_peerDevice(const std::string &peerDeviceId) {
sql<<"DELETE FROM lime_peerDevices WHERE DeviceId = :peerDeviceId;", use(peerDeviceId);
}
/**
* @brief Check peer device information(DeviceId - GRUU -, public Ik, Uid to link it to a user) in local storage
*
......
......@@ -95,9 +95,25 @@ namespace lime {
* @param[in] status value of flag to set: accepted values are trusted, untrusted, unsafe
*
* throw an exception if given key doesn't match the one present in local storage
* throw an exception if the status flag value is unexpected (not one of trusted, untrusted, unsafe)
* if the status flag value is unexpected (not one of trusted, untrusted, unsafe), ignore the call
* if the status flag is unsafe or untrusted, ignore the value of Ik and call the version of this function without it
*
* if peer Device is not present in local storage and status is trusted or unsafe, it is added, if status is untrusted, it is just ignored
*
* General algorithm followed by the set_peerDeviceStatus functions
* - Status is valid? (not one of trusted, untrusted, unsafe)? No: return
* - status is trusted
* - We have Ik? -> No: return
* - Device is already in storage but Ik differs from the given one : exception
* - Insert/update in local storage
* - status is untrusted
* - Ik is ignored
* - Device already in storage? No: return
* - Device already in storage but current status is unsafe? Yes: return
* - update in local storage
* -status is unsafe
* - ignore Ik
* - insert/update the status. If inserted, insert an invalid Ik
*/
void set_peerDeviceStatus(const std::string &peerDeviceId, const std::vector<uint8_t> &Ik, lime::PeerDeviceStatus status);
......@@ -108,9 +124,11 @@ namespace lime {
* @param[in] peerDeviceId The device Id of peer, shall be its GRUU
* @param[in] status value of flag to set: accepted values are untrusted or unsafe
*
* throw an exception if the status flag value is unexpected (not one of untrusted, unsafe)
* if the status flag value is unexpected (not one of untrusted, unsafe), ignore the call
*
* if peer Device is not present in local storage, it is just ignored
* if peer Device is not present in local storage, it is inserted if status is unsafe and call is ignored if status is untrusted
* if the status is untrusted but the current status in local storage is unsafe, ignore the call
* Any call to the other form of the function with a status to unsafe or untrusted is rerouted to this function
*/
void set_peerDeviceStatus(const std::string &peerDeviceId, lime::PeerDeviceStatus status);
......@@ -124,6 +142,15 @@ namespace lime {
*/
lime::PeerDeviceStatus get_peerDeviceStatus(const std::string &peerDeviceId);
/**
* @delete a peerDevice from local storage
*
* @param[in] peerDeviceId The device Id to be removed from local storage, shall be its GRUU
*
* Call is silently ignored if the device is not found in local storage
*/
void delete_peerDevice(const std::string &peerDeviceId);
/**
* @brief check if the given peer Device information are in the local storage
* raise an exception if a different Ik is found for the given peer Device Id
......
......@@ -191,4 +191,17 @@ namespace lime {
return localStorage->get_peerDeviceStatus(peerDeviceId);
}
void LimeManager::delete_peerDevice(const std::string &peerDeviceId) {
// loop on all local users in cache to destroy any cached session linked to that user
for (auto userElem : m_users_cache) {
userElem.second->delete_peerDevice(peerDeviceId);
}
// open local DB
auto localStorage = std::unique_ptr<lime::Db>(new lime::Db(m_db_access));
localStorage->delete_peerDevice(peerDeviceId);
}
} // namespace lime
......@@ -707,6 +707,7 @@ static void lime_identityVerifiedStatus_test(const lime::CurveId curve, const st
lime_tester::events_counters_t counters={};
int expected_success=0;
int expected_failure=0;
limeCallback callback([&counters](lime::CallbackReturn returnCode, std::string anythingToSay) {
if (returnCode == lime::CallbackReturn::success) {
......@@ -723,6 +724,7 @@ static void lime_identityVerifiedStatus_test(const lime::CurveId curve, const st
std::shared_ptr<std::string> bobDeviceId = nullptr;
std::vector<uint8_t> aliceIk{};
std::vector<uint8_t> bobIk{};
std::vector<uint8_t> fakeIk{};
try {
// create Manager and device for alice and bob
......@@ -738,6 +740,10 @@ static void lime_identityVerifiedStatus_test(const lime::CurveId curve, const st
// retrieve their respective Ik
aliceManager->get_selfIdentityKey(*aliceDeviceId, aliceIk);
bobManager->get_selfIdentityKey(*bobDeviceId, bobIk);
// build the fake alice Ik
fakeIk = aliceIk;
fakeIk[0] ^= 0xFF;
// check their status: they don't know each other
BC_ASSERT_TRUE(aliceManager->get_peerDeviceStatus(*bobDeviceId) == lime::PeerDeviceStatus::unknown);
......@@ -750,49 +756,83 @@ static void lime_identityVerifiedStatus_test(const lime::CurveId curve, const st
bobManager->set_peerDeviceStatus(*aliceDeviceId, aliceIk, lime::PeerDeviceStatus::unsafe);
BC_ASSERT_TRUE(bobManager->get_peerDeviceStatus(*aliceDeviceId) == lime::PeerDeviceStatus::unsafe);
// reset it to untrusted and check it worked : now Bob knows alice but he doesn't trust her
// reset it to untrusted and check it is still unsafe : we can escape unsafe only by setting to safe
bobManager->set_peerDeviceStatus(*aliceDeviceId, aliceIk, lime::PeerDeviceStatus::untrusted);
BC_ASSERT_TRUE(bobManager->get_peerDeviceStatus(*aliceDeviceId) == lime::PeerDeviceStatus::unsafe);
// set alice Id key as verified and check it this time it worked
bobManager->set_peerDeviceStatus(*aliceDeviceId, aliceIk, lime::PeerDeviceStatus::trusted);
BC_ASSERT_TRUE(bobManager->get_peerDeviceStatus(*aliceDeviceId) == lime::PeerDeviceStatus::trusted);
// set to untrusted without using alice Ik
bobManager->set_peerDeviceStatus(*aliceDeviceId, lime::PeerDeviceStatus::untrusted);
BC_ASSERT_TRUE(bobManager->get_peerDeviceStatus(*aliceDeviceId) == lime::PeerDeviceStatus::untrusted);
// set to unsafe without using alice Ik
bobManager->set_peerDeviceStatus(*aliceDeviceId, lime::PeerDeviceStatus::unsafe);
BC_ASSERT_TRUE(bobManager->get_peerDeviceStatus(*aliceDeviceId) == lime::PeerDeviceStatus::unsafe);
// set to untrusted without using alice Ik
bobManager->set_peerDeviceStatus(*aliceDeviceId, lime::PeerDeviceStatus::untrusted);
// try to set it to trusted without giving the Ik, it shall be ignored
bobManager->set_peerDeviceStatus(*aliceDeviceId, lime::PeerDeviceStatus::trusted);
BC_ASSERT_TRUE(bobManager->get_peerDeviceStatus(*aliceDeviceId) == lime::PeerDeviceStatus::unsafe);
// set it back to trusted and check it this time it worked
bobManager->set_peerDeviceStatus(*aliceDeviceId, aliceIk, lime::PeerDeviceStatus::trusted);
BC_ASSERT_TRUE(bobManager->get_peerDeviceStatus(*aliceDeviceId) == lime::PeerDeviceStatus::trusted);
// try to set it to unknown, it shall be ignored
bobManager->set_peerDeviceStatus(*aliceDeviceId, aliceIk, lime::PeerDeviceStatus::unknown);
BC_ASSERT_TRUE(bobManager->get_peerDeviceStatus(*aliceDeviceId) == lime::PeerDeviceStatus::trusted);
// try to set it to fail, it shall be ignored
bobManager->set_peerDeviceStatus(*aliceDeviceId, aliceIk, lime::PeerDeviceStatus::fail);
BC_ASSERT_TRUE(bobManager->get_peerDeviceStatus(*aliceDeviceId) == lime::PeerDeviceStatus::trusted);
// try to set another key for alice in bob's context, setting it to untrusted, it shall be ok as the Ik is ignored when setting to untrusted
bobManager->set_peerDeviceStatus(*aliceDeviceId, fakeIk, lime::PeerDeviceStatus::untrusted);
BC_ASSERT_TRUE(bobManager->get_peerDeviceStatus(*aliceDeviceId) == lime::PeerDeviceStatus::untrusted);
// same goes for unsafe
bobManager->set_peerDeviceStatus(*aliceDeviceId, fakeIk, lime::PeerDeviceStatus::unsafe);
BC_ASSERT_TRUE(bobManager->get_peerDeviceStatus(*aliceDeviceId) == lime::PeerDeviceStatus::unsafe);
// set it back to trusted with the real key, it shall be Ok as it is still the one present in local storage
bobManager->set_peerDeviceStatus(*aliceDeviceId, aliceIk, lime::PeerDeviceStatus::trusted);
BC_ASSERT_TRUE(bobManager->get_peerDeviceStatus(*aliceDeviceId) == lime::PeerDeviceStatus::trusted);
} catch (BctbxException &e) {
LIME_LOGE <<e;;
BC_FAIL();
}
auto gotException = false;
// set it to trusted without giving the Ik, it shall generate an exception
try {
bobManager->set_peerDeviceStatus(*aliceDeviceId, lime::PeerDeviceStatus::trusted);
// try to set another key for alice in bob's context, it shall generate an exception
bobManager->set_peerDeviceStatus(*aliceDeviceId, fakeIk, lime::PeerDeviceStatus::trusted);
} catch (BctbxException &e) {
BC_PASS();
gotException = true;
}
BC_ASSERT_TRUE(gotException);
gotException = false;
// Now delete the alice device from Bob's cache and check its status is now back to unknown
bobManager->delete_peerDevice(*aliceDeviceId);
BC_ASSERT_TRUE(bobManager->get_peerDeviceStatus(*aliceDeviceId) == lime::PeerDeviceStatus::unknown);
// set it to unknown, it shall generate an exception
try {
bobManager->set_peerDeviceStatus(*aliceDeviceId, aliceIk, lime::PeerDeviceStatus::unknown);
} catch (BctbxException &e) {
BC_PASS();
gotException = true;
// set the device with the fake Ik but to untrusted so it won't be actually stored and shall still be unknown
bobManager->set_peerDeviceStatus(*aliceDeviceId, fakeIk, lime::PeerDeviceStatus::untrusted);
BC_ASSERT_TRUE(bobManager->get_peerDeviceStatus(*aliceDeviceId) == lime::PeerDeviceStatus::unknown);
// set the device with the fake Ik but to unsafe so the key shall not be registered in base but the user will
bobManager->set_peerDeviceStatus(*aliceDeviceId, fakeIk, lime::PeerDeviceStatus::unsafe);
BC_ASSERT_TRUE(bobManager->get_peerDeviceStatus(*aliceDeviceId) == lime::PeerDeviceStatus::unsafe);
}
BC_ASSERT_TRUE(gotException);
gotException = false;
// set it to fail, it shall generate an exception
try {
bobManager->set_peerDeviceStatus(*aliceDeviceId, aliceIk, lime::PeerDeviceStatus::fail);
// try to set it to trusted, still using the fake Ik, it shall generate an exception as the Ik is invalid in storage
bobManager->set_peerDeviceStatus(*aliceDeviceId, fakeIk, lime::PeerDeviceStatus::trusted);
} catch (BctbxException &e) {
BC_PASS();
gotException = true;
......@@ -801,29 +841,35 @@ static void lime_identityVerifiedStatus_test(const lime::CurveId curve, const st
BC_ASSERT_TRUE(gotException);
gotException = false;
// try to set another key for alice in bob's context, it shall generate an exception
try {
// copy alice Ik but modify it
std::vector<uint8_t> fakeIk = aliceIk;
fakeIk[0] ^= 0xFF;
bobManager->set_peerDeviceStatus(*aliceDeviceId, fakeIk, lime::PeerDeviceStatus::trusted);
// same than above but using the actual key : try to set it to trusted, still using the fake Ik, it shall generate an exception as the Ik is invalid in storage
bobManager->set_peerDeviceStatus(*aliceDeviceId, aliceIk, lime::PeerDeviceStatus::trusted);
} catch (BctbxException &e) {
BC_PASS();
gotException = true;
}
BC_ASSERT_TRUE(gotException);
// Now delete the alice device from Bob's cache and check its status is now back to unknown
bobManager->delete_peerDevice(*aliceDeviceId);
BC_ASSERT_TRUE(bobManager->get_peerDeviceStatus(*aliceDeviceId) == lime::PeerDeviceStatus::unknown);
}
try {
// Bob encrypts a message for Alice, alice device status shall be : untrusted(it is the first message bob sends but he already knows about alice's device)
// Bob encrypts a message for Alice, alice device status shall be : unknown(it is the first message bob sends and alice is not in cache)
auto bobRecipients = make_shared<std::vector<RecipientData>>();
bobRecipients->emplace_back(*aliceDeviceId);
auto bobMessage = make_shared<const std::vector<uint8_t>>(lime_tester::messages_pattern[0].begin(), lime_tester::messages_pattern[0].end());
auto bobCipherMessage = make_shared<std::vector<uint8_t>>();
bobManager->encrypt(*bobDeviceId, make_shared<const std::string>("alice"), bobRecipients, bobMessage, bobCipherMessage, callback);
BC_ASSERT_TRUE(lime_tester::wait_for(stack,&counters.operation_success,++expected_success,lime_tester::wait_for_timeout));
BC_ASSERT_TRUE((*bobRecipients)[0].peerStatus == lime::PeerDeviceStatus::unknown);
// Bob encrypts a second message for Alice, alice device status shall now be : untrusted(we know that device but didn't share the trust yet)
bobRecipients = make_shared<std::vector<RecipientData>>();
bobRecipients->emplace_back(*aliceDeviceId);
bobMessage = make_shared<const std::vector<uint8_t>>(lime_tester::messages_pattern[1].begin(), lime_tester::messages_pattern[1].end());
bobCipherMessage = make_shared<std::vector<uint8_t>>();
bobManager->encrypt(*bobDeviceId, make_shared<const std::string>("alice"), bobRecipients, bobMessage, bobCipherMessage, callback);
BC_ASSERT_TRUE(lime_tester::wait_for(stack,&counters.operation_success,++expected_success,lime_tester::wait_for_timeout));
BC_ASSERT_TRUE((*bobRecipients)[0].peerStatus == lime::PeerDeviceStatus::untrusted);
// set again the key as verified in bob's context
......@@ -833,14 +879,14 @@ static void lime_identityVerifiedStatus_test(const lime::CurveId curve, const st
// Bob encrypts a message for Alice, alice device status shall now be : trusted
bobRecipients = make_shared<std::vector<RecipientData>>();
bobRecipients->emplace_back(*aliceDeviceId);
bobMessage = make_shared<const std::vector<uint8_t>>(lime_tester::messages_pattern[1].begin(), lime_tester::messages_pattern[1].end());
bobMessage = make_shared<const std::vector<uint8_t>>(lime_tester::messages_pattern[2].begin(), lime_tester::messages_pattern[2].end());
bobCipherMessage = make_shared<std::vector<uint8_t>>();
bobManager->encrypt(*bobDeviceId, make_shared<const std::string>("alice"), bobRecipients, bobMessage, bobCipherMessage, callback);
BC_ASSERT_TRUE(lime_tester::wait_for(stack,&counters.operation_success,++expected_success,lime_tester::wait_for_timeout));
BC_ASSERT_TRUE((*bobRecipients)[0].peerStatus == lime::PeerDeviceStatus::trusted);
// set a fake bob key in alice context(set is as verified otherwise the request is just ignored)
std::vector<uint8_t> fakeIk = bobIk;
fakeIk = bobIk;
fakeIk[0] ^= 0xFF;
aliceManager->set_peerDeviceStatus(*bobDeviceId, fakeIk, lime::PeerDeviceStatus::trusted);
......@@ -851,11 +897,68 @@ static void lime_identityVerifiedStatus_test(const lime::CurveId curve, const st
// alice now try to encrypt to Bob but it will fail as key fetched from X3DH server won't match the one we assert as verified
auto aliceRecipients = make_shared<std::vector<RecipientData>>();
aliceRecipients->emplace_back(*bobDeviceId);
auto aliceMessage = make_shared<const std::vector<uint8_t>>(lime_tester::messages_pattern[2].begin(), lime_tester::messages_pattern[2].end());
auto aliceMessage = make_shared<const std::vector<uint8_t>>(lime_tester::messages_pattern[3].begin(), lime_tester::messages_pattern[3].end());
auto aliceCipherMessage = make_shared<std::vector<uint8_t>>();
aliceManager->encrypt(*aliceDeviceId, make_shared<const std::string>("bob"), aliceRecipients, aliceMessage, aliceCipherMessage, callback);
BC_ASSERT_TRUE(lime_tester::wait_for(stack,&counters.operation_failed,1,lime_tester::wait_for_timeout));
BC_ASSERT_TRUE(lime_tester::wait_for(stack,&counters.operation_failed,++expected_failure,lime_tester::wait_for_timeout));
// delete bob's key from alice context and just set it to unsafe, he will get then no Ik in local storage
aliceManager->delete_peerDevice(*bobDeviceId);
BC_ASSERT_TRUE(aliceManager->get_peerDeviceStatus(*bobDeviceId) == lime::PeerDeviceStatus::unknown);
aliceManager->set_peerDeviceStatus(*bobDeviceId, lime::PeerDeviceStatus::unsafe);
BC_ASSERT_TRUE(aliceManager->get_peerDeviceStatus(*bobDeviceId) == lime::PeerDeviceStatus::unsafe);
// delete alice's key from Bob context, it will delete all session associated to Alice so when we encrypt a new message, it will fetch a new OPk as the previous one was deleted by alice
bobManager->delete_peerDevice(*aliceDeviceId);
BC_ASSERT_TRUE(bobManager->get_peerDeviceStatus(*aliceDeviceId) == lime::PeerDeviceStatus::unknown);
// Bob encrypts a message for Alice, alice device status shall be : unknown(it is the first message bob sends and alice is not in cache)
bobRecipients = make_shared<std::vector<RecipientData>>();
bobRecipients->emplace_back(*aliceDeviceId);
bobMessage = make_shared<const std::vector<uint8_t>>(lime_tester::messages_pattern[1].begin(), lime_tester::messages_pattern[1].end());
bobCipherMessage = make_shared<std::vector<uint8_t>>();
bobManager->encrypt(*bobDeviceId, make_shared<const std::string>("alice"), bobRecipients, bobMessage, bobCipherMessage, callback);
BC_ASSERT_TRUE(lime_tester::wait_for(stack,&counters.operation_success,++expected_success,lime_tester::wait_for_timeout));
BC_ASSERT_TRUE((*bobRecipients)[0].peerStatus == lime::PeerDeviceStatus::unknown);
// alice tries again to decrypt but it will fail as the identity key in X3DH init packet is not matching the invalid one set in base by setting its status to unsafe
receivedMessage.clear();
BC_ASSERT_TRUE(aliceManager->decrypt(*aliceDeviceId, "alice", *bobDeviceId, (*bobRecipients)[0].DRmessage, *bobCipherMessage, receivedMessage) == lime::PeerDeviceStatus::fail);
// alice fails again to encrypt to Bob as key fetched from X3DH server won't match the one we assert as verified
aliceRecipients = make_shared<std::vector<RecipientData>>();
aliceRecipients->emplace_back(*bobDeviceId);
aliceMessage = make_shared<const std::vector<uint8_t>>(lime_tester::messages_pattern[3].begin(), lime_tester::messages_pattern[3].end());
aliceCipherMessage = make_shared<std::vector<uint8_t>>();
aliceManager->encrypt(*aliceDeviceId, make_shared<const std::string>("bob"), aliceRecipients, aliceMessage, aliceCipherMessage, callback);
BC_ASSERT_TRUE(lime_tester::wait_for(stack,&counters.operation_failed,++expected_failure,lime_tester::wait_for_timeout));
// delete bob's key from alice context
aliceManager->delete_peerDevice(*bobDeviceId);
BC_ASSERT_TRUE(aliceManager->get_peerDeviceStatus(*bobDeviceId) == lime::PeerDeviceStatus::unknown);
// delete alice's key from Bob context, it will delete all session associated to Alice so when we encrypt a new message, it will fetch a new OPk as the previous one was deleted by alice
bobManager->delete_peerDevice(*aliceDeviceId);
BC_ASSERT_TRUE(bobManager->get_peerDeviceStatus(*aliceDeviceId) == lime::PeerDeviceStatus::unknown);
// Bob encrypts a message for Alice, alice device status shall be : unknown(it is the first message bob sends and alice is not in cache)
bobRecipients = make_shared<std::vector<RecipientData>>();
bobRecipients->emplace_back(*aliceDeviceId);
bobMessage = make_shared<const std::vector<uint8_t>>(lime_tester::messages_pattern[1].begin(), lime_tester::messages_pattern[1].end());
bobCipherMessage = make_shared<std::vector<uint8_t>>();
bobManager->encrypt(*bobDeviceId, make_shared<const std::string>("alice"), bobRecipients, bobMessage, bobCipherMessage, callback);
BC_ASSERT_TRUE(lime_tester::wait_for(stack,&counters.operation_success,++expected_success,lime_tester::wait_for_timeout));
BC_ASSERT_TRUE((*bobRecipients)[0].peerStatus == lime::PeerDeviceStatus::unknown);
// alice tries again to decrypt but it shall work and return status unknown as we just deleted bob's device
receivedMessage.clear();
BC_ASSERT_TRUE(aliceManager->decrypt(*aliceDeviceId, "alice", *bobDeviceId, (*bobRecipients)[0].DRmessage, *bobCipherMessage, receivedMessage) == lime::PeerDeviceStatus::unknown);
auto receivedMessageString = std::string{receivedMessage.begin(), receivedMessage.end()};
BC_ASSERT_TRUE(receivedMessageString == lime_tester::messages_pattern[1]);
// now set bob's to trusted in alice cache, it shall work as key retrieved from X3DH init message during decryption match the one we're giving
aliceManager->set_peerDeviceStatus(*bobDeviceId, bobIk, lime::PeerDeviceStatus::trusted);
BC_ASSERT_TRUE(aliceManager->get_peerDeviceStatus(*bobDeviceId) == lime::PeerDeviceStatus::trusted);
if (cleanDatabase) {
aliceManager->delete_user(*aliceDeviceId, callback);
......
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