mirror of
https://github.com/vgough/encfs.git
synced 2024-11-22 16:03:34 +01:00
add CommonCrypto support, other misc fixes
git-svn-id: http://encfs.googlecode.com/svn/trunk@97 db9cf616-1c43-0410-9cb8-a902689de0d6
This commit is contained in:
parent
5a126ea797
commit
63c2d1c539
@ -3,11 +3,17 @@ project(Encfs)
|
|||||||
|
|
||||||
set (ENCFS_MAJOR 2)
|
set (ENCFS_MAJOR 2)
|
||||||
set (ENCFS_MINOR 0)
|
set (ENCFS_MINOR 0)
|
||||||
set (ENCFS_PATCH 0)
|
set (ENCFS_VERSION "${ENCFS_MAJOR}.${ENCFS_MINOR}")
|
||||||
set (ENCFS_VERSION "${ENCFS_MAJOR}.${ENCFS_MINOR}.${ENCFS_PATCH}")
|
|
||||||
|
|
||||||
option (BUILD_SHARED_LIBS "Build dynamic link libraries" OFF)
|
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}
|
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
|
||||||
"${CMAKE_SOURCE_DIR}/CMakeModules/")
|
"${CMAKE_SOURCE_DIR}/CMakeModules/")
|
||||||
|
|
||||||
@ -36,7 +42,6 @@ endif (APPLE)
|
|||||||
set (CPACK_PACKAGE_NAME "Encfs")
|
set (CPACK_PACKAGE_NAME "Encfs")
|
||||||
set (CPACK_PACKAGE_VERSION_MAJOR ${ENCFS_MAJOR})
|
set (CPACK_PACKAGE_VERSION_MAJOR ${ENCFS_MAJOR})
|
||||||
set (CPACK_PACKAGE_VERSION_MINOR ${ENCFS_MINOR})
|
set (CPACK_PACKAGE_VERSION_MINOR ${ENCFS_MINOR})
|
||||||
set (CPACK_PACKAGE_VERSION_PATCH ${ENCFS_PATCH})
|
|
||||||
set (CPACK_SOURCE_GENERATOR TGZ)
|
set (CPACK_SOURCE_GENERATOR TGZ)
|
||||||
set (CPACK_SOURCE_IGNORE_FILES
|
set (CPACK_SOURCE_IGNORE_FILES
|
||||||
"/_darcs/"
|
"/_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/valgrind.h HAVE_VALGRIND_VALGRIND_H)
|
||||||
check_include_file_cxx (valgrind/memcheck.h HAVE_VALGRIND_MEMCHECK_H)
|
check_include_file_cxx (valgrind/memcheck.h HAVE_VALGRIND_MEMCHECK_H)
|
||||||
|
|
||||||
|
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.
|
# TODO: move this to cipher directory.
|
||||||
find_package (OpenSSL REQUIRED)
|
find_package (OpenSSL REQUIRED)
|
||||||
include (OpenSSLTests)
|
include (OpenSSLTests)
|
||||||
|
endif (WITH_OPENSSL)
|
||||||
|
|
||||||
# Check if xattr functions take extra argument.
|
# Check if xattr functions take extra argument.
|
||||||
include (CheckCXXSourceCompiles)
|
include (CheckCXXSourceCompiles)
|
||||||
|
@ -30,7 +30,9 @@
|
|||||||
|
|
||||||
#include "base/types.h"
|
#include "base/types.h"
|
||||||
|
|
||||||
using namespace std;
|
using std::make_pair;
|
||||||
|
using std::map;
|
||||||
|
using std::string;
|
||||||
|
|
||||||
namespace encfs {
|
namespace encfs {
|
||||||
|
|
||||||
|
@ -38,8 +38,7 @@
|
|||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include "base/base64.h"
|
#include "base/base64.h"
|
||||||
#include "base/Interface.h"
|
#include "base/Interface.h"
|
||||||
|
#include "base/shared_ptr.h"
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace encfs {
|
namespace encfs {
|
||||||
|
|
||||||
@ -116,16 +115,9 @@ bool XmlValue::readB64(const char *path, byte *data, int length) const
|
|||||||
|
|
||||||
std::string s = value->text();
|
std::string s = value->text();
|
||||||
s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end());
|
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());
|
int decodedSize = B64ToB256Bytes(s.size());
|
||||||
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);
|
|
||||||
|
|
||||||
if (decodedSize != length)
|
if (decodedSize != length)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "decoding bytes len " << s.size()
|
LOG(ERROR) << "decoding bytes len " << s.size()
|
||||||
@ -133,6 +125,8 @@ bool XmlValue::readB64(const char *path, byte *data, int length) const
|
|||||||
<< ", got " << decodedSize;
|
<< ", got " << decodedSize;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
changeBase2((byte *)s.data(), s.size(), 6, data, length, 8);
|
||||||
|
B64ToAsciiStandard(data, length);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -148,6 +148,25 @@ void B64ToAscii(byte *in, int length)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void B64ToAsciiStandard(byte *in, int length)
|
||||||
|
{
|
||||||
|
static const char LookupTable[] = "+/0123456789";
|
||||||
|
for(int offset=0; offset<length; ++offset)
|
||||||
|
{
|
||||||
|
int ch = in[offset];
|
||||||
|
if(ch > 11)
|
||||||
|
{
|
||||||
|
if(ch > 37)
|
||||||
|
ch += 'a' - 38;
|
||||||
|
else
|
||||||
|
ch += 'A' - 12;
|
||||||
|
} else
|
||||||
|
ch = LookupTable[ ch ];
|
||||||
|
|
||||||
|
in[offset] = ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const byte Ascii2B64Table[] =
|
static const byte Ascii2B64Table[] =
|
||||||
" 01 23456789:; ";
|
" 01 23456789:; ";
|
||||||
// 0123456789 123456789 123456789 123456789 123456789 123456789 1234
|
// 0123456789 123456789 123456789 123456789 123456789 123456789 1234
|
||||||
|
@ -62,6 +62,8 @@ void changeBase2Inline(byte *buf, int srcLength,
|
|||||||
|
|
||||||
// inplace translation from values [0,2^6] => base64 ASCII
|
// inplace translation from values [0,2^6] => base64 ASCII
|
||||||
void B64ToAscii(byte *buf, int length);
|
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
|
// inplace translation from values [0,2^5] => base32 ASCII
|
||||||
void B32ToAscii(byte *buf, int length);
|
void B32ToAscii(byte *buf, int length);
|
||||||
|
|
||||||
|
@ -10,15 +10,19 @@
|
|||||||
#cmakedefine HAVE_TR1_UNORDERED_SET
|
#cmakedefine HAVE_TR1_UNORDERED_SET
|
||||||
#cmakedefine HAVE_TR1_TUPLE
|
#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_BF
|
||||||
#cmakedefine HAVE_EVP_AES
|
#cmakedefine HAVE_EVP_AES
|
||||||
#cmakedefine HAVE_EVP_AES_XTS
|
#cmakedefine HAVE_EVP_AES_XTS
|
||||||
|
|
||||||
#cmakedefine HAVE_LCHMOD
|
#cmakedefine HAVE_LCHMOD
|
||||||
|
|
||||||
#cmakedefine HAVE_VALGRIND_VALGRIND_H
|
|
||||||
#cmakedefine HAVE_VALGRIND_MEMCHECK_H
|
|
||||||
|
|
||||||
/* TODO: add other thread library support. */
|
/* TODO: add other thread library support. */
|
||||||
#cmakedefine CMAKE_USE_PTHREADS_INIT
|
#cmakedefine CMAKE_USE_PTHREADS_INIT
|
||||||
|
|
||||||
|
@ -1,7 +1,14 @@
|
|||||||
#include "cipher/BlockCipher.h"
|
#include "cipher/BlockCipher.h"
|
||||||
|
|
||||||
// TODO: add ifdef when OpenSSL becomes optional.
|
#include "base/config.h"
|
||||||
|
|
||||||
|
#ifdef WITH_OPENSSL
|
||||||
#include "cipher/openssl.h"
|
#include "cipher/openssl.h"
|
||||||
|
#endif
|
||||||
|
#ifdef WITH_COMMON_CRYPTO
|
||||||
|
#include "cipher/CommonCrypto.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "cipher/NullCiphers.h"
|
#include "cipher/NullCiphers.h"
|
||||||
|
|
||||||
namespace encfs {
|
namespace encfs {
|
||||||
@ -12,7 +19,12 @@ Registry<BlockCipher>& BlockCipher::GetRegistry()
|
|||||||
static bool first = true;
|
static bool first = true;
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
|
#ifdef WITH_OPENSSL
|
||||||
OpenSSL::registerCiphers();
|
OpenSSL::registerCiphers();
|
||||||
|
#endif
|
||||||
|
#ifdef WITH_COMMON_CRYPTO
|
||||||
|
CommonCrypto::registerCiphers();
|
||||||
|
#endif
|
||||||
NullCiphers::registerCiphers();
|
NullCiphers::registerCiphers();
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
@ -23,12 +23,17 @@
|
|||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "base/config.h"
|
||||||
#include "base/shared_ptr.h"
|
#include "base/shared_ptr.h"
|
||||||
#include "cipher/BlockCipher.h"
|
#include "cipher/BlockCipher.h"
|
||||||
#include "cipher/MemoryPool.h"
|
#include "cipher/MemoryPool.h"
|
||||||
#include "cipher/PBKDF.h"
|
#include "cipher/PBKDF.h"
|
||||||
#include "cipher/testing.h"
|
#include "cipher/testing.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||||
|
#include <valgrind/memcheck.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace encfs;
|
using namespace encfs;
|
||||||
using std::list;
|
using std::list;
|
||||||
using std::string;
|
using std::string;
|
||||||
@ -36,6 +41,10 @@ using std::string;
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void compare(const byte *a, const byte *b, int size) {
|
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++) {
|
for (int i = 0; i < size; i++) {
|
||||||
bool match = (a[i] == b[i]);
|
bool match = (a[i] == b[i]);
|
||||||
ASSERT_TRUE(match) << "mismatched data at offset " << i
|
ASSERT_TRUE(match) << "mismatched data at offset " << i
|
||||||
@ -61,31 +70,83 @@ TEST(RequiredStreamCiphers, StreamCipher) {
|
|||||||
ASSERT_TRUE(bf_cfb != NULL);
|
ASSERT_TRUE(bf_cfb != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BlowfishTestVector, BlockCihper) {
|
template <typename T>
|
||||||
auto cbc = BlockCipher::GetRegistry().CreateForMatch(NAME_BLOWFISH_CBC);
|
void checkTestVector(const char *cipherName,
|
||||||
auto cfb = StreamCipher::GetRegistry().CreateForMatch(NAME_BLOWFISH_CFB);
|
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);
|
auto cipher = T::GetRegistry().CreateForMatch(cipherName);
|
||||||
setDataFromHex(key.data(), key.size(), "0123456789abcdeff0e1d2c3b4a59687");
|
ASSERT_TRUE(cipher != NULL);
|
||||||
cbc->setKey(key);
|
|
||||||
cfb->setKey(key);
|
|
||||||
|
|
||||||
byte iv[8];
|
CipherKey key(strlen(hexKey)/2);
|
||||||
setDataFromHex(iv, 8, "fedcba9876543210");
|
setDataFromHex(key.data(), key.size(), hexKey);
|
||||||
|
ASSERT_TRUE(cipher->setKey(key));
|
||||||
|
|
||||||
byte data[32];
|
byte iv[strlen(hexIv)/2];
|
||||||
setDataFromHex(data, 32,
|
setDataFromHex(iv, sizeof(iv), hexIv);
|
||||||
"37363534333231204e6f77206973207468652074696d6520666f722000000000");
|
|
||||||
|
|
||||||
byte cipherData[32];
|
byte plaintext[strlen(hexPlaintext)/2];
|
||||||
cbc->encrypt(iv, data, cipherData, 32);
|
setDataFromHex(plaintext, sizeof(plaintext), hexPlaintext);
|
||||||
|
|
||||||
ASSERT_EQ("6b77b4d63006dee605b156e27403979358deb9e7154616d959f1652bd5ff92cc",
|
byte ciphertext[sizeof(plaintext)];
|
||||||
stringToHex(cipherData, 32));
|
ASSERT_TRUE(cipher->encrypt(iv, plaintext, ciphertext, sizeof(ciphertext)));
|
||||||
|
|
||||||
cfb->encrypt(iv, data, cipherData, 29);
|
ASSERT_EQ(hexCipher, stringToHex(ciphertext, sizeof(ciphertext)));
|
||||||
ASSERT_EQ("e73214a2822139caf26ecf6d2eb9e76e3da3de04d1517200519d57a6c3",
|
|
||||||
stringToHex(cipherData, 29));
|
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<BlockCipher>(NAME_BLOWFISH_CBC,
|
||||||
|
"0123456789abcdeff0e1d2c3b4a59687",
|
||||||
|
"fedcba9876543210",
|
||||||
|
"37363534333231204e6f77206973207468652074696d6520666f722000000000",
|
||||||
|
"6b77b4d63006dee605b156e27403979358deb9e7154616d959f1652bd5ff92cc");
|
||||||
|
|
||||||
|
// BF128 CFB
|
||||||
|
checkTestVector<StreamCipher>(NAME_BLOWFISH_CFB,
|
||||||
|
"0123456789abcdeff0e1d2c3b4a59687",
|
||||||
|
"fedcba9876543210",
|
||||||
|
"37363534333231204e6f77206973207468652074696d6520666f722000",
|
||||||
|
"e73214a2822139caf26ecf6d2eb9e76e3da3de04d1517200519d57a6c3");
|
||||||
|
|
||||||
|
// AES128 CBC
|
||||||
|
checkTestVector<BlockCipher>(NAME_AES_CBC,
|
||||||
|
"2b7e151628aed2a6abf7158809cf4f3c",
|
||||||
|
"000102030405060708090a0b0c0d0e0f",
|
||||||
|
"6bc1bee22e409f96e93d7e117393172a",
|
||||||
|
"7649abac8119b246cee98e9b12e9197d");
|
||||||
|
|
||||||
|
// AES128 CFB
|
||||||
|
checkTestVector<StreamCipher>(NAME_AES_CFB,
|
||||||
|
"2b7e151628aed2a6abf7158809cf4f3c",
|
||||||
|
"000102030405060708090a0b0c0d0e0f",
|
||||||
|
"6bc1bee22e409f96e93d7e117393172a",
|
||||||
|
"3b3fd92eb72dad20333449f8e83cfb4a");
|
||||||
|
|
||||||
|
// AES256 CBC
|
||||||
|
checkTestVector<BlockCipher>(NAME_AES_CBC,
|
||||||
|
"603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
|
||||||
|
"000102030405060708090a0b0c0d0e0f",
|
||||||
|
"6bc1bee22e409f96e93d7e117393172a",
|
||||||
|
"f58c4c04d6e5f1ba779eabfb5f7bfbd6");
|
||||||
|
|
||||||
|
// AES256 CFB
|
||||||
|
checkTestVector<StreamCipher>(NAME_AES_CFB,
|
||||||
|
"603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
|
||||||
|
"000102030405060708090a0b0c0d0e0f",
|
||||||
|
"6bc1bee22e409f96e93d7e117393172a",
|
||||||
|
"dc7e84bfda79164b7ecd8486985d3860");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(BlockEncryptionTest, BlockCipher) {
|
TEST(BlockEncryptionTest, BlockCipher) {
|
||||||
@ -109,10 +170,12 @@ TEST(BlockEncryptionTest, BlockCipher) {
|
|||||||
|
|
||||||
CipherKey key = pbkdf->randomKey(keySize / 8);
|
CipherKey key = pbkdf->randomKey(keySize / 8);
|
||||||
ASSERT_TRUE(key.valid());
|
ASSERT_TRUE(key.valid());
|
||||||
cipher->setKey(key);
|
ASSERT_TRUE(cipher->setKey(key));
|
||||||
|
|
||||||
// Create some data to encrypt.
|
// Create some data to encrypt.
|
||||||
int blockSize = cipher->blockSize();
|
int blockSize = cipher->blockSize();
|
||||||
|
SCOPED_TRACE(testing::Message() << "blockSize " << blockSize);
|
||||||
|
|
||||||
MemBlock mb;
|
MemBlock mb;
|
||||||
mb.allocate(16 * blockSize);
|
mb.allocate(16 * blockSize);
|
||||||
|
|
||||||
|
@ -1,7 +1,16 @@
|
|||||||
include_directories (${OPENSSL_INCLUDE_DIR})
|
|
||||||
|
|
||||||
link_directories (${Encfs_BINARY_DIR}/base)
|
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
|
add_library (encfs-cipher
|
||||||
BlockCipher.cpp
|
BlockCipher.cpp
|
||||||
CipherKey.cpp
|
CipherKey.cpp
|
||||||
@ -9,14 +18,14 @@ add_library (encfs-cipher
|
|||||||
MAC.cpp
|
MAC.cpp
|
||||||
MemoryPool.cpp
|
MemoryPool.cpp
|
||||||
NullCiphers.cpp
|
NullCiphers.cpp
|
||||||
openssl.cpp
|
|
||||||
PBKDF.cpp
|
PBKDF.cpp
|
||||||
readpassphrase.cpp
|
readpassphrase.cpp
|
||||||
StreamCipher.cpp
|
StreamCipher.cpp
|
||||||
|
${EXTRA_SOURCE}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries (encfs-cipher
|
target_link_libraries (encfs-cipher
|
||||||
${OPENSSL_LIBRARIES}
|
${EXTRA_LIBS}
|
||||||
)
|
)
|
||||||
|
|
||||||
if (GTEST_FOUND)
|
if (GTEST_FOUND)
|
||||||
|
45
cipher/CipherKey_test.cpp
Normal file
45
cipher/CipherKey_test.cpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#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 <valgrind/memcheck.h>
|
||||||
|
#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
|
@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cipher/CipherV1.h"
|
#include "cipher/CipherV1.h"
|
||||||
|
#include "base/config.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
@ -28,18 +29,29 @@
|
|||||||
|
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||||
|
#include <valgrind/memcheck.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "base/base64.h"
|
#include "base/base64.h"
|
||||||
#include "base/Error.h"
|
#include "base/Error.h"
|
||||||
#include "base/i18n.h"
|
#include "base/i18n.h"
|
||||||
#include "base/Mutex.h"
|
#include "base/Mutex.h"
|
||||||
#include "base/Range.h"
|
#include "base/Range.h"
|
||||||
|
|
||||||
#include "cipher/MemoryPool.h"
|
#include "cipher/MemoryPool.h"
|
||||||
#include "cipher/MAC.h"
|
#include "cipher/MAC.h"
|
||||||
#include "cipher/BlockCipher.h"
|
#include "cipher/BlockCipher.h"
|
||||||
#include "cipher/PBKDF.h"
|
#include "cipher/PBKDF.h"
|
||||||
#include "cipher/StreamCipher.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 {
|
namespace encfs {
|
||||||
|
|
||||||
@ -54,6 +66,18 @@ inline int MIN(int a, int b)
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
DEPRECATED: this is here for backward compatibilty only. Use PBKDF
|
||||||
|
|
||||||
@ -77,7 +101,7 @@ bool BytesToKey(const byte *data, int dataLen,
|
|||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
sha1->reset();
|
sha1->init();
|
||||||
if( addmd++ )
|
if( addmd++ )
|
||||||
sha1->update(mdBuf.data, mdBuf.size);
|
sha1->update(mdBuf.data, mdBuf.size);
|
||||||
sha1->update(data, dataLen);
|
sha1->update(data, dataLen);
|
||||||
@ -85,7 +109,7 @@ bool BytesToKey(const byte *data, int dataLen,
|
|||||||
|
|
||||||
for(unsigned int i=1; i < rounds; ++i)
|
for(unsigned int i=1; i < rounds; ++i)
|
||||||
{
|
{
|
||||||
sha1->reset();
|
sha1->init();
|
||||||
sha1->update(mdBuf.data, mdBuf.size);
|
sha1->update(mdBuf.data, mdBuf.size);
|
||||||
sha1->write(mdBuf.data);
|
sha1->write(mdBuf.data);
|
||||||
}
|
}
|
||||||
@ -115,6 +139,10 @@ int CipherV1::TimedPBKDF2(const char *pass, int passlen,
|
|||||||
const byte *salt, int saltlen,
|
const byte *salt, int saltlen,
|
||||||
CipherKey *key, long desiredPDFTime)
|
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<PBKDF> registry = PBKDF::GetRegistry();
|
Registry<PBKDF> registry = PBKDF::GetRegistry();
|
||||||
shared_ptr<PBKDF> impl(registry.CreateForMatch(NAME_PKCS5_PBKDF2_HMAC_SHA1));
|
shared_ptr<PBKDF> impl(registry.CreateForMatch(NAME_PKCS5_PBKDF2_HMAC_SHA1));
|
||||||
if (!impl)
|
if (!impl)
|
||||||
@ -212,10 +240,17 @@ shared_ptr<CipherV1> CipherV1::New(const std::string& name, int keyLen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<CipherV1> CipherV1::New(const Interface &iface, int keyLen) {
|
shared_ptr<CipherV1> CipherV1::New(const Interface &iface, int keyLen) {
|
||||||
return shared_ptr<CipherV1>(new CipherV1(iface, iface, keyLen));
|
shared_ptr<CipherV1> result(new CipherV1());
|
||||||
|
if (!result->initCiphers(iface, iface, keyLen))
|
||||||
|
result.reset();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CipherV1::CipherV1(const Interface &iface, const Interface &realIface,
|
CipherV1::CipherV1()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CipherV1::initCiphers(const Interface &iface, const Interface &realIface,
|
||||||
int keyLength)
|
int keyLength)
|
||||||
{
|
{
|
||||||
this->iface = iface;
|
this->iface = iface;
|
||||||
@ -243,12 +278,11 @@ CipherV1::CipherV1(const Interface &iface, const Interface &realIface,
|
|||||||
defaultKeyLength = 0;
|
defaultKeyLength = 0;
|
||||||
_blockCipher.reset( blockCipherRegistry.CreateForMatch("NullCipher") );
|
_blockCipher.reset( blockCipherRegistry.CreateForMatch("NullCipher") );
|
||||||
_streamCipher.reset( streamCipherRegistry.CreateForMatch("NullCipher") );
|
_streamCipher.reset( streamCipherRegistry.CreateForMatch("NullCipher") );
|
||||||
} else {
|
|
||||||
throw Error("Unsupported cipher");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_blockCipher || !_streamCipher) {
|
if (!_blockCipher || !_streamCipher) {
|
||||||
throw Error("Requested cipher not available");
|
LOG(INFO) << "Unsupported cipher " << iface.name();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyLength <= 0)
|
if (keyLength <= 0)
|
||||||
@ -259,7 +293,8 @@ CipherV1::CipherV1(const Interface &iface, const Interface &realIface,
|
|||||||
_pbkdf.reset(PBKDF::GetRegistry().CreateForMatch(
|
_pbkdf.reset(PBKDF::GetRegistry().CreateForMatch(
|
||||||
NAME_PKCS5_PBKDF2_HMAC_SHA1));
|
NAME_PKCS5_PBKDF2_HMAC_SHA1));
|
||||||
if (!_pbkdf) {
|
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
|
// 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);
|
Lock l(_hmacMutex);
|
||||||
_hmac.reset(MAC::GetRegistry().CreateForMatch(NAME_SHA1_HMAC));
|
_hmac.reset(MAC::GetRegistry().CreateForMatch(NAME_SHA1_HMAC));
|
||||||
if (!_hmac)
|
if (!_hmac) {
|
||||||
throw Error("SHA1_HMAC not available");
|
LOG(ERROR) << "SHA1_HMAC not available";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CipherV1::~CipherV1()
|
CipherV1::~CipherV1()
|
||||||
@ -296,6 +335,10 @@ CipherKey CipherV1::newKey(const char *password, int passwdLength,
|
|||||||
int *iterationCount, long desiredDuration,
|
int *iterationCount, long desiredDuration,
|
||||||
const byte *salt, int saltLen)
|
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);
|
CipherKey key(_keySize + _ivLength);
|
||||||
|
|
||||||
if(*iterationCount == 0)
|
if(*iterationCount == 0)
|
||||||
@ -329,6 +372,9 @@ CipherKey CipherV1::newKey(const char *password, int passwdLength,
|
|||||||
// password is changed or configuration is rewritten.
|
// password is changed or configuration is rewritten.
|
||||||
CipherKey CipherV1::newKey(const char *password, int passwdLength)
|
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);
|
CipherKey key(_keySize + _ivLength);
|
||||||
|
|
||||||
bool ok = BytesToKey((byte *)password, passwdLength, 16, &key);
|
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()];
|
byte md[_hmac->outputSize()];
|
||||||
|
|
||||||
Lock l(_hmacMutex);
|
Lock l(_hmacMutex);
|
||||||
_hmac->reset();
|
|
||||||
|
|
||||||
|
_hmac->init();
|
||||||
_hmac->update(data, len);
|
_hmac->update(data, len);
|
||||||
if(chainedIV)
|
if(chainedIV)
|
||||||
{
|
{
|
||||||
@ -398,8 +444,11 @@ uint64_t CipherV1::MAC_64(const byte *data, int len,
|
|||||||
|
|
||||||
// chop this down to a 64bit value..
|
// chop this down to a 64bit value..
|
||||||
byte h[8] = {0,0,0,0,0,0,0,0};
|
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]);
|
h[i%8] ^= (byte)(md[i]);
|
||||||
|
|
||||||
uint64_t value = (uint64_t)h[0];
|
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];
|
checksum = (checksum << 8) | (unsigned int)data[i];
|
||||||
|
|
||||||
memcpy( key.data(), data+KEY_CHECKSUM_BYTES, key.size() );
|
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
|
// check for success
|
||||||
|
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||||
|
VALGRIND_CHECK_MEM_IS_DEFINED(key.data(), key.size());
|
||||||
|
#endif
|
||||||
|
|
||||||
unsigned int checksum2 = reduceMac32(
|
unsigned int checksum2 = reduceMac32(
|
||||||
MAC_64( key.data(), key.size(), NULL ));
|
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
|
<< ", got " << checksum2
|
||||||
<< "on decode of " << _keySize + _ivLength << " bytes";
|
<< "on decode of " << _keySize + _ivLength << " bytes";
|
||||||
return CipherKey();
|
return CipherKey();
|
||||||
@ -454,7 +516,6 @@ CipherKey CipherV1::readKey(const byte *data, bool checkKey)
|
|||||||
void CipherV1::writeKey(const CipherKey &ckey, byte *out)
|
void CipherV1::writeKey(const CipherKey &ckey, byte *out)
|
||||||
{
|
{
|
||||||
rAssert( _keySet );
|
rAssert( _keySet );
|
||||||
rAssert(ckey.size() > KEY_CHECKSUM_BYTES);
|
|
||||||
|
|
||||||
SecureMem tmpBuf(ckey.size());
|
SecureMem tmpBuf(ckey.size());
|
||||||
memcpy(tmpBuf.data, ckey.data(), tmpBuf.size);
|
memcpy(tmpBuf.data, ckey.data(), tmpBuf.size);
|
||||||
@ -463,14 +524,14 @@ void CipherV1::writeKey(const CipherKey &ckey, byte *out)
|
|||||||
MAC_64(tmpBuf.data, tmpBuf.size, NULL));
|
MAC_64(tmpBuf.data, tmpBuf.size, NULL));
|
||||||
streamEncode(tmpBuf.data, tmpBuf.size, checksum);
|
streamEncode(tmpBuf.data, tmpBuf.size, checksum);
|
||||||
|
|
||||||
memcpy( out+KEY_CHECKSUM_BYTES, tmpBuf.data, tmpBuf.size );
|
|
||||||
|
|
||||||
// first N bytes contain HMAC derived checksum..
|
// first N bytes contain HMAC derived checksum..
|
||||||
for(int i=1; i<=KEY_CHECKSUM_BYTES; ++i)
|
for(int i=1; i<=KEY_CHECKSUM_BYTES; ++i)
|
||||||
{
|
{
|
||||||
out[KEY_CHECKSUM_BYTES-i] = checksum & 0xff;
|
out[KEY_CHECKSUM_BYTES-i] = checksum & 0xff;
|
||||||
checksum >>= 8;
|
checksum >>= 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy( out+KEY_CHECKSUM_BYTES, tmpBuf.data, tmpBuf.size );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CipherV1::encodeAsString(const CipherKey &key)
|
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
|
// combine ivec and seed with HMAC
|
||||||
Lock l(_hmacMutex);
|
Lock l(_hmacMutex);
|
||||||
_hmac->reset();
|
_hmac->init();
|
||||||
_hmac->update(ivec, _ivLength);
|
_hmac->update(ivec, _ivLength);
|
||||||
_hmac->update(md.data(), 8);
|
_hmac->update(md.data(), 8);
|
||||||
_hmac->write(md.data());
|
_hmac->write(md.data());
|
||||||
|
@ -102,6 +102,9 @@ class CipherV1
|
|||||||
Range blockSize;
|
Range blockSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void init(bool threaded);
|
||||||
|
static void shutdown(bool threaded);
|
||||||
|
|
||||||
// Returns a list of supported algorithms.
|
// Returns a list of supported algorithms.
|
||||||
static std::list<CipherAlgorithm> GetAlgorithmList();
|
static std::list<CipherAlgorithm> GetAlgorithmList();
|
||||||
static shared_ptr<CipherV1> New(const std::string &name, int keyLen = -1);
|
static shared_ptr<CipherV1> New(const std::string &name, int keyLen = -1);
|
||||||
@ -114,9 +117,12 @@ class CipherV1
|
|||||||
const byte *salt, int saltLen,
|
const byte *salt, int saltLen,
|
||||||
CipherKey *out, long desiredPDFTimeMicroseconds);
|
CipherKey *out, long desiredPDFTimeMicroseconds);
|
||||||
|
|
||||||
CipherV1(const Interface &iface, const Interface &realIface, int keyLength);
|
CipherV1();
|
||||||
~CipherV1();
|
~CipherV1();
|
||||||
|
|
||||||
|
bool initCiphers(const Interface &iface,
|
||||||
|
const Interface &realIface, int keyLength);
|
||||||
|
|
||||||
// returns the real interface, not the one we're emulating (if any)..
|
// returns the real interface, not the one we're emulating (if any)..
|
||||||
Interface interface() const;
|
Interface interface() const;
|
||||||
|
|
||||||
|
263
cipher/CommonCrypto.cpp
Normal file
263
cipher/CommonCrypto.cpp
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Author: Valient Gough <vgough@pobox.com>
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cipher/CommonCrypto.h"
|
||||||
|
|
||||||
|
#include <glog/logging.h>
|
||||||
|
|
||||||
|
#include <CommonCrypto/CommonCryptor.h>
|
||||||
|
#include <CommonCrypto/CommonDigest.h>
|
||||||
|
#include <CommonCrypto/CommonHMAC.h>
|
||||||
|
#include <CommonCrypto/CommonKeyDerivation.h>
|
||||||
|
|
||||||
|
#include "base/config.h"
|
||||||
|
#include "cipher/BlockCipher.h"
|
||||||
|
#include "cipher/MAC.h"
|
||||||
|
#include "cipher/PBKDF.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_SEC_RANDOM_H
|
||||||
|
#include <Security/SecRandom.h>
|
||||||
|
#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
|
35
cipher/CommonCrypto.h
Normal file
35
cipher/CommonCrypto.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Author: Valient Gough <vgough@pobox.com>
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _COMMONCRYPTO_incl_
|
||||||
|
#define _COMMONCRYPTO_incl_
|
||||||
|
|
||||||
|
namespace encfs {
|
||||||
|
|
||||||
|
struct CommonCrypto {
|
||||||
|
static void registerCiphers();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace encfs
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -35,7 +35,8 @@ class MAC
|
|||||||
|
|
||||||
virtual bool setKey(const CipherKey &key) =0;
|
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 update(const byte *in, int length) =0;
|
||||||
virtual bool write(byte *out) =0;
|
virtual bool write(byte *out) =0;
|
||||||
};
|
};
|
||||||
|
@ -44,7 +44,7 @@ TEST(HMacSha1Test, MAC) {
|
|||||||
for (int i = 0; i < 20; ++i)
|
for (int i = 0; i < 20; ++i)
|
||||||
key.data()[i] = 0x0b;
|
key.data()[i] = 0x0b;
|
||||||
hmac->setKey(key);
|
hmac->setKey(key);
|
||||||
hmac->reset();
|
hmac->init();
|
||||||
hmac->update((byte *)"Hi There", 8);
|
hmac->update((byte *)"Hi There", 8);
|
||||||
hmac->write(out);
|
hmac->write(out);
|
||||||
ASSERT_EQ("b617318655057264e28bc0b6fb378c8ef146be00", stringToHex(out, 20));
|
ASSERT_EQ("b617318655057264e28bc0b6fb378c8ef146be00", stringToHex(out, 20));
|
||||||
@ -52,7 +52,7 @@ TEST(HMacSha1Test, MAC) {
|
|||||||
// Test case 2
|
// Test case 2
|
||||||
key = CipherKey((const byte *)"Jefe", 4);
|
key = CipherKey((const byte *)"Jefe", 4);
|
||||||
hmac->setKey(key);
|
hmac->setKey(key);
|
||||||
hmac->reset();
|
hmac->init();
|
||||||
hmac->update((byte *)"what do ya want for nothing?", 28);
|
hmac->update((byte *)"what do ya want for nothing?", 28);
|
||||||
hmac->write(out);
|
hmac->write(out);
|
||||||
ASSERT_EQ("effcdf6ae5eb2fa2d27416d5f184df9c259a7c79", stringToHex(out, 20));
|
ASSERT_EQ("effcdf6ae5eb2fa2d27416d5f184df9c259a7c79", stringToHex(out, 20));
|
||||||
@ -62,7 +62,7 @@ TEST(HMacSha1Test, MAC) {
|
|||||||
for (int i = 0; i < 20; ++i)
|
for (int i = 0; i < 20; ++i)
|
||||||
key.data()[i] = 0xaa;
|
key.data()[i] = 0xaa;
|
||||||
hmac->setKey(key);
|
hmac->setKey(key);
|
||||||
hmac->reset();
|
hmac->init();
|
||||||
{
|
{
|
||||||
byte data[50];
|
byte data[50];
|
||||||
memset(data, 0xdd, 50);
|
memset(data, 0xdd, 50);
|
||||||
@ -75,7 +75,7 @@ TEST(HMacSha1Test, MAC) {
|
|||||||
key = CipherKey(80);
|
key = CipherKey(80);
|
||||||
memset(key.data(), 0xaa, 80);
|
memset(key.data(), 0xaa, 80);
|
||||||
hmac->setKey(key);
|
hmac->setKey(key);
|
||||||
hmac->reset();
|
hmac->init();
|
||||||
hmac->update((byte *)"Test Using Larger Than Block-Size Key and Larger "
|
hmac->update((byte *)"Test Using Larger Than Block-Size Key and Larger "
|
||||||
"Than One Block-Size Data", 73);
|
"Than One Block-Size Data", 73);
|
||||||
hmac->write(out);
|
hmac->write(out);
|
||||||
|
@ -42,105 +42,69 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
using namespace std;
|
#ifdef WITH_OPENSSL
|
||||||
|
|
||||||
# include <openssl/crypto.h>
|
# include <openssl/crypto.h>
|
||||||
# include <openssl/buffer.h>
|
# include <openssl/buffer.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace encfs {
|
namespace encfs {
|
||||||
|
|
||||||
static BUF_MEM *allocBlock( int size )
|
#ifdef WITH_OPENSSL
|
||||||
|
static byte *allocBlock( int size )
|
||||||
{
|
{
|
||||||
BUF_MEM *block = BUF_MEM_new( );
|
byte *block = (byte *)OPENSSL_malloc(size);
|
||||||
BUF_MEM_grow( block, size );
|
|
||||||
VALGRIND_MAKE_MEM_NOACCESS( block->data, block->max );
|
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void freeBlock( BUF_MEM *block )
|
static void freeBlock( byte *block, int size )
|
||||||
{
|
{
|
||||||
VALGRIND_MAKE_MEM_UNDEFINED( block->data, block->max );
|
OPENSSL_cleanse(block, size);
|
||||||
BUF_MEM_free( block );
|
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;
|
unsigned char cleanse_ctr = 0;
|
||||||
|
static void freeBlock(byte *data, int len) {
|
||||||
typedef std::map<int, std::list<BUF_MEM* > > FreeBlockMap;
|
byte *p = data;
|
||||||
static FreeBlockMap gFreeBlocks;
|
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)
|
void MemBlock::allocate(int size)
|
||||||
{
|
{
|
||||||
rAssert(size > 0);
|
rAssert(size > 0);
|
||||||
pthread_mutex_lock( &gMPoolMutex );
|
this->data = allocBlock(size);
|
||||||
|
this->size = size;
|
||||||
list<BUF_MEM*> &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<byte *>(mem->data);
|
|
||||||
VALGRIND_MAKE_MEM_UNDEFINED( data, size );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MemBlock::~MemBlock()
|
MemBlock::~MemBlock()
|
||||||
{
|
{
|
||||||
BUF_MEM *block = (BUF_MEM*)internalData;
|
freeBlock(data, size);
|
||||||
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<BUF_MEM*>::const_iterator bIt = it->second.begin();
|
|
||||||
bIt != it->second.end(); bIt++)
|
|
||||||
{
|
|
||||||
freeBlock( *bIt );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gFreeBlocks.clear();
|
|
||||||
|
|
||||||
pthread_mutex_unlock( &gMPoolMutex );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SecureMem::SecureMem(int len)
|
SecureMem::SecureMem(int len)
|
||||||
{
|
{
|
||||||
rAssert(len > 0);
|
rAssert(len > 0);
|
||||||
data = (byte *)OPENSSL_malloc(len);
|
data = allocBlock(len);
|
||||||
if (data)
|
if (data)
|
||||||
{
|
{
|
||||||
size = len;
|
size = len;
|
||||||
mlock(data, size);
|
mlock(data, size);
|
||||||
memset(data, '\0', size);
|
|
||||||
VALGRIND_MAKE_MEM_UNDEFINED( data, size );
|
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
size = 0;
|
size = 0;
|
||||||
@ -151,17 +115,18 @@ SecureMem::~SecureMem()
|
|||||||
{
|
{
|
||||||
if (size)
|
if (size)
|
||||||
{
|
{
|
||||||
memset(data, '\0', size);
|
freeBlock(data, size);
|
||||||
OPENSSL_cleanse(data, size);
|
|
||||||
|
|
||||||
munlock(data, size);
|
munlock(data, size);
|
||||||
OPENSSL_free(data);
|
|
||||||
VALGRIND_MAKE_MEM_NOACCESS( data, size );
|
|
||||||
|
|
||||||
data = NULL;
|
data = NULL;
|
||||||
size = 0;
|
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
|
} // namespace encfs
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ namespace encfs {
|
|||||||
struct MemBlock
|
struct MemBlock
|
||||||
{
|
{
|
||||||
byte *data;
|
byte *data;
|
||||||
void *internalData;
|
int size;
|
||||||
|
|
||||||
MemBlock();
|
MemBlock();
|
||||||
~MemBlock();
|
~MemBlock();
|
||||||
@ -48,15 +48,10 @@ struct MemBlock
|
|||||||
};
|
};
|
||||||
|
|
||||||
inline MemBlock::MemBlock()
|
inline MemBlock::MemBlock()
|
||||||
: data(0), internalData(0)
|
: data(0), size(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MemoryPool
|
|
||||||
{
|
|
||||||
void destroyAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
class SecureMem
|
class SecureMem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -67,6 +62,8 @@ class SecureMem
|
|||||||
~SecureMem();
|
~SecureMem();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool operator == (const SecureMem &a, const SecureMem &b);
|
||||||
|
|
||||||
} // namespace encfs
|
} // namespace encfs
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -46,6 +46,13 @@ class StreamCipher
|
|||||||
std::string toString() const {
|
std::string toString() const {
|
||||||
return cipher + "/" + mode;
|
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();
|
StreamCipher();
|
||||||
@ -53,9 +60,9 @@ class StreamCipher
|
|||||||
|
|
||||||
virtual bool setKey(const CipherKey& key) =0;
|
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;
|
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;
|
byte *out, int numBytes) =0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cipher/openssl.h"
|
#include "cipher/openssl.h"
|
||||||
|
#include "base/config.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
@ -28,6 +29,10 @@
|
|||||||
|
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||||
|
#include <valgrind/memcheck.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "base/config.h"
|
#include "base/config.h"
|
||||||
|
|
||||||
#define NO_DES
|
#define NO_DES
|
||||||
@ -54,8 +59,6 @@
|
|||||||
#include "cipher/PBKDF.h"
|
#include "cipher/PBKDF.h"
|
||||||
#include "cipher/StreamCipher.h"
|
#include "cipher/StreamCipher.h"
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace encfs {
|
namespace encfs {
|
||||||
|
|
||||||
const int MAX_KEYLENGTH = 64; // in bytes (256 bit)
|
const int MAX_KEYLENGTH = 64; // in bytes (256 bit)
|
||||||
@ -108,10 +111,18 @@ class OpenSSLCipher : public BlockCipher {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(key->data(), key->size());
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool pseudoRandomize(byte *out, int length) {
|
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 );
|
int result = RAND_pseudo_bytes( out, length );
|
||||||
if(result != 1)
|
if(result != 1)
|
||||||
{
|
{
|
||||||
@ -136,12 +147,27 @@ class OpenSSLCipher : public BlockCipher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual int blockSize() const {
|
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,
|
virtual bool encrypt(const byte *ivec, const byte *in,
|
||||||
byte *out, int size) {
|
byte *out, int size) {
|
||||||
int dstLen = 0, tmpLen = 0;
|
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_EncryptInit_ex( &enc, NULL, NULL, NULL, ivec);
|
||||||
EVP_EncryptUpdate( &enc, out, &dstLen, in, size);
|
EVP_EncryptUpdate( &enc, out, &dstLen, in, size);
|
||||||
EVP_EncryptFinal_ex( &enc, out+dstLen, &tmpLen );
|
EVP_EncryptFinal_ex( &enc, out+dstLen, &tmpLen );
|
||||||
@ -159,6 +185,17 @@ class OpenSSLCipher : public BlockCipher {
|
|||||||
virtual bool decrypt(const byte *ivec, const byte *in,
|
virtual bool decrypt(const byte *ivec, const byte *in,
|
||||||
byte *out, int size) {
|
byte *out, int size) {
|
||||||
int dstLen = 0, tmpLen = 0;
|
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_DecryptInit_ex( &dec, NULL, NULL, NULL, ivec);
|
||||||
EVP_DecryptUpdate( &dec, out, &dstLen, in, size );
|
EVP_DecryptUpdate( &dec, out, &dstLen, in, size );
|
||||||
EVP_DecryptFinal_ex( &dec, out+dstLen, &tmpLen );
|
EVP_DecryptFinal_ex( &dec, out+dstLen, &tmpLen );
|
||||||
@ -346,7 +383,7 @@ class Sha1HMac : public MAC {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void reset() {
|
virtual void init() {
|
||||||
HMAC_Init_ex(&ctx, 0, 0, 0, 0);
|
HMAC_Init_ex(&ctx, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,6 +401,9 @@ class Sha1HMac : public MAC {
|
|||||||
unsigned int outSize = 0;
|
unsigned int outSize = 0;
|
||||||
HMAC_Final(&ctx, (unsigned char *)out, &outSize);
|
HMAC_Final(&ctx, (unsigned char *)out, &outSize);
|
||||||
CHECK_EQ(outputSize(), outSize) << "Invalid HMAC output size";
|
CHECK_EQ(outputSize(), outSize) << "Invalid HMAC output size";
|
||||||
|
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||||
|
VALGRIND_MAKE_MEM_DEFINED(out, outSize);
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
|
|
||||||
|
#include <glog/logging.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "base/config.h"
|
||||||
#include "cipher/testing.h"
|
#include "cipher/testing.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_VALGRIND_MEMCHECK_H
|
||||||
|
#include <valgrind/memcheck.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace encfs {
|
namespace encfs {
|
||||||
|
|
||||||
static const char hexLut[] = "0123456789abcdef";
|
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) {
|
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;
|
bool odd = false;
|
||||||
unsigned int last = 0;
|
unsigned int last = 0;
|
||||||
while (len > 0 && *hex != '\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) {
|
int main(int argc, char **argv) {
|
||||||
|
google::InitGoogleLogging(argv[0]);
|
||||||
::testing::InitGoogleTest(&argc, argv);
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
return RUN_ALL_TESTS();
|
return RUN_ALL_TESTS();
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,7 @@
|
|||||||
#include "base/Interface.h"
|
#include "base/Interface.h"
|
||||||
#include "base/i18n.h"
|
#include "base/i18n.h"
|
||||||
|
|
||||||
#include "cipher/MemoryPool.h"
|
#include "cipher/CipherV1.h"
|
||||||
#include "cipher/openssl.h"
|
|
||||||
|
|
||||||
#include "fs/FileUtils.h"
|
#include "fs/FileUtils.h"
|
||||||
#include "fs/DirNode.h"
|
#include "fs/DirNode.h"
|
||||||
@ -61,9 +60,12 @@ inline static int MAX(int a, int b)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace gnu;
|
|
||||||
using namespace encfs;
|
using namespace encfs;
|
||||||
|
using gnu::autosprintf;
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
using std::string;
|
||||||
|
using std::ostringstream;
|
||||||
|
|
||||||
namespace encfs {
|
namespace encfs {
|
||||||
|
|
||||||
@ -580,7 +582,7 @@ int main(int argc, char *argv[])
|
|||||||
// encfs_oper.fsetattr_x
|
// encfs_oper.fsetattr_x
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
OpenSSL::init( encfsArgs->isThreaded );
|
CipherV1::init( encfsArgs->isThreaded );
|
||||||
|
|
||||||
// context is not a smart pointer because it will live for the life of
|
// context is not a smart pointer because it will live for the life of
|
||||||
// the filesystem.
|
// the filesystem.
|
||||||
@ -672,8 +674,7 @@ int main(int argc, char *argv[])
|
|||||||
rootInfo.reset();
|
rootInfo.reset();
|
||||||
ctx->setRoot( shared_ptr<DirNode>() );
|
ctx->setRoot( shared_ptr<DirNode>() );
|
||||||
|
|
||||||
MemoryPool::destroyAll();
|
CipherV1::shutdown( encfsArgs->isThreaded );
|
||||||
OpenSSL::shutdown( encfsArgs->isThreaded );
|
|
||||||
|
|
||||||
return returnCode;
|
return returnCode;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,16 @@ target_link_libraries (encfs-fs
|
|||||||
${PROTOBUF_LIBRARY}
|
${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).
|
# Unit tests are optional, depends on libgtest (Google's C++ test framework).
|
||||||
if (GTEST_FOUND)
|
if (GTEST_FOUND)
|
||||||
link_directories (${PROJECT_BINARY_DIR}/base)
|
link_directories (${PROJECT_BINARY_DIR}/base)
|
||||||
|
@ -289,7 +289,6 @@ ssize_t CipherFileIO::readOneBlock( const IORequest &req ) const
|
|||||||
IORequest tmpReq = req;
|
IORequest tmpReq = req;
|
||||||
|
|
||||||
MemBlock mb;
|
MemBlock mb;
|
||||||
if (headerLen != 0)
|
|
||||||
tmpReq.offset += headerLen;
|
tmpReq.offset += headerLen;
|
||||||
|
|
||||||
int maxReadSize = req.dataLen;
|
int maxReadSize = req.dataLen;
|
||||||
|
@ -84,8 +84,6 @@ private:
|
|||||||
|
|
||||||
// if haveHeader is true, then we have a transparent file header which
|
// if haveHeader is true, then we have a transparent file header which
|
||||||
int headerLen;
|
int headerLen;
|
||||||
// Use block only encryption, no stream encryption.
|
|
||||||
bool blockOnlyMode;
|
|
||||||
|
|
||||||
bool perFileIV;
|
bool perFileIV;
|
||||||
bool externalIVChaining;
|
bool externalIVChaining;
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "base/Mutex.h"
|
#include "base/Mutex.h"
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#ifdef HAVE_TR1_UNORDERED_MAP
|
#ifdef HAVE_TR1_UNORDERED_MAP
|
||||||
#include <tr1/unordered_map>
|
#include <tr1/unordered_map>
|
||||||
|
@ -44,7 +44,8 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
using namespace std;
|
using std::list;
|
||||||
|
using std::string;
|
||||||
|
|
||||||
namespace encfs {
|
namespace encfs {
|
||||||
|
|
||||||
|
@ -75,6 +75,11 @@ struct FSConfig
|
|||||||
bool reverseEncryption; // reverse encryption operation
|
bool reverseEncryption; // reverse encryption operation
|
||||||
|
|
||||||
bool idleTracking; // turn on idle monitoring of filesystem
|
bool idleTracking; // turn on idle monitoring of filesystem
|
||||||
|
|
||||||
|
FSConfig()
|
||||||
|
: forceDecode(false),
|
||||||
|
reverseEncryption(false),
|
||||||
|
idleTracking(false) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef shared_ptr<FSConfig> FSConfigPtr;
|
typedef shared_ptr<FSConfig> FSConfigPtr;
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
|
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
|
|
||||||
using namespace std;
|
using std::string;
|
||||||
|
|
||||||
namespace encfs {
|
namespace encfs {
|
||||||
|
|
||||||
|
@ -66,8 +66,12 @@
|
|||||||
#include <google/protobuf/text_format.h>
|
#include <google/protobuf/text_format.h>
|
||||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||||
|
|
||||||
using namespace std;
|
using gnu::autosprintf;
|
||||||
using namespace gnu;
|
using std::cout;
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
using std::map;
|
||||||
|
using std::string;
|
||||||
|
|
||||||
namespace encfs {
|
namespace encfs {
|
||||||
|
|
||||||
@ -1186,6 +1190,11 @@ void showFSInfo( const EncfsConfig &config )
|
|||||||
cout << "\n";
|
cout << "\n";
|
||||||
} else
|
} 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..
|
// check if we support the filename encoding interface..
|
||||||
shared_ptr<NameIO> nameCoder = NameIO::New( config.naming(), cipher );
|
shared_ptr<NameIO> nameCoder = NameIO::New( config.naming(), cipher );
|
||||||
if(!nameCoder)
|
if(!nameCoder)
|
||||||
|
@ -30,8 +30,6 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace encfs {
|
namespace encfs {
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -34,7 +34,11 @@
|
|||||||
#include "fs/StreamNameIO.h"
|
#include "fs/StreamNameIO.h"
|
||||||
#include "fs/NullNameIO.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 {
|
namespace encfs {
|
||||||
|
|
||||||
|
@ -35,8 +35,6 @@
|
|||||||
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace encfs {
|
namespace encfs {
|
||||||
|
|
||||||
static Interface RawFileIO_iface = makeInterface("FileIO/Raw", 1, 0, 0);
|
static Interface RawFileIO_iface = makeInterface("FileIO/Raw", 1, 0, 0);
|
||||||
|
@ -28,8 +28,6 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace encfs {
|
namespace encfs {
|
||||||
|
|
||||||
static shared_ptr<NameIO> NewStreamNameIO( const Interface &iface,
|
static shared_ptr<NameIO> NewStreamNameIO( const Interface &iface,
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
#include "base/config.h"
|
#include "base/config.h"
|
||||||
#include "base/Interface.h"
|
#include "base/Interface.h"
|
||||||
#include "base/Error.h"
|
#include "base/Error.h"
|
||||||
#include "cipher/Cipher.h"
|
#include "cipher/CipherV1.h"
|
||||||
#include "cipher/MemoryPool.h"
|
#include "cipher/MemoryPool.h"
|
||||||
#include "fs/DirNode.h"
|
#include "fs/DirNode.h"
|
||||||
#include "fs/FileUtils.h"
|
#include "fs/FileUtils.h"
|
||||||
@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
#include <google/protobuf/text_format.h>
|
#include <google/protobuf/text_format.h>
|
||||||
|
|
||||||
#if HAVE_TR1_UNORDERED_SET
|
#ifdef HAVE_TR1_UNORDERED_SET
|
||||||
#include <tr1/unordered_set>
|
#include <tr1/unordered_set>
|
||||||
using std::tr1::unordered_set;
|
using std::tr1::unordered_set;
|
||||||
#else
|
#else
|
||||||
@ -54,15 +54,17 @@ using std::tr1::unordered_set;
|
|||||||
using std::unordered_set;
|
using std::unordered_set;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace std;
|
using std::cerr;
|
||||||
|
using std::string;
|
||||||
|
using namespace encfs;
|
||||||
|
|
||||||
namespace encfs {
|
namespace encfs {
|
||||||
|
|
||||||
const int FSBlockSize = 256;
|
const int FSBlockSize = 256;
|
||||||
|
|
||||||
static
|
static
|
||||||
int checkErrorPropogation( const shared_ptr<Cipher> &cipher,
|
int checkErrorPropogation( const shared_ptr<CipherV1> &cipher,
|
||||||
int size, int byteToChange, const CipherKey &key )
|
int size, int byteToChange )
|
||||||
{
|
{
|
||||||
MemBlock orig;
|
MemBlock orig;
|
||||||
orig.allocate(size);
|
orig.allocate(size);
|
||||||
@ -77,9 +79,9 @@ int checkErrorPropogation( const shared_ptr<Cipher> &cipher,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(size != FSBlockSize)
|
if(size != FSBlockSize)
|
||||||
cipher->streamEncode( data.data, size, 0, key );
|
cipher->streamEncode( data.data, size, 0 );
|
||||||
else
|
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
|
// intoduce an error in the encoded data, so we can check error propogation
|
||||||
if(byteToChange >= 0 && byteToChange < size)
|
if(byteToChange >= 0 && byteToChange < size)
|
||||||
@ -92,9 +94,9 @@ int checkErrorPropogation( const shared_ptr<Cipher> &cipher,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(size != FSBlockSize)
|
if(size != FSBlockSize)
|
||||||
cipher->streamDecode( data.data, size, 0, key );
|
cipher->streamDecode( data.data, size, 0 );
|
||||||
else
|
else
|
||||||
cipher->blockDecode( data.data, size, 0, key );
|
cipher->blockDecode( data.data, size, 0 );
|
||||||
|
|
||||||
int numByteErrors = 0;
|
int numByteErrors = 0;
|
||||||
for(int i=0; i<size; ++i)
|
for(int i=0; i<size; ++i)
|
||||||
@ -191,7 +193,7 @@ bool testNameCoding( DirNode &dirNode, bool verbose,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
|
bool runTests(const shared_ptr<CipherV1> &cipher, bool verbose)
|
||||||
{
|
{
|
||||||
// create a random key
|
// create a random key
|
||||||
if(verbose)
|
if(verbose)
|
||||||
@ -205,16 +207,17 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
|
|||||||
int encodedKeySize = cipher->encodedKeySize();
|
int encodedKeySize = cipher->encodedKeySize();
|
||||||
unsigned char *keyBuf = new unsigned char [ encodedKeySize ];
|
unsigned char *keyBuf = new unsigned char [ encodedKeySize ];
|
||||||
|
|
||||||
cipher->writeKey( key, keyBuf, encodingKey );
|
cipher->setKey(encodingKey);
|
||||||
CipherKey key2 = cipher->readKey( keyBuf, encodingKey );
|
cipher->writeKey( key, keyBuf );
|
||||||
if(!key2)
|
CipherKey key2 = cipher->readKey( keyBuf, true );
|
||||||
|
if(!key2.valid())
|
||||||
{
|
{
|
||||||
if(verbose)
|
if(verbose)
|
||||||
cerr << " FAILED (decode error)\n";
|
cerr << " FAILED (decode error)\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cipher->compareKey( key, key2 ))
|
if(key == key2)
|
||||||
{
|
{
|
||||||
if(verbose)
|
if(verbose)
|
||||||
cerr << " OK\n";
|
cerr << " OK\n";
|
||||||
@ -233,7 +236,8 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
|
|||||||
int encodedKeySize = cipher->encodedKeySize();
|
int encodedKeySize = cipher->encodedKeySize();
|
||||||
unsigned char *keyBuf = new unsigned char [ encodedKeySize ];
|
unsigned char *keyBuf = new unsigned char [ encodedKeySize ];
|
||||||
|
|
||||||
cipher->writeKey( key, keyBuf, encodingKey );
|
cipher->setKey(encodingKey);
|
||||||
|
cipher->writeKey( key, keyBuf );
|
||||||
|
|
||||||
// store in config struct..
|
// store in config struct..
|
||||||
EncfsConfig cfg;
|
EncfsConfig cfg;
|
||||||
@ -257,16 +261,15 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
|
|||||||
rAssert( cfg.block_size() == cfg2.block_size() );
|
rAssert( cfg.block_size() == cfg2.block_size() );
|
||||||
|
|
||||||
// try decoding key..
|
// try decoding key..
|
||||||
|
CipherKey key2 = cipher->readKey( (unsigned char *)cfg2.key().ciphertext().data(), true );
|
||||||
CipherKey key2 = cipher->readKey( (unsigned char *)cfg2.key().ciphertext().data(), encodingKey );
|
if(!key2.valid())
|
||||||
if(!key2)
|
|
||||||
{
|
{
|
||||||
if(verbose)
|
if(verbose)
|
||||||
cerr << " FAILED (decode error)\n";
|
cerr << " FAILED (decode error)\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cipher->compareKey( key, key2 ))
|
if(key == key2)
|
||||||
{
|
{
|
||||||
if(verbose)
|
if(verbose)
|
||||||
cerr << " OK\n";
|
cerr << " OK\n";
|
||||||
@ -285,15 +288,15 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
|
|||||||
fsCfg->config->set_block_size(FSBlockSize);
|
fsCfg->config->set_block_size(FSBlockSize);
|
||||||
fsCfg->opts.reset(new EncFS_Opts);
|
fsCfg->opts.reset(new EncFS_Opts);
|
||||||
|
|
||||||
|
cipher->setKey(key);
|
||||||
if(verbose)
|
if(verbose)
|
||||||
cerr << "Testing name encode/decode (stream coding w/ IV chaining)\n";
|
cerr << "Testing name encode/decode (stream coding w/ IV chaining)\n";
|
||||||
if (cipher->hasStreamMode())
|
|
||||||
{
|
{
|
||||||
fsCfg->opts->idleTracking = false;
|
fsCfg->opts->idleTracking = false;
|
||||||
fsCfg->config->set_unique_iv(false);
|
fsCfg->config->set_unique_iv(false);
|
||||||
|
|
||||||
fsCfg->nameCoding.reset( new StreamNameIO(
|
fsCfg->nameCoding.reset( new StreamNameIO(
|
||||||
StreamNameIO::CurrentInterface(), cipher, key ) );
|
StreamNameIO::CurrentInterface(), cipher) );
|
||||||
fsCfg->nameCoding->setChainedNameIV( true );
|
fsCfg->nameCoding->setChainedNameIV( true );
|
||||||
|
|
||||||
DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );
|
DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );
|
||||||
@ -308,7 +311,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
|
|||||||
fsCfg->opts->idleTracking = false;
|
fsCfg->opts->idleTracking = false;
|
||||||
fsCfg->config->set_unique_iv(false);
|
fsCfg->config->set_unique_iv(false);
|
||||||
fsCfg->nameCoding.reset( new BlockNameIO(
|
fsCfg->nameCoding.reset( new BlockNameIO(
|
||||||
BlockNameIO::CurrentInterface(), cipher, key ) );
|
BlockNameIO::CurrentInterface(), cipher) );
|
||||||
fsCfg->nameCoding->setChainedNameIV( true );
|
fsCfg->nameCoding->setChainedNameIV( true );
|
||||||
|
|
||||||
DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );
|
DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );
|
||||||
@ -323,7 +326,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
|
|||||||
fsCfg->opts->idleTracking = false;
|
fsCfg->opts->idleTracking = false;
|
||||||
fsCfg->config->set_unique_iv(false);
|
fsCfg->config->set_unique_iv(false);
|
||||||
fsCfg->nameCoding.reset( new BlockNameIO(
|
fsCfg->nameCoding.reset( new BlockNameIO(
|
||||||
BlockNameIO::CurrentInterface(), cipher, key, true ) );
|
BlockNameIO::CurrentInterface(), cipher) );
|
||||||
fsCfg->nameCoding->setChainedNameIV( true );
|
fsCfg->nameCoding->setChainedNameIV( true );
|
||||||
|
|
||||||
DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );
|
DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );
|
||||||
@ -334,12 +337,11 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
|
|||||||
|
|
||||||
if(!verbose)
|
if(!verbose)
|
||||||
{
|
{
|
||||||
if (cipher->hasStreamMode())
|
|
||||||
{
|
{
|
||||||
// test stream mode, this time without IV chaining
|
// test stream mode, this time without IV chaining
|
||||||
fsCfg->nameCoding =
|
fsCfg->nameCoding =
|
||||||
shared_ptr<NameIO>( new StreamNameIO(
|
shared_ptr<NameIO>( new StreamNameIO(
|
||||||
StreamNameIO::CurrentInterface(), cipher, key ) );
|
StreamNameIO::CurrentInterface(), cipher) );
|
||||||
fsCfg->nameCoding->setChainedNameIV( false );
|
fsCfg->nameCoding->setChainedNameIV( false );
|
||||||
|
|
||||||
DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );
|
DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );
|
||||||
@ -351,7 +353,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
|
|||||||
{
|
{
|
||||||
// test block mode, this time without IV chaining
|
// test block mode, this time without IV chaining
|
||||||
fsCfg->nameCoding = shared_ptr<NameIO>( new BlockNameIO(
|
fsCfg->nameCoding = shared_ptr<NameIO>( new BlockNameIO(
|
||||||
BlockNameIO::CurrentInterface(), cipher, key ) );
|
BlockNameIO::CurrentInterface(), cipher) );
|
||||||
fsCfg->nameCoding->setChainedNameIV( false );
|
fsCfg->nameCoding->setChainedNameIV( false );
|
||||||
|
|
||||||
DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );
|
DirNode dirNode( NULL, TEST_ROOTDIR, fsCfg );
|
||||||
@ -365,7 +367,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
|
|||||||
cerr << "Testing block encode/decode on full block - ";
|
cerr << "Testing block encode/decode on full block - ";
|
||||||
{
|
{
|
||||||
int numErrors = checkErrorPropogation( cipher,
|
int numErrors = checkErrorPropogation( cipher,
|
||||||
FSBlockSize, -1, key );
|
FSBlockSize, -1 );
|
||||||
if(numErrors)
|
if(numErrors)
|
||||||
{
|
{
|
||||||
if(verbose)
|
if(verbose)
|
||||||
@ -379,10 +381,9 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
|
|||||||
}
|
}
|
||||||
if(verbose)
|
if(verbose)
|
||||||
cerr << "Testing block encode/decode on partial block - ";
|
cerr << "Testing block encode/decode on partial block - ";
|
||||||
if (cipher->hasStreamMode())
|
|
||||||
{
|
{
|
||||||
int numErrors = checkErrorPropogation( cipher,
|
int numErrors = checkErrorPropogation( cipher,
|
||||||
FSBlockSize-1, -1, key );
|
FSBlockSize-1, -1 );
|
||||||
if(numErrors)
|
if(numErrors)
|
||||||
{
|
{
|
||||||
if(verbose)
|
if(verbose)
|
||||||
@ -397,7 +398,6 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
|
|||||||
|
|
||||||
if(verbose)
|
if(verbose)
|
||||||
cerr << "Checking error propogation in partial block:\n";
|
cerr << "Checking error propogation in partial block:\n";
|
||||||
if (cipher->hasStreamMode())
|
|
||||||
{
|
{
|
||||||
int minChanges = FSBlockSize-1;
|
int minChanges = FSBlockSize-1;
|
||||||
int maxChanges = 0;
|
int maxChanges = 0;
|
||||||
@ -406,7 +406,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
|
|||||||
for(int i=0; i<FSBlockSize-1; ++i)
|
for(int i=0; i<FSBlockSize-1; ++i)
|
||||||
{
|
{
|
||||||
int numErrors = checkErrorPropogation( cipher,
|
int numErrors = checkErrorPropogation( cipher,
|
||||||
FSBlockSize-1, i, key );
|
FSBlockSize-1, i );
|
||||||
|
|
||||||
if(numErrors < minChanges)
|
if(numErrors < minChanges)
|
||||||
{
|
{
|
||||||
@ -438,7 +438,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
|
|||||||
for(int i=0; i<FSBlockSize; ++i)
|
for(int i=0; i<FSBlockSize; ++i)
|
||||||
{
|
{
|
||||||
int numErrors = checkErrorPropogation( cipher,
|
int numErrors = checkErrorPropogation( cipher,
|
||||||
FSBlockSize, i, key );
|
FSBlockSize, i );
|
||||||
|
|
||||||
if(numErrors < minChanges)
|
if(numErrors < minChanges)
|
||||||
{
|
{
|
||||||
@ -464,6 +464,7 @@ bool runTests(const shared_ptr<Cipher> &cipher, bool verbose)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace encfs
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -488,9 +489,9 @@ int main(int argc, char *argv[])
|
|||||||
srand( time(0) );
|
srand( time(0) );
|
||||||
|
|
||||||
// get a list of the available algorithms
|
// get a list of the available algorithms
|
||||||
std::list<Cipher::CipherAlgorithm> algorithms =
|
std::list<CipherV1::CipherAlgorithm> algorithms =
|
||||||
Cipher::GetAlgorithmList();
|
CipherV1::GetAlgorithmList();
|
||||||
std::list<Cipher::CipherAlgorithm>::const_iterator it;
|
std::list<CipherV1::CipherAlgorithm>::const_iterator it;
|
||||||
cerr << "Supported Crypto interfaces:\n";
|
cerr << "Supported Crypto interfaces:\n";
|
||||||
for(it = algorithms.begin(); it != algorithms.end(); ++it)
|
for(it = algorithms.begin(); it != algorithms.end(); ++it)
|
||||||
{
|
{
|
||||||
@ -515,7 +516,7 @@ int main(int argc, char *argv[])
|
|||||||
cerr << it->name << ", key length " << keySize
|
cerr << it->name << ", key length " << keySize
|
||||||
<< ", block size " << blockSize << ": ";
|
<< ", block size " << blockSize << ": ";
|
||||||
|
|
||||||
shared_ptr<Cipher> cipher = Cipher::New( it->name, keySize );
|
shared_ptr<CipherV1> cipher = CipherV1::New( it->name, keySize );
|
||||||
if(!cipher)
|
if(!cipher)
|
||||||
{
|
{
|
||||||
cerr << "FAILED TO CREATE\n";
|
cerr << "FAILED TO CREATE\n";
|
||||||
@ -536,7 +537,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
// run one test with verbose output too..
|
// run one test with verbose output too..
|
||||||
shared_ptr<Cipher> cipher = Cipher::New("AES", 192);
|
shared_ptr<CipherV1> cipher = CipherV1::New("AES", 192);
|
||||||
if(!cipher)
|
if(!cipher)
|
||||||
{
|
{
|
||||||
cerr << "\nNo AES cipher found, skipping verbose test.\n";
|
cerr << "\nNo AES cipher found, skipping verbose test.\n";
|
||||||
@ -549,10 +550,6 @@ int main(int argc, char *argv[])
|
|||||||
runTests( cipher, true );
|
runTests( cipher, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryPool::destroyAll();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace encfs
|
|
||||||
|
|
13
fs/encfs.cpp
13
fs/encfs.cpp
@ -43,11 +43,14 @@
|
|||||||
|
|
||||||
#ifdef HAVE_TR1_TUPLE
|
#ifdef HAVE_TR1_TUPLE
|
||||||
#include <tr1/tuple>
|
#include <tr1/tuple>
|
||||||
using namespace std;
|
using std::tr1::get;
|
||||||
using namespace std::tr1;
|
using std::tr1::make_tuple;
|
||||||
|
using std::tr1::tuple;
|
||||||
#else
|
#else
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
using namespace std;
|
using std::get;
|
||||||
|
using std::make_tuple;
|
||||||
|
using std::tuple;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "base/config.h"
|
#include "base/config.h"
|
||||||
@ -61,6 +64,10 @@ using namespace std;
|
|||||||
|
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
|
|
||||||
|
using std::map;
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
namespace encfs {
|
namespace encfs {
|
||||||
|
|
||||||
#ifndef MIN
|
#ifndef MIN
|
||||||
|
@ -76,6 +76,38 @@ TEST(IOTest, MacIO) {
|
|||||||
runWithAllCiphers(testMacIO);
|
runWithAllCiphers(testMacIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testBasicCipherIO(FSConfigPtr& cfg) {
|
||||||
|
shared_ptr<MemFileIO> base(new MemFileIO(0));
|
||||||
|
shared_ptr<CipherFileIO> 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) {
|
void testCipherIO(FSConfigPtr& cfg) {
|
||||||
shared_ptr<MemFileIO> base(new MemFileIO(0));
|
shared_ptr<MemFileIO> base(new MemFileIO(0));
|
||||||
shared_ptr<CipherFileIO> test(new CipherFileIO(base, cfg));
|
shared_ptr<CipherFileIO> test(new CipherFileIO(base, cfg));
|
||||||
|
@ -36,7 +36,8 @@
|
|||||||
#include "fs/MACFileIO.h"
|
#include "fs/MACFileIO.h"
|
||||||
#include "fs/MemFileIO.h"
|
#include "fs/MemFileIO.h"
|
||||||
|
|
||||||
using namespace std;
|
using std::list;
|
||||||
|
using std::string;
|
||||||
|
|
||||||
namespace encfs {
|
namespace encfs {
|
||||||
|
|
||||||
@ -92,8 +93,13 @@ void truncate(FileIO* a, FileIO* b, int len) {
|
|||||||
void writeRandom(FSConfigPtr& cfg, FileIO* a, FileIO* b, int offset, int len) {
|
void writeRandom(FSConfigPtr& cfg, FileIO* a, FileIO* b, int offset, int len) {
|
||||||
SCOPED_TRACE(testing::Message() << "Write random " << offset << ", " << len);
|
SCOPED_TRACE(testing::Message() << "Write random " << offset << ", " << len);
|
||||||
|
|
||||||
if (a->getSize() < offset + len)
|
if (a->getSize() < offset + len) {
|
||||||
a->truncate(offset + len);
|
a->truncate(offset + len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b->getSize() < offset + len) {
|
||||||
|
b->truncate(offset + len);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned char *buf = new unsigned char[len];
|
unsigned char *buf = new unsigned char[len];
|
||||||
ASSERT_TRUE(cfg->cipher->pseudoRandomize(buf, len));
|
ASSERT_TRUE(cfg->cipher->pseudoRandomize(buf, len));
|
||||||
@ -106,13 +112,27 @@ void writeRandom(FSConfigPtr& cfg, FileIO* a, FileIO* b, int offset, int len) {
|
|||||||
req.offset = offset;
|
req.offset = offset;
|
||||||
ASSERT_TRUE(a->write(req));
|
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);
|
memcpy(req.data, buf, len);
|
||||||
req.offset = offset;
|
req.offset = offset;
|
||||||
|
req.dataLen = len;
|
||||||
ASSERT_TRUE(b->write(req));
|
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);
|
compare(a, b, offset, len);
|
||||||
|
|
||||||
delete[] buf;
|
delete[] buf;
|
||||||
|
delete[] req.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void compare(FileIO* a, FileIO* b, int offset, int len) {
|
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);
|
ASSERT_EQ(size1, size2);
|
||||||
for(int i = 0; i < len; i++) {
|
for(int i = 0; i < len; i++) {
|
||||||
bool match = (buf1[i] == buf2[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) {
|
if(!match) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -148,15 +169,13 @@ void compare(FileIO* a, FileIO* b, int offset, int len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void comparisonTest(FSConfigPtr& cfg, FileIO* a, FileIO* b) {
|
void comparisonTest(FSConfigPtr& cfg, FileIO* a, FileIO* b) {
|
||||||
const int size = 18*1024;
|
const int size = 2*1024;
|
||||||
writeRandom(cfg, a, b, 0, size);
|
writeRandom(cfg, a, b, 0, size);
|
||||||
if (testing::Test::HasFatalFailure()) return;
|
if (testing::Test::HasFatalFailure()) return;
|
||||||
compare(a, b, 0, size);
|
|
||||||
if (testing::Test::HasFatalFailure()) return;
|
|
||||||
|
|
||||||
for (int i = 0; i < 10000; i++) {
|
for (int i = 0; i < 10000; i++) {
|
||||||
SCOPED_TRACE(testing::Message() << "Test Loop " << i);
|
SCOPED_TRACE(testing::Message() << "Test Loop " << i);
|
||||||
int len = 128 + random() % 2048;
|
int len = 128 + random() % 512;
|
||||||
int offset = (len == a->getSize()) ? 0
|
int offset = (len == a->getSize()) ? 0
|
||||||
: random() % (a->getSize() - len);
|
: random() % (a->getSize() - len);
|
||||||
writeRandom(cfg, a, b, offset, len);
|
writeRandom(cfg, a, b, offset, len);
|
||||||
|
@ -4,7 +4,7 @@ file (GLOB CXX_FILES RELATIVE ${PROJECT_SOURCE_DIR} "*/*.cpp")
|
|||||||
|
|
||||||
set (GettextTranslate_GMO_BINARY true)
|
set (GettextTranslate_GMO_BINARY true)
|
||||||
|
|
||||||
include (GetTextTranslate)
|
include (GettextTranslate)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@ target_link_libraries (encfsctl
|
|||||||
encfs-cipher
|
encfs-cipher
|
||||||
encfs-base
|
encfs-base
|
||||||
${GLOG_LIBRARIES}
|
${GLOG_LIBRARIES}
|
||||||
${FUSE_LIBRARIES}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (POD2MAN)
|
if (POD2MAN)
|
||||||
|
@ -50,9 +50,14 @@
|
|||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace gnu;
|
|
||||||
using namespace encfs;
|
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 showInfo( int argc, char **argv );
|
||||||
static int showVersion( int argc, char **argv );
|
static int showVersion( int argc, char **argv );
|
||||||
|
@ -29,8 +29,6 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
void genKey( const shared_ptr<Cipher> &cipher )
|
void genKey( const shared_ptr<Cipher> &cipher )
|
||||||
{
|
{
|
||||||
CipherKey key = cipher->newRandomKey();
|
CipherKey key = cipher->newRandomKey();
|
||||||
|
Loading…
Reference in New Issue
Block a user