From 69f269ffaf88515f6d5c0b34178bf0096cf5773b Mon Sep 17 00:00:00 2001
From: Richard van der Hoff <richard@matrix.org>
Date: Fri, 2 Sep 2016 15:35:04 +0100
Subject: [PATCH] Convert AES functions to plain C

---
 include/olm/account.hh |  2 +-
 include/olm/crypto.h   | 35 +++++++++++++++++++++
 include/olm/crypto.hh  | 69 ------------------------------------------
 include/olm/pickle.hh  |  2 +-
 include/olm/ratchet.hh |  4 ++-
 src/cipher.cpp         | 16 +++++-----
 src/crypto.cpp         | 24 +++++++--------
 src/session.cpp        |  2 +-
 src/utility.cpp        |  2 +-
 tests/test_crypto.cpp  | 12 ++++----
 10 files changed, 68 insertions(+), 100 deletions(-)
 delete mode 100644 include/olm/crypto.hh

diff --git a/include/olm/account.hh b/include/olm/account.hh
index 4b7b190..7e58ca3 100644
--- a/include/olm/account.hh
+++ b/include/olm/account.hh
@@ -16,7 +16,7 @@
 #define OLM_ACCOUNT_HH_
 
 #include "olm/list.hh"
-#include "olm/crypto.hh"
+#include "olm/crypto.h"
 #include "olm/error.h"
 
 #include <cstdint>
diff --git a/include/olm/crypto.h b/include/olm/crypto.h
index 9fc3842..dbf78ed 100644
--- a/include/olm/crypto.h
+++ b/include/olm/crypto.h
@@ -57,6 +57,15 @@ extern "C" {
 /** length of an aes256 initialisation vector */
 #define AES256_IV_LENGTH 16
 
+struct _olm_aes256_key {
+    uint8_t key[AES256_KEY_LENGTH];
+};
+
+struct _olm_aes256_iv {
+    uint8_t iv[AES256_IV_LENGTH];
+};
+
+
 struct _olm_curve25519_public_key {
     uint8_t public_key[CURVE25519_KEY_LENGTH];
 };
@@ -84,6 +93,32 @@ struct _olm_ed25519_key_pair {
 };
 
 
+/** The length of output the aes_encrypt_cbc function will write */
+size_t _olm_crypto_aes_encrypt_cbc_length(
+    size_t input_length
+);
+
+/** Encrypts the input using AES256 in CBC mode with PKCS#7 padding.
+ * The output buffer must be big enough to hold the output including padding */
+void _olm_crypto_aes_encrypt_cbc(
+    const struct _olm_aes256_key *key,
+    const struct _olm_aes256_iv *iv,
+    const uint8_t *input, size_t input_length,
+    uint8_t *output
+);
+
+/** Decrypts the input using AES256 in CBC mode. The output buffer must be at
+ * least the same size as the input buffer. Returns the length of the plaintext
+ * without padding on success or std::size_t(-1) if the padding is invalid.
+ */
+size_t _olm_crypto_aes_decrypt_cbc(
+    const struct _olm_aes256_key *key,
+    const struct _olm_aes256_iv *iv,
+    uint8_t const * input, size_t input_length,
+    uint8_t * output
+);
+
+
 /** Computes SHA-256 of the input. The output buffer must be a least
  * SHA256_OUTPUT_LENGTH (32) bytes long. */
 void _olm_crypto_sha256(
diff --git a/include/olm/crypto.hh b/include/olm/crypto.hh
deleted file mode 100644
index e3098cc..0000000
--- a/include/olm/crypto.hh
+++ /dev/null
@@ -1,69 +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_CRYPTO_HH_
-#define OLM_CRYPTO_HH_
-
-#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 {
-
-
-struct Aes256Key {
-    std::uint8_t key[AES256_KEY_LENGTH];
-};
-
-
-struct Aes256Iv {
-    std::uint8_t iv[AES256_IV_LENGTH];
-};
-
-
-/** The length of output the aes_encrypt_cbc function will write */
-std::size_t aes_encrypt_cbc_length(
-    std::size_t input_length
-);
-
-
-/** Encrypts the input using AES256 in CBC mode with PKCS#7 padding.
- * The output buffer must be big enough to hold the output including padding */
-void aes_encrypt_cbc(
-    Aes256Key const & key,
-    Aes256Iv const & iv,
-    std::uint8_t const * input, std::size_t input_length,
-    std::uint8_t * output
-);
-
-
-/** Decrypts the input using AES256 in CBC mode. The output buffer must be at
- * least the same size as the input buffer. Returns the length of the plaintext
- * without padding on success or std::size_t(-1) if the padding is invalid.
- */
-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
-);
-
-
-} // namespace olm
-
-#endif /* OLM_CRYPTO_HH_ */
diff --git a/include/olm/pickle.hh b/include/olm/pickle.hh
index c0b6ebf..a09b8a1 100644
--- a/include/olm/pickle.hh
+++ b/include/olm/pickle.hh
@@ -16,7 +16,7 @@
 #define OLM_PICKLE_HH_
 
 #include "olm/list.hh"
-#include "olm/crypto.hh"
+#include "olm/crypto.h"
 
 #include <cstring>
 #include <cstdint>
diff --git a/include/olm/ratchet.hh b/include/olm/ratchet.hh
index cdcba6b..2e87e35 100644
--- a/include/olm/ratchet.hh
+++ b/include/olm/ratchet.hh
@@ -13,7 +13,9 @@
  * limitations under the License.
  */
 
-#include "olm/crypto.hh"
+#include <cstdint>
+
+#include "olm/crypto.h"
 #include "olm/list.hh"
 #include "olm/error.h"
 
diff --git a/src/cipher.cpp b/src/cipher.cpp
index 8e3d7a5..6b53690 100644
--- a/src/cipher.cpp
+++ b/src/cipher.cpp
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 #include "olm/cipher.h"
-#include "olm/crypto.hh"
+#include "olm/crypto.h"
 #include "olm/memory.hh"
 #include <cstring>
 
@@ -22,9 +22,9 @@ const std::size_t HMAC_KEY_LENGTH = 32;
 namespace {
 
 struct DerivedKeys {
-    olm::Aes256Key aes_key;
+    _olm_aes256_key aes_key;
     std::uint8_t mac_key[HMAC_KEY_LENGTH];
-    olm::Aes256Iv aes_iv;
+    _olm_aes256_iv aes_iv;
 };
 
 
@@ -58,7 +58,7 @@ size_t aes_sha_256_cipher_mac_length(const struct _olm_cipher *cipher) {
 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);
+    return _olm_crypto_aes_encrypt_cbc_length(plaintext_length);
 }
 
 size_t aes_sha_256_cipher_encrypt(
@@ -80,8 +80,8 @@ size_t aes_sha_256_cipher_encrypt(
 
     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_crypto_aes_encrypt_cbc(
+        &keys.aes_key, &keys.aes_iv, plaintext, plaintext_length, ciphertext
     );
 
     _olm_crypto_hmac_sha256(
@@ -126,8 +126,8 @@ size_t aes_sha_256_cipher_decrypt(
         return std::size_t(-1);
     }
 
-    std::size_t plaintext_length = olm::aes_decrypt_cbc(
-        keys.aes_key, keys.aes_iv, ciphertext, ciphertext_length, plaintext
+    std::size_t plaintext_length = _olm_crypto_aes_decrypt_cbc(
+        &keys.aes_key, &keys.aes_iv, ciphertext, ciphertext_length, plaintext
     );
 
     olm::unset(keys);
diff --git a/src/crypto.cpp b/src/crypto.cpp
index 89d9d72..5095c79 100644
--- a/src/crypto.cpp
+++ b/src/crypto.cpp
@@ -12,7 +12,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include "olm/crypto.hh"
+#include "olm/crypto.h"
 #include "olm/memory.hh"
 
 #include <cstring>
@@ -163,23 +163,23 @@ int _olm_crypto_ed25519_verify(
 }
 
 
-std::size_t olm::aes_encrypt_cbc_length(
+std::size_t _olm_crypto_aes_encrypt_cbc_length(
     std::size_t input_length
 ) {
     return input_length + AES_BLOCK_LENGTH - input_length % AES_BLOCK_LENGTH;
 }
 
 
-void olm::aes_encrypt_cbc(
-    olm::Aes256Key const & key,
-    olm::Aes256Iv const & iv,
+void _olm_crypto_aes_encrypt_cbc(
+    _olm_aes256_key const *key,
+    _olm_aes256_iv const *iv,
     std::uint8_t const * input, std::size_t input_length,
     std::uint8_t * output
 ) {
     std::uint32_t key_schedule[AES_KEY_SCHEDULE_LENGTH];
-    ::aes_key_setup(key.key, key_schedule, AES_KEY_BITS);
+    ::aes_key_setup(key->key, key_schedule, AES_KEY_BITS);
     std::uint8_t input_block[AES_BLOCK_LENGTH];
-    std::memcpy(input_block, iv.iv, AES_BLOCK_LENGTH);
+    std::memcpy(input_block, iv->iv, AES_BLOCK_LENGTH);
     while (input_length >= AES_BLOCK_LENGTH) {
         xor_block<AES_BLOCK_LENGTH>(input_block, input);
         ::aes_encrypt(input_block, output, key_schedule, AES_KEY_BITS);
@@ -201,17 +201,17 @@ void olm::aes_encrypt_cbc(
 }
 
 
-std::size_t olm::aes_decrypt_cbc(
-    olm::Aes256Key const & key,
-    olm::Aes256Iv const & iv,
+std::size_t _olm_crypto_aes_decrypt_cbc(
+    _olm_aes256_key const *key,
+    _olm_aes256_iv const *iv,
     std::uint8_t const * input, std::size_t input_length,
     std::uint8_t * output
 ) {
     std::uint32_t key_schedule[AES_KEY_SCHEDULE_LENGTH];
-    ::aes_key_setup(key.key, key_schedule, AES_KEY_BITS);
+    ::aes_key_setup(key->key, key_schedule, AES_KEY_BITS);
     std::uint8_t block1[AES_BLOCK_LENGTH];
     std::uint8_t block2[AES_BLOCK_LENGTH];
-    std::memcpy(block1, iv.iv, AES_BLOCK_LENGTH);
+    std::memcpy(block1, iv->iv, AES_BLOCK_LENGTH);
     for (std::size_t i = 0; i < input_length; i += AES_BLOCK_LENGTH) {
         std::memcpy(block2, &input[i], AES_BLOCK_LENGTH);
         ::aes_decrypt(&input[i], &output[i], key_schedule, AES_KEY_BITS);
diff --git a/src/session.cpp b/src/session.cpp
index 72e2be8..f1bc5a7 100644
--- a/src/session.cpp
+++ b/src/session.cpp
@@ -14,7 +14,7 @@
  */
 #include "olm/session.hh"
 #include "olm/cipher.h"
-#include "olm/crypto.hh"
+#include "olm/crypto.h"
 #include "olm/account.hh"
 #include "olm/memory.hh"
 #include "olm/message.hh"
diff --git a/src/utility.cpp b/src/utility.cpp
index 43d8e16..e9688de 100644
--- a/src/utility.cpp
+++ b/src/utility.cpp
@@ -14,7 +14,7 @@
  */
 
 #include "olm/utility.hh"
-#include "olm/crypto.hh"
+#include "olm/crypto.h"
 
 
 olm::Utility::Utility(
diff --git a/tests/test_crypto.cpp b/tests/test_crypto.cpp
index 12715d0..7dad892 100644
--- a/tests/test_crypto.cpp
+++ b/tests/test_crypto.cpp
@@ -12,7 +12,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include "olm/crypto.hh"
+#include "olm/crypto.h"
 
 #include "unittest.hh"
 
@@ -115,8 +115,8 @@ assert_equals(false, result);
 
 TestCase test_case("AES Test Case 1");
 
-olm::Aes256Key key = {};
-olm::Aes256Iv iv = {};
+_olm_aes256_key key = {};
+_olm_aes256_iv iv = {};
 std::uint8_t input[16] = {};
 
 std::uint8_t expected[32] = {
@@ -126,16 +126,16 @@ std::uint8_t expected[32] = {
     0x4B, 0xAE, 0xDF, 0xFC, 0x3D, 0x21, 0x4C, 0x38
 };
 
-std::size_t length = olm::aes_encrypt_cbc_length(sizeof(input));
+std::size_t length = _olm_crypto_aes_encrypt_cbc_length(sizeof(input));
 assert_equals(std::size_t(32), length);
 
 
 std::uint8_t actual[32] = {};
 
-olm::aes_encrypt_cbc(key, iv, input, sizeof(input), actual);
+_olm_crypto_aes_encrypt_cbc(&key, &iv, input, sizeof(input), actual);
 assert_equals(expected, actual, 32);
 
-length = olm::aes_decrypt_cbc(key, iv, expected, sizeof(expected), actual);
+length = _olm_crypto_aes_decrypt_cbc(&key, &iv, expected, sizeof(expected), actual);
 assert_equals(std::size_t(16), length);
 assert_equals(input, actual, length);
 
-- 
GitLab