Commit 2e7800cf authored by Richard van der Hoff's avatar Richard van der Hoff
Browse files

Merge branch 'rav/c_bindings'

parents b1c5732f 2fd28a66
......@@ -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))))
......
......@@ -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();
......
/* 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_ */
......@@ -13,30 +13,32 @@
* limitations under the License.
*/
#ifndef OLM_CIPHER_HH_
#define OLM_CIPHER_HH_
#ifndef OLM_CIPHER_H_
#define OLM_CIPHER_H_
#include <cstdint>
#include <cstddef>
#include <stdint.h>
#include <stdlib.h>
namespace olm {
#ifdef __cplusplus
extern "C" {
#endif
class Cipher {
public:
virtual ~Cipher();
struct _olm_cipher;
struct _olm_cipher_ops {
/**
* Returns the length of the message authentication code that will be
* appended to the output.
*/
virtual std::size_t mac_length() const = 0;
size_t (*mac_length)(const struct _olm_cipher *cipher);
/**
* 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;
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
......@@ -49,23 +51,25 @@ public:
*
* 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
* 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.
*/
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;
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.
*/
virtual std::size_t decrypt_max_plaintext_length(
std::size_t ciphertext_length
) const = 0;
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
......@@ -77,56 +81,58 @@ public:
*
* 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
* 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.
*/
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;
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 */
};
class CipherAesSha256 : public Cipher {
public:
CipherAesSha256(
std::uint8_t const * kdf_info, std::size_t kdf_info_length
);
struct _olm_cipher_aes_sha_256 {
struct _olm_cipher base_cipher;
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;
/** 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))
} // namespace
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* OLM_CIPHER_HH_ */
#endif /* OLM_CIPHER_H_ */
/* 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_ */
......@@ -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_ */
/* 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_ */
/* Copyright 2015 OpenMarket Ltd
/* 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.
......@@ -12,25 +12,30 @@
* 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_ */
/* 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_ */
/* 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 */