lime
Lime is a C++ library implementing Open Whisper System Signal protocol
Loading...
Searching...
No Matches
lime_impl.hpp
Go to the documentation of this file.
1/*
2 lime_impl.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_impl_hpp
20#define lime_impl_hpp
21
22#include <memory>
23#include <vector>
24#include <unordered_map>
25#include <queue>
26#include <mutex>
27
28#include "lime/lime.hpp"
29#include "lime_lime.hpp"
31#include "lime_localStorage.hpp"
34
35namespace lime {
36 // an enum used by network state engine to manage sequence packet sending(at user creation)
37 enum class network_state : uint8_t {done=0x00, sendSPk=0x01, sendOPk=0x02};
38
39 template <typename Curve>
40 struct callbackUserData;
41
45 template <typename Curve>
46 class Lime : public LimeGeneric, public std::enable_shared_from_this<Lime<Curve>> {
47 private:
48 /*** data members ***/
49 /* general purpose */
50 std::shared_ptr<RNG> m_RNG; // Random Number Generator context
51 std::string m_selfDeviceId; // self device Id, shall be the GRUU
52 std::mutex m_mutex; // a mutex to lock own thread sensitive ressources (m_DR_sessions_cache, encryption_queue)
53
54 /* X3DH keys */
55 DSApair<Curve> m_Ik; // our identity key pair, is loaded from DB only if requested(to sign a SPK or to perform X3DH init)
56 bool m_Ik_loaded; // did we load the Ik yet?
57
58 /* local storage related */
59 std::shared_ptr<lime::Db> m_localStorage; // shared pointer would be used/stored in Double Ratchet Sessions
60 long int m_db_Uid; // the Uid in database, retrieved at creation/load, used for faster access
61
62 /* network related */
63 limeX3DHServerPostData m_X3DH_post_data; // externally provided function to communicate with x3dh server
64 std::string m_X3DH_Server_URL; // url of x3dh key server
65
66 /* Double ratchet related */
67 std::unordered_map<std::string, std::shared_ptr<DR<Curve>>> m_DR_sessions_cache; // store already loaded DR session
68
69 /* encryption queue: encryption requesting asynchronous operation(connection to X3DH server) are queued to avoid repeating a request to server */
70 std::shared_ptr<callbackUserData<Curve>> m_ongoing_encryption;
71 std::queue<std::shared_ptr<callbackUserData<Curve>>> m_encryption_queue;
72
73 /*** Private functions ***/
74 /* database related functions, implementation is in lime_localStorage.cpp */
75 // create user in DB, throw an exception if already there or something went wrong
76 bool create_user();
77 // Once X3DH server confirms user registration, active it locally
78 bool activate_user();
79 // user load from DB is implemented directly as a Db member function, output of it is passed to Lime<> ctor
80 void get_SelfIdentityKey(); // check our Identity key pair is loaded in Lime object, retrieve it from DB if it isn't
81 void cache_DR_sessions(std::vector<RecipientInfos<Curve>> &internal_recipients, std::vector<std::string> &missing_devices); // loop on internal recipient an try to load in DR session cache the one which have no session attached
82 void get_DRSessions(const std::string &senderDeviceId, const long int ignoreThisDRSessionId, std::vector<std::shared_ptr<DR<Curve>>> &DRSessions); // load from local storage in DRSessions all DR session matching the peerDeviceId, ignore the one picked by id in 2nd arg
83
84 /* X3DH related - part related to exchange with server or localStorage - implemented in lime_x3dh_protocol.cpp or lime_localStorage.cpp */
85 void X3DH_generate_SPk(X<Curve, lime::Xtype::publicKey> &publicSPk, DSA<Curve, lime::DSAtype::signature> &SPk_sig, uint32_t &SPk_id, const bool load=false); // generate a new Signed Pre-Key key pair, store it in DB and set its public key, signature and Id in given params
86 void X3DH_generate_OPks(std::vector<X<Curve, lime::Xtype::publicKey>> &publicOPks, std::vector<uint32_t> &OPk_ids, const uint16_t OPk_number, const bool load=false); // generate a new batch of OPks, store them in base and fill the vector with information to be sent to X3DH server
87 void X3DH_get_SPk(uint32_t SPk_id, Xpair<Curve> &SPk); // retrieve matching SPk from localStorage, throw an exception if not found
88 bool is_currentSPk_valid(void); // check validity of current SPk
89 void X3DH_get_OPk(uint32_t OPk_id, Xpair<Curve> &OPk); // retrieve matching OPk from localStorage, throw an exception if not found
90 void X3DH_updateOPkStatus(const std::vector<uint32_t> &OPkIds); // update OPks to tag those not anymore on X3DH server but not used and destroyed yet
91 /* X3DH related - part related to X3DH DR session initiation, implemented in lime_x3dh.cpp */
92 void X3DH_init_sender_session(const std::vector<X3DH_peerBundle<Curve>> &peersBundle); // compute a sender X3DH using the data from peer bundle, then create and load the DR_Session
93 std::shared_ptr<DR<Curve>> X3DH_init_receiver_session(const std::vector<uint8_t> X3DH_initMessage, const std::string &senderDeviceId); // from received X3DH init packet, try to compute the shared secrets, then create the DR_Session
94
95 /* network related, implemented in lime_x3dh_protocol.cpp */
96 void postToX3DHServer(std::shared_ptr<callbackUserData<Curve>> userData, const std::vector<uint8_t> &message); // send a request to X3DH server
97 void process_response(std::shared_ptr<callbackUserData<Curve>> userData, int responseCode, const std::vector<uint8_t> &responseBody) noexcept; // callback on server response
98 void cleanUserData(std::shared_ptr<callbackUserData<Curve>> userData); // clean user data
99
100 public: /* Implement API defined in lime_lime.hpp in LimeGeneric abstract class */
101 Lime(std::unique_ptr<lime::Db> &&localStorage, const std::string &deviceId, const std::string &url, const limeX3DHServerPostData &X3DH_post_data);
102 Lime(std::unique_ptr<lime::Db> &&localStorage, const std::string &deviceId, const std::string &url, const limeX3DHServerPostData &X3DH_post_data, const long int Uid);
103 ~Lime();
104 Lime(Lime<Curve> &a) = delete; // can't copy a session, force usage of shared pointers
105 Lime<Curve> &operator=(Lime<Curve> &a) = delete; // can't copy a session
106 void publish_user(const limeCallback &callback, const uint16_t OPkInitialBatchSize) override;
107 void delete_user(const limeCallback &callback) override;
108 void delete_peerDevice(const std::string &peerDeviceId) override;
109 void update_SPk(const limeCallback &callback) override;
110 void update_OPk(const limeCallback &callback, uint16_t OPkServerLowLimit, uint16_t OPkBatchSize) override;
111 void get_Ik(std::vector<uint8_t> &Ik) override;
112 void encrypt(std::shared_ptr<const std::string> recipientUserId, std::shared_ptr<std::vector<RecipientData>> recipients, std::shared_ptr<const std::vector<uint8_t>> plainMessage, const lime::EncryptionPolicy encryptionPolicy, std::shared_ptr<std::vector<uint8_t>> cipherMessage, const limeCallback &callback) override;
113 lime::PeerDeviceStatus decrypt(const std::string &recipientUserId, const std::string &senderDeviceId, const std::vector<uint8_t> &DRmessage, const std::vector<uint8_t> &cipherMessage, std::vector<uint8_t> &plainMessage) override;
114 void set_x3dhServerUrl(const std::string &x3dhServerUrl) override;
115 std::string get_x3dhServerUrl() override;
116 void stale_sessions(const std::string &peerDeviceId) override;
117 };
118
122 template <typename Curve>
125 std::weak_ptr<Lime<Curve>> limeObj;
129 std::shared_ptr<const std::string> recipientUserId;
131 std::shared_ptr<std::vector<RecipientData>> recipients;
133 std::shared_ptr<const std::vector<uint8_t>> plainMessage;
135 std::shared_ptr<std::vector<uint8_t>> cipherMessage;
141 uint16_t OPkBatchSize;
142
144 callbackUserData(std::weak_ptr<Lime<Curve>> thiz, const limeCallback &callbackRef, uint16_t OPkInitialBatchSize=lime::settings::OPk_initialBatchSize)
145 : limeObj{thiz}, callback{callbackRef},
146 recipientUserId{nullptr}, recipients{nullptr}, plainMessage{nullptr}, cipherMessage{nullptr},
148
150 callbackUserData(std::weak_ptr<Lime<Curve>> thiz, const limeCallback &callbackRef, uint16_t OPkServerLowLimit, uint16_t OPkBatchSize)
151 : limeObj{thiz}, callback{callbackRef},
152 recipientUserId{nullptr}, recipients{nullptr}, plainMessage{nullptr}, cipherMessage{nullptr},
154
156 callbackUserData(std::weak_ptr<Lime<Curve>> thiz, const limeCallback &callbackRef,
157 std::shared_ptr<const std::string> recipientUserId, std::shared_ptr<std::vector<RecipientData>> recipients,
158 std::shared_ptr<const std::vector<uint8_t>> plainMessage, std::shared_ptr<std::vector<uint8_t>> cipherMessage,
160 : limeObj{thiz}, callback{callbackRef},
163
168 };
169
170
171/* this template is intanciated in lime.cpp, do not re-instanciate it anywhere else */
172#ifdef EC25519_ENABLED
173 extern template class Lime<C255>;
174#endif
175
176#ifdef EC448_ENABLED
177 extern template class Lime<C448>;
178#endif
179
180}
181#endif /* lime_impl_hpp */
store a Double Rachet session.
Definition lime_double_ratchet.hpp:82
Base buffer definition for DSA data structure.
Definition lime_crypto_primitives.hpp:97
Key pair structure for DSA algorithm.
Definition lime_crypto_primitives.hpp:112
A pure abstract class defining the API to encrypt/decrypt/manage user and its keys.
Definition lime_lime.hpp:35
Implement the abstract class LimeGeneric.
Definition lime_impl.hpp:46
std::string get_x3dhServerUrl() override
Get the X3DH key server URL for this identified user.
Definition lime.cpp:314
void stale_sessions(const std::string &peerDeviceId) override
Stale all sessions between localDeviceId and peerDevice. If peerDevice keep using this session to enc...
Definition lime_localStorage.cpp:1467
void get_Ik(std::vector< uint8_t > &Ik) override
Retrieve self public Identity key.
Definition lime.cpp:162
Lime< Curve > & operator=(Lime< Curve > &a)=delete
void delete_user(const limeCallback &callback) override
Delete user from local Storage and from X3DH server.
Definition lime.cpp:115
~Lime()
Definition lime.cpp:85
void update_SPk(const limeCallback &callback) override
Check if the current SPk needs to be updated, if yes, generate a new one and publish it on server.
Definition lime.cpp:132
void update_OPk(const limeCallback &callback, uint16_t OPkServerLowLimit, uint16_t OPkBatchSize) override
check if we shall upload more OPks on X3DH server
Definition lime.cpp:151
void publish_user(const limeCallback &callback, const uint16_t OPkInitialBatchSize) override
Publish on X3DH server the user, it is performed just after creation in local storage this will,...
Definition lime.cpp:94
lime::PeerDeviceStatus decrypt(const std::string &recipientUserId, const std::string &senderDeviceId, const std::vector< uint8_t > &DRmessage, const std::vector< uint8_t > &cipherMessage, std::vector< uint8_t > &plainMessage) override
Decrypt the given message.
Definition lime.cpp:251
Lime(Lime< Curve > &a)=delete
void set_x3dhServerUrl(const std::string &x3dhServerUrl) override
Set the X3DH key server URL for this identified user.
Definition lime_localStorage.cpp:1449
void delete_peerDevice(const std::string &peerDeviceId) override
Purge cached sessions for a given peer Device (used when a peer device is being deleted)
Definition lime.cpp:127
void encrypt(std::shared_ptr< const std::string > recipientUserId, std::shared_ptr< std::vector< RecipientData > > recipients, std::shared_ptr< const std::vector< uint8_t > > plainMessage, const lime::EncryptionPolicy encryptionPolicy, std::shared_ptr< std::vector< uint8_t > > cipherMessage, const limeCallback &callback) override
Encrypt a buffer(text or file) for a given list of recipient devices if specified localDeviceId is no...
Definition lime.cpp:169
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
constexpr uint16_t OPk_initialBatchSize
default batch size when creating a new user
Definition lime_settings.hpp:82
Definition lime.cpp:30
EncryptionPolicy
Definition lime.hpp:42
std::function< void(const lime::CallbackReturn status, const std::string message)> limeCallback
Callback use to give a status on asynchronous operation.
Definition lime.hpp:96
PeerDeviceStatus
Definition lime.hpp:54
std::function< void(const std::string &url, const std::string &from, const std::vector< uint8_t > &message, const limeX3DHServerResponseProcess &reponseProcess)> limeX3DHServerPostData
Post a message to the X3DH server.
Definition lime.hpp:116
network_state
Definition lime_impl.hpp:37
extend the RecipientData to add a Double Ratchet session shared with the recipient
Definition lime_double_ratchet.hpp:143
Holds everything found in a key bundle received from X3DH server.
Definition lime_x3dh_protocol.hpp:41
structure holding user data while waiting for callback from X3DH server response processing
Definition lime_impl.hpp:123
callbackUserData(std::weak_ptr< Lime< Curve > > thiz, const limeCallback &callbackRef, uint16_t OPkServerLowLimit, uint16_t OPkBatchSize)
created at update: getSelfOPks. EncryptionPolicy is not used, set it to the default value anyway
Definition lime_impl.hpp:150
const limeCallback callback
is a lambda closure, not real idea of what is its lifetime but it seems ok to hold it this way
Definition lime_impl.hpp:127
uint16_t OPkBatchSize
Used when fetching from server self OPk : how many will we upload if needed.
Definition lime_impl.hpp:141
callbackUserData(std::weak_ptr< Lime< Curve > > thiz, const limeCallback &callbackRef, std::shared_ptr< const std::string > recipientUserId, std::shared_ptr< std::vector< RecipientData > > recipients, std::shared_ptr< const std::vector< uint8_t > > plainMessage, std::shared_ptr< std::vector< uint8_t > > cipherMessage, lime::EncryptionPolicy policy)
created at encrypt(getPeerBundle)
Definition lime_impl.hpp:156
uint16_t OPkServerLowLimit
Used when fetching from server self OPk to check if we shall upload more.
Definition lime_impl.hpp:139
callbackUserData(std::weak_ptr< Lime< Curve > > thiz, const limeCallback &callbackRef, uint16_t OPkInitialBatchSize=lime::settings::OPk_initialBatchSize)
created at user create/delete and keys Post. EncryptionPolicy is not used, set it to the default valu...
Definition lime_impl.hpp:144
std::shared_ptr< const std::vector< uint8_t > > plainMessage
plaintext. Needed for encryption: get a shared ref to keep params alive
Definition lime_impl.hpp:133
std::weak_ptr< Lime< Curve > > limeObj
limeObj is owned by the LimeManager, it shall no be destructed, do not own this with a shared_ptr as ...
Definition lime_impl.hpp:125
callbackUserData operator=(callbackUserData &a)=delete
do not copy callback data, force passing the pointer around after creation
callbackUserData(callbackUserData &a)=delete
do not copy callback data, force passing the pointer around after creation
std::shared_ptr< std::vector< RecipientData > > recipients
Recipient data vector. Needed for encryption: get a shared ref to keep params alive.
Definition lime_impl.hpp:131
std::shared_ptr< std::vector< uint8_t > > cipherMessage
ciphertext buffer. Needed for encryption: get a shared ref to keep params alive
Definition lime_impl.hpp:135
lime::EncryptionPolicy encryptionPolicy
the encryption policy from the original encryption request(if running an encryption request),...
Definition lime_impl.hpp:137
std::shared_ptr< const std::string > recipientUserId
Recipient username. Needed for encryption: get a shared ref to keep params alive.
Definition lime_impl.hpp:129