diff --git a/Makefile b/Makefile
index 142e92d..bef297d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,19 @@
CXX := c++
CXXFLAGS := -Wall -pedantic -Wno-long-long -O2
-LDFLAGS := -lcrypto
+LDFLAGS :=
PREFIX := /usr/local
-OBJFILES = git-crypt.o commands.o crypto.o gpg.o key.o util.o parse_options.o
+OBJFILES = \
+ git-crypt.o \
+ commands.o \
+ crypto.o \
+ gpg.o \
+ key.o \
+ util.o \
+ parse_options.o
+
+OBJFILES += crypto-openssl.o
+LDFLAGS += -lcrypto
all: git-crypt
diff --git a/crypto-openssl.cpp b/crypto-openssl.cpp
new file mode 100644
index 0000000..6ae8293
--- /dev/null
+++ b/crypto-openssl.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2012, 2014 Andrew Ayer
+ *
+ * This file is part of git-crypt.
+ *
+ * git-crypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * git-crypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with git-crypt. If not, see .
+ *
+ * Additional permission under GNU GPL version 3 section 7:
+ *
+ * If you modify the Program, or any covered work, by linking or
+ * combining it with the OpenSSL project's OpenSSL library (or a
+ * modified version of that library), containing parts covered by the
+ * terms of the OpenSSL or SSLeay licenses, the licensors of the Program
+ * grant you additional permission to convey the resulting work.
+ * Corresponding Source for a non-source form of such a combination
+ * shall include the source code for the parts of OpenSSL used as well
+ * as that of the covered work.
+ */
+
+#include "crypto.hpp"
+#include "key.hpp"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+void init_crypto ()
+{
+ ERR_load_crypto_strings();
+}
+
+struct Aes_impl {
+ AES_KEY key;
+};
+
+Aes_ecb_encryptor::Aes_ecb_encryptor (const unsigned char* raw_key)
+{
+ impl = new Aes_impl;
+ if (AES_set_encrypt_key(raw_key, KEY_LEN * 8, &(impl->key)) != 0) {
+ throw Crypto_error("Aes_ctr_encryptor::Aes_ctr_encryptor", "AES_set_encrypt_key failed");
+ }
+}
+
+Aes_ecb_encryptor::~Aes_ecb_encryptor ()
+{
+ delete impl;
+}
+
+void Aes_ecb_encryptor::encrypt(const unsigned char* plain, unsigned char* cipher)
+{
+ AES_encrypt(plain, cipher, &(impl->key));
+}
+
+struct Hmac_impl {
+ HMAC_CTX ctx;
+};
+
+Hmac_sha1_state::Hmac_sha1_state (const unsigned char* key, size_t key_len)
+{
+ impl = new Hmac_impl;
+ HMAC_Init(&(impl->ctx), key, key_len, EVP_sha1());
+}
+
+Hmac_sha1_state::~Hmac_sha1_state ()
+{
+ HMAC_cleanup(&(impl->ctx));
+ delete impl;
+}
+
+void Hmac_sha1_state::add (const unsigned char* buffer, size_t buffer_len)
+{
+ HMAC_Update(&(impl->ctx), buffer, buffer_len);
+}
+
+void Hmac_sha1_state::get (unsigned char* digest)
+{
+ unsigned int len;
+ HMAC_Final(&(impl->ctx), digest, &len);
+}
+
+
+void random_bytes (unsigned char* buffer, size_t len)
+{
+ if (RAND_bytes(buffer, len) != 1) {
+ std::ostringstream message;
+ while (unsigned long code = ERR_get_error()) {
+ char error_string[120];
+ ERR_error_string_n(code, error_string, sizeof(error_string));
+ message << "OpenSSL Error: " << error_string << "; ";
+ }
+ throw Crypto_error("random_bytes", message.str());
+ }
+}
+
diff --git a/crypto.cpp b/crypto.cpp
index c11d5e2..db081ae 100644
--- a/crypto.cpp
+++ b/crypto.cpp
@@ -30,22 +30,11 @@
#include "crypto.hpp"
#include "util.hpp"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
#include
-#include
Aes_ctr_encryptor::Aes_ctr_encryptor (const unsigned char* raw_key, const unsigned char* arg_nonce)
+: ecb(raw_key)
{
- if (AES_set_encrypt_key(raw_key, KEY_LEN * 8, &key) != 0) {
- throw Crypto_error("Aes_ctr_encryptor::Aes_ctr_encryptor", "AES_set_encrypt_key failed");
- }
-
std::memcpy(nonce, arg_nonce, NONCE_LEN);
byte_counter = 0;
std::memset(otp, '\0', sizeof(otp));
@@ -64,7 +53,7 @@ void Aes_ctr_encryptor::process (const unsigned char* in, unsigned char* out, si
store_be32(ctr + NONCE_LEN, byte_counter / BLOCK_LEN);
// Generate a new OTP
- AES_encrypt(ctr, otp, &key);
+ ecb.encrypt(ctr, otp);
}
// encrypt one byte
@@ -76,28 +65,6 @@ void Aes_ctr_encryptor::process (const unsigned char* in, unsigned char* out, si
}
}
-Hmac_sha1_state::Hmac_sha1_state (const unsigned char* key, size_t key_len)
-{
- HMAC_Init(&ctx, key, key_len, EVP_sha1());
-}
-
-Hmac_sha1_state::~Hmac_sha1_state ()
-{
- HMAC_cleanup(&ctx);
-}
-
-void Hmac_sha1_state::add (const unsigned char* buffer, size_t buffer_len)
-{
- HMAC_Update(&ctx, buffer, buffer_len);
-}
-
-void Hmac_sha1_state::get (unsigned char* digest)
-{
- unsigned int len;
- HMAC_Final(&ctx, digest, &len);
-}
-
-
// Encrypt/decrypt an entire input stream, writing to the given output stream
void Aes_ctr_encryptor::process_stream (std::istream& in, std::ostream& out, const unsigned char* key, const unsigned char* nonce)
{
@@ -111,16 +78,3 @@ void Aes_ctr_encryptor::process_stream (std::istream& in, std::ostream& out, con
}
}
-void random_bytes (unsigned char* buffer, size_t len)
-{
- if (RAND_bytes(buffer, len) != 1) {
- std::ostringstream message;
- while (unsigned long code = ERR_get_error()) {
- char error_string[120];
- ERR_error_string_n(code, error_string, sizeof(error_string));
- message << "OpenSSL Error: " << error_string << "; ";
- }
- throw Crypto_error("random_bytes", message.str());
- }
-}
-
diff --git a/crypto.hpp b/crypto.hpp
index 63772a1..ae6a14c 100644
--- a/crypto.hpp
+++ b/crypto.hpp
@@ -32,13 +32,13 @@
#define GIT_CRYPT_CRYPTO_HPP
#include "key.hpp"
-#include
-#include
#include
#include
#include
#include
+void init_crypto ();
+
struct Crypto_error {
std::string where;
std::string message;
@@ -46,6 +46,28 @@ struct Crypto_error {
Crypto_error (const std::string& w, const std::string& m) : where(w), message(m) { }
};
+struct Aes_impl;
+
+class Aes_ecb_encryptor {
+public:
+ enum {
+ KEY_LEN = AES_KEY_LEN,
+ BLOCK_LEN = 16
+ };
+
+private:
+ Aes_impl* impl;
+
+ // disallow copy/assignment:
+ Aes_ecb_encryptor (const Aes_ecb_encryptor&);
+ Aes_ecb_encryptor& operator= (const Aes_ecb_encryptor&);
+
+public:
+ Aes_ecb_encryptor (const unsigned char* key);
+ ~Aes_ecb_encryptor ();
+ void encrypt (const unsigned char* plain, unsigned char* cipher);
+};
+
class Aes_ctr_encryptor {
public:
enum {
@@ -56,10 +78,10 @@ public:
};
private:
- AES_KEY key;
- char nonce[NONCE_LEN];// First 96 bits of counter
- uint32_t byte_counter; // How many bytes processed so far?
- unsigned char otp[BLOCK_LEN]; // The current OTP that's in use
+ Aes_ecb_encryptor ecb;
+ char nonce[NONCE_LEN];// First 96 bits of counter
+ uint32_t byte_counter; // How many bytes processed so far?
+ unsigned char otp[BLOCK_LEN]; // The current OTP that's in use
public:
Aes_ctr_encryptor (const unsigned char* key, const unsigned char* nonce);
@@ -72,6 +94,8 @@ public:
typedef Aes_ctr_encryptor Aes_ctr_decryptor;
+struct Hmac_impl;
+
class Hmac_sha1_state {
public:
enum {
@@ -80,7 +104,7 @@ public:
};
private:
- HMAC_CTX ctx;
+ Hmac_impl* impl;
// disallow copy/assignment:
Hmac_sha1_state (const Hmac_sha1_state&) { }
diff --git a/git-crypt.cpp b/git-crypt.cpp
index 58b9923..e2cc9fc 100644
--- a/git-crypt.cpp
+++ b/git-crypt.cpp
@@ -39,7 +39,6 @@
#include
#include
#include
-#include
const char* argv0;
@@ -90,7 +89,7 @@ try {
*/
init_std_streams();
- ERR_load_crypto_strings();
+ init_crypto();
/*
* Parse command line arguments