abouttreesummaryrefslogcommitdiff
path: root/ext/olm/include
diff options
context:
space:
mode:
Diffstat (limited to 'ext/olm/include')
-rw-r--r--ext/olm/include/olm/account.hh208
-rw-r--r--ext/olm/include/olm/base64.h81
-rw-r--r--ext/olm/include/olm/base64.hh71
-rw-r--r--ext/olm/include/olm/cipher.h142
-rw-r--r--ext/olm/include/olm/crypto.h206
-rw-r--r--ext/olm/include/olm/error.h80
-rw-r--r--ext/olm/include/olm/inbound_group_session.h246
-rw-r--r--ext/olm/include/olm/list.hh119
-rw-r--r--ext/olm/include/olm/megolm.h99
-rw-r--r--ext/olm/include/olm/memory.h41
-rw-r--r--ext/olm/include/olm/memory.hh90
-rw-r--r--ext/olm/include/olm/message.h97
-rw-r--r--ext/olm/include/olm/message.hh141
-rw-r--r--ext/olm/include/olm/olm.h527
-rw-r--r--ext/olm/include/olm/olm.hh4
-rw-r--r--ext/olm/include/olm/olm_export.h42
-rw-r--r--ext/olm/include/olm/outbound_group_session.h192
-rw-r--r--ext/olm/include/olm/pickle.h107
-rw-r--r--ext/olm/include/olm/pickle.hh182
-rw-r--r--ext/olm/include/olm/pickle_encoding.h80
-rw-r--r--ext/olm/include/olm/pk.h298
-rw-r--r--ext/olm/include/olm/ratchet.hh188
-rw-r--r--ext/olm/include/olm/sas.h197
-rw-r--r--ext/olm/include/olm/session.hh168
-rw-r--r--ext/olm/include/olm/utility.hh61
25 files changed, 3667 insertions, 0 deletions
diff --git a/ext/olm/include/olm/account.hh b/ext/olm/include/olm/account.hh
new file mode 100644
index 0000000..50708ed
--- /dev/null
+++ b/ext/olm/include/olm/account.hh
@@ -0,0 +1,208 @@
+/* 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.h"
+#include "olm/error.h"
+
+#include <cstdint>
+
+namespace olm {
+
+
+struct IdentityKeys {
+ _olm_ed25519_key_pair ed25519_key;
+ _olm_curve25519_key_pair curve25519_key;
+};
+
+struct OneTimeKey {
+ std::uint32_t id;
+ bool published;
+ _olm_curve25519_key_pair key;
+};
+
+
+static std::size_t const MAX_ONE_TIME_KEYS = 100;
+
+
+struct Account {
+ Account();
+ IdentityKeys identity_keys;
+ List<OneTimeKey, MAX_ONE_TIME_KEYS> one_time_keys;
+ std::uint8_t num_fallback_keys;
+ OneTimeKey current_fallback_key;
+ OneTimeKey prev_fallback_key;
+ std::uint32_t next_one_time_key_id;
+ OlmErrorCode last_error;
+
+ /** Number of random bytes needed to create a new account */
+ std::size_t new_account_random_length() const;
+
+ /** Create a new account. Returns std::size_t(-1) on error. If the number of
+ * random bytes is too small then last_error will be NOT_ENOUGH_RANDOM */
+ std::size_t new_account(
+ uint8_t const * random, std::size_t random_length
+ );
+
+ /** Number of bytes needed to output the identity keys for this account */
+ std::size_t get_identity_json_length() const;
+
+ /** Output the identity keys for this account as JSON in the following
+ * format:
+ *
+ * {"curve25519":"<43 base64 characters>"
+ * ,"ed25519":"<43 base64 characters>"
+ * }
+ *
+ *
+ * Returns the size of the JSON written or std::size_t(-1) on error.
+ * If the buffer is too small last_error will be OUTPUT_BUFFER_TOO_SMALL. */
+ std::size_t get_identity_json(
+ std::uint8_t * identity_json, std::size_t identity_json_length
+ );
+
+ /**
+ * The length of an ed25519 signature in bytes.
+ */
+ std::size_t signature_length() const;
+
+ /**
+ * Signs a message with the ed25519 key for this account.
+ */
+ std::size_t sign(
+ std::uint8_t const * message, std::size_t message_length,
+ std::uint8_t * signature, std::size_t signature_length
+ );
+
+ /** Number of bytes needed to output the one time keys for this account */
+ std::size_t get_one_time_keys_json_length() const;
+
+ /** Output the one time keys that haven't been published yet as JSON:
+ *
+ * {"curve25519":
+ * ["<6 byte key id>":"<43 base64 characters>"
+ * ,"<6 byte key id>":"<43 base64 characters>"
+ * ...
+ * ]
+ * }
+ *
+ * Returns the size of the JSON written or std::size_t(-1) on error.
+ * If the buffer is too small last_error will be OUTPUT_BUFFER_TOO_SMALL.
+ */
+ std::size_t get_one_time_keys_json(
+ std::uint8_t * one_time_json, std::size_t one_time_json_length
+ );
+
+ /** Mark the current list of one_time_keys and the current fallback key as
+ * being published. The current one time keys will no longer be returned by
+ * get_one_time_keys_json() and the current fallback key will no longer be
+ * returned by get_unpublished_fallback_key_json(). */
+ std::size_t mark_keys_as_published();
+
+ /** The largest number of one time keys this account can store. */
+ std::size_t max_number_of_one_time_keys() const;
+
+ /** The number of random bytes needed to generate a given number of new one
+ * time keys. */
+ std::size_t generate_one_time_keys_random_length(
+ std::size_t number_of_keys
+ ) const;
+
+ /** Generates a number of new one time keys. If the total number of keys
+ * stored by this account exceeds max_number_of_one_time_keys() then the
+ * old keys are discarded. Returns std::size_t(-1) on error. If the number
+ * of random bytes is too small then last_error will be NOT_ENOUGH_RANDOM */
+ std::size_t generate_one_time_keys(
+ std::size_t number_of_keys,
+ std::uint8_t const * random, std::size_t random_length
+ );
+
+ /** The number of random bytes needed to generate a fallback key. */
+ std::size_t generate_fallback_key_random_length() const;
+
+ /** Generates a new fallback key. Returns std::size_t(-1) on error. If the
+ * number of random bytes is too small then last_error will be
+ * NOT_ENOUGH_RANDOM */
+ std::size_t generate_fallback_key(
+ std::uint8_t const * random, std::size_t random_length
+ );
+
+ /** Number of bytes needed to output the fallback keys for this account */
+ std::size_t get_fallback_key_json_length() const;
+
+ /** Deprecated: use get_unpublished_fallback_key_json instead */
+ std::size_t get_fallback_key_json(
+ std::uint8_t * fallback_json, std::size_t fallback_json_length
+ );
+
+ /** Number of bytes needed to output the unpublished fallback keys for this
+ * account */
+ std::size_t get_unpublished_fallback_key_json_length() const;
+
+ /** Output the fallback key as JSON:
+ *
+ * {"curve25519":
+ * ["<6 byte key id>":"<43 base64 characters>"
+ * ,"<6 byte key id>":"<43 base64 characters>"
+ * ...
+ * ]
+ * }
+ *
+ * if there is a fallback key and it has not been published yet.
+ *
+ * Returns the size of the JSON written or std::size_t(-1) on error.
+ * If the buffer is too small last_error will be OUTPUT_BUFFER_TOO_SMALL.
+ */
+ std::size_t get_unpublished_fallback_key_json(
+ std::uint8_t * fallback_json, std::size_t fallback_json_length
+ );
+
+ /** Forget about the old fallback key */
+ void forget_old_fallback_key();
+
+ /** Lookup a one time key with the given public key */
+ OneTimeKey const * lookup_key(
+ _olm_curve25519_public_key const & public_key
+ );
+
+ /** Remove a one time key with the given public key */
+ std::size_t remove_key(
+ _olm_curve25519_public_key const & public_key
+ );
+};
+
+
+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/ext/olm/include/olm/base64.h b/ext/olm/include/olm/base64.h
new file mode 100644
index 0000000..23bd010
--- /dev/null
+++ b/ext/olm/include/olm/base64.h
@@ -0,0 +1,81 @@
+/* Copyright 2015, 2016 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.
+ */
+
+/* C bindings for base64 functions */
+
+
+#ifndef OLM_BASE64_H_
+#define OLM_BASE64_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// Note: exports in this file are only for unit tests. Nobody else should be
+// using this externally
+#include "olm/olm_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * The number of bytes of unpadded base64 needed to encode a length of input.
+ */
+OLM_EXPORT size_t _olm_encode_base64_length(
+ size_t input_length
+);
+
+/**
+ * Encode the raw input as unpadded base64.
+ * Writes encode_base64_length(input_length) bytes to the output buffer.
+ * The input can overlap with the last three quarters of the output buffer.
+ * That is, the input pointer may be output + output_length - input_length.
+ *
+ * Returns number of bytes encoded
+ */
+OLM_EXPORT size_t _olm_encode_base64(
+ uint8_t const * input, size_t input_length,
+ uint8_t * output
+);
+
+/**
+ * The number of bytes of raw data a length of unpadded base64 will encode to.
+ * Returns size_t(-1) if the length is not a valid length for base64.
+ */
+OLM_EXPORT size_t _olm_decode_base64_length(
+ size_t input_length
+);
+
+/**
+ * Decodes the unpadded base64 input to raw bytes.
+ * Writes decode_base64_length(input_length) bytes to the output buffer.
+ * The output can overlap with the first three quarters of the input buffer.
+ * That is, the input pointers and output pointer may be the same.
+ *
+ * Returns number of bytes decoded
+ */
+OLM_EXPORT size_t _olm_decode_base64(
+ uint8_t const * input, size_t input_length,
+ uint8_t * output
+);
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+#endif /* OLM_BASE64_H_ */
diff --git a/ext/olm/include/olm/base64.hh b/ext/olm/include/olm/base64.hh
new file mode 100644
index 0000000..1fe549e
--- /dev/null
+++ b/ext/olm/include/olm/base64.hh
@@ -0,0 +1,71 @@
+/* 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_BASE64_HH_
+#define OLM_BASE64_HH_
+
+#include <cstddef>
+#include <cstdint>
+
+// Note: exports in this file are only for unit tests. Nobody else should be
+// using this externally
+#include "olm/olm_export.h"
+
+namespace olm {
+
+/**
+ * The number of bytes of unpadded base64 needed to encode a length of input.
+ */
+OLM_EXPORT std::size_t encode_base64_length(
+ std::size_t input_length
+);
+
+/**
+ * Encode the raw input as unpadded base64.
+ * Writes encode_base64_length(input_length) bytes to the output buffer.
+ * The input can overlap with the last three quarters of the output buffer.
+ * That is, the input pointer may be output + output_length - input_length.
+ */
+OLM_EXPORT std::uint8_t * encode_base64(
+ std::uint8_t const * input, std::size_t input_length,
+ std::uint8_t * output
+);
+
+/**
+ * The number of bytes of raw data a length of unpadded base64 will encode to.
+ * Returns std::size_t(-1) if the length is not a valid length for base64.
+ */
+OLM_EXPORT std::size_t decode_base64_length(
+ std::size_t input_length
+);
+
+/**
+ * Decodes the unpadded base64 input to raw bytes.
+ * Writes decode_base64_length(input_length) bytes to the output buffer.
+ * The output can overlap with the first three quarters of the input buffer.
+ * That is, the input pointers and output pointer may be the same.
+ *
+ * Returns the number of bytes of raw data the base64 input decoded to. If the
+ * input length supplied is not a valid length for base64, returns
+ * std::size_t(-1) and does not decode.
+ */
+OLM_EXPORT std::size_t decode_base64(
+ std::uint8_t const * input, std::size_t input_length,
+ std::uint8_t * output
+);
+
+} // namespace olm
+
+
+#endif /* OLM_BASE64_HH_ */
diff --git a/ext/olm/include/olm/cipher.h b/ext/olm/include/olm/cipher.h
new file mode 100644
index 0000000..76236dc
--- /dev/null
+++ b/ext/olm/include/olm/cipher.h
@@ -0,0 +1,142 @@
+/* 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_H_
+#define OLM_CIPHER_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+
+// Note: exports in this file are only for unit tests. Nobody else should be
+// using this externally
+#include "olm/olm_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _olm_cipher;
+
+struct _olm_cipher_ops {
+ /**
+ * Returns the length of the message authentication code that will be
+ * appended to the output.
+ */
+ size_t (*mac_length)(const struct _olm_cipher *cipher);
+
+ /**
+ * Returns the length of cipher-text for a given length of plain-text.
+ */
+ size_t (*encrypt_ciphertext_length)(
+ const struct _olm_cipher *cipher,
+ size_t plaintext_length
+ );
+
+ /*
+ * 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
+ *
+ * The plain-text pointers and cipher-text pointers may be the same.
+ *
+ * Returns 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.
+ */
+ size_t (*encrypt)(
+ const struct _olm_cipher *cipher,
+ uint8_t const * key, size_t key_length,
+ uint8_t const * plaintext, size_t plaintext_length,
+ uint8_t * ciphertext, size_t ciphertext_length,
+ uint8_t * output, size_t output_length
+ );
+
+ /**
+ * Returns the maximum length of plain-text that a given length of
+ * cipher-text can contain.
+ */
+ size_t (*decrypt_max_plaintext_length)(
+ const struct _olm_cipher *cipher,
+ size_t ciphertext_length
+ );
+
+ /**
+ * Authenticates the input and decrypts the cipher-text into the plain-text
+ * buffer.
+ *
+ * |----------------------------------------input_length-->|
+ * input |--ciphertext_length-->| |---mac_length-->|
+ * ciphertext
+ *
+ * The plain-text pointers and cipher-text pointers may be the same.
+ *
+ * Returns 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.
+ */
+ size_t (*decrypt)(
+ const struct _olm_cipher *cipher,
+ uint8_t const * key, size_t key_length,
+ uint8_t const * input, size_t input_length,
+ uint8_t const * ciphertext, size_t ciphertext_length,
+ uint8_t * plaintext, size_t max_plaintext_length
+ );
+};
+
+struct _olm_cipher {
+ const struct _olm_cipher_ops *ops;
+ /* cipher-specific fields follow */
+};
+
+struct _olm_cipher_aes_sha_256 {
+ struct _olm_cipher base_cipher;
+
+ /** context string for the HKDF used for deriving the AES256 key, HMAC key,
+ * and AES IV, from the key material passed to encrypt/decrypt.
+ */
+ uint8_t const * kdf_info;
+
+ /** length of context string kdf_info */
+ size_t kdf_info_length;
+};
+
+OLM_EXPORT extern const struct _olm_cipher_ops _olm_cipher_aes_sha_256_ops;
+
+/**
+ * get an initializer for an instance of struct _olm_cipher_aes_sha_256.
+ *
+ * To use it, declare:
+ *
+ * struct _olm_cipher_aes_sha_256 MY_CIPHER =
+ * OLM_CIPHER_INIT_AES_SHA_256("MY_KDF");
+ * struct _olm_cipher *cipher = OLM_CIPHER_BASE(&MY_CIPHER);
+ */
+#define OLM_CIPHER_INIT_AES_SHA_256(KDF_INFO) { \
+ /*.base_cipher = */{ &_olm_cipher_aes_sha_256_ops },\
+ /*.kdf_info = */(uint8_t *)(KDF_INFO), \
+ /*.kdf_info_length = */sizeof(KDF_INFO) - 1 \
+}
+#define OLM_CIPHER_BASE(CIPHER) \
+ (&((CIPHER)->base_cipher))
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* OLM_CIPHER_H_ */
diff --git a/ext/olm/include/olm/crypto.h b/ext/olm/include/olm/crypto.h
new file mode 100644
index 0000000..939c6d9
--- /dev/null
+++ b/ext/olm/include/olm/crypto.h
@@ -0,0 +1,206 @@
+/* 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.
+ */
+
+/* C-compatible crpyto utility functions. At some point all of crypto.hh will
+ * move here.
+ */
+
+#ifndef OLM_CRYPTO_H_
+#define OLM_CRYPTO_H_
+
+// Note: exports in this file are only for unit tests. Nobody else should be
+// using this externally
+#include "olm/olm_export.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** length of a sha256 hash */
+#define SHA256_OUTPUT_LENGTH 32
+
+/** length of a public or private Curve25519 key */
+#define CURVE25519_KEY_LENGTH 32
+
+/** length of the shared secret created by a Curve25519 ECDH operation */
+#define CURVE25519_SHARED_SECRET_LENGTH 32
+
+/** amount of random data required to create a Curve25519 keypair */
+#define CURVE25519_RANDOM_LENGTH CURVE25519_KEY_LENGTH
+
+/** length of a public Ed25519 key */
+#define ED25519_PUBLIC_KEY_LENGTH 32
+
+/** length of a private Ed25519 key */
+#define ED25519_PRIVATE_KEY_LENGTH 64
+
+/** amount of random data required to create a Ed25519 keypair */
+#define ED25519_RANDOM_LENGTH 32
+
+/** length of an Ed25519 signature */
+#define ED25519_SIGNATURE_LENGTH 64
+
+/** length of an aes256 key */
+#define AES256_KEY_LENGTH 32
+
+/** length of an aes256 initialisation vector */
+#define AES256_IV_LENGTH 16
+
+struct _olm_aes256_key {
+ uint8_t key[AES256_KEY_LENGTH];
+};
+
+struct _olm_aes256_iv {
+ uint8_t iv[AES256_IV_LENGTH];
+};
+
+
+struct _olm_curve25519_public_key {
+ uint8_t public_key[CURVE25519_KEY_LENGTH];
+};
+
+struct _olm_curve25519_private_key {
+ uint8_t private_key[CURVE25519_KEY_LENGTH];
+};
+
+struct _olm_curve25519_key_pair {
+ struct _olm_curve25519_public_key public_key;
+ struct _olm_curve25519_private_key private_key;
+};
+
+struct _olm_ed25519_public_key {
+ uint8_t public_key[ED25519_PUBLIC_KEY_LENGTH];
+};
+
+struct _olm_ed25519_private_key {
+ uint8_t private_key[ED25519_PRIVATE_KEY_LENGTH];
+};
+
+struct _olm_ed25519_key_pair {
+ struct _olm_ed25519_public_key public_key;
+ struct _olm_ed25519_private_key private_key;
+};
+
+
+/** The length of output the aes_encrypt_cbc function will write */
+OLM_EXPORT size_t _olm_crypto_aes_encrypt_cbc_length(
+ 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 */
+OLM_EXPORT void _olm_crypto_aes_encrypt_cbc(
+ const struct _olm_aes256_key *key,
+ const struct _olm_aes256_iv *iv,
+ const uint8_t *input, size_t input_length,
+ 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.
+ */
+OLM_EXPORT size_t _olm_crypto_aes_decrypt_cbc(
+ const struct _olm_aes256_key *key,
+ const struct _olm_aes256_iv *iv,
+ uint8_t const * input, size_t input_length,
+ uint8_t * output
+);
+
+
+/** Computes SHA-256 of the input. The output buffer must be a least
+ * SHA256_OUTPUT_LENGTH (32) bytes long. */
+OLM_EXPORT void _olm_crypto_sha256(
+ uint8_t const * input, size_t input_length,
+ uint8_t * output
+);
+
+/** 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 SHA256_OUTPUT_LENGTH (32) bytes long. */
+OLM_EXPORT void _olm_crypto_hmac_sha256(
+ uint8_t const * key, size_t key_length,
+ uint8_t const * input, size_t input_length,
+ uint8_t * output
+);
+
+
+/** HMAC-based Key Derivation Function (HKDF)
+ * https://tools.ietf.org/html/rfc5869
+ * Derives key material from the input bytes. */
+OLM_EXPORT void _olm_crypto_hkdf_sha256(
+ uint8_t const * input, size_t input_length,
+ uint8_t const * info, size_t info_length,
+ uint8_t const * salt, size_t salt_length,
+ uint8_t * output, size_t output_length
+);
+
+
+/** Generate a curve25519 key pair
+ * random_32_bytes should be CURVE25519_RANDOM_LENGTH (32) bytes long.
+ */
+OLM_EXPORT void _olm_crypto_curve25519_generate_key(
+ uint8_t const * random_32_bytes,
+ struct _olm_curve25519_key_pair *output
+);
+
+
+/** Create a shared secret using our private key and their public key.
+ * The output buffer must be at least CURVE25519_SHARED_SECRET_LENGTH (32) bytes long.
+ */
+OLM_EXPORT void _olm_crypto_curve25519_shared_secret(
+ const struct _olm_curve25519_key_pair *our_key,
+ const struct _olm_curve25519_public_key *their_key,
+ uint8_t * output
+);
+
+/** Generate an ed25519 key pair
+ * random_32_bytes should be ED25519_RANDOM_LENGTH (32) bytes long.
+ */
+OLM_EXPORT void _olm_crypto_ed25519_generate_key(
+ uint8_t const * random_bytes,
+ struct _olm_ed25519_key_pair *output
+);
+
+/** Signs the message using our private key.
+ *
+ * The output buffer must be at least ED25519_SIGNATURE_LENGTH (64) bytes
+ * long. */
+OLM_EXPORT void _olm_crypto_ed25519_sign(
+ const struct _olm_ed25519_key_pair *our_key,
+ const uint8_t * message, size_t message_length,
+ uint8_t * output
+);
+
+/** Verify an ed25519 signature
+ * The signature input buffer must be ED25519_SIGNATURE_LENGTH (64) bytes long.
+ * Returns non-zero if the signature is valid. */
+OLM_EXPORT int _olm_crypto_ed25519_verify(
+ const struct _olm_ed25519_public_key *their_key,
+ const uint8_t * message, size_t message_length,
+ const uint8_t * signature
+);
+
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* OLM_CRYPTO_H_ */
diff --git a/ext/olm/include/olm/error.h b/ext/olm/include/olm/error.h
new file mode 100644
index 0000000..c91e89f
--- /dev/null
+++ b/ext/olm/include/olm/error.h
@@ -0,0 +1,80 @@
+/* Copyright 2015-2016 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_ERROR_H_
+#define OLM_ERROR_H_
+
+#include "olm/olm_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum OlmErrorCode {
+ OLM_SUCCESS = 0, /*!< There wasn't an error */
+ OLM_NOT_ENOUGH_RANDOM = 1, /*!< Not enough entropy was supplied */
+ OLM_OUTPUT_BUFFER_TOO_SMALL = 2, /*!< Supplied output buffer is too small */
+ OLM_BAD_MESSAGE_VERSION = 3, /*!< The message version is unsupported */
+ OLM_BAD_MESSAGE_FORMAT = 4, /*!< The message couldn't be decoded */
+ OLM_BAD_MESSAGE_MAC = 5, /*!< The message couldn't be decrypted */
+ OLM_BAD_MESSAGE_KEY_ID = 6, /*!< The message references an unknown key id */
+ OLM_INVALID_BASE64 = 7, /*!< The input base64 was invalid */
+ OLM_BAD_ACCOUNT_KEY = 8, /*!< The supplied account key is invalid */
+ OLM_UNKNOWN_PICKLE_VERSION = 9, /*!< The pickled object is too new */
+ OLM_CORRUPTED_PICKLE = 10, /*!< The pickled object couldn't be decoded */
+
+ OLM_BAD_SESSION_KEY = 11, /*!< Attempt to initialise an inbound group
+ session from an invalid session key */
+ OLM_UNKNOWN_MESSAGE_INDEX = 12, /*!< Attempt to decode a message whose
+ * index is earlier than our earliest
+ * known session key.
+ */
+
+ /**
+ * Attempt to unpickle an account which uses pickle version 1 (which did
+ * not save enough space for the Ed25519 key; the key should be considered
+ * compromised. We don't let the user reload the account.
+ */
+ OLM_BAD_LEGACY_ACCOUNT_PICKLE = 13,
+
+ /**
+ * Received message had a bad signature
+ */
+ OLM_BAD_SIGNATURE = 14,
+
+ OLM_INPUT_BUFFER_TOO_SMALL = 15,
+
+ /**
+ * SAS doesn't have their key set.
+ */
+ OLM_SAS_THEIR_KEY_NOT_SET = 16,
+
+ /**
+ * The pickled object was successfully decoded, but the unpickling still failed
+ * because it had some extraneous junk data at the end.
+ */
+ OLM_PICKLE_EXTRA_DATA = 17,
+
+ /* remember to update the list of string constants in error.c when updating
+ * this list. */
+};
+
+/** get a string representation of the given error code. */
+OLM_EXPORT const char * _olm_error_to_string(enum OlmErrorCode error);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* OLM_ERROR_H_ */
diff --git a/ext/olm/include/olm/inbound_group_session.h b/ext/olm/include/olm/inbound_group_session.h
new file mode 100644
index 0000000..ef68513
--- /dev/null
+++ b/ext/olm/include/olm/inbound_group_session.h
@@ -0,0 +1,246 @@
+/* Copyright 2016 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_INBOUND_GROUP_SESSION_H_
+#define OLM_INBOUND_GROUP_SESSION_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "olm/error.h"
+
+#include "olm/olm_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct OlmInboundGroupSession OlmInboundGroupSession;
+
+/** get the size of an inbound group session, in bytes. */
+OLM_EXPORT size_t olm_inbound_group_session_size(void);
+
+/**
+ * Initialise an inbound group session object using the supplied memory
+ * The supplied memory should be at least olm_inbound_group_session_size()
+ * bytes.
+ */
+OLM_EXPORT OlmInboundGroupSession * olm_inbound_group_session(
+ void *memory
+);
+
+/**
+ * A null terminated string describing the most recent error to happen to a
+ * group session */
+OLM_EXPORT const char *olm_inbound_group_session_last_error(
+ const OlmInboundGroupSession *session
+);
+
+/**
+ * An error code describing the most recent error to happen to a group
+ * session */
+OLM_EXPORT enum OlmErrorCode olm_inbound_group_session_last_error_code(
+ const OlmInboundGroupSession *session
+);
+
+/** Clears the memory used to back this group session */
+OLM_EXPORT size_t olm_clear_inbound_group_session(
+ OlmInboundGroupSession *session
+);
+
+/** Returns the number of bytes needed to store an inbound group session */
+OLM_EXPORT size_t olm_pickle_inbound_group_session_length(
+ const OlmInboundGroupSession *session
+);
+
+/**
+ * Stores a group session as a base64 string. Encrypts the session using the
+ * supplied key. Returns the length of the session on success.
+ *
+ * Returns olm_error() on failure. If the pickle output buffer
+ * is smaller than olm_pickle_inbound_group_session_length() then
+ * olm_inbound_group_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL"
+ */
+OLM_EXPORT size_t olm_pickle_inbound_group_session(
+ OlmInboundGroupSession *session,
+ void const * key, size_t key_length,
+ void * pickled, size_t pickled_length
+);
+
+/**
+ * Loads a group 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_inbound_group_session_last_error() will be
+ * "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then
+ * olm_inbound_group_session_last_error() will be "INVALID_BASE64". The input
+ * pickled buffer is destroyed
+ */
+OLM_EXPORT size_t olm_unpickle_inbound_group_session(
+ OlmInboundGroupSession *session,
+ void const * key, size_t key_length,
+ void * pickled, size_t pickled_length
+);
+
+
+/**
+ * Start a new inbound group session, from a key exported from
+ * olm_outbound_group_session_key
+ *
+ * Returns olm_error() on failure. On failure last_error will be set with an
+ * error code. The last_error will be:
+ *
+ * * OLM_INVALID_BASE64 if the session_key is not valid base64
+ * * OLM_BAD_SESSION_KEY if the session_key is invalid
+ */
+OLM_EXPORT size_t olm_init_inbound_group_session(
+ OlmInboundGroupSession *session,
+ /* base64-encoded keys */
+ uint8_t const * session_key, size_t session_key_length
+);
+
+/**
+ * Import an inbound group session, from a previous export.
+ *
+ * Returns olm_error() on failure. On failure last_error will be set with an
+ * error code. The last_error will be:
+ *
+ * * OLM_INVALID_BASE64 if the session_key is not valid base64
+ * * OLM_BAD_SESSION_KEY if the session_key is invalid
+ */
+OLM_EXPORT size_t olm_import_inbound_group_session(
+ OlmInboundGroupSession *session,
+ /* base64-encoded keys; note that it will be overwritten with the base64-decoded
+ data. */
+ uint8_t const * session_key, size_t session_key_length
+);
+
+
+/**
+ * Get an upper bound on the number of bytes of plain-text the decrypt method
+ * will write for a given input message length. The actual size could be
+ * different due to padding.
+ *
+ * The input message buffer is destroyed.
+ *
+ * Returns olm_error() on failure.
+ */
+OLM_EXPORT size_t olm_group_decrypt_max_plaintext_length(
+ OlmInboundGroupSession *session,
+ uint8_t * message, size_t message_length
+);
+
+/**
+ * Decrypt a message.
+ *
+ * The input message buffer is destroyed.
+ *
+ * Returns the length of the decrypted plain-text, or olm_error() on failure.
+ *
+ * On failure last_error will be set with an error code. The last_error will
+ * be:
+ * * OLM_OUTPUT_BUFFER_TOO_SMALL if the plain-text buffer is too small
+ * * OLM_INVALID_BASE64 if the message is not valid base-64
+ * * OLM_BAD_MESSAGE_VERSION if the message was encrypted with an unsupported
+ * version of the protocol
+ * * OLM_BAD_MESSAGE_FORMAT if the message headers could not be decoded
+ * * OLM_BAD_MESSAGE_MAC if the message could not be verified
+ * * OLM_UNKNOWN_MESSAGE_INDEX if we do not have a session key corresponding to the
+ * message's index (ie, it was sent before the session key was shared with
+ * us)
+ */
+OLM_EXPORT size_t olm_group_decrypt(
+ OlmInboundGroupSession *session,
+
+ /* input; note that it will be overwritten with the base64-decoded
+ message. */
+ uint8_t * message, size_t message_length,
+
+ /* output */
+ uint8_t * plaintext, size_t max_plaintext_length,
+ uint32_t * message_index
+);
+
+
+/**
+ * Get the number of bytes returned by olm_inbound_group_session_id()
+ */
+OLM_EXPORT size_t olm_inbound_group_session_id_length(
+ const OlmInboundGroupSession *session
+);
+
+/**
+ * Get a base64-encoded identifier for this session.
+ *
+ * Returns the length of the session id on success or olm_error() on
+ * failure. On failure last_error will be set with an error code. The
+ * last_error will be OUTPUT_BUFFER_TOO_SMALL if the id buffer was too
+ * small.
+ */
+OLM_EXPORT size_t olm_inbound_group_session_id(
+ OlmInboundGroupSession *session,
+ uint8_t * id, size_t id_length
+);
+
+/**
+ * Get the first message index we know how to decrypt.
+ */
+OLM_EXPORT uint32_t olm_inbound_group_session_first_known_index(
+ const OlmInboundGroupSession *session
+);
+
+
+/**
+ * Check if the session has been verified as a valid session.
+ *
+ * (A session is verified either because the original session share was signed,
+ * or because we have subsequently successfully decrypted a message.)
+ *
+ * This is mainly intended for the unit tests, currently.
+ */
+OLM_EXPORT int olm_inbound_group_session_is_verified(
+ const OlmInboundGroupSession *session
+);
+
+/**
+ * Get the number of bytes returned by olm_export_inbound_group_session()
+ */
+OLM_EXPORT size_t olm_export_inbound_group_session_length(
+ const OlmInboundGroupSession *session
+);
+
+/**
+ * Export the base64-encoded ratchet key for this session, at the given index,
+ * in a format which can be used by olm_import_inbound_group_session
+ *
+ * Returns the length of the ratchet key on success or olm_error() on
+ * failure. On failure last_error will be set with an error code. The
+ * last_error will be:
+ * * OUTPUT_BUFFER_TOO_SMALL if the buffer was too small
+ * * OLM_UNKNOWN_MESSAGE_INDEX if we do not have a session key corresponding to the
+ * given index (ie, it was sent before the session key was shared with
+ * us)
+ */
+OLM_EXPORT size_t olm_export_inbound_group_session(
+ OlmInboundGroupSession *session,
+ uint8_t * key, size_t key_length, uint32_t message_index
+);
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* OLM_INBOUND_GROUP_SESSION_H_ */
diff --git a/ext/olm/include/olm/list.hh b/ext/olm/include/olm/list.hh
new file mode 100644
index 0000000..6906c87
--- /dev/null
+++ b/ext/olm/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 = _end - 1;
+ while (tmp != pos) {
+ *tmp = *(tmp - 1);
+ --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/ext/olm/include/olm/megolm.h b/ext/olm/include/olm/megolm.h
new file mode 100644
index 0000000..338ab21
--- /dev/null
+++ b/ext/olm/include/olm/megolm.h
@@ -0,0 +1,99 @@
+/* Copyright 2016 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_MEGOLM_H_
+#define OLM_MEGOLM_H_
+
+/**
+ * implementation of the Megolm multi-part ratchet used in group chats.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+// Note: exports in this file are only for unit tests. Nobody else should be
+// using this externally
+#include "olm/olm_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * number of bytes in each part of the ratchet; this should be the same as
+ * the length of the hash function used in the HMAC (32 bytes for us, as we
+ * use HMAC-SHA-256)
+ */
+#define MEGOLM_RATCHET_PART_LENGTH 32 /* SHA256_OUTPUT_LENGTH */
+
+/**
+ * number of parts in the ratchet; the advance() implementations rely on
+ * this being 4.
+ */
+#define MEGOLM_RATCHET_PARTS 4
+
+#define MEGOLM_RATCHET_LENGTH (MEGOLM_RATCHET_PARTS * MEGOLM_RATCHET_PART_LENGTH)
+
+typedef struct Megolm {
+ uint8_t data[MEGOLM_RATCHET_PARTS][MEGOLM_RATCHET_PART_LENGTH];
+ uint32_t counter;
+} Megolm;
+
+
+/**
+ * The cipher used in megolm-backed conversations
+ *
+ * (AES256 + SHA256, with keys based on an HKDF with info of MEGOLM_KEYS)
+ */
+extern const struct _olm_cipher *megolm_cipher;
+
+/**
+ * initialize the megolm ratchet. random_data should be at least
+ * MEGOLM_RATCHET_LENGTH bytes of randomness.
+ */
+OLM_EXPORT void megolm_init(Megolm *megolm, uint8_t const *random_data, uint32_t counter);
+
+/** Returns the number of bytes needed to store a megolm */
+OLM_EXPORT size_t megolm_pickle_length(const Megolm *megolm);
+
+/**
+ * Pickle the megolm. Returns a pointer to the next free space in the buffer.
+ */
+OLM_EXPORT uint8_t * megolm_pickle(const Megolm *megolm, uint8_t *pos);
+
+/**
+ * Unpickle the megolm. Returns a pointer to the next item in the buffer.
+ */
+OLM_EXPORT const uint8_t * megolm_unpickle(Megolm *megolm, const uint8_t *pos,
+ const uint8_t *end);
+
+
+/** advance the ratchet by one step */
+OLM_EXPORT void megolm_advance(Megolm *megolm);
+
+/**
+ * get the key data in the ratchet. The returned data is
+ * MEGOLM_RATCHET_LENGTH bytes long.
+ */
+#define megolm_get_data(megolm) ((const uint8_t *)((megolm)->data))
+
+/** advance the ratchet to a given count */
+OLM_EXPORT void megolm_advance_to(Megolm *megolm, uint32_t advance_to);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* OLM_MEGOLM_H_ */
diff --git a/ext/olm/include/olm/memory.h b/ext/olm/include/olm/memory.h
new file mode 100644
index 0000000..cc346d0
--- /dev/null
+++ b/ext/olm/include/olm/memory.h
@@ -0,0 +1,41 @@
+/* Copyright 2015, 2016 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.
+ */
+
+/* C bindings for memory functions */
+
+
+#ifndef OLM_MEMORY_H_
+#define OLM_MEMORY_H_
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Clear the memory held in the buffer. This is more resilient to being
+ * optimised away than memset or bzero.
+ */
+void _olm_unset(
+ void volatile * buffer, size_t buffer_length
+);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+#endif /* OLM_MEMORY_H_ */
diff --git a/ext/olm/include/olm/memory.hh b/ext/olm/include/olm/memory.hh
new file mode 100644
index 0000000..74ff9f8
--- /dev/null
+++ b/ext/olm/include/olm/memory.hh
@@ -0,0 +1,90 @@
+/* Copyright 2015, 2016 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>
+#include <cstring>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <type_traits>
+
+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
+);
+
+/** Check if two fixed size arrays are equals */
+template<typename T>
+bool array_equal(
+ T const & array_a,
+ T const & array_b
+) {
+ static_assert(
+ std::is_array<T>::value
+ && std::is_convertible<T, std::uint8_t *>::value
+ && sizeof(T) > 0,
+ "Arguments to array_equal must be std::uint8_t arrays[]."
+ );
+ return is_equal(array_a, array_b, sizeof(T));
+}
+
+/** Copy into a fixed size array */
+template<typename T>
+std::uint8_t const * load_array(
+ T & destination,
+ std::uint8_t const * source
+) {
+ static_assert(
+ std::is_array<T>::value
+ && std::is_convertible<T, std::uint8_t *>::value
+ && sizeof(T) > 0,
+ "The first argument to load_array must be a std::uint8_t array[]."
+ );
+ std::memcpy(destination, source, sizeof(T));
+ return source + sizeof(T);
+}
+
+/** Copy from a fixed size array */
+template<typename T>
+std::uint8_t * store_array(
+ std::uint8_t * destination,
+ T const & source
+) {
+ static_assert(
+ std::is_array<T>::value
+ && std::is_convertible<T, std::uint8_t *>::value
+ && sizeof(T) > 0,
+ "The second argument to store_array must be a std::uint8_t array[]."
+ );
+ std::memcpy(destination, source, sizeof(T));
+ return destination + sizeof(T);
+}
+
+} // namespace olm
diff --git a/ext/olm/include/olm/message.h b/ext/olm/include/olm/message.h
new file mode 100644
index 0000000..cc4158b
--- /dev/null
+++ b/ext/olm/include/olm/message.h
@@ -0,0 +1,97 @@
+/* Copyright 2016 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.
+ */
+
+/**
+ * functions for encoding and decoding messages in the Olm protocol.
+ *
+ * Some of these functions have only C++ bindings, and are declared in
+ * message.hh; in time, they should probably be converted to plain C and
+ * declared here.
+ */
+
+#ifndef OLM_MESSAGE_H_
+#define OLM_MESSAGE_H_
+
+#include <stdint.h>
+#include <stddef.h>
+
+// Note: exports in this file are only for unit tests. Nobody else should be
+// using this externally
+#include "olm/olm_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The length of the buffer needed to hold a group message.
+ */
+OLM_EXPORT size_t _olm_encode_group_message_length(
+ uint32_t chain_index,
+ size_t ciphertext_length,
+ size_t mac_length,
+ size_t signature_length
+);
+
+/**
+ * Writes the message headers into the output buffer.
+ *
+ * version: version number of the olm protocol
+ * message_index: message index
+ * ciphertext_length: length of the ciphertext
+ * output: where to write the output. Should be at least
+ * olm_encode_group_message_length() bytes long.
+ * ciphertext_ptr: returns the address that the ciphertext
+ * should be written to, followed by the MAC and the
+ * signature.
+ *
+ * Returns the size of the message, up to the MAC.
+ */
+OLM_EXPORT size_t _olm_encode_group_message(
+ uint8_t version,
+ uint32_t message_index,
+ size_t ciphertext_length,
+ uint8_t *output,
+ uint8_t **ciphertext_ptr
+);
+
+
+struct _OlmDecodeGroupMessageResults {
+ uint8_t version;
+ uint32_t message_index;
+ int has_message_index;
+ const uint8_t *ciphertext;
+ size_t ciphertext_length;
+};
+
+
+/**
+ * Reads the message headers from the input buffer.
+ */
+OLM_EXPORT void _olm_decode_group_message(
+ const uint8_t *input, size_t input_length,
+ size_t mac_length, size_t signature_length,
+
+ /* output structure: updated with results */
+ struct _OlmDecodeGroupMessageResults *results
+);
+
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* OLM_MESSAGE_H_ */
diff --git a/ext/olm/include/olm/message.hh b/ext/olm/include/olm/message.hh
new file mode 100644
index 0000000..6da4851
--- /dev/null
+++ b/ext/olm/include/olm/message.hh
@@ -0,0 +1,141 @@
+/* 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.
+ */
+
+
+/**
+ * functions for encoding and decoding messages in the Olm protocol.
+ *
+ * Some of these functions have plain-C bindings, and are declared in
+ * message.h; in time, all of the functions declared here should probably be
+ * converted to plain C and moved to message.h.
+ */
+
+#include "message.h"
+
+#include <cstddef>
+#include <cstdint>
+
+// Note: exports in this file are only for unit tests. Nobody else should be
+// using this externally
+#include "olm/olm_export.h"
+
+namespace olm {
+
+/**
+ * The length of the buffer needed to hold a message.
+ */
+OLM_EXPORT 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.
+ */
+OLM_EXPORT 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.
+ */
+OLM_EXPORT 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 * one_time_key;
+ std::uint8_t * message;
+};
+
+
+struct PreKeyMessageReader {
+ std::uint8_t version;
+ 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 * one_time_key; std::size_t one_time_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::size_t identity_key_length,
+ std::size_t base_key_length,
+ std::size_t one_time_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::size_t identity_key_length,
+ std::size_t base_key_length,
+ std::size_t one_time_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/ext/olm/include/olm/olm.h b/ext/olm/include/olm/olm.h
new file mode 100644
index 0000000..2cd5339
--- /dev/null
+++ b/ext/olm/include/olm/olm.h
@@ -0,0 +1,527 @@
+/* Copyright 2015, 2016 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_H_
+#define OLM_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "olm/error.h"
+#include "olm/inbound_group_session.h"
+#include "olm/outbound_group_session.h"
+
+#include "olm/olm_export.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;
+
+typedef struct OlmAccount OlmAccount;
+typedef struct OlmSession OlmSession;
+typedef struct OlmUtility OlmUtility;
+
+/** Get the version number of the library.
+ * Arguments will be updated if non-null.
+ */
+OLM_EXPORT void olm_get_library_version(uint8_t *major, uint8_t *minor, uint8_t *patch);
+
+/** The size of an account object in bytes */
+OLM_EXPORT size_t olm_account_size(void);
+
+/** The size of a session object in bytes */
+OLM_EXPORT size_t olm_session_size(void);
+
+/** The size of a utility object in bytes */
+OLM_EXPORT size_t olm_utility_size(void);
+
+/** Initialise an account object using the supplied memory
+ * The supplied memory must be at least olm_account_size() bytes */
+OLM_EXPORT OlmAccount * olm_account(
+ void * memory
+);
+
+/** Initialise a session object using the supplied memory
+ * The supplied memory must be at least olm_session_size() bytes */
+OLM_EXPORT OlmSession * olm_session(
+ void * memory
+);
+
+/** Initialise a utility object using the supplied memory
+ * The supplied memory must be at least olm_utility_size() bytes */
+OLM_EXPORT OlmUtility * olm_utility(
+ void * memory
+);
+
+/** The value that olm will return from a function if there was an error */
+OLM_EXPORT size_t olm_error(void);
+
+/** A null terminated string describing the most recent error to happen to an
+ * account */
+OLM_EXPORT const char * olm_account_last_error(
+ OlmAccount const * account
+);
+
+/** An error code describing the most recent error to happen to an account */
+OLM_EXPORT enum OlmErrorCode olm_account_last_error_code(
+ OlmAccount const * account
+);
+
+/** A null terminated string describing the most recent error to happen to a
+ * session */
+OLM_EXPORT const char * olm_session_last_error(
+ OlmSession const * session
+);
+
+/** An error code describing the most recent error to happen to a session */
+OLM_EXPORT enum OlmErrorCode olm_session_last_error_code(
+ OlmSession const * session
+);
+
+/** A null terminated string describing the most recent error to happen to a
+ * utility */
+OLM_EXPORT const char * olm_utility_last_error(
+ OlmUtility const * utility
+);
+
+/** An error code describing the most recent error to happen to a utility */
+OLM_EXPORT enum OlmErrorCode olm_utility_last_error_code(
+ OlmUtility const * utility
+);
+
+/** Clears the memory used to back this account */
+OLM_EXPORT size_t olm_clear_account(
+ OlmAccount * account
+);
+
+/** Clears the memory used to back this session */
+OLM_EXPORT size_t olm_clear_session(
+ OlmSession * session
+);
+
+/** Clears the memory used to back this utility */
+OLM_EXPORT size_t olm_clear_utility(
+ OlmUtility * utility
+);
+
+/** Returns the number of bytes needed to store an account */
+OLM_EXPORT size_t olm_pickle_account_length(
+ OlmAccount const * account
+);
+
+/** Returns the number of bytes needed to store a session */
+OLM_EXPORT size_t olm_pickle_session_length(
+ OlmSession const * 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" */
+OLM_EXPORT 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" */
+OLM_EXPORT 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 */
+OLM_EXPORT 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 */
+OLM_EXPORT 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.*/
+OLM_EXPORT size_t olm_create_account_random_length(
+ OlmAccount const * account
+);
+
+/** Creates a new account. Returns olm_error() on failure. If there weren't
+ * enough random bytes then olm_account_last_error() will be
+ * "NOT_ENOUGH_RANDOM" */
+OLM_EXPORT size_t olm_create_account(
+ OlmAccount * account,
+ void * random, size_t random_length
+);
+
+/** The size of the output buffer needed to hold the identity keys */
+OLM_EXPORT size_t olm_account_identity_keys_length(
+ OlmAccount const * account
+);
+
+/** Writes the public parts of the identity keys for the account into the
+ * identity_keys output buffer. Returns olm_error() on failure. If the
+ * identity_keys buffer was too small then olm_account_last_error() will be
+ * "OUTPUT_BUFFER_TOO_SMALL". */
+OLM_EXPORT size_t olm_account_identity_keys(
+ OlmAccount * account,
+ void * identity_keys, size_t identity_key_length
+);
+
+
+/** The length of an ed25519 signature encoded as base64. */
+OLM_EXPORT size_t olm_account_signature_length(
+ OlmAccount const * account
+);
+
+/** Signs a message with the ed25519 key for this account. Returns olm_error()
+ * on failure. If the signature buffer was too small then
+ * olm_account_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */
+OLM_EXPORT size_t olm_account_sign(
+ OlmAccount * account,
+ void const * message, size_t message_length,
+ void * signature, size_t signature_length
+);
+
+/** The size of the output buffer needed to hold the one time keys */
+OLM_EXPORT size_t olm_account_one_time_keys_length(
+ OlmAccount const * account
+);
+
+/** Writes the public parts of the unpublished one time keys for the account
+ * into the one_time_keys output buffer.
+ * <p>
+ * The returned data is a JSON-formatted object with the single property
+ * <tt>curve25519</tt>, which is itself an object mapping key id to
+ * base64-encoded Curve25519 key. For example:
+ * <pre>
+ * {
+ * curve25519: {
+ * "AAAAAA": "wo76WcYtb0Vk/pBOdmduiGJ0wIEjW4IBMbbQn7aSnTo",
+ * "AAAAAB": "LRvjo46L1X2vx69sS9QNFD29HWulxrmW11Up5AfAjgU"
+ * }
+ * }
+ * </pre>
+ * Returns olm_error() on failure.
+ * <p>
+ * If the one_time_keys buffer was too small then olm_account_last_error()
+ * will be "OUTPUT_BUFFER_TOO_SMALL". */
+OLM_EXPORT size_t olm_account_one_time_keys(
+ OlmAccount * account,
+ void * one_time_keys, size_t one_time_keys_length
+);
+
+/** Marks the current set of one time keys and fallback key as being published
+ * Once marked as published, the one time keys will no longer be returned by
+ * olm_account_one_time_keys(), and the fallback key will no longer be returned
+ * by olm_account_unpublished_fallback_key().
+ *
+ * Returns the number of one-time keys that were marked as published. Note that
+ * this count does not include the fallback key. */
+OLM_EXPORT size_t olm_account_mark_keys_as_published(
+ OlmAccount * account
+);
+
+/** The largest number of one time keys this account can store. */
+OLM_EXPORT size_t olm_account_max_number_of_one_time_keys(
+ OlmAccount const * account
+);
+
+/** The number of random bytes needed to generate a given number of new one
+ * time keys. */
+OLM_EXPORT size_t olm_account_generate_one_time_keys_random_length(
+ OlmAccount const * account,
+ size_t number_of_keys
+);
+
+/** Generates a number of new one time keys. If the total number of keys stored
+ * by this account exceeds max_number_of_one_time_keys() then the old keys are
+ * discarded. Returns olm_error() on error. If the number of random bytes is
+ * too small then olm_account_last_error() will be "NOT_ENOUGH_RANDOM". */
+OLM_EXPORT size_t olm_account_generate_one_time_keys(
+ OlmAccount * account,
+ size_t number_of_keys,
+ void * random, size_t random_length
+);
+
+/** The number of random bytes needed to generate a fallback key. */
+OLM_EXPORT size_t olm_account_generate_fallback_key_random_length(
+ OlmAccount const * account
+);
+
+/** Generates a new fallback key. Only one previous fallback key is
+ * stored. Returns olm_error() on error. If the number of random bytes is too
+ * small then olm_account_last_error() will be "NOT_ENOUGH_RANDOM". */
+OLM_EXPORT size_t olm_account_generate_fallback_key(
+ OlmAccount * account,
+ void * random, size_t random_length
+);
+
+/** The number of bytes needed to hold the fallback key as returned by
+ * olm_account_fallback_key. */
+OLM_EXPORT size_t olm_account_fallback_key_length(
+ OlmAccount const * account
+);
+
+/** Deprecated: use olm_account_unpublished_fallback_key instead */
+OLM_EXPORT size_t olm_account_fallback_key(
+ OlmAccount * account,
+ void * fallback_key, size_t fallback_key_size
+);
+
+/** The number of bytes needed to hold the unpublished fallback key as returned
+ * by olm_account_unpublished fallback_key. */
+OLM_EXPORT size_t olm_account_unpublished_fallback_key_length(
+ OlmAccount const * account
+);
+
+/** Returns the fallback key (if present, and if unpublished) into the
+ * fallback_key buffer */
+OLM_EXPORT size_t olm_account_unpublished_fallback_key(
+ OlmAccount * account,
+ void * fallback_key, size_t fallback_key_size
+);
+
+/** Forget about the old fallback key. This should be called once you are
+ * reasonably certain that you will not receive any more messages that use
+ * the old fallback key (e.g. 5 minutes after the new fallback key has been
+ * published).
+ */
+OLM_EXPORT void olm_account_forget_old_fallback_key(
+ OlmAccount * account
+);
+
+
+/** The number of random bytes needed to create an outbound session */
+OLM_EXPORT size_t olm_create_outbound_session_random_length(
+ OlmSession const * 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". */
+OLM_EXPORT size_t olm_create_outbound_session(
+ OlmSession * session,
+ OlmAccount const * account,
+ void const * their_identity_key, size_t their_identity_key_length,
+ void const * their_one_time_key, size_t their_one_time_key_length,
+ void * 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 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". */
+OLM_EXPORT size_t olm_create_inbound_session(
+ OlmSession * session,
+ OlmAccount * account,
+ void * one_time_key_message, size_t message_length
+);
+
+/** Same as olm_create_inbound_session, but ensures that the identity key
+ * in the pre-key message matches the expected identity key, supplied via the
+ * `their_identity_key` parameter. Fails early if there is no match. */
+OLM_EXPORT size_t olm_create_inbound_session_from(
+ OlmSession * session,
+ OlmAccount * account,
+ void const * their_identity_key, size_t their_identity_key_length,
+ void * one_time_key_message, size_t message_length
+);
+
+/** The length of the buffer needed to return the id for this session. */
+OLM_EXPORT size_t olm_session_id_length(
+ OlmSession const * session
+);
+
+/** An identifier for this session. Will be the same for both ends of the
+ * conversation. If the id buffer is too small then olm_session_last_error()
+ * will be "OUTPUT_BUFFER_TOO_SMALL". */
+OLM_EXPORT size_t olm_session_id(
+ OlmSession * session,
+ void * id, size_t id_length
+);
+
+OLM_EXPORT int olm_session_has_received_message(
+ OlmSession const *session
+);
+
+/**
+ * Write a null-terminated string describing the internal state of an olm
+ * session to the buffer provided for debugging and logging purposes. If the
+ * buffer is not large enough to hold the entire string, it will be truncated
+ * and will end with "...". A buffer length of 600 will be enough to hold any
+ * output.
+ */
+OLM_EXPORT void olm_session_describe(OlmSession * session, char *buf, size_t buflen);
+
+/** 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. The one_time_key_message buffer is destroyed. Returns 1 if
+ * the session matches. Returns 0 if the session does not match. 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". */
+OLM_EXPORT size_t olm_matches_inbound_session(
+ OlmSession * session,
+ 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. The one_time_key_message buffer is destroyed. Returns 1 if
+ * the session matches. Returns 0 if the session does not match. 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". */
+OLM_EXPORT size_t olm_matches_inbound_session_from(
+ OlmSession * session,
+ void const * their_identity_key, size_t their_identity_key_length,
+ 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". */
+OLM_EXPORT 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. */
+OLM_EXPORT size_t olm_encrypt_message_type(
+ OlmSession const * session
+);
+
+/** The number of random bytes needed to encrypt the next message. */
+OLM_EXPORT size_t olm_encrypt_random_length(
+ OlmSession const * session
+);
+
+/** The size of the next message in bytes for the given number of plain-text
+ * bytes. */
+OLM_EXPORT size_t olm_encrypt_message_length(
+ OlmSession const * 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". */
+OLM_EXPORT size_t olm_encrypt(
+ OlmSession * session,
+ void const * plaintext, size_t plaintext_length,
+ void * 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". */
+OLM_EXPORT 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". */
+OLM_EXPORT size_t olm_decrypt(
+ OlmSession * session,
+ size_t message_type,
+ void * message, size_t message_length,
+ void * plaintext, size_t max_plaintext_length
+);
+
+/** The length of the buffer needed to hold the SHA-256 hash. */
+OLM_EXPORT size_t olm_sha256_length(
+ OlmUtility const * utility
+);
+
+/** Calculates the SHA-256 hash of the input and encodes it as base64. If the
+ * output buffer is smaller than olm_sha256_length() then
+ * olm_utility_last_error() will be "OUTPUT_BUFFER_TOO_SMALL". */
+OLM_EXPORT size_t olm_sha256(
+ OlmUtility * utility,
+ void const * input, size_t input_length,
+ void * output, size_t output_length
+);
+
+/** Verify an ed25519 signature. If the key was too small then
+ * olm_utility_last_error() will be "INVALID_BASE64". If the signature was invalid
+ * then olm_utility_last_error() will be "BAD_MESSAGE_MAC". */
+OLM_EXPORT size_t olm_ed25519_verify(
+ OlmUtility * utility,
+ void const * key, size_t key_length,
+ void const * message, size_t message_length,
+ void * signature, size_t signature_length
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OLM_H_ */
diff --git a/ext/olm/include/olm/olm.hh b/ext/olm/include/olm/olm.hh
new file mode 100644
index 0000000..5ca59c3
--- /dev/null
+++ b/ext/olm/include/olm/olm.hh
@@ -0,0 +1,4 @@
+/* this file exists only for compatibility with existing applications.
+ * You should use "#include <olm/olm.h>" instead.
+ */
+#include "olm/olm.h"
diff --git a/ext/olm/include/olm/olm_export.h b/ext/olm/include/olm/olm_export.h
new file mode 100644
index 0000000..d7197a2
--- /dev/null
+++ b/ext/olm/include/olm/olm_export.h
@@ -0,0 +1,42 @@
+
+#ifndef OLM_EXPORT_H
+#define OLM_EXPORT_H
+
+#ifdef OLM_STATIC_DEFINE
+# define OLM_EXPORT
+# define OLM_NO_EXPORT
+#else
+# ifndef OLM_EXPORT
+# ifdef olm_EXPORTS
+ /* We are building this library */
+# define OLM_EXPORT
+# else
+ /* We are using this library */
+# define OLM_EXPORT
+# endif
+# endif
+
+# ifndef OLM_NO_EXPORT
+# define OLM_NO_EXPORT
+# endif
+#endif
+
+#ifndef OLM_DEPRECATED
+# define OLM_DEPRECATED __attribute__ ((__deprecated__))
+#endif
+
+#ifndef OLM_DEPRECATED_EXPORT
+# define OLM_DEPRECATED_EXPORT OLM_EXPORT OLM_DEPRECATED
+#endif
+
+#ifndef OLM_DEPRECATED_NO_EXPORT
+# define OLM_DEPRECATED_NO_EXPORT OLM_NO_EXPORT OLM_DEPRECATED
+#endif
+
+#if 0 /* DEFINE_NO_DEPRECATED */
+# ifndef OLM_NO_DEPRECATED
+# define OLM_NO_DEPRECATED
+# endif
+#endif
+
+#endif /* OLM_EXPORT_H */
diff --git a/ext/olm/include/olm/outbound_group_session.h b/ext/olm/include/olm/outbound_group_session.h
new file mode 100644
index 0000000..ccfbee5
--- /dev/null
+++ b/ext/olm/include/olm/outbound_group_session.h
@@ -0,0 +1,192 @@
+/* Copyright 2016 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_OUTBOUND_GROUP_SESSION_H_
+#define OLM_OUTBOUND_GROUP_SESSION_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "olm/error.h"
+
+#include "olm/olm_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct OlmOutboundGroupSession OlmOutboundGroupSession;
+
+/** get the size of an outbound group session, in bytes. */
+OLM_EXPORT size_t olm_outbound_group_session_size(void);
+
+/**
+ * Initialise an outbound group session object using the supplied memory
+ * The supplied memory should be at least olm_outbound_group_session_size()
+ * bytes.
+ */
+OLM_EXPORT OlmOutboundGroupSession * olm_outbound_group_session(
+ void *memory
+);
+
+/**
+ * A null terminated string describing the most recent error to happen to a
+ * group session */
+OLM_EXPORT const char *olm_outbound_group_session_last_error(
+ const OlmOutboundGroupSession *session
+);
+
+/**
+ * An error code describing the most recent error to happen to a group
+ * session */
+OLM_EXPORT enum OlmErrorCode olm_outbound_group_session_last_error_code(
+ const OlmOutboundGroupSession *session
+);
+
+/** Clears the memory used to back this group session */
+OLM_EXPORT size_t olm_clear_outbound_group_session(
+ OlmOutboundGroupSession *session
+);
+
+/** Returns the number of bytes needed to store an outbound group session */
+OLM_EXPORT size_t olm_pickle_outbound_group_session_length(
+ const OlmOutboundGroupSession *session
+);
+
+/**
+ * Stores a group session as a base64 string. Encrypts the session using the
+ * supplied key. Returns the length of the session on success.
+ *
+ * Returns olm_error() on failure. If the pickle output buffer
+ * is smaller than olm_pickle_outbound_group_session_length() then
+ * olm_outbound_group_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL"
+ */
+OLM_EXPORT size_t olm_pickle_outbound_group_session(
+ OlmOutboundGroupSession *session,
+ void const * key, size_t key_length,
+ void * pickled, size_t pickled_length
+);
+
+/**
+ * Loads a group 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_outbound_group_session_last_error() will be
+ * "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then
+ * olm_outbound_group_session_last_error() will be "INVALID_BASE64". The input
+ * pickled buffer is destroyed
+ */
+OLM_EXPORT size_t olm_unpickle_outbound_group_session(
+ OlmOutboundGroupSession *session,
+ void const * key, size_t key_length,
+ void * pickled, size_t pickled_length
+);
+
+
+/** The number of random bytes needed to create an outbound group session */
+OLM_EXPORT size_t olm_init_outbound_group_session_random_length(
+ const OlmOutboundGroupSession *session
+);
+
+/**
+ * Start a new outbound group session. Returns olm_error() 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 was too small.
+ */
+OLM_EXPORT size_t olm_init_outbound_group_session(
+ OlmOutboundGroupSession *session,
+ uint8_t *random, size_t random_length
+);
+
+/**
+ * The number of bytes that will be created by encrypting a message
+ */
+OLM_EXPORT size_t olm_group_encrypt_message_length(
+ OlmOutboundGroupSession *session,
+ size_t plaintext_length
+);
+
+/**
+ * Encrypt some plain-text. Returns the length of the encrypted message or
+ * olm_error() on failure. On failure last_error will be set with an
+ * error code. The last_error will be OUTPUT_BUFFER_TOO_SMALL if the output
+ * buffer is too small.
+ */
+OLM_EXPORT size_t olm_group_encrypt(
+ OlmOutboundGroupSession *session,
+ uint8_t const * plaintext, size_t plaintext_length,
+ uint8_t * message, size_t message_length
+);
+
+
+/**
+ * Get the number of bytes returned by olm_outbound_group_session_id()
+ */
+OLM_EXPORT size_t olm_outbound_group_session_id_length(
+ const OlmOutboundGroupSession *session
+);
+
+/**
+ * Get a base64-encoded identifier for this session.
+ *
+ * Returns the length of the session id on success or olm_error() on
+ * failure. On failure last_error will be set with an error code. The
+ * last_error will be OUTPUT_BUFFER_TOO_SMALL if the id buffer was too
+ * small.
+ */
+OLM_EXPORT size_t olm_outbound_group_session_id(
+ OlmOutboundGroupSession *session,
+ uint8_t * id, size_t id_length
+);
+
+/**
+ * Get the current message index for this session.
+ *
+ * Each message is sent with an increasing index; this returns the index for
+ * the next message.
+ */
+OLM_EXPORT uint32_t olm_outbound_group_session_message_index(
+ OlmOutboundGroupSession *session
+);
+
+/**
+ * Get the number of bytes returned by olm_outbound_group_session_key()
+ */
+OLM_EXPORT size_t olm_outbound_group_session_key_length(
+ const OlmOutboundGroupSession *session
+);
+
+/**
+ * Get the base64-encoded current ratchet key for this session.
+ *
+ * Each message is sent with a different ratchet key. This function returns the
+ * ratchet key that will be used for the next message.
+ *
+ * Returns the length of the ratchet key on success or olm_error() on
+ * failure. On failure last_error will be set with an error code. The
+ * last_error will be OUTPUT_BUFFER_TOO_SMALL if the buffer was too small.
+ */
+OLM_EXPORT size_t olm_outbound_group_session_key(
+ OlmOutboundGroupSession *session,
+ uint8_t * key, size_t key_length
+);
+
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* OLM_OUTBOUND_GROUP_SESSION_H_ */
diff --git a/ext/olm/include/olm/pickle.h b/ext/olm/include/olm/pickle.h
new file mode 100644
index 0000000..d62c371
--- /dev/null
+++ b/ext/olm/include/olm/pickle.h
@@ -0,0 +1,107 @@
+/* Copyright 2015-2016 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_H_
+#define OLM_PICKLE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/* 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)
+#endif
+
+/* Convenience macro for failing on corrupted pickles from public
+ * API unpickling functions. */
+#define FAIL_ON_CORRUPTED_PICKLE(pos, session) \
+ do { \
+ if (!pos) { \
+ session->last_error = OLM_CORRUPTED_PICKLE; \
+ return (size_t)-1; \
+ } \
+ } while(0)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _olm_ed25519_public_key;
+struct _olm_ed25519_key_pair;
+
+
+#define _olm_pickle_uint32_length(value) 4
+uint8_t * _olm_pickle_uint32(uint8_t * pos, uint32_t value);
+uint8_t const * _olm_unpickle_uint32(
+ uint8_t const * pos, uint8_t const * end,
+ uint32_t *value
+);
+
+
+#define _olm_pickle_bool_length(value) 1
+uint8_t * _olm_pickle_bool(uint8_t * pos, int value);
+uint8_t const * _olm_unpickle_bool(
+ uint8_t const * pos, uint8_t const * end,
+ int *value
+);
+
+#define _olm_pickle_bytes_length(bytes, bytes_length) (bytes_length)
+uint8_t * _olm_pickle_bytes(uint8_t * pos, uint8_t const * bytes,
+ size_t bytes_length);
+uint8_t const * _olm_unpickle_bytes(uint8_t const * pos, uint8_t const * end,
+ uint8_t * bytes, size_t bytes_length);
+
+
+/** Get the number of bytes needed to pickle an ed25519 public key */
+size_t _olm_pickle_ed25519_public_key_length(
+ const struct _olm_ed25519_public_key * value
+);
+
+/** Pickle the ed25519 public key. Returns a pointer to the next free space in
+ * the buffer. */
+uint8_t * _olm_pickle_ed25519_public_key(
+ uint8_t *pos, const struct _olm_ed25519_public_key * value
+);
+
+/** Unpickle the ed25519 public key. Returns a pointer to the next item in the
+ * buffer on success, NULL on error. */
+const uint8_t * _olm_unpickle_ed25519_public_key(
+ const uint8_t *pos, const uint8_t *end,
+ struct _olm_ed25519_public_key * value
+);
+
+/** Get the number of bytes needed to pickle an ed25519 key pair */
+size_t _olm_pickle_ed25519_key_pair_length(
+ const struct _olm_ed25519_key_pair * value
+);
+
+/** Pickle the ed25519 key pair. Returns a pointer to the next free space in
+ * the buffer. */
+uint8_t * _olm_pickle_ed25519_key_pair(
+ uint8_t *pos, const struct _olm_ed25519_key_pair * value
+);
+
+/** Unpickle the ed25519 key pair. Returns a pointer to the next item in the
+ * buffer on success, NULL on error. */
+const uint8_t * _olm_unpickle_ed25519_key_pair(
+ const uint8_t *pos, const uint8_t *end,
+ struct _olm_ed25519_key_pair * value
+);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* OLM_PICKLE_H */
diff --git a/ext/olm/include/olm/pickle.hh b/ext/olm/include/olm/pickle.hh
new file mode 100644
index 0000000..f8d41b6
--- /dev/null
+++ b/ext/olm/include/olm/pickle.hh
@@ -0,0 +1,182 @@
+/* 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.h"
+
+#include <cstring>
+#include <cstdint>
+
+/* 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 nullptr; } while(0)
+#endif
+
+namespace olm {
+
+inline std::size_t pickle_length(
+ const std::uint32_t & value
+) {
+ return 4;
+}
+
+std::uint8_t * pickle(
+ std::uint8_t * pos,
+ std::uint32_t value
+);
+
+std::uint8_t const * unpickle(
+ std::uint8_t const * pos, std::uint8_t const * end,
+ std::uint32_t & value
+);
+
+
+inline std::size_t pickle_length(
+ const std::uint8_t & value
+) {
+ return 1;
+}
+
+std::uint8_t * pickle(
+ std::uint8_t * pos,
+ std::uint8_t value
+);
+
+std::uint8_t const * unpickle(
+ std::uint8_t const * pos, std::uint8_t const * end,
+ std::uint8_t & value
+);
+
+
+inline std::size_t pickle_length(
+ const bool & value
+) {
+ return 1;
+}
+
+std::uint8_t * pickle(
+ std::uint8_t * pos,
+ bool value
+);
+
+std::uint8_t const * unpickle(
+ std::uint8_t const * pos, std::uint8_t const * end,
+ bool & value
+);
+
+
+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);
+ if (!pos) {
+ return nullptr;
+ }
+
+ while (size-- && pos != end) {
+ T * value = list.insert(list.end());
+ pos = unpickle(pos, end, *value);
+
+ if (!pos) {
+ return nullptr;
+ }
+ }
+
+ return pos;
+}
+
+
+std::uint8_t * pickle_bytes(
+ std::uint8_t * pos,
+ std::uint8_t const * bytes, std::size_t bytes_length
+);
+
+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
+);
+
+
+std::size_t pickle_length(
+ const _olm_curve25519_public_key & value
+);
+
+
+std::uint8_t * pickle(
+ std::uint8_t * pos,
+ const _olm_curve25519_public_key & value
+);
+
+
+std::uint8_t const * unpickle(
+ std::uint8_t const * pos, std::uint8_t const * end,
+ _olm_curve25519_public_key & value
+);
+
+
+std::size_t pickle_length(
+ const _olm_curve25519_key_pair & value
+);
+
+
+std::uint8_t * pickle(
+ std::uint8_t * pos,
+ const _olm_curve25519_key_pair & value
+);
+
+
+std::uint8_t const * unpickle(
+ std::uint8_t const * pos, std::uint8_t const * end,
+ _olm_curve25519_key_pair & value
+);
+
+} // namespace olm
+
+
+
+
+#endif /* OLM_PICKLE_HH */
diff --git a/ext/olm/include/olm/pickle_encoding.h b/ext/olm/include/olm/pickle_encoding.h
new file mode 100644
index 0000000..ec2a2d6
--- /dev/null
+++ b/ext/olm/include/olm/pickle_encoding.h
@@ -0,0 +1,80 @@
+/* Copyright 2016 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.
+ */
+
+/* functions for encrypting and decrypting pickled representations of objects */
+
+#ifndef OLM_PICKLE_ENCODING_H_
+#define OLM_PICKLE_ENCODING_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "olm/error.h"
+
+// Note: exports in this file are only for unit tests. Nobody else should be
+// using this externally
+#include "olm/olm_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * Get the number of bytes needed to encode a pickle of the length given
+ */
+OLM_EXPORT size_t _olm_enc_output_length(size_t raw_length);
+
+/**
+ * Get the point in the output buffer that the raw pickle should be written to.
+ *
+ * In order that we can use the same buffer for the raw pickle, and the encoded
+ * pickle, the raw pickle needs to be written at the end of the buffer. (The
+ * base-64 encoding would otherwise overwrite the end of the input before it
+ * was encoded.)
+ */
+OLM_EXPORT uint8_t *_olm_enc_output_pos(uint8_t * output, size_t raw_length);
+
+/**
+ * Encrypt and encode the given pickle in-situ.
+ *
+ * The raw pickle should have been written to enc_output_pos(pickle,
+ * raw_length).
+ *
+ * Returns the number of bytes in the encoded pickle.
+ */
+OLM_EXPORT size_t _olm_enc_output(
+ uint8_t const * key, size_t key_length,
+ uint8_t *pickle, size_t raw_length
+);
+
+/**
+ * Decode and decrypt the given pickle in-situ.
+ *
+ * Returns the number of bytes in the decoded pickle, or olm_error() on error,
+ * in which case *last_error will be updated, if last_error is non-NULL.
+ */
+OLM_EXPORT size_t _olm_enc_input(
+ uint8_t const * key, size_t key_length,
+ uint8_t * input, size_t b64_length,
+ enum OlmErrorCode * last_error
+);
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* OLM_PICKLE_ENCODING_H_ */
diff --git a/ext/olm/include/olm/pk.h b/ext/olm/include/olm/pk.h
new file mode 100644
index 0000000..b3670fe
--- /dev/null
+++ b/ext/olm/include/olm/pk.h
@@ -0,0 +1,298 @@
+/* Copyright 2018, 2019 New Vector 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_PK_H_
+#define OLM_PK_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "olm/error.h"
+
+#include "olm/olm_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct OlmPkEncryption OlmPkEncryption;
+
+/* The size of an encryption object in bytes */
+OLM_EXPORT size_t olm_pk_encryption_size(void);
+
+/** Initialise an encryption object using the supplied memory
+ * The supplied memory must be at least olm_pk_encryption_size() bytes */
+OLM_EXPORT OlmPkEncryption *olm_pk_encryption(
+ void * memory
+);
+
+/** A null terminated string describing the most recent error to happen to an
+ * encryption object */
+OLM_EXPORT const char * olm_pk_encryption_last_error(
+ const OlmPkEncryption * encryption
+);
+
+/** An error code describing the most recent error to happen to an encryption
+ * object */
+OLM_EXPORT enum OlmErrorCode olm_pk_encryption_last_error_code(
+ const OlmPkEncryption * encryption
+);
+
+/** Clears the memory used to back this encryption object */
+OLM_EXPORT size_t olm_clear_pk_encryption(
+ OlmPkEncryption *encryption
+);
+
+/** Set the recipient's public key for encrypting to */
+OLM_EXPORT size_t olm_pk_encryption_set_recipient_key(
+ OlmPkEncryption *encryption,
+ void const *public_key, size_t public_key_length
+);
+
+/** Get the length of the ciphertext that will correspond to a plaintext of the
+ * given length. */
+OLM_EXPORT size_t olm_pk_ciphertext_length(
+ const OlmPkEncryption *encryption,
+ size_t plaintext_length
+);
+
+/** Get the length of the message authentication code. */
+OLM_EXPORT size_t olm_pk_mac_length(
+ const OlmPkEncryption *encryption
+);
+
+/** Get the length of a public or ephemeral key */
+OLM_EXPORT size_t olm_pk_key_length(void);
+
+/** The number of random bytes needed to encrypt a message. */
+OLM_EXPORT size_t olm_pk_encrypt_random_length(
+ const OlmPkEncryption *encryption
+);
+
+/** Encrypt a plaintext for the recipient set using
+ * olm_pk_encryption_set_recipient_key. Writes to the ciphertext, mac, and
+ * ephemeral_key buffers, whose values should be sent to the recipient. mac is
+ * a Message Authentication Code to ensure that the data is received and
+ * decrypted properly. ephemeral_key is the public part of the ephemeral key
+ * used (together with the recipient's key) to generate a symmetric encryption
+ * key. Returns olm_error() on failure. If the ciphertext, mac, or
+ * ephemeral_key buffers were too small then olm_pk_encryption_last_error()
+ * will be "OUTPUT_BUFFER_TOO_SMALL". If there weren't enough random bytes then
+ * olm_pk_encryption_last_error() will be "OLM_INPUT_BUFFER_TOO_SMALL". */
+OLM_EXPORT size_t olm_pk_encrypt(
+ OlmPkEncryption *encryption,
+ void const * plaintext, size_t plaintext_length,
+ void * ciphertext, size_t ciphertext_length,
+ void * mac, size_t mac_length,
+ void * ephemeral_key, size_t ephemeral_key_size,
+ const void * random, size_t random_length
+);
+
+typedef struct OlmPkDecryption OlmPkDecryption;
+
+/* The size of a decryption object in bytes */
+OLM_EXPORT size_t olm_pk_decryption_size(void);
+
+/** Initialise a decryption object using the supplied memory
+ * The supplied memory must be at least olm_pk_decryption_size() bytes */
+OLM_EXPORT OlmPkDecryption *olm_pk_decryption(
+ void * memory
+);
+
+/** A null terminated string describing the most recent error to happen to a
+ * decription object */
+OLM_EXPORT const char * olm_pk_decryption_last_error(
+ const OlmPkDecryption * decryption
+);
+
+/** An error code describing the most recent error to happen to a decription
+ * object */
+OLM_EXPORT enum OlmErrorCode olm_pk_decryption_last_error_code(
+ const OlmPkDecryption * decryption
+);
+
+/** Clears the memory used to back this decryption object */
+OLM_EXPORT size_t olm_clear_pk_decryption(
+ OlmPkDecryption *decryption
+);
+
+/** Get the number of bytes required to store an olm private key
+ */
+OLM_EXPORT size_t olm_pk_private_key_length(void);
+
+/** DEPRECATED: Use olm_pk_private_key_length()
+ */
+OLM_EXPORT size_t olm_pk_generate_key_random_length(void);
+
+/** Initialise the key from the private part of a key as returned by
+ * olm_pk_get_private_key(). The associated public key will be written to the
+ * pubkey buffer. Returns olm_error() on failure. If the pubkey buffer is too
+ * small then olm_pk_decryption_last_error() will be "OUTPUT_BUFFER_TOO_SMALL".
+ * If the private key was not long enough then olm_pk_decryption_last_error()
+ * will be "OLM_INPUT_BUFFER_TOO_SMALL".
+ *
+ * Note that the pubkey is a base64 encoded string, but the private key is
+ * an unencoded byte array
+ */
+OLM_EXPORT size_t olm_pk_key_from_private(
+ OlmPkDecryption * decryption,
+ void * pubkey, size_t pubkey_length,
+ const void * privkey, size_t privkey_length
+);
+
+/** DEPRECATED: Use olm_pk_key_from_private
+ */
+OLM_EXPORT size_t olm_pk_generate_key(
+ OlmPkDecryption * decryption,
+ void * pubkey, size_t pubkey_length,
+ const void * privkey, size_t privkey_length
+);
+
+/** Returns the number of bytes needed to store a decryption object. */
+OLM_EXPORT size_t olm_pickle_pk_decryption_length(
+ const OlmPkDecryption * decryption
+);
+
+/** Stores decryption object as a base64 string. Encrypts the object using the
+ * supplied key. Returns the length of the pickled object on success.
+ * Returns olm_error() on failure. If the pickle output buffer
+ * is smaller than olm_pickle_pk_decryption_length() then
+ * olm_pk_decryption_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */
+OLM_EXPORT size_t olm_pickle_pk_decryption(
+ OlmPkDecryption * decryption,
+ void const * key, size_t key_length,
+ void *pickled, size_t pickled_length
+);
+
+/** Loads a decryption object from a pickled base64 string. The associated
+ * public key will be written to the pubkey buffer. Decrypts the object using
+ * the supplied key. Returns olm_error() on failure. If the key doesn't
+ * match the one used to encrypt the account then olm_pk_decryption_last_error()
+ * will be "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then
+ * olm_pk_decryption_last_error() will be "INVALID_BASE64". The input pickled
+ * buffer is destroyed */
+OLM_EXPORT size_t olm_unpickle_pk_decryption(
+ OlmPkDecryption * decryption,
+ void const * key, size_t key_length,
+ void *pickled, size_t pickled_length,
+ void *pubkey, size_t pubkey_length
+);
+
+/** Get the length of the plaintext that will correspond to a ciphertext of the
+ * given length. */
+OLM_EXPORT size_t olm_pk_max_plaintext_length(
+ const OlmPkDecryption * decryption,
+ size_t ciphertext_length
+);
+
+/** Decrypt a ciphertext. The input ciphertext buffer is destroyed. See the
+ * olm_pk_encrypt function for descriptions of the ephemeral_key and mac
+ * arguments. Returns the length of the plaintext on success. Returns
+ * olm_error() on failure. If the plaintext buffer is too small then
+ * olm_pk_encryption_last_error() will be "OUTPUT_BUFFER_TOO_SMALL". */
+OLM_EXPORT size_t olm_pk_decrypt(
+ OlmPkDecryption * decryption,
+ void const * ephemeral_key, size_t ephemeral_key_length,
+ void const * mac, size_t mac_length,
+ void * ciphertext, size_t ciphertext_length,
+ void * plaintext, size_t max_plaintext_length
+);
+
+/**
+ * Get the private key for an OlmDecryption object as an unencoded byte array
+ * private_key must be a pointer to a buffer of at least
+ * olm_pk_private_key_length() bytes and this length must be passed in
+ * private_key_length. If the given buffer is too small, returns olm_error()
+ * and olm_pk_encryption_last_error() will be "OUTPUT_BUFFER_TOO_SMALL".
+ * Returns the number of bytes written.
+ */
+OLM_EXPORT size_t olm_pk_get_private_key(
+ OlmPkDecryption * decryption,
+ void *private_key, size_t private_key_length
+);
+
+typedef struct OlmPkSigning OlmPkSigning;
+
+/* The size of a signing object in bytes */
+OLM_EXPORT size_t olm_pk_signing_size(void);
+
+/** Initialise a signing object using the supplied memory
+ * The supplied memory must be at least olm_pk_signing_size() bytes */
+OLM_EXPORT OlmPkSigning *olm_pk_signing(
+ void * memory
+);
+
+/** A null terminated string describing the most recent error to happen to a
+ * signing object */
+OLM_EXPORT const char * olm_pk_signing_last_error(
+ const OlmPkSigning * sign
+);
+
+/** A null terminated string describing the most recent error to happen to a
+ * signing object */
+OLM_EXPORT enum OlmErrorCode olm_pk_signing_last_error_code(
+ const OlmPkSigning * sign
+);
+
+/** Clears the memory used to back this signing object */
+OLM_EXPORT size_t olm_clear_pk_signing(
+ OlmPkSigning *sign
+);
+
+/**
+ * Initialise the signing object with a public/private keypair from a seed. The
+ * associated public key will be written to the pubkey buffer. Returns
+ * olm_error() on failure. If the public key buffer is too small then
+ * olm_pk_signing_last_error() will be "OUTPUT_BUFFER_TOO_SMALL". If the seed
+ * buffer is too small then olm_pk_signing_last_error() will be
+ * "INPUT_BUFFER_TOO_SMALL".
+ */
+OLM_EXPORT size_t olm_pk_signing_key_from_seed(
+ OlmPkSigning * sign,
+ void * pubkey, size_t pubkey_length,
+ const void * seed, size_t seed_length
+);
+
+/**
+ * The size required for the seed for initialising a signing object.
+ */
+OLM_EXPORT size_t olm_pk_signing_seed_length(void);
+
+/**
+ * The size of the public key of a signing object.
+ */
+OLM_EXPORT size_t olm_pk_signing_public_key_length(void);
+
+/**
+ * The size of a signature created by a signing object.
+ */
+OLM_EXPORT size_t olm_pk_signature_length(void);
+
+/**
+ * Sign a message. The signature will be written to the signature
+ * buffer. Returns olm_error() on failure. If the signature buffer is too
+ * small, olm_pk_signing_last_error() will be "OUTPUT_BUFFER_TOO_SMALL".
+ */
+OLM_EXPORT size_t olm_pk_sign(
+ OlmPkSigning *sign,
+ uint8_t const * message, size_t message_length,
+ uint8_t * signature, size_t signature_length
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OLM_PK_H_ */
diff --git a/ext/olm/include/olm/ratchet.hh b/ext/olm/include/olm/ratchet.hh
new file mode 100644
index 0000000..2ada0eb
--- /dev/null
+++ b/ext/olm/include/olm/ratchet.hh
@@ -0,0 +1,188 @@
+/* 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 <cstdint>
+
+#include "olm/crypto.h"
+#include "olm/list.hh"
+#include "olm/error.h"
+
+// Note: exports in this file are only for unit tests. Nobody else should be
+// using this externally
+#include "olm/olm_export.h"
+
+struct _olm_cipher;
+
+namespace olm {
+
+/** length of a shared key: the root key R(i), chain key C(i,j), and message key
+ * M(i,j)). They are all only used to stuff into HMACs, so could be any length
+ * for that. The chain key and message key are both derived from SHA256
+ * operations, so their length is determined by that. */
+const std::size_t OLM_SHARED_KEY_LENGTH = SHA256_OUTPUT_LENGTH;
+
+typedef std::uint8_t SharedKey[OLM_SHARED_KEY_LENGTH];
+
+struct ChainKey {
+ std::uint32_t index;
+ SharedKey key;
+};
+
+struct MessageKey {
+ std::uint32_t index;
+ SharedKey key;
+};
+
+
+struct SenderChain {
+ _olm_curve25519_key_pair ratchet_key;
+ ChainKey chain_key;
+};
+
+
+struct ReceiverChain {
+ _olm_curve25519_public_key ratchet_key;
+ ChainKey chain_key;
+};
+
+
+struct SkippedMessageKey {
+ _olm_curve25519_public_key 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 OLM_EXPORT Ratchet {
+
+ Ratchet(
+ KdfInfo const & kdf_info,
+ _olm_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. */
+ _olm_cipher const *ratchet_cipher;
+
+ /** The last error that happened encrypting or decrypting a message. */
+ OlmErrorCode last_error;
+
+ /** The root key is used to generate chain keys from the ephemeral keys.
+ * A new root_key derived each time a new chain is started. */
+ 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 ephemeral 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,
+ _olm_curve25519_public_key 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,
+ _olm_curve25519_key_pair 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
+ ) const;
+
+ /** 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() const;
+
+ /** 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,
+ bool includes_chain_index
+);
+
+
+} // namespace olm
diff --git a/ext/olm/include/olm/sas.h b/ext/olm/include/olm/sas.h
new file mode 100644
index 0000000..df5a1f5
--- /dev/null
+++ b/ext/olm/include/olm/sas.h
@@ -0,0 +1,197 @@
+/* Copyright 2018-2019 New Vector 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_SAS_H_
+#define OLM_SAS_H_
+
+#include <stddef.h>
+
+#include "olm/error.h"
+
+#include "olm/olm_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup SAS Short Authentication String verification
+ * These functions are used for verifying keys using the Short Authentication
+ * String (SAS) method.
+ * @{
+ */
+
+typedef struct OlmSAS OlmSAS;
+
+/** A null terminated string describing the most recent error to happen to an
+ * SAS object. */
+OLM_EXPORT const char * olm_sas_last_error(
+ const OlmSAS * sas
+);
+
+/** An error code describing the most recent error to happen to an SAS
+ * object. */
+OLM_EXPORT enum OlmErrorCode olm_sas_last_error_code(
+ const OlmSAS * sas
+);
+
+/** The size of an SAS object in bytes. */
+OLM_EXPORT size_t olm_sas_size(void);
+
+/** Initialize an SAS object using the supplied memory.
+ * The supplied memory must be at least `olm_sas_size()` bytes. */
+OLM_EXPORT OlmSAS * olm_sas(
+ void * memory
+);
+
+/** Clears the memory used to back an SAS object. */
+OLM_EXPORT size_t olm_clear_sas(
+ OlmSAS * sas
+);
+
+/** The number of random bytes needed to create an SAS object. */
+OLM_EXPORT size_t olm_create_sas_random_length(
+ const OlmSAS * sas
+);
+
+/** Creates a new SAS object.
+ *
+ * @param[in] sas the SAS object to create, initialized by `olm_sas()`.
+ * @param[in] random array of random bytes. The contents of the buffer may be
+ * overwritten.
+ * @param[in] random_length the number of random bytes provided. Must be at
+ * least `olm_create_sas_random_length()`.
+ *
+ * @return `olm_error()` on failure. If there weren't enough random bytes then
+ * `olm_sas_last_error()` will be `NOT_ENOUGH_RANDOM`.
+ */
+OLM_EXPORT size_t olm_create_sas(
+ OlmSAS * sas,
+ void * random, size_t random_length
+);
+
+/** The size of a public key in bytes. */
+OLM_EXPORT size_t olm_sas_pubkey_length(const OlmSAS * sas);
+
+/** Get the public key for the SAS object.
+ *
+ * @param[in] sas the SAS object.
+ * @param[out] pubkey buffer to store the public key.
+ * @param[in] pubkey_length the size of the `pubkey` buffer. Must be at least
+ * `olm_sas_pubkey_length()`.
+ *
+ * @return `olm_error()` on failure. If the `pubkey` buffer is too small, then
+ * `olm_sas_last_error()` will be `OUTPUT_BUFFER_TOO_SMALL`.
+ */
+OLM_EXPORT size_t olm_sas_get_pubkey(
+ OlmSAS * sas,
+ void * pubkey, size_t pubkey_length
+);
+
+/** Sets the public key of other user.
+ *
+ * @param[in] sas the SAS object.
+ * @param[in] their_key the other user's public key. The contents of the
+ * buffer will be overwritten.
+ * @param[in] their_key_length the size of the `their_key` buffer.
+ *
+ * @return `olm_error()` on failure. If the `their_key` buffer is too small,
+ * then `olm_sas_last_error()` will be `INPUT_BUFFER_TOO_SMALL`.
+ */
+OLM_EXPORT size_t olm_sas_set_their_key(
+ OlmSAS *sas,
+ void * their_key, size_t their_key_length
+);
+
+/** Checks if their key was set.
+ *
+ * @param[in] sas the SAS object.
+ *
+ */
+OLM_EXPORT int olm_sas_is_their_key_set(
+ const OlmSAS *sas
+);
+
+/** Generate bytes to use for the short authentication string.
+ *
+ * @param[in] sas the SAS object.
+ * @param[in] info extra information to mix in when generating the bytes, as
+ * per the Matrix spec.
+ * @param[in] info_length the length of the `info` parameter.
+ * @param[out] output the output buffer.
+ * @param[in] output_length the size of the output buffer. For hex-based SAS
+ * as in the Matrix spec, this will be 5.
+ *
+ * @return `olm_error()` on failure. If their key wasn't set then
+ * `olm_sas_last_error()` will be `SAS_THEIR_KEY_NOT_SET`.
+ */
+OLM_EXPORT size_t olm_sas_generate_bytes(
+ OlmSAS * sas,
+ const void * info, size_t info_length,
+ void * output, size_t output_length
+);
+
+/** The size of the message authentication code generated by
+ * olm_sas_calculate_mac()`. */
+OLM_EXPORT size_t olm_sas_mac_length(
+ const OlmSAS *sas
+);
+
+/** Generate a message authentication code (MAC) based on the shared secret.
+ *
+ * @param[in] sas the SAS object.
+ * @param[in] input the message to produce the authentication code for.
+ * @param[in] input_length the length of the message.
+ * @param[in] info extra information to mix in when generating the MAC, as per
+ * the Matrix spec.
+ * @param[in] info_length the length of the `info` parameter.
+ * @param[out] mac the buffer in which to store the MAC.
+ * @param[in] mac_length the size of the `mac` buffer. Must be at least
+ * `olm_sas_mac_length()`
+ *
+ * @return `olm_error()` on failure. If the `mac` buffer is too small, then
+ * `olm_sas_last_error()` will be `OUTPUT_BUFFER_TOO_SMALL`.
+ */
+OLM_EXPORT size_t olm_sas_calculate_mac(
+ OlmSAS * sas,
+ const void * input, size_t input_length,
+ const void * info, size_t info_length,
+ void * mac, size_t mac_length
+);
+
+// A version of the calculate mac function that produces base64 strings that are
+// compatible with other base64 implementations.
+OLM_EXPORT size_t olm_sas_calculate_mac_fixed_base64(
+ OlmSAS * sas,
+ const void * input, size_t input_length,
+ const void * info, size_t info_length,
+ void * mac, size_t mac_length
+);
+
+// for compatibility with an old version of Riot
+OLM_EXPORT size_t olm_sas_calculate_mac_long_kdf(
+ OlmSAS * sas,
+ const void * input, size_t input_length,
+ const void * info, size_t info_length,
+ void * mac, size_t mac_length
+);
+
+/** @} */ // end of SAS group
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* OLM_SAS_H_ */
diff --git a/ext/olm/include/olm/session.hh b/ext/olm/include/olm/session.hh
new file mode 100644
index 0000000..41300db
--- /dev/null
+++ b/ext/olm/include/olm/session.hh
@@ -0,0 +1,168 @@
+/* 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"
+
+// Note: exports in this file are only for unit tests. Nobody else should be
+// using this externally
+#include "olm/olm_export.h"
+
+namespace olm {
+
+struct Account;
+
+enum struct MessageType {
+ PRE_KEY = 0,
+ MESSAGE = 1,
+};
+
+struct OLM_EXPORT Session {
+
+ Session();
+
+ Ratchet ratchet;
+ OlmErrorCode last_error;
+
+ bool received_message;
+
+ _olm_curve25519_public_key alice_identity_key;
+ _olm_curve25519_public_key alice_base_key;
+ _olm_curve25519_public_key bob_one_time_key;
+
+ /** The number of random bytes that are needed to create a new outbound
+ * session. This will be 64 bytes since two ephemeral keys are needed. */
+ std::size_t new_outbound_session_random_length() const;
+
+ /** Start a new outbound session. Returns 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 was too small. */
+ std::size_t new_outbound_session(
+ Account const & local_account,
+ _olm_curve25519_public_key const & identity_key,
+ _olm_curve25519_public_key const & one_time_key,
+ std::uint8_t const * random, std::size_t random_length
+ );
+
+ /** Start a new inbound session from a pre-key message.
+ * Returns std::size_t(-1) on failure. On failure last_error will be set
+ * with an error code. The last_error will be BAD_MESSAGE_FORMAT if
+ * the message headers could not be decoded. */
+ std::size_t new_inbound_session(
+ Account & local_account,
+ _olm_curve25519_public_key const * their_identity_key,
+ std::uint8_t const * pre_key_message, std::size_t message_length
+ );
+
+ /** The number of bytes written by session_id() */
+ std::size_t session_id_length() const;
+
+ /** An identifier for this session. Generated by hashing the public keys
+ * used to create the session. Returns the length of the session id on
+ * success 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 id buffer was too small. */
+ std::size_t session_id(
+ std::uint8_t * id, std::size_t id_length
+ );
+
+ /** True if this session can be used to decode an inbound pre-key message.
+ * This can be used to test whether a pre-key message should be decoded
+ * with an existing session or if a new session will need to be created.
+ * Returns true if the session is the same. Returns false if either the
+ * session does not match or the pre-key message could not be decoded.
+ */
+ bool matches_inbound_session(
+ _olm_curve25519_public_key const * their_identity_key,
+ std::uint8_t const * pre_key_message, std::size_t message_length
+ ) const;
+
+ /** Whether the next message will be a pre-key message or a normal message.
+ * An outbound session will send pre-key messages until it receives a
+ * message with a ratchet key. */
+ MessageType encrypt_message_type() const;
+
+ std::size_t encrypt_message_length(
+ std::size_t plaintext_length
+ ) const;
+
+ /** 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() const;
+
+ /** 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 * message, std::size_t message_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(
+ MessageType message_type,
+ std::uint8_t const * message, std::size_t message_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(
+ MessageType message_type,
+ std::uint8_t const * message, std::size_t message_length,
+ std::uint8_t * plaintext, std::size_t max_plaintext_length
+ );
+
+ /**
+ * Write a string describing this session and its state (not including the
+ * private key) into the buffer provided.
+ *
+ * Takes a buffer to write to and the length of that buffer
+ */
+ void describe(char *buf, size_t buflen);
+};
+
+
+std::size_t pickle_length(
+ Session const & value
+);
+
+
+std::uint8_t * pickle(
+ std::uint8_t * pos,
+ Session const & value
+);
+
+
+OLM_EXPORT std::uint8_t const * unpickle(
+ std::uint8_t const * pos, std::uint8_t const * end,
+ Session & value
+);
+
+
+} // namespace olm
+
+#endif /* OLM_SESSION_HH_ */
diff --git a/ext/olm/include/olm/utility.hh b/ext/olm/include/olm/utility.hh
new file mode 100644
index 0000000..3e5f5b7
--- /dev/null
+++ b/ext/olm/include/olm/utility.hh
@@ -0,0 +1,61 @@
+/* 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 UTILITY_HH_
+#define UTILITY_HH_
+
+#include "olm/error.h"
+
+#include <cstddef>
+#include <cstdint>
+
+struct _olm_ed25519_public_key;
+
+namespace olm {
+
+struct Utility {
+
+ Utility();
+
+ OlmErrorCode last_error;
+
+ /** The length of a SHA-256 hash in bytes. */
+ std::size_t sha256_length() const;
+
+ /** Compute a SHA-256 hash. Returns the length of the SHA-256 hash in bytes
+ * on success. Returns std::size_t(-1) on failure. On failure last_error
+ * will be set with an error code. If the output buffer was too small then
+ * last error will be OUTPUT_BUFFER_TOO_SMALL. */
+ std::size_t sha256(
+ std::uint8_t const * input, std::size_t input_length,
+ std::uint8_t * output, std::size_t output_length
+ );
+
+ /** Verify a ed25519 signature. Returns std::size_t(0) on success. Returns
+ * std::size_t(-1) on failure or if the signature was invalid. On failure
+ * last_error will be set with an error code. If the signature was too short
+ * or was not a valid signature then last_error will be BAD_MESSAGE_MAC. */
+ std::size_t ed25519_verify(
+ _olm_ed25519_public_key const & key,
+ std::uint8_t const * message, std::size_t message_length,
+ std::uint8_t const * signature, std::size_t signature_length
+ );
+
+};
+
+
+} // namespace olm
+
+#endif /* UTILITY_HH_ */