mirror of https://github.com/bqv/weechat-xmpp
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
254 lines
8.8 KiB
C++
254 lines
8.8 KiB
C++
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, version 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
#pragma once
|
|
|
|
#include <fmt/core.h>
|
|
#include <memory>
|
|
#include <functional>
|
|
#include <type_traits>
|
|
#include <signal_protocol.h>
|
|
#include <key_helper.h>
|
|
#include <session_builder.h>
|
|
#include <session_cipher.h>
|
|
#include <session_pre_key.h>
|
|
#include <protocol.h>
|
|
#include <curve.h>
|
|
|
|
namespace libsignal {
|
|
|
|
template<typename T>
|
|
struct deleter {
|
|
void operator() (T *ptr) { SIGNAL_UNREF(ptr); }
|
|
};
|
|
|
|
template<typename T>
|
|
using object = std::unique_ptr<T, deleter<T>>;
|
|
|
|
template<typename T, typename CFun, typename DFun,
|
|
CFun &f_create, DFun &f_destroy, typename Base = T>
|
|
class type {
|
|
private:
|
|
T *_ptr;
|
|
|
|
protected:
|
|
typedef T* pointer_type;
|
|
|
|
inline type(T *ptr) : _ptr(ptr) {
|
|
}
|
|
|
|
template<typename Fun, Fun &func, int success = 0, typename... Args,
|
|
typename = std::enable_if_t<std::is_same_v<int, std::invoke_result_t<Fun, pointer_type, Args...>>>>
|
|
inline void call(Args&&... args) {
|
|
int ret = func(*this, std::forward<Args>(args)...);
|
|
if (ret != success) throw std::runtime_error(
|
|
fmt::format("Signal Error: expected {}, was {}", success, ret));
|
|
}
|
|
|
|
template<typename Fun, Fun &func, typename... Args,
|
|
typename = std::enable_if_t<!std::is_same_v<int, std::invoke_result_t<Fun, pointer_type, Args...>>>>
|
|
inline std::invoke_result<Fun, pointer_type, Args...>::type
|
|
call(Args&&... args) {
|
|
return func(*this, std::forward<Args>(args)...);
|
|
}
|
|
|
|
public:
|
|
inline explicit type() : _ptr(nullptr) {
|
|
}
|
|
|
|
template<typename... Args>
|
|
inline explicit type(Args&&... args) : type() {
|
|
f_create(&_ptr, std::forward<Args>(args)...);
|
|
}
|
|
|
|
inline ~type() {
|
|
if (_ptr)
|
|
f_destroy(reinterpret_cast<Base*>(_ptr));
|
|
_ptr = nullptr;
|
|
}
|
|
|
|
type(const type &other) = delete; /* no copy construction */
|
|
type(type &&other) = default;
|
|
|
|
template<typename... Args>
|
|
inline void create(Args&&... args) {
|
|
if (_ptr)
|
|
f_destroy(reinterpret_cast<Base*>(_ptr));
|
|
_ptr = nullptr;
|
|
f_create(&_ptr, std::forward<Args>(args)...);
|
|
}
|
|
|
|
type& operator =(const type &other) = delete; /* no copy assignment */
|
|
type& operator =(type &&other) = default;
|
|
|
|
inline operator bool() const { return _ptr; }
|
|
|
|
inline T* operator *() { return _ptr; }
|
|
|
|
inline operator T*() { return _ptr; }
|
|
|
|
inline operator const T*() const { return _ptr; }
|
|
};
|
|
|
|
typedef type<struct signal_context,
|
|
decltype(signal_context_create), decltype(signal_context_destroy),
|
|
signal_context_create, signal_context_destroy> context_type;
|
|
class context : public context_type {
|
|
public:
|
|
using context_type::context_type;
|
|
|
|
inline auto set_log_function(auto &&...args) {
|
|
return call<decltype(signal_context_set_log_function),
|
|
signal_context_set_log_function>(args...);
|
|
}
|
|
|
|
inline auto set_crypto_provider(auto &&...args) {
|
|
return call<decltype(signal_context_set_crypto_provider),
|
|
signal_context_set_crypto_provider>(args...);
|
|
}
|
|
|
|
inline auto set_locking_functions(auto &&...args) {
|
|
return call<decltype(signal_context_set_locking_functions),
|
|
signal_context_set_locking_functions>(args...);
|
|
}
|
|
};
|
|
|
|
typedef type<struct signal_protocol_store_context,
|
|
decltype(signal_protocol_store_context_create),
|
|
decltype(signal_protocol_store_context_destroy),
|
|
signal_protocol_store_context_create,
|
|
signal_protocol_store_context_destroy> store_context_type;
|
|
class store_context : public store_context_type {
|
|
public:
|
|
using store_context_type::store_context_type;
|
|
|
|
inline auto set_identity_key_store(auto &&...args) {
|
|
return call<decltype(signal_protocol_store_context_set_identity_key_store),
|
|
signal_protocol_store_context_set_identity_key_store>(args...);
|
|
}
|
|
|
|
inline auto set_pre_key_store(auto &&...args) {
|
|
return call<decltype(signal_protocol_store_context_set_pre_key_store),
|
|
signal_protocol_store_context_set_pre_key_store>(args...);
|
|
}
|
|
|
|
inline auto set_signed_pre_key_store(auto &&...args) {
|
|
return call<decltype(signal_protocol_store_context_set_signed_pre_key_store),
|
|
signal_protocol_store_context_set_signed_pre_key_store>(args...);
|
|
}
|
|
|
|
inline auto set_session_store(auto &&...args) {
|
|
return call<decltype(signal_protocol_store_context_set_session_store),
|
|
signal_protocol_store_context_set_session_store>(args...);
|
|
}
|
|
|
|
inline auto set_sender_key_store(auto &&...args) {
|
|
return call<decltype(signal_protocol_store_context_set_sender_key_store),
|
|
signal_protocol_store_context_set_sender_key_store>(args...);
|
|
}
|
|
};
|
|
|
|
typedef type<struct ec_public_key,
|
|
decltype(curve_decode_point),
|
|
decltype(ec_public_key_destroy),
|
|
curve_decode_point,
|
|
ec_public_key_destroy,
|
|
signal_type_base> public_key_type;
|
|
class public_key : public public_key_type {
|
|
public:
|
|
using public_key_type::public_key_type;
|
|
|
|
inline static public_key deserialize(auto &&...args) {
|
|
pointer_type pointer;
|
|
ec_public_key_deserialize(&pointer, args...);
|
|
return public_key(pointer);
|
|
}
|
|
|
|
inline auto serialize(auto &&...args) {
|
|
return call<decltype(ec_public_key_serialize),
|
|
ec_public_key_serialize>(args...);
|
|
}
|
|
|
|
friend class identity_key_pair;
|
|
};
|
|
|
|
typedef type<struct ec_private_key,
|
|
decltype(curve_decode_private_point),
|
|
decltype(ec_private_key_destroy),
|
|
curve_decode_private_point,
|
|
ec_private_key_destroy,
|
|
signal_type_base> private_key_type;
|
|
class private_key : public private_key_type {
|
|
public:
|
|
using private_key_type::private_key_type;
|
|
|
|
inline static private_key deserialize(auto &&...args) {
|
|
pointer_type pointer;
|
|
ec_private_key_deserialize(&pointer, args...);
|
|
return private_key(pointer);
|
|
}
|
|
|
|
inline auto serialize(auto &&...args) {
|
|
return call<decltype(ec_private_key_serialize),
|
|
ec_private_key_serialize>(args...);
|
|
}
|
|
|
|
friend class identity_key_pair;
|
|
};
|
|
|
|
typedef type<struct ratchet_identity_key_pair,
|
|
decltype(ratchet_identity_key_pair_create),
|
|
decltype(ratchet_identity_key_pair_destroy),
|
|
ratchet_identity_key_pair_create,
|
|
ratchet_identity_key_pair_destroy,
|
|
signal_type_base> identity_key_pair_type;
|
|
class identity_key_pair : public identity_key_pair_type {
|
|
public:
|
|
using identity_key_pair_type::identity_key_pair_type;
|
|
|
|
inline static identity_key_pair generate(auto &&...args) {
|
|
pointer_type pointer;
|
|
signal_protocol_key_helper_generate_identity_key_pair(&pointer, args...);
|
|
return identity_key_pair(pointer);
|
|
}
|
|
|
|
inline public_key get_public(auto &&...args) {
|
|
return call<decltype(ratchet_identity_key_pair_get_public),
|
|
ratchet_identity_key_pair_get_public>(args...);
|
|
}
|
|
|
|
inline private_key get_private(auto &&...args) {
|
|
return call<decltype(ratchet_identity_key_pair_get_private),
|
|
ratchet_identity_key_pair_get_private>(args...);
|
|
}
|
|
};
|
|
|
|
typedef type<struct session_pre_key_bundle,
|
|
decltype(session_pre_key_bundle_create),
|
|
decltype(session_pre_key_bundle_destroy),
|
|
session_pre_key_bundle_create,
|
|
session_pre_key_bundle_destroy,
|
|
signal_type_base> pre_key_bundle_type;
|
|
class pre_key_bundle : public pre_key_bundle_type {
|
|
public:
|
|
using pre_key_bundle_type::pre_key_bundle_type;
|
|
};
|
|
|
|
typedef type<struct session_builder,
|
|
decltype(session_builder_create),
|
|
decltype(session_builder_free),
|
|
session_builder_create,
|
|
session_builder_free> session_builder_type;
|
|
class session_builder : public session_builder_type {
|
|
public:
|
|
using session_builder_type::session_builder_type;
|
|
|
|
inline auto process_pre_key_bundle(auto &&...args) {
|
|
return call<decltype(session_builder_process_pre_key_bundle),
|
|
session_builder_process_pre_key_bundle>(args...);
|
|
}
|
|
};
|
|
|
|
}
|