Skip to content
Snippets Groups Projects
Commit 8dd3c182 authored by Richard van der Hoff's avatar Richard van der Hoff
Browse files

Make space in the session pickle for chain index

Keeping track of the chain index is a useful thing to do, but is only required
if we've enabled diagnostics. Extend the session pickle format to make a space
for it, so that pickles can be transferred between the logging_enabled branch
and the master branch without loss of information.

Also add some tests for session pickling which explicitly check that we can
unpickle both formats of pickle.
parent 757c4225
No related branches found
No related tags found
No related merge requests found
......@@ -169,7 +169,8 @@ std::uint8_t * pickle(
std::uint8_t const * unpickle(
std::uint8_t const * pos, std::uint8_t const * end,
Ratchet & value
Ratchet & value,
bool includes_chain_index
);
......
......@@ -363,6 +363,10 @@ std::size_t olm::pickle_length(
length += olm::pickle_length(value.sender_chain);
length += olm::pickle_length(value.receiver_chains);
length += olm::pickle_length(value.skipped_message_keys);
// the logging_enabled branch includes a 'chain_index' field
length += olm::pickle_length(std::uint32_t(0));
return length;
}
......@@ -374,18 +378,30 @@ std::uint8_t * olm::pickle(
pos = pickle(pos, value.sender_chain);
pos = pickle(pos, value.receiver_chains);
pos = pickle(pos, value.skipped_message_keys);
// the logging_enabled branch includes a 'chain_index' field; for us, it is
// empty.
pos = pickle(pos, std::uint32_t(0));
return pos;
}
std::uint8_t const * olm::unpickle(
std::uint8_t const * pos, std::uint8_t const * end,
olm::Ratchet & value
olm::Ratchet & value,
bool includes_chain_index
) {
pos = unpickle(pos, end, value.root_key);
pos = unpickle(pos, end, value.sender_chain);
pos = unpickle(pos, end, value.receiver_chains);
pos = unpickle(pos, end, value.skipped_message_keys);
// pickle v2 includes a chain index; pickle v1 did not.
if (includes_chain_index) {
std::uint32_t dummy;
pos = unpickle(pos, end, dummy);
}
return pos;
}
......
......@@ -396,7 +396,7 @@ std::size_t olm::Session::decrypt(
}
namespace {
static const std::uint32_t SESSION_PICKLE_VERSION = 1;
static const std::uint32_t SESSION_PICKLE_VERSION = 2;
}
std::size_t olm::pickle_length(
......@@ -433,14 +433,26 @@ std::uint8_t const * olm::unpickle(
) {
uint32_t pickle_version;
pos = olm::unpickle(pos, end, pickle_version);
if (pickle_version != SESSION_PICKLE_VERSION) {
value.last_error = OlmErrorCode::OLM_UNKNOWN_PICKLE_VERSION;
return end;
bool includes_chain_index;
switch (pickle_version) {
case 1:
includes_chain_index = false;
break;
case 2:
includes_chain_index = true;
break;
default:
value.last_error = OlmErrorCode::OLM_UNKNOWN_PICKLE_VERSION;
return end;
}
pos = olm::unpickle(pos, end, value.received_message);
pos = olm::unpickle(pos, end, value.alice_identity_key);
pos = olm::unpickle(pos, end, value.alice_base_key);
pos = olm::unpickle(pos, end, value.bob_one_time_key);
pos = olm::unpickle(pos, end, value.ratchet);
pos = olm::unpickle(pos, end, value.ratchet, includes_chain_index);
return pos;
}
#include "olm/session.hh"
#include "olm/pickle_encoding.h"
#include "unittest.hh"
/* decode into a buffer, which is returned */
std::uint8_t *decode_hex(
const char * input
) {
static std::uint8_t buf[256];
std::uint8_t *p = buf;
while (*input != '\0') {
char high = *(input++);
char low = *(input++);
if (high >= 'a') high -= 'a' - ('9' + 1);
if (low >= 'a') low -= 'a' - ('9' + 1);
uint8_t value = ((high - '0') << 4) | (low - '0');
*p++ = value;
}
return buf;
}
void check_session(const olm::Session &session) {
assert_equals(
decode_hex("49d640dc96b80176694af69fc4b8ca9fac49aecbd697d01fd8bee1ed2693b6c9"),
session.ratchet.root_key, 32
);
assert_equals(
std::size_t(1),
session.ratchet.sender_chain.size()
);
assert_equals(
decode_hex("f77a03eaa9b301fa7d2a5aa6b50286906de12cc96044f526dbbcb12839ad7003"),
session.ratchet.sender_chain[0].ratchet_key.public_key, 32
);
assert_equals(
decode_hex("d945c6ed4c7c277117adf11fb133a7936d287afe97c0b3ac989644b4490d4f31"),
session.ratchet.sender_chain[0].ratchet_key.private_key, 32
);
assert_equals(
std::uint32_t(0),
session.ratchet.sender_chain[0].chain_key.index
);
assert_equals(
std::size_t(0),
session.ratchet.receiver_chains.size()
);
assert_equals(
std::size_t(0),
session.ratchet.skipped_message_keys.size()
);
assert_equals(OLM_SUCCESS, session.last_error);
assert_equals(false, session.received_message);
assert_equals(
decode_hex("7326b58623a3f7bd8da11a1bab51f432c02a7430241b326e9fc8916a21eb257e"),
session.alice_identity_key.public_key, 32
);
assert_equals(
decode_hex("0ab4b30bde20bd374ceccc72861660f0fd046f7516900796c3e5de41c598316c"),
session.alice_base_key.public_key, 32
);
assert_equals(
decode_hex("585dba930b10d90d81702c715f4085d07c42b0cd2d676010bb6086c86c4cc618"),
session.bob_one_time_key.public_key, 32
);
}
int main() {
{
TestCase test_case("V1 session pickle");
const uint8_t *PICKLE_KEY=(uint8_t *)"secret_key";
uint8_t pickled[] =
"wkEpwMgiAqD7B1/Lw2cKYYDcUZVOd9QHes7ZroWxr/Rp/nWEAySgRsIu/a54YhO67rwitr"
"Lpos7tFxxK9IZ7pKB1qrR1coVWIt78V9lp9WgmBAvxHBSY+tu1lkL/JjLi963/yFdPancZ"
"+WHMVfaKlV3gWGpo7EfNK6qAOxI1Ea/eCsE2sYrsHEDvLLGlKAA9E56rmmoe2w6TKzsQjs"
"ZM2/XT2eJ82EgMO9pL02iLElXWmGNv72Ut7DouR0pQIT50HIEEKcFxYcoTb3WCfJD76Coe"
"sE4kx+TA6d45Xu1bwQNNkTGF+nCCu/GmKY+sECXbz9U6WhxG0YdF9Z4T8YkWYAgpKNS0FW"
"RV";
size_t pickle_len = _olm_enc_input(
PICKLE_KEY, strlen((char *)PICKLE_KEY),
pickled, strlen((char *)pickled), NULL
);
olm::Session session;
const uint8_t *unpickle_res = olm::unpickle(pickled, pickled+sizeof(pickled), session);
assert_equals(
pickle_len, (size_t)(unpickle_res - pickled)
);
check_session(session);
#if 0
size_t rawlen = olm::pickle_length(session);
uint8_t *r1 = _olm_enc_output_pos(pickled, rawlen);
olm::pickle(r1, session);
_olm_enc_output(
PICKLE_KEY, strlen((char *)PICKLE_KEY),
pickled, rawlen);
printf("%s\n", pickled);
#endif
}
{
TestCase test_case("V2 session pickle");
const uint8_t *PICKLE_KEY=(uint8_t *)"secret_key";
uint8_t pickled[1024] =
"XTc0/aHUZIVjq257h6sCI1f4/EFJ42QYSOp6SDn88FSXRkO9dfrxGk8gPvZiNCnXFYWggX"
"UkTkaiSd9MFuj6kB49COlLU1zKw3caJmEIgud7umbYrAXhaBMCTl8T3XFVJK5gXThOE3sI"
"QCRy4RP4zAVJMTwnvNTzobi3N0aCxEDC+RIol6cEv+bV04zs8wbivdBDVJ7WIDVBF42dzQ"
"qPhL4KC5TLB9FYn/eUvrn56tHa5B3udjm1dbPynkjzkRy7Mbp5zUe6XhHDesKo0VxaHhOl"
"t117bSOKdf72wK/bStaWTpNdAA9h0AFuj2Rgp7E42yJTHY0tv23lMH1Hd+IHdsMsgMcfvL"
"Si";
size_t pickle_len = _olm_enc_input(
PICKLE_KEY, strlen((char *)PICKLE_KEY),
pickled, strlen((char *)pickled), NULL
);
olm::Session session;
const uint8_t *unpickle_res = olm::unpickle(pickled, pickled+sizeof(pickled), session);
assert_equals(
pickle_len, (size_t)(unpickle_res - pickled)
);
check_session(session);
}
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment