Commit 046fd0db authored by johan's avatar johan
Browse files

Delay OPk delete until DR session is actually saved in local storage

parent 7b43ba8f
...@@ -148,8 +148,8 @@ namespace lime { ...@@ -148,8 +148,8 @@ namespace lime {
template <typename Curve> template <typename Curve>
DR<Curve>::DR(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const X<Curve, lime::Xtype::publicKey> &peerPublicKey, long int peerDid, const std::string &peerDeviceId, const DSA<Curve, lime::DSAtype::publicKey> &peerIk, long int selfDid, const std::vector<uint8_t> &X3DH_initMessage, std::shared_ptr<RNG> RNG_context) DR<Curve>::DR(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const X<Curve, lime::Xtype::publicKey> &peerPublicKey, long int peerDid, const std::string &peerDeviceId, const DSA<Curve, lime::DSAtype::publicKey> &peerIk, long int selfDid, const std::vector<uint8_t> &X3DH_initMessage, std::shared_ptr<RNG> RNG_context)
:m_DHr{peerPublicKey},m_DHr_valid{true}, m_DHs{},m_RK(SK),m_CKs{},m_CKr{},m_Ns(0),m_Nr(0),m_PN(0),m_sharedAD(AD),m_mkskipped{}, :m_DHr{peerPublicKey},m_DHr_valid{true}, m_DHs{},m_RK(SK),m_CKs{},m_CKr{},m_Ns(0),m_Nr(0),m_PN(0),m_sharedAD(AD),m_mkskipped{},
m_RNG{RNG_context},m_dbSessionId{0},m_usedNr{0},m_usedDHid{0},m_localStorage{localStorage},m_dirty{DRSessionDbStatus::dirty},m_peerDid{peerDid},m_peerDeviceId{},m_peerIk{},m_db_Uid{selfDid}, m_RNG{RNG_context},m_dbSessionId{0},m_usedNr{0},m_usedDHid{0}, m_usedOPkId{0}, m_localStorage{localStorage},m_dirty{DRSessionDbStatus::dirty},m_peerDid{peerDid},m_peerDeviceId{},
m_active_status{true}, m_X3DH_initMessage{X3DH_initMessage} m_peerIk{},m_db_Uid{selfDid}, m_active_status{true}, m_X3DH_initMessage{X3DH_initMessage}
{ {
// generate a new self key pair // generate a new self key pair
auto DH = make_keyExchange<Curve>(); auto DH = make_keyExchange<Curve>();
...@@ -181,18 +181,19 @@ namespace lime { ...@@ -181,18 +181,19 @@ namespace lime {
* @param[in] localStorage Local storage accessor to save DR session and perform mkskipped lookup * @param[in] localStorage Local storage accessor to save DR session and perform mkskipped lookup
* @param[in] SK a 32 bytes shared secret established prior the session init (likely done using X3DH) * @param[in] SK a 32 bytes shared secret established prior the session init (likely done using X3DH)
* @param[in] AD The associated data generated by X3DH protocol and permanently part of the DR session(see X3DH spec section 3.3 and lime doc section 5.4.3) * @param[in] AD The associated data generated by X3DH protocol and permanently part of the DR session(see X3DH spec section 3.3 and lime doc section 5.4.3)
* @param[in] selfKeyPair the key pair used by sender to establish this DR session * @param[in] selfKeyPair the key pair used by sender to establish this DR session (DR spec section 5.1: it shall be our SPk)
* @param[in] peerDid Id used in local storage for this peer Device this session shall be attached to * @param[in] peerDid Id used in local storage for this peer Device this session shall be attached to
* @param[in] peerDeviceId The peer Device Id this session is connected to. Ignored if peerDid is not 0 * @param[in] peerDeviceId The peer Device Id this session is connected to. Ignored if peerDid is not 0
* @param[in] OPk_id Id of the self OPk used to create this session: we must remove it from local storage when saving the session in it. (ignored if 0)
* @param[in] peerIk The Identity Key of the peer device this session is connected to. Ignored if peerDid is not 0 * @param[in] peerIk The Identity Key of the peer device this session is connected to. Ignored if peerDid is not 0
* @param[in] selfDid Id used in local storage for local user this session shall be attached to * @param[in] selfDid Id used in local storage for local user this session shall be attached to
* @param[in] RNG_context A Random Number Generator context used for any rndom generation needed by this session * @param[in] RNG_context A Random Number Generator context used for any rndom generation needed by this session
*/ */
template <typename Curve> template <typename Curve>
DR<Curve>::DR(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const Xpair<Curve> &selfKeyPair, long int peerDid, const std::string &peerDeviceId, const DSA<Curve, lime::DSAtype::publicKey> &peerIk, long int selfDid, std::shared_ptr<RNG> RNG_context) DR<Curve>::DR(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const Xpair<Curve> &selfKeyPair, long int peerDid, const std::string &peerDeviceId, const uint32_t OPk_id, const DSA<Curve, lime::DSAtype::publicKey> &peerIk, long int selfDid, std::shared_ptr<RNG> RNG_context)
:m_DHr{},m_DHr_valid{false},m_DHs{selfKeyPair},m_RK(SK),m_CKs{},m_CKr{},m_Ns(0),m_Nr(0),m_PN(0),m_sharedAD(AD),m_mkskipped{}, :m_DHr{},m_DHr_valid{false},m_DHs{selfKeyPair},m_RK(SK),m_CKs{},m_CKr{},m_Ns(0),m_Nr(0),m_PN(0),m_sharedAD(AD),m_mkskipped{},
m_RNG{RNG_context},m_dbSessionId{0},m_usedNr{0},m_usedDHid{0},m_localStorage{localStorage},m_dirty{DRSessionDbStatus::dirty},m_peerDid{peerDid},m_peerDeviceId{},m_peerIk{},m_db_Uid{selfDid}, m_RNG{RNG_context},m_dbSessionId{0},m_usedNr{0},m_usedDHid{0}, m_usedOPkId{OPk_id}, m_localStorage{localStorage},m_dirty{DRSessionDbStatus::dirty},m_peerDid{peerDid},m_peerDeviceId{},
m_active_status{true}, m_X3DH_initMessage{} m_peerIk{},m_db_Uid{selfDid}, m_active_status{true}, m_X3DH_initMessage{}
{ {
// If we have no peerDid, copy peer DeviceId and Ik in the session so we can use them to create the peer device in local storage when first saving the session // If we have no peerDid, copy peer DeviceId and Ik in the session so we can use them to create the peer device in local storage when first saving the session
if (peerDid == 0) { if (peerDid == 0) {
...@@ -214,8 +215,8 @@ namespace lime { ...@@ -214,8 +215,8 @@ namespace lime {
template <typename Curve> template <typename Curve>
DR<Curve>::DR(std::shared_ptr<lime::Db> localStorage, long sessionId, std::shared_ptr<RNG> RNG_context) DR<Curve>::DR(std::shared_ptr<lime::Db> localStorage, long sessionId, std::shared_ptr<RNG> RNG_context)
:m_DHr{},m_DHr_valid{true},m_DHs{},m_RK{},m_CKs{},m_CKr{},m_Ns(0),m_Nr(0),m_PN(0),m_sharedAD{},m_mkskipped{}, :m_DHr{},m_DHr_valid{true},m_DHs{},m_RK{},m_CKs{},m_CKr{},m_Ns(0),m_Nr(0),m_PN(0),m_sharedAD{},m_mkskipped{},
m_RNG{RNG_context},m_dbSessionId{sessionId},m_usedNr{0},m_usedDHid{0},m_localStorage{localStorage},m_dirty{DRSessionDbStatus::clean},m_peerDid{0},m_peerDeviceId{},m_peerIk{},m_db_Uid{0}, m_RNG{RNG_context},m_dbSessionId{sessionId},m_usedNr{0},m_usedDHid{0}, m_usedOPkId{0}, m_localStorage{localStorage},m_dirty{DRSessionDbStatus::clean},m_peerDid{0},m_peerDeviceId{},
m_active_status{false}, m_X3DH_initMessage{} m_peerIk{},m_db_Uid{0}, m_active_status{false}, m_X3DH_initMessage{}
{ {
session_load(); session_load();
} }
......
...@@ -98,6 +98,7 @@ namespace lime { ...@@ -98,6 +98,7 @@ namespace lime {
long int m_dbSessionId; // used to store row id from Database Storage long int m_dbSessionId; // used to store row id from Database Storage
uint16_t m_usedNr; // store the index of message key used for decryption if it came from mkskipped db uint16_t m_usedNr; // store the index of message key used for decryption if it came from mkskipped db
long m_usedDHid; // store the index of DHr message key used for decryption if it came from mkskipped db(not zero only if used) long m_usedDHid; // store the index of DHr message key used for decryption if it came from mkskipped db(not zero only if used)
uint32_t m_usedOPkId; // when the session is created on receiver side, store the OPk id used so we can remove it from local storage when saving session for the first time.
std::shared_ptr<lime::Db> m_localStorage; // enable access to the database holding sessions and skipped message keys std::shared_ptr<lime::Db> m_localStorage; // enable access to the database holding sessions and skipped message keys
DRSessionDbStatus m_dirty; // status of the object regarding its instance in local storage, could be: clean, dirty_encrypt, dirty_decrypt or dirty DRSessionDbStatus m_dirty; // status of the object regarding its instance in local storage, could be: clean, dirty_encrypt, dirty_decrypt or dirty
long int m_peerDid; // used during session creation only to hold the peer device id in DB as we need it to insert the session in local Storage long int m_peerDid; // used during session creation only to hold the peer device id in DB as we need it to insert the session in local Storage
...@@ -118,7 +119,7 @@ namespace lime { ...@@ -118,7 +119,7 @@ namespace lime {
public: public:
DR() = delete; // make sure the Double Ratchet is not initialised without parameters DR() = delete; // make sure the Double Ratchet is not initialised without parameters
DR(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const X<Curve, lime::Xtype::publicKey> &peerPublicKey, const long int peerDid, const std::string &peerDeviceId, const DSA<Curve, lime::DSAtype::publicKey> &peerIk, long int selfDeviceId, const std::vector<uint8_t> &X3DH_initMessage, std::shared_ptr<RNG> RNG_context); // call to initialise a session for sender: we have Shared Key and peer Public key DR(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const X<Curve, lime::Xtype::publicKey> &peerPublicKey, const long int peerDid, const std::string &peerDeviceId, const DSA<Curve, lime::DSAtype::publicKey> &peerIk, long int selfDeviceId, const std::vector<uint8_t> &X3DH_initMessage, std::shared_ptr<RNG> RNG_context); // call to initialise a session for sender: we have Shared Key and peer Public key
DR(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const Xpair<Curve> &selfKeyPair, long int peerDid, const std::string &peerDeviceId, const DSA<Curve, lime::DSAtype::publicKey> &peerIk, long int selfDeviceId, std::shared_ptr<RNG> RNG_context); // call at initialisation of a session for receiver: we have Share Key and self key pair DR(std::shared_ptr<lime::Db> localStorage, const DRChainKey &SK, const SharedADBuffer &AD, const Xpair<Curve> &selfKeyPair, long int peerDid, const std::string &peerDeviceId, const uint32_t OPk_id, const DSA<Curve, lime::DSAtype::publicKey> &peerIk, long int selfDeviceId, std::shared_ptr<RNG> RNG_context); // call at initialisation of a session for receiver: we have Share Key and self key pair
DR(std::shared_ptr<lime::Db> localStorage, long sessionId, std::shared_ptr<RNG> RNG_context); // load session from DB DR(std::shared_ptr<lime::Db> localStorage, long sessionId, std::shared_ptr<RNG> RNG_context); // load session from DB
DR(DR<Curve> &a) = delete; // can't copy a session, force usage of shared pointers DR(DR<Curve> &a) = delete; // can't copy a session, force usage of shared pointers
DR<Curve> &operator=(DR<Curve> &a) = delete; // can't copy a session DR<Curve> &operator=(DR<Curve> &a) = delete; // can't copy a session
......
...@@ -616,6 +616,12 @@ bool DR<Curve>::session_save() { ...@@ -616,6 +616,12 @@ bool DR<Curve>::session_save() {
/*if (!(sql.get_last_insert_id("DR_sessions", m_dbSessionId))) { /*if (!(sql.get_last_insert_id("DR_sessions", m_dbSessionId))) {
throw; throw;
} */ } */
// At session creation, we may have to delete an OPk from storage
if (m_usedOPkId != 0) {
m_localStorage->sql<<"DELETE FROM X3DH_OPK WHERE Uid = :Uid AND OPKid = :OPk_id;", use(m_db_Uid), use(m_usedOPkId);
m_usedOPkId = 0;
}
} else { // we have an id, it shall already be in the db } else { // we have an id, it shall already be in the db
// Try to update an existing row // Try to update an existing row
try{ //TODO: make sure the update was a success, or we shall signal it try{ //TODO: make sure the update was a success, or we shall signal it
...@@ -1250,7 +1256,6 @@ void Lime<Curve>::X3DH_get_OPk(uint32_t OPk_id, Xpair<Curve> &OPk) { ...@@ -1250,7 +1256,6 @@ void Lime<Curve>::X3DH_get_OPk(uint32_t OPk_id, Xpair<Curve> &OPk) {
if (m_localStorage->sql.got_data()) { // Found it, it is stored in one buffer Public || Private if (m_localStorage->sql.got_data()) { // Found it, it is stored in one buffer Public || Private
OPk_blob.read(0, (char *)(OPk.publicKey().data()), OPk.publicKey().size()); // Read the public key OPk_blob.read(0, (char *)(OPk.publicKey().data()), OPk.publicKey().size()); // Read the public key
OPk_blob.read(OPk.publicKey().size(), (char *)(OPk.privateKey().data()), OPk.privateKey().size()); // Read the private key OPk_blob.read(OPk.publicKey().size(), (char *)(OPk.privateKey().data()), OPk.privateKey().size()); // Read the private key
m_localStorage->sql<<"DELETE FROM X3DH_OPK WHERE Uid = :Uid AND OPKid = :OPk_id;", use(m_db_Uid), use(OPk_id); // And remove it from local Storage
} else { } else {
throw BCTBX_EXCEPTION << "X3DH "<<m_selfDeviceId<<"look up for OPk id "<<OPk_id<<" failed"; throw BCTBX_EXCEPTION << "X3DH "<<m_selfDeviceId<<"look up for OPk id "<<OPk_id<<" failed";
} }
......
...@@ -211,7 +211,7 @@ namespace lime { ...@@ -211,7 +211,7 @@ namespace lime {
// check the new peer device Id in Storage, if it is not found, the DR session will add it when it saves itself after successful decryption // check the new peer device Id in Storage, if it is not found, the DR session will add it when it saves itself after successful decryption
auto peerDid = m_localStorage->check_peerDevice(senderDeviceId, peerIk); auto peerDid = m_localStorage->check_peerDevice(senderDeviceId, peerIk);
auto DRSession = make_shared<DR<Curve>>(m_localStorage, SK, AD, SPk, peerDid, senderDeviceId, peerIk, m_db_Uid, m_RNG); auto DRSession = make_shared<DR<Curve>>(m_localStorage, SK, AD, SPk, peerDid, senderDeviceId, OPk_flag?OPk_id:0, peerIk, m_db_Uid, m_RNG);
return DRSession; return DRSession;
} }
......
...@@ -215,7 +215,7 @@ void dr_sessionsInit(std::shared_ptr<DR<Curve>> &alice, std::shared_ptr<DR<Curve ...@@ -215,7 +215,7 @@ void dr_sessionsInit(std::shared_ptr<DR<Curve>> &alice, std::shared_ptr<DR<Curve
std::vector<uint8_t> X3DH_initMessage{}; std::vector<uint8_t> X3DH_initMessage{};
DSA<Curve, lime::DSAtype::publicKey> dummyPeerIk{}; // DR session creation gets the peerDeviceId and peerIk but uses it only if peerDid is 0, give dummy, we're focusing on DR here DSA<Curve, lime::DSAtype::publicKey> dummyPeerIk{}; // DR session creation gets the peerDeviceId and peerIk but uses it only if peerDid is 0, give dummy, we're focusing on DR here
alice = std::make_shared<DR<Curve>>(localStorageAlice, SK, AD, bobKeyPair.publicKey(), aliceDid, "dummyPeerDevice", dummyPeerIk, aliceUid, X3DH_initMessage, RNG_context); alice = std::make_shared<DR<Curve>>(localStorageAlice, SK, AD, bobKeyPair.publicKey(), aliceDid, "dummyPeerDevice", dummyPeerIk, aliceUid, X3DH_initMessage, RNG_context);
bob = std::make_shared<DR<Curve>>(localStorageBob, SK, AD, bobKeyPair, bobDid, "dummyPeerDevice", dummyPeerIk, bobUid, RNG_context); bob = std::make_shared<DR<Curve>>(localStorageBob, SK, AD, bobKeyPair, bobDid, "dummyPeerDevice", 0, dummyPeerIk, bobUid, RNG_context);
} }
......
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