diff --git a/src/crypto.cpp b/src/crypto.cpp index 1aa77ad13c2dbd6ef54bcf2bc00420e02551697b..61947de854d5c39d8498460d92c97315572ed11b 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -6,163 +6,205 @@ using json = nlohmann::json; using namespace mtx::client::crypto; -constexpr std::size_t SIGNATURE_SIZE = 64; - -std::shared_ptr<olm::Account> -mtx::client::crypto::olm_new_account() +void +OlmClient::create_new_account() { - auto olm_account = std::make_shared<olm::Account>(); + // The method has no effect if the account is already initialized. + if (account_) + return; - const auto nbytes = olm_account->new_account_random_length(); - auto buf = create_buffer(nbytes); + account_ = + std::unique_ptr<OlmAccount, OlmDeleter>(olm_account(new uint8_t[olm_account_size()])); - int result = olm_account->new_account(buf->data(), buf->size()); + auto tmp_buf = create_buffer(olm_create_account_random_length(account_.get())); + const int ret = olm_create_account(account_.get(), tmp_buf->data(), tmp_buf->size()); - if (result == -1) - throw olm_exception("olm_new_account", olm_account->last_error); + if (ret == -1) { + account_.reset(); + throw olm_exception("create_new_account", account_.get()); + } +} - return olm_account; +void +OlmClient::create_new_utility() +{ + // The method has no effect if the account is already initialized. + if (utility_) + return; + + utility_ = + std::unique_ptr<OlmUtility, OlmDeleter>(olm_utility(new uint8_t[olm_utility_size()])); } -IdentityKeys -mtx::client::crypto::identity_keys(std::shared_ptr<olm::Account> account) +std::unique_ptr<OlmSession, OlmDeleter> +OlmClient::create_new_session() { - const auto nbytes = account->get_identity_json_length(); - auto buf = create_buffer(nbytes); + return std::unique_ptr<OlmSession, OlmDeleter>( + olm_session(new uint8_t[olm_session_size()])); +} - int result = account->get_identity_json(buf->data(), buf->size()); +IdentityKeys +OlmClient::identity_keys() +{ + auto tmp_buf = create_buffer(olm_account_identity_keys_length(account_.get())); + int result = + olm_account_identity_keys(account_.get(), (void *)tmp_buf->data(), tmp_buf->size()); if (result == -1) - throw olm_exception("identity_keys", account->last_error); + throw olm_exception("identity_keys", account_.get()); + + return json::parse(std::string(tmp_buf->begin(), tmp_buf->end())); +} + +std::unique_ptr<BinaryBuf> +OlmClient::sign_message(const std::string &msg) +{ + // Message buffer + auto buf = str_to_buffer(msg); - std::string data(buf->begin(), buf->end()); - IdentityKeys keys = json::parse(data); + // Signature buffer + auto signature_buf = create_buffer(olm_account_signature_length(account_.get())); + olm_account_sign( + account_.get(), buf->data(), buf->size(), signature_buf->data(), signature_buf->size()); - return keys; + return signature_buf; } std::string -mtx::client::crypto::sign_identity_keys(std::shared_ptr<olm::Account> account, - const IdentityKeys &keys, - const mtx::identifiers::User &user_id, - const std::string &device_id) +OlmClient::sign_identity_keys() { + auto keys = identity_keys(); + json body{{"algorithms", {"m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"}}, - {"user_id", user_id.to_string()}, - {"device_id", device_id}, + {"user_id", user_id_}, + {"device_id", device_id_}, {"keys", { - {"curve25519:" + device_id, keys.curve25519}, - {"ed25519:" + device_id, keys.ed25519}, + {"curve25519:" + device_id_, keys.curve25519}, + {"ed25519:" + device_id_, keys.ed25519}, }}}; - return encode_base64(sign_message(account, body.dump())->data(), SIGNATURE_SIZE); + return encode_base64(sign_message(body.dump())->data(), + olm_account_signature_length(account_.get())); } std::size_t -mtx::client::crypto::generate_one_time_keys(std::shared_ptr<olm::Account> account, - std::size_t number_of_keys) +OlmClient::generate_one_time_keys(std::size_t number_of_keys) { - const auto nbytes = account->generate_one_time_keys_random_length(number_of_keys); + const std::size_t nbytes = + olm_account_generate_one_time_keys_random_length(account_.get(), number_of_keys); auto buf = create_buffer(nbytes); - return account->generate_one_time_keys(number_of_keys, buf->data(), buf->size()); + + const int ret = olm_account_generate_one_time_keys( + account_.get(), number_of_keys, buf->data(), buf->size()); + + if (ret == -1) + throw olm_exception("generate_one_time_keys", account_.get()); + + return ret; } -json -mtx::client::crypto::one_time_keys(std::shared_ptr<olm::Account> account) +OneTimeKeys +OlmClient::one_time_keys() { - const auto nbytes = account->get_one_time_keys_json_length(); - auto buf = create_buffer(nbytes); + auto buf = create_buffer(olm_account_one_time_keys_length(account_.get())); - int result = account->get_one_time_keys_json(buf->data(), buf->size()); + const int ret = olm_account_one_time_keys(account_.get(), buf->data(), buf->size()); - if (result == -1) - throw olm_exception("one_time_keys", account->last_error); + if (ret == -1) + throw olm_exception("one_time_keys", account_.get()); return json::parse(std::string(buf->begin(), buf->end())); } std::string -mtx::client::crypto::sign_one_time_key(std::shared_ptr<olm::Account> account, - const std::string &key) +OlmClient::sign_one_time_key(const std::string &key) { json j{{"key", key}}; - auto str_json = j.dump(); + auto str_json = j.dump(); + auto signature = sign_message(j.dump()); - auto signature_buf = sign_message(account, j.dump()); - - return encode_base64(signature_buf->data(), signature_buf->size()); + return encode_base64(signature->data(), signature->size()); } std::map<std::string, json> -mtx::client::crypto::sign_one_time_keys(std::shared_ptr<olm::Account> account, - const mtx::client::crypto::OneTimeKeys &keys, - const mtx::identifiers::User &user_id, - const std::string &device_id) +OlmClient::sign_one_time_keys(const OneTimeKeys &keys) { // Sign & append the one time keys. std::map<std::string, json> signed_one_time_keys; for (const auto &elem : keys.curve25519) { - auto sig = sign_one_time_key(account, elem.second); + auto sig = sign_one_time_key(elem.second); signed_one_time_keys["signed_curve25519:" + elem.first] = - signed_one_time_key_json(user_id, device_id, elem.second, sig); + signed_one_time_key_json(elem.second, sig); } return signed_one_time_keys; } +json +OlmClient::signed_one_time_key_json(const std::string &key, const std::string &signature) +{ + return json{{"key", key}, + {"signatures", {{user_id_, {{"ed25519:" + device_id_, signature}}}}}}; +} + +mtx::requests::UploadKeys +OlmClient::create_upload_keys_request() +{ + return create_upload_keys_request(one_time_keys()); +} + mtx::requests::UploadKeys -mtx::client::crypto::create_upload_keys_request( - std::shared_ptr<olm::Account> account, - const mtx::client::crypto::IdentityKeys &identity_keys, - const mtx::client::crypto::OneTimeKeys &one_time_keys, - const mtx::identifiers::User &user_id, - const std::string &device_id) +OlmClient::create_upload_keys_request(const mtx::client::crypto::OneTimeKeys &one_time_keys) { mtx::requests::UploadKeys req; - req.device_keys.user_id = user_id.to_string(); - req.device_keys.device_id = device_id; + req.device_keys.user_id = user_id_; + req.device_keys.device_id = device_id_; + + auto id_keys = identity_keys(); - req.device_keys.keys["curve25519:" + device_id] = identity_keys.curve25519; - req.device_keys.keys["ed25519:" + device_id] = identity_keys.ed25519; + req.device_keys.keys["curve25519:" + device_id_] = id_keys.curve25519; + req.device_keys.keys["ed25519:" + device_id_] = id_keys.ed25519; // Generate and add the signature to the request. - auto sig = sign_identity_keys(account, identity_keys, user_id, device_id); - req.device_keys.signatures[user_id.to_string()]["ed25519:" + device_id] = sig; + auto sig = sign_identity_keys(); + + req.device_keys.signatures[user_id_]["ed25519:" + device_id_] = sig; if (one_time_keys.curve25519.empty()) return req; // Sign & append the one time keys. - req.one_time_keys = - mtx::client::crypto::sign_one_time_keys(account, one_time_keys, user_id, device_id); + req.one_time_keys = sign_one_time_keys(one_time_keys); return req; } -std::unique_ptr<BinaryBuf> -mtx::client::crypto::sign_message(std::shared_ptr<olm::Account> account, const std::string &msg) +std::unique_ptr<OlmSession, OlmDeleter> +OlmClient::create_outbound_group_session(const std::string &peer_identity_key, + const std::string &peer_one_time_key) { - // Message buffer - auto buf = str_to_buffer(msg); + auto session = create_new_session(); + auto tmp_buf = create_buffer(olm_create_outbound_session_random_length(session.get())); - // Signature buffer - auto signature_buf = create_buffer(SIGNATURE_SIZE); - account->sign(buf->data(), buf->size(), signature_buf->data(), signature_buf->size()); + auto idk_buf = str_to_buffer(peer_identity_key); + auto otk_buf = str_to_buffer(peer_one_time_key); - return signature_buf; -} + const int ret = olm_create_outbound_session(session.get(), + account_.get(), + idk_buf->data(), + idk_buf->size(), + otk_buf->data(), + otk_buf->size(), + tmp_buf->data(), + tmp_buf->size()); -json -mtx::client::crypto::signed_one_time_key_json(const mtx::identifiers::User &user_id, - const std::string &device_id, - const std::string &key, - const std::string &signature) -{ - return json{{"key", key}, - {"signatures", {{user_id.to_string(), {{"ed25519:" + device_id, signature}}}}}}; + if (ret == -1) + throw olm_exception("init_outbound_group_session", session.get()); + + return session; } std::unique_ptr<BinaryBuf> @@ -213,34 +255,3 @@ mtx::client::crypto::json_to_buffer(const nlohmann::json &obj) { return str_to_buffer(obj.dump()); } - -_olm_curve25519_public_key -mtx::client::crypto::str_to_curve25519_pk(const std::string &data) -{ - auto decoded = decode_base64(data); - - if (decoded->size() != CURVE25519_KEY_LENGTH) - throw olm_exception("str_to_curve25519_pk: invalid input size"); - - _olm_curve25519_public_key pk; - std::copy(decoded->begin(), decoded->end(), pk.public_key); - - return pk; -} - -olm::Session -mtx::client::crypto::init_outbound_group_session(std::shared_ptr<olm::Account> account, - const std::string &peer_identity_key, - const std::string &peer_one_time_key) -{ - olm::Session session; - - auto buf = create_buffer(session.new_outbound_session_random_length()); - session.new_outbound_session(*account, - str_to_curve25519_pk(peer_identity_key), - str_to_curve25519_pk(peer_one_time_key), - buf->data(), - buf->size()); - - return session; -} diff --git a/src/crypto.hpp b/src/crypto.hpp index 32ba11ed8180e89e4a24d6e22e9ca656db8a437f..de803e29005136b5b807856277a41861757c584b 100644 --- a/src/crypto.hpp +++ b/src/crypto.hpp @@ -2,6 +2,7 @@ #include <exception> #include <memory> +#include <new> #include <json.hpp> #include <sodium.h> @@ -13,6 +14,8 @@ #include <olm/error.h> #include <olm/session.hh> +#include <olm/olm.h> + namespace mtx { namespace client { namespace crypto { @@ -66,41 +69,28 @@ from_json(const nlohmann::json &obj, OneTimeKeys &keys) class olm_exception : public std::exception { public: - olm_exception(std::string msg, OlmErrorCode errcode) - : errcode_(errcode) - , msg_(msg + ": " + std::string(_olm_error_to_string(errcode))) + olm_exception(std::string func, OlmSession *s) + : msg_(func + ": " + std::string(olm_session_last_error(s))) + {} + + olm_exception(std::string func, OlmAccount *acc) + : msg_(func + ": " + std::string(olm_account_last_error(acc))) + {} + + olm_exception(std::string func, OlmUtility *util) + : msg_(func + ": " + std::string(olm_utility_last_error(util))) {} olm_exception(std::string msg) : msg_(msg) {} - OlmErrorCode get_errcode() const { return errcode_; } - const char *get_error() const { return _olm_error_to_string(errcode_); } - virtual const char *what() const throw() { return msg_.c_str(); } private: - OlmErrorCode errcode_; std::string msg_; }; -//! Create a new olm Account. -std::shared_ptr<olm::Account> -olm_new_account(); - -//! Retrieve the json representation of the identity keys for the given account. -IdentityKeys -identity_keys(std::shared_ptr<olm::Account> user); - -//! Generate a number of one time keys. -std::size_t -generate_one_time_keys(std::shared_ptr<olm::Account> account, std::size_t number_of_keys); - -//! Retrieve the json representation of the one time keys for the given account. -nlohmann::json -one_time_keys(std::shared_ptr<olm::Account> user); - //! Create a uint8_t buffer which is initialized with random bytes. template<class T = BinaryBuf> std::unique_ptr<T> @@ -112,42 +102,72 @@ create_buffer(std::size_t nbytes) return buf; } -//! Sign the given one time keys and encode it to base64. -std::string -sign_one_time_key(std::shared_ptr<olm::Account> account, const std::string &key); +struct OlmDeleter +{ + void operator()(OlmAccount *ptr) { operator delete(ptr, olm_account_size()); } + void operator()(OlmSession *ptr) { operator delete(ptr, olm_session_size()); } + void operator()(OlmUtility *ptr) { operator delete(ptr, olm_utility_size()); } +}; -//! Sign the identity keys. The result should be used as part of the /keys/upload/ request. -std::string -sign_identity_keys(std::shared_ptr<olm::Account> account, - const IdentityKeys &keys, - const mtx::identifiers::User &user_id, - const std::string &device_id); +class OlmClient : public std::enable_shared_from_this<OlmClient> +{ +public: + OlmClient() = default; + OlmClient(std::string user_id, std::string device_id) + : user_id_(std::move(user_id)) + , device_id_(std::move(device_id)) + {} -//! Sign the given message. -std::unique_ptr<BinaryBuf> -sign_message(std::shared_ptr<olm::Account> account, const std::string &msg); - -//! Generate the json structure for the signed one time key. -nlohmann::json -signed_one_time_key_json(const mtx::identifiers::User &user_id, - const std::string &device_id, - const std::string &key, - const std::string &signature); - -//! Sign one_time_keys and generate the appropriate structure for the /keys/upload request. -std::map<std::string, nlohmann::json> -sign_one_time_keys(std::shared_ptr<olm::Account> account, - const mtx::client::crypto::OneTimeKeys &keys, - const mtx::identifiers::User &user_id, - const std::string &device_id); - -//! Prepare request for the /keys/upload endpoint by signing identity & one time keys. -mtx::requests::UploadKeys -create_upload_keys_request(std::shared_ptr<olm::Account> account, - const mtx::client::crypto::IdentityKeys &identity_keys, - const mtx::client::crypto::OneTimeKeys &one_time_keys, - const mtx::identifiers::User &user_id, - const std::string &device_id); + using Base64String = std::string; + using SignedOneTimeKeys = std::map<std::string, json>; + + void set_device_id(std::string device_id) { device_id_ = std::move(device_id); } + void set_user_id(std::string user_id) { user_id_ = std::move(user_id); } + + //! Sign the given message. + std::unique_ptr<BinaryBuf> sign_message(const std::string &msg); + + //! Create a new olm Account. Must be called before any other operation. + void create_new_account(); + void create_new_utility(); + std::unique_ptr<OlmSession, OlmDeleter> create_new_session(); + + //! Retrieve the json representation of the identity keys for the given account. + IdentityKeys identity_keys(); + //! Sign the identity keys. + //! The result should be used as part of the /keys/upload/ request. + Base64String sign_identity_keys(); + + //! Generate a number of one time keys. + std::size_t generate_one_time_keys(std::size_t nkeys); + //! Retrieve the json representation of the one time keys for the given account. + OneTimeKeys one_time_keys(); + //! Sign the given one time keys and encode it to base64. + Base64String sign_one_time_key(const Base64String &encoded_key); + //! Sign one_time_keys and generate the appropriate structure for the /keys/upload request. + SignedOneTimeKeys sign_one_time_keys(const OneTimeKeys &keys); + //! Generate the json structure for the signed one time key. + json signed_one_time_key_json(const std::string &key, const std::string &signature); + + //! Prepare request for the /keys/upload endpoint by signing identity & one time keys. + mtx::requests::UploadKeys create_upload_keys_request(const OneTimeKeys &keys); + mtx::requests::UploadKeys create_upload_keys_request(); + + //! Create an outbount megolm session. + std::unique_ptr<OlmSession, OlmDeleter> create_outbound_group_session( + const std::string &peer_identity_key, + const std::string &peer_one_time_key); + + OlmAccount *account() { return account_.get(); } + OlmUtility *utility() { return utility_.get(); } + +private: + std::string user_id_; + std::string device_id_; + + std::unique_ptr<OlmAccount, OlmDeleter> account_; + std::unique_ptr<OlmUtility, OlmDeleter> utility_; +}; std::string encode_base64(const uint8_t *data, std::size_t len); @@ -156,23 +176,13 @@ encode_base64(const uint8_t *data, std::size_t len); std::unique_ptr<BinaryBuf> decode_base64(const std::string &data); -//! Convert the given string to an uint8_t buffer. -std::unique_ptr<BinaryBuf> -str_to_buffer(const std::string &data); - //! Convert the given json struct to an uint8_t buffer. std::unique_ptr<BinaryBuf> json_to_buffer(const nlohmann::json &obj); -//! Convert from base64 encoded public key. -_olm_curve25519_public_key -str_to_curve25519_pk(const std::string &data); - -//! Create an outbount megolm session. -olm::Session -init_outbound_group_session(std::shared_ptr<olm::Account> account, - const std::string &peer_id_key, - const std::string &peer_one_time_key); +//! Convert the given string to an uint8_t buffer. +std::unique_ptr<BinaryBuf> +str_to_buffer(const std::string &data); } // namespace crypto } // namespace client diff --git a/tests/e2ee.cpp b/tests/e2ee.cpp index fd5b4f21c471fa55d061cca7a641c0e38f31aeed..f591e6bf5240820d75090aab37f0799d45cf7d09 100644 --- a/tests/e2ee.cpp +++ b/tests/e2ee.cpp @@ -23,23 +23,20 @@ using namespace mtx::responses; using namespace std; mtx::requests::UploadKeys -generate_keys(std::shared_ptr<olm::Account> account, - const mtx::identifiers::User &user_id, - const std::string &device_id) +generate_keys(std::shared_ptr<mtx::client::crypto::OlmClient> account) { - auto idks = mtx::client::crypto::identity_keys(account); + auto idks = account->identity_keys(); + account->generate_one_time_keys(1); + auto otks = account->one_time_keys(); - mtx::client::crypto::generate_one_time_keys(account, 1); - auto otks = mtx::client::crypto::one_time_keys(account); - - return mtx::client::crypto::create_upload_keys_request( - account, idks, otks, user_id, device_id); + return account->create_upload_keys_request(otks); } TEST(Encryption, UploadIdentityKeys) { auto alice = std::make_shared<Client>("localhost"); - auto olm_account = mtx::client::crypto::olm_new_account(); + auto olm_account = std::make_shared<mtx::client::crypto::OlmClient>(); + olm_account->create_new_account(); alice->login("alice", "secret", [](const mtx::responses::Login &, RequestErr err) { check_error(err); @@ -48,14 +45,16 @@ TEST(Encryption, UploadIdentityKeys) while (alice->access_token().empty()) sleep(); - auto identity_keys = mtx::client::crypto::identity_keys(olm_account); + olm_account->set_user_id(alice->user_id().to_string()); + olm_account->set_device_id(alice->device_id()); + + auto id_keys = olm_account->identity_keys(); - ASSERT_TRUE(identity_keys.curve25519.size() > 10); - ASSERT_TRUE(identity_keys.curve25519.size() > 10); + ASSERT_TRUE(id_keys.curve25519.size() > 10); + ASSERT_TRUE(id_keys.curve25519.size() > 10); mtx::client::crypto::OneTimeKeys unused; - auto request = mtx::client::crypto::create_upload_keys_request( - olm_account, identity_keys, unused, alice->user_id(), alice->device_id()); + auto request = olm_account->create_upload_keys_request(unused); // Make the request with the signed identity keys. alice->upload_keys(request, [](const mtx::responses::UploadKeys &res, RequestErr err) { @@ -69,7 +68,8 @@ TEST(Encryption, UploadIdentityKeys) TEST(Encryption, UploadOneTimeKeys) { auto alice = std::make_shared<Client>("localhost"); - auto olm_account = mtx::client::crypto::olm_new_account(); + auto olm_account = std::make_shared<mtx::client::crypto::OlmClient>(); + olm_account->create_new_account(); alice->login("alice", "secret", [](const mtx::responses::Login &, RequestErr err) { check_error(err); @@ -78,17 +78,20 @@ TEST(Encryption, UploadOneTimeKeys) while (alice->access_token().empty()) sleep(); - auto nkeys = mtx::client::crypto::generate_one_time_keys(olm_account, 5); + olm_account->set_user_id(alice->user_id().to_string()); + olm_account->set_device_id(alice->device_id()); + + auto nkeys = olm_account->generate_one_time_keys(5); EXPECT_EQ(nkeys, 5); - auto one_time_keys = mtx::client::crypto::one_time_keys(olm_account); + json otks = olm_account->one_time_keys(); mtx::requests::UploadKeys req; // Create the proper structure for uploading. std::map<std::string, json> unsigned_keys; - auto obj = one_time_keys.at("curve25519"); + auto obj = otks.at("curve25519"); for (auto it = obj.begin(); it != obj.end(); ++it) unsigned_keys["curve25519:" + it.key()] = it.value(); @@ -106,7 +109,8 @@ TEST(Encryption, UploadOneTimeKeys) TEST(Encryption, UploadSignedOneTimeKeys) { auto alice = std::make_shared<Client>("localhost"); - auto olm_account = mtx::client::crypto::olm_new_account(); + auto olm_account = std::make_shared<mtx::client::crypto::OlmClient>(); + olm_account->create_new_account(); alice->login("alice", "secret", [](const mtx::responses::Login &, RequestErr err) { check_error(err); @@ -115,14 +119,16 @@ TEST(Encryption, UploadSignedOneTimeKeys) while (alice->access_token().empty()) sleep(); - auto nkeys = mtx::client::crypto::generate_one_time_keys(olm_account, 5); + olm_account->set_user_id(alice->user_id().to_string()); + olm_account->set_device_id(alice->device_id()); + + auto nkeys = olm_account->generate_one_time_keys(5); EXPECT_EQ(nkeys, 5); - auto one_time_keys = mtx::client::crypto::one_time_keys(olm_account); + auto one_time_keys = olm_account->one_time_keys(); mtx::requests::UploadKeys req; - req.one_time_keys = mtx::client::crypto::sign_one_time_keys( - olm_account, one_time_keys, alice->user_id(), alice->device_id()); + req.one_time_keys = olm_account->sign_one_time_keys(one_time_keys); alice->upload_keys(req, [nkeys](const mtx::responses::UploadKeys &res, RequestErr err) { check_error(err); @@ -136,7 +142,8 @@ TEST(Encryption, UploadSignedOneTimeKeys) TEST(Encryption, UploadKeys) { auto alice = std::make_shared<Client>("localhost"); - auto olm_account = mtx::client::crypto::olm_new_account(); + auto olm_account = std::make_shared<mtx::client::crypto::OlmClient>(); + olm_account->create_new_account(); alice->login("alice", "secret", [](const mtx::responses::Login &, RequestErr err) { check_error(err); @@ -145,7 +152,10 @@ TEST(Encryption, UploadKeys) while (alice->access_token().empty()) sleep(); - auto req = ::generate_keys(olm_account, alice->user_id(), alice->device_id()); + olm_account->set_user_id(alice->user_id().to_string()); + olm_account->set_device_id(alice->device_id()); + + auto req = generate_keys(olm_account); alice->upload_keys(req, [](const mtx::responses::UploadKeys &res, RequestErr err) { check_error(err); @@ -159,10 +169,13 @@ TEST(Encryption, UploadKeys) TEST(Encryption, QueryKeys) { auto alice = std::make_shared<Client>("localhost"); - auto alice_olm = mtx::client::crypto::olm_new_account(); + auto alice_olm = std::make_shared<mtx::client::crypto::OlmClient>(); auto bob = std::make_shared<Client>("localhost"); - auto bob_olm = mtx::client::crypto::olm_new_account(); + auto bob_olm = std::make_shared<mtx::client::crypto::OlmClient>(); + + alice_olm->create_new_account(); + bob_olm->create_new_account(); alice->login("alice", "secret", [](const mtx::responses::Login &, RequestErr err) { check_error(err); @@ -174,9 +187,15 @@ TEST(Encryption, QueryKeys) while (alice->access_token().empty() || bob->access_token().empty()) sleep(); + alice_olm->set_user_id(alice->user_id().to_string()); + alice_olm->set_device_id(alice->device_id()); + + bob_olm->set_user_id(bob->user_id().to_string()); + bob_olm->set_device_id(bob->device_id()); + // Create and upload keys for both users. - auto alice_req = ::generate_keys(alice_olm, alice->user_id(), alice->device_id()); - auto bob_req = ::generate_keys(bob_olm, bob->user_id(), bob->device_id()); + auto alice_req = ::generate_keys(alice_olm); + auto bob_req = ::generate_keys(bob_olm); // Validates that both upload requests are finished. atomic_int uploads(0); @@ -257,7 +276,8 @@ TEST(Encryption, QueryKeys) TEST(Encryption, KeyChanges) { auto carl = std::make_shared<Client>("localhost"); - auto carl_olm = mtx::client::crypto::olm_new_account(); + auto carl_olm = std::make_shared<mtx::client::crypto::OlmClient>(); + carl_olm->create_new_account(); carl->login("carl", "secret", [](const mtx::responses::Login &, RequestErr err) { check_error(err); @@ -266,6 +286,9 @@ TEST(Encryption, KeyChanges) while (carl->access_token().empty()) sleep(); + carl_olm->set_device_id(carl->device_id()); + carl_olm->set_user_id(carl->user_id().to_string()); + mtx::requests::CreateRoom req; carl->create_room( req, [carl, carl_olm](const mtx::responses::CreateRoom &, RequestErr err) { @@ -281,8 +304,7 @@ TEST(Encryption, KeyChanges) check_error(err); const auto next_batch_token = res.next_batch; - auto key_req = - ::generate_keys(carl_olm, carl->user_id(), carl->device_id()); + auto key_req = ::generate_keys(carl_olm); atomic_bool keys_uploaded(false); diff --git a/tests/utils.cpp b/tests/utils.cpp index db182c64466d51fb4fc2a7f66a89f8d36316bb82..bfef609fef67cefd60458a20815a0c22a24f05fd 100644 --- a/tests/utils.cpp +++ b/tests/utils.cpp @@ -11,8 +11,6 @@ using json = nlohmann::json; using namespace mtx::client::crypto; using namespace std; -constexpr int SIGNATURE_SIZE = 64; - TEST(Utilities, JsonToBuffer) { auto msg = json({{"key", "text"}}); @@ -23,33 +21,39 @@ TEST(Utilities, JsonToBuffer) TEST(Utilities, VerifySignedOneTimeKey) { - auto alice = olm_new_account(); + auto alice = make_shared<OlmClient>(); + alice->create_new_account(); + alice->create_new_utility(); - generate_one_time_keys(alice, 1); - auto keys = one_time_keys(alice); + alice->identity_keys(); - auto first_key = keys["curve25519"].begin()->get<std::string>(); - auto msg = json({{"key", first_key}}).dump(); + alice->generate_one_time_keys(1); + auto keys = alice->one_time_keys(); - auto sig_buf = sign_message(alice, msg); + auto first_key = keys.curve25519.begin()->second; + auto msg = json({{"key", first_key}}).dump(); - olm::Utility utillity; + auto sig_buf = alice->sign_message(msg); - auto res = utillity.ed25519_verify(alice->identity_keys.ed25519_key.public_key, - str_to_buffer(msg)->data(), - msg.size(), - sig_buf->data(), - SIGNATURE_SIZE); + auto res = olm_ed25519_verify(alice->utility(), + str_to_buffer(alice->identity_keys().ed25519)->data(), + str_to_buffer(alice->identity_keys().ed25519)->size(), + str_to_buffer(msg)->data(), + str_to_buffer(msg)->size(), + sig_buf->data(), + sig_buf->size()); - EXPECT_EQ(utillity.last_error, 0); + EXPECT_EQ(std::string(olm_utility_last_error(alice->utility())), "SUCCESS"); EXPECT_EQ(res, 0); } TEST(Utilities, VerifySignedIdentityKeys) { - auto alice = olm_new_account(); + auto alice = make_shared<OlmClient>(); + alice->create_new_account(); + alice->create_new_utility(); - json keys = identity_keys(alice); + json keys = alice->identity_keys(); auto msg = json({{"algorithms", {"m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"}}, {"device_id", "some_device"}, @@ -59,47 +63,16 @@ TEST(Utilities, VerifySignedIdentityKeys) {"ed25519:some_device", keys["ed25519"]}}}}) .dump(); - auto sig_buf = sign_message(alice, msg); - - olm::Utility utillity; + auto sig_buf = alice->sign_message(msg); - auto res = utillity.ed25519_verify(alice->identity_keys.ed25519_key.public_key, - str_to_buffer(msg)->data(), - msg.size(), - sig_buf->data(), - SIGNATURE_SIZE); + auto res = olm_ed25519_verify(alice->utility(), + str_to_buffer(alice->identity_keys().ed25519)->data(), + str_to_buffer(alice->identity_keys().ed25519)->size(), + str_to_buffer(msg)->data(), + str_to_buffer(msg)->size(), + sig_buf->data(), + sig_buf->size()); - EXPECT_EQ(utillity.last_error, 0); + EXPECT_EQ(std::string(olm_utility_last_error(alice->utility())), "SUCCESS"); EXPECT_EQ(res, 0); } - -TEST(Utilities, OutboundGroupSession) -{ - auto alice = olm_new_account(); - auto bob = olm_new_account(); - auto carl = olm_new_account(); - - generate_one_time_keys(bob, 1); - generate_one_time_keys(carl, 1); - - OneTimeKeys bob_otk = one_time_keys(bob); - IdentityKeys bob_ik = identity_keys(bob); - - OneTimeKeys carl_otk = one_time_keys(carl); - IdentityKeys carl_ik = identity_keys(carl); - - auto bob_session = - init_outbound_group_session(alice, bob_ik.curve25519, bob_otk.curve25519.begin()->second); - auto carl_session = init_outbound_group_session( - alice, carl_ik.curve25519, carl_otk.curve25519.begin()->second); - - auto sid_1 = create_buffer(bob_session.session_id_length()); - bob_session.session_id(sid_1->data(), sid_1->size()); - - EXPECT_EQ(sid_1->size(), 32); - - auto sid_2 = create_buffer(carl_session.session_id_length()); - carl_session.session_id(sid_2->data(), sid_2->size()); - - EXPECT_EQ(sid_2->size(), 32); -}