aboutsummaryrefslogtreecommitdiff
path: root/include/olm
diff options
context:
space:
mode:
Diffstat (limited to 'include/olm')
-rw-r--r--include/olm/base64.hh24
-rw-r--r--include/olm/cipher.hh4
-rw-r--r--include/olm/crypto.hh26
-rw-r--r--include/olm/memory.hh49
-rw-r--r--include/olm/pickle.hh2
-rw-r--r--include/olm/ratchet.hh2
-rw-r--r--include/olm/session.hh46
-rw-r--r--include/olm/utility.hh9
8 files changed, 137 insertions, 25 deletions
diff --git a/include/olm/base64.hh b/include/olm/base64.hh
index 018924a..da4641d 100644
--- a/include/olm/base64.hh
+++ b/include/olm/base64.hh
@@ -20,31 +20,45 @@
namespace olm {
-
+/**
+ * The number of bytes of unpadded base64 needed to encode a length of input.
+ */
static std::size_t encode_base64_length(
std::size_t input_length
) {
return 4 * ((input_length + 2) / 3) + (input_length + 2) % 3 - 2;
}
-
+/**
+ * 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.
+ */
std::uint8_t * encode_base64(
std::uint8_t const * input, std::size_t input_length,
std::uint8_t * output
);
-
+/**
+ * The number of bytes of raw data a length of unpadded base64 will encode to.
+ * Returns std::size_t(-1) if the length is not a valid length for base64.
+ */
std::size_t decode_base64_length(
std::size_t input_length
);
-
+/**
+ * Decodes the unpadded base64 input to raw bytes.
+ * Writes decode_base64_length(input_length) bytes to the output buffer.
+ * The output can overlap with the first three quarters of the input buffer.
+ * That is, the input pointers and output pointer may be the same.
+ */
std::uint8_t const * decode_base64(
std::uint8_t const * input, std::size_t input_length,
std::uint8_t * output
);
-
} // namespace olm
diff --git a/include/olm/cipher.hh b/include/olm/cipher.hh
index f71b3af..c561972 100644
--- a/include/olm/cipher.hh
+++ b/include/olm/cipher.hh
@@ -47,6 +47,8 @@ public:
* 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.
*/
@@ -73,6 +75,8 @@ public:
* 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.
diff --git a/include/olm/crypto.hh b/include/olm/crypto.hh
index b845bfe..7a05f8d 100644
--- a/include/olm/crypto.hh
+++ b/include/olm/crypto.hh
@@ -20,28 +20,27 @@
namespace olm {
+static const std::size_t KEY_LENGTH = 32;
+static const std::size_t SIGNATURE_LENGTH = 64;
+static const std::size_t IV_LENGTH = 16;
struct Curve25519PublicKey {
- static const int LENGTH = 32;
- std::uint8_t public_key[32];
+ std::uint8_t public_key[KEY_LENGTH];
};
struct Curve25519KeyPair : public Curve25519PublicKey {
- static const int LENGTH = 64;
- std::uint8_t private_key[32];
+ std::uint8_t private_key[KEY_LENGTH];
};
struct Ed25519PublicKey {
- static const int LENGTH = 32;
- std::uint8_t public_key[32];
+ std::uint8_t public_key[KEY_LENGTH];
};
struct Ed25519KeyPair : public Ed25519PublicKey {
- static const int LENGTH = 64;
- std::uint8_t private_key[32];
+ std::uint8_t private_key[KEY_LENGTH];
};
@@ -52,9 +51,6 @@ void curve25519_generate_key(
);
-const std::size_t CURVE25519_SHARED_SECRET_LENGTH = 32;
-
-
/** Create a shared secret using our private key and their public key.
* The output buffer must be at least 32 bytes long. */
void curve25519_shared_secret(
@@ -109,14 +105,12 @@ bool ed25519_verify(
struct Aes256Key {
- static const int LENGTH = 32;
- std::uint8_t key[32];
+ std::uint8_t key[KEY_LENGTH];
};
struct Aes256Iv {
- static const int LENGTH = 16;
- std::uint8_t iv[16];
+ std::uint8_t iv[IV_LENGTH];
};
@@ -156,7 +150,7 @@ void sha256(
);
-const std::size_t HMAC_SHA256_OUTPUT_LENGTH = 32;
+const std::size_t SHA256_OUTPUT_LENGTH = 32;
/** HMAC: Keyed-Hashing for Message Authentication
diff --git a/include/olm/memory.hh b/include/olm/memory.hh
index b19c74b..128990a 100644
--- a/include/olm/memory.hh
+++ b/include/olm/memory.hh
@@ -14,6 +14,8 @@
*/
#include <cstddef>
#include <cstdint>
+#include <cstring>
+#include <type_traits>
namespace olm {
@@ -35,4 +37,51 @@ bool is_equal(
std::size_t length
);
+/** Check if two fixed size arrays are equals */
+template<typename T>
+bool array_equal(
+ T const & array_a,
+ T const & array_b
+) {
+ static_assert(
+ std::is_array<T>::value
+ && std::is_convertible<T, std::uint8_t *>::value
+ && sizeof(T) > 0,
+ "Arguments to array_equal must be std::uint8_t arrays[]."
+ );
+ return is_equal(array_a, array_b, sizeof(T));
+}
+
+/** Copy into a fixed size array */
+template<typename T>
+std::uint8_t const * load_array(
+ T & destination,
+ std::uint8_t const * source
+) {
+ static_assert(
+ std::is_array<T>::value
+ && std::is_convertible<T, std::uint8_t *>::value
+ && sizeof(T) > 0,
+ "The first argument to load_array must be a std::uint8_t array[]."
+ );
+ std::memcpy(destination, source, sizeof(T));
+ return source + sizeof(T);
+}
+
+/** Copy from a fixed size array */
+template<typename T>
+std::uint8_t * store_array(
+ std::uint8_t * destination,
+ T const & source
+) {
+ static_assert(
+ std::is_array<T>::value
+ && std::is_convertible<T, std::uint8_t *>::value
+ && sizeof(T) > 0,
+ "The second argument to store_array must be a std::uint8_t array[]."
+ );
+ std::memcpy(destination, source, sizeof(T));
+ return destination + sizeof(T);
+}
+
} // namespace olm
diff --git a/include/olm/pickle.hh b/include/olm/pickle.hh
index 7a2bd1b..27f1f26 100644
--- a/include/olm/pickle.hh
+++ b/include/olm/pickle.hh
@@ -109,7 +109,7 @@ std::uint8_t const * unpickle(
) {
std::uint32_t size;
pos = unpickle(pos, end, size);
- while (size--) {
+ while (size-- && pos != end) {
T * value = list.insert(list.end());
pos = unpickle(pos, end, *value);
}
diff --git a/include/olm/ratchet.hh b/include/olm/ratchet.hh
index 7274255..2393e5b 100644
--- a/include/olm/ratchet.hh
+++ b/include/olm/ratchet.hh
@@ -21,7 +21,7 @@ namespace olm {
class Cipher;
-typedef std::uint8_t SharedKey[32];
+typedef std::uint8_t SharedKey[olm::KEY_LENGTH];
struct ChainKey {
diff --git a/include/olm/session.hh b/include/olm/session.hh
index 993a8da..b21b0aa 100644
--- a/include/olm/session.hh
+++ b/include/olm/session.hh
@@ -39,8 +39,13 @@ struct Session {
Curve25519PublicKey alice_base_key;
Curve25519PublicKey bob_one_time_key;
+ /** The number of random bytes that are needed to create a new outbound
+ * session. This will be 64 bytes since two ephemeral keys are needed. */
std::size_t new_outbound_session_random_length();
+ /** Start a new outbound session. Returns std::size_t(-1) on failure. On
+ * failure last_error will be set with an error code. The last_error will be
+ * NOT_ENOUGH_RANDOM if the number of random bytes was too small. */
std::size_t new_outbound_session(
Account const & local_account,
Curve25519PublicKey const & identity_key,
@@ -48,42 +53,79 @@ struct Session {
std::uint8_t const * random, std::size_t random_length
);
+ /** Start a new inbound session from a pre-key message.
+ * Returns std::size_t(-1) on failure. On failure last_error will be set
+ * with an error code. The last_error will be BAD_MESSAGE_FORMAT if
+ * the message headers could not be decoded. */
std::size_t new_inbound_session(
Account & local_account,
Curve25519PublicKey const * their_identity_key,
- std::uint8_t const * one_time_key_message, std::size_t message_length
+ std::uint8_t const * pre_key_message, std::size_t message_length
);
+ /** The number of bytes written by session_id() */
std::size_t session_id_length();
+ /** An identifier for this session. Generated by hashing the public keys
+ * used to create the session. Returns the length of the session id on
+ * success or std::size_t(-1) on failure. On failure last_error will be set
+ * with an error code. The last_error will be OUTPUT_BUFFER_TOO_SMALL if
+ * the id buffer was too small. */
std::size_t session_id(
std::uint8_t * id, std::size_t id_length
);
+ /** True if this session can be used to decode an inbound pre-key message.
+ * This can be used to test whether a pre-key message should be decoded
+ * with an existing session or if a new session will need to be created.
+ * Returns true if the session is the same. Returns false if either the
+ * session does not match or the pre-key message could not be decoded.
+ */
bool matches_inbound_session(
Curve25519PublicKey const * their_identity_key,
- std::uint8_t const * one_time_key_message, std::size_t message_length
+ std::uint8_t const * pre_key_message, std::size_t message_length
);
+ /** Whether the next message will be a pre-key message or a normal message.
+ * An outbound session will send pre-key messages until it receives a
+ * message with a ratchet key. */
MessageType encrypt_message_type();
std::size_t encrypt_message_length(
std::size_t plaintext_length
);
+ /** The number of bytes of random data the encrypt method will need to
+ * encrypt a message. This will be 32 bytes if the session needs to
+ * generate a new ephemeral key, or will be 0 bytes otherwise. */
std::size_t encrypt_random_length();
+ /** Encrypt some plain-text. Returns the length of the encrypted message
+ * or std::size_t(-1) on failure. On failure last_error will be set with
+ * an error code. The last_error will be NOT_ENOUGH_RANDOM if the number
+ * of random bytes is too small. The last_error will be
+ * OUTPUT_BUFFER_TOO_SMALL if the output buffer is too small. */
std::size_t encrypt(
std::uint8_t const * plaintext, std::size_t plaintext_length,
std::uint8_t const * random, std::size_t random_length,
std::uint8_t * message, std::size_t message_length
);
+ /** An upper bound on the number of bytes of plain-text the decrypt method
+ * will write for a given input message length. */
std::size_t decrypt_max_plaintext_length(
MessageType message_type,
std::uint8_t const * message, std::size_t message_length
);
+ /** Decrypt a message. Returns the length of the decrypted plain-text or
+ * std::size_t(-1) on failure. On failure last_error will be set with an
+ * error code. The last_error will be OUTPUT_BUFFER_TOO_SMALL if the
+ * plain-text buffer is too small. The last_error will be
+ * BAD_MESSAGE_VERSION if the message was encrypted with an unsupported
+ * version of the protocol. The last_error will be BAD_MESSAGE_FORMAT if
+ * the message headers could not be decoded. The last_error will be
+ * BAD_MESSAGE_MAC if the message could not be verified */
std::size_t decrypt(
MessageType message_type,
std::uint8_t const * message, std::size_t message_length,
diff --git a/include/olm/utility.hh b/include/olm/utility.hh
index 241d7e0..5329a59 100644
--- a/include/olm/utility.hh
+++ b/include/olm/utility.hh
@@ -31,13 +31,22 @@ struct Utility {
ErrorCode last_error;
+ /** The length of a SHA-256 hash in bytes. */
std::size_t sha256_length();
+ /** Compute a SHA-256 hash. Returns the length of the SHA-256 hash in bytes
+ * on success. Returns std::size_t(-1) on failure. On failure last_error
+ * will be set with an error code. If the output buffer was too small then
+ * last error will be OUTPUT_BUFFER_TOO_SMALL. */
std::size_t sha256(
std::uint8_t const * input, std::size_t input_length,
std::uint8_t * output, std::size_t output_length
);
+ /** Verify a ed25519 signature. Returns std::size_t(0) on success. Returns
+ * std::size_t(-1) on failure or if the signature was invalid. On failure
+ * last_error will be set with an error code. If the signature was too short
+ * or was not a valid signature then last_error will be BAD_MESSAGE_MAC. */
std::size_t ed25519_verify(
Ed25519PublicKey const & key,
std::uint8_t const * message, std::size_t message_length,