aboutsummaryrefslogtreecommitdiff
path: root/include/axolotl
diff options
context:
space:
mode:
Diffstat (limited to 'include/axolotl')
-rw-r--r--include/axolotl/axolotl.hh114
-rw-r--r--include/axolotl/crypto.hh90
-rw-r--r--include/axolotl/list.hh100
-rw-r--r--include/axolotl/message.hh62
4 files changed, 366 insertions, 0 deletions
diff --git a/include/axolotl/axolotl.hh b/include/axolotl/axolotl.hh
new file mode 100644
index 0000000..ead52fc
--- /dev/null
+++ b/include/axolotl/axolotl.hh
@@ -0,0 +1,114 @@
+
+#include "axolotl/crypto.hh"
+#include "axolotl/list.hh"
+
+namespace axolotl {
+
+typedef std::uint8_t SharedKey[32];
+
+
+struct ChainKey {
+ std::uint32_t index;
+ SharedKey key;
+};
+
+
+struct MessageKey {
+ std::uint32_t index;
+ Aes256Key cipher_key;
+ SharedKey mac_key;
+ Aes256Iv iv;
+};
+
+
+struct SenderChain {
+ Curve25519KeyPair ratchet_key;
+ ChainKey chain_key;
+};
+
+
+struct ReceiverChain {
+ Curve25519PublicKey ratchet_key;
+ ChainKey chain_key;
+};
+
+
+struct SkippedMessageKey {
+ Curve25519PublicKey ratchet_key;
+ MessageKey message_key;
+};
+
+
+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 */
+};
+
+
+static std::size_t const MAX_RECEIVER_CHAINS = 5;
+static std::size_t const MAX_SKIPPED_MESSAGE_KEYS = 40;
+
+
+struct KdfInfo {
+ std::uint8_t const * root_info;
+ std::size_t root_info_length;
+ std::uint8_t const * ratchet_info;
+ std::size_t ratchet_info_length;
+ std::uint8_t const * message_info;
+ std::size_t message_info_length;
+};
+
+
+struct Session {
+
+ Session(
+ KdfInfo const & kdf_info
+ );
+
+ /** A pair of string to feed into the KDF identifing the application */
+ KdfInfo kdf_info;
+ /** The last error that happened encypting or decrypting a message */
+ ErrorCode last_error;
+ SharedKey root_key;
+ List<SenderChain, 1> sender_chain;
+ List<ReceiverChain, MAX_RECEIVER_CHAINS> receiver_chains;
+ List<SkippedMessageKey, MAX_SKIPPED_MESSAGE_KEYS> skipped_message_keys;
+
+ void initialise_as_bob(
+ std::uint8_t const * shared_secret, std::size_t shared_secret_length,
+ Curve25519PublicKey const & their_ratchet_key
+ );
+
+ void initialise_as_alice(
+ std::uint8_t const * shared_secret, std::size_t shared_secret_length,
+ Curve25519KeyPair const & our_ratchet_key
+ );
+
+ std::size_t encrypt_max_output_length(
+ std::size_t plaintext_length
+ );
+
+ std::size_t encrypt_random_length();
+
+ std::size_t encrypt(
+ std::uint8_t const * plaintext, std::size_t plaintext_length,
+ std::uint8_t const * random, std::size_t random_length,
+ std::uint8_t * output, std::size_t max_output_length
+ );
+
+ std::size_t decrypt_max_plaintext_length(
+ std::size_t input_length
+ );
+
+ std::size_t decrypt(
+ std::uint8_t const * input, std::size_t input_length,
+ std::uint8_t * plaintext, std::size_t max_plaintext_length
+ );
+};
+
+
+} // namespace axololt
diff --git a/include/axolotl/crypto.hh b/include/axolotl/crypto.hh
new file mode 100644
index 0000000..f1e81ac
--- /dev/null
+++ b/include/axolotl/crypto.hh
@@ -0,0 +1,90 @@
+#include <cstdint>
+#include <cstddef>
+
+namespace axolotl {
+
+
+struct Curve25519PublicKey {
+ static const int LENGTH = 32;
+ std::uint8_t public_key[32];
+};
+
+
+struct Curve25519KeyPair : public Curve25519PublicKey {
+ std::uint8_t private_key[32];
+};
+
+
+void generate_key(
+ std::uint8_t const * random_32_bytes,
+ Curve25519KeyPair & key_pair
+);
+
+
+const std::size_t CURVE25519_SHARED_SECRET_LENGTH = 32;
+
+
+void curve25519_shared_secret(
+ Curve25519KeyPair const & our_key,
+ Curve25519PublicKey const & their_key,
+ std::uint8_t * output
+);
+
+
+struct Aes256Key {
+ static const int LENGTH = 32;
+ std::uint8_t key[32];
+};
+
+
+struct Aes256Iv {
+ static const int LENGTH = 16;
+ std::uint8_t iv[16];
+};
+
+
+std::size_t aes_encrypt_cbc_length(
+ std::size_t input_length
+);
+
+
+void aes_encrypt_cbc(
+ Aes256Key const & key,
+ Aes256Iv const & iv,
+ std::uint8_t const * input, std::size_t input_length,
+ std::uint8_t * output
+);
+
+
+std::size_t aes_decrypt_cbc(
+ Aes256Key const & key,
+ Aes256Iv const & iv,
+ std::uint8_t const * input, std::size_t input_length,
+ std::uint8_t * output
+);
+
+
+void sha256(
+ std::uint8_t const * input, std::size_t input_length,
+ std::uint8_t * output
+);
+
+
+const std::size_t HMAC_SHA256_OUTPUT_LENGTH = 32;
+
+
+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
+);
+
+
+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 axolotl
diff --git a/include/axolotl/list.hh b/include/axolotl/list.hh
new file mode 100644
index 0000000..4c87630
--- /dev/null
+++ b/include/axolotl/list.hh
@@ -0,0 +1,100 @@
+#include <cstddef>
+
+namespace axolotl {
+
+template<typename T, std::size_t max_size>
+class List {
+public:
+ List() : _end(_data) {}
+
+ typedef T * iterator;
+ typedef T const * const_iterator;
+
+ T * begin() { return _data; }
+ T * end() { return _end; }
+ T const * begin() const { return _data; }
+ T const * end() const { return _end; }
+
+ /**
+ * Is the list empty?
+ */
+ bool empty() const { return _end == _data; }
+
+ /**
+ * The number of items in the list.
+ */
+ std::size_t size() const { return _end - _data; }
+
+ T & operator[](std::size_t index) { return _data[index]; }
+
+ T const & operator[](std::size_t index) const { return _data[index]; }
+
+ /**
+ * Erase the item from the list at the given position.
+ */
+ void erase(T * pos) {
+ --_end;
+ while (pos != _end) {
+ *pos = *(pos + 1);
+ ++pos;
+ }
+ }
+
+ /**
+ * Make space for an item in the list at a given position.
+ * If inserting the item makes the list longer than max_size then
+ * the end of the list is discarded.
+ * Returns the where the item is inserted.
+ */
+ T * insert(T * pos) {
+ if (_end != _data + max_size) {
+ ++_end;
+ } else if (pos == _end) {
+ --pos;
+ }
+ T * tmp = pos;
+ while (tmp != _end - 1) {
+ *(tmp + 1) = *tmp;
+ ++tmp;
+ }
+ return pos;
+ }
+
+ /**
+ * Make space for an item in the list at the start of the list
+ */
+ T * insert() { return insert(begin()); }
+
+ /**
+ * Insert an item into the list at a given position.
+ * If inserting the item makes the list longer than max_size then
+ * the end of the list is discarded.
+ * Returns the where the item is inserted.
+ */
+ T * insert(T * pos, T const & value) {
+ pos = insert(pos);
+ *pos = value;
+ return pos;
+ }
+
+ List<T, max_size> & operator=(List<T, max_size> const & other) {
+ if (this = &other) {
+ return *this;
+ }
+ T * this_pos = _data;
+ T * const other_pos = other._data;
+ while (other_pos != other._end) {
+ *this_pos = *other;
+ ++this_pos;
+ ++other_pos;
+ }
+ _end = this_pos;
+ return *this;
+ }
+
+private:
+ T * _end;
+ T _data[max_size];
+};
+
+} // namespace axolotl
diff --git a/include/axolotl/message.hh b/include/axolotl/message.hh
new file mode 100644
index 0000000..ac4b3e0
--- /dev/null
+++ b/include/axolotl/message.hh
@@ -0,0 +1,62 @@
+#include <cstddef>
+#include <cstdint>
+
+
+namespace axolotl {
+
+/**
+ * The length of the buffer needed to hold a message.
+ */
+std::size_t encode_message_length(
+ std::uint32_t counter,
+ std::size_t ratchet_key_length,
+ std::size_t ciphertext_length,
+ std::size_t mac_length
+);
+
+
+struct MessageWriter {
+ std::size_t body_length;
+ std::uint8_t * ratchet_key;
+ std::uint8_t * ciphertext;
+ std::uint8_t * mac;
+};
+
+
+struct MessageReader {
+ std::size_t body_length;
+ std::uint8_t version;
+ std::uint32_t counter;
+ std::size_t ratchet_key_length;
+ std::size_t ciphertext_length;
+ std::uint8_t const * ratchet_key;
+ std::uint8_t const * ciphertext;
+ std::uint8_t const * mac;
+};
+
+
+/**
+ * Writes the message headers into the output buffer.
+ * Returns a writer struct populated with pointers into the output buffer.
+ */
+MessageWriter encode_message(
+ std::uint8_t version,
+ std::uint32_t counter,
+ std::size_t ratchet_key_length,
+ std::size_t ciphertext_length,
+ std::uint8_t * output
+);
+
+
+/**
+ * Reads the message headers from the input buffer.
+ * Returns a reader struct populated with pointers into the input buffer.
+ * On failure the returned body_length will be 0.
+ */
+MessageReader decode_message(
+ std::uint8_t const * input, std::size_t input_length,
+ std::size_t mac_length
+);
+
+
+} // namespace axolotl