Merge branch 'rav/c_bindings'

logging_enabled
Richard van der Hoff 2016-05-24 13:33:33 +01:00
commit 2e7800cf65
34 changed files with 1143 additions and 804 deletions

View File

@ -12,7 +12,7 @@ JS_TARGET := javascript/olm.js
JS_EXPORTED_FUNCTIONS := javascript/exported_functions.json
PUBLIC_HEADERS := include/olm/olm.hh
PUBLIC_HEADERS := include/olm/olm.h
SOURCES := $(wildcard src/*.cpp) $(wildcard src/*.c)
RELEASE_OBJECTS := $(patsubst src/%,$(BUILD_DIR)/release/%,$(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES))))

View File

@ -17,7 +17,7 @@
#include "olm/list.hh"
#include "olm/crypto.hh"
#include "olm/error.hh"
#include "olm/error.h"
#include <cstdint>
@ -44,7 +44,7 @@ struct Account {
IdentityKeys identity_keys;
List<OneTimeKey, MAX_ONE_TIME_KEYS> one_time_keys;
std::uint32_t next_one_time_key_id;
ErrorCode last_error;
OlmErrorCode last_error;
/** Number of random bytes needed to create a new account */
std::size_t new_account_random_length();

77
include/olm/base64.h Normal file
View File

@ -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 <stddef.h>
#include <stdint.h>
#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_ */

138
include/olm/cipher.h Normal file
View File

@ -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 <stdint.h>
#include <stdlib.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;
};
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_ */

View File

@ -1,132 +0,0 @@
/* Copyright 2015 OpenMarket Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OLM_CIPHER_HH_
#define OLM_CIPHER_HH_
#include <cstdint>
#include <cstddef>
namespace olm {
class Cipher {
public:
virtual ~Cipher();
/**
* Returns the length of the message authentication code that will be
* appended to the output.
*/
virtual std::size_t mac_length() const = 0;
/**
* Returns the length of cipher-text for a given length of plain-text.
*/
virtual std::size_t encrypt_ciphertext_length(
std::size_t plaintext_length
) const = 0;
/*
* Encrypts the plain-text into the output buffer and authenticates the
* contents of the output buffer covering both cipher-text and any other
* associated data in the output buffer.
*
* |---------------------------------------output_length-->|
* output |--ciphertext_length-->| |---mac_length-->|
* ciphertext
*
* The plain-text pointers and cipher-text pointers may be the same.
*
* Returns std::size_t(-1) if the length of the cipher-text or the output
* buffer is too small. Otherwise returns the length of the output buffer.
*/
virtual std::size_t encrypt(
std::uint8_t const * key, std::size_t key_length,
std::uint8_t const * plaintext, std::size_t plaintext_length,
std::uint8_t * ciphertext, std::size_t ciphertext_length,
std::uint8_t * output, std::size_t output_length
) const = 0;
/**
* Returns the maximum length of plain-text that a given length of
* cipher-text can contain.
*/
virtual std::size_t decrypt_max_plaintext_length(
std::size_t ciphertext_length
) const = 0;
/**
* Authenticates the input and decrypts the cipher-text into the plain-text
* buffer.
*
* |----------------------------------------input_length-->|
* input |--ciphertext_length-->| |---mac_length-->|
* ciphertext
*
* The plain-text pointers and cipher-text pointers may be the same.
*
* Returns std::size_t(-1) if the length of the plain-text buffer is too
* small or if the authentication check fails. Otherwise returns the length
* of the plain text.
*/
virtual std::size_t decrypt(
std::uint8_t const * key, std::size_t key_length,
std::uint8_t const * input, std::size_t input_length,
std::uint8_t const * ciphertext, std::size_t ciphertext_length,
std::uint8_t * plaintext, std::size_t max_plaintext_length
) const = 0;
};
class CipherAesSha256 : public Cipher {
public:
CipherAesSha256(
std::uint8_t const * kdf_info, std::size_t kdf_info_length
);
virtual std::size_t mac_length() const;
virtual std::size_t encrypt_ciphertext_length(
std::size_t plaintext_length
) const;
virtual std::size_t encrypt(
std::uint8_t const * key, std::size_t key_length,
std::uint8_t const * plaintext, std::size_t plaintext_length,
std::uint8_t * ciphertext, std::size_t ciphertext_length,
std::uint8_t * output, std::size_t output_length
) const;
virtual std::size_t decrypt_max_plaintext_length(
std::size_t ciphertext_length
) const;
virtual std::size_t decrypt(
std::uint8_t const * key, std::size_t key_length,
std::uint8_t const * input, std::size_t input_length,
std::uint8_t const * ciphertext, std::size_t ciphertext_length,
std::uint8_t * plaintext, std::size_t max_plaintext_length
) const;
private:
std::uint8_t const * kdf_info;
std::size_t kdf_info_length;
};
} // namespace
#endif /* OLM_CIPHER_HH_ */

65
include/olm/crypto.h Normal file
View File

@ -0,0 +1,65 @@
/* 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 <stdint.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
const size_t SHA256_OUTPUT_LENGTH = 32;
/** Computes SHA-256 of the input. The output buffer must be a least 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 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
);
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* OLM_CRYPTO_H_ */

View File

@ -18,6 +18,11 @@
#include <cstdint>
#include <cstddef>
// eventually all of this needs to move into crypto.h, and everything should
// use that. For now, include crypto.h here.
#include "olm/crypto.h"
namespace olm {
static const std::size_t KEY_LENGTH = 32;
@ -142,38 +147,6 @@ std::size_t aes_decrypt_cbc(
);
/** Computes SHA-256 of the input. The output buffer must be a least 32
* bytes long. */
void sha256(
std::uint8_t const * input, std::size_t input_length,
std::uint8_t * output
);
const std::size_t SHA256_OUTPUT_LENGTH = 32;
/** HMAC: Keyed-Hashing for Message Authentication
* http://tools.ietf.org/html/rfc2104
* Computes HMAC-SHA-256 of the input for the key. The output buffer must
* be at least 32 bytes long. */
void hmac_sha256(
std::uint8_t const * key, std::size_t key_length,
std::uint8_t const * input, std::size_t input_length,
std::uint8_t * output
);
/** HMAC-based Key Derivation Function (HKDF)
* https://tools.ietf.org/html/rfc5869
* Derives key material from the input bytes. */
void hkdf_sha256(
std::uint8_t const * input, std::size_t input_length,
std::uint8_t const * info, std::size_t info_length,
std::uint8_t const * salt, std::size_t salt_length,
std::uint8_t * output, std::size_t output_length
);
} // namespace olm
#endif /* OLM_CRYPTO_HH_ */

40
include/olm/error.h Normal file
View File

@ -0,0 +1,40 @@
/* 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 */
};
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* OLM_ERROR_H_ */

View File

@ -1,36 +0,0 @@
/* Copyright 2015 OpenMarket Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ERROR_HH_
#define ERROR_HH_
namespace olm {
enum struct ErrorCode {
SUCCESS = 0, /*!< There wasn't an error */
NOT_ENOUGH_RANDOM = 1, /*!< Not enough entropy was supplied */
OUTPUT_BUFFER_TOO_SMALL = 2, /*!< Supplied output buffer is too small */
BAD_MESSAGE_VERSION = 3, /*!< The message version is unsupported */
BAD_MESSAGE_FORMAT = 4, /*!< The message couldn't be decoded */
BAD_MESSAGE_MAC = 5, /*!< The message couldn't be decrypted */
BAD_MESSAGE_KEY_ID = 6, /*!< The message references an unknown key id */
INVALID_BASE64 = 7, /*!< The input base64 was invalid */
BAD_ACCOUNT_KEY = 8, /*!< The supplied account key is invalid */
UNKNOWN_PICKLE_VERSION = 9, /*!< The pickled object is too new */
CORRUPTED_PICKLE = 10, /*!< The pickled object couldn't be decoded */
};
} // namespace olm
#endif /* ERROR_HH_ */

41
include/olm/memory.h Normal file
View File

@ -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_ */

423
include/olm/olm.h Normal file
View File

@ -0,0 +1,423 @@
/* 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>
#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;
/** The size of an account object in bytes */
size_t olm_account_size();
/** The size of a session object in bytes */
size_t olm_session_size();
/** The size of a utility object in bytes */
size_t olm_utility_size();
/** Initialise an account object using the supplied memory
* The supplied memory must be at least olm_account_size() bytes */
OlmAccount * olm_account(
void * memory
);
/** Initialise a session object using the supplied memory
* The supplied memory must be at least olm_session_size() bytes */
OlmSession * olm_session(
void * memory
);
/** 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();
/** 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 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. 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
);
/** Checks if the PRE_KEY message is for this in-bound session. This can happen
* if multiple messages are sent to this account before this account sends a
* message in reply. Returns olm_error() on failure. If the base64
* couldn't be decoded then olm_session_last_error will be "INVALID_BASE64".
* If the message was for an unsupported protocol version then
* olm_session_last_error() will be "BAD_MESSAGE_VERSION". If the message
* couldn't be decoded then then olm_session_last_error() will be
* "BAD_MESSAGE_FORMAT". */
size_t olm_matches_inbound_session(
OlmSession * session,
void * one_time_key_message, size_t message_length
);
/** Checks if the PRE_KEY message is for this in-bound session. This can happen
* if multiple messages are sent to this account before this account sends a
* message in reply. Returns olm_error() on failure. If the base64
* couldn't be decoded then olm_session_last_error will be "INVALID_BASE64".
* If the message was for an unsupported protocol version then
* olm_session_last_error() will be "BAD_MESSAGE_VERSION". If the message
* couldn't be decoded then then olm_session_last_error() will be
* "BAD_MESSAGE_FORMAT". */
size_t olm_matches_inbound_session_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_session_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_session_last_error will be "INVALID_BASE64". If the signature was invalid
* then olm_session_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_HH_ */

View File

@ -1,422 +1,4 @@
/* 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.
/* this file exists only for compatibility with existing applications.
* You should use "#include <olm/olm.h>" instead.
*/
#ifndef OLM_HH_
#define OLM_HH_
#include <stddef.h>
#include <stdint.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;
/** The size of an account object in bytes */
size_t olm_account_size();
/** The size of a session object in bytes */
size_t olm_session_size();
/** The size of a utility object in bytes */
size_t olm_utility_size();
/** Initialise an account object using the supplied memory
* The supplied memory must be at least olm_account_size() bytes */
OlmAccount * olm_account(
void * memory
);
/** Initialise a session object using the supplied memory
* The supplied memory must be at least olm_session_size() bytes */
OlmSession * olm_session(
void * memory
);
/** 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();
/** 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 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. 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
);
/** Checks if the PRE_KEY message is for this in-bound session. This can happen
* if multiple messages are sent to this account before this account sends a
* message in reply. Returns olm_error() on failure. If the base64
* couldn't be decoded then olm_session_last_error will be "INVALID_BASE64".
* If the message was for an unsupported protocol version then
* olm_session_last_error() will be "BAD_MESSAGE_VERSION". If the message
* couldn't be decoded then then olm_session_last_error() will be
* "BAD_MESSAGE_FORMAT". */
size_t olm_matches_inbound_session(
OlmSession * session,
void * one_time_key_message, size_t message_length
);
/** Checks if the PRE_KEY message is for this in-bound session. This can happen
* if multiple messages are sent to this account before this account sends a
* message in reply. Returns olm_error() on failure. If the base64
* couldn't be decoded then olm_session_last_error will be "INVALID_BASE64".
* If the message was for an unsupported protocol version then
* olm_session_last_error() will be "BAD_MESSAGE_VERSION". If the message
* couldn't be decoded then then olm_session_last_error() will be
* "BAD_MESSAGE_FORMAT". */
size_t olm_matches_inbound_session_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_session_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_session_last_error will be "INVALID_BASE64". If the signature was invalid
* then olm_session_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_HH_ */
#include "olm/olm.h"

50
include/olm/pickle.h Normal file
View File

@ -0,0 +1,50 @@
/* 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 <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#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);
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* OLM_PICKLE_H */

View File

@ -15,12 +15,12 @@
#include "olm/crypto.hh"
#include "olm/list.hh"
#include "olm/error.hh"
#include "olm/error.h"
struct _olm_cipher;
namespace olm {
class Cipher;
typedef std::uint8_t SharedKey[olm::KEY_LENGTH];
@ -69,17 +69,17 @@ struct Ratchet {
Ratchet(
KdfInfo const & kdf_info,
Cipher const & ratchet_cipher
_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. */
Cipher const & ratchet_cipher;
_olm_cipher const *ratchet_cipher;
/** The last error that happened encrypting or decrypting a message. */
ErrorCode last_error;
OlmErrorCode last_error;
/**
* A count of the number of times the root key has been advanced; this is

View File

@ -31,7 +31,7 @@ struct Session {
Session();
Ratchet ratchet;
ErrorCode last_error;
OlmErrorCode last_error;
bool received_message;

View File

@ -16,7 +16,7 @@
#ifndef UTILITY_HH_
#define UTILITY_HH_
#include "olm/error.hh"
#include "olm/error.h"
#include <cstddef>
#include <cstdint>
@ -29,7 +29,7 @@ struct Utility {
Utility();
ErrorCode last_error;
OlmErrorCode last_error;
/** The length of a SHA-256 hash in bytes. */
std::size_t sha256_length();

View File

@ -19,7 +19,7 @@
olm::Account::Account(
) : next_one_time_key_id(0),
last_error(olm::ErrorCode::SUCCESS) {
last_error(OlmErrorCode::OLM_SUCCESS) {
}
@ -56,7 +56,7 @@ std::size_t olm::Account::new_account(
uint8_t const * random, std::size_t random_length
) {
if (random_length < new_account_random_length()) {
last_error = olm::ErrorCode::NOT_ENOUGH_RANDOM;
last_error = OlmErrorCode::OLM_NOT_ENOUGH_RANDOM;
return std::size_t(-1);
}
@ -110,7 +110,7 @@ std::size_t olm::Account::get_identity_json(
size_t expected_length = get_identity_json_length();
if (identity_json_length < expected_length) {
last_error = olm::ErrorCode::OUTPUT_BUFFER_TOO_SMALL;
last_error = OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
return std::size_t(-1);
}
@ -146,7 +146,7 @@ std::size_t olm::Account::sign(
std::uint8_t * signature, std::size_t signature_length
) {
if (signature_length < this->signature_length()) {
last_error = olm::ErrorCode::OUTPUT_BUFFER_TOO_SMALL;
last_error = OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
return std::size_t(-1);
}
olm::ed25519_sign(
@ -185,7 +185,7 @@ std::size_t olm::Account::get_one_time_keys_json(
) {
std::uint8_t * pos = one_time_json;
if (one_time_json_length < get_one_time_keys_json_length()) {
last_error = olm::ErrorCode::OUTPUT_BUFFER_TOO_SMALL;
last_error = OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
return std::size_t(-1);
}
*(pos++) = '{';
@ -246,7 +246,7 @@ std::size_t olm::Account::generate_one_time_keys(
std::uint8_t const * random, std::size_t random_length
) {
if (random_length < generate_one_time_keys_random_length(number_of_keys)) {
last_error = olm::ErrorCode::NOT_ENOUGH_RANDOM;
last_error = OlmErrorCode::OLM_NOT_ENOUGH_RANDOM;
return std::size_t(-1);
}
for (unsigned i = 0; i < number_of_keys; ++i) {
@ -361,7 +361,7 @@ std::uint8_t const * olm::unpickle(
uint32_t pickle_version;
pos = olm::unpickle(pos, end, pickle_version);
if (pickle_version != ACCOUNT_PICKLE_VERSION) {
value.last_error = olm::ErrorCode::UNKNOWN_PICKLE_VERSION;
value.last_error = OlmErrorCode::OLM_UNKNOWN_PICKLE_VERSION;
return end;
}
pos = olm::unpickle(pos, end, value.identity_keys);

View File

@ -12,9 +12,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "olm/base64.h"
#include "olm/base64.hh"
namespace {
static const std::uint8_t ENCODE_BASE64[64] = {
@ -134,3 +134,34 @@ std::uint8_t const * olm::decode_base64(
}
return input + input_length;
}
// implementations of base64.h
size_t _olm_encode_base64_length(
size_t input_length
) {
return olm::encode_base64_length(input_length);
}
size_t _olm_encode_base64(
uint8_t const * input, size_t input_length,
uint8_t * output
) {
uint8_t * r = olm::encode_base64(input, input_length, output);
return r - output;
}
size_t _olm_decode_base64_length(
size_t input_length
) {
return olm::decode_base64_length(input_length);
}
size_t _olm_decode_base64(
uint8_t const * input, size_t input_length,
uint8_t * output
) {
olm::decode_base64(input, input_length, output);
return olm::decode_base64_length(input_length);
}

View File

@ -12,15 +12,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "olm/cipher.hh"
#include "olm/cipher.h"
#include "olm/crypto.hh"
#include "olm/memory.hh"
#include <cstring>
olm::Cipher::~Cipher() {
}
namespace {
struct DerivedKeys {
@ -36,7 +32,7 @@ static void derive_keys(
DerivedKeys & keys
) {
std::uint8_t derived_secrets[2 * olm::KEY_LENGTH + olm::IV_LENGTH];
olm::hkdf_sha256(
_olm_crypto_hkdf_sha256(
key, key_length,
nullptr, 0,
kdf_info, kdf_info_length,
@ -51,47 +47,40 @@ static void derive_keys(
static const std::size_t MAC_LENGTH = 8;
} // namespace
olm::CipherAesSha256::CipherAesSha256(
std::uint8_t const * kdf_info, std::size_t kdf_info_length
) : kdf_info(kdf_info), kdf_info_length(kdf_info_length) {
}
std::size_t olm::CipherAesSha256::mac_length() const {
size_t aes_sha_256_cipher_mac_length(const struct _olm_cipher *cipher) {
return MAC_LENGTH;
}
std::size_t olm::CipherAesSha256::encrypt_ciphertext_length(
std::size_t plaintext_length
) const {
size_t aes_sha_256_cipher_encrypt_ciphertext_length(
const struct _olm_cipher *cipher, size_t plaintext_length
) {
return olm::aes_encrypt_cbc_length(plaintext_length);
}
size_t aes_sha_256_cipher_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
) {
auto *c = reinterpret_cast<const _olm_cipher_aes_sha_256 *>(cipher);
std::size_t olm::CipherAesSha256::encrypt(
std::uint8_t const * key, std::size_t key_length,
std::uint8_t const * plaintext, std::size_t plaintext_length,
std::uint8_t * ciphertext, std::size_t ciphertext_length,
std::uint8_t * output, std::size_t output_length
) const {
if (encrypt_ciphertext_length(plaintext_length) < ciphertext_length) {
if (aes_sha_256_cipher_encrypt_ciphertext_length(cipher, plaintext_length)
< ciphertext_length) {
return std::size_t(-1);
}
struct DerivedKeys keys;
std::uint8_t mac[olm::SHA256_OUTPUT_LENGTH];
derive_keys(kdf_info, kdf_info_length, key, key_length, keys);
struct DerivedKeys keys;
std::uint8_t mac[SHA256_OUTPUT_LENGTH];
derive_keys(c->kdf_info, c->kdf_info_length, key, key_length, keys);
olm::aes_encrypt_cbc(
keys.aes_key, keys.aes_iv, plaintext, plaintext_length, ciphertext
);
olm::hmac_sha256(
_olm_crypto_hmac_sha256(
keys.mac_key, olm::KEY_LENGTH, output, output_length - MAC_LENGTH, mac
);
@ -102,24 +91,28 @@ std::size_t olm::CipherAesSha256::encrypt(
}
std::size_t olm::CipherAesSha256::decrypt_max_plaintext_length(
std::size_t ciphertext_length
) const {
size_t aes_sha_256_cipher_decrypt_max_plaintext_length(
const struct _olm_cipher *cipher,
size_t ciphertext_length
) {
return ciphertext_length;
}
std::size_t olm::CipherAesSha256::decrypt(
std::uint8_t const * key, std::size_t key_length,
std::uint8_t const * input, std::size_t input_length,
std::uint8_t const * ciphertext, std::size_t ciphertext_length,
std::uint8_t * plaintext, std::size_t max_plaintext_length
) const {
size_t aes_sha_256_cipher_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
) {
auto *c = reinterpret_cast<const _olm_cipher_aes_sha_256 *>(cipher);
DerivedKeys keys;
std::uint8_t mac[olm::SHA256_OUTPUT_LENGTH];
std::uint8_t mac[SHA256_OUTPUT_LENGTH];
derive_keys(kdf_info, kdf_info_length, key, key_length, keys);
derive_keys(c->kdf_info, c->kdf_info_length, key, key_length, keys);
olm::hmac_sha256(
_olm_crypto_hmac_sha256(
keys.mac_key, olm::KEY_LENGTH, input, input_length - MAC_LENGTH, mac
);
@ -136,3 +129,13 @@ std::size_t olm::CipherAesSha256::decrypt(
olm::unset(keys);
return plaintext_length;
}
} // namespace
const struct _olm_cipher_ops _olm_cipher_aes_sha_256_ops = {
aes_sha_256_cipher_mac_length,
aes_sha_256_cipher_encrypt_ciphertext_length,
aes_sha_256_cipher_encrypt,
aes_sha_256_cipher_decrypt_max_plaintext_length,
aes_sha_256_cipher_decrypt,
};

View File

@ -85,7 +85,7 @@ inline static void hmac_sha256_final(
std::uint8_t const * hmac_key,
std::uint8_t * output
) {
std::uint8_t o_pad[SHA256_BLOCK_LENGTH + olm::SHA256_OUTPUT_LENGTH];
std::uint8_t o_pad[SHA256_BLOCK_LENGTH + SHA256_OUTPUT_LENGTH];
std::memcpy(o_pad, hmac_key, SHA256_BLOCK_LENGTH);
for (std::size_t i = 0; i < SHA256_BLOCK_LENGTH; ++i) {
o_pad[i] ^= 0x5C;
@ -255,7 +255,7 @@ std::size_t olm::aes_decrypt_cbc(
}
void olm::sha256(
void _olm_crypto_sha256(
std::uint8_t const * input, std::size_t input_length,
std::uint8_t * output
) {
@ -267,7 +267,7 @@ void olm::sha256(
}
void olm::hmac_sha256(
void _olm_crypto_hmac_sha256(
std::uint8_t const * key, std::size_t key_length,
std::uint8_t const * input, std::size_t input_length,
std::uint8_t * output
@ -283,7 +283,7 @@ void olm::hmac_sha256(
}
void olm::hkdf_sha256(
void _olm_crypto_hkdf_sha256(
std::uint8_t const * input, std::size_t input_length,
std::uint8_t const * salt, std::size_t salt_length,
std::uint8_t const * info, std::size_t info_length,
@ -291,7 +291,7 @@ void olm::hkdf_sha256(
) {
::SHA256_CTX context;
std::uint8_t hmac_key[SHA256_BLOCK_LENGTH];
std::uint8_t step_result[olm::SHA256_OUTPUT_LENGTH];
std::uint8_t step_result[SHA256_OUTPUT_LENGTH];
std::size_t bytes_remaining = output_length;
std::uint8_t iteration = 1;
if (!salt) {
@ -303,20 +303,20 @@ void olm::hkdf_sha256(
hmac_sha256_init(&context, hmac_key);
::sha256_update(&context, input, input_length);
hmac_sha256_final(&context, hmac_key, step_result);
hmac_sha256_key(step_result, olm::SHA256_OUTPUT_LENGTH, hmac_key);
hmac_sha256_key(step_result, SHA256_OUTPUT_LENGTH, hmac_key);
/* Expand */
hmac_sha256_init(&context, hmac_key);
::sha256_update(&context, info, info_length);
::sha256_update(&context, &iteration, 1);
hmac_sha256_final(&context, hmac_key, step_result);
while (bytes_remaining > olm::SHA256_OUTPUT_LENGTH) {
std::memcpy(output, step_result, olm::SHA256_OUTPUT_LENGTH);
output += olm::SHA256_OUTPUT_LENGTH;
bytes_remaining -= olm::SHA256_OUTPUT_LENGTH;
while (bytes_remaining > SHA256_OUTPUT_LENGTH) {
std::memcpy(output, step_result, SHA256_OUTPUT_LENGTH);
output += SHA256_OUTPUT_LENGTH;
bytes_remaining -= SHA256_OUTPUT_LENGTH;
iteration ++;
hmac_sha256_init(&context, hmac_key);
::sha256_update(&context, step_result, olm::SHA256_OUTPUT_LENGTH);
::sha256_update(&context, step_result, SHA256_OUTPUT_LENGTH);
::sha256_update(&context, info, info_length);
::sha256_update(&context, &iteration, 1);
hmac_sha256_final(&context, hmac_key, step_result);

View File

@ -13,7 +13,13 @@
* limitations under the License.
*/
#include "olm/memory.hh"
#include "olm/memory.h"
void _olm_unset(
void volatile * buffer, size_t buffer_length
) {
olm::unset(buffer, buffer_length);
}
void olm::unset(
void volatile * buffer, std::size_t buffer_length

View File

@ -12,12 +12,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "olm/olm.hh"
#include "olm/olm.h"
#include "olm/session.hh"
#include "olm/account.hh"
#include "olm/cipher.h"
#include "olm/utility.hh"
#include "olm/base64.hh"
#include "olm/cipher.hh"
#include "olm/memory.hh"
#include <new>
@ -57,17 +57,15 @@ static std::uint8_t const * from_c(void const * bytes) {
return reinterpret_cast<std::uint8_t const *>(bytes);
}
static const std::uint8_t CIPHER_KDF_INFO[] = "Pickle";
static const olm::CipherAesSha256 PICKLE_CIPHER(
CIPHER_KDF_INFO, sizeof(CIPHER_KDF_INFO) -1
);
static const struct _olm_cipher_aes_sha_256 PICKLE_CIPHER =
OLM_CIPHER_INIT_AES_SHA_256("Pickle");
std::size_t enc_output_length(
size_t raw_length
) {
std::size_t length = PICKLE_CIPHER.encrypt_ciphertext_length(raw_length);
length += PICKLE_CIPHER.mac_length();
auto *cipher = OLM_CIPHER_BASE(&PICKLE_CIPHER);
std::size_t length = cipher->ops->encrypt_ciphertext_length(cipher, raw_length);
length += cipher->ops->mac_length(cipher);
return olm::encode_base64_length(length);
}
@ -76,8 +74,9 @@ std::uint8_t * enc_output_pos(
std::uint8_t * output,
size_t raw_length
) {
std::size_t length = PICKLE_CIPHER.encrypt_ciphertext_length(raw_length);
length += PICKLE_CIPHER.mac_length();
auto *cipher = OLM_CIPHER_BASE(&PICKLE_CIPHER);
std::size_t length = cipher->ops->encrypt_ciphertext_length(cipher, raw_length);
length += cipher->ops->mac_length(cipher);
return output + olm::encode_base64_length(length) - length;
}
@ -85,13 +84,15 @@ std::size_t enc_output(
std::uint8_t const * key, std::size_t key_length,
std::uint8_t * output, size_t raw_length
) {
std::size_t ciphertext_length = PICKLE_CIPHER.encrypt_ciphertext_length(
raw_length
auto *cipher = OLM_CIPHER_BASE(&PICKLE_CIPHER);
std::size_t ciphertext_length = cipher->ops->encrypt_ciphertext_length(
cipher, raw_length
);
std::size_t length = ciphertext_length + PICKLE_CIPHER.mac_length();
std::size_t length = ciphertext_length + cipher->ops->mac_length(cipher);
std::size_t base64_length = olm::encode_base64_length(length);
std::uint8_t * raw_output = output + base64_length - length;
PICKLE_CIPHER.encrypt(
cipher->ops->encrypt(
cipher,
key, key_length,
raw_output, raw_length,
raw_output, ciphertext_length,
@ -104,23 +105,25 @@ std::size_t enc_output(
std::size_t enc_input(
std::uint8_t const * key, std::size_t key_length,
std::uint8_t * input, size_t b64_length,
olm::ErrorCode & last_error
OlmErrorCode & last_error
) {
std::size_t enc_length = olm::decode_base64_length(b64_length);
if (enc_length == std::size_t(-1)) {
last_error = olm::ErrorCode::INVALID_BASE64;
last_error = OlmErrorCode::OLM_INVALID_BASE64;
return std::size_t(-1);
}
olm::decode_base64(input, b64_length, input);
std::size_t raw_length = enc_length - PICKLE_CIPHER.mac_length();
std::size_t result = PICKLE_CIPHER.decrypt(
auto *cipher = OLM_CIPHER_BASE(&PICKLE_CIPHER);
std::size_t raw_length = enc_length - cipher->ops->mac_length(cipher);
std::size_t result = cipher->ops->decrypt(
cipher,
key, key_length,
input, enc_length,
input, raw_length,
input, raw_length
);
if (result == std::size_t(-1)) {
last_error = olm::ErrorCode::BAD_ACCOUNT_KEY;
last_error = OlmErrorCode::OLM_BAD_ACCOUNT_KEY;
}
return result;
}
@ -150,11 +153,11 @@ std::size_t b64_output(
std::size_t b64_input(
std::uint8_t * input, size_t b64_length,
olm::ErrorCode & last_error
OlmErrorCode & last_error
) {
std::size_t raw_length = olm::decode_base64_length(b64_length);
if (raw_length == std::size_t(-1)) {
last_error = olm::ErrorCode::INVALID_BASE64;
last_error = OlmErrorCode::OLM_INVALID_BASE64;
return std::size_t(-1);
}
olm::decode_base64(input, b64_length, input);
@ -312,7 +315,7 @@ size_t olm_pickle_account(
olm::Account & object = *from_c(account);
std::size_t raw_length = pickle_length(object);
if (pickled_length < enc_output_length(raw_length)) {
object.last_error = olm::ErrorCode::OUTPUT_BUFFER_TOO_SMALL;
object.last_error = OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
return size_t(-1);
}
pickle(enc_output_pos(from_c(pickled), raw_length), object);
@ -328,7 +331,7 @@ size_t olm_pickle_session(
olm::Session & object = *from_c(session);
std::size_t raw_length = pickle_length(object);
if (pickled_length < enc_output_length(raw_length)) {
object.last_error = olm::ErrorCode::OUTPUT_BUFFER_TOO_SMALL;
object.last_error = OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
return size_t(-1);
}
pickle(enc_output_pos(from_c(pickled), raw_length), object);
@ -355,8 +358,8 @@ size_t olm_unpickle_account(
* (pos + raw_length). On error unpickle will return (pos + raw_length + 1).
*/
if (end != unpickle(pos, end + 1, object)) {
if (object.last_error == olm::ErrorCode::SUCCESS) {
object.last_error = olm::ErrorCode::CORRUPTED_PICKLE;
if (object.last_error == OlmErrorCode::OLM_SUCCESS) {
object.last_error = OlmErrorCode::OLM_CORRUPTED_PICKLE;
}
return std::size_t(-1);
}
@ -384,8 +387,8 @@ size_t olm_unpickle_session(
* (pos + raw_length). On error unpickle will return (pos + raw_length + 1).
*/
if (end != unpickle(pos, end + 1, object)) {
if (object.last_error == olm::ErrorCode::SUCCESS) {
object.last_error = olm::ErrorCode::CORRUPTED_PICKLE;
if (object.last_error == OlmErrorCode::OLM_SUCCESS) {
object.last_error = OlmErrorCode::OLM_CORRUPTED_PICKLE;
}
return std::size_t(-1);
}
@ -442,7 +445,7 @@ size_t olm_account_sign(
std::size_t raw_length = from_c(account)->signature_length();
if (signature_length < b64_output_length(raw_length)) {
from_c(account)->last_error =
olm::ErrorCode::OUTPUT_BUFFER_TOO_SMALL;
OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
return std::size_t(-1);
}
from_c(account)->sign(
@ -528,7 +531,7 @@ size_t olm_create_outbound_session(
if (olm::decode_base64_length(id_key_length) != olm::KEY_LENGTH
|| olm::decode_base64_length(ot_key_length) != olm::KEY_LENGTH
) {
from_c(session)->last_error = olm::ErrorCode::INVALID_BASE64;
from_c(session)->last_error = OlmErrorCode::OLM_INVALID_BASE64;
return std::size_t(-1);
}
olm::Curve25519PublicKey identity_key;
@ -573,7 +576,7 @@ size_t olm_create_inbound_session_from(
std::size_t id_key_length = their_identity_key_length;
if (olm::decode_base64_length(id_key_length) != olm::KEY_LENGTH) {
from_c(session)->last_error = olm::ErrorCode::INVALID_BASE64;
from_c(session)->last_error = OlmErrorCode::OLM_INVALID_BASE64;
return std::size_t(-1);
}
olm::Curve25519PublicKey identity_key;
@ -605,7 +608,7 @@ size_t olm_session_id(
std::size_t raw_length = from_c(session)->session_id_length();
if (id_length < b64_output_length(raw_length)) {
from_c(session)->last_error =
olm::ErrorCode::OUTPUT_BUFFER_TOO_SMALL;
OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
return std::size_t(-1);
}
std::size_t result = from_c(session)->session_id(
@ -644,7 +647,7 @@ size_t olm_matches_inbound_session_from(
std::size_t id_key_length = their_identity_key_length;
if (olm::decode_base64_length(id_key_length) != olm::KEY_LENGTH) {
from_c(session)->last_error = olm::ErrorCode::INVALID_BASE64;
from_c(session)->last_error = OlmErrorCode::OLM_INVALID_BASE64;
return std::size_t(-1);
}
olm::Curve25519PublicKey identity_key;
@ -671,7 +674,7 @@ size_t olm_remove_one_time_keys(
from_c(session)->bob_one_time_key
);
if (result == std::size_t(-1)) {
from_c(account)->last_error = olm::ErrorCode::BAD_MESSAGE_KEY_ID;
from_c(account)->last_error = OlmErrorCode::OLM_BAD_MESSAGE_KEY_ID;
}
return result;
}
@ -712,7 +715,7 @@ size_t olm_encrypt(
);
if (message_length < b64_output_length(raw_length)) {
from_c(session)->last_error =
olm::ErrorCode::OUTPUT_BUFFER_TOO_SMALL;
OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
return std::size_t(-1);
}
std::size_t result = from_c(session)->encrypt(
@ -779,7 +782,7 @@ size_t olm_sha256(
std::size_t raw_length = from_c(utility)->sha256_length();
if (output_length < b64_output_length(raw_length)) {
from_c(utility)->last_error =
olm::ErrorCode::OUTPUT_BUFFER_TOO_SMALL;
OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
return std::size_t(-1);
}
std::size_t result = from_c(utility)->sha256(
@ -800,7 +803,7 @@ size_t olm_ed25519_verify(
void * signature, size_t signature_length
) {
if (olm::decode_base64_length(key_length) != olm::KEY_LENGTH) {
from_c(utility)->last_error = olm::ErrorCode::INVALID_BASE64;
from_c(utility)->last_error = OlmErrorCode::OLM_INVALID_BASE64;
return std::size_t(-1);
}
olm::Ed25519PublicKey verify_key;

View File

@ -13,6 +13,7 @@
* limitations under the License.
*/
#include "olm/pickle.hh"
#include "olm/pickle.h"
std::uint8_t * olm::pickle(
std::uint8_t * pos,
@ -196,3 +197,37 @@ std::uint8_t const * olm::unpickle(
);
return pos;
}
////// pickle.h implementations
uint8_t * _olm_pickle_uint32(uint8_t * pos, uint32_t value) {
return olm::pickle(pos, value);
}
uint8_t const * _olm_unpickle_uint32(
uint8_t const * pos, uint8_t const * end,
uint32_t *value
) {
return olm::unpickle(pos, end, *value);
}
uint8_t * _olm_pickle_bool(uint8_t * pos, int value) {
return olm::pickle(pos, (bool)value);
}
uint8_t const * _olm_unpickle_bool(
uint8_t const * pos, uint8_t const * end,
int *value
) {
return olm::unpickle(pos, end, *reinterpret_cast<bool *>(value));
}
uint8_t * _olm_pickle_bytes(uint8_t * pos, uint8_t const * bytes,
size_t bytes_length) {
return olm::pickle_bytes(pos, bytes, bytes_length);
}
uint8_t const * _olm_unpickle_bytes(uint8_t const * pos, uint8_t const * end,
uint8_t * bytes, size_t bytes_length) {
return olm::unpickle_bytes(pos, end, bytes, bytes_length);
}

View File

@ -15,7 +15,7 @@
#include "olm/ratchet.hh"
#include "olm/message.hh"
#include "olm/memory.hh"
#include "olm/cipher.hh"
#include "olm/cipher.h"
#include "olm/pickle.hh"
#include <cstring>
@ -50,7 +50,7 @@ static void create_chain_key(
olm::SharedKey secret;
olm::curve25519_shared_secret(our_key, their_key, secret);
std::uint8_t derived_secrets[2 * olm::KEY_LENGTH];
olm::hkdf_sha256(
_olm_crypto_hkdf_sha256(
secret, sizeof(secret),
root_key, sizeof(root_key),
info.ratchet_info, info.ratchet_info_length,
@ -70,7 +70,7 @@ static void advance_chain_key(
olm::ChainKey const & chain_key,
olm::ChainKey & new_chain_key
) {
olm::hmac_sha256(
_olm_crypto_hmac_sha256(
chain_key.key, sizeof(chain_key.key),
CHAIN_KEY_SEED, sizeof(CHAIN_KEY_SEED),
new_chain_key.key
@ -84,7 +84,7 @@ static void create_message_keys(
olm::ChainKey const & chain_key,
olm::KdfInfo const & info,
olm::MessageKey & message_key) {
olm::hmac_sha256(
_olm_crypto_hmac_sha256(
chain_key.key, sizeof(chain_key.key),
MESSAGE_KEY_SEED, sizeof(MESSAGE_KEY_SEED),
message_key.key
@ -94,12 +94,13 @@ static void create_message_keys(
static std::size_t verify_mac_and_decrypt(
olm::Cipher const & cipher,
_olm_cipher const *cipher,
olm::MessageKey const & message_key,
olm::MessageReader const & reader,
std::uint8_t * plaintext, std::size_t max_plaintext_length
) {
return cipher.decrypt(
return cipher->ops->decrypt(
cipher,
message_key.key, sizeof(message_key.key),
reader.input, reader.input_length,
reader.ciphertext, reader.ciphertext_length,
@ -183,10 +184,10 @@ static std::size_t verify_mac_and_decrypt_for_new_chain(
olm::Ratchet::Ratchet(
olm::KdfInfo const & kdf_info,
Cipher const & ratchet_cipher
_olm_cipher const * ratchet_cipher
) : kdf_info(kdf_info),
ratchet_cipher(ratchet_cipher),
last_error(olm::ErrorCode::SUCCESS) {
last_error(OlmErrorCode::OLM_SUCCESS) {
}
@ -195,7 +196,7 @@ void olm::Ratchet::initialise_as_bob(
olm::Curve25519PublicKey const & their_ratchet_key
) {
std::uint8_t derived_secrets[2 * olm::KEY_LENGTH];
olm::hkdf_sha256(
_olm_crypto_hkdf_sha256(
shared_secret, shared_secret_length,
nullptr, 0,
kdf_info.root_info, kdf_info.root_info_length,
@ -217,7 +218,7 @@ void olm::Ratchet::initialise_as_alice(
olm::Curve25519KeyPair const & our_ratchet_key
) {
std::uint8_t derived_secrets[2 * olm::KEY_LENGTH];
olm::hkdf_sha256(
_olm_crypto_hkdf_sha256(
shared_secret, shared_secret_length,
nullptr, 0,
kdf_info.root_info, kdf_info.root_info_length,
@ -405,11 +406,12 @@ std::size_t olm::Ratchet::encrypt_output_length(
if (!sender_chain.empty()) {
counter = sender_chain[0].chain_key.index;
}
std::size_t padded = ratchet_cipher.encrypt_ciphertext_length(
std::size_t padded = ratchet_cipher->ops->encrypt_ciphertext_length(
ratchet_cipher,
plaintext_length
);
return olm::encode_message_length(
counter, olm::KEY_LENGTH, padded, ratchet_cipher.mac_length()
counter, olm::KEY_LENGTH, padded, ratchet_cipher->ops->mac_length(ratchet_cipher)
);
}
@ -427,11 +429,11 @@ std::size_t olm::Ratchet::encrypt(
std::size_t output_length = encrypt_output_length(plaintext_length);
if (random_length < encrypt_random_length()) {
last_error = olm::ErrorCode::NOT_ENOUGH_RANDOM;
last_error = OlmErrorCode::OLM_NOT_ENOUGH_RANDOM;
return std::size_t(-1);
}
if (max_output_length < output_length) {
last_error = olm::ErrorCode::OUTPUT_BUFFER_TOO_SMALL;
last_error = OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
return std::size_t(-1);
}
@ -452,7 +454,8 @@ std::size_t olm::Ratchet::encrypt(
create_message_keys(chain_index, sender_chain[0].chain_key, kdf_info, keys);
advance_chain_key(chain_index, sender_chain[0].chain_key, sender_chain[0].chain_key);
std::size_t ciphertext_length = ratchet_cipher.encrypt_ciphertext_length(
std::size_t ciphertext_length = ratchet_cipher->ops->encrypt_ciphertext_length(
ratchet_cipher,
plaintext_length
);
std::uint32_t counter = keys.index;
@ -467,7 +470,8 @@ std::size_t olm::Ratchet::encrypt(
olm::store_array(writer.ratchet_key, ratchet_key.public_key);
ratchet_cipher.encrypt(
ratchet_cipher->ops->encrypt(
ratchet_cipher,
keys.key, sizeof(keys.key),
plaintext, plaintext_length,
writer.ciphertext, ciphertext_length,
@ -484,15 +488,17 @@ std::size_t olm::Ratchet::decrypt_max_plaintext_length(
) {
olm::MessageReader reader;
olm::decode_message(
reader, input, input_length, ratchet_cipher.mac_length()
reader, input, input_length,
ratchet_cipher->ops->mac_length(ratchet_cipher)
);
if (!reader.ciphertext) {
last_error = olm::ErrorCode::BAD_MESSAGE_FORMAT;
last_error = OlmErrorCode::OLM_BAD_MESSAGE_FORMAT;
return std::size_t(-1);
}
return ratchet_cipher.decrypt_max_plaintext_length(reader.ciphertext_length);
return ratchet_cipher->ops->decrypt_max_plaintext_length(
ratchet_cipher, reader.ciphertext_length);
}
@ -502,30 +508,32 @@ std::size_t olm::Ratchet::decrypt(
) {
olm::MessageReader reader;
olm::decode_message(
reader, input, input_length, ratchet_cipher.mac_length()
reader, input, input_length,
ratchet_cipher->ops->mac_length(ratchet_cipher)
);
if (reader.version != PROTOCOL_VERSION) {
last_error = olm::ErrorCode::BAD_MESSAGE_VERSION;
last_error = OlmErrorCode::OLM_BAD_MESSAGE_VERSION;
return std::size_t(-1);
}
if (!reader.has_counter || !reader.ratchet_key || !reader.ciphertext) {
last_error = olm::ErrorCode::BAD_MESSAGE_FORMAT;
last_error = OlmErrorCode::OLM_BAD_MESSAGE_FORMAT;
return std::size_t(-1);
}
std::size_t max_length = ratchet_cipher.decrypt_max_plaintext_length(
std::size_t max_length = ratchet_cipher->ops->decrypt_max_plaintext_length(
ratchet_cipher,
reader.ciphertext_length
);
if (max_plaintext_length < max_length) {
last_error = olm::ErrorCode::OUTPUT_BUFFER_TOO_SMALL;
last_error = OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
return std::size_t(-1);
}
if (reader.ratchet_key_length != olm::KEY_LENGTH) {
last_error = olm::ErrorCode::BAD_MESSAGE_FORMAT;
last_error = OlmErrorCode::OLM_BAD_MESSAGE_FORMAT;
return std::size_t(-1);
}
@ -588,7 +596,7 @@ std::size_t olm::Ratchet::decrypt(
}
if (result == std::size_t(-1)) {
last_error = olm::ErrorCode::BAD_MESSAGE_MAC;
last_error = OlmErrorCode::OLM_BAD_MESSAGE_MAC;
return std::size_t(-1);
}

View File

@ -13,7 +13,7 @@
* limitations under the License.
*/
#include "olm/session.hh"
#include "olm/cipher.hh"
#include "olm/cipher.h"
#include "olm/crypto.hh"
#include "olm/account.hh"
#include "olm/memory.hh"
@ -30,20 +30,19 @@ static const std::uint8_t ROOT_KDF_INFO[] = "OLM_ROOT";
static const std::uint8_t RATCHET_KDF_INFO[] = "OLM_RATCHET";
static const std::uint8_t CIPHER_KDF_INFO[] = "OLM_KEYS";
static const olm::CipherAesSha256 OLM_CIPHER(
CIPHER_KDF_INFO, sizeof(CIPHER_KDF_INFO) -1
);
static const olm::KdfInfo OLM_KDF_INFO = {
ROOT_KDF_INFO, sizeof(ROOT_KDF_INFO) - 1,
RATCHET_KDF_INFO, sizeof(RATCHET_KDF_INFO) - 1
};
static const struct _olm_cipher_aes_sha_256 OLM_CIPHER =
OLM_CIPHER_INIT_AES_SHA_256(CIPHER_KDF_INFO);
} // namespace
olm::Session::Session(
) : ratchet(OLM_KDF_INFO, OLM_CIPHER),
last_error(olm::ErrorCode::SUCCESS),
) : ratchet(OLM_KDF_INFO, OLM_CIPHER_BASE(&OLM_CIPHER)),
last_error(OlmErrorCode::OLM_SUCCESS),
received_message(false) {
}
@ -61,7 +60,7 @@ std::size_t olm::Session::new_outbound_session(
std::uint8_t const * random, std::size_t random_length
) {
if (random_length < new_outbound_session_random_length()) {
last_error = olm::ErrorCode::NOT_ENOUGH_RANDOM;
last_error = OlmErrorCode::OLM_NOT_ENOUGH_RANDOM;
return std::size_t(-1);
}
@ -128,7 +127,7 @@ std::size_t olm::Session::new_inbound_session(
decode_one_time_key_message(reader, one_time_key_message, message_length);
if (!check_message_fields(reader, their_identity_key)) {
last_error = olm::ErrorCode::BAD_MESSAGE_FORMAT;
last_error = OlmErrorCode::OLM_BAD_MESSAGE_FORMAT;
return std::size_t(-1);
}
@ -137,7 +136,7 @@ std::size_t olm::Session::new_inbound_session(
their_identity_key->public_key, reader.identity_key, olm::KEY_LENGTH
);
if (!same) {
last_error = olm::ErrorCode::BAD_MESSAGE_KEY_ID;
last_error = OlmErrorCode::OLM_BAD_MESSAGE_KEY_ID;
return std::size_t(-1);
}
}
@ -149,12 +148,12 @@ std::size_t olm::Session::new_inbound_session(
olm::MessageReader message_reader;
decode_message(
message_reader, reader.message, reader.message_length,
ratchet.ratchet_cipher.mac_length()
ratchet.ratchet_cipher->ops->mac_length(ratchet.ratchet_cipher)
);
if (!message_reader.ratchet_key
|| message_reader.ratchet_key_length != olm::KEY_LENGTH) {
last_error = olm::ErrorCode::BAD_MESSAGE_FORMAT;
last_error = OlmErrorCode::OLM_BAD_MESSAGE_FORMAT;
return std::size_t(-1);
}
@ -166,7 +165,7 @@ std::size_t olm::Session::new_inbound_session(
);
if (!our_one_time_key) {
last_error = olm::ErrorCode::BAD_MESSAGE_KEY_ID;
last_error = OlmErrorCode::OLM_BAD_MESSAGE_KEY_ID;
return std::size_t(-1);
}
@ -192,7 +191,7 @@ std::size_t olm::Session::new_inbound_session(
std::size_t olm::Session::session_id_length() {
return olm::SHA256_OUTPUT_LENGTH;
return SHA256_OUTPUT_LENGTH;
}
@ -200,7 +199,7 @@ std::size_t olm::Session::session_id(
std::uint8_t * id, std::size_t id_length
) {
if (id_length < session_id_length()) {
last_error = olm::ErrorCode::OUTPUT_BUFFER_TOO_SMALL;
last_error = OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
return std::size_t(-1);
}
std::uint8_t tmp[olm::KEY_LENGTH * 3];
@ -208,7 +207,7 @@ std::size_t olm::Session::session_id(
pos = olm::store_array(pos, alice_identity_key.public_key);
pos = olm::store_array(pos, alice_base_key.public_key);
pos = olm::store_array(pos, bob_one_time_key.public_key);
olm::sha256(tmp, sizeof(tmp), id);
_olm_crypto_sha256(tmp, sizeof(tmp), id);
return session_id_length();
}
@ -286,7 +285,7 @@ std::size_t olm::Session::encrypt(
std::uint8_t * message, std::size_t message_length
) {
if (message_length < encrypt_message_length(plaintext_length)) {
last_error = olm::ErrorCode::OUTPUT_BUFFER_TOO_SMALL;
last_error = OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
return std::size_t(-1);
}
std::uint8_t * message_body;
@ -321,7 +320,7 @@ std::size_t olm::Session::encrypt(
if (result == std::size_t(-1)) {
last_error = ratchet.last_error;
ratchet.last_error = olm::ErrorCode::SUCCESS;
ratchet.last_error = OlmErrorCode::OLM_SUCCESS;
return result;
}
@ -342,7 +341,7 @@ std::size_t olm::Session::decrypt_max_plaintext_length(
olm::PreKeyMessageReader reader;
decode_one_time_key_message(reader, message, message_length);
if (!reader.message) {
last_error = olm::ErrorCode::BAD_MESSAGE_FORMAT;
last_error = OlmErrorCode::OLM_BAD_MESSAGE_FORMAT;
return std::size_t(-1);
}
message_body = reader.message;
@ -355,7 +354,7 @@ std::size_t olm::Session::decrypt_max_plaintext_length(
if (result == std::size_t(-1)) {
last_error = ratchet.last_error;
ratchet.last_error = olm::ErrorCode::SUCCESS;
ratchet.last_error = OlmErrorCode::OLM_SUCCESS;
}
return result;
}
@ -375,7 +374,7 @@ std::size_t olm::Session::decrypt(
olm::PreKeyMessageReader reader;
decode_one_time_key_message(reader, message, message_length);
if (!reader.message) {
last_error = olm::ErrorCode::BAD_MESSAGE_FORMAT;
last_error = OlmErrorCode::OLM_BAD_MESSAGE_FORMAT;
return std::size_t(-1);
}
message_body = reader.message;
@ -388,7 +387,7 @@ std::size_t olm::Session::decrypt(
if (result == std::size_t(-1)) {
last_error = ratchet.last_error;
ratchet.last_error = olm::ErrorCode::SUCCESS;
ratchet.last_error = OlmErrorCode::OLM_SUCCESS;
return result;
}
@ -435,7 +434,7 @@ std::uint8_t const * olm::unpickle(
uint32_t pickle_version;
pos = olm::unpickle(pos, end, pickle_version);
if (pickle_version != SESSION_PICKLE_VERSION) {
value.last_error = olm::ErrorCode::UNKNOWN_PICKLE_VERSION;
value.last_error = OlmErrorCode::OLM_UNKNOWN_PICKLE_VERSION;
return end;
}
pos = olm::unpickle(pos, end, value.received_message);

View File

@ -18,12 +18,12 @@
olm::Utility::Utility(
) : last_error(olm::ErrorCode::SUCCESS) {
) : last_error(OlmErrorCode::OLM_SUCCESS) {
}
size_t olm::Utility::sha256_length() {
return olm::SHA256_OUTPUT_LENGTH;
return SHA256_OUTPUT_LENGTH;
}
@ -32,11 +32,11 @@ size_t olm::Utility::sha256(
std::uint8_t * output, std::size_t output_length
) {
if (output_length < sha256_length()) {
last_error = olm::ErrorCode::OUTPUT_BUFFER_TOO_SMALL;
last_error = OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
return std::size_t(-1);
}
olm::sha256(input, input_length, output);
return olm::SHA256_OUTPUT_LENGTH;
_olm_crypto_sha256(input, input_length, output);
return SHA256_OUTPUT_LENGTH;
}
@ -46,11 +46,11 @@ size_t olm::Utility::ed25519_verify(
std::uint8_t const * signature, std::size_t signature_length
) {
if (signature_length < olm::SIGNATURE_LENGTH) {
last_error = olm::ErrorCode::BAD_MESSAGE_MAC;
last_error = OlmErrorCode::OLM_BAD_MESSAGE_MAC;
return std::size_t(-1);
}
if (!olm::ed25519_verify(key, message, message_length, signature)) {
last_error = olm::ErrorCode::BAD_MESSAGE_MAC;
last_error = OlmErrorCode::OLM_BAD_MESSAGE_MAC;
return std::size_t(-1);
}
return std::size_t(0);

View File

@ -1,10 +1,11 @@
#include "olm/base64.hh"
#include "olm/base64.h"
#include "unittest.hh"
int main() {
{ /* Base64 encode test */
TestCase test_case("Base64 encode test");
TestCase test_case("Base64 C++ binding encode test");
std::uint8_t input[] = "Hello World";
std::uint8_t expected_output[] = "SGVsbG8gV29ybGQ";
@ -18,8 +19,24 @@ olm::encode_base64(input, input_length, output);
assert_equals(expected_output, output, output_length);
}
{
TestCase test_case("Base64 C binding encode test");
std::uint8_t input[] = "Hello World";
std::uint8_t expected_output[] = "SGVsbG8gV29ybGQ";
std::size_t input_length = sizeof(input) - 1;
std::size_t output_length = ::_olm_encode_base64_length(input_length);
assert_equals(std::size_t(15), output_length);
std::uint8_t output[output_length];
output_length = ::_olm_encode_base64(input, input_length, output);
assert_equals(std::size_t(15), output_length);
assert_equals(expected_output, output, output_length);
}
{ /* Base64 decode test */
TestCase test_case("Base64 decode test");
TestCase test_case("Base64 C++ binding decode test");
std::uint8_t input[] = "SGVsbG8gV29ybGQ";
std::uint8_t expected_output[] = "Hello World";
@ -33,4 +50,21 @@ olm::decode_base64(input, input_length, output);
assert_equals(expected_output, output, output_length);
}
{
TestCase test_case("Base64 C binding decode test");
std::uint8_t input[] = "SGVsbG8gV29ybGQ";
std::uint8_t expected_output[] = "Hello World";
std::size_t input_length = sizeof(input) - 1;
std::size_t output_length = ::_olm_decode_base64_length(input_length);
assert_equals(std::size_t(11), output_length);
std::uint8_t output[output_length];
output_length = ::_olm_decode_base64(input, input_length, output);
assert_equals(std::size_t(11), output_length);
assert_equals(expected_output, output, output_length);
}
}

View File

@ -186,7 +186,7 @@ std::uint8_t expected[32] = {
std::uint8_t actual[32];
olm::sha256(input, sizeof(input), actual);
_olm_crypto_sha256(input, sizeof(input), actual);
assert_equals(expected, actual, 32);
@ -207,7 +207,7 @@ std::uint8_t expected[32] = {
std::uint8_t actual[32];
olm::hmac_sha256(input, sizeof(input), input, sizeof(input), actual);
_olm_crypto_hmac_sha256(input, sizeof(input), input, sizeof(input), actual);
assert_equals(expected, actual, 32);
@ -242,7 +242,7 @@ std::uint8_t hmac_expected_output[32] = {
std::uint8_t hmac_actual_output[32] = {};
olm::hmac_sha256(
_olm_crypto_hmac_sha256(
salt, sizeof(salt),
input, sizeof(input),
hmac_actual_output
@ -261,7 +261,7 @@ std::uint8_t hkdf_expected_output[42] = {
std::uint8_t hkdf_actual_output[42] = {};
olm::hkdf_sha256(
_olm_crypto_hkdf_sha256(
input, sizeof(input),
salt, sizeof(salt),
info, sizeof(info),

View File

@ -1,4 +1,4 @@
#include "olm/olm.hh"
#include "olm/olm.h"
#include "unittest.hh"
#include <cstddef>

View File

@ -1,4 +1,4 @@
#include "olm/olm.hh"
#include "olm/olm.h"
#include "unittest.hh"
const char * test_cases[] = {

View File

@ -1,4 +1,4 @@
#include "olm/olm.hh"
#include "olm/olm.h"
#include "unittest.hh"
int main() {

View File

@ -1,4 +1,4 @@
#include "olm/olm.hh"
#include "olm/olm.h"
#include "unittest.hh"
#include <cstddef>

View File

@ -1,4 +1,4 @@
#include "olm/olm.hh"
#include "olm/olm.h"
#include "unittest.hh"
#include <cstddef>

View File

@ -13,7 +13,7 @@
* limitations under the License.
*/
#include "olm/ratchet.hh"
#include "olm/cipher.hh"
#include "olm/cipher.h"
#include "unittest.hh"
@ -28,9 +28,8 @@ olm::KdfInfo kdf_info = {
ratchet_info, sizeof(ratchet_info) - 1
};
olm::CipherAesSha256 cipher(
message_info, sizeof(message_info) - 1
);
_olm_cipher_aes_sha_256 cipher0 = OLM_CIPHER_INIT_AES_SHA_256(message_info);
_olm_cipher *cipher = OLM_CIPHER_BASE(&cipher0);
std::uint8_t random_bytes[] = "0123456789ABDEF0123456789ABCDEF";
olm::Curve25519KeyPair alice_key;