From 816435a86097a6609cb6e5ad422083bc49b19632 Mon Sep 17 00:00:00 2001 From: Mark Haines Date: Thu, 11 Jun 2015 14:20:35 +0100 Subject: Move AES specific details behind a cipher interface --- include/axolotl/cipher.hh | 127 +++++++++++++++++++++++++++++++++++++++++++++ include/axolotl/list.hh | 2 +- include/axolotl/message.hh | 22 ++++---- include/axolotl/ratchet.hh | 32 ++++++------ 4 files changed, 155 insertions(+), 28 deletions(-) create mode 100644 include/axolotl/cipher.hh (limited to 'include/axolotl') diff --git a/include/axolotl/cipher.hh b/include/axolotl/cipher.hh new file mode 100644 index 0000000..93974fd --- /dev/null +++ b/include/axolotl/cipher.hh @@ -0,0 +1,127 @@ +/* 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 AXOLOTL_CIPHER_HH_ +#define AXOLOTL_CIPHER_HH_ + +#include + +namespace axolotl { + +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 + * + * 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 + * + * 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 /* AXOLOTL_CIPHER_HH_ */ diff --git a/include/axolotl/list.hh b/include/axolotl/list.hh index d1407b8..ae8900c 100644 --- a/include/axolotl/list.hh +++ b/include/axolotl/list.hh @@ -92,7 +92,7 @@ public: } List & operator=(List const & other) { - if (this = &other) { + if (this == &other) { return *this; } T * this_pos = _data; diff --git a/include/axolotl/message.hh b/include/axolotl/message.hh index 5cd4211..cfbb715 100644 --- a/include/axolotl/message.hh +++ b/include/axolotl/message.hh @@ -30,22 +30,17 @@ std::size_t encode_message_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; + std::uint8_t const * input; std::size_t input_length; + std::uint8_t const * ratchet_key; std::size_t ratchet_key_length; + std::uint8_t const * ciphertext; std::size_t ciphertext_length; }; @@ -53,7 +48,9 @@ struct MessageReader { * Writes the message headers into the output buffer. * Returns a writer struct populated with pointers into the output buffer. */ -MessageWriter encode_message( + +void encode_message( + MessageWriter & writer, std::uint8_t version, std::uint32_t counter, std::size_t ratchet_key_length, @@ -64,10 +61,11 @@ MessageWriter encode_message( /** * 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. + * Populates the reader struct with pointers into the input buffer. + * On failure returns std::size_t(-1). */ -MessageReader decode_message( +std::size_t decode_message( + MessageReader & reader, std::uint8_t const * input, std::size_t input_length, std::size_t mac_length ); diff --git a/include/axolotl/ratchet.hh b/include/axolotl/ratchet.hh index cf41359..f4eeafa 100644 --- a/include/axolotl/ratchet.hh +++ b/include/axolotl/ratchet.hh @@ -18,6 +18,8 @@ namespace axolotl { +class Cipher; + typedef std::uint8_t SharedKey[32]; @@ -29,9 +31,7 @@ struct ChainKey { struct MessageKey { std::uint32_t index; - Aes256Key cipher_key; - SharedKey mac_key; - Aes256Iv iv; + SharedKey key; }; @@ -72,21 +72,23 @@ struct KdfInfo { 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 + KdfInfo const & kdf_info, + Cipher const & ratchet_cipher ); - /** A some strings identifing the application to feed into the KDF. */ - const KdfInfo &kdf_info; + /** 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; - /** The last error that happened encypting or decrypting a message. */ + /** The last error that happened encrypting or decrypting a message. */ ErrorCode last_error; /** The root key is used to generate chain keys from the ephemeral keys. @@ -98,7 +100,7 @@ struct Session { * with a new empheral key when we next send a message. */ List sender_chain; - /** The receiver chain is used to decrypt recieved messages. We store the + /** The receiver chain is used to decrypt received messages. We store the * last few chains so we can decrypt any out of order messages we haven't * received yet. */ List receiver_chains; @@ -114,7 +116,7 @@ struct Session { Curve25519PublicKey const & their_ratchet_key ); - /** Intialise the session using a shared secret and the public/private key + /** Initialise the session using a shared secret and the public/private key * pair for the first ratchet key */ void initialise_as_alice( std::uint8_t const * shared_secret, std::size_t shared_secret_length, @@ -150,7 +152,7 @@ struct Session { * generate a new ephemeral key, or will be 0 bytes otherwise.*/ std::size_t encrypt_random_length(); - /** Encrypt some plaintext. Returns the length of the encrypted message + /** 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 @@ -161,16 +163,16 @@ struct Session { std::uint8_t * output, std::size_t max_output_length ); - /** An upper bound on the number of bytes of plaintext the decrypt method + /** 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( std::size_t input_length ); - /** Decrypt a message. Returns the length of the decrypted plaintext or + /** 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 - * plaintext buffer is too small. The last_error will be + * 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 -- cgit v1.2.3