From 63c2d1c539d26df5af487f5fd3631c27e3b34ca4 Mon Sep 17 00:00:00 2001 From: Valient Gough Date: Tue, 5 Mar 2013 06:39:51 +0000 Subject: [PATCH] add CommonCrypto support, other misc fixes git-svn-id: http://encfs.googlecode.com/svn/trunk@97 db9cf616-1c43-0410-9cb8-a902689de0d6 --- CMakeLists.txt | 23 ++- base/ConfigReader.cpp | 4 +- base/XmlReader.cpp | 16 +-- base/base64.cpp | 111 ++++++++------ base/base64.h | 2 + base/config.h.cmake | 10 +- cipher/BlockCipher.cpp | 14 +- cipher/BlockCipher_test.cpp | 103 ++++++++++--- cipher/CMakeLists.txt | 17 ++- cipher/CipherKey_test.cpp | 45 ++++++ cipher/CipherV1.cpp | 107 +++++++++++--- cipher/CipherV1.h | 8 +- cipher/CommonCrypto.cpp | 263 ++++++++++++++++++++++++++++++++++ cipher/CommonCrypto.h | 35 +++++ cipher/MAC.h | 3 +- cipher/MAC_test.cpp | 8 +- cipher/MemoryPool.cpp | 121 ++++++---------- cipher/MemoryPool.h | 11 +- cipher/StreamCipher.h | 11 +- cipher/openssl.cpp | 48 ++++++- cipher/testing.cpp | 10 ++ encfs/main.cpp | 15 +- fs/CMakeLists.txt | 10 ++ fs/CipherFileIO.cpp | 3 +- fs/CipherFileIO.h | 2 - fs/Context.h | 1 + fs/DirNode.cpp | 3 +- fs/FSConfig.h | 5 + fs/FileNode.cpp | 2 +- fs/FileUtils.cpp | 13 +- fs/MACFileIO.cpp | 2 - fs/NameIO.cpp | 6 +- fs/RawFileIO.cpp | 2 - fs/StreamNameIO.cpp | 2 - fs/{test.cpp => checkops.cpp} | 79 +++++----- fs/encfs.cpp | 13 +- fs/test_IO.cpp | 32 +++++ fs/testing.cpp | 35 +++-- po/CMakeLists.txt | 2 +- util/CMakeLists.txt | 1 - util/encfsctl.cpp | 9 +- util/makeKey.cpp | 2 - 42 files changed, 917 insertions(+), 292 deletions(-) create mode 100644 cipher/CipherKey_test.cpp create mode 100644 cipher/CommonCrypto.cpp create mode 100644 cipher/CommonCrypto.h rename fs/{test.cpp => checkops.cpp} (88%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 782b26c..b54f226 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,11 +3,17 @@ project(Encfs) set (ENCFS_MAJOR 2) set (ENCFS_MINOR 0) -set (ENCFS_PATCH 0) -set (ENCFS_VERSION "${ENCFS_MAJOR}.${ENCFS_MINOR}.${ENCFS_PATCH}") +set (ENCFS_VERSION "${ENCFS_MAJOR}.${ENCFS_MINOR}") option (BUILD_SHARED_LIBS "Build dynamic link libraries" OFF) +option (WITH_OPENSSL "WithOpenSSL" ON) +option (WITH_COMMON_CRYPTO "WithCommonCrypto" OFF) + +if (WITH_COMMON_CRYPTO) + set (WITH_OPENSSL OFF) +endif (WITH_COMMON_CRYPTO) + set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMakeModules/") @@ -36,7 +42,6 @@ endif (APPLE) set (CPACK_PACKAGE_NAME "Encfs") set (CPACK_PACKAGE_VERSION_MAJOR ${ENCFS_MAJOR}) set (CPACK_PACKAGE_VERSION_MINOR ${ENCFS_MINOR}) -set (CPACK_PACKAGE_VERSION_PATCH ${ENCFS_PATCH}) set (CPACK_SOURCE_GENERATOR TGZ) set (CPACK_SOURCE_IGNORE_FILES "/_darcs/" @@ -56,9 +61,15 @@ check_include_file_cxx (tr1/tuple HAVE_TR1_TUPLE) check_include_file_cxx (valgrind/valgrind.h HAVE_VALGRIND_VALGRIND_H) check_include_file_cxx (valgrind/memcheck.h HAVE_VALGRIND_MEMCHECK_H) -# TODO: move this to cipher directory. -find_package (OpenSSL REQUIRED) -include (OpenSSLTests) +if (WITH_COMMON_CRYPTO) + check_include_file_cxx (Security/SecRandom.h HAVE_SEC_RANDOM_H) +endif (WITH_COMMON_CRYPTO) + +if (WITH_OPENSSL) + # TODO: move this to cipher directory. + find_package (OpenSSL REQUIRED) + include (OpenSSLTests) +endif (WITH_OPENSSL) # Check if xattr functions take extra argument. include (CheckCXXSourceCompiles) diff --git a/base/ConfigReader.cpp b/base/ConfigReader.cpp index f5a8f60..a623b67 100644 --- a/base/ConfigReader.cpp +++ b/base/ConfigReader.cpp @@ -30,7 +30,9 @@ #include "base/types.h" -using namespace std; +using std::make_pair; +using std::map; +using std::string; namespace encfs { diff --git a/base/XmlReader.cpp b/base/XmlReader.cpp index ad37b45..75088e7 100644 --- a/base/XmlReader.cpp +++ b/base/XmlReader.cpp @@ -38,8 +38,7 @@ #include #include "base/base64.h" #include "base/Interface.h" - -using namespace std; +#include "base/shared_ptr.h" namespace encfs { @@ -116,16 +115,9 @@ bool XmlValue::readB64(const char *path, byte *data, int length) const std::string s = value->text(); s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end()); + s.erase(s.find_last_not_of("=")+1); - BIO *b64 = BIO_new(BIO_f_base64()); - BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); - - BIO *bmem = BIO_new_mem_buf((void *)s.c_str(), s.size()); - bmem = BIO_push(b64, bmem); - - int decodedSize = BIO_read(bmem, data, length); - BIO_free_all(b64); - + int decodedSize = B64ToB256Bytes(s.size()); if (decodedSize != length) { LOG(ERROR) << "decoding bytes len " << s.size() @@ -133,6 +125,8 @@ bool XmlValue::readB64(const char *path, byte *data, int length) const << ", got " << decodedSize; return false; } + changeBase2((byte *)s.data(), s.size(), 6, data, length, 8); + B64ToAsciiStandard(data, length); return true; } diff --git a/base/base64.cpp b/base/base64.cpp index f89997f..215b02e 100644 --- a/base/base64.cpp +++ b/base/base64.cpp @@ -132,20 +132,39 @@ void changeBase2Inline(byte *src, int srcLen, static const char B642AsciiTable[] = ",-0123456789"; void B64ToAscii(byte *in, int length) { - for(int offset=0; offset 11) { - int ch = in[offset]; - if(ch > 11) - { - if(ch > 37) - ch += 'a' - 38; - else - ch += 'A' - 12; - } else - ch = B642AsciiTable[ ch ]; - - in[offset] = ch; - } + if(ch > 37) + ch += 'a' - 38; + else + ch += 'A' - 12; + } else + ch = B642AsciiTable[ ch ]; + + in[offset] = ch; + } +} + +void B64ToAsciiStandard(byte *in, int length) +{ + static const char LookupTable[] = "+/0123456789"; + for(int offset=0; offset 11) + { + if(ch > 37) + ch += 'a' - 38; + else + ch += 'A' - 12; + } else + ch = LookupTable[ ch ]; + + in[offset] = ch; + } } static const byte Ascii2B64Table[] = @@ -159,55 +178,55 @@ void AsciiToB64(byte *in, int length) void AsciiToB64(byte *out, const byte *in, int length) { - while(length--) + while(length--) + { + byte ch = *in++; + if(ch >= 'A') { - byte ch = *in++; - if(ch >= 'A') - { - if(ch >= 'a') - ch += 38 - 'a'; - else - ch += 12 - 'A'; - } else - ch = Ascii2B64Table[ ch ] - '0'; + if(ch >= 'a') + ch += 38 - 'a'; + else + ch += 12 - 'A'; + } else + ch = Ascii2B64Table[ ch ] - '0'; - *out++ = ch; - } + *out++ = ch; + } } void B32ToAscii(byte *buf, int len) { - for(int offset=0; offset= 0 && ch < 26) - ch += 'A'; - else - ch += '2' - 26; - - buf[offset] = ch; - } + for(int offset=0; offset= 0 && ch < 26) + ch += 'A'; + else + ch += '2' - 26; + + buf[offset] = ch; + } } void AsciiToB32(byte *in, int length) { - return AsciiToB32(in, in, length); + return AsciiToB32(in, in, length); } void AsciiToB32(byte *out, const byte *in, int length) { - while(length--) - { - byte ch = *in++; - int lch = toupper(ch); - if (lch >= 'A') - lch -= 'A'; - else - lch += 26 - '2'; + while(length--) + { + byte ch = *in++; + int lch = toupper(ch); + if (lch >= 'A') + lch -= 'A'; + else + lch += 26 - '2'; - *out++ = (byte)lch; - } + *out++ = (byte)lch; + } } } // namespace encfs diff --git a/base/base64.h b/base/base64.h index 6be224c..4434041 100644 --- a/base/base64.h +++ b/base/base64.h @@ -62,6 +62,8 @@ void changeBase2Inline(byte *buf, int srcLength, // inplace translation from values [0,2^6] => base64 ASCII void B64ToAscii(byte *buf, int length); +// Like B64ToAscii, but uses standard characters "+" and "/" in encoding. +void B64ToAsciiStandard(byte *buf, int length); // inplace translation from values [0,2^5] => base32 ASCII void B32ToAscii(byte *buf, int length); diff --git a/base/config.h.cmake b/base/config.h.cmake index 68fecab..fb3b11b 100644 --- a/base/config.h.cmake +++ b/base/config.h.cmake @@ -10,15 +10,19 @@ #cmakedefine HAVE_TR1_UNORDERED_SET #cmakedefine HAVE_TR1_TUPLE +#cmakedefine HAVE_VALGRIND_VALGRIND_H +#cmakedefine HAVE_VALGRIND_MEMCHECK_H + +#cmakedefine WITH_OPENSSL +#cmakedefine WITH_COMMON_CRYPTO +#cmakedefine HAVE_SEC_RANDOM_H + #cmakedefine HAVE_EVP_BF #cmakedefine HAVE_EVP_AES #cmakedefine HAVE_EVP_AES_XTS #cmakedefine HAVE_LCHMOD -#cmakedefine HAVE_VALGRIND_VALGRIND_H -#cmakedefine HAVE_VALGRIND_MEMCHECK_H - /* TODO: add other thread library support. */ #cmakedefine CMAKE_USE_PTHREADS_INIT diff --git a/cipher/BlockCipher.cpp b/cipher/BlockCipher.cpp index 75305c6..8d7e82d 100644 --- a/cipher/BlockCipher.cpp +++ b/cipher/BlockCipher.cpp @@ -1,7 +1,14 @@ #include "cipher/BlockCipher.h" -// TODO: add ifdef when OpenSSL becomes optional. +#include "base/config.h" + +#ifdef WITH_OPENSSL #include "cipher/openssl.h" +#endif +#ifdef WITH_COMMON_CRYPTO +#include "cipher/CommonCrypto.h" +#endif + #include "cipher/NullCiphers.h" namespace encfs { @@ -12,7 +19,12 @@ Registry& BlockCipher::GetRegistry() static bool first = true; if (first) { +#ifdef WITH_OPENSSL OpenSSL::registerCiphers(); +#endif +#ifdef WITH_COMMON_CRYPTO + CommonCrypto::registerCiphers(); +#endif NullCiphers::registerCiphers(); first = false; } diff --git a/cipher/BlockCipher_test.cpp b/cipher/BlockCipher_test.cpp index 8cf89f9..feeee7e 100644 --- a/cipher/BlockCipher_test.cpp +++ b/cipher/BlockCipher_test.cpp @@ -23,12 +23,17 @@ #include +#include "base/config.h" #include "base/shared_ptr.h" #include "cipher/BlockCipher.h" #include "cipher/MemoryPool.h" #include "cipher/PBKDF.h" #include "cipher/testing.h" +#ifdef HAVE_VALGRIND_MEMCHECK_H +#include +#endif + using namespace encfs; using std::list; using std::string; @@ -36,6 +41,10 @@ using std::string; namespace { void compare(const byte *a, const byte *b, int size) { +#ifdef HAVE_VALGRIND_MEMCHECK_H + ASSERT_EQ(0, VALGRIND_CHECK_MEM_IS_DEFINED(a, size)); + ASSERT_EQ(0, VALGRIND_CHECK_MEM_IS_DEFINED(b, size)); +#endif for (int i = 0; i < size; i++) { bool match = (a[i] == b[i]); ASSERT_TRUE(match) << "mismatched data at offset " << i @@ -61,31 +70,83 @@ TEST(RequiredStreamCiphers, StreamCipher) { ASSERT_TRUE(bf_cfb != NULL); } -TEST(BlowfishTestVector, BlockCihper) { - auto cbc = BlockCipher::GetRegistry().CreateForMatch(NAME_BLOWFISH_CBC); - auto cfb = StreamCipher::GetRegistry().CreateForMatch(NAME_BLOWFISH_CFB); +template +void checkTestVector(const char *cipherName, + const char *hexKey, + const char *hexIv, + const char *hexPlaintext, + const char *hexCipher) { + SCOPED_TRACE(testing::Message() << "Testing cipher: " << cipherName + << ", key = " << hexKey << ", plaintext = " << hexPlaintext); - CipherKey key(16); - setDataFromHex(key.data(), key.size(), "0123456789abcdeff0e1d2c3b4a59687"); - cbc->setKey(key); - cfb->setKey(key); + auto cipher = T::GetRegistry().CreateForMatch(cipherName); + ASSERT_TRUE(cipher != NULL); - byte iv[8]; - setDataFromHex(iv, 8, "fedcba9876543210"); + CipherKey key(strlen(hexKey)/2); + setDataFromHex(key.data(), key.size(), hexKey); + ASSERT_TRUE(cipher->setKey(key)); - byte data[32]; - setDataFromHex(data, 32, - "37363534333231204e6f77206973207468652074696d6520666f722000000000"); + byte iv[strlen(hexIv)/2]; + setDataFromHex(iv, sizeof(iv), hexIv); - byte cipherData[32]; - cbc->encrypt(iv, data, cipherData, 32); + byte plaintext[strlen(hexPlaintext)/2]; + setDataFromHex(plaintext, sizeof(plaintext), hexPlaintext); - ASSERT_EQ("6b77b4d63006dee605b156e27403979358deb9e7154616d959f1652bd5ff92cc", - stringToHex(cipherData, 32)); + byte ciphertext[sizeof(plaintext)]; + ASSERT_TRUE(cipher->encrypt(iv, plaintext, ciphertext, sizeof(ciphertext))); - cfb->encrypt(iv, data, cipherData, 29); - ASSERT_EQ("e73214a2822139caf26ecf6d2eb9e76e3da3de04d1517200519d57a6c3", - stringToHex(cipherData, 29)); + ASSERT_EQ(hexCipher, stringToHex(ciphertext, sizeof(ciphertext))); + + byte decypered[sizeof(plaintext)]; + ASSERT_TRUE(cipher->decrypt(iv, ciphertext, decypered, sizeof(ciphertext))); + + for (unsigned int i = 0; i < sizeof(plaintext); ++i) { + ASSERT_EQ(plaintext[i], decypered[i]); + } +} + +TEST(TestVectors, BlockCipher) { + // BF128 CBC + checkTestVector(NAME_BLOWFISH_CBC, + "0123456789abcdeff0e1d2c3b4a59687", + "fedcba9876543210", + "37363534333231204e6f77206973207468652074696d6520666f722000000000", + "6b77b4d63006dee605b156e27403979358deb9e7154616d959f1652bd5ff92cc"); + + // BF128 CFB + checkTestVector(NAME_BLOWFISH_CFB, + "0123456789abcdeff0e1d2c3b4a59687", + "fedcba9876543210", + "37363534333231204e6f77206973207468652074696d6520666f722000", + "e73214a2822139caf26ecf6d2eb9e76e3da3de04d1517200519d57a6c3"); + + // AES128 CBC + checkTestVector(NAME_AES_CBC, + "2b7e151628aed2a6abf7158809cf4f3c", + "000102030405060708090a0b0c0d0e0f", + "6bc1bee22e409f96e93d7e117393172a", + "7649abac8119b246cee98e9b12e9197d"); + + // AES128 CFB + checkTestVector(NAME_AES_CFB, + "2b7e151628aed2a6abf7158809cf4f3c", + "000102030405060708090a0b0c0d0e0f", + "6bc1bee22e409f96e93d7e117393172a", + "3b3fd92eb72dad20333449f8e83cfb4a"); + + // AES256 CBC + checkTestVector(NAME_AES_CBC, + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", + "000102030405060708090a0b0c0d0e0f", + "6bc1bee22e409f96e93d7e117393172a", + "f58c4c04d6e5f1ba779eabfb5f7bfbd6"); + + // AES256 CFB + checkTestVector(NAME_AES_CFB, + "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", + "000102030405060708090a0b0c0d0e0f", + "6bc1bee22e409f96e93d7e117393172a", + "dc7e84bfda79164b7ecd8486985d3860"); } TEST(BlockEncryptionTest, BlockCipher) { @@ -109,10 +170,12 @@ TEST(BlockEncryptionTest, BlockCipher) { CipherKey key = pbkdf->randomKey(keySize / 8); ASSERT_TRUE(key.valid()); - cipher->setKey(key); + ASSERT_TRUE(cipher->setKey(key)); // Create some data to encrypt. int blockSize = cipher->blockSize(); + SCOPED_TRACE(testing::Message() << "blockSize " << blockSize); + MemBlock mb; mb.allocate(16 * blockSize); diff --git a/cipher/CMakeLists.txt b/cipher/CMakeLists.txt index f00a2c4..be1101e 100644 --- a/cipher/CMakeLists.txt +++ b/cipher/CMakeLists.txt @@ -1,7 +1,16 @@ -include_directories (${OPENSSL_INCLUDE_DIR}) - link_directories (${Encfs_BINARY_DIR}/base) +if (WITH_COMMON_CRYPTO) + find_library (SECURITY_FRAMEWORK Security) + mark_as_advanced (SECURITY_FRAMEWORK) + set (EXTRA_LIBS ${SECURITY_FRAMEWORK}) + set (EXTRA_SOURCE CommonCrypto.cpp) +elseif (WITH_OPENSSL) + include_directories (${OPENSSL_INCLUDE_DIR}) + set (EXTRA_LIBS ${OPENSSL_LIBRARIES}) + set (EXTRA_SOURCE openssl.cpp) +endif (WITH_COMMON_CRYPTO) + add_library (encfs-cipher BlockCipher.cpp CipherKey.cpp @@ -9,14 +18,14 @@ add_library (encfs-cipher MAC.cpp MemoryPool.cpp NullCiphers.cpp - openssl.cpp PBKDF.cpp readpassphrase.cpp StreamCipher.cpp + ${EXTRA_SOURCE} ) target_link_libraries (encfs-cipher - ${OPENSSL_LIBRARIES} + ${EXTRA_LIBS} ) if (GTEST_FOUND) diff --git a/cipher/CipherKey_test.cpp b/cipher/CipherKey_test.cpp new file mode 100644 index 0000000..a5898f2 --- /dev/null +++ b/cipher/CipherKey_test.cpp @@ -0,0 +1,45 @@ + +#include + +#include + +#include "base/config.h" +#include "base/shared_ptr.h" +#include "cipher/CipherV1.h" +#include "cipher/MemoryPool.h" +#include "cipher/testing.h" + +#ifdef HAVE_VALGRIND_MEMCHECK_H +#include +#endif + +using namespace encfs; +using std::list; +using std::string; + +namespace { + +TEST(CipherKey, ReadWrite) { + for (auto alg : CipherV1::GetAlgorithmList()) { + auto cipher = CipherV1::New(alg.iface); + + CipherKey masterKey = cipher->newRandomKey(); + CipherKey volumeKey = cipher->newRandomKey(); + + int encodedSize = cipher->encodedKeySize(); + unsigned char *keyBuf = new unsigned char[encodedSize]; + + cipher->setKey(masterKey); + cipher->writeKey(volumeKey, keyBuf); + + CipherKey readKey = cipher->readKey(keyBuf, true); + ASSERT_TRUE(readKey.valid()); + ASSERT_TRUE(readKey == volumeKey); + ASSERT_FALSE(readKey == masterKey); + + delete[] keyBuf; + } +} + + +} // namespace diff --git a/cipher/CipherV1.cpp b/cipher/CipherV1.cpp index fec3206..8dea654 100644 --- a/cipher/CipherV1.cpp +++ b/cipher/CipherV1.cpp @@ -19,6 +19,7 @@ */ #include "cipher/CipherV1.h" +#include "base/config.h" #include #include @@ -28,18 +29,29 @@ #include +#ifdef HAVE_VALGRIND_MEMCHECK_H +#include +#endif + #include "base/base64.h" #include "base/Error.h" #include "base/i18n.h" #include "base/Mutex.h" #include "base/Range.h" + #include "cipher/MemoryPool.h" #include "cipher/MAC.h" #include "cipher/BlockCipher.h" #include "cipher/PBKDF.h" #include "cipher/StreamCipher.h" -using namespace std; +#ifdef WITH_OPENSSL +#include "cipher/openssl.h" +#endif + +using std::list; +using std::string; +using std::vector; namespace encfs { @@ -54,6 +66,18 @@ inline int MIN(int a, int b) } #endif +void CipherV1::init(bool threaded) { +#ifdef WITH_OPENSSL + OpenSSL::init(threaded); +#endif +} + +void CipherV1::shutdown(bool threaded) { +#ifdef WITH_OPENSSL + OpenSSL::shutdown(threaded); +#endif +} + /* DEPRECATED: this is here for backward compatibilty only. Use PBKDF @@ -77,7 +101,7 @@ bool BytesToKey(const byte *data, int dataLen, for(;;) { - sha1->reset(); + sha1->init(); if( addmd++ ) sha1->update(mdBuf.data, mdBuf.size); sha1->update(data, dataLen); @@ -85,7 +109,7 @@ bool BytesToKey(const byte *data, int dataLen, for(unsigned int i=1; i < rounds; ++i) { - sha1->reset(); + sha1->init(); sha1->update(mdBuf.data, mdBuf.size); sha1->write(mdBuf.data); } @@ -115,6 +139,10 @@ int CipherV1::TimedPBKDF2(const char *pass, int passlen, const byte *salt, int saltlen, CipherKey *key, long desiredPDFTime) { +#ifdef HAVE_VALGRIND_MEMCHECK_H + VALGRIND_CHECK_MEM_IS_DEFINED(pass, passlen); + VALGRIND_CHECK_MEM_IS_DEFINED(salt, saltlen); +#endif Registry registry = PBKDF::GetRegistry(); shared_ptr impl(registry.CreateForMatch(NAME_PKCS5_PBKDF2_HMAC_SHA1)); if (!impl) @@ -212,11 +240,18 @@ shared_ptr CipherV1::New(const std::string& name, int keyLen) { } shared_ptr CipherV1::New(const Interface &iface, int keyLen) { - return shared_ptr(new CipherV1(iface, iface, keyLen)); + shared_ptr result(new CipherV1()); + if (!result->initCiphers(iface, iface, keyLen)) + result.reset(); + return result; } -CipherV1::CipherV1(const Interface &iface, const Interface &realIface, - int keyLength) +CipherV1::CipherV1() +{ +} + +bool CipherV1::initCiphers(const Interface &iface, const Interface &realIface, + int keyLength) { this->iface = iface; this->realIface = realIface; @@ -243,12 +278,11 @@ CipherV1::CipherV1(const Interface &iface, const Interface &realIface, defaultKeyLength = 0; _blockCipher.reset( blockCipherRegistry.CreateForMatch("NullCipher") ); _streamCipher.reset( streamCipherRegistry.CreateForMatch("NullCipher") ); - } else { - throw Error("Unsupported cipher"); } if (!_blockCipher || !_streamCipher) { - throw Error("Requested cipher not available"); + LOG(INFO) << "Unsupported cipher " << iface.name(); + return false; } if (keyLength <= 0) @@ -259,7 +293,8 @@ CipherV1::CipherV1(const Interface &iface, const Interface &realIface, _pbkdf.reset(PBKDF::GetRegistry().CreateForMatch( NAME_PKCS5_PBKDF2_HMAC_SHA1)); if (!_pbkdf) { - throw Error("PBKDF not available"); + LOG(ERROR) << "PBKDF missing"; + return false; } // Initialize the cipher with a temporary key in order to determine the block @@ -272,8 +307,12 @@ CipherV1::CipherV1(const Interface &iface, const Interface &realIface, Lock l(_hmacMutex); _hmac.reset(MAC::GetRegistry().CreateForMatch(NAME_SHA1_HMAC)); - if (!_hmac) - throw Error("SHA1_HMAC not available"); + if (!_hmac) { + LOG(ERROR) << "SHA1_HMAC not available"; + return false; + } + + return true; } CipherV1::~CipherV1() @@ -296,6 +335,10 @@ CipherKey CipherV1::newKey(const char *password, int passwdLength, int *iterationCount, long desiredDuration, const byte *salt, int saltLen) { +#ifdef HAVE_VALGRIND_MEMCHECK_H + VALGRIND_CHECK_MEM_IS_DEFINED(password, passwdLength); + VALGRIND_CHECK_MEM_IS_DEFINED(salt, saltLen); +#endif CipherKey key(_keySize + _ivLength); if(*iterationCount == 0) @@ -329,6 +372,9 @@ CipherKey CipherV1::newKey(const char *password, int passwdLength, // password is changed or configuration is rewritten. CipherKey CipherV1::newKey(const char *password, int passwdLength) { +#ifdef HAVE_VALGRIND_MEMCHECK_H + VALGRIND_CHECK_MEM_IS_DEFINED(password, passwdLength); +#endif CipherKey key(_keySize + _ivLength); bool ok = BytesToKey((byte *)password, passwdLength, 16, &key); @@ -376,8 +422,8 @@ uint64_t CipherV1::MAC_64(const byte *data, int len, byte md[_hmac->outputSize()]; Lock l(_hmacMutex); - _hmac->reset(); + _hmac->init(); _hmac->update(data, len); if(chainedIV) { @@ -398,8 +444,11 @@ uint64_t CipherV1::MAC_64(const byte *data, int len, // chop this down to a 64bit value.. byte h[8] = {0,0,0,0,0,0,0,0}; - // TODO: outputSize - 1? - for(unsigned int i=0; i<_hmac->outputSize(); ++i) + + // XXX: the last byte off the hmac isn't used. This minor inconsistency + // must be maintained in order to maintain backward compatiblity with earlier + // releases. + for(int i=0; i<_hmac->outputSize()-1; ++i) h[i%8] ^= (byte)(md[i]); uint64_t value = (uint64_t)h[0]; @@ -435,14 +484,27 @@ CipherKey CipherV1::readKey(const byte *data, bool checkKey) checksum = (checksum << 8) | (unsigned int)data[i]; memcpy( key.data(), data+KEY_CHECKSUM_BYTES, key.size() ); - streamDecode(key.data(), key.size(), checksum); + if (!streamDecode(key.data(), key.size(), checksum)) { + LOG(ERROR) << "stream decode failure"; + return CipherKey(); + } // check for success +#ifdef HAVE_VALGRIND_MEMCHECK_H + VALGRIND_CHECK_MEM_IS_DEFINED(key.data(), key.size()); +#endif + unsigned int checksum2 = reduceMac32( MAC_64( key.data(), key.size(), NULL )); - if(checksum2 != checksum && checkKey) + +#ifdef HAVE_VALGRIND_MEMCHECK_H + VALGRIND_CHECK_VALUE_IS_DEFINED(checksum2); + VALGRIND_CHECK_VALUE_IS_DEFINED(checksum); +#endif + + if(checkKey && (checksum2 != checksum)) { - VLOG(1) << "checksum mismatch: expected " << checksum + LOG(INFO) << "checksum mismatch: expected " << checksum << ", got " << checksum2 << "on decode of " << _keySize + _ivLength << " bytes"; return CipherKey(); @@ -454,23 +516,22 @@ CipherKey CipherV1::readKey(const byte *data, bool checkKey) void CipherV1::writeKey(const CipherKey &ckey, byte *out) { rAssert( _keySet ); - rAssert(ckey.size() > KEY_CHECKSUM_BYTES); SecureMem tmpBuf(ckey.size()); memcpy(tmpBuf.data, ckey.data(), tmpBuf.size); unsigned int checksum = reduceMac32( - MAC_64( tmpBuf.data, tmpBuf.size, NULL )); + MAC_64(tmpBuf.data, tmpBuf.size, NULL)); streamEncode(tmpBuf.data, tmpBuf.size, checksum); - memcpy( out+KEY_CHECKSUM_BYTES, tmpBuf.data, tmpBuf.size ); - // first N bytes contain HMAC derived checksum.. for(int i=1; i<=KEY_CHECKSUM_BYTES; ++i) { out[KEY_CHECKSUM_BYTES-i] = checksum & 0xff; checksum >>= 8; } + + memcpy( out+KEY_CHECKSUM_BYTES, tmpBuf.data, tmpBuf.size ); } std::string CipherV1::encodeAsString(const CipherKey &key) @@ -558,7 +619,7 @@ void CipherV1::setIVec(byte *ivec, uint64_t seed) const // combine ivec and seed with HMAC Lock l(_hmacMutex); - _hmac->reset(); + _hmac->init(); _hmac->update(ivec, _ivLength); _hmac->update(md.data(), 8); _hmac->write(md.data()); diff --git a/cipher/CipherV1.h b/cipher/CipherV1.h index 376cfc1..03a840a 100644 --- a/cipher/CipherV1.h +++ b/cipher/CipherV1.h @@ -102,6 +102,9 @@ class CipherV1 Range blockSize; }; + static void init(bool threaded); + static void shutdown(bool threaded); + // Returns a list of supported algorithms. static std::list GetAlgorithmList(); static shared_ptr New(const std::string &name, int keyLen = -1); @@ -114,9 +117,12 @@ class CipherV1 const byte *salt, int saltLen, CipherKey *out, long desiredPDFTimeMicroseconds); - CipherV1(const Interface &iface, const Interface &realIface, int keyLength); + CipherV1(); ~CipherV1(); + bool initCiphers(const Interface &iface, + const Interface &realIface, int keyLength); + // returns the real interface, not the one we're emulating (if any).. Interface interface() const; diff --git a/cipher/CommonCrypto.cpp b/cipher/CommonCrypto.cpp new file mode 100644 index 0000000..1bb24d0 --- /dev/null +++ b/cipher/CommonCrypto.cpp @@ -0,0 +1,263 @@ + +/***************************************************************************** + * Author: Valient Gough + * + ***************************************************************************** + * Copyright (c) 2013 Valient Gough + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program 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 Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "cipher/CommonCrypto.h" + +#include + +#include +#include +#include +#include + +#include "base/config.h" +#include "cipher/BlockCipher.h" +#include "cipher/MAC.h" +#include "cipher/PBKDF.h" + +#ifdef HAVE_SEC_RANDOM_H +#include +#endif + +namespace encfs { +namespace commoncrypto { + +class PbkdfPkcs5HmacSha1CC : public PBKDF { +public: + PbkdfPkcs5HmacSha1CC() {} + virtual ~PbkdfPkcs5HmacSha1CC() {} + + virtual bool makeKey(const char *password, int passwordLength, + const byte *salt, int saltLength, + int numIterations, + CipherKey *outKey) { + int ret = CCKeyDerivationPBKDF(kCCPBKDF2, password, passwordLength, + salt, saltLength, kCCPRFHmacAlgSHA1, + numIterations, + outKey->data(), outKey->size()); + if (ret != 0) { + PLOG(ERROR) << "CCKeyDerivationPBKDF failed"; + return false; + } + return true; + } + + virtual CipherKey randomKey(int length) { + CipherKey key(length); + if (length == 0) return key; +#ifdef HAVE_SEC_RANDOM_H + if (SecRandomCopyBytes(kSecRandomDefault, key.size(), key.data()) < 0) { + PLOG(ERROR) << "random key generation failure for length " << length; + key.reset(); + } +#else +#error No random number generator provided. +#endif + return key; + } + + virtual bool pseudoRandom(byte *out, int length) { + if (length == 0) return true; +#ifdef HAVE_SEC_RANDOM_H + if (SecRandomCopyBytes(kSecRandomDefault, length, out) < 0) { + PLOG(ERROR) << "random key generation failure for length " << length; + return false; + } +#else +#error No random number generator provided. +#endif + return true; + } + + static Properties GetProperties() { + Properties props; + props.mode = NAME_PKCS5_PBKDF2_HMAC_SHA1; + props.library = "CommonCrypto"; + return props; + } +}; +REGISTER_CLASS(PbkdfPkcs5HmacSha1CC, PBKDF); + +class CCCipher : public BlockCipher { + CipherKey key; + CCAlgorithm algorithm; + CCMode mode; + public: + CCCipher() { } + virtual ~CCCipher() { } + + bool rekey(const CipherKey &key, CCAlgorithm algorithm, CCMode mode) { + this->key = key; + this->algorithm = algorithm; + this->mode = mode; + return true; + } + + virtual bool encrypt(const byte *iv, const byte *in, byte *out, int size) { + CCCryptorRef cryptor; + CCCryptorCreateWithMode(kCCEncrypt, mode, algorithm, 0, + iv, key.data(), key.size(), + NULL, 0, 0, 0, &cryptor); + size_t updateLength = 0; + CCCryptorUpdate(cryptor, in, size, out, size, &updateLength); + CCCryptorRelease(cryptor); + return true; + } + + virtual bool decrypt(const byte *iv, const byte *in, byte *out, int size) { + CCCryptorRef cryptor; + CCCryptorCreateWithMode(kCCDecrypt, mode, algorithm, 0, + iv, key.data(), key.size(), + NULL, 0, 0, 0, &cryptor); + size_t updateLength = 0; + CCCryptorUpdate(cryptor, in, size, out, size, &updateLength); + CCCryptorRelease(cryptor); + return true; + } +}; + +class BfCbc : public CCCipher { + public: + BfCbc() {} + virtual ~BfCbc() {} + + virtual bool setKey(const CipherKey &key) { + return CCCipher::rekey(key, kCCAlgorithmBlowfish, kCCModeCBC); + } + + virtual int blockSize() const { + return kCCBlockSizeBlowfish; + } + + static Properties GetProperties() { + return Properties(Range(128,256,32), "Blowfish", "CBC", "CommonCrypto"); + } +}; +REGISTER_CLASS(BfCbc, BlockCipher); + +class AesCbc : public CCCipher { + public: + AesCbc() {} + virtual ~AesCbc() {} + + virtual bool setKey(const CipherKey &key) { + return CCCipher::rekey(key, kCCAlgorithmAES128, kCCModeCBC); + } + + virtual int blockSize() const { + return kCCBlockSizeAES128; + } + + static Properties GetProperties() { + return Properties(Range(128,256,64), "AES", "CBC", "CommonCrypto"); + } +}; +REGISTER_CLASS(AesCbc, BlockCipher); + +class BfCfb : public CCCipher { + public: + BfCfb() {} + virtual ~BfCfb() {} + + virtual bool setKey(const CipherKey &key) { + return CCCipher::rekey(key, kCCAlgorithmBlowfish, kCCModeCFB); + } + + virtual int blockSize() const { return 1; } + + static Properties GetProperties() { + return Properties(Range(128,256,32), "Blowfish", "CFB", "CommonCrypto"); + } +}; +REGISTER_CLASS(BfCfb, StreamCipher); + +class AesCfb : public CCCipher { + public: + AesCfb() {} + virtual ~AesCfb() {} + + virtual bool setKey(const CipherKey &key) { + return CCCipher::rekey(key, kCCAlgorithmAES128, kCCModeCFB); + } + + virtual int blockSize() const { return 1; } + + static Properties GetProperties() { + return Properties(Range(128,256,64), "AES", "CFB", "CommonCrypto"); + } +}; +REGISTER_CLASS(AesCfb, StreamCipher); + +class Sha1HMac : public MAC { + public: + Sha1HMac() {} + virtual ~Sha1HMac() {} + + virtual int outputSize() const { + return CC_SHA1_DIGEST_LENGTH; + } + + virtual bool setKey(const CipherKey &key) { + this->key = key; + return true; + } + + virtual void init() { + if (key.size() > 0) { + CCHmacInit(&ctx, kCCHmacAlgSHA1, key.data(), key.size()); + } else { + // CommonCrypto will segfault later on if a null key is passed, even if + // key length is 0. + CCHmacInit(&ctx, kCCHmacAlgSHA1, &ctx, 0); + } + } + + virtual bool update (const byte *in, int length) { + CCHmacUpdate(&ctx, in, length); + return true; + } + + virtual bool write(byte *out) { + CCHmacFinal(&ctx, out); + return true; + } + + static Properties GetProperties() { + Properties props; + props.blockSize = CC_SHA1_DIGEST_LENGTH; + props.hashFunction = "SHA-1"; + props.mode = "HMAC"; + props.library = "CommonCrypto"; + return props; + } + + private: + CipherKey key; + CCHmacContext ctx; +}; +REGISTER_CLASS(Sha1HMac, MAC); + +} // namespace commoncrypto + +void CommonCrypto::registerCiphers() { +} + +} // namespace encfs diff --git a/cipher/CommonCrypto.h b/cipher/CommonCrypto.h new file mode 100644 index 0000000..d08289b --- /dev/null +++ b/cipher/CommonCrypto.h @@ -0,0 +1,35 @@ + +/***************************************************************************** + * Author: Valient Gough + * + ***************************************************************************** + * Copyright (c) 2013 Valient Gough + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This program 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 Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef _COMMONCRYPTO_incl_ +#define _COMMONCRYPTO_incl_ + +namespace encfs { + +struct CommonCrypto { + static void registerCiphers(); +}; + +} // namespace encfs + + +#endif + diff --git a/cipher/MAC.h b/cipher/MAC.h index 436e6d6..d0b7fd5 100644 --- a/cipher/MAC.h +++ b/cipher/MAC.h @@ -35,7 +35,8 @@ class MAC virtual bool setKey(const CipherKey &key) =0; - virtual void reset() =0; + // Init must be called before any calls to update. + virtual void init() =0; virtual bool update(const byte *in, int length) =0; virtual bool write(byte *out) =0; }; diff --git a/cipher/MAC_test.cpp b/cipher/MAC_test.cpp index de8115c..7afc7d9 100644 --- a/cipher/MAC_test.cpp +++ b/cipher/MAC_test.cpp @@ -44,7 +44,7 @@ TEST(HMacSha1Test, MAC) { for (int i = 0; i < 20; ++i) key.data()[i] = 0x0b; hmac->setKey(key); - hmac->reset(); + hmac->init(); hmac->update((byte *)"Hi There", 8); hmac->write(out); ASSERT_EQ("b617318655057264e28bc0b6fb378c8ef146be00", stringToHex(out, 20)); @@ -52,7 +52,7 @@ TEST(HMacSha1Test, MAC) { // Test case 2 key = CipherKey((const byte *)"Jefe", 4); hmac->setKey(key); - hmac->reset(); + hmac->init(); hmac->update((byte *)"what do ya want for nothing?", 28); hmac->write(out); ASSERT_EQ("effcdf6ae5eb2fa2d27416d5f184df9c259a7c79", stringToHex(out, 20)); @@ -62,7 +62,7 @@ TEST(HMacSha1Test, MAC) { for (int i = 0; i < 20; ++i) key.data()[i] = 0xaa; hmac->setKey(key); - hmac->reset(); + hmac->init(); { byte data[50]; memset(data, 0xdd, 50); @@ -75,7 +75,7 @@ TEST(HMacSha1Test, MAC) { key = CipherKey(80); memset(key.data(), 0xaa, 80); hmac->setKey(key); - hmac->reset(); + hmac->init(); hmac->update((byte *)"Test Using Larger Than Block-Size Key and Larger " "Than One Block-Size Data", 73); hmac->write(out); diff --git a/cipher/MemoryPool.cpp b/cipher/MemoryPool.cpp index 5c079f3..14e68c6 100644 --- a/cipher/MemoryPool.cpp +++ b/cipher/MemoryPool.cpp @@ -42,105 +42,69 @@ #include #include -using namespace std; - +#ifdef WITH_OPENSSL # include # include +#endif namespace encfs { -static BUF_MEM *allocBlock( int size ) +#ifdef WITH_OPENSSL +static byte *allocBlock( int size ) { - BUF_MEM *block = BUF_MEM_new( ); - BUF_MEM_grow( block, size ); - VALGRIND_MAKE_MEM_NOACCESS( block->data, block->max ); - - return block; + byte *block = (byte *)OPENSSL_malloc(size); + return block; } -static void freeBlock( BUF_MEM *block ) +static void freeBlock( byte *block, int size ) { - VALGRIND_MAKE_MEM_UNDEFINED( block->data, block->max ); - BUF_MEM_free( block ); + OPENSSL_cleanse(block, size); + OPENSSL_free(block); +} +#elif defined(WITH_COMMON_CRYPTO) +static byte *allocBlock(int size) { + byte *block = new byte[size]; + return block; } -static pthread_mutex_t gMPoolMutex = PTHREAD_MUTEX_INITIALIZER; - -typedef std::map > FreeBlockMap; -static FreeBlockMap gFreeBlocks; +unsigned char cleanse_ctr = 0; +static void freeBlock(byte *data, int len) { + byte *p = data; + size_t loop = len, ctr = cleanse_ctr; + while(loop--) + { + *(p++) = (unsigned char)ctr; + ctr += (17 + ((size_t)p & 0xF)); + } + // Try to ensure the compiler doesn't optimize away the loop. + p=(byte *)memchr(data, (unsigned char)ctr, len); + if(p) + ctr += (63 + (size_t)p); + cleanse_ctr = (unsigned char)ctr; + delete[] data; +} +#endif void MemBlock::allocate(int size) { - rAssert(size > 0); - pthread_mutex_lock( &gMPoolMutex ); - - list &freeList = gFreeBlocks[size]; - BUF_MEM *mem; - - if (!freeList.empty()) - { - mem = freeList.front(); - freeList.pop_front(); - pthread_mutex_unlock( &gMPoolMutex ); - } else - { - pthread_mutex_unlock( &gMPoolMutex ); - mem = allocBlock( size ); - } - - internalData = mem; - data = reinterpret_cast(mem->data); - VALGRIND_MAKE_MEM_UNDEFINED( data, size ); + rAssert(size > 0); + this->data = allocBlock(size); + this->size = size; } MemBlock::~MemBlock() { - BUF_MEM *block = (BUF_MEM*)internalData; - data = NULL; - internalData = NULL; - - if (block) - { - // wipe the buffer.. - VALGRIND_MAKE_MEM_UNDEFINED( block->data, block->max ); - memset( block->data , 0, block->max); - VALGRIND_MAKE_MEM_NOACCESS( block->data, block->max ); - - pthread_mutex_lock( &gMPoolMutex ); - gFreeBlocks[ block->max ].push_front(block); - pthread_mutex_unlock( &gMPoolMutex ); - } -} - -void MemoryPool::destroyAll() -{ - pthread_mutex_lock( &gMPoolMutex ); - - for (FreeBlockMap::const_iterator it = gFreeBlocks.begin(); - it != gFreeBlocks.end(); it++) - { - for (list::const_iterator bIt = it->second.begin(); - bIt != it->second.end(); bIt++) - { - freeBlock( *bIt ); - } - } - - gFreeBlocks.clear(); - - pthread_mutex_unlock( &gMPoolMutex ); + freeBlock(data, size); } SecureMem::SecureMem(int len) { rAssert(len > 0); - data = (byte *)OPENSSL_malloc(len); + data = allocBlock(len); if (data) { size = len; mlock(data, size); - memset(data, '\0', size); - VALGRIND_MAKE_MEM_UNDEFINED( data, size ); } else { size = 0; @@ -151,17 +115,18 @@ SecureMem::~SecureMem() { if (size) { - memset(data, '\0', size); - OPENSSL_cleanse(data, size); - + freeBlock(data, size); munlock(data, size); - OPENSSL_free(data); - VALGRIND_MAKE_MEM_NOACCESS( data, size ); data = NULL; size = 0; } } - + +bool operator == (const SecureMem &a, const SecureMem &b) { + return (a.size == b.size) && + (memcmp(a.data, b.data, a.size) == 0); +} + } // namespace encfs diff --git a/cipher/MemoryPool.h b/cipher/MemoryPool.h index 26070a4..fcd5d96 100644 --- a/cipher/MemoryPool.h +++ b/cipher/MemoryPool.h @@ -39,7 +39,7 @@ namespace encfs { struct MemBlock { byte *data; - void *internalData; + int size; MemBlock(); ~MemBlock(); @@ -48,15 +48,10 @@ struct MemBlock }; inline MemBlock::MemBlock() - : data(0), internalData(0) + : data(0), size(0) { } -namespace MemoryPool -{ - void destroyAll(); -} - class SecureMem { public: @@ -67,6 +62,8 @@ class SecureMem ~SecureMem(); }; +bool operator == (const SecureMem &a, const SecureMem &b); + } // namespace encfs #endif diff --git a/cipher/StreamCipher.h b/cipher/StreamCipher.h index 3a54e1e..c5c8055 100644 --- a/cipher/StreamCipher.h +++ b/cipher/StreamCipher.h @@ -46,6 +46,13 @@ class StreamCipher std::string toString() const { return cipher + "/" + mode; } + Properties() {} + Properties(Range keys, const char *cipher_, const char *mode_, + const char *library_) + : keySize(keys), + cipher(cipher_), + mode(mode_), + library(library_) { } }; StreamCipher(); @@ -53,9 +60,9 @@ class StreamCipher virtual bool setKey(const CipherKey& key) =0; - virtual bool encrypt(const byte *iv, const byte *in, + virtual bool encrypt(const byte *ivec, const byte *in, byte *out, int numBytes) =0; - virtual bool decrypt(const byte *iv, const byte *in, + virtual bool decrypt(const byte *ivec, const byte *in, byte *out, int numBytes) =0; }; diff --git a/cipher/openssl.cpp b/cipher/openssl.cpp index ebf5f63..7e44e6e 100644 --- a/cipher/openssl.cpp +++ b/cipher/openssl.cpp @@ -19,6 +19,7 @@ */ #include "cipher/openssl.h" +#include "base/config.h" #include #include @@ -28,6 +29,10 @@ #include +#ifdef HAVE_VALGRIND_MEMCHECK_H +#include +#endif + #include "base/config.h" #define NO_DES @@ -54,8 +59,6 @@ #include "cipher/PBKDF.h" #include "cipher/StreamCipher.h" -using namespace std; - namespace encfs { const int MAX_KEYLENGTH = 64; // in bytes (256 bit) @@ -108,10 +111,18 @@ class OpenSSLCipher : public BlockCipher { return false; } +#ifdef HAVE_VALGRIND_MEMCHECK_H + VALGRIND_MAKE_MEM_DEFINED(key->data(), key->size()); +#endif return true; } static bool pseudoRandomize(byte *out, int length) { +#ifdef HAVE_VALGRIND_MEMCHECK_H + if (VALGRIND_CHECK_MEM_IS_ADDRESSABLE(out, length) != 0) { + return false; + } +#endif int result = RAND_pseudo_bytes( out, length ); if(result != 1) { @@ -136,12 +147,27 @@ class OpenSSLCipher : public BlockCipher { } virtual int blockSize() const { - return EVP_CIPHER_CTX_block_size(&enc); + int len = EVP_CIPHER_CTX_block_size(&enc); + // Some versions of OpenSSL report 1 for block size os AES_XTS.. + if (len == 1) + len = EVP_CIPHER_CTX_key_length(&enc); + return len; } virtual bool encrypt(const byte *ivec, const byte *in, byte *out, int size) { int dstLen = 0, tmpLen = 0; +#ifdef HAVE_VALGRIND_MEMCHECK_H + int ivLen = EVP_CIPHER_CTX_iv_length(&enc); + if (VALGRIND_CHECK_MEM_IS_DEFINED(ivec, ivLen) != 0) { + LOG(ERROR) << "expected iv of length " << ivLen; + return false; + } + if (VALGRIND_CHECK_MEM_IS_ADDRESSABLE(out, size) != 0) { + LOG(ERROR) << "expected output length " << size; + return false; + } +#endif EVP_EncryptInit_ex( &enc, NULL, NULL, NULL, ivec); EVP_EncryptUpdate( &enc, out, &dstLen, in, size); EVP_EncryptFinal_ex( &enc, out+dstLen, &tmpLen ); @@ -159,6 +185,17 @@ class OpenSSLCipher : public BlockCipher { virtual bool decrypt(const byte *ivec, const byte *in, byte *out, int size) { int dstLen = 0, tmpLen = 0; +#ifdef HAVE_VALGRIND_MEMCHECK_H + int ivLen = EVP_CIPHER_CTX_iv_length(&enc); + if (VALGRIND_CHECK_MEM_IS_DEFINED(ivec, ivLen) != 0) { + LOG(ERROR) << "expected iv of length " << ivLen; + return false; + } + if (VALGRIND_CHECK_MEM_IS_ADDRESSABLE(out, size) != 0) { + LOG(ERROR) << "expected output length " << size; + return false; + } +#endif EVP_DecryptInit_ex( &dec, NULL, NULL, NULL, ivec); EVP_DecryptUpdate( &dec, out, &dstLen, in, size ); EVP_DecryptFinal_ex( &dec, out+dstLen, &tmpLen ); @@ -346,7 +383,7 @@ class Sha1HMac : public MAC { return true; } - virtual void reset() { + virtual void init() { HMAC_Init_ex(&ctx, 0, 0, 0, 0); } @@ -364,6 +401,9 @@ class Sha1HMac : public MAC { unsigned int outSize = 0; HMAC_Final(&ctx, (unsigned char *)out, &outSize); CHECK_EQ(outputSize(), outSize) << "Invalid HMAC output size"; +#ifdef HAVE_VALGRIND_MEMCHECK_H + VALGRIND_MAKE_MEM_DEFINED(out, outSize); +#endif return true; } diff --git a/cipher/testing.cpp b/cipher/testing.cpp index 547b694..1ed5649 100644 --- a/cipher/testing.cpp +++ b/cipher/testing.cpp @@ -1,8 +1,14 @@ +#include #include +#include "base/config.h" #include "cipher/testing.h" +#ifdef HAVE_VALGRIND_MEMCHECK_H +#include +#endif + namespace encfs { static const char hexLut[] = "0123456789abcdef"; @@ -22,6 +28,9 @@ std::string stringToHex(const byte *data, int len) { } void setDataFromHex(byte *out, int len, const char *hex) { +#ifdef HAVE_VALGRIND_MEMCHECK_H + VALGRIND_CHECK_MEM_IS_ADDRESSABLE(out, len); +#endif bool odd = false; unsigned int last = 0; while (len > 0 && *hex != '\0') { @@ -49,6 +58,7 @@ void setDataFromHex(byte *out, int len, const char *hex) { } int main(int argc, char **argv) { + google::InitGoogleLogging(argv[0]); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/encfs/main.cpp b/encfs/main.cpp index f1cfbc4..374adcb 100644 --- a/encfs/main.cpp +++ b/encfs/main.cpp @@ -40,8 +40,7 @@ #include "base/Interface.h" #include "base/i18n.h" -#include "cipher/MemoryPool.h" -#include "cipher/openssl.h" +#include "cipher/CipherV1.h" #include "fs/FileUtils.h" #include "fs/DirNode.h" @@ -61,9 +60,12 @@ inline static int MAX(int a, int b) } #endif -using namespace std; -using namespace gnu; using namespace encfs; +using gnu::autosprintf; +using std::cerr; +using std::endl; +using std::string; +using std::ostringstream; namespace encfs { @@ -580,7 +582,7 @@ int main(int argc, char *argv[]) // encfs_oper.fsetattr_x #endif - OpenSSL::init( encfsArgs->isThreaded ); + CipherV1::init( encfsArgs->isThreaded ); // context is not a smart pointer because it will live for the life of // the filesystem. @@ -672,8 +674,7 @@ int main(int argc, char *argv[]) rootInfo.reset(); ctx->setRoot( shared_ptr() ); - MemoryPool::destroyAll(); - OpenSSL::shutdown( encfsArgs->isThreaded ); + CipherV1::shutdown( encfsArgs->isThreaded ); return returnCode; } diff --git a/fs/CMakeLists.txt b/fs/CMakeLists.txt index ae6b86c..27c837a 100644 --- a/fs/CMakeLists.txt +++ b/fs/CMakeLists.txt @@ -24,6 +24,16 @@ target_link_libraries (encfs-fs ${PROTOBUF_LIBRARY} ) +add_executable (checkops + checkops.cpp +) +target_link_libraries (checkops + encfs-fs + encfs-cipher + encfs-base + ${GLOG_LIBRARIES} +) + # Unit tests are optional, depends on libgtest (Google's C++ test framework). if (GTEST_FOUND) link_directories (${PROJECT_BINARY_DIR}/base) diff --git a/fs/CipherFileIO.cpp b/fs/CipherFileIO.cpp index 762a090..2bb4438 100644 --- a/fs/CipherFileIO.cpp +++ b/fs/CipherFileIO.cpp @@ -289,8 +289,7 @@ ssize_t CipherFileIO::readOneBlock( const IORequest &req ) const IORequest tmpReq = req; MemBlock mb; - if (headerLen != 0) - tmpReq.offset += headerLen; + tmpReq.offset += headerLen; int maxReadSize = req.dataLen; readSize = base->read( tmpReq ); diff --git a/fs/CipherFileIO.h b/fs/CipherFileIO.h index 2193b39..2c17f5b 100644 --- a/fs/CipherFileIO.h +++ b/fs/CipherFileIO.h @@ -84,8 +84,6 @@ private: // if haveHeader is true, then we have a transparent file header which int headerLen; - // Use block only encryption, no stream encryption. - bool blockOnlyMode; bool perFileIV; bool externalIVChaining; diff --git a/fs/Context.h b/fs/Context.h index 61888e3..00426c3 100644 --- a/fs/Context.h +++ b/fs/Context.h @@ -26,6 +26,7 @@ #include "base/Mutex.h" #include +#include #ifdef HAVE_TR1_UNORDERED_MAP #include diff --git a/fs/DirNode.cpp b/fs/DirNode.cpp index 54ab0cd..21e5452 100644 --- a/fs/DirNode.cpp +++ b/fs/DirNode.cpp @@ -44,7 +44,8 @@ #include -using namespace std; +using std::list; +using std::string; namespace encfs { diff --git a/fs/FSConfig.h b/fs/FSConfig.h index 296841a..94d1bea 100644 --- a/fs/FSConfig.h +++ b/fs/FSConfig.h @@ -75,6 +75,11 @@ struct FSConfig bool reverseEncryption; // reverse encryption operation bool idleTracking; // turn on idle monitoring of filesystem + + FSConfig() + : forceDecode(false), + reverseEncryption(false), + idleTracking(false) { } }; typedef shared_ptr FSConfigPtr; diff --git a/fs/FileNode.cpp b/fs/FileNode.cpp index 978d7c4..1895f07 100644 --- a/fs/FileNode.cpp +++ b/fs/FileNode.cpp @@ -49,7 +49,7 @@ #include -using namespace std; +using std::string; namespace encfs { diff --git a/fs/FileUtils.cpp b/fs/FileUtils.cpp index 938da03..3f61e1f 100644 --- a/fs/FileUtils.cpp +++ b/fs/FileUtils.cpp @@ -66,8 +66,12 @@ #include #include -using namespace std; -using namespace gnu; +using gnu::autosprintf; +using std::cout; +using std::cerr; +using std::endl; +using std::map; +using std::string; namespace encfs { @@ -1186,6 +1190,11 @@ void showFSInfo( const EncfsConfig &config ) cout << "\n"; } else { + // Set a null key - the cipher won't work, but it will at least know the + // key size and blocksize. + CipherKey tmpKey(config.key().size()); + cipher->setKey(tmpKey); + // check if we support the filename encoding interface.. shared_ptr nameCoder = NameIO::New( config.naming(), cipher ); if(!nameCoder) diff --git a/fs/MACFileIO.cpp b/fs/MACFileIO.cpp index cef8e6d..db48c81 100644 --- a/fs/MACFileIO.cpp +++ b/fs/MACFileIO.cpp @@ -30,8 +30,6 @@ #include -using namespace std; - namespace encfs { // diff --git a/fs/NameIO.cpp b/fs/NameIO.cpp index a7494aa..b8c6740 100644 --- a/fs/NameIO.cpp +++ b/fs/NameIO.cpp @@ -34,7 +34,11 @@ #include "fs/StreamNameIO.h" #include "fs/NullNameIO.h" -using namespace std; +using std::cerr; +using std::list; +using std::make_pair; +using std::multimap; +using std::string; namespace encfs { diff --git a/fs/RawFileIO.cpp b/fs/RawFileIO.cpp index 4b15743..fa76676 100644 --- a/fs/RawFileIO.cpp +++ b/fs/RawFileIO.cpp @@ -35,8 +35,6 @@ #include -using namespace std; - namespace encfs { static Interface RawFileIO_iface = makeInterface("FileIO/Raw", 1, 0, 0); diff --git a/fs/StreamNameIO.cpp b/fs/StreamNameIO.cpp index a7a703d..77968cf 100644 --- a/fs/StreamNameIO.cpp +++ b/fs/StreamNameIO.cpp @@ -28,8 +28,6 @@ #include -using namespace std; - namespace encfs { static shared_ptr NewStreamNameIO( const Interface &iface, diff --git a/fs/test.cpp b/fs/checkops.cpp similarity index 88% rename from fs/test.cpp rename to fs/checkops.cpp index c1a0c1d..591ca34 100644 --- a/fs/test.cpp +++ b/fs/checkops.cpp @@ -26,7 +26,7 @@ #include "base/config.h" #include "base/Interface.h" #include "base/Error.h" -#include "cipher/Cipher.h" +#include "cipher/CipherV1.h" #include "cipher/MemoryPool.h" #include "fs/DirNode.h" #include "fs/FileUtils.h" @@ -46,7 +46,7 @@ #include -#if HAVE_TR1_UNORDERED_SET +#ifdef HAVE_TR1_UNORDERED_SET #include using std::tr1::unordered_set; #else @@ -54,15 +54,17 @@ using std::tr1::unordered_set; using std::unordered_set; #endif -using namespace std; +using std::cerr; +using std::string; +using namespace encfs; namespace encfs { const int FSBlockSize = 256; static -int checkErrorPropogation( const shared_ptr &cipher, - int size, int byteToChange, const CipherKey &key ) +int checkErrorPropogation( const shared_ptr &cipher, + int size, int byteToChange ) { MemBlock orig; orig.allocate(size); @@ -77,9 +79,9 @@ int checkErrorPropogation( const shared_ptr &cipher, } if(size != FSBlockSize) - cipher->streamEncode( data.data, size, 0, key ); + cipher->streamEncode( data.data, size, 0 ); else - cipher->blockEncode( data.data, size, 0, key ); + cipher->blockEncode( data.data, size, 0 ); // intoduce an error in the encoded data, so we can check error propogation if(byteToChange >= 0 && byteToChange < size) @@ -92,9 +94,9 @@ int checkErrorPropogation( const shared_ptr &cipher, } if(size != FSBlockSize) - cipher->streamDecode( data.data, size, 0, key ); + cipher->streamDecode( data.data, size, 0 ); else - cipher->blockDecode( data.data, size, 0, key ); + cipher->blockDecode( data.data, size, 0 ); int numByteErrors = 0; for(int i=0; i &cipher, bool verbose) +bool runTests(const shared_ptr &cipher, bool verbose) { // create a random key if(verbose) @@ -205,16 +207,17 @@ bool runTests(const shared_ptr &cipher, bool verbose) int encodedKeySize = cipher->encodedKeySize(); unsigned char *keyBuf = new unsigned char [ encodedKeySize ]; - cipher->writeKey( key, keyBuf, encodingKey ); - CipherKey key2 = cipher->readKey( keyBuf, encodingKey ); - if(!key2) + cipher->setKey(encodingKey); + cipher->writeKey( key, keyBuf ); + CipherKey key2 = cipher->readKey( keyBuf, true ); + if(!key2.valid()) { if(verbose) cerr << " FAILED (decode error)\n"; return false; } - if(cipher->compareKey( key, key2 )) + if(key == key2) { if(verbose) cerr << " OK\n"; @@ -233,7 +236,8 @@ bool runTests(const shared_ptr &cipher, bool verbose) int encodedKeySize = cipher->encodedKeySize(); unsigned char *keyBuf = new unsigned char [ encodedKeySize ]; - cipher->writeKey( key, keyBuf, encodingKey ); + cipher->setKey(encodingKey); + cipher->writeKey( key, keyBuf ); // store in config struct.. EncfsConfig cfg; @@ -257,16 +261,15 @@ bool runTests(const shared_ptr &cipher, bool verbose) rAssert( cfg.block_size() == cfg2.block_size() ); // try decoding key.. - - CipherKey key2 = cipher->readKey( (unsigned char *)cfg2.key().ciphertext().data(), encodingKey ); - if(!key2) + CipherKey key2 = cipher->readKey( (unsigned char *)cfg2.key().ciphertext().data(), true ); + if(!key2.valid()) { if(verbose) cerr << " FAILED (decode error)\n"; return false; } - if(cipher->compareKey( key, key2 )) + if(key == key2) { if(verbose) cerr << " OK\n"; @@ -285,15 +288,15 @@ bool runTests(const shared_ptr &cipher, bool verbose) fsCfg->config->set_block_size(FSBlockSize); fsCfg->opts.reset(new EncFS_Opts); + cipher->setKey(key); if(verbose) cerr << "Testing name encode/decode (stream coding w/ IV chaining)\n"; - if (cipher->hasStreamMode()) { fsCfg->opts->idleTracking = false; fsCfg->config->set_unique_iv(false); fsCfg->nameCoding.reset( new StreamNameIO( - StreamNameIO::CurrentInterface(), cipher, key ) ); + StreamNameIO::CurrentInterface(), cipher) ); fsCfg->nameCoding->setChainedNameIV( true ); DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg ); @@ -308,7 +311,7 @@ bool runTests(const shared_ptr &cipher, bool verbose) fsCfg->opts->idleTracking = false; fsCfg->config->set_unique_iv(false); fsCfg->nameCoding.reset( new BlockNameIO( - BlockNameIO::CurrentInterface(), cipher, key ) ); + BlockNameIO::CurrentInterface(), cipher) ); fsCfg->nameCoding->setChainedNameIV( true ); DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg ); @@ -323,7 +326,7 @@ bool runTests(const shared_ptr &cipher, bool verbose) fsCfg->opts->idleTracking = false; fsCfg->config->set_unique_iv(false); fsCfg->nameCoding.reset( new BlockNameIO( - BlockNameIO::CurrentInterface(), cipher, key, true ) ); + BlockNameIO::CurrentInterface(), cipher) ); fsCfg->nameCoding->setChainedNameIV( true ); DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg ); @@ -334,12 +337,11 @@ bool runTests(const shared_ptr &cipher, bool verbose) if(!verbose) { - if (cipher->hasStreamMode()) { // test stream mode, this time without IV chaining fsCfg->nameCoding = shared_ptr( new StreamNameIO( - StreamNameIO::CurrentInterface(), cipher, key ) ); + StreamNameIO::CurrentInterface(), cipher) ); fsCfg->nameCoding->setChainedNameIV( false ); DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg ); @@ -351,7 +353,7 @@ bool runTests(const shared_ptr &cipher, bool verbose) { // test block mode, this time without IV chaining fsCfg->nameCoding = shared_ptr( new BlockNameIO( - BlockNameIO::CurrentInterface(), cipher, key ) ); + BlockNameIO::CurrentInterface(), cipher) ); fsCfg->nameCoding->setChainedNameIV( false ); DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg ); @@ -365,7 +367,7 @@ bool runTests(const shared_ptr &cipher, bool verbose) cerr << "Testing block encode/decode on full block - "; { int numErrors = checkErrorPropogation( cipher, - FSBlockSize, -1, key ); + FSBlockSize, -1 ); if(numErrors) { if(verbose) @@ -379,10 +381,9 @@ bool runTests(const shared_ptr &cipher, bool verbose) } if(verbose) cerr << "Testing block encode/decode on partial block - "; - if (cipher->hasStreamMode()) { int numErrors = checkErrorPropogation( cipher, - FSBlockSize-1, -1, key ); + FSBlockSize-1, -1 ); if(numErrors) { if(verbose) @@ -397,7 +398,6 @@ bool runTests(const shared_ptr &cipher, bool verbose) if(verbose) cerr << "Checking error propogation in partial block:\n"; - if (cipher->hasStreamMode()) { int minChanges = FSBlockSize-1; int maxChanges = 0; @@ -406,7 +406,7 @@ bool runTests(const shared_ptr &cipher, bool verbose) for(int i=0; i &cipher, bool verbose) for(int i=0; i &cipher, bool verbose) return true; } +} // namespace encfs int main(int argc, char *argv[]) { @@ -488,9 +489,9 @@ int main(int argc, char *argv[]) srand( time(0) ); // get a list of the available algorithms - std::list algorithms = - Cipher::GetAlgorithmList(); - std::list::const_iterator it; + std::list algorithms = + CipherV1::GetAlgorithmList(); + std::list::const_iterator it; cerr << "Supported Crypto interfaces:\n"; for(it = algorithms.begin(); it != algorithms.end(); ++it) { @@ -515,7 +516,7 @@ int main(int argc, char *argv[]) cerr << it->name << ", key length " << keySize << ", block size " << blockSize << ": "; - shared_ptr cipher = Cipher::New( it->name, keySize ); + shared_ptr cipher = CipherV1::New( it->name, keySize ); if(!cipher) { cerr << "FAILED TO CREATE\n"; @@ -536,7 +537,7 @@ int main(int argc, char *argv[]) } // run one test with verbose output too.. - shared_ptr cipher = Cipher::New("AES", 192); + shared_ptr cipher = CipherV1::New("AES", 192); if(!cipher) { cerr << "\nNo AES cipher found, skipping verbose test.\n"; @@ -549,10 +550,6 @@ int main(int argc, char *argv[]) runTests( cipher, true ); } - MemoryPool::destroyAll(); - return 0; } -} // namespace encfs - diff --git a/fs/encfs.cpp b/fs/encfs.cpp index 5068c68..e3e4f18 100644 --- a/fs/encfs.cpp +++ b/fs/encfs.cpp @@ -43,11 +43,14 @@ #ifdef HAVE_TR1_TUPLE #include -using namespace std; -using namespace std::tr1; +using std::tr1::get; +using std::tr1::make_tuple; +using std::tr1::tuple; #else #include -using namespace std; +using std::get; +using std::make_tuple; +using std::tuple; #endif #include "base/config.h" @@ -61,6 +64,10 @@ using namespace std; #include +using std::map; +using std::string; +using std::vector; + namespace encfs { #ifndef MIN diff --git a/fs/test_IO.cpp b/fs/test_IO.cpp index 2e82cb9..9e4bfd6 100644 --- a/fs/test_IO.cpp +++ b/fs/test_IO.cpp @@ -76,6 +76,38 @@ TEST(IOTest, MacIO) { runWithAllCiphers(testMacIO); } +void testBasicCipherIO(FSConfigPtr& cfg) { + shared_ptr base(new MemFileIO(0)); + shared_ptr test(new CipherFileIO(base, cfg)); + + byte buf[1024]; + cfg->cipher->pseudoRandomize(buf, sizeof(buf)); + + IORequest req; + req.data = new byte[sizeof(buf)]; + req.offset = 0; + req.dataLen = sizeof(buf); + + memcpy(req.data, buf, sizeof(buf)); + ASSERT_TRUE(test->write(req)); + + memset(req.data, 0, sizeof(buf)); + ASSERT_EQ(req.dataLen, test->read(req)); + + for (unsigned int i = 0; i < sizeof(buf); ++i) { + bool match = (buf[i] == req.data[i]); + ASSERT_TRUE(match) << "mismatched data at offset " << i; + if (!match) + break; + } + + delete[] req.data; +} + +TEST(IOTest, BasicCipherFileIO) { + runWithAllCiphers(testBasicCipherIO); +} + void testCipherIO(FSConfigPtr& cfg) { shared_ptr base(new MemFileIO(0)); shared_ptr test(new CipherFileIO(base, cfg)); diff --git a/fs/testing.cpp b/fs/testing.cpp index 329e08b..960843b 100644 --- a/fs/testing.cpp +++ b/fs/testing.cpp @@ -36,7 +36,8 @@ #include "fs/MACFileIO.h" #include "fs/MemFileIO.h" -using namespace std; +using std::list; +using std::string; namespace encfs { @@ -92,27 +93,46 @@ void truncate(FileIO* a, FileIO* b, int len) { void writeRandom(FSConfigPtr& cfg, FileIO* a, FileIO* b, int offset, int len) { SCOPED_TRACE(testing::Message() << "Write random " << offset << ", " << len); - if (a->getSize() < offset + len) + if (a->getSize() < offset + len) { a->truncate(offset + len); + } + if (b->getSize() < offset + len) { + b->truncate(offset + len); + } + unsigned char *buf = new unsigned char[len]; ASSERT_TRUE(cfg->cipher->pseudoRandomize(buf, len)); IORequest req; req.data = new unsigned char[len]; req.dataLen = len; - + memcpy(req.data, buf, len); req.offset = offset; ASSERT_TRUE(a->write(req)); + + // Check that write succeeded. + req.offset = offset; + req.dataLen = len; + ASSERT_EQ(len, a->read(req)); + ASSERT_TRUE(memcmp(req.data, buf, len) == 0); memcpy(req.data, buf, len); req.offset = offset; + req.dataLen = len; ASSERT_TRUE(b->write(req)); + // Check that write succeeded. + req.offset = offset; + req.dataLen = len; + ASSERT_EQ(len, b->read(req)); + ASSERT_TRUE(memcmp(req.data, buf, len) == 0); + compare(a, b, offset, len); delete[] buf; + delete[] req.data; } void compare(FileIO* a, FileIO* b, int offset, int len) { @@ -137,7 +157,8 @@ void compare(FileIO* a, FileIO* b, int offset, int len) { ASSERT_EQ(size1, size2); for(int i = 0; i < len; i++) { bool match = (buf1[i] == buf2[i]); - ASSERT_TRUE(match) << "mismatched data at offset " << i << " of " << len; + ASSERT_TRUE(match) << "mismatched data at offset " << i << " of " << len + << ", got " << int(buf1[i]) << " and " << int(buf2[i]); if(!match) { break; } @@ -148,15 +169,13 @@ void compare(FileIO* a, FileIO* b, int offset, int len) { } void comparisonTest(FSConfigPtr& cfg, FileIO* a, FileIO* b) { - const int size = 18*1024; + const int size = 2*1024; writeRandom(cfg, a, b, 0, size); if (testing::Test::HasFatalFailure()) return; - compare(a, b, 0, size); - if (testing::Test::HasFatalFailure()) return; for (int i = 0; i < 10000; i++) { SCOPED_TRACE(testing::Message() << "Test Loop " << i); - int len = 128 + random() % 2048; + int len = 128 + random() % 512; int offset = (len == a->getSize()) ? 0 : random() % (a->getSize() - len); writeRandom(cfg, a, b, offset, len); diff --git a/po/CMakeLists.txt b/po/CMakeLists.txt index feff967..ef928b0 100644 --- a/po/CMakeLists.txt +++ b/po/CMakeLists.txt @@ -4,7 +4,7 @@ file (GLOB CXX_FILES RELATIVE ${PROJECT_SOURCE_DIR} "*/*.cpp") set (GettextTranslate_GMO_BINARY true) -include (GetTextTranslate) +include (GettextTranslate) diff --git a/util/CMakeLists.txt b/util/CMakeLists.txt index 6bdfde1..700f07f 100644 --- a/util/CMakeLists.txt +++ b/util/CMakeLists.txt @@ -18,7 +18,6 @@ target_link_libraries (encfsctl encfs-cipher encfs-base ${GLOG_LIBRARIES} - ${FUSE_LIBRARIES} ) if (POD2MAN) diff --git a/util/encfsctl.cpp b/util/encfsctl.cpp index 2caa72a..6b4fffb 100644 --- a/util/encfsctl.cpp +++ b/util/encfsctl.cpp @@ -50,9 +50,14 @@ #include #endif -using namespace std; -using namespace gnu; using namespace encfs; +using gnu::autosprintf; +using std::cerr; +using std::cin; +using std::cout; +using std::endl; +using std::string; +using std::vector; static int showInfo( int argc, char **argv ); static int showVersion( int argc, char **argv ); diff --git a/util/makeKey.cpp b/util/makeKey.cpp index d5e4479..fb93585 100644 --- a/util/makeKey.cpp +++ b/util/makeKey.cpp @@ -29,8 +29,6 @@ #include #include -using namespace std; - void genKey( const shared_ptr &cipher ) { CipherKey key = cipher->newRandomKey();