lime
Lime is a C++ library implementing Open Whisper System Signal protocol
Loading...
Searching...
No Matches
lime_double_ratchet.hpp
Go to the documentation of this file.
1/*
2 lime_double_ratchet.hpp
3 @author Johan Pascal
4 @copyright Copyright (C) 2017 Belledonne Communications SARL
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19#ifndef lime_double_ratchet_hpp
20#define lime_double_ratchet_hpp
21
22#include <array>
23#include <string>
24#include <unordered_map>
25#include <vector>
26#include <memory>
27
28#include "lime_settings.hpp"
29#include "lime_defines.hpp"
31
32namespace lime {
33
34 class Db; // forward declaration of class Db used by DR<Curve>, declared in lime_localStorage.hpp
35
41 enum class DRSessionDbStatus : uint8_t {
42 clean,
46 dirty
47 };
48
51
54
56 using SharedADBuffer = std::array<uint8_t, lime::settings::DRSessionSharedADSize>;
57
62 template <typename Curve>
72
81 template <typename Curve>
82 class DR {
83 private:
84 /* State variables for Double Ratchet, see Double Ratchet spec section 3.2 for details */
85 X<Curve, lime::Xtype::publicKey> m_DHr; // Remote public key
86 bool m_DHr_valid; // do we have a valid remote public key, flag used to spot the first message arriving at session creation in receiver mode
87 Xpair<Curve> m_DHs; // self Key pair
88 DRChainKey m_RK; // 32 bytes root key
89 DRChainKey m_CKs; // 32 bytes key chain for sending
90 DRChainKey m_CKr; // 32 bytes key chain for receiving
91 uint16_t m_Ns,m_Nr; // Message index in sending and receiving chain
92 uint16_t m_PN; // Number of messages in previous sending chain
93 SharedADBuffer m_sharedAD; // Associated Data derived from self and peer device Identity key, set once at session creation, given by X3DH
94 std::vector<lime::ReceiverKeyChain<Curve>> m_mkskipped; // list of skipped message indexed by DH receiver public key and Nr, store MK generated during on-going decrypt, lookup is done directly in DB.
95
96 /* helpers variables */
97 std::shared_ptr<RNG> m_RNG; // Random Number Generator context
98 long int m_dbSessionId; // used to store row id from Database Storage
99 uint16_t m_usedNr; // store the index of message key used for decryption if it came from mkskipped db
100 long m_usedDHid; // store the index of DHr message key used for decryption if it came from mkskipped db(not zero only if used)
101 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.
102 std::shared_ptr<lime::Db> m_localStorage; // enable access to the database holding sessions and skipped message keys
103 DRSessionDbStatus m_dirty; // status of the object regarding its instance in local storage, could be: clean, dirty_encrypt, dirty_decrypt or dirty
104 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
105 std::string m_peerDeviceId; // used during session creation only, if the deviceId is not yet in local storage, to hold the peer device Id so we can insert it in DB when session is saved for the first time
106 DSA<Curve, lime::DSAtype::publicKey> m_peerIk; // used during session creation only, if the deviceId is not yet in local storage, to hold the peer device Ik so we can insert it in DB when session is saved for the first time
107 long int m_db_Uid; // used to link session to a local device Id
108 bool m_active_status; // current status of this session, true if it is the active one, false if it is stale
109 std::vector<uint8_t> m_X3DH_initMessage; // store the X3DH init message to be able to prepend it to any message until we got a first response from peer so we're sure he was able to init the session on his side
110
111 /*helpers functions */
112 void skipMessageKeys(const uint16_t until, const int limit); /* check if we skipped some messages in current receiving chain, generate and store in session intermediate message keys */
113 void DHRatchet(const X<Curve, lime::Xtype::publicKey> &headerDH); /* perform a Diffie-Hellman ratchet using the given peer public key */
114 /* local storage related implemented in lime_localStorage.cpp */
115 bool session_save(bool commit=true); /* save/update session in database : updated component depends m_dirty value, when commit is true, commit transaction in DB */
116 bool session_load(); /* load session in database */
117 bool trySkippedMessageKeys(const uint16_t Nr, const X<Curve, lime::Xtype::publicKey> &DHr, DRMKey &MK); /* check in DB if we have a message key matching public DH and Ns */
118
119 public:
120 DR() = delete; // make sure the Double Ratchet is not initialised without parameters
121 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
122 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
123 DR(std::shared_ptr<lime::Db> localStorage, long sessionId, std::shared_ptr<RNG> RNG_context); // load session from DB
124 DR(DR<Curve> &a) = delete; // can't copy a session, force usage of shared pointers
125 DR<Curve> &operator=(DR<Curve> &a) = delete; // can't copy a session
126 ~DR();
127
128 template<typename inputContainer>
129 void ratchetEncrypt(const inputContainer &plaintext, std::vector<uint8_t> &&AD, std::vector<uint8_t> &ciphertext, const bool payloadDirectEncryption);
130 template<typename outputContainer>
131 bool ratchetDecrypt(const std::vector<uint8_t> &cipherText, const std::vector<uint8_t> &AD, outputContainer &plaintext, const bool payloadDirectEncryption);
133 long int dbSessionId(void) const {return m_dbSessionId;};
135 bool isActive(void) const {return m_active_status;}
136 };
137
138
142 template <typename Curve>
144 std::shared_ptr<DR<Curve>> DRSession;
153 RecipientInfos(const std::string &deviceId, std::shared_ptr<DR<Curve>> session) : RecipientData(deviceId), DRSession{session} {};
159 RecipientInfos(const std::string &deviceId) : RecipientData(deviceId), DRSession{nullptr} {};
160 };
161
162 // helpers function wich are the one to be used to encrypt/decrypt messages
163 template <typename Curve>
164 void encryptMessage(std::vector<RecipientInfos<Curve>>& recipients, const std::vector<uint8_t>& plaintext, const std::vector<uint8_t>& recipientUserId, const std::string& sourceDeviceId, std::vector<uint8_t>& cipherMessage, const lime::EncryptionPolicy encryptionPolicy, std::shared_ptr<lime::Db> localStorage);
165
166 template <typename Curve>
167 std::shared_ptr<DR<Curve>> decryptMessage(const std::string& sourceDeviceId, const std::string& recipientDeviceId, const std::vector<uint8_t>& recipientUserId, std::vector<std::shared_ptr<DR<Curve>>>& DRSessions, const std::vector<uint8_t>& DRmessage, const std::vector<uint8_t>& cipherMessage, std::vector<uint8_t>& plaintext);
168
169 /* this templates are instanciated once in the lime_double_ratchet.cpp file, explicitly tell anyone including this header that there is no need to re-instanciate them */
170#ifdef EC25519_ENABLED
171 extern template class DR<C255>;
172 extern template void encryptMessage<C255>(std::vector<RecipientInfos<C255>>& recipients, const std::vector<uint8_t>& plaintext, const std::vector<uint8_t>& recipientUserId, const std::string& sourceDeviceId, std::vector<uint8_t>& cipherMessage, const lime::EncryptionPolicy encryptionPolicy, std::shared_ptr<lime::Db> localStorage);
173 extern template std::shared_ptr<DR<C255>> decryptMessage<C255>(const std::string& sourceDeviceId, const std::string& recipientDeviceId, const std::vector<uint8_t>& recipientUserId, std::vector<std::shared_ptr<DR<C255>>>& DRSessions, const std::vector<uint8_t>& DRmessage, const std::vector<uint8_t>& cipherMessage, std::vector<uint8_t>& plaintext);
174#endif
175#ifdef EC448_ENABLED
176 extern template class DR<C448>;
177 extern template void encryptMessage<C448>(std::vector<RecipientInfos<C448>>& recipients, const std::vector<uint8_t>& plaintext, const std::vector<uint8_t>& recipientUserId, const std::string& sourceDeviceId, std::vector<uint8_t>& cipherMessage, const lime::EncryptionPolicy encryptionPolicy, std::shared_ptr<lime::Db> localStorage);
178 extern template std::shared_ptr<DR<C448>> decryptMessage<C448>(const std::string& sourceDeviceId, const std::string& recipientDeviceId, const std::vector<uint8_t>& recipientUserId, std::vector<std::shared_ptr<DR<C448>>>& DRSessions, const std::vector<uint8_t>& DRmessage, const std::vector<uint8_t>& cipherMessage, std::vector<uint8_t>& plaintext);
179#endif
180
181}
182
183#endif /* lime_double_ratchet_hpp */
store a Double Rachet session.
Definition lime_double_ratchet.hpp:82
DR< Curve > & operator=(DR< Curve > &a)=delete
bool ratchetDecrypt(const std::vector< uint8_t > &cipherText, const std::vector< uint8_t > &AD, outputContainer &plaintext, const bool payloadDirectEncryption)
Decrypt Double Ratchet message.
Definition lime_double_ratchet.cpp:371
void ratchetEncrypt(const inputContainer &plaintext, std::vector< uint8_t > &&AD, std::vector< uint8_t > &ciphertext, const bool payloadDirectEncryption)
Encrypt using the double-ratchet algorithm.
Definition lime_double_ratchet.cpp:317
DR()=delete
long int dbSessionId(void) const
return the session's local storage id
Definition lime_double_ratchet.hpp:133
~DR()
Definition lime_double_ratchet.cpp:225
bool isActive(void) const
return the current status of session
Definition lime_double_ratchet.hpp:135
DR(DR< Curve > &a)=delete
Base buffer definition for DSA data structure.
Definition lime_crypto_primitives.hpp:97
Base buffer definition for Key Exchange data structure.
Definition lime_crypto_primitives.hpp:56
Key pair structure for key exchange algorithm.
Definition lime_crypto_primitives.hpp:71
Definition lime.cpp:30
std::shared_ptr< DR< Curve > > decryptMessage(const std::string &sourceDeviceId, const std::string &recipientDeviceId, const std::vector< uint8_t > &recipientUserId, std::vector< std::shared_ptr< DR< Curve > > > &DRSessions, const std::vector< uint8_t > &DRmessage, const std::vector< uint8_t > &cipherMessage, std::vector< uint8_t > &plaintext)
Decrypt a message.
Definition lime_double_ratchet.cpp:606
DRSessionDbStatus
the possible status of session regarding the Local Storage
Definition lime_double_ratchet.hpp:41
std::array< uint8_t, lime::settings::DRSessionSharedADSize > SharedADBuffer
Definition lime_double_ratchet.hpp:56
void encryptMessage(std::vector< RecipientInfos< Curve > > &recipients, const std::vector< uint8_t > &plaintext, const std::vector< uint8_t > &recipientUserId, const std::string &sourceDeviceId, std::vector< uint8_t > &cipherMessage, const lime::EncryptionPolicy encryptionPolicy, std::shared_ptr< lime::Db > localStorage)
Encrypt a message to all recipients, identified by their device id.
Definition lime_double_ratchet.cpp:470
EncryptionPolicy
Definition lime.hpp:42
Definition errors.hpp:10
Chain storing the DH and MKs associated with Nr(uint16_t map index)
Definition lime_double_ratchet.hpp:63
ReceiverKeyChain(X< Curve, lime::Xtype::publicKey > key)
Definition lime_double_ratchet.hpp:70
X< Curve, lime::Xtype::publicKey > DHr
Definition lime_double_ratchet.hpp:64
std::unordered_map< uint16_t, DRMKey > messageKeys
Definition lime_double_ratchet.hpp:65
The encrypt function input/output data structure.
Definition lime.hpp:68
const std::string deviceId
Definition lime.hpp:69
extend the RecipientData to add a Double Ratchet session shared with the recipient
Definition lime_double_ratchet.hpp:143
RecipientInfos(const std::string &deviceId, std::shared_ptr< DR< Curve > > session)
Definition lime_double_ratchet.hpp:153
RecipientInfos(const std::string &deviceId)
Definition lime_double_ratchet.hpp:159
std::shared_ptr< DR< Curve > > DRSession
Definition lime_double_ratchet.hpp:144