aboutsummaryrefslogtreecommitdiff
path: root/include/olm
diff options
context:
space:
mode:
Diffstat (limited to 'include/olm')
-rw-r--r--include/olm/account.hh84
-rw-r--r--include/olm/base64.hh49
-rw-r--r--include/olm/cipher.hh128
-rw-r--r--include/olm/crypto.hh148
-rw-r--r--include/olm/error.hh34
-rw-r--r--include/olm/list.hh119
-rw-r--r--include/olm/memory.hh38
-rw-r--r--include/olm/message.hh126
-rw-r--r--include/olm/olm.hh295
-rw-r--r--include/olm/pickle.hh178
-rw-r--r--include/olm/ratchet.hh177
-rw-r--r--include/olm/session.hh114
12 files changed, 1490 insertions, 0 deletions
diff --git a/include/olm/account.hh b/include/olm/account.hh
new file mode 100644
index 0000000..8094a25
--- /dev/null
+++ b/include/olm/account.hh
@@ -0,0 +1,84 @@
+/* Copyright 2015 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef OLM_ACCOUNT_HH_
+#define OLM_ACCOUNT_HH_
+
+#include "olm/list.hh"
+#include "olm/crypto.hh"
+#include "olm/error.hh"
+
+#include <cstdint>
+
+namespace olm {
+
+
+struct LocalKey {
+ std::uint32_t id;
+ Curve25519KeyPair key;
+};
+
+
+struct SignedKey : LocalKey {
+ std::uint8_t signature[64];
+};
+
+
+static std::size_t const MAX_ONE_TIME_KEYS = 100;
+
+struct Account {
+ LocalKey identity_key;
+ LocalKey last_resort_one_time_key;
+ List<LocalKey, MAX_ONE_TIME_KEYS> one_time_keys;
+ ErrorCode last_error;
+
+ /** Number of random bytes needed to create a new account */
+ std::size_t new_account_random_length();
+
+ /** Create a new account. Returns NOT_ENOUGH_RANDOM if the number of random
+ * bytes is too small. */
+ std::size_t new_account(
+ uint8_t const * random, std::size_t random_length
+ );
+
+ LocalKey const * lookup_key(
+ std::uint32_t id
+ );
+
+ std::size_t remove_key(
+ std::uint32_t id
+ );
+};
+
+
+std::size_t pickle_length(
+ Account const & value
+);
+
+
+std::uint8_t * pickle(
+ std::uint8_t * pos,
+ Account const & value
+);
+
+
+std::uint8_t const * unpickle(
+ std::uint8_t const * pos, std::uint8_t const * end,
+ Account & value
+);
+
+
+} // namespace olm
+
+#endif /* OLM_ACCOUNT_HH_ */
diff --git a/include/olm/base64.hh b/include/olm/base64.hh
new file mode 100644
index 0000000..0a7435b
--- /dev/null
+++ b/include/olm/base64.hh
@@ -0,0 +1,49 @@
+/* Copyright 2015 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef AXOLOLT_BASE64_HH_
+#define AXOLOLT_BASE64_HH_
+
+#include <cstddef>
+#include <cstdint>
+
+namespace olm {
+
+
+std::size_t encode_base64_length(
+ std::size_t input_length
+);
+
+
+void encode_base64(
+ std::uint8_t const * input, std::size_t input_length,
+ std::uint8_t * output
+);
+
+
+std::size_t decode_base64_length(
+ std::size_t input_length
+);
+
+
+void decode_base64(
+ std::uint8_t const * input, std::size_t input_length,
+ std::uint8_t * output
+);
+
+
+} // namespace olm
+
+
+#endif /* AXOLOLT_BASE64_HH_ */
diff --git a/include/olm/cipher.hh b/include/olm/cipher.hh
new file mode 100644
index 0000000..f71b3af
--- /dev/null
+++ b/include/olm/cipher.hh
@@ -0,0 +1,128 @@
+/* Copyright 2015 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OLM_CIPHER_HH_
+#define OLM_CIPHER_HH_
+
+#include <cstdint>
+#include <cstddef>
+
+namespace olm {
+
+class Cipher {
+public:
+ virtual ~Cipher();
+
+ /**
+ * Returns the length of the message authentication code that will be
+ * appended to the output.
+ */
+ virtual std::size_t mac_length() const = 0;
+
+ /**
+ * Returns the length of cipher-text for a given length of plain-text.
+ */
+ virtual std::size_t encrypt_ciphertext_length(
+ std::size_t plaintext_length
+ ) const = 0;
+
+ /*
+ * Encrypts the plain-text into the output buffer and authenticates the
+ * contents of the output buffer covering both cipher-text and any other
+ * associated data in the output buffer.
+ *
+ * |---------------------------------------output_length-->|
+ * output |--ciphertext_length-->| |---mac_length-->|
+ * ciphertext
+ *
+ * Returns std::size_t(-1) if the length of the cipher-text or the output
+ * buffer is too small. Otherwise returns the length of the output buffer.
+ */
+ virtual std::size_t encrypt(
+ std::uint8_t const * key, std::size_t key_length,
+ std::uint8_t const * plaintext, std::size_t plaintext_length,
+ std::uint8_t * ciphertext, std::size_t ciphertext_length,
+ std::uint8_t * output, std::size_t output_length
+ ) const = 0;
+
+ /**
+ * Returns the maximum length of plain-text that a given length of
+ * cipher-text can contain.
+ */
+ virtual std::size_t decrypt_max_plaintext_length(
+ std::size_t ciphertext_length
+ ) const = 0;
+
+ /**
+ * Authenticates the input and decrypts the cipher-text into the plain-text
+ * buffer.
+ *
+ * |----------------------------------------input_length-->|
+ * input |--ciphertext_length-->| |---mac_length-->|
+ * ciphertext
+ *
+ * Returns std::size_t(-1) if the length of the plain-text buffer is too
+ * small or if the authentication check fails. Otherwise returns the length
+ * of the plain text.
+ */
+ virtual std::size_t decrypt(
+ std::uint8_t const * key, std::size_t key_length,
+ std::uint8_t const * input, std::size_t input_length,
+ std::uint8_t const * ciphertext, std::size_t ciphertext_length,
+ std::uint8_t * plaintext, std::size_t max_plaintext_length
+ ) const = 0;
+};
+
+
+class CipherAesSha256 : public Cipher {
+public:
+ CipherAesSha256(
+ std::uint8_t const * kdf_info, std::size_t kdf_info_length
+ );
+
+ virtual std::size_t mac_length() const;
+
+ virtual std::size_t encrypt_ciphertext_length(
+ std::size_t plaintext_length
+ ) const;
+
+ virtual std::size_t encrypt(
+ std::uint8_t const * key, std::size_t key_length,
+ std::uint8_t const * plaintext, std::size_t plaintext_length,
+ std::uint8_t * ciphertext, std::size_t ciphertext_length,
+ std::uint8_t * output, std::size_t output_length
+ ) const;
+
+ virtual std::size_t decrypt_max_plaintext_length(
+ std::size_t ciphertext_length
+ ) const;
+
+ virtual std::size_t decrypt(
+ std::uint8_t const * key, std::size_t key_length,
+ std::uint8_t const * input, std::size_t input_length,
+ std::uint8_t const * ciphertext, std::size_t ciphertext_length,
+ std::uint8_t * plaintext, std::size_t max_plaintext_length
+ ) const;
+
+private:
+ std::uint8_t const * kdf_info;
+ std::size_t kdf_info_length;
+};
+
+
+} // namespace
+
+
+#endif /* OLM_CIPHER_HH_ */
diff --git a/include/olm/crypto.hh b/include/olm/crypto.hh
new file mode 100644
index 0000000..b299e12
--- /dev/null
+++ b/include/olm/crypto.hh
@@ -0,0 +1,148 @@
+/* Copyright 2015 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef OLM_CRYPTO_HH_
+#define OLM_CRYPTO_HH_
+
+#include <cstdint>
+#include <cstddef>
+
+namespace olm {
+
+
+struct Curve25519PublicKey {
+ static const int LENGTH = 32;
+ std::uint8_t public_key[32];
+};
+
+
+struct Curve25519KeyPair : public Curve25519PublicKey {
+ static const int LENGTH = 64;
+ std::uint8_t private_key[32];
+};
+
+
+/** Generate a curve25519 key pair from 32 random bytes. */
+void generate_key(
+ std::uint8_t const * random_32_bytes,
+ Curve25519KeyPair & key_pair
+);
+
+
+const std::size_t CURVE25519_SHARED_SECRET_LENGTH = 32;
+
+
+/** Create a shared secret using our private key and their public key.
+ * The output buffer must be at least 32 bytes long. */
+void curve25519_shared_secret(
+ Curve25519KeyPair const & our_key,
+ Curve25519PublicKey const & their_key,
+ std::uint8_t * output
+);
+
+
+/** Signs the message using our private key.
+ * The output buffer must be at least 64 bytes long. */
+void curve25519_sign(
+ Curve25519KeyPair const & our_key,
+ std::uint8_t const * message, std::size_t message_length,
+ std::uint8_t * output
+);
+
+
+/** Verify thei message using their public key.
+ * The signature input buffer must be 64 bytes long.
+ * Returns true if the signature is valid. */
+bool curve25519_verify(
+ Curve25519PublicKey const & their_key,
+ std::uint8_t const * message, std::size_t message_length,
+ std::uint8_t const * signature
+);
+
+
+struct Aes256Key {
+ static const int LENGTH = 32;
+ std::uint8_t key[32];
+};
+
+
+struct Aes256Iv {
+ static const int LENGTH = 16;
+ std::uint8_t iv[16];
+};
+
+
+/** The length of output the aes_encrypt_cbc function will write */
+std::size_t aes_encrypt_cbc_length(
+ std::size_t input_length
+);
+
+
+/** Encrypts the input using AES256 in CBC mode with PKCS#7 padding.
+ * The output buffer must be big enough to hold the output including padding */
+void aes_encrypt_cbc(
+ Aes256Key const & key,
+ Aes256Iv const & iv,
+ std::uint8_t const * input, std::size_t input_length,
+ std::uint8_t * output
+);
+
+
+/** Decrypts the input using AES256 in CBC mode. The output buffer must be at
+ * least the same size as the input buffer. Returns the length of the plaintext
+ * without padding on success or std::size_t(-1) if the padding is invalid.
+ */
+std::size_t aes_decrypt_cbc(
+ Aes256Key const & key,
+ Aes256Iv const & iv,
+ std::uint8_t const * input, std::size_t input_length,
+ std::uint8_t * output
+);
+
+
+/** Computes SHA-256 of the input. The output buffer must be a least 32
+ * bytes long. */
+void sha256(
+ std::uint8_t const * input, std::size_t input_length,
+ std::uint8_t * output
+);
+
+
+const std::size_t HMAC_SHA256_OUTPUT_LENGTH = 32;
+
+
+/** HMAC: Keyed-Hashing for Message Authentication
+ * http://tools.ietf.org/html/rfc2104
+ * Computes HMAC-SHA-256 of the input for the key. The output buffer must
+ * be at least 32 bytes long. */
+void hmac_sha256(
+ std::uint8_t const * key, std::size_t key_length,
+ std::uint8_t const * input, std::size_t input_length,
+ std::uint8_t * output
+);
+
+
+/** HMAC-based Key Derivation Function (HKDF)
+ * https://tools.ietf.org/html/rfc5869
+ * Derives key material from the input bytes. */
+void hkdf_sha256(
+ std::uint8_t const * input, std::size_t input_length,
+ std::uint8_t const * info, std::size_t info_length,
+ std::uint8_t const * salt, std::size_t salt_length,
+ std::uint8_t * output, std::size_t output_length
+);
+
+} // namespace olm
+
+#endif /* OLM_CRYPTO_HH_ */
diff --git a/include/olm/error.hh b/include/olm/error.hh
new file mode 100644
index 0000000..960de72
--- /dev/null
+++ b/include/olm/error.hh
@@ -0,0 +1,34 @@
+/* Copyright 2015 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ERROR_HH_
+#define ERROR_HH_
+
+namespace olm {
+
+enum struct ErrorCode {
+ SUCCESS = 0, /*!< There wasn't an error */
+ NOT_ENOUGH_RANDOM = 1, /*!< Not enough entropy was supplied */
+ OUTPUT_BUFFER_TOO_SMALL = 2, /*!< Supplied output buffer is too small */
+ BAD_MESSAGE_VERSION = 3, /*!< The message version is unsupported */
+ BAD_MESSAGE_FORMAT = 4, /*!< The message couldn't be decoded */
+ BAD_MESSAGE_MAC = 5, /*!< The message couldn't be decrypted */
+ BAD_MESSAGE_KEY_ID = 6, /*!< The message references an unknown key id */
+ INVALID_BASE64 = 7, /*!< The input base64 was invalid */
+ BAD_ACCOUNT_KEY = 8, /*!< The supplied account key is invalid */
+};
+
+} // namespace olm
+
+#endif /* ERROR_HH_ */
diff --git a/include/olm/list.hh b/include/olm/list.hh
new file mode 100644
index 0000000..e4bf951
--- /dev/null
+++ b/include/olm/list.hh
@@ -0,0 +1,119 @@
+/* Copyright 2015 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef OLM_LIST_HH_
+#define OLM_LIST_HH_
+
+#include <cstddef>
+
+namespace olm {
+
+template<typename T, std::size_t max_size>
+class List {
+public:
+ List() : _end(_data) {}
+
+ typedef T * iterator;
+ typedef T const * const_iterator;
+
+ T * begin() { return _data; }
+ T * end() { return _end; }
+ T const * begin() const { return _data; }
+ T const * end() const { return _end; }
+
+ /**
+ * Is the list empty?
+ */
+ bool empty() const { return _end == _data; }
+
+ /**
+ * The number of items in the list.
+ */
+ std::size_t size() const { return _end - _data; }
+
+ T & operator[](std::size_t index) { return _data[index]; }
+
+ T const & operator[](std::size_t index) const { return _data[index]; }
+
+ /**
+ * Erase the item from the list at the given position.
+ */
+ void erase(T * pos) {
+ --_end;
+ while (pos != _end) {
+ *pos = *(pos + 1);
+ ++pos;
+ }
+ }
+
+ /**
+ * Make space for an item in the list at a given position.
+ * If inserting the item makes the list longer than max_size then
+ * the end of the list is discarded.
+ * Returns the where the item is inserted.
+ */
+ T * insert(T * pos) {
+ if (_end != _data + max_size) {
+ ++_end;
+ } else if (pos == _end) {
+ --pos;
+ }
+ T * tmp = pos;
+ while (tmp != _end - 1) {
+ *(tmp + 1) = *tmp;
+ ++tmp;
+ }
+ return pos;
+ }
+
+ /**
+ * Make space for an item in the list at the start of the list
+ */
+ T * insert() { return insert(begin()); }
+
+ /**
+ * Insert an item into the list at a given position.
+ * If inserting the item makes the list longer than max_size then
+ * the end of the list is discarded.
+ * Returns the where the item is inserted.
+ */
+ T * insert(T * pos, T const & value) {
+ pos = insert(pos);
+ *pos = value;
+ return pos;
+ }
+
+ List<T, max_size> & operator=(List<T, max_size> const & other) {
+ if (this == &other) {
+ return *this;
+ }
+ T * this_pos = _data;
+ T * const other_pos = other._data;
+ while (other_pos != other._end) {
+ *this_pos = *other;
+ ++this_pos;
+ ++other_pos;
+ }
+ _end = this_pos;
+ return *this;
+ }
+
+private:
+ T * _end;
+ T _data[max_size];
+};
+
+} // namespace olm
+
+#endif /* OLM_LIST_HH_ */
diff --git a/include/olm/memory.hh b/include/olm/memory.hh
new file mode 100644
index 0000000..b19c74b
--- /dev/null
+++ b/include/olm/memory.hh
@@ -0,0 +1,38 @@
+/* Copyright 2015 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <cstddef>
+#include <cstdint>
+
+namespace olm {
+
+/** Clear the memory held in the buffer */
+void unset(
+ void volatile * buffer, std::size_t buffer_length
+);
+
+/** Clear the memory backing an object */
+template<typename T>
+void unset(T & value) {
+ unset(reinterpret_cast<void volatile *>(&value), sizeof(T));
+}
+
+/** Check if two buffers are equal in constant time. */
+bool is_equal(
+ std::uint8_t const * buffer_a,
+ std::uint8_t const * buffer_b,
+ std::size_t length
+);
+
+} // namespace olm
diff --git a/include/olm/message.hh b/include/olm/message.hh
new file mode 100644
index 0000000..fefdd20
--- /dev/null
+++ b/include/olm/message.hh
@@ -0,0 +1,126 @@
+/* Copyright 2015 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <cstddef>
+#include <cstdint>
+
+
+namespace olm {
+
+/**
+ * The length of the buffer needed to hold a message.
+ */
+std::size_t encode_message_length(
+ std::uint32_t counter,
+ std::size_t ratchet_key_length,
+ std::size_t ciphertext_length,
+ std::size_t mac_length
+);
+
+
+struct MessageWriter {
+ std::uint8_t * ratchet_key;
+ std::uint8_t * ciphertext;
+};
+
+
+struct MessageReader {
+ std::uint8_t version;
+ bool has_counter;
+ std::uint32_t counter;
+ std::uint8_t const * input; std::size_t input_length;
+ std::uint8_t const * ratchet_key; std::size_t ratchet_key_length;
+ std::uint8_t const * ciphertext; std::size_t ciphertext_length;
+};
+
+
+/**
+ * Writes the message headers into the output buffer.
+ * Populates the writer struct with pointers into the output buffer.
+ */
+void encode_message(
+ MessageWriter & writer,
+ std::uint8_t version,
+ std::uint32_t counter,
+ std::size_t ratchet_key_length,
+ std::size_t ciphertext_length,
+ std::uint8_t * output
+);
+
+
+/**
+ * Reads the message headers from the input buffer.
+ * Populates the reader struct with pointers into the input buffer.
+ */
+void decode_message(
+ MessageReader & reader,
+ std::uint8_t const * input, std::size_t input_length,
+ std::size_t mac_length
+);
+
+
+struct PreKeyMessageWriter {
+ std::uint8_t * identity_key;
+ std::uint8_t * base_key;
+ std::uint8_t * message;
+};
+
+
+struct PreKeyMessageReader {
+ std::uint8_t version;
+ bool has_one_time_key_id;
+ std::uint32_t one_time_key_id;
+ std::uint8_t const * identity_key; std::size_t identity_key_length;
+ std::uint8_t const * base_key; std::size_t base_key_length;
+ std::uint8_t const * message; std::size_t message_length;
+};
+
+
+/**
+ * The length of the buffer needed to hold a message.
+ */
+std::size_t encode_one_time_key_message_length(
+ std::uint32_t one_time_key_id,
+ std::size_t identity_key_length,
+ std::size_t base_key_length,
+ std::size_t message_length
+);
+
+
+/**
+ * Writes the message headers into the output buffer.
+ * Populates the writer struct with pointers into the output buffer.
+ */
+void encode_one_time_key_message(
+ PreKeyMessageWriter & writer,
+ std::uint8_t version,
+ std::uint32_t one_time_key_id,
+ std::size_t identity_key_length,
+ std::size_t base_key_length,
+ std::size_t message_length,
+ std::uint8_t * output
+);
+
+
+/**
+ * Reads the message headers from the input buffer.
+ * Populates the reader struct with pointers into the input buffer.
+ */
+void decode_one_time_key_message(
+ PreKeyMessageReader & reader,
+ std::uint8_t const * input, std::size_t input_length
+);
+
+
+} // namespace olm
diff --git a/include/olm/olm.hh b/include/olm/olm.hh
new file mode 100644
index 0000000..fca35c4
--- /dev/null
+++ b/include/olm/olm.hh
@@ -0,0 +1,295 @@
+/* Copyright 2015 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef OLM_HH_
+#define OLM_HH_
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static const size_t OLM_MESSAGE_TYPE_PRE_KEY = 0;
+static const size_t OLM_MESSAGE_TYPE_MESSAGE = 1;
+
+struct OlmAccount;
+struct OlmSession;
+
+/** The size of an account object in bytes */
+size_t olm_account_size();
+
+/** The size of a session object in bytes */
+size_t olm_session_size();
+
+/** Initialise an account object using the supplied memory
+ * The supplied memory must be at least olm_account_size() bytes */
+OlmAccount * olm_account(
+ void * memory
+);
+
+/** Initialise a session object using the supplied memory
+ * The supplied memory must be at least olm_session_size() bytes */
+OlmSession * olm_session(
+ void * memory
+);
+
+/** The value that olm will return from a function if there was an error */
+size_t olm_error();
+
+/** A null terminated string describing the most recent error to happen to an
+ * account */
+const char * olm_account_last_error(
+ OlmSession * account
+);
+
+/** A null terminated string describing the most recent error to happen to a
+ * session */
+const char * olm_session_last_error(
+ OlmSession * session
+);
+
+/** Returns the number of bytes needed to store an account */
+size_t olm_pickle_account_length(
+ OlmAccount * account
+);
+
+/** Returns the number of bytes needed to store a session */
+size_t olm_pickle_session_length(
+ OlmSession * session
+);
+
+/** Stores an account as a base64 string. Encrypts the account using the
+ * supplied key. Returns the length of the pickled account on success.
+ * Returns olm_error() on failure. If the pickle output buffer
+ * is smaller than olm_pickle_account_length() then
+ * olm_account_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */
+size_t olm_pickle_account(
+ OlmAccount * account,
+ void const * key, size_t key_length,
+ void * pickled, size_t pickled_length
+);
+
+/** Stores a session as a base64 string. Encrypts the session using the
+ * supplied key. Returns the length of the pickled session on success.
+ * Returns olm_error() on failure. If the pickle output buffer
+ * is smaller than olm_pickle_session_length() then
+ * olm_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */
+size_t olm_pickle_session(
+ OlmSession * session,
+ void const * key, size_t key_length,
+ void * pickled, size_t pickled_length
+);
+
+/** Loads an account from a pickled base64 string. Decrypts the account using
+ * the supplied key. Returns olm_error() on failure. If the key doesn't
+ * match the one used to encrypt the account then olm_account_last_error()
+ * will be "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then
+ * olm_account_last_error() will be "INVALID_BASE64". The input pickled
+ * buffer is destroyed */
+size_t olm_unpickle_account(
+ OlmAccount * account,
+ void const * key, size_t key_length,
+ void * pickled, size_t pickled_length
+);
+
+/** Loads a session from a pickled base64 string. Decrypts the session using
+ * the supplied key. Returns olm_error() on failure. If the key doesn't
+ * match the one used to encrypt the account then olm_session_last_error()
+ * will be "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then
+ * olm_session_last_error() will be "INVALID_BASE64". The input pickled
+ * buffer is destroyed */
+size_t olm_unpickle_session(
+ OlmSession * session,
+ void const * key, size_t key_length,
+ void * pickled, size_t pickled_length
+);
+
+/** The number of random bytes needed to create an account.*/
+size_t olm_create_account_random_length(
+ OlmAccount * account
+);
+
+/** Creates a new account. Returns olm_error() on failure. If weren't
+ * enough random bytes then olm_account_last_error() will be
+ * "NOT_ENOUGH_RANDOM" */
+size_t olm_create_account(
+ OlmAccount * account,
+ void const * random, size_t random_length
+);
+
+/** The size of the output buffer needed to hold the identity keys */
+size_t olm_account_identity_keys_length(
+ OlmAccount * account
+);
+
+/** Writes the public parts of the identity keys for the account into the
+ * identity_keys output buffer. The output is formatted as though it was
+ * created with sprintf(output, "[[%10d,\"%43s\"]\n]", key_id, key_base64).
+ * The output can either be parsed as fixed width using the above format or by
+ * a JSON parser. Returns olm_error() on failure. If the identity_keys
+ * buffer was too small then olm_account_last_error() will be
+ * "OUTPUT_BUFFER_TOO_SMALL". */
+size_t olm_account_identity_keys(
+ OlmAccount * account,
+ void * identity_keys, size_t identity_key_length
+);
+
+/** The size of the output buffer needed to hold the one time keys */
+size_t olm_account_one_time_keys_length(
+ OlmAccount * account
+);
+
+/** Writes the public parts of the one time keys for the account into the
+ * one_time_keys output buffer. The first key will be formatted as though it was
+ * created with sprintf(output, "[[%10d,\"%43s\"]\n", key_id, key_base64).
+ * subsequent keys are formatted with ",[%10d,\"%43s\"]\n". The final byte of
+ * output will be "]". The output can either be parsed as fixed width using
+ * the above format or by a JSON parser. Returns olm_error() on failure.
+ * If the one_time_keys buffer was too small then olm_account_last_error()
+ * will be "OUTPUT_BUFFER_TOO_SMALL". */
+size_t olm_account_one_time_keys(
+ OlmAccount * account,
+ void * one_time_keys, size_t one_time_keys_length
+);
+
+/* TODO: Add methods for marking keys as used, generating new keys, and
+ * tracking which keys have been uploaded to the central servers */
+
+/** The number of random bytes needed to create an outbound session */
+size_t olm_create_outbound_session_random_length(
+ OlmSession * session
+);
+
+/** Creates a new out-bound session for sending messages to a given identity_key
+ * and one_time_key. Returns olm_error() on failure. If the keys couldn't be
+ * decoded as base64 then olm_session_last_error() will be "INVALID_BASE64"
+ * If there weren't enough random bytes then olm_session_last_error() will
+ * be "NOT_ENOUGH_RANDOM". */
+size_t olm_create_outbound_session(
+ OlmSession * session,
+ OlmAccount * account,
+ void const * their_identity_key, size_t their_identity_key_length,
+ unsigned their_one_time_key_id,
+ void const * their_one_time_key, size_t their_one_time_key_length,
+ void const * random, size_t random_length
+);
+
+/** Create a new in-bound session for sending/receiving messages from an
+ * incoming PRE_KEY message. Returns olm_error() on failure. If the base64
+ * couldn't be decoded then olm_session_last_error will be "INVALID_BASE64".
+ * If the message was for an unsupported protocol version then
+ * olm_session_last_error() will be "BAD_MESSAGE_VERSION". If the message
+ * couldn't be decoded then then olm_session_last_error() will be
+ * "BAD_MESSAGE_FORMAT". If the message refers to an unknown one time
+ * key then olm_session_last_error() will be "BAD_MESSAGE_KEY_ID". */
+size_t olm_create_inbound_session(
+ OlmSession * session,
+ OlmAccount * account,
+ void * one_time_key_message, size_t message_length
+);
+
+/** Checks if the PRE_KEY message is for this in-bound session. This can happen
+ * if multiple messages are sent to this account before this account sends a
+ * message in reply. Returns olm_error() on failure. If the base64
+ * couldn't be decoded then olm_session_last_error will be "INVALID_BASE64".
+ * If the message was for an unsupported protocol version then
+ * olm_session_last_error() will be "BAD_MESSAGE_VERSION". If the message
+ * couldn't be decoded then then olm_session_last_error() will be
+ * "BAD_MESSAGE_FORMAT". */
+size_t olm_matches_inbound_session(
+ OlmSession * session,
+ void * one_time_key_message, size_t message_length
+);
+
+/** Removes the one time keys that the session used from the account. Returns
+ * olm_error() on failure. If the account doesn't have any matching one time
+ * keys then olm_account_last_error() will be "BAD_MESSAGE_KEY_ID". */
+size_t olm_remove_one_time_keys(
+ OlmAccount * account,
+ OlmSession * session
+);
+
+/** The type of the next message that olm_encrypt() will return. Returns
+ * OLM_MESSAGE_TYPE_PRE_KEY if the message will be a PRE_KEY message.
+ * Returns OLM_MESSAGE_TYPE_MESSAGE if the message will be a normal message.
+ * Returns olm_error on failure. */
+size_t olm_encrypt_message_type(
+ OlmSession * session
+);
+
+/** The number of random bytes needed to encrypt the next message. */
+size_t olm_encrypt_random_length(
+ OlmSession * session
+);
+
+/** The size of the next message in bytes for the given number of plain-text
+ * bytes. */
+size_t olm_encrypt_message_length(
+ OlmSession * session,
+ size_t plaintext_length
+);
+
+/** Encrypts a message using the session. Returns the length of the message in
+ * bytes on success. Writes the message as base64 into the message buffer.
+ * Returns olm_error() on failure. If the message buffer is too small then
+ * olm_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL". If there
+ * weren't enough random bytes then olm_session_last_error() will be
+ * "NOT_ENOUGH_RANDOM". */
+size_t olm_encrypt(
+ OlmSession * session,
+ void const * plaintext, size_t plaintext_length,
+ void const * random, size_t random_length,
+ void * message, size_t message_length
+);
+
+/** The maximum number of bytes of plain-text a given message could decode to.
+ * The actual size could be different due to padding. The input message buffer
+ * is destroyed. Returns olm_error() on failure. If the message base64
+ * couldn't be decoded then olm_session_last_error() will be
+ * "INVALID_BASE64". If the message is for an unsupported version of the
+ * protocol then olm_session_last_error() will be "BAD_MESSAGE_VERSION".
+ * If the message couldn't be decoded then olm_session_last_error() will be
+ * "BAD_MESSAGE_FORMAT". */
+size_t olm_decrypt_max_plaintext_length(
+ OlmSession * session,
+ size_t message_type,
+ void * message, size_t message_length
+);
+
+/** Decrypts a message using the session. The input message buffer is destroyed.
+ * Returns the length of the plain-text on success. Returns olm_error() on
+ * failure. If the plain-text buffer is smaller than
+ * olm_decrypt_max_plaintext_length() then olm_session_last_error()
+ * will be "OUTPUT_BUFFER_TOO_SMALL". If the base64 couldn't be decoded then
+ * olm_session_last_error() will be "INVALID_BASE64". If the message is for
+ * an unsupported version of the protocol then olm_session_last_error() will
+ * be "BAD_MESSAGE_VERSION". If the message couldn't be decoded then
+ * olm_session_last_error() will be BAD_MESSAGE_FORMAT".
+ * If the MAC on the message was invalid then olm_session_last_error() will
+ * be "BAD_MESSAGE_MAC". */
+size_t olm_decrypt(
+ OlmSession * session,
+ size_t message_type,
+ void * message, size_t message_length,
+ void * plaintext, size_t max_plaintext_length
+);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OLM_HH_ */
diff --git a/include/olm/pickle.hh b/include/olm/pickle.hh
new file mode 100644
index 0000000..1676e23
--- /dev/null
+++ b/include/olm/pickle.hh
@@ -0,0 +1,178 @@
+/* Copyright 2015 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef OLM_PICKLE_HH_
+#define OLM_PICKLE_HH_
+
+#include "olm/list.hh"
+#include "olm/crypto.hh"
+
+#include <cstring>
+#include <cstdint>
+
+namespace olm {
+
+static std::size_t pickle_length(
+ const std::uint32_t & value
+) {
+ return 4;
+}
+
+
+static std::uint8_t * pickle(
+ std::uint8_t * pos,
+ std::uint32_t value
+) {
+ pos += 4;
+ for (unsigned i = 4; i--;) { *(--pos) = value; value >>= 8; }
+ return pos + 4;
+}
+
+
+static std::uint8_t const * unpickle(
+ std::uint8_t const * pos, std::uint8_t const * end,
+ std::uint32_t & value
+) {
+ value = 0;
+ if (end - pos < 4) return end;
+ for (unsigned i = 4; i--;) { value <<= 8; value |= *(pos++); }
+ return pos;
+}
+
+static std::size_t pickle_length(
+ const bool & value
+) {
+ return 1;
+}
+
+
+static std::uint8_t * pickle(
+ std::uint8_t * pos,
+ bool value
+) {
+ *(pos++) = value ? 1 : 0;
+ return pos;
+}
+
+
+static std::uint8_t const * unpickle(
+ std::uint8_t const * pos, std::uint8_t const * end,
+ bool & value
+) {
+ if (pos == end) return end;
+ value = *(pos++);
+ return pos;
+}
+
+
+
+template<typename T, std::size_t max_size>
+std::size_t pickle_length(
+ olm::List<T, max_size> const & list
+) {
+ std::size_t length = pickle_length(std::uint32_t(list.size()));
+ for (auto const & value : list) {
+ length += pickle_length(value);
+ }
+ return length;
+}
+
+
+template<typename T, std::size_t max_size>
+std::uint8_t * pickle(
+ std::uint8_t * pos,
+ olm::List<T, max_size> const & list
+) {
+ pos = pickle(pos, std::uint32_t(list.size()));
+ for (auto const & value : list) {
+ pos = pickle(pos, value);
+ }
+ return pos;
+}
+
+
+template<typename T, std::size_t max_size>
+std::uint8_t const * unpickle(
+ std::uint8_t const * pos, std::uint8_t const * end,
+ olm::List<T, max_size> & list
+) {
+ std::uint32_t size;
+ pos = unpickle(pos, end, size);
+ while (size--) {
+ T * value = list.insert(list.end());
+ pos = unpickle(pos, end, *value);
+ }
+ return pos;
+}
+
+
+static std::uint8_t * pickle_bytes(
+ std::uint8_t * pos,
+ std::uint8_t const * bytes, std::size_t bytes_length
+) {
+ std::memcpy(pos, bytes, bytes_length);
+ return pos + bytes_length;
+}
+
+
+static std::uint8_t const * unpickle_bytes(
+ std::uint8_t const * pos, std::uint8_t const * end,
+ std::uint8_t * bytes, std::size_t bytes_length
+) {
+ if (end - pos < bytes_length) return end;
+ std::memcpy(bytes, pos, bytes_length);
+ return pos + bytes_length;
+}
+
+
+std::size_t pickle_length(
+ const Curve25519PublicKey & value
+);
+
+
+std::uint8_t * pickle(
+ std::uint8_t * pos,
+ const Curve25519PublicKey & value
+);
+
+
+std::uint8_t const * unpickle(
+ std::uint8_t const * pos, std::uint8_t const * end,
+ Curve25519PublicKey & value
+);
+
+
+std::size_t pickle_length(
+ const Curve25519KeyPair & value
+);
+
+
+std::uint8_t * pickle(
+ std::uint8_t * pos,
+ const Curve25519KeyPair & value
+);
+
+
+std::uint8_t const * unpickle(
+ std::uint8_t const * pos, std::uint8_t const * end,
+ Curve25519KeyPair & value
+);
+
+
+} // namespace olm
+
+
+
+
+#endif /* OLM_PICKLE_HH */
diff --git a/include/olm/ratchet.hh b/include/olm/ratchet.hh
new file mode 100644
index 0000000..7274255
--- /dev/null
+++ b/include/olm/ratchet.hh
@@ -0,0 +1,177 @@
+/* Copyright 2015 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "olm/crypto.hh"
+#include "olm/list.hh"
+#include "olm/error.hh"
+
+namespace olm {
+
+class Cipher;
+
+typedef std::uint8_t SharedKey[32];
+
+
+struct ChainKey {
+ std::uint32_t index;
+ SharedKey key;
+};
+
+
+struct MessageKey {
+ std::uint32_t index;
+ SharedKey key;
+};
+
+
+struct SenderChain {
+ Curve25519KeyPair ratchet_key;
+ ChainKey chain_key;
+};
+
+
+struct ReceiverChain {
+ Curve25519PublicKey ratchet_key;
+ ChainKey chain_key;
+};
+
+
+struct SkippedMessageKey {
+ Curve25519PublicKey ratchet_key;
+ MessageKey message_key;
+};
+
+
+static std::size_t const MAX_RECEIVER_CHAINS = 5;
+static std::size_t const MAX_SKIPPED_MESSAGE_KEYS = 40;
+
+
+struct KdfInfo {
+ std::uint8_t const * root_info;
+ std::size_t root_info_length;
+ std::uint8_t const * ratchet_info;
+ std::size_t ratchet_info_length;
+};
+
+
+struct Ratchet {
+
+ Ratchet(
+ KdfInfo const & kdf_info,
+ Cipher const & ratchet_cipher
+ );
+
+ /** A some strings identifying the application to feed into the KDF. */
+ KdfInfo const & kdf_info;
+
+ /** The AEAD cipher to use for encrypting messages. */
+ Cipher const & ratchet_cipher;
+
+ /** The last error that happened encrypting or decrypting a message. */
+ ErrorCode last_error;
+
+ /** The root key is used to generate chain keys from the ephemeral keys.
+ * A new root_key derived each time a chain key is derived. */
+ SharedKey root_key;
+
+ /** The sender chain is used to send messages. Each time a new ephemeral
+ * key is received from the remote server we generate a new sender chain
+ * with a new empheral key when we next send a message. */
+ List<SenderChain, 1> sender_chain;
+
+ /** The receiver chain is used to decrypt received messages. We store the
+ * last few chains so we can decrypt any out of order messages we haven't
+ * received yet. */
+ List<ReceiverChain, MAX_RECEIVER_CHAINS> receiver_chains;
+
+ /** List of message keys we've skipped over when advancing the receiver
+ * chain. */
+ List<SkippedMessageKey, MAX_SKIPPED_MESSAGE_KEYS> skipped_message_keys;
+
+ /** Initialise the session using a shared secret and the public part of the
+ * remote's first ratchet key */
+ void initialise_as_bob(
+ std::uint8_t const * shared_secret, std::size_t shared_secret_length,
+ Curve25519PublicKey const & their_ratchet_key
+ );
+
+ /** Initialise the session using a shared secret and the public/private key
+ * pair for the first ratchet key */
+ void initialise_as_alice(
+ std::uint8_t const * shared_secret, std::size_t shared_secret_length,
+ Curve25519KeyPair const & our_ratchet_key
+ );
+
+ /** The number of bytes of output the encrypt method will write for
+ * a given message length. */
+ std::size_t encrypt_output_length(
+ std::size_t plaintext_length
+ );
+
+ /** The number of bytes of random data the encrypt method will need to
+ * encrypt a message. This will be 32 bytes if the session needs to
+ * generate a new ephemeral key, or will be 0 bytes otherwise.*/
+ std::size_t encrypt_random_length();
+
+ /** Encrypt some plain-text. Returns the length of the encrypted message
+ * or std::size_t(-1) on failure. On failure last_error will be set with
+ * an error code. The last_error will be NOT_ENOUGH_RANDOM if the number
+ * of random bytes is too small. The last_error will be
+ * OUTPUT_BUFFER_TOO_SMALL if the output buffer is too small. */
+ std::size_t encrypt(
+ std::uint8_t const * plaintext, std::size_t plaintext_length,
+ std::uint8_t const * random, std::size_t random_length,
+ std::uint8_t * output, std::size_t max_output_length
+ );
+
+ /** An upper bound on the number of bytes of plain-text the decrypt method
+ * will write for a given input message length. */
+ std::size_t decrypt_max_plaintext_length(
+ std::uint8_t const * input, std::size_t input_length
+ );
+
+ /** Decrypt a message. Returns the length of the decrypted plain-text or
+ * std::size_t(-1) on failure. On failure last_error will be set with an
+ * error code. The last_error will be OUTPUT_BUFFER_TOO_SMALL if the
+ * plain-text buffer is too small. The last_error will be
+ * BAD_MESSAGE_VERSION if the message was encrypted with an unsupported
+ * version of the protocol. The last_error will be BAD_MESSAGE_FORMAT if
+ * the message headers could not be decoded. The last_error will be
+ * BAD_MESSAGE_MAC if the message could not be verified */
+ std::size_t decrypt(
+ std::uint8_t const * input, std::size_t input_length,
+ std::uint8_t * plaintext, std::size_t max_plaintext_length
+ );
+};
+
+
+std::size_t pickle_length(
+ Ratchet const & value
+);
+
+
+std::uint8_t * pickle(
+ std::uint8_t * pos,
+ Ratchet const & value
+);
+
+
+std::uint8_t const * unpickle(
+ std::uint8_t const * pos, std::uint8_t const * end,
+ Ratchet & value
+);
+
+
+} // namespace olm
diff --git a/include/olm/session.hh b/include/olm/session.hh
new file mode 100644
index 0000000..a0aff08
--- /dev/null
+++ b/include/olm/session.hh
@@ -0,0 +1,114 @@
+/* Copyright 2015 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef OLM_SESSION_HH_
+#define OLM_SESSION_HH_
+
+#include "olm/ratchet.hh"
+
+namespace olm {
+
+class Account;
+
+struct RemoteKey {
+ std::uint32_t id;
+ Curve25519PublicKey key;
+};
+
+
+enum struct MessageType {
+ PRE_KEY = 0,
+ MESSAGE = 1,
+};
+
+
+struct Session {
+
+ Session();
+
+ Ratchet ratchet;
+ ErrorCode last_error;
+
+ bool received_message;
+
+ RemoteKey alice_identity_key;
+ Curve25519PublicKey alice_base_key;
+ std::uint32_t bob_one_time_key_id;
+
+
+ std::size_t new_outbound_session_random_length();
+
+ std::size_t new_outbound_session(
+ Account const & local_account,
+ Curve25519PublicKey const & identity_key,
+ RemoteKey const & one_time_key,
+ std::uint8_t const * random, std::size_t random_length
+ );
+
+ std::size_t new_inbound_session(
+ Account & local_account,
+ std::uint8_t const * one_time_key_message, std::size_t message_length
+ );
+
+ bool matches_inbound_session(
+ std::uint8_t const * one_time_key_message, std::size_t message_length
+ );
+
+ MessageType encrypt_message_type();
+
+ std::size_t encrypt_message_length(
+ std::size_t plaintext_length
+ );
+
+ std::size_t encrypt_random_length();
+
+ std::size_t encrypt(
+ std::uint8_t const * plaintext, std::size_t plaintext_length,
+ std::uint8_t const * random, std::size_t random_length,
+ std::uint8_t * message, std::size_t message_length
+ );
+
+ std::size_t decrypt_max_plaintext_length(
+ MessageType message_type,
+ std::uint8_t const * message, std::size_t message_length
+ );
+
+ std::size_t decrypt(
+ MessageType message_type,
+ std::uint8_t const * message, std::size_t message_length,
+ std::uint8_t * plaintext, std::size_t max_plaintext_length
+ );
+};
+
+
+std::size_t pickle_length(
+ Session const & value
+);
+
+
+std::uint8_t * pickle(
+ std::uint8_t * pos,
+ Session const & value
+);
+
+
+std::uint8_t const * unpickle(
+ std::uint8_t const * pos, std::uint8_t const * end,
+ Session & value
+);
+
+
+} // namespace olm
+
+#endif /* OLM_SESSION_HH_ */