Version the pickled objects and check for errors when unpickling them
This commit is contained in:
parent
b6e248c9a5
commit
5ad929104e
4 changed files with 50 additions and 4 deletions
|
@ -27,6 +27,8 @@ enum struct ErrorCode {
|
||||||
BAD_MESSAGE_KEY_ID = 6, /*!< The message references an unknown key id */
|
BAD_MESSAGE_KEY_ID = 6, /*!< The message references an unknown key id */
|
||||||
INVALID_BASE64 = 7, /*!< The input base64 was invalid */
|
INVALID_BASE64 = 7, /*!< The input base64 was invalid */
|
||||||
BAD_ACCOUNT_KEY = 8, /*!< The supplied account key is invalid */
|
BAD_ACCOUNT_KEY = 8, /*!< The supplied account key is invalid */
|
||||||
|
UNKNOWN_PICKLE_VERSION = 9, /*!< The pickled object is too new */
|
||||||
|
CORRUPTED_PICKLE = 10, /*!< The pickled object couldn't be decoded */
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace olm
|
} // namespace olm
|
||||||
|
|
|
@ -360,11 +360,16 @@ static std::uint8_t const * unpickle(
|
||||||
|
|
||||||
} // namespace olm
|
} // namespace olm
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static const std::uint32_t ACCOUNT_PICKLE_VERSION = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::size_t olm::pickle_length(
|
std::size_t olm::pickle_length(
|
||||||
olm::Account const & value
|
olm::Account const & value
|
||||||
) {
|
) {
|
||||||
std::size_t length = 0;
|
std::size_t length = 0;
|
||||||
|
length += olm::pickle_length(ACCOUNT_PICKLE_VERSION);
|
||||||
length += olm::pickle_length(value.identity_keys);
|
length += olm::pickle_length(value.identity_keys);
|
||||||
length += olm::pickle_length(value.one_time_keys);
|
length += olm::pickle_length(value.one_time_keys);
|
||||||
length += olm::pickle_length(value.next_one_time_key_id);
|
length += olm::pickle_length(value.next_one_time_key_id);
|
||||||
|
@ -376,6 +381,7 @@ std::uint8_t * olm::pickle(
|
||||||
std::uint8_t * pos,
|
std::uint8_t * pos,
|
||||||
olm::Account const & value
|
olm::Account const & value
|
||||||
) {
|
) {
|
||||||
|
pos = olm::pickle(pos, ACCOUNT_PICKLE_VERSION);
|
||||||
pos = olm::pickle(pos, value.identity_keys);
|
pos = olm::pickle(pos, value.identity_keys);
|
||||||
pos = olm::pickle(pos, value.one_time_keys);
|
pos = olm::pickle(pos, value.one_time_keys);
|
||||||
pos = olm::pickle(pos, value.next_one_time_key_id);
|
pos = olm::pickle(pos, value.next_one_time_key_id);
|
||||||
|
@ -387,6 +393,12 @@ std::uint8_t const * olm::unpickle(
|
||||||
std::uint8_t const * pos, std::uint8_t const * end,
|
std::uint8_t const * pos, std::uint8_t const * end,
|
||||||
olm::Account & value
|
olm::Account & value
|
||||||
) {
|
) {
|
||||||
|
uint32_t pickle_version;
|
||||||
|
pos = olm::unpickle(pos, end, pickle_version);
|
||||||
|
if (pickle_version != ACCOUNT_PICKLE_VERSION) {
|
||||||
|
value.last_error = olm::ErrorCode::UNKNOWN_PICKLE_VERSION;
|
||||||
|
return end;
|
||||||
|
}
|
||||||
pos = olm::unpickle(pos, end, value.identity_keys);
|
pos = olm::unpickle(pos, end, value.identity_keys);
|
||||||
pos = olm::unpickle(pos, end, value.one_time_keys);
|
pos = olm::unpickle(pos, end, value.one_time_keys);
|
||||||
pos = olm::unpickle(pos, end, value.next_one_time_key_id);
|
pos = olm::unpickle(pos, end, value.next_one_time_key_id);
|
||||||
|
|
29
src/olm.cpp
29
src/olm.cpp
|
@ -151,7 +151,7 @@ std::size_t b64_input(
|
||||||
return raw_length;
|
return raw_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * errors[9] {
|
const char * errors[11] {
|
||||||
"SUCCESS",
|
"SUCCESS",
|
||||||
"NOT_ENOUGH_RANDOM",
|
"NOT_ENOUGH_RANDOM",
|
||||||
"OUTPUT_BUFFER_TOO_SMALL",
|
"OUTPUT_BUFFER_TOO_SMALL",
|
||||||
|
@ -161,6 +161,8 @@ const char * errors[9] {
|
||||||
"BAD_MESSAGE_KEY_ID",
|
"BAD_MESSAGE_KEY_ID",
|
||||||
"INVALID_BASE64",
|
"INVALID_BASE64",
|
||||||
"BAD_ACCOUNT_KEY",
|
"BAD_ACCOUNT_KEY",
|
||||||
|
"UNKNOWN_PICKLE_VERSION",
|
||||||
|
"CORRUPTED_PICKLE",
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -282,7 +284,16 @@ size_t olm_unpickle_account(
|
||||||
return std::size_t(-1);
|
return std::size_t(-1);
|
||||||
}
|
}
|
||||||
std::uint8_t * const end = pos + raw_length;
|
std::uint8_t * const end = pos + raw_length;
|
||||||
unpickle(pos, end, object);
|
/* On success unpickle will return (pos + raw_length). If unpickling
|
||||||
|
* terminates too soon then it will return a pointer before
|
||||||
|
* (pos + raw_length). On error unpickle will return (pos + raw_length + 1).
|
||||||
|
*/
|
||||||
|
if (end != unpickle(pos, end + 1, object)) {
|
||||||
|
if (object.last_error == olm::ErrorCode::SUCCESS) {
|
||||||
|
object.last_error = olm::ErrorCode::CORRUPTED_PICKLE;
|
||||||
|
}
|
||||||
|
return std::size_t(-1);
|
||||||
|
}
|
||||||
return pickled_length;
|
return pickled_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,8 +311,18 @@ size_t olm_unpickle_session(
|
||||||
if (raw_length == std::size_t(-1)) {
|
if (raw_length == std::size_t(-1)) {
|
||||||
return std::size_t(-1);
|
return std::size_t(-1);
|
||||||
}
|
}
|
||||||
std::uint8_t * const end = pos + raw_length;
|
|
||||||
unpickle(pos, end, object);
|
std::uint8_t * const end = pos + raw_length + 1;
|
||||||
|
/* On success unpickle will return (pos + raw_length). If unpickling
|
||||||
|
* terminates too soon then it will return a pointer before
|
||||||
|
* (pos + raw_length). On error unpickle will return (pos + raw_length + 1).
|
||||||
|
*/
|
||||||
|
if (end != unpickle(pos, end + 1, object)) {
|
||||||
|
if (object.last_error == olm::ErrorCode::SUCCESS) {
|
||||||
|
object.last_error = olm::ErrorCode::CORRUPTED_PICKLE;
|
||||||
|
}
|
||||||
|
return std::size_t(-1);
|
||||||
|
}
|
||||||
return pickled_length;
|
return pickled_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -353,11 +353,15 @@ std::size_t olm::Session::decrypt(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static const std::uint32_t SESSION_PICKLE_VERSION = 1;
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t olm::pickle_length(
|
std::size_t olm::pickle_length(
|
||||||
Session const & value
|
Session const & value
|
||||||
) {
|
) {
|
||||||
std::size_t length = 0;
|
std::size_t length = 0;
|
||||||
|
length += olm::pickle_length(SESSION_PICKLE_VERSION);
|
||||||
length += olm::pickle_length(value.received_message);
|
length += olm::pickle_length(value.received_message);
|
||||||
length += olm::pickle_length(value.alice_identity_key);
|
length += olm::pickle_length(value.alice_identity_key);
|
||||||
length += olm::pickle_length(value.alice_base_key);
|
length += olm::pickle_length(value.alice_base_key);
|
||||||
|
@ -371,6 +375,7 @@ std::uint8_t * olm::pickle(
|
||||||
std::uint8_t * pos,
|
std::uint8_t * pos,
|
||||||
Session const & value
|
Session const & value
|
||||||
) {
|
) {
|
||||||
|
pos = olm::pickle(pos, SESSION_PICKLE_VERSION);
|
||||||
pos = olm::pickle(pos, value.received_message);
|
pos = olm::pickle(pos, value.received_message);
|
||||||
pos = olm::pickle(pos, value.alice_identity_key);
|
pos = olm::pickle(pos, value.alice_identity_key);
|
||||||
pos = olm::pickle(pos, value.alice_base_key);
|
pos = olm::pickle(pos, value.alice_base_key);
|
||||||
|
@ -384,6 +389,12 @@ std::uint8_t const * olm::unpickle(
|
||||||
std::uint8_t const * pos, std::uint8_t const * end,
|
std::uint8_t const * pos, std::uint8_t const * end,
|
||||||
Session & value
|
Session & value
|
||||||
) {
|
) {
|
||||||
|
uint32_t pickle_version;
|
||||||
|
pos = olm::unpickle(pos, end, pickle_version);
|
||||||
|
if (pickle_version != SESSION_PICKLE_VERSION) {
|
||||||
|
value.last_error = olm::ErrorCode::UNKNOWN_PICKLE_VERSION;
|
||||||
|
return end;
|
||||||
|
}
|
||||||
pos = olm::unpickle(pos, end, value.received_message);
|
pos = olm::unpickle(pos, end, value.received_message);
|
||||||
pos = olm::unpickle(pos, end, value.alice_identity_key);
|
pos = olm::unpickle(pos, end, value.alice_identity_key);
|
||||||
pos = olm::unpickle(pos, end, value.alice_base_key);
|
pos = olm::unpickle(pos, end, value.alice_base_key);
|
||||||
|
|
Loading…
Reference in a new issue