lime_manager.cpp 7.33 KB
Newer Older
johan's avatar
johan committed
1 2
/*
	lime_manager.cpp
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 26 27

	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/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#define BCTBX_LOG_DOMAIN "lime"
#include <bctoolbox/logging.h>

#include "lime/lime.hpp"
#include "lime_lime.hpp"
28
#include "lime_localStorage.hpp"
johan's avatar
johan committed
29
#include "lime_settings.hpp"
johan's avatar
johan committed
30 31 32 33

using namespace::std;

namespace lime {
34 35 36 37
	void LimeManager::load_user(std::shared_ptr<LimeGeneric> &user, const std::string &localDeviceId) {
		// Load user object
		auto userElem = m_users_cache.find(localDeviceId);
		if (userElem == m_users_cache.end()) { // not in cache, load it from DB
38
			user = load_LimeUser(m_db_access, localDeviceId, m_X3DH_post_data);
39 40 41 42 43 44 45
			m_users_cache[localDeviceId]=user;
		} else {
			user = userElem->second;
		}

	}

johan's avatar
johan committed
46 47 48 49 50
	/****************************************************************************/
	/*                                                                          */
	/* Lime Manager API                                                         */
	/*                                                                          */
	/****************************************************************************/
johan's avatar
johan committed
51
	void LimeManager::create_user(const std::string &localDeviceId, const std::string &x3dhServerUrl, const lime::CurveId curve, const limeCallback &callback) {
johan's avatar
johan committed
52 53 54
		create_user(localDeviceId, x3dhServerUrl, curve, lime::settings::OPk_initialBatchSize, callback);
	}
	void LimeManager::create_user(const std::string &localDeviceId, const std::string &x3dhServerUrl, const lime::CurveId curve, const uint16_t OPkInitialBatchSize, const limeCallback &callback) {
johan's avatar
johan committed
55
		auto thiz = this;
johan's avatar
johan committed
56
		limeCallback managerCreateCallback([thiz, localDeviceId, callback](lime::callbackReturn returnCode, std::string errorMessage) {
johan's avatar
johan committed
57 58 59
			// first forward the callback
			callback(returnCode, errorMessage);

60
			// then check if it went well, if not delete the user from localDB
johan's avatar
johan committed
61
			if (returnCode != lime::callbackReturn::success) {
62 63
				auto localStorage = std::unique_ptr<lime::Db>(new lime::Db(thiz->m_db_access));
				localStorage->delete_LimeUser(localDeviceId);
johan's avatar
johan committed
64
				thiz->m_users_cache.erase(localDeviceId);
johan's avatar
johan committed
65 66 67
			}
		});

68
		m_users_cache.insert({localDeviceId, insert_LimeUser(m_db_access, localDeviceId, x3dhServerUrl, curve, OPkInitialBatchSize, m_X3DH_post_data, managerCreateCallback)});
johan's avatar
johan committed
69 70
	}

johan's avatar
johan committed
71
	void LimeManager::delete_user(const std::string &localDeviceId, const limeCallback &callback) {
johan's avatar
johan committed
72
		auto thiz = this;
johan's avatar
johan committed
73
		limeCallback managerDeleteCallback([thiz, localDeviceId, callback](lime::callbackReturn returnCode, std::string errorMessage) {
johan's avatar
johan committed
74 75 76 77 78
			// first forward the callback
			callback(returnCode, errorMessage);

			// then remove the user from cache(it will trigger destruction of the lime generic object so do it last
			// as it will also destroy the instance of this callback)
johan's avatar
johan committed
79
			thiz->m_users_cache.erase(localDeviceId);
johan's avatar
johan committed
80 81
		});

82
		// Load user object
johan's avatar
johan committed
83
		std::shared_ptr<LimeGeneric> user;
84
		LimeManager::load_user(user, localDeviceId);
johan's avatar
johan committed
85 86 87 88

		user->delete_user(managerDeleteCallback);
	}

johan's avatar
johan committed
89
	void LimeManager::encrypt(const std::string &localDeviceId, 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, const limeCallback &callback) {
johan's avatar
johan committed
90 91
		// Load user object
		std::shared_ptr<LimeGeneric> user;
92
		LimeManager::load_user(user, localDeviceId);
johan's avatar
johan committed
93 94 95 96 97

		// call the encryption function
		user->encrypt(recipientUserId, recipients, plainMessage, cipherMessage, callback);
	}

johan's avatar
johan committed
98
	bool LimeManager::decrypt(const std::string &localDeviceId, const std::string &recipientUserId, const std::string &senderDeviceId, const std::vector<uint8_t> &cipherHeader, const std::vector<uint8_t> &cipherMessage, std::vector<uint8_t> &plainMessage) {
johan's avatar
johan committed
99 100
		// Load user object
		std::shared_ptr<LimeGeneric> user;
101
		LimeManager::load_user(user, localDeviceId);
johan's avatar
johan committed
102 103 104 105

		// call the decryption function
		return user->decrypt(recipientUserId, senderDeviceId, cipherHeader, cipherMessage, plainMessage);
	}
106

johan's avatar
johan committed
107
	/* This version use default settings */
108
	void LimeManager::update(const limeCallback &callback) {
johan's avatar
johan committed
109 110 111
		update(callback, lime::settings::OPk_serverLowLimit, lime::settings::OPk_batchSize);
	}
	void LimeManager::update(const limeCallback &callback, uint16_t OPkServerLowLimit, uint16_t OPkBatchSize) {
112 113 114
		// open local DB
		auto localStorage = std::unique_ptr<lime::Db>(new lime::Db(m_db_access));

johan's avatar
johan committed
115
		/* DR sessions and old stale SPk cleaning */
116
		localStorage->clean_DRSessions();
johan's avatar
johan committed
117 118 119 120 121 122
		localStorage->clean_SPk();

		// get all users from localStorage
		std::vector<std::string> deviceIds{};
		localStorage->get_allLocalDevices(deviceIds);

johan's avatar
johan committed
123
		//This counter will trace number of callbacks, to trace how many operation did end.
johan's avatar
johan committed
124
		// we expect two callback per local user account: one for update SPk, one for get OPk number on server
johan's avatar
johan committed
125
		auto callbackCount = make_shared<size_t>(deviceIds.size()*2);
johan's avatar
johan committed
126 127
		auto globalReturnCode = make_shared<lime::callbackReturn>(lime::callbackReturn::success);

johan's avatar
johan committed
128 129 130
		// this callback will get all callbacks from update OPk and SPk on all users, when everyone is done, call the callback given to LimeManager::update
		limeCallback managerUpdateCallback([callbackCount, globalReturnCode, callback](lime::callbackReturn returnCode, std::string errorMessage) {
			(*callbackCount)--;
johan's avatar
johan committed
131 132 133 134
			if (returnCode == lime::callbackReturn::fail) {
				*globalReturnCode = lime::callbackReturn::fail; // if one fail, return fail at the end of it
			}

johan's avatar
johan committed
135
			if (*callbackCount == 0) {
johan's avatar
johan committed
136 137 138 139 140 141 142 143 144 145
				if (callback) callback(*globalReturnCode, "");
			}
		});


		// for each user
		for (auto deviceId : deviceIds) {
			BCTBX_SLOGI<<"Lime update user "<<deviceId;
			//load user
			std::shared_ptr<LimeGeneric> user;
146
			LimeManager::load_user(user, deviceId);
johan's avatar
johan committed
147

johan's avatar
johan committed
148 149
			// send a request to X3DH server to check how many OPk are left on server, upload more if needed
			user->update_OPk(managerUpdateCallback, OPkServerLowLimit, OPkBatchSize);
johan's avatar
johan committed
150 151 152 153

			// update the SPk(if needed)
			user->update_SPk(managerUpdateCallback);
		}
154
	}
155

156 157 158
	void LimeManager::get_selfIdentityKey(const std::string &localDeviceId, std::vector<uint8_t> &Ik) {
		std::shared_ptr<LimeGeneric> user;
		LimeManager::load_user(user, localDeviceId);
159

160
		user->get_Ik(Ik);
161
	}
162

163 164 165 166 167 168 169 170 171 172 173 174 175 176
	void LimeManager::set_peerIdentityVerifiedStatus(const std::string &peerDeviceId, const std::vector<uint8_t> &Ik, bool status) {
		// open local DB
		auto localStorage = std::unique_ptr<lime::Db>(new lime::Db(m_db_access));

		localStorage->set_PeerDevicesVerifiedStatus(peerDeviceId, Ik, status);
	}

	bool LimeManager::get_peerIdentityVerifiedStatus(const std::string &peerDeviceId) {
		// open local DB
		auto localStorage = std::unique_ptr<lime::Db>(new lime::Db(m_db_access));

		return localStorage->get_PeerDevicesIdentityVerifiedStatus(peerDeviceId);
	}

johan's avatar
johan committed
177
} // namespace lime