From a22cffdd2926c0785f969872a4c1245d203294cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Helge=20He=C3=9F?= Date: Fri, 10 Apr 2020 18:50:34 +0200 Subject: [PATCH] Separate C from C++ headers for SPM Swift can't import C++, so we need to remove it from the module. --- Package.swift | 4 +- include/public/olm/base64.h | 77 ++++ include/public/olm/cipher.h | 138 ++++++ include/public/olm/crypto.h | 202 +++++++++ include/public/olm/error.h | 72 +++ include/public/olm/inbound_group_session.h | 235 ++++++++++ include/public/olm/list.hh | 119 +++++ include/public/olm/megolm.h | 95 ++++ include/public/olm/memory.h | 41 ++ include/public/olm/message.h | 93 ++++ include/public/olm/olm.h | 457 ++++++++++++++++++++ include/public/olm/outbound_group_session.h | 181 ++++++++ include/public/olm/pickle.h | 90 ++++ include/public/olm/pickle_encoding.h | 76 ++++ include/public/olm/pk.h | 276 ++++++++++++ include/public/olm/sas.h | 166 +++++++ 16 files changed, 2321 insertions(+), 1 deletion(-) create mode 100644 include/public/olm/base64.h create mode 100644 include/public/olm/cipher.h create mode 100644 include/public/olm/crypto.h create mode 100644 include/public/olm/error.h create mode 100644 include/public/olm/inbound_group_session.h create mode 100644 include/public/olm/list.hh create mode 100644 include/public/olm/megolm.h create mode 100644 include/public/olm/memory.h create mode 100644 include/public/olm/message.h create mode 100644 include/public/olm/olm.h create mode 100644 include/public/olm/outbound_group_session.h create mode 100644 include/public/olm/pickle.h create mode 100644 include/public/olm/pickle_encoding.h create mode 100644 include/public/olm/pk.h create mode 100644 include/public/olm/sas.h diff --git a/Package.swift b/Package.swift index c2e1d8a..96e6c67 100644 --- a/Package.swift +++ b/Package.swift @@ -20,12 +20,14 @@ let package = Package( "lib/crypto-algorithms/sha256.c", "lib/curve25519-donna/curve25519-donna.c" ], - publicHeadersPath: "include", + //publicHeadersPath: "include", + publicHeadersPath: "include/public", cSettings: [ .define("OLMLIB_VERSION_MAJOR", to: String(version.major)), .define("OLMLIB_VERSION_MINOR", to: String(version.minor)), .define("OLMLIB_VERSION_PATCH", to: String(version.patch)), .headerSearchPath("lib"), + .headerSearchPath("include"), .unsafeFlags([ "-Wall", "-Werror" ]) ] ), diff --git a/include/public/olm/base64.h b/include/public/olm/base64.h new file mode 100644 index 0000000..80384a8 --- /dev/null +++ b/include/public/olm/base64.h @@ -0,0 +1,77 @@ +/* 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 +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * The number of bytes of unpadded base64 needed to encode a length of input. + */ +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 + */ +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. + */ +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 + */ +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/include/public/olm/cipher.h b/include/public/olm/cipher.h new file mode 100644 index 0000000..f0f3033 --- /dev/null +++ b/include/public/olm/cipher.h @@ -0,0 +1,138 @@ +/* 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 +#include + +#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; +}; + +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/include/public/olm/crypto.h b/include/public/olm/crypto.h new file mode 100644 index 0000000..dbf78ed --- /dev/null +++ b/include/public/olm/crypto.h @@ -0,0 +1,202 @@ +/* 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_ + +#include +#include + +#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 */ +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 */ +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. + */ +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. */ +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. */ +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. */ +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. + */ +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. + */ +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. + */ +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. */ +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. */ +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/include/public/olm/error.h b/include/public/olm/error.h new file mode 100644 index 0000000..ee2187c --- /dev/null +++ b/include/public/olm/error.h @@ -0,0 +1,72 @@ +/* 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_ + +#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, + + // Not an error code, just here to pad out the enum past 16 because + // otherwise the compiler warns about a redunant check. If you're + // adding an error code, replace this one! + OLM_ERROR_NOT_INVENTED_YET = 16, + + /* remember to update the list of string constants in error.c when updating + * this list. */ +}; + +/** get a string representation of the given error code. */ +const char * _olm_error_to_string(enum OlmErrorCode error); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* OLM_ERROR_H_ */ diff --git a/include/public/olm/inbound_group_session.h b/include/public/olm/inbound_group_session.h new file mode 100644 index 0000000..9b2f9df --- /dev/null +++ b/include/public/olm/inbound_group_session.h @@ -0,0 +1,235 @@ +/* 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 +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct OlmInboundGroupSession OlmInboundGroupSession; + +/** get the size of an inbound group session, in bytes. */ +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. + */ +OlmInboundGroupSession * olm_inbound_group_session( + void *memory +); + +/** + * A null terminated string describing the most recent error to happen to a + * group session */ +const char *olm_inbound_group_session_last_error( + const OlmInboundGroupSession *session +); + +/** Clears the memory used to back this group session */ +size_t olm_clear_inbound_group_session( + OlmInboundGroupSession *session +); + +/** Returns the number of bytes needed to store an inbound group session */ +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" + */ +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 + */ +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 + */ +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 + */ +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. + */ +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) + */ +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() + */ +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. + */ +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. + */ +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. + */ +int olm_inbound_group_session_is_verified( + const OlmInboundGroupSession *session +); + +/** + * Get the number of bytes returned by olm_export_inbound_group_session() + */ +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) + */ +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/include/public/olm/list.hh b/include/public/olm/list.hh new file mode 100644 index 0000000..6906c87 --- /dev/null +++ b/include/public/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 + +namespace olm { + +template +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 & operator=(List const & other) { + if (this == &other) { + return *this; + } + T * this_pos = _data; + T * const other_pos = other._data; + while (other_pos != other._end) { + *this_pos = *other; + ++this_pos; + ++other_pos; + } + _end = this_pos; + return *this; + } + +private: + T * _end; + T _data[max_size]; +}; + +} // namespace olm + +#endif /* OLM_LIST_HH_ */ diff --git a/include/public/olm/megolm.h b/include/public/olm/megolm.h new file mode 100644 index 0000000..e4e5d0b --- /dev/null +++ b/include/public/olm/megolm.h @@ -0,0 +1,95 @@ +/* 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 +#include + +#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. + */ +void megolm_init(Megolm *megolm, uint8_t const *random_data, uint32_t counter); + +/** Returns the number of bytes needed to store a megolm */ +size_t megolm_pickle_length(const Megolm *megolm); + +/** + * Pickle the megolm. Returns a pointer to the next free space in the buffer. + */ +uint8_t * megolm_pickle(const Megolm *megolm, uint8_t *pos); + +/** + * Unpickle the megolm. Returns a pointer to the next item in the buffer. + */ +const uint8_t * megolm_unpickle(Megolm *megolm, const uint8_t *pos, + const uint8_t *end); + + +/** advance the ratchet by one step */ +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 */ +void megolm_advance_to(Megolm *megolm, uint32_t advance_to); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* OLM_MEGOLM_H_ */ diff --git a/include/public/olm/memory.h b/include/public/olm/memory.h new file mode 100644 index 0000000..cc346d0 --- /dev/null +++ b/include/public/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 + +#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/include/public/olm/message.h b/include/public/olm/message.h new file mode 100644 index 0000000..61012c9 --- /dev/null +++ b/include/public/olm/message.h @@ -0,0 +1,93 @@ +/* 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 +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The length of the buffer needed to hold a group message. + */ +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. + */ +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. + */ +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/include/public/olm/olm.h b/include/public/olm/olm.h new file mode 100644 index 0000000..6a2b3fb --- /dev/null +++ b/include/public/olm/olm.h @@ -0,0 +1,457 @@ +/* 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 +#include + +#include "olm/inbound_group_session.h" +#include "olm/outbound_group_session.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. + */ +void olm_get_library_version(uint8_t *major, uint8_t *minor, uint8_t *patch); + +/** The size of an account object in bytes */ +size_t olm_account_size(void); + +/** The size of a session object in bytes */ +size_t olm_session_size(void); + +/** The size of a utility object in bytes */ +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 */ +OlmAccount * olm_account( + void * memory +); + +/** Initialise a session object using the supplied memory + * The supplied memory must be at least olm_session_size() bytes */ +OlmSession * olm_session( + void * memory +); + +/** Initialise a utility object using the supplied memory + * The supplied memory must be at least olm_utility_size() bytes */ +OlmUtility * olm_utility( + void * memory +); + +/** The value that olm will return from a function if there was an error */ +size_t olm_error(void); + +/** A null terminated string describing the most recent error to happen to an + * account */ +const char * olm_account_last_error( + OlmAccount * account +); + +/** A null terminated string describing the most recent error to happen to a + * session */ +const char * olm_session_last_error( + OlmSession * session +); + +/** A null terminated string describing the most recent error to happen to a + * utility */ +const char * olm_utility_last_error( + OlmUtility * utility +); + +/** Clears the memory used to back this account */ +size_t olm_clear_account( + OlmAccount * account +); + +/** Clears the memory used to back this session */ +size_t olm_clear_session( + OlmSession * session +); + +/** Clears the memory used to back this utility */ +size_t olm_clear_utility( + OlmUtility * utility +); + +/** Returns the number of bytes needed to store an account */ +size_t olm_pickle_account_length( + OlmAccount * account +); + +/** Returns the number of bytes needed to store a session */ +size_t olm_pickle_session_length( + OlmSession * session +); + +/** Stores an account as a base64 string. Encrypts the account using the + * supplied key. Returns the length of the pickled account on success. + * Returns olm_error() on failure. If the pickle output buffer + * is smaller than olm_pickle_account_length() then + * olm_account_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */ +size_t olm_pickle_account( + OlmAccount * account, + void const * key, size_t key_length, + void * pickled, size_t pickled_length +); + +/** Stores a session as a base64 string. Encrypts the session using the + * supplied key. Returns the length of the pickled session on success. + * Returns olm_error() on failure. If the pickle output buffer + * is smaller than olm_pickle_session_length() then + * olm_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */ +size_t olm_pickle_session( + OlmSession * session, + void const * key, size_t key_length, + void * pickled, size_t pickled_length +); + +/** Loads an account from a pickled base64 string. Decrypts the account using + * the supplied key. Returns olm_error() on failure. If the key doesn't + * match the one used to encrypt the account then olm_account_last_error() + * will be "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then + * olm_account_last_error() will be "INVALID_BASE64". The input pickled + * buffer is destroyed */ +size_t olm_unpickle_account( + OlmAccount * account, + void const * key, size_t key_length, + void * pickled, size_t pickled_length +); + +/** Loads a session from a pickled base64 string. Decrypts the session using + * the supplied key. Returns olm_error() on failure. If the key doesn't + * match the one used to encrypt the account then olm_session_last_error() + * will be "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then + * olm_session_last_error() will be "INVALID_BASE64". The input pickled + * buffer is destroyed */ +size_t olm_unpickle_session( + OlmSession * session, + void const * key, size_t key_length, + void * pickled, size_t pickled_length +); + +/** The number of random bytes needed to create an account.*/ +size_t olm_create_account_random_length( + OlmAccount * account +); + +/** Creates a new account. Returns olm_error() on failure. If there weren't + * enough random bytes then olm_account_last_error() will be + * "NOT_ENOUGH_RANDOM" */ +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 */ +size_t olm_account_identity_keys_length( + OlmAccount * account +); + +/** Writes the public parts of the identity keys for the account into the + * identity_keys output buffer. Returns olm_error() on failure. If the + * identity_keys buffer was too small then olm_account_last_error() will be + * "OUTPUT_BUFFER_TOO_SMALL". */ +size_t olm_account_identity_keys( + OlmAccount * account, + void * identity_keys, size_t identity_key_length +); + + +/** The length of an ed25519 signature encoded as base64. */ +size_t olm_account_signature_length( + OlmAccount * 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" */ +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 */ +size_t olm_account_one_time_keys_length( + OlmAccount * account +); + +/** Writes the public parts of the unpublished one time keys for the account + * into the one_time_keys output buffer. + *

+ * The returned data is a JSON-formatted object with the single property + * curve25519, which is itself an object mapping key id to + * base64-encoded Curve25519 key. For example: + *

+ * {
+ *     curve25519: {
+ *         "AAAAAA": "wo76WcYtb0Vk/pBOdmduiGJ0wIEjW4IBMbbQn7aSnTo",
+ *         "AAAAAB": "LRvjo46L1X2vx69sS9QNFD29HWulxrmW11Up5AfAjgU"
+ *     }
+ * }
+ * 
+ * Returns olm_error() on failure. + *

+ * If the one_time_keys buffer was too small then olm_account_last_error() + * will be "OUTPUT_BUFFER_TOO_SMALL". */ +size_t olm_account_one_time_keys( + OlmAccount * account, + void * one_time_keys, size_t one_time_keys_length +); + +/** Marks the current set of one time keys as being published. */ +size_t olm_account_mark_keys_as_published( + OlmAccount * account +); + +/** The largest number of one time keys this account can store. */ +size_t olm_account_max_number_of_one_time_keys( + OlmAccount * account +); + +/** The number of random bytes needed to generate a given number of new one + * time keys. */ +size_t olm_account_generate_one_time_keys_random_length( + OlmAccount * 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". */ +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 create an outbound session */ +size_t olm_create_outbound_session_random_length( + OlmSession * session +); + +/** Creates a new out-bound session for sending messages to a given identity_key + * and one_time_key. Returns olm_error() on failure. If the keys couldn't be + * decoded as base64 then olm_session_last_error() will be "INVALID_BASE64" + * If there weren't enough random bytes then olm_session_last_error() will + * be "NOT_ENOUGH_RANDOM". */ +size_t olm_create_outbound_session( + OlmSession * session, + OlmAccount * account, + void const * their_identity_key, size_t their_identity_key_length, + 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 then olm_session_last_error() will be + * "BAD_MESSAGE_FORMAT". If the message refers to an unknown one time + * key then olm_session_last_error() will be "BAD_MESSAGE_KEY_ID". */ +size_t olm_create_inbound_session( + OlmSession * session, + OlmAccount * account, + void * one_time_key_message, size_t message_length +); + +/** Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message. Returns olm_error() on failure. If the base64 + * couldn't be decoded then olm_session_last_error will be "INVALID_BASE64". + * If the message was for an unsupported protocol version then + * olm_session_last_error() will be "BAD_MESSAGE_VERSION". If the message + * couldn't be decoded then then olm_session_last_error() will be + * "BAD_MESSAGE_FORMAT". If the message refers to an unknown one time + * key then olm_session_last_error() will be "BAD_MESSAGE_KEY_ID". */ +size_t olm_create_inbound_session_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. */ +size_t olm_session_id_length( + OlmSession * 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". */ +size_t olm_session_id( + OlmSession * session, + void * id, size_t id_length +); + +int olm_session_has_received_message( + OlmSession *session +); + +/** + * Write a null-terminated string describing the internal state of an olm + * session to the buffer provided for debugging and logging purposes. + */ +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". */ +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". */ +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". */ +size_t olm_remove_one_time_keys( + OlmAccount * account, + OlmSession * session +); + +/** The type of the next message that olm_encrypt() will return. Returns + * OLM_MESSAGE_TYPE_PRE_KEY if the message will be a PRE_KEY message. + * Returns OLM_MESSAGE_TYPE_MESSAGE if the message will be a normal message. + * Returns olm_error on failure. */ +size_t olm_encrypt_message_type( + OlmSession * session +); + +/** The number of random bytes needed to encrypt the next message. */ +size_t olm_encrypt_random_length( + OlmSession * session +); + +/** The size of the next message in bytes for the given number of plain-text + * bytes. */ +size_t olm_encrypt_message_length( + OlmSession * session, + size_t plaintext_length +); + +/** Encrypts a message using the session. Returns the length of the message in + * bytes on success. Writes the message as base64 into the message buffer. + * Returns olm_error() on failure. If the message buffer is too small then + * olm_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL". If there + * weren't enough random bytes then olm_session_last_error() will be + * "NOT_ENOUGH_RANDOM". */ +size_t olm_encrypt( + OlmSession * session, + void const * plaintext, size_t plaintext_length, + void * random, size_t random_length, + void * message, size_t message_length +); + +/** The maximum number of bytes of plain-text a given message could decode to. + * The actual size could be different due to padding. The input message buffer + * is destroyed. Returns olm_error() on failure. If the message base64 + * couldn't be decoded then olm_session_last_error() will be + * "INVALID_BASE64". If the message is for an unsupported version of the + * protocol then olm_session_last_error() will be "BAD_MESSAGE_VERSION". + * If the message couldn't be decoded then olm_session_last_error() will be + * "BAD_MESSAGE_FORMAT". */ +size_t olm_decrypt_max_plaintext_length( + OlmSession * session, + size_t message_type, + void * message, size_t message_length +); + +/** Decrypts a message using the session. The input message buffer is destroyed. + * Returns the length of the plain-text on success. Returns olm_error() on + * failure. If the plain-text buffer is smaller than + * olm_decrypt_max_plaintext_length() then olm_session_last_error() + * will be "OUTPUT_BUFFER_TOO_SMALL". If the base64 couldn't be decoded then + * olm_session_last_error() will be "INVALID_BASE64". If the message is for + * an unsupported version of the protocol then olm_session_last_error() will + * be "BAD_MESSAGE_VERSION". If the message couldn't be decoded then + * olm_session_last_error() will be BAD_MESSAGE_FORMAT". + * If the MAC on the message was invalid then olm_session_last_error() will + * be "BAD_MESSAGE_MAC". */ +size_t olm_decrypt( + OlmSession * session, + size_t message_type, + void * message, size_t message_length, + void * plaintext, size_t max_plaintext_length +); + +/** The length of the buffer needed to hold the SHA-256 hash. */ +size_t olm_sha256_length( + OlmUtility * 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". */ +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". */ +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/include/public/olm/outbound_group_session.h b/include/public/olm/outbound_group_session.h new file mode 100644 index 0000000..eafaf80 --- /dev/null +++ b/include/public/olm/outbound_group_session.h @@ -0,0 +1,181 @@ +/* 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 +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct OlmOutboundGroupSession OlmOutboundGroupSession; + +/** get the size of an outbound group session, in bytes. */ +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. + */ +OlmOutboundGroupSession * olm_outbound_group_session( + void *memory +); + +/** + * A null terminated string describing the most recent error to happen to a + * group session */ +const char *olm_outbound_group_session_last_error( + const OlmOutboundGroupSession *session +); + +/** Clears the memory used to back this group session */ +size_t olm_clear_outbound_group_session( + OlmOutboundGroupSession *session +); + +/** Returns the number of bytes needed to store an outbound group session */ +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" + */ +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 + */ +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 */ +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. + */ +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 + */ +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. + */ +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() + */ +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. + */ +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. + */ +uint32_t olm_outbound_group_session_message_index( + OlmOutboundGroupSession *session +); + +/** + * Get the number of bytes returned by olm_outbound_group_session_key() + */ +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. + */ +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/include/public/olm/pickle.h b/include/public/olm/pickle.h new file mode 100644 index 0000000..0e668bb --- /dev/null +++ b/include/public/olm/pickle.h @@ -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. + */ +#ifndef OLM_PICKLE_H_ +#define OLM_PICKLE_H_ + +#include + +#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. */ +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. */ +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/include/public/olm/pickle_encoding.h b/include/public/olm/pickle_encoding.h new file mode 100644 index 0000000..03611df --- /dev/null +++ b/include/public/olm/pickle_encoding.h @@ -0,0 +1,76 @@ +/* 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 +#include + +#include "olm/error.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Get the number of bytes needed to encode a pickle of the length given + */ +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.) + */ + 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. + */ +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. + */ +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/include/public/olm/pk.h b/include/public/olm/pk.h new file mode 100644 index 0000000..d6476f2 --- /dev/null +++ b/include/public/olm/pk.h @@ -0,0 +1,276 @@ +/* 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 +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct OlmPkEncryption OlmPkEncryption; + +/* The size of an encryption object in bytes */ +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 */ +OlmPkEncryption *olm_pk_encryption( + void * memory +); + +/** A null terminated string describing the most recent error to happen to an + * encryption object */ +const char * olm_pk_encryption_last_error( + OlmPkEncryption * encryption +); + +/** Clears the memory used to back this encryption object */ +size_t olm_clear_pk_encryption( + OlmPkEncryption *encryption +); + +/** Set the recipient's public key for encrypting to */ +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. */ +size_t olm_pk_ciphertext_length( + OlmPkEncryption *encryption, + size_t plaintext_length +); + +/** Get the length of the message authentication code. */ +size_t olm_pk_mac_length( + OlmPkEncryption *encryption +); + +/** Get the length of a public or ephemeral key */ +size_t olm_pk_key_length(void); + +/** The number of random bytes needed to encrypt a message. */ +size_t olm_pk_encrypt_random_length( + 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". */ +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 */ +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 */ +OlmPkDecryption *olm_pk_decryption( + void * memory +); + +/** A null terminated string describing the most recent error to happen to a + * decription object */ +const char * olm_pk_decryption_last_error( + OlmPkDecryption * decryption +); + +/** Clears the memory used to back this decryption object */ +size_t olm_clear_pk_decryption( + OlmPkDecryption *decryption +); + +/** Get the number of bytes required to store an olm private key + */ +size_t olm_pk_private_key_length(void); + +/** DEPRECATED: Use olm_pk_private_key_length() + */ +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 + */ +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 + */ +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. */ +size_t olm_pickle_pk_decryption_length( + 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" */ +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 */ +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. */ +size_t olm_pk_max_plaintext_length( + 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". */ +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. + */ +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 */ +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 */ +OlmPkSigning *olm_pk_signing( + void * memory +); + +/** A null terminated string describing the most recent error to happen to a + * signing object */ +const char * olm_pk_signing_last_error( + OlmPkSigning * sign +); + +/** Clears the memory used to back this signing object */ +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". + */ +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. + */ +size_t olm_pk_signing_seed_length(void); + +/** + * The size of the public key of a signing object. + */ +size_t olm_pk_signing_public_key_length(void); + +/** + * The size of a signature created by a signing object. + */ +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". + */ +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/include/public/olm/sas.h b/include/public/olm/sas.h new file mode 100644 index 0000000..ee44eff --- /dev/null +++ b/include/public/olm/sas.h @@ -0,0 +1,166 @@ +/* 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 + +#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. */ +const char * olm_sas_last_error( + OlmSAS * sas +); + +/** The size of an SAS object in bytes. */ +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. */ +OlmSAS * olm_sas( + void * memory +); + +/** Clears the memory used to back an SAS object. */ +size_t olm_clear_sas( + OlmSAS * sas +); + +/** The number of random bytes needed to create an SAS object. */ +size_t olm_create_sas_random_length( + 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`. + */ +size_t olm_create_sas( + OlmSAS * sas, + void * random, size_t random_length +); + +/** The size of a public key in bytes. */ +size_t olm_sas_pubkey_length(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`. + */ +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`. + */ +size_t olm_sas_set_their_key( + OlmSAS *sas, + void * their_key, size_t their_key_length +); + +/** 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. + */ +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()`. */ +size_t olm_sas_mac_length( + 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`. + */ +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 +); + +// for compatibility with an old version of Riot +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_ */