spank-olm

WIP Do not look
git clone git://archive.git.mtrnord.blog/MTRNord/spank-olm.git
Log | Files | Refs | README | LICENSE

commit b34e2f0bc86bc15047174d4f8571dfd547879ee2
parent 22cf7b66f01e148b4f50a94256aa4f91d92f42ad
Author: MTRNord <mtrnord1@gmail.com>
Date:   Wed,  7 Aug 2024 16:21:12 +0200

Small refactoring

Diffstat:
Minclude/account.hpp | 4+---
Msrc/account.cpp | 134+++++++++++++++++++++++++++++++------------------------------------------------
Mtests/account_test.cpp | 4----
3 files changed, 54 insertions(+), 88 deletions(-)

diff --git a/include/account.hpp b/include/account.hpp @@ -39,8 +39,7 @@ namespace spank_olm struct Account { - Account() : num_fallback_keys(0), - next_one_time_key_id(0) + Account() : next_one_time_key_id(0) { } @@ -48,7 +47,6 @@ namespace spank_olm std::optional<IdentityKeys> identity_keys; ///< The identity keys for the account. FixedSizeArray<OneTimeKey, MAX_ONE_TIME_KEYS> one_time_keys; ///< The one-time keys for the account. - std::uint8_t num_fallback_keys; ///< The number of fallback keys. std::optional<OneTimeKey> current_fallback_key; ///< The current fallback key. std::optional<OneTimeKey> prev_fallback_key; ///< The previous fallback key. std::uint32_t next_one_time_key_id; ///< The identifier for the next one-time key. diff --git a/src/account.cpp b/src/account.cpp @@ -7,25 +7,24 @@ /* Convenience macro for checking the return value of internal unpickling * functions and returning early on failure. */ #ifndef UNPICKLE_OK -#define UNPICKLE_OK(x) do { if (!(x)) return NULL; } while(0) +#define UNPICKLE_OK(x) do { if (!(x)) return nullptr; } while(0) #endif namespace spank_olm { /** - * Serializes a 32-bit unsigned integer into a byte array. - * - * @param pos Pointer to the current position in the byte array. - * @param value The 32-bit unsigned integer to serialize. - * @return Pointer to the position in the byte array after the serialized data. - */ + * Serializes a 32-bit unsigned integer into a byte array. + * + * @param pos Pointer to the current position in the byte array. + * @param value The 32-bit unsigned integer to serialize. + * @return Pointer to the position in the byte array after the serialized data. + */ std::uint8_t* pickle(std::uint8_t* pos, std::uint32_t value) { - pos += 4; - for (unsigned i = 4; i--;) + for (int i = 3; i >= 0; --i) { - *(--pos) = value; + pos[i] = value & 0xFF; value >>= 8; } return pos + 4; @@ -41,14 +40,9 @@ namespace spank_olm */ std::uint8_t const* unpickle(std::uint8_t const* pos, std::uint8_t const* end, std::uint32_t& value) { - value = 0; if (!pos || end < pos + 4) return nullptr; - for (unsigned i = 4; i--;) - { - value <<= 8; - value |= *(pos++); - } - return pos; + value = (pos[0] << 24) | (pos[1] << 16) | (pos[2] << 8) | pos[3]; + return pos + 4; } /** @@ -115,12 +109,12 @@ namespace spank_olm /** - * Serializes a std::vector<uint8_t> into a byte array. - * - * @param pos Pointer to the current position in the byte array. - * @param value The Botan::secure_vector<uint8_t> to serialize. - * @return Pointer to the position in the byte array after the serialized data. - */ + * Serializes a std::vector<uint8_t> into a byte array. + * + * @param pos Pointer to the current position in the byte array. + * @param value The Botan::secure_vector<uint8_t> to serialize. + * @return Pointer to the position in the byte array after the serialized data. + */ std::uint8_t* pickle(std::uint8_t* pos, const std::vector<uint8_t>& value) { pos = pickle(pos, static_cast<std::uint32_t>(value.size())); @@ -154,8 +148,7 @@ namespace spank_olm { pos = pickle(pos, value->id); pos = pickle(pos, value->published); - pos = pickle(pos, value->key.raw_private_key_bits()); - return pos; + return pickle(pos, value->key.raw_private_key_bits()); } /** @@ -173,13 +166,17 @@ namespace spank_olm bool published; ///< Indicates whether the key has been published. pos = unpickle(pos, end, id); - if (!id) + if (!pos || !id) { return {nullptr, std::nullopt}; } pos = unpickle(pos, end, published); + if (!pos) return {nullptr, std::nullopt}; + Botan::secure_vector<uint8_t> key_bits; pos = unpickle(pos, end, key_bits); + if (!pos) return {nullptr, std::nullopt}; + auto otk = OneTimeKey{id, published, Botan::X25519_PrivateKey(key_bits)}; return {pos, otk}; @@ -233,11 +230,7 @@ namespace spank_olm while (size-- && pos != end) { auto [temp_pos, value] = unpickle_otk(pos, end); - pos = temp_pos; - if (!pos) - { - return nullptr; - } + if (!((pos = temp_pos))) return nullptr; list.insert(value.value()); } @@ -292,8 +285,7 @@ namespace spank_olm pos = pickle(pos, value->ed25519_key.public_key()->raw_public_key_bits()); pos = pickle(pos, value->ed25519_key.raw_private_key_bits()); pos = pickle(pos, value->curve25519_key.public_key()->raw_public_key_bits()); - pos = pickle(pos, value->curve25519_key.raw_private_key_bits()); - return pos; + return pickle(pos, value->curve25519_key.raw_private_key_bits()); } /** @@ -310,15 +302,16 @@ namespace spank_olm { if (!pos || pos == end) return nullptr; Botan::secure_vector<uint8_t> ed25519_public_key_bits; + Botan::secure_vector<uint8_t> curve25519_public_key_bits; + Botan::secure_vector<uint8_t> ed25519_private_key_bits; + Botan::secure_vector<uint8_t> curve25519_private_key_bits; + pos = unpickle(pos, end, ed25519_public_key_bits); UNPICKLE_OK(pos); - Botan::secure_vector<uint8_t> ed25519_private_key_bits; pos = unpickle(pos, end, ed25519_private_key_bits); UNPICKLE_OK(pos); - Botan::secure_vector<uint8_t> curve25519_public_key_bits; pos = unpickle(pos, end, curve25519_public_key_bits); UNPICKLE_OK(pos); - Botan::secure_vector<uint8_t> curve25519_private_key_bits; pos = unpickle(pos, end, curve25519_private_key_bits); UNPICKLE_OK(pos); value = IdentityKeys{ @@ -363,14 +356,10 @@ namespace spank_olm // Make sure we check the key pairs. if (!identity_keys->ed25519_key.check_key(rng, false) || - !identity_keys->curve25519_key.check_key(rng, false)) - { - throw SpankOlmErrorKeyGeneration(); - } - - // Verify the public keys using the respective check_key methods. - if (!identity_keys->ed25519_key.public_key()->check_key(rng, false) || - !identity_keys->curve25519_key.public_key()->check_key(rng, false)) + !identity_keys->curve25519_key.check_key(rng, false) || + !identity_keys->ed25519_key.public_key()->check_key(rng, false) || + !identity_keys->curve25519_key.public_key()->check_key(rng, false) + ) { throw SpankOlmErrorKeyGeneration(); } @@ -401,7 +390,7 @@ namespace spank_olm if (!key->published) { key->published = true; - count++; + ++count; } } @@ -413,25 +402,20 @@ namespace spank_olm { for (std::size_t i = 0; i < number_of_keys; ++i) { - one_time_keys.insert(OneTimeKey{++next_one_time_key_id, false, Botan::X25519_PrivateKey(rng)}); + one_time_keys.insert({++next_one_time_key_id, false, Botan::X25519_PrivateKey(rng)}); } } void Account::generate_fallback_key(Botan::RandomNumberGenerator& rng) { - if (num_fallback_keys < 2) - { - num_fallback_keys++; - } prev_fallback_key = current_fallback_key; current_fallback_key = OneTimeKey{++next_one_time_key_id, false, Botan::X25519_PrivateKey(rng)}; } void Account::forget_old_fallback_key() { - if (num_fallback_keys >= 2) + if (current_fallback_key && prev_fallback_key) { - num_fallback_keys = 1; // TODO: Verify if this is correct. prev_fallback_key.reset(); } @@ -446,12 +430,12 @@ namespace spank_olm return one_time_key; } } - if (num_fallback_keys >= 1 && current_fallback_key->key.public_key()->raw_public_key_bits() == key. + if (current_fallback_key && current_fallback_key->key.public_key()->raw_public_key_bits() == key. raw_public_key_bits()) { return &current_fallback_key.value(); } - if (num_fallback_keys >= 2 && prev_fallback_key->key.public_key()->raw_public_key_bits() == key. + if (prev_fallback_key && prev_fallback_key->key.public_key()->raw_public_key_bits() == key. raw_public_key_bits()) { return &current_fallback_key.value(); @@ -503,12 +487,18 @@ namespace spank_olm pos = spank_olm::pickle(pos, one_time_keys); - pos = spank_olm::pickle(pos, num_fallback_keys); + // Calculate the number of fallback keys + std::uint8_t fallback_key_count = 0; + if (current_fallback_key && current_fallback_key->published) fallback_key_count++; + if (prev_fallback_key && prev_fallback_key->published) fallback_key_count++; + + // Serialize the fallback key count + pos = spank_olm::pickle(pos, fallback_key_count); - if (num_fallback_keys >= 1) + if (current_fallback_key) { pos = spank_olm::pickle(pos, current_fallback_key); - if (num_fallback_keys >= 2) + if (prev_fallback_key) { pos = spank_olm::pickle(pos, prev_fallback_key); } @@ -566,11 +556,7 @@ namespace spank_olm throw SpankOlmErrorCorruptedAccountPickle(); } - if (pickle_version <= 2) - { - value.num_fallback_keys = 0; - } - else if (pickle_version == 3) + if (pickle_version == 3) { pos = spank_olm::unpickle(pos, end, value.current_fallback_key); if (!pos) @@ -582,44 +568,30 @@ namespace spank_olm { throw SpankOlmErrorCorruptedAccountPickle(); } - if (value.current_fallback_key->published) - { - if (value.prev_fallback_key->published) - { - value.num_fallback_keys = 2; - } - else - { - value.num_fallback_keys = 1; - } - } - else - { - value.num_fallback_keys = 0; - } } else { - pos = spank_olm::unpickle(pos, end, value.num_fallback_keys); + std::uint8_t num_fallback_keys; + pos = spank_olm::unpickle(pos, end, num_fallback_keys); if (!pos) { throw SpankOlmErrorCorruptedAccountPickle(); } - if (value.num_fallback_keys >= 1) + if (num_fallback_keys >= 1) { pos = spank_olm::unpickle(pos, end, value.current_fallback_key); if (!pos) { throw SpankOlmErrorCorruptedAccountPickle(); } - if (value.num_fallback_keys >= 2) + if (num_fallback_keys >= 2) { pos = spank_olm::unpickle(pos, end, value.prev_fallback_key); if (!pos) { throw SpankOlmErrorCorruptedAccountPickle(); } - if (value.num_fallback_keys >= 3) + if (num_fallback_keys >= 3) { throw SpankOlmErrorCorruptedAccountPickle(); } diff --git a/tests/account_test.cpp b/tests/account_test.cpp @@ -24,7 +24,6 @@ TEST_CASE("Account serialization and deserialization") account.identity_keys->curve25519_key.public_key()->raw_public_key_bits() == deserialized.identity_keys-> curve25519_key.public_key()->raw_public_key_bits()); REQUIRE(account.one_time_keys.size() == deserialized.one_time_keys.size()); - REQUIRE(account.num_fallback_keys == deserialized.num_fallback_keys); REQUIRE(account.next_one_time_key_id == deserialized.next_one_time_key_id); } @@ -67,13 +66,10 @@ TEST_CASE("Account generate and forget fallback key") account.new_account(rng); account.generate_fallback_key(rng); - REQUIRE(account.num_fallback_keys == 1); account.generate_fallback_key(rng); - REQUIRE(account.num_fallback_keys == 2); account.forget_old_fallback_key(); - REQUIRE(account.num_fallback_keys == 1); REQUIRE(account.prev_fallback_key == std::nullopt); }