mirror of
https://github.com/vgough/encfs.git
synced 2024-11-21 23:43:26 +01:00
break out cipher primitives, add unit tests
git-svn-id: http://encfs.googlecode.com/svn/trunk@94 db9cf616-1c43-0410-9cb8-a902689de0d6
This commit is contained in:
parent
7799c88df6
commit
f00ef5c6d3
@ -11,8 +11,28 @@ option (BUILD_SHARED_LIBS "Build dynamic link libraries" OFF)
|
||||
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
|
||||
"${CMAKE_SOURCE_DIR}/CMakeModules/")
|
||||
|
||||
# Tweak compiler flags.
|
||||
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall")
|
||||
|
||||
include (CheckCXXCompilerFlag)
|
||||
check_cxx_compiler_flag (-std=c++11 HAVE_C11_FLAG)
|
||||
check_cxx_compiler_flag (-std=gnu++11 HAVE_GNU11_FLAG)
|
||||
|
||||
if (HAVE_GNU11_FLAG)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
|
||||
elseif (HAVE_C11_FLAG)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
endif (HAVE_GNU11_FLAG)
|
||||
|
||||
# Flume specific flags.
|
||||
find_package (FUSE REQUIRED)
|
||||
include_directories (${FUSE_INCLUDE_DIR})
|
||||
add_definitions (-D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26)
|
||||
if (APPLE)
|
||||
add_definitions (-D__FreeBSD__=10)
|
||||
endif (APPLE)
|
||||
|
||||
# Packaging config.
|
||||
set (CPACK_PACKAGE_NAME "Encfs")
|
||||
set (CPACK_PACKAGE_VERSION_MAJOR ${ENCFS_MAJOR})
|
||||
set (CPACK_PACKAGE_VERSION_MINOR ${ENCFS_MINOR})
|
||||
@ -23,6 +43,7 @@ set (CPACK_SOURCE_IGNORE_FILES
|
||||
"/build/")
|
||||
include (CPack)
|
||||
|
||||
# Check for external files.
|
||||
include (CheckIncludeFileCXX)
|
||||
check_include_file_cxx (attr/xattr.h HAVE_ATTR_XATTR_H)
|
||||
check_include_file_cxx (sys/xattr.h HAVE_SYS_XATTR_H)
|
||||
@ -45,11 +66,7 @@ CHECK_CXX_SOURCE_COMPILES ("#include <sys/types.h>
|
||||
#include <sys/xattr.h>
|
||||
int main() { getxattr(0,0,0,0,0,0); return 1; } " XATTR_ADD_OPT)
|
||||
|
||||
add_definitions (-D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26)
|
||||
if (APPLE)
|
||||
add_definitions (-D__FreeBSD__=10)
|
||||
endif (APPLE)
|
||||
|
||||
# Libraries or programs used for multiple modules.
|
||||
find_package (Protobuf REQUIRED)
|
||||
include_directories (${PROTOBUF_INCLUDE_DIR})
|
||||
|
||||
@ -58,9 +75,16 @@ include_directories (${GLOG_INCLUDE_DIRS})
|
||||
|
||||
find_program (POD2MAN pod2man)
|
||||
|
||||
find_package (GTest)
|
||||
if (GTEST_FOUND)
|
||||
enable_testing()
|
||||
endif (GTEST_FOUND)
|
||||
|
||||
# Prefix for encfs module includes.
|
||||
include_directories (${Encfs_BINARY_DIR})
|
||||
include_directories (${Encfs_SOURCE_DIR})
|
||||
|
||||
# Subdirectories.
|
||||
add_subdirectory(base)
|
||||
add_subdirectory(cipher)
|
||||
add_subdirectory(fs)
|
||||
@ -68,3 +92,10 @@ add_subdirectory(encfs)
|
||||
add_subdirectory(util)
|
||||
add_subdirectory(po)
|
||||
|
||||
# Test target.
|
||||
if (GTEST_FOUND)
|
||||
add_custom_target (test COMMAND ${CMAKE_TEST_COMMAND} DEPENDS
|
||||
cipher/cipher-tests fs/fs-tests)
|
||||
endif (GTEST_FOUND)
|
||||
|
||||
|
||||
|
@ -17,6 +17,8 @@ add_library (encfs-base
|
||||
ConfigVar.cpp
|
||||
Error.cpp
|
||||
Interface.cpp
|
||||
Range.h
|
||||
Registry.h
|
||||
XmlReader.cpp
|
||||
${PROTO_SRCS}
|
||||
${PROTO_HDRS}
|
||||
|
14
base/Range.h
14
base/Range.h
@ -21,6 +21,8 @@
|
||||
#ifndef _Range_incl_
|
||||
#define _Range_incl_
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace encfs {
|
||||
|
||||
class Range
|
||||
@ -42,6 +44,18 @@ public:
|
||||
int inc() const;
|
||||
};
|
||||
|
||||
inline std::ostream & operator << (std::ostream &st, const Range &r) {
|
||||
bool separator = false;
|
||||
for (int size = r.min(); size <= r.max(); size += r.inc()) {
|
||||
if (separator)
|
||||
st << ", ";
|
||||
else
|
||||
separator = true;
|
||||
st << size;
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
inline Range::Range(int minMax)
|
||||
{
|
||||
this->minVal = minMax;
|
||||
|
94
base/Registry.h
Normal file
94
base/Registry.h
Normal file
@ -0,0 +1,94 @@
|
||||
#ifndef REGISTRY_H
|
||||
#define REGISTRY_H
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
namespace encfs {
|
||||
|
||||
template <typename T>
|
||||
class Registry
|
||||
{
|
||||
public:
|
||||
typedef T *(*FactoryFn)();
|
||||
struct Data {
|
||||
FactoryFn constructor;
|
||||
typename T::Properties properties;
|
||||
};
|
||||
|
||||
void Register(const char *name, FactoryFn fn,
|
||||
typename T::Properties properties)
|
||||
{
|
||||
Data d;
|
||||
d.constructor = fn;
|
||||
d.properties = properties;
|
||||
data[name] = d;
|
||||
}
|
||||
|
||||
T* Create(const char *name)
|
||||
{
|
||||
auto it = data.find(name);
|
||||
if (it == data.end())
|
||||
return NULL;
|
||||
return (*it->second.constructor)();
|
||||
}
|
||||
|
||||
T* CreateForMatch(const std::string &description)
|
||||
{
|
||||
for (auto &it : data) {
|
||||
if (description == it.second.properties.toString())
|
||||
return (*it.second.constructor)();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::list<std::string> GetAll() const {
|
||||
std::list<std::string> result;
|
||||
for (auto &it : data) {
|
||||
result.push_back(it.first);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const typename T::Properties *GetProperties(const char *name) const {
|
||||
auto it = data.find(name);
|
||||
if (it == data.end())
|
||||
return NULL;
|
||||
return &(it->second.properties);
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, Data> data;
|
||||
};
|
||||
|
||||
template <typename T, typename BASE>
|
||||
class Registrar
|
||||
{
|
||||
public:
|
||||
Registrar(const char *name)
|
||||
{
|
||||
BASE::GetRegistry().Register(name,
|
||||
Registrar<T, BASE>::Construct,
|
||||
T::GetProperties());
|
||||
}
|
||||
|
||||
static BASE *Construct() {
|
||||
return new T();
|
||||
}
|
||||
};
|
||||
|
||||
#define DECLARE_REGISTERABLE_TYPE(TYPE) \
|
||||
static Registry<TYPE>& GetRegistry()
|
||||
|
||||
#define DEFINE_REGISTERABLE_TYPE(TYPE) \
|
||||
Registry<TYPE>& TYPE::GetRegistry() { \
|
||||
static Registry<TYPE> registry; \
|
||||
return registry; \
|
||||
}
|
||||
|
||||
#define REGISTER_CLASS(DERIVED, BASE) \
|
||||
static Registrar<DERIVED, BASE> registrar_##DERIVED(#DERIVED)
|
||||
|
||||
} // namespace encfs
|
||||
|
||||
#endif // REGISTRY_H
|
29
cipher/BlockCipher.cpp
Normal file
29
cipher/BlockCipher.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include "cipher/BlockCipher.h"
|
||||
|
||||
// TODO: add ifdef when OpenSSL becomes optional.
|
||||
#include "cipher/openssl.h"
|
||||
|
||||
namespace encfs {
|
||||
|
||||
Registry<BlockCipher>& BlockCipher::GetRegistry()
|
||||
{
|
||||
static Registry<BlockCipher> registry;
|
||||
static bool first = true;
|
||||
if (first)
|
||||
{
|
||||
OpenSSL::registerCiphers();
|
||||
first = false;
|
||||
}
|
||||
return registry;
|
||||
}
|
||||
|
||||
BlockCipher::BlockCipher()
|
||||
{
|
||||
}
|
||||
|
||||
BlockCipher::~BlockCipher()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace encfs
|
||||
|
28
cipher/BlockCipher.h
Normal file
28
cipher/BlockCipher.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef BLOCKCIPHER_H
|
||||
#define BLOCKCIPHER_H
|
||||
|
||||
#include "base/Interface.h"
|
||||
#include "base/Range.h"
|
||||
#include "base/Registry.h"
|
||||
#include "base/shared_ptr.h"
|
||||
#include "base/types.h"
|
||||
#include "cipher/StreamCipher.h"
|
||||
|
||||
namespace encfs {
|
||||
|
||||
// BlockCipher is a StreamCipher with a block size.
|
||||
// Encryption and decryption must be in multiples of the block size.
|
||||
class BlockCipher : public StreamCipher
|
||||
{
|
||||
public:
|
||||
static Registry<BlockCipher>& GetRegistry();
|
||||
|
||||
BlockCipher();
|
||||
virtual ~BlockCipher();
|
||||
|
||||
virtual int blockSize() const =0;
|
||||
};
|
||||
|
||||
} // namespace encfs
|
||||
|
||||
#endif // BLOCKCIPHER_H
|
95
cipher/BlockCipher_test.cpp
Normal file
95
cipher/BlockCipher_test.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
|
||||
/*****************************************************************************
|
||||
* 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 <list>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "base/shared_ptr.h"
|
||||
#include "cipher/BlockCipher.h"
|
||||
#include "cipher/MemoryPool.h"
|
||||
|
||||
using namespace encfs;
|
||||
using std::list;
|
||||
using std::string;
|
||||
|
||||
namespace {
|
||||
|
||||
void compare(const byte *a, const byte *b, int size) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
bool match = (a[i] == b[i]);
|
||||
ASSERT_TRUE(match) << "mismatched data at offset " << i
|
||||
<< " of " << size;
|
||||
if (!match)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BlockEncryptionTest, BlockCipher) {
|
||||
Registry<BlockCipher> registry = BlockCipher::GetRegistry();
|
||||
list<string> ciphers = registry.GetAll();
|
||||
for (const string &name : ciphers) {
|
||||
const BlockCipher::Properties *properties = registry.GetProperties(name.c_str());
|
||||
SCOPED_TRACE(testing::Message() << "Cipher " << name);
|
||||
|
||||
for (int keySize = properties->keySize.min();
|
||||
keySize <= properties->keySize.max();
|
||||
keySize += properties->keySize.inc()) {
|
||||
SCOPED_TRACE(testing::Message() << "Key size " << keySize);
|
||||
|
||||
shared_ptr<BlockCipher> cipher (registry.Create(name.c_str()));
|
||||
|
||||
ASSERT_TRUE(cipher->randomKey(keySize / 8));
|
||||
|
||||
// Create some data to encrypt.
|
||||
int blockSize = cipher->blockSize();
|
||||
MemBlock mb;
|
||||
mb.allocate(16 * blockSize);
|
||||
|
||||
for (int i = 0; i < 16 * blockSize; i++) {
|
||||
mb.data[i] = i % 256;
|
||||
}
|
||||
|
||||
MemBlock iv;
|
||||
iv.allocate(blockSize);
|
||||
for (int i = 0; i < blockSize; i++) {
|
||||
iv.data[i] = i;
|
||||
}
|
||||
|
||||
// Encrypt.
|
||||
MemBlock encrypted;
|
||||
encrypted.allocate(16 * blockSize);
|
||||
|
||||
ASSERT_TRUE(cipher->encrypt(iv.data, mb.data,
|
||||
encrypted.data, 16 * blockSize));
|
||||
|
||||
// Decrypt.
|
||||
MemBlock decrypted;
|
||||
decrypted.allocate(16 * blockSize);
|
||||
ASSERT_TRUE(cipher->decrypt(iv.data, encrypted.data,
|
||||
decrypted.data, 16 * blockSize));
|
||||
|
||||
compare(mb.data, decrypted.data, 16 * blockSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
@ -2,41 +2,42 @@ include_directories (${OPENSSL_INCLUDE_DIR})
|
||||
|
||||
link_directories (${Encfs_BINARY_DIR}/base)
|
||||
|
||||
enable_testing ()
|
||||
find_package (GTest REQUIRED)
|
||||
|
||||
add_library (encfs-cipher
|
||||
readpassphrase.cpp
|
||||
BlockCipher.cpp
|
||||
Cipher.cpp
|
||||
CipherKey.cpp
|
||||
MAC.cpp
|
||||
MemoryPool.cpp
|
||||
NullCipher.cpp
|
||||
openssl.cpp
|
||||
PBKDF.cpp
|
||||
readpassphrase.cpp
|
||||
SSL_Cipher.cpp
|
||||
StreamCipher.cpp
|
||||
)
|
||||
|
||||
target_link_libraries (encfs-cipher
|
||||
${OPENSSL_LIBRARIES}
|
||||
)
|
||||
|
||||
#include_directories (${GTEST_INCLUDE_DIR})
|
||||
#add_executable (unittests
|
||||
#MemBlockFileIO.cpp
|
||||
#MemFileIO.cpp
|
||||
#testing.cpp
|
||||
#test_IO.cpp
|
||||
#test_BlockIO.cpp
|
||||
#)
|
||||
if (GTEST_FOUND)
|
||||
link_directories (${PROJECT_BINARY_DIR}/base)
|
||||
include_directories (${GTEST_INCLUDE_DIR})
|
||||
|
||||
#target_link_libraries (unittests
|
||||
#${GTEST_BOTH_LIBRARIES}
|
||||
#encfs-fs
|
||||
#encfs-base
|
||||
#${GLOG_LIBRARIES}
|
||||
#)
|
||||
file (GLOB TEST_FILES "*_test.cpp")
|
||||
|
||||
#add_test (UnitTests unittests)
|
||||
#GTEST_ADD_TESTS (unittests "${UnitTestArgs}" test_IO.cpp test_BlockIO.cpp)
|
||||
#add_custom_target (test COMMAND ${CMAKE_CTEST_COMMAND} DEPENDS unittests)
|
||||
add_executable (cipher-tests
|
||||
testing.cpp
|
||||
${TEST_FILES}
|
||||
)
|
||||
|
||||
target_link_libraries (cipher-tests
|
||||
${GTEST_BOTH_LIBRARIES}
|
||||
encfs-cipher
|
||||
encfs-base
|
||||
${GLOG_LIBRARIES}
|
||||
)
|
||||
|
||||
add_test (CipherTests cipher-tests)
|
||||
GTEST_ADD_TESTS (cipher-tests "${CipherTestArgs}" ${TEST_FILES})
|
||||
endif (GTEST_FOUND)
|
||||
|
16
cipher/MAC.cpp
Normal file
16
cipher/MAC.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include "cipher/MAC.h"
|
||||
|
||||
namespace encfs {
|
||||
|
||||
DEFINE_REGISTERABLE_TYPE(MessageAuthenticationCode)
|
||||
|
||||
MessageAuthenticationCode::MessageAuthenticationCode()
|
||||
{
|
||||
}
|
||||
|
||||
MessageAuthenticationCode::~MessageAuthenticationCode()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace encfs
|
||||
|
43
cipher/MAC.h
Normal file
43
cipher/MAC.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef ENCFS_MAC_H
|
||||
#define ENCFS_MAC_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/Registry.h"
|
||||
#include "base/types.h"
|
||||
|
||||
namespace encfs {
|
||||
|
||||
// MessageAuthenticationCode provides keyed MAC algorithms, eg HMAC.
|
||||
class MessageAuthenticationCode
|
||||
{
|
||||
public:
|
||||
DECLARE_REGISTERABLE_TYPE(MessageAuthenticationCode);
|
||||
|
||||
struct Properties {
|
||||
int blockSize; // Block length of hash function.
|
||||
std::string hashFunction;
|
||||
std::string mode;
|
||||
std::string library;
|
||||
|
||||
std::string toString() const {
|
||||
return hashFunction + "/" + mode;
|
||||
}
|
||||
};
|
||||
|
||||
MessageAuthenticationCode();
|
||||
virtual ~MessageAuthenticationCode();
|
||||
|
||||
virtual int outputSize() const =0;
|
||||
|
||||
virtual bool setKey(const byte *key, int keyLength) =0;
|
||||
virtual bool randomKey(int keyLength) =0;
|
||||
|
||||
virtual void reset() =0;
|
||||
virtual bool update(const byte *in, int length) =0;
|
||||
virtual bool write(byte *out) =0;
|
||||
};
|
||||
|
||||
} // namespace encfs
|
||||
|
||||
#endif // ENCFS_MAC_H
|
88
cipher/MAC_test.cpp
Normal file
88
cipher/MAC_test.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
|
||||
/*****************************************************************************
|
||||
* 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 <string.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "base/shared_ptr.h"
|
||||
#include "cipher/MAC.h"
|
||||
#include "cipher/testing.h"
|
||||
|
||||
using namespace encfs;
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(HMacSha1Test, MessageAuthenticationCode) {
|
||||
Registry<MessageAuthenticationCode> registry =
|
||||
MessageAuthenticationCode::GetRegistry();
|
||||
shared_ptr<MessageAuthenticationCode> hmac(
|
||||
registry.CreateForMatch( "SHA-1/HMAC" ));
|
||||
ASSERT_FALSE(!hmac);
|
||||
|
||||
// Test cases from rfc2202
|
||||
// Test case 1
|
||||
byte key[20];
|
||||
byte out[20];
|
||||
for (int i = 0; i < 20; ++i)
|
||||
key[i] = 0x0b;
|
||||
hmac->setKey(key, 20);
|
||||
hmac->reset();
|
||||
hmac->update((byte *)"Hi There", 8);
|
||||
hmac->write(out);
|
||||
ASSERT_EQ("b617318655057264e28bc0b6fb378c8ef146be00", stringToHex(out, 20));
|
||||
|
||||
// Test case 2
|
||||
strcpy((char *)key, "Jefe");
|
||||
hmac->setKey(key, 4);
|
||||
hmac->reset();
|
||||
hmac->update((byte *)"what do ya want for nothing?", 28);
|
||||
hmac->write(out);
|
||||
ASSERT_EQ("effcdf6ae5eb2fa2d27416d5f184df9c259a7c79", stringToHex(out, 20));
|
||||
|
||||
// Test case 3
|
||||
for (int i = 0; i < 20; ++i)
|
||||
key[i] = 0xaa;
|
||||
hmac->setKey(key, 20);
|
||||
hmac->reset();
|
||||
{
|
||||
byte data[50];
|
||||
memset(data, 0xdd, 50);
|
||||
hmac->update(data, 50);
|
||||
}
|
||||
hmac->write(out);
|
||||
ASSERT_EQ("125d7342b9ac11cd91a39af48aa17b4f63f175d3", stringToHex(out, 20));
|
||||
|
||||
// Test #7
|
||||
byte longKey[80];
|
||||
memset(longKey, 0xaa, 80);
|
||||
hmac->setKey(longKey, 80);
|
||||
hmac->reset();
|
||||
hmac->update((byte *)"Test Using Larger Than Block-Size Key and Larger "
|
||||
"Than One Block-Size Data", 73);
|
||||
hmac->write(out);
|
||||
ASSERT_EQ("e8e99d0f45237d786d6bbaa7965c7808bbff1a91", stringToHex(out, 20));
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
@ -134,7 +134,7 @@ void MemoryPool::destroyAll()
|
||||
SecureMem::SecureMem(int len)
|
||||
{
|
||||
rAssert(len > 0);
|
||||
data = (char *)OPENSSL_malloc(len);
|
||||
data = (byte *)OPENSSL_malloc(len);
|
||||
if (data)
|
||||
{
|
||||
size = len;
|
||||
|
@ -29,7 +29,8 @@ namespace encfs {
|
||||
Memory Pool for fixed sized objects.
|
||||
|
||||
Usage:
|
||||
MemBlock mb( size );
|
||||
MemBlock mb;
|
||||
mb.allocate( size );
|
||||
// do things with storage in mb.data
|
||||
byte *buffer = mb.data;
|
||||
|
||||
@ -59,7 +60,7 @@ namespace MemoryPool
|
||||
struct SecureMem
|
||||
{
|
||||
int size;
|
||||
char *data;
|
||||
byte *data;
|
||||
|
||||
SecureMem(int len);
|
||||
~SecureMem();
|
||||
|
16
cipher/PBKDF.cpp
Normal file
16
cipher/PBKDF.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include "cipher/PBKDF.h"
|
||||
|
||||
namespace encfs {
|
||||
|
||||
DEFINE_REGISTERABLE_TYPE(PBKDF)
|
||||
|
||||
PBKDF::PBKDF()
|
||||
{
|
||||
}
|
||||
|
||||
PBKDF::~PBKDF()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace encfs
|
||||
|
35
cipher/PBKDF.h
Normal file
35
cipher/PBKDF.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef ENCFS_PBKDF_H
|
||||
#define ENCFS_PBKDF_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/Registry.h"
|
||||
#include "base/types.h"
|
||||
|
||||
namespace encfs {
|
||||
|
||||
// Password Based Key Derivation Function.
|
||||
class PBKDF
|
||||
{
|
||||
public:
|
||||
DECLARE_REGISTERABLE_TYPE(PBKDF);
|
||||
|
||||
struct Properties {
|
||||
std::string mode;
|
||||
std::string library;
|
||||
|
||||
std::string toString() const { return mode; }
|
||||
};
|
||||
|
||||
PBKDF();
|
||||
virtual ~PBKDF();
|
||||
|
||||
virtual bool makeKey(const char *password, int passwordLength,
|
||||
const byte *salt, int saltLength,
|
||||
int numIterations,
|
||||
byte *outKey, int keyLength) const = 0;
|
||||
};
|
||||
|
||||
} // namespace encfs
|
||||
|
||||
#endif // ENCFS_PBKDF_H
|
78
cipher/PBKDF_test.cpp
Normal file
78
cipher/PBKDF_test.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
|
||||
/*****************************************************************************
|
||||
* 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 <string.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "base/shared_ptr.h"
|
||||
#include "cipher/PBKDF.h"
|
||||
#include "cipher/testing.h"
|
||||
|
||||
using namespace encfs;
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(PKCS5_PBKDF2_HMAC_SHA1, PBKDF) {
|
||||
Registry<PBKDF> registry = PBKDF::GetRegistry();
|
||||
shared_ptr<PBKDF> impl( registry.CreateForMatch( "PKCS5_PBKDF2_HMAC_SHA1" ));
|
||||
ASSERT_FALSE(!impl);
|
||||
|
||||
// Test cases from rfc6070
|
||||
// Test case 1
|
||||
{
|
||||
byte key[20];
|
||||
bool ok = impl->makeKey("password", 8,
|
||||
(byte*)"salt", 4,
|
||||
1,
|
||||
key, sizeof(key));
|
||||
ASSERT_TRUE(ok);
|
||||
ASSERT_EQ("0c60c80f961f0e71f3a9b524af6012062fe037a6",
|
||||
stringToHex(key, sizeof(key)));
|
||||
}
|
||||
|
||||
{
|
||||
byte key[25];
|
||||
bool ok = impl->makeKey("passwordPASSWORDpassword", 24,
|
||||
(byte*)"saltSALTsaltSALTsaltSALTsaltSALTsalt", 36,
|
||||
4096,
|
||||
key, sizeof(key));
|
||||
ASSERT_TRUE(ok);
|
||||
ASSERT_EQ("3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038",
|
||||
stringToHex(key, sizeof(key)));
|
||||
}
|
||||
|
||||
{
|
||||
byte key[16];
|
||||
bool ok = impl->makeKey("pass\0word", 9,
|
||||
(byte*)"sa\0lt", 5,
|
||||
4096,
|
||||
key, sizeof(key));
|
||||
ASSERT_TRUE(ok);
|
||||
ASSERT_EQ("56fa6aa75548099dcc37d7f03425e0c3",
|
||||
stringToHex(key, sizeof(key)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include "cipher/SSL_Cipher.h"
|
||||
#include "cipher/MemoryPool.h"
|
||||
#include "cipher/BlockCipher.h"
|
||||
#include "base/Error.h"
|
||||
#include "base/Mutex.h"
|
||||
#include "base/Range.h"
|
||||
@ -65,13 +66,13 @@ inline int MIN(int a, int b)
|
||||
|
||||
DEPRECATED: this is here for backward compatibilty only. Use PBKDF
|
||||
*/
|
||||
int BytesToKey( int keyLen, int ivLen, const EVP_MD *md,
|
||||
int BytesToKey(int keyLen, int ivLen, const EVP_MD *md,
|
||||
const byte *data, int dataLen,
|
||||
unsigned int rounds, byte *key, byte *iv)
|
||||
{
|
||||
if( data == NULL || dataLen == 0 )
|
||||
return 0; // OpenSSL returns nkey here, but why? It is a failure..
|
||||
|
||||
|
||||
byte mdBuf[ EVP_MAX_MD_SIZE ];
|
||||
unsigned int mds=0;
|
||||
int addmd =0;
|
||||
@ -110,7 +111,7 @@ int BytesToKey( int keyLen, int ivLen, const EVP_MD *md,
|
||||
{
|
||||
memcpy( iv, mdBuf+offset, toCopy );
|
||||
iv += toCopy;
|
||||
niv -= toCopy;
|
||||
niv -= toCopy;
|
||||
offset += toCopy;
|
||||
}
|
||||
if((nkey == 0) && (niv == 0)) break;
|
||||
@ -128,9 +129,9 @@ long time_diff(const timeval &end, const timeval &start)
|
||||
}
|
||||
|
||||
int SSL_Cipher::TimedPBKDF2(const char *pass, int passlen,
|
||||
const byte *salt, int saltlen,
|
||||
int keylen, byte *out,
|
||||
long desiredPDFTime)
|
||||
const byte *salt, int saltlen,
|
||||
int keylen, byte *out,
|
||||
long desiredPDFTime)
|
||||
{
|
||||
int iter = 1000;
|
||||
timeval start, end;
|
||||
@ -188,8 +189,9 @@ static shared_ptr<Cipher> NewBFCipher( const Interface &iface, int keyLen )
|
||||
const EVP_CIPHER *blockCipher = EVP_bf_cbc();
|
||||
const EVP_CIPHER *streamCipher = EVP_bf_cfb();
|
||||
|
||||
return shared_ptr<Cipher>( new SSL_Cipher(iface, BlowfishInterface,
|
||||
blockCipher, streamCipher, keyLen / 8) );
|
||||
return shared_ptr<Cipher>(
|
||||
new SSL_Cipher(iface, BlowfishInterface,
|
||||
blockCipher, streamCipher, keyLen / 8) );
|
||||
}
|
||||
|
||||
static bool BF_Cipher_registered = Cipher::Register(
|
||||
@ -239,8 +241,8 @@ static shared_ptr<Cipher> NewAESCipher( const Interface &iface, int keyLen )
|
||||
}
|
||||
|
||||
static bool AES_Cipher_registered = Cipher::Register(
|
||||
"AES", "16 byte block cipher",
|
||||
AESInterface, AESKeyRange, AESBlockRange, NewAESCipher, true);
|
||||
"AES", "16 byte block cipher",
|
||||
AESInterface, AESKeyRange, AESBlockRange, NewAESCipher, true);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_EVP_AES_XTS)
|
||||
@ -276,35 +278,35 @@ static shared_ptr<Cipher> NewAesXtsCipher( const Interface &iface, int keyLen )
|
||||
}
|
||||
|
||||
static bool AES_XTS_Cipher_registered = Cipher::Register(
|
||||
"AES_XTS", "Tweakable wide-block cipher",
|
||||
AesXtsInterface, AesXtsKeyRange, AesXtsBlockRange, NewAesXtsCipher, false);
|
||||
"AES_XTS", "Tweakable wide-block cipher",
|
||||
AesXtsInterface, AesXtsKeyRange, AesXtsBlockRange, NewAesXtsCipher, false);
|
||||
#endif
|
||||
|
||||
class SSLKey : public AbstractCipherKey
|
||||
{
|
||||
public:
|
||||
pthread_mutex_t mutex;
|
||||
public:
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
unsigned int keySize; // in bytes
|
||||
unsigned int ivLength;
|
||||
unsigned int keySize; // in bytes
|
||||
unsigned int ivLength;
|
||||
|
||||
// key data is first _keySize bytes,
|
||||
// followed by iv of _ivLength bytes,
|
||||
SecureMem buf;
|
||||
// key data is first _keySize bytes,
|
||||
// followed by iv of _ivLength bytes,
|
||||
SecureMem buf;
|
||||
|
||||
EVP_CIPHER_CTX block_enc;
|
||||
EVP_CIPHER_CTX block_dec;
|
||||
EVP_CIPHER_CTX stream_enc;
|
||||
EVP_CIPHER_CTX stream_dec;
|
||||
EVP_CIPHER_CTX block_enc;
|
||||
EVP_CIPHER_CTX block_dec;
|
||||
EVP_CIPHER_CTX stream_enc;
|
||||
EVP_CIPHER_CTX stream_dec;
|
||||
|
||||
HMAC_CTX mac_ctx;
|
||||
HMAC_CTX mac_ctx;
|
||||
|
||||
SSLKey(int keySize, int ivLength);
|
||||
~SSLKey();
|
||||
SSLKey(int keySize, int ivLength);
|
||||
~SSLKey();
|
||||
};
|
||||
|
||||
SSLKey::SSLKey(int keySize_, int ivLength_)
|
||||
: buf(keySize_ + ivLength_)
|
||||
: buf(keySize_ + ivLength_)
|
||||
{
|
||||
rAssert(keySize_ >= 8);
|
||||
rAssert(ivLength_ >= 8);
|
||||
@ -341,7 +343,7 @@ inline byte* IVData( const shared_ptr<SSLKey> &key )
|
||||
}
|
||||
|
||||
void initKey(const shared_ptr<SSLKey> &key, const EVP_CIPHER *_blockCipher,
|
||||
const EVP_CIPHER *_streamCipher, int _keySize)
|
||||
const EVP_CIPHER *_streamCipher, int _keySize)
|
||||
{
|
||||
Lock lock( key->mutex );
|
||||
// initialize the cipher context once so that we don't have to do it for
|
||||
@ -377,10 +379,10 @@ void initKey(const shared_ptr<SSLKey> &key, const EVP_CIPHER *_blockCipher,
|
||||
|
||||
|
||||
SSL_Cipher::SSL_Cipher(const Interface &iface_,
|
||||
const Interface &realIface_,
|
||||
const EVP_CIPHER *blockCipher,
|
||||
const EVP_CIPHER *streamCipher,
|
||||
int keySize_)
|
||||
const Interface &realIface_,
|
||||
const EVP_CIPHER *blockCipher,
|
||||
const EVP_CIPHER *streamCipher,
|
||||
int keySize_)
|
||||
{
|
||||
this->iface = iface_;
|
||||
this->realIface = realIface_;
|
||||
@ -393,8 +395,8 @@ SSL_Cipher::SSL_Cipher(const Interface &iface_,
|
||||
rAssert(_ivLength <= _keySize);
|
||||
|
||||
VLOG(1) << "allocated cipher " << iface.name()
|
||||
<< ", keySize " << _keySize
|
||||
<< ", ivlength " << _ivLength;
|
||||
<< ", keySize " << _keySize
|
||||
<< ", ivlength " << _ivLength;
|
||||
|
||||
// EVP_CIPHER_key_length isn't useful for variable-length ciphers like
|
||||
// Blowfish. Version 1 relied upon it incorrectly.
|
||||
@ -402,8 +404,8 @@ SSL_Cipher::SSL_Cipher(const Interface &iface_,
|
||||
&& iface.major() == 1)
|
||||
{
|
||||
LOG(WARNING) << "Running in backward compatibilty mode for 1.0 - \n"
|
||||
<< "key is really " << EVP_CIPHER_key_length( _blockCipher ) * 8
|
||||
<< " bits, not " << _keySize * 8;
|
||||
<< "key is really " << EVP_CIPHER_key_length( _blockCipher ) * 8
|
||||
<< " bits, not " << _keySize * 8;
|
||||
}
|
||||
}
|
||||
|
||||
@ -422,10 +424,10 @@ Interface SSL_Cipher::interface() const
|
||||
|
||||
This algorithm must remain constant for backward compatibility, as this key
|
||||
is used to encipher/decipher the master key.
|
||||
*/
|
||||
*/
|
||||
CipherKey SSL_Cipher::newKey(const char *password, int passwdLength,
|
||||
int &iterationCount, long desiredDuration,
|
||||
const byte *salt, int saltLen)
|
||||
int &iterationCount, long desiredDuration,
|
||||
const byte *salt, int saltLen)
|
||||
{
|
||||
shared_ptr<SSLKey> key( new SSLKey( _keySize, _ivLength) );
|
||||
|
||||
@ -477,7 +479,7 @@ CipherKey SSL_Cipher::newKey(const char *password, int passwdLength)
|
||||
if(bytes != (int)_keySize)
|
||||
{
|
||||
LOG(WARNING) << "newKey: BytesToKey returned " << bytes
|
||||
<< ", expecting " << _keySize << " key bytes";
|
||||
<< ", expecting " << _keySize << " key bytes";
|
||||
}
|
||||
} else
|
||||
{
|
||||
@ -499,7 +501,7 @@ CipherKey SSL_Cipher::newKey(const char *password, int passwdLength)
|
||||
|
||||
This algorithm can change at any time without affecting backward
|
||||
compatibility.
|
||||
*/
|
||||
*/
|
||||
CipherKey SSL_Cipher::newRandomKey()
|
||||
{
|
||||
const int bufLen = MAX_KEYLENGTH;
|
||||
@ -531,11 +533,11 @@ CipherKey SSL_Cipher::newRandomKey()
|
||||
|
||||
/*
|
||||
Compute a 64-bit check value for the data using HMAC.
|
||||
*/
|
||||
*/
|
||||
static uint64_t _checksum_64(SSLKey *key,
|
||||
const byte *data,
|
||||
int dataLen,
|
||||
uint64_t *chainedIV)
|
||||
const byte *data,
|
||||
int dataLen,
|
||||
uint64_t *chainedIV)
|
||||
{
|
||||
rAssert( dataLen > 0 );
|
||||
Lock lock( key->mutex );
|
||||
@ -576,7 +578,7 @@ static uint64_t _checksum_64(SSLKey *key,
|
||||
}
|
||||
|
||||
bool SSL_Cipher::randomize( byte *buf, int len,
|
||||
bool strongRandom ) const
|
||||
bool strongRandom ) const
|
||||
{
|
||||
// to avoid warnings of uninitialized data from valgrind
|
||||
memset(buf, 0, len);
|
||||
@ -599,7 +601,7 @@ bool SSL_Cipher::randomize( byte *buf, int len,
|
||||
}
|
||||
|
||||
uint64_t SSL_Cipher::MAC_64( const byte *data, int len,
|
||||
const CipherKey &key, uint64_t *chainedIV ) const
|
||||
const CipherKey &key, uint64_t *chainedIV ) const
|
||||
{
|
||||
shared_ptr<SSLKey> mk = dynamic_pointer_cast<SSLKey>(key);
|
||||
uint64_t tmp = _checksum_64( mk.get(), data, len, chainedIV );
|
||||
@ -611,7 +613,7 @@ uint64_t SSL_Cipher::MAC_64( const byte *data, int len,
|
||||
}
|
||||
|
||||
CipherKey SSL_Cipher::readKey(const byte *data,
|
||||
const CipherKey &masterKey, bool checkKey)
|
||||
const CipherKey &masterKey, bool checkKey)
|
||||
{
|
||||
shared_ptr<SSLKey> mk = dynamic_pointer_cast<SSLKey>(masterKey);
|
||||
rAssert(mk->keySize == _keySize);
|
||||
@ -638,8 +640,8 @@ CipherKey SSL_Cipher::readKey(const byte *data,
|
||||
if(checksum2 != checksum && checkKey)
|
||||
{
|
||||
VLOG(1) << "checksum mismatch: expected " << checksum
|
||||
<< ", got " << checksum2
|
||||
<< "on decode of " << _keySize + _ivLength << " bytes";
|
||||
<< ", got " << checksum2
|
||||
<< "on decode of " << _keySize + _ivLength << " bytes";
|
||||
OPENSSL_cleanse(tmpBuf, sizeof(tmpBuf));
|
||||
return CipherKey();
|
||||
}
|
||||
@ -656,7 +658,7 @@ CipherKey SSL_Cipher::readKey(const byte *data,
|
||||
}
|
||||
|
||||
void SSL_Cipher::writeKey(const CipherKey &ckey, byte *data,
|
||||
const CipherKey &masterKey)
|
||||
const CipherKey &masterKey)
|
||||
{
|
||||
shared_ptr<SSLKey> key = dynamic_pointer_cast<SSLKey>(ckey);
|
||||
rAssert(key->keySize == _keySize);
|
||||
@ -771,7 +773,7 @@ void SSL_Cipher::setIVec_old(byte *ivec,
|
||||
{
|
||||
unsigned int var1 = 0x060a4011 * seed;
|
||||
unsigned int var2 = 0x0221040d * (seed ^ 0xD3FEA11C);
|
||||
|
||||
|
||||
memcpy( ivec, IVData(key), _ivLength );
|
||||
|
||||
ivec[0] ^= (var1 >> 24) & 0xff;
|
||||
@ -861,7 +863,7 @@ bool SSL_Cipher::streamEncode(byte *buf, int size,
|
||||
|
||||
dstLen += tmpLen;
|
||||
LOG_IF(ERROR, dstLen != size) << "encoding " << size
|
||||
<< " bytes, got back " << dstLen << " (" << tmpLen << " in final_ex)";
|
||||
<< " bytes, got back " << dstLen << " (" << tmpLen << " in final_ex)";
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -897,7 +899,7 @@ bool SSL_Cipher::streamDecode(byte *buf, int size,
|
||||
|
||||
dstLen += tmpLen;
|
||||
LOG_IF(ERROR, dstLen != size) << "encoding " << size
|
||||
<< " bytes, got back " << dstLen << " (" << tmpLen << " in final_ex)";
|
||||
<< " bytes, got back " << dstLen << " (" << tmpLen << " in final_ex)";
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -928,7 +930,7 @@ bool SSL_Cipher::blockEncode(byte *buf, int size,
|
||||
dstLen += tmpLen;
|
||||
|
||||
LOG_IF(ERROR, dstLen != size) << "encoding " << size
|
||||
<< " bytes, got back " << dstLen << " (" << tmpLen << " in final_ex)";
|
||||
<< " bytes, got back " << dstLen << " (" << tmpLen << " in final_ex)";
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -958,7 +960,7 @@ bool SSL_Cipher::blockDecode(byte *buf, int size,
|
||||
dstLen += tmpLen;
|
||||
|
||||
LOG_IF(ERROR, dstLen != size) << "decoding " << size
|
||||
<< " bytes, got back " << dstLen << " (" << tmpLen << " in final_ex)";
|
||||
<< " bytes, got back " << dstLen << " (" << tmpLen << " in final_ex)";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
20
cipher/StreamCipher.cpp
Normal file
20
cipher/StreamCipher.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
#include "cipher/StreamCipher.h"
|
||||
|
||||
namespace encfs {
|
||||
|
||||
Registry<StreamCipher>& StreamCipher::GetRegistry()
|
||||
{
|
||||
static Registry<StreamCipher> registry;
|
||||
return registry;
|
||||
}
|
||||
|
||||
StreamCipher::StreamCipher()
|
||||
{
|
||||
}
|
||||
|
||||
StreamCipher::~StreamCipher()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace encfs
|
||||
|
60
cipher/StreamCipher.h
Normal file
60
cipher/StreamCipher.h
Normal file
@ -0,0 +1,60 @@
|
||||
|
||||
/*****************************************************************************
|
||||
* 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 _STREAMCIPHER_incl_
|
||||
#define _STREAMCIPHER_incl_
|
||||
|
||||
#include "base/Range.h"
|
||||
#include "base/Registry.h"
|
||||
#include "base/shared_ptr.h"
|
||||
#include "base/types.h"
|
||||
|
||||
namespace encfs {
|
||||
|
||||
class StreamCipher
|
||||
{
|
||||
public:
|
||||
static Registry<StreamCipher>& GetRegistry();
|
||||
|
||||
struct Properties {
|
||||
Range keySize;
|
||||
std::string cipher;
|
||||
std::string mode;
|
||||
std::string library;
|
||||
};
|
||||
|
||||
StreamCipher();
|
||||
virtual ~StreamCipher();
|
||||
|
||||
virtual bool setKey(const byte *key, int keyLength) =0;
|
||||
virtual bool randomKey(int keyLength) =0;
|
||||
|
||||
virtual bool encrypt(const byte *iv, const byte *in,
|
||||
byte *out, int numBytes) =0;
|
||||
virtual bool decrypt(const byte *iv, const byte *in,
|
||||
byte *out, int numBytes) =0;
|
||||
};
|
||||
|
||||
} // namespace encfs
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Author: Valient Gough <vgough@pobox.com>
|
||||
*
|
||||
*****************************************************************************
|
||||
* Copyright (c) 2007, Valient Gough
|
||||
* Copyright (c) 2007-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
|
||||
@ -20,10 +20,16 @@
|
||||
|
||||
#include "cipher/openssl.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <pthread.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <glog/logging.h>
|
||||
|
||||
#include "base/config.h"
|
||||
|
||||
#define NO_DES
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/rand.h>
|
||||
@ -31,8 +37,345 @@
|
||||
#include <openssl/engine.h>
|
||||
#endif
|
||||
|
||||
#include <openssl/blowfish.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "base/Error.h"
|
||||
#include "base/i18n.h"
|
||||
#include "base/Mutex.h"
|
||||
#include "base/Range.h"
|
||||
|
||||
#include "cipher/BlockCipher.h"
|
||||
#include "cipher/MAC.h"
|
||||
#include "cipher/MemoryPool.h"
|
||||
#include "cipher/PBKDF.h"
|
||||
#include "cipher/StreamCipher.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace encfs {
|
||||
|
||||
const int MAX_KEYLENGTH = 64; // in bytes (256 bit)
|
||||
const int MAX_IVLENGTH = 16;
|
||||
const int KEY_CHECKSUM_BYTES = 4;
|
||||
|
||||
#ifndef MIN
|
||||
inline int MIN(int a, int b)
|
||||
{
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Base for {Block,Stream}Cipher implementation.
|
||||
class OpenSSLCipher : public BlockCipher {
|
||||
public:
|
||||
OpenSSLCipher() {
|
||||
}
|
||||
|
||||
virtual ~OpenSSLCipher() {
|
||||
EVP_CIPHER_CTX_cleanup( &enc );
|
||||
EVP_CIPHER_CTX_cleanup( &dec );
|
||||
}
|
||||
|
||||
bool rekey(const EVP_CIPHER *cipher, const byte *key, int length) {
|
||||
EVP_CIPHER_CTX_init( &enc );
|
||||
EVP_EncryptInit_ex( &enc, cipher, NULL, NULL, NULL);
|
||||
EVP_CIPHER_CTX_set_key_length( &enc, length );
|
||||
EVP_CIPHER_CTX_set_padding( &enc, 0 );
|
||||
EVP_EncryptInit_ex( &enc, NULL, NULL, key, NULL);
|
||||
|
||||
EVP_CIPHER_CTX_init( &dec );
|
||||
EVP_DecryptInit_ex( &dec, cipher, NULL, NULL, NULL);
|
||||
EVP_CIPHER_CTX_set_key_length( &dec, length );
|
||||
EVP_CIPHER_CTX_set_padding( &dec, 0 );
|
||||
EVP_DecryptInit_ex( &dec, NULL, NULL, key, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool randomize(byte *out, int len) {
|
||||
int result = RAND_bytes( out, len );
|
||||
if(result != 1)
|
||||
{
|
||||
char errStr[120]; // specs require string at least 120 bytes long..
|
||||
unsigned long errVal = 0;
|
||||
if((errVal = ERR_get_error()) != 0)
|
||||
LOG(ERROR) << "openssl error: " << ERR_error_string( errVal, errStr );
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Rekey with random key.
|
||||
bool rekey(const EVP_CIPHER *cipher, int keyLength) {
|
||||
SecureMem key(keyLength);
|
||||
|
||||
if (!randomize(key.data, key.size))
|
||||
return false;
|
||||
|
||||
return rekey(cipher, key.data, key.size);
|
||||
}
|
||||
|
||||
virtual int blockSize() const {
|
||||
return EVP_CIPHER_CTX_block_size(&enc);
|
||||
}
|
||||
|
||||
virtual bool encrypt(const byte *ivec, const byte *in,
|
||||
byte *out, int size) {
|
||||
int dstLen = 0, tmpLen = 0;
|
||||
EVP_EncryptInit_ex( &enc, NULL, NULL, NULL, ivec);
|
||||
EVP_EncryptUpdate( &enc, out, &dstLen, in, size);
|
||||
EVP_EncryptFinal_ex( &enc, out+dstLen, &tmpLen );
|
||||
dstLen += tmpLen;
|
||||
|
||||
if (dstLen != size) {
|
||||
LOG(ERROR) << "encoding " << size
|
||||
<< " bytes, got back " << dstLen << " (" << tmpLen << " in final_ex)";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool decrypt(const byte *ivec, const byte *in,
|
||||
byte *out, int size) {
|
||||
int dstLen = 0, tmpLen = 0;
|
||||
EVP_DecryptInit_ex( &dec, NULL, NULL, NULL, ivec);
|
||||
EVP_DecryptUpdate( &dec, out, &dstLen, in, size );
|
||||
EVP_DecryptFinal_ex( &dec, out+dstLen, &tmpLen );
|
||||
dstLen += tmpLen;
|
||||
|
||||
if (dstLen != size) {
|
||||
LOG(ERROR) << "decoding " << size
|
||||
<< " bytes, got back " << dstLen << " (" << tmpLen << " in final_ex)";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
EVP_CIPHER_CTX enc;
|
||||
EVP_CIPHER_CTX dec;
|
||||
};
|
||||
|
||||
|
||||
#if defined(HAVE_EVP_BF)
|
||||
static Range BfKeyRange(128,256,32);
|
||||
class BfCbcBlockCipher : public OpenSSLCipher {
|
||||
public:
|
||||
BfCbcBlockCipher() {}
|
||||
virtual ~BfCbcBlockCipher() {}
|
||||
|
||||
virtual bool setKey(const byte *key, int length) {
|
||||
if (BfKeyRange.allowed(length * 8))
|
||||
return rekey(EVP_bf_cbc(), key, length);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool randomKey(int length) {
|
||||
return BfKeyRange.allowed(length * 8) && rekey(EVP_bf_cbc(), length);
|
||||
}
|
||||
|
||||
static Properties GetProperties() {
|
||||
Properties props;
|
||||
props.keySize = BfKeyRange;
|
||||
props.cipher = "Blowfish";
|
||||
props.mode = "CBC";
|
||||
props.library = "OpenSSL";
|
||||
return props;
|
||||
}
|
||||
};
|
||||
REGISTER_CLASS(BfCbcBlockCipher, BlockCipher);
|
||||
|
||||
class BfCfbStreamCipher : public OpenSSLCipher {
|
||||
public:
|
||||
BfCfbStreamCipher() {}
|
||||
virtual ~BfCfbStreamCipher() {}
|
||||
|
||||
virtual bool setKey(const byte *key, int length) {
|
||||
return BfKeyRange.allowed(length * 8) && rekey(EVP_bf_cfb(), key, length);
|
||||
}
|
||||
|
||||
virtual bool randomKey(int length) {
|
||||
return BfKeyRange.allowed(length * 8) && rekey(EVP_bf_cfb(), length);
|
||||
}
|
||||
|
||||
static Properties GetProperties() {
|
||||
Properties props;
|
||||
props.keySize = BfKeyRange;
|
||||
props.cipher = "Blowfish";
|
||||
props.mode = "CFB";
|
||||
props.library = "OpenSSL";
|
||||
return props;
|
||||
}
|
||||
};
|
||||
REGISTER_CLASS(BfCfbStreamCipher, StreamCipher);
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(HAVE_EVP_AES)
|
||||
static Range AesKeyRange(128,256,64);
|
||||
class AesCbcBlockCipher : public OpenSSLCipher {
|
||||
public:
|
||||
AesCbcBlockCipher() {}
|
||||
virtual ~AesCbcBlockCipher() {}
|
||||
|
||||
virtual bool setKey(const byte *key, int length) {
|
||||
const EVP_CIPHER *cipher = getCipher(length);
|
||||
return (cipher != NULL) && rekey(cipher, key, length);
|
||||
}
|
||||
|
||||
virtual bool randomKey(int length) {
|
||||
const EVP_CIPHER *cipher = getCipher(length);
|
||||
return (cipher != NULL) && rekey(cipher, length);
|
||||
}
|
||||
|
||||
static const EVP_CIPHER *getCipher(int keyLength) {
|
||||
switch(keyLength * 8)
|
||||
{
|
||||
case 128: return EVP_aes_128_cbc();
|
||||
case 192: return EVP_aes_192_cbc();
|
||||
case 256: return EVP_aes_256_cbc();
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static Properties GetProperties() {
|
||||
Properties props;
|
||||
props.keySize = AesKeyRange;
|
||||
props.cipher = "AES";
|
||||
props.mode = "CBC";
|
||||
props.library = "OpenSSL";
|
||||
return props;
|
||||
}
|
||||
};
|
||||
REGISTER_CLASS(AesCbcBlockCipher, BlockCipher);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_EVP_AES_XTS)
|
||||
static Range AesXtsKeyRange(128,256,128);
|
||||
class AesXtsBlockCipher : public OpenSSLCipher {
|
||||
public:
|
||||
AesXtsBlockCipher() {}
|
||||
virtual ~AesXtsBlockCipher() {}
|
||||
|
||||
virtual bool setKey(const byte *key, int length) {
|
||||
const EVP_CIPHER *cipher = getCipher(length);
|
||||
return (cipher != NULL) && rekey(cipher, key, length);
|
||||
}
|
||||
|
||||
virtual bool randomKey(int length) {
|
||||
const EVP_CIPHER *cipher = getCipher(length);
|
||||
return (cipher != NULL) && rekey(cipher, length);
|
||||
}
|
||||
|
||||
static const EVP_CIPHER *getCipher(int keyLength) {
|
||||
switch(keyLength * 8)
|
||||
{
|
||||
case 128: return EVP_aes_128_xts();
|
||||
case 256: return EVP_aes_256_xts();
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static Properties GetProperties() {
|
||||
Properties props;
|
||||
props.keySize = AesXtsKeyRange;
|
||||
props.cipher = "AES";
|
||||
props.mode = "XTS";
|
||||
props.library = "OpenSSL";
|
||||
return props;
|
||||
}
|
||||
};
|
||||
REGISTER_CLASS(AesXtsBlockCipher, BlockCipher);
|
||||
#endif
|
||||
|
||||
class Sha1HMac : public MessageAuthenticationCode {
|
||||
public:
|
||||
Sha1HMac() {}
|
||||
virtual ~Sha1HMac() {
|
||||
HMAC_CTX_cleanup(&ctx);
|
||||
}
|
||||
|
||||
virtual int outputSize() const {
|
||||
return 20; // 160 bit.
|
||||
}
|
||||
|
||||
virtual bool setKey(const byte *key, int keyLength) {
|
||||
HMAC_CTX_init(&ctx);
|
||||
HMAC_Init_ex(&ctx, key, keyLength, EVP_sha1(), 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool randomKey(int keyLength) {
|
||||
SecureMem key(keyLength);
|
||||
|
||||
return OpenSSLCipher::randomize(key.data, key.size)
|
||||
&& setKey(key.data, key.size);
|
||||
}
|
||||
|
||||
virtual void reset() {
|
||||
HMAC_Init_ex(&ctx, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
virtual bool update(const byte *in, int length) {
|
||||
HMAC_Update(&ctx, in, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool write(byte *out) {
|
||||
unsigned int outSize = 0;
|
||||
HMAC_Final(&ctx, (unsigned char *)out, &outSize);
|
||||
CHECK_EQ(outputSize(), outSize) << "Invalid HMAC output size";
|
||||
return true;
|
||||
}
|
||||
|
||||
static Properties GetProperties() {
|
||||
Properties props;
|
||||
props.blockSize = 20;
|
||||
props.hashFunction = "SHA-1";
|
||||
props.mode = "HMAC";
|
||||
props.library = "OpenSSL";
|
||||
return props;
|
||||
}
|
||||
private:
|
||||
HMAC_CTX ctx;
|
||||
};
|
||||
REGISTER_CLASS(Sha1HMac, MessageAuthenticationCode);
|
||||
|
||||
|
||||
class PbkdfPkcs5HmacSha1 : public PBKDF {
|
||||
public:
|
||||
PbkdfPkcs5HmacSha1() {}
|
||||
virtual ~PbkdfPkcs5HmacSha1() {}
|
||||
|
||||
virtual bool makeKey(const char *password, int passwordLength,
|
||||
const byte *salt, int saltLength,
|
||||
int numIterations,
|
||||
byte *outKey, int keyLength) const {
|
||||
return PKCS5_PBKDF2_HMAC_SHA1(
|
||||
password, passwordLength,
|
||||
const_cast<byte *>(salt), saltLength,
|
||||
numIterations, keyLength, outKey) == 1;
|
||||
}
|
||||
|
||||
static Properties GetProperties() {
|
||||
Properties props;
|
||||
props.mode = "PKCS5_PBKDF2_HMAC_SHA1";
|
||||
props.library = "OpenSSL";
|
||||
return props;
|
||||
}
|
||||
};
|
||||
REGISTER_CLASS(PbkdfPkcs5HmacSha1, PBKDF);
|
||||
|
||||
|
||||
unsigned long pthreads_thread_id()
|
||||
{
|
||||
return (unsigned long)pthread_self();
|
||||
@ -73,7 +416,7 @@ void pthreads_locking_cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
void openssl_init(bool threaded)
|
||||
void OpenSSL::init(bool threaded)
|
||||
{
|
||||
// initialize the SSL library
|
||||
SSL_load_error_strings();
|
||||
@ -99,7 +442,7 @@ void openssl_init(bool threaded)
|
||||
}
|
||||
}
|
||||
|
||||
void openssl_shutdown(bool threaded)
|
||||
void OpenSSL::shutdown(bool threaded)
|
||||
{
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
ENGINE_cleanup();
|
||||
@ -109,4 +452,10 @@ void openssl_shutdown(bool threaded)
|
||||
pthreads_locking_cleanup();
|
||||
}
|
||||
|
||||
void OpenSSL::registerCiphers()
|
||||
{
|
||||
// Nothing required.. Just need to reference this code block to get static
|
||||
// initializers.
|
||||
}
|
||||
|
||||
} // namespace encfs
|
||||
|
@ -21,10 +21,17 @@
|
||||
#ifndef _openssl_incl_
|
||||
#define _openssl_incl_
|
||||
|
||||
#include "base/Registry.h"
|
||||
|
||||
namespace encfs {
|
||||
|
||||
void openssl_init(bool isThreaded);
|
||||
void openssl_shutdown(bool isThreaded);
|
||||
class OpenSSL {
|
||||
public:
|
||||
static void init(bool isThreaded);
|
||||
static void shutdown(bool isThreaded);
|
||||
|
||||
static void registerCiphers();
|
||||
};
|
||||
|
||||
} // namespace encfs
|
||||
|
||||
|
30
cipher/testing.cpp
Normal file
30
cipher/testing.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "cipher/testing.h"
|
||||
|
||||
namespace encfs {
|
||||
|
||||
std::string stringToHex(const byte *data, int len) {
|
||||
static const char lookup[] = "0123456789abcdef";
|
||||
|
||||
std::string out;
|
||||
out.reserve(2 * len);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
unsigned int c = (unsigned int)data[i] & 0xff;
|
||||
int first = (unsigned int)c >> 4;
|
||||
int second = (unsigned int)c & 15;
|
||||
|
||||
out.push_back(lookup[first]);
|
||||
out.push_back(lookup[second]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
} // namespace encfs
|
||||
|
36
cipher/testing.h
Normal file
36
cipher/testing.h
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
/*****************************************************************************
|
||||
* 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 _CIPHER_TESTING_incl_
|
||||
#define _CIPHER_TESTING_incl_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/types.h"
|
||||
|
||||
namespace encfs {
|
||||
|
||||
std::string stringToHex(const byte *data, int len);
|
||||
|
||||
} // namespace encfs
|
||||
|
||||
#endif
|
||||
|
@ -8,10 +8,6 @@ link_directories (${Encfs_BINARY_DIR}/cipher)
|
||||
include_directories (${Encfs_SOURCE_DIR}/fs)
|
||||
link_directories (${Encfs_BINARY_DIR}/fs)
|
||||
|
||||
# TODO: move FUSE code into encfs-fs.
|
||||
find_package (FUSE REQUIRED)
|
||||
include_directories (${FUSE_INCLUDE_DIR})
|
||||
|
||||
include_directories (${CMAKE_BINARY_DIR}/base)
|
||||
|
||||
add_executable (encfs
|
||||
|
@ -578,7 +578,7 @@ int main(int argc, char *argv[])
|
||||
// encfs_oper.fsetattr_x
|
||||
#endif
|
||||
|
||||
openssl_init( encfsArgs->isThreaded );
|
||||
OpenSSL::init( encfsArgs->isThreaded );
|
||||
|
||||
// context is not a smart pointer because it will live for the life of
|
||||
// the filesystem.
|
||||
@ -671,7 +671,7 @@ int main(int argc, char *argv[])
|
||||
ctx->setRoot( shared_ptr<DirNode>() );
|
||||
|
||||
MemoryPool::destroyAll();
|
||||
openssl_shutdown( encfsArgs->isThreaded );
|
||||
OpenSSL::shutdown( encfsArgs->isThreaded );
|
||||
|
||||
return returnCode;
|
||||
}
|
||||
|
@ -1,12 +1,6 @@
|
||||
find_package (FUSE REQUIRED)
|
||||
include_directories (${FUSE_INCLUDE_DIR})
|
||||
protobuf_generate_cpp (PROTO_SRCS PROTO_HDRS ${PROJECT_SOURCE_DIR}/protos/fsconfig.proto)
|
||||
|
||||
protobuf_generate_cpp (PROTO_SRCS PROTO_HDRS ${Encfs_SOURCE_DIR}/protos/fsconfig.proto)
|
||||
|
||||
enable_testing ()
|
||||
find_package (GTest)
|
||||
|
||||
include_directories (${Encfs_BINARY_DIR}/base)
|
||||
include_directories (${PROJECT_BINARY_DIR}/base)
|
||||
add_library (encfs-fs
|
||||
encfs.cpp
|
||||
Context.cpp
|
||||
@ -32,11 +26,11 @@ target_link_libraries (encfs-fs
|
||||
|
||||
# Unit tests are optional, depends on libgtest (Google's C++ test framework).
|
||||
if (GTEST_FOUND)
|
||||
link_directories (${Encfs_BINARY_DIR}/base)
|
||||
link_directories (${Encfs_BINARY_DIR}/cipher)
|
||||
link_directories (${PROJECT_BINARY_DIR}/base)
|
||||
link_directories (${PROJECT_BINARY_DIR}/cipher)
|
||||
|
||||
include_directories (${GTEST_INCLUDE_DIR})
|
||||
add_executable (unittests
|
||||
add_executable (fs-tests
|
||||
MemBlockFileIO.cpp
|
||||
MemFileIO.cpp
|
||||
testing.cpp
|
||||
@ -44,7 +38,7 @@ if (GTEST_FOUND)
|
||||
test_BlockIO.cpp
|
||||
)
|
||||
|
||||
target_link_libraries (unittests
|
||||
target_link_libraries (fs-tests
|
||||
${GTEST_BOTH_LIBRARIES}
|
||||
encfs-fs
|
||||
encfs-cipher
|
||||
@ -52,8 +46,6 @@ if (GTEST_FOUND)
|
||||
${GLOG_LIBRARIES}
|
||||
)
|
||||
|
||||
add_test (UnitTests unittests)
|
||||
GTEST_ADD_TESTS (unittests "${UnitTestArgs}" test_IO.cpp test_BlockIO.cpp)
|
||||
add_custom_target (test COMMAND ${CMAKE_CTEST_COMMAND} DEPENDS unittests)
|
||||
|
||||
add_test (FSTests fs-tests)
|
||||
GTEST_ADD_TESTS (fs-tests "${FSTestArgs}" test_IO.cpp test_BlockIO.cpp)
|
||||
endif (GTEST_FOUND)
|
||||
|
@ -1349,7 +1349,7 @@ std::string readPassword( int FD )
|
||||
|
||||
if(rdSize > 0)
|
||||
{
|
||||
result.append( buf->data, rdSize );
|
||||
result.append( (char*)buf->data, rdSize );
|
||||
} else
|
||||
break;
|
||||
}
|
||||
@ -1436,7 +1436,7 @@ SecureMem *passwordFromProgram(const std::string &passProg,
|
||||
|
||||
SecureMem *result = new SecureMem(password.length()+1);
|
||||
if (result)
|
||||
strncpy(result->data, password.c_str(), result->size);
|
||||
strncpy((char *)result->data, password.c_str(), result->size);
|
||||
password.assign(password.length(), '\0');
|
||||
|
||||
return result;
|
||||
@ -1446,11 +1446,11 @@ SecureMem *passwordFromStdin()
|
||||
{
|
||||
SecureMem *buf = new SecureMem(MaxPassBuf);
|
||||
|
||||
char *res = fgets( buf->data, buf->size, stdin );
|
||||
char *res = fgets( (char *)buf->data, buf->size, stdin );
|
||||
if (res)
|
||||
{
|
||||
// Kill the trailing newline.
|
||||
int last = strnlen(buf->data, buf->size);
|
||||
int last = strnlen((char *)buf->data, buf->size);
|
||||
if (last > 0 && buf->data[last-1] == '\n')
|
||||
buf->data[ last-1 ] = '\0';
|
||||
}
|
||||
@ -1464,7 +1464,7 @@ SecureMem *passwordFromPrompt()
|
||||
|
||||
// xgroup(common)
|
||||
char *res = readpassphrase( _("EncFS Password: "),
|
||||
buf->data, buf->size-1, RPP_ECHO_OFF );
|
||||
(char *)buf->data, buf->size-1, RPP_ECHO_OFF );
|
||||
if (!res)
|
||||
{
|
||||
delete buf;
|
||||
@ -1483,12 +1483,13 @@ SecureMem *passwordFromPrompts()
|
||||
{
|
||||
// xgroup(common)
|
||||
char *res1 = readpassphrase(_("New Encfs Password: "),
|
||||
buf->data, buf->size-1, RPP_ECHO_OFF);
|
||||
(char *)buf->data, buf->size-1, RPP_ECHO_OFF);
|
||||
// xgroup(common)
|
||||
char *res2 = readpassphrase(_("Verify Encfs Password: "),
|
||||
buf2->data, buf2->size-1, RPP_ECHO_OFF);
|
||||
(char *)buf2->data, buf2->size-1, RPP_ECHO_OFF);
|
||||
|
||||
if(res1 && res2 && !strncmp(buf->data, buf2->data, MaxPassBuf))
|
||||
if(res1 && res2
|
||||
&& !strncmp((char*)buf->data, (char*)buf2->data, MaxPassBuf))
|
||||
{
|
||||
break;
|
||||
} else
|
||||
@ -1514,7 +1515,8 @@ CipherKey getUserKey(const EncfsConfig &config, bool useStdin)
|
||||
|
||||
if (password)
|
||||
{
|
||||
userKey = decryptKey(config, password->data, strlen(password->data));
|
||||
userKey = decryptKey(config, (char*)password->data,
|
||||
strlen((char*)password->data));
|
||||
delete password;
|
||||
}
|
||||
|
||||
@ -1529,7 +1531,8 @@ CipherKey getUserKey( const EncfsConfig &config, const std::string &passProg,
|
||||
|
||||
if (password)
|
||||
{
|
||||
result = decryptKey(config, password->data, strlen(password->data));
|
||||
result = decryptKey(config, (char*)password->data,
|
||||
strlen((char*)password->data));
|
||||
delete password;
|
||||
}
|
||||
|
||||
@ -1552,7 +1555,8 @@ CipherKey getNewUserKey(EncfsConfig &config,
|
||||
|
||||
if (password)
|
||||
{
|
||||
result = makeNewKey(config, password->data, strlen(password->data));
|
||||
result = makeNewKey(config, (char*)password->data,
|
||||
strlen((char*)password->data));
|
||||
delete password;
|
||||
}
|
||||
|
||||
|
@ -8,10 +8,6 @@ link_directories (${Encfs_BINARY_DIR}/cipher)
|
||||
include_directories (${Encfs_SOURCE_DIR}/fs)
|
||||
link_directories (${Encfs_BINARY_DIR}/fs)
|
||||
|
||||
# TODO: move FUSE code into encfs-fs.
|
||||
find_package (FUSE REQUIRED)
|
||||
include_directories (${FUSE_INCLUDE_DIR})
|
||||
|
||||
include_directories (${CMAKE_BINARY_DIR}/base)
|
||||
|
||||
|
||||
|
@ -24,6 +24,9 @@
|
||||
#include "base/i18n.h"
|
||||
|
||||
#include "cipher/Cipher.h"
|
||||
#include "cipher/BlockCipher.h"
|
||||
#include "cipher/MAC.h"
|
||||
#include "cipher/StreamCipher.h"
|
||||
|
||||
#include "fs/FileUtils.h"
|
||||
#include "fs/Context.h"
|
||||
@ -35,6 +38,7 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <list>
|
||||
|
||||
#include <getopt.h>
|
||||
#include <sys/types.h>
|
||||
@ -52,6 +56,7 @@ using namespace encfs;
|
||||
|
||||
static int showInfo( int argc, char **argv );
|
||||
static int showVersion( int argc, char **argv );
|
||||
static int showCiphers( int argc, char **argv );
|
||||
static int chpasswd( int argc, char **argv );
|
||||
static int chpasswdAutomaticly( int argc, char **argv );
|
||||
static int cmd_ls( int argc, char **argv );
|
||||
@ -101,6 +106,9 @@ struct CommandOpts
|
||||
{"export", 2, 2, cmd_export, "(root dir) path",
|
||||
// xgroup(usage)
|
||||
gettext_noop(" -- decrypts a volume and writes results to path")},
|
||||
{"--ciphers", 0, 0, showCiphers, "",
|
||||
// xgroup(usage)
|
||||
gettext_noop(" -- show available ciphers")},
|
||||
{"--version", 0, 0, showVersion, "",
|
||||
// xgroup(usage)
|
||||
gettext_noop(" -- print version number and exit")},
|
||||
@ -140,7 +148,7 @@ static bool checkDir( string &rootDir )
|
||||
{
|
||||
if( !isDirectory( rootDir.c_str() ))
|
||||
{
|
||||
cerr << autosprintf(_("directory %s does not exist.\n"),
|
||||
cout << autosprintf(_("directory %s does not exist.\n"),
|
||||
rootDir.c_str());
|
||||
return false;
|
||||
}
|
||||
@ -155,11 +163,45 @@ static int showVersion( int argc, char **argv )
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
// xgroup(usage)
|
||||
cerr << autosprintf(_("encfsctl version %s"), VERSION) << "\n";
|
||||
cout << autosprintf(_("encfsctl version %s"), VERSION) << "\n";
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int showCiphers( int argc, char **argv )
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
list<string> names = BlockCipher::GetRegistry().GetAll();
|
||||
for (const string& name : names) {
|
||||
auto props = BlockCipher::GetRegistry().GetProperties(name.c_str());
|
||||
cout << _("Implementation: ") << name << "\n";
|
||||
cout << "\t" << _("Block cipher: ") << props->cipher << " / " << props->mode
|
||||
<< " ( " << autosprintf(_("via %s"), props->library.c_str()) << " )\n";
|
||||
cout << "\t" << _("Key Sizes: ") << props->keySize << "\n";
|
||||
}
|
||||
|
||||
names = StreamCipher::GetRegistry().GetAll();
|
||||
for (const string& name : names) {
|
||||
auto props = StreamCipher::GetRegistry().GetProperties(name.c_str());
|
||||
cout << _("Implementation: ") << name << "\n";
|
||||
cout << "\t" << _("Stream cipher: ") << props->cipher << " / " << props->mode
|
||||
<< " ( " << autosprintf(_("via %s"), props->library.c_str()) << " )\n";
|
||||
cout << "\t" << _("Key Sizes: ") << props->keySize << "\n";
|
||||
}
|
||||
|
||||
names = MessageAuthenticationCode::GetRegistry().GetAll();
|
||||
for (const string& name : names) {
|
||||
auto props = MessageAuthenticationCode::GetRegistry()
|
||||
.GetProperties(name.c_str());
|
||||
cout << _("Implementation: ") << name << "\n";
|
||||
cout << "\t" << _("HMAC: ") << props->hashFunction << " / " << props->mode
|
||||
<< " ( " << autosprintf(_("via %s"), props->library.c_str()) << " )\n";
|
||||
cout << "\t" << _("Block size: ") << props->blockSize << "\n";
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int showInfo( int argc, char **argv )
|
||||
{
|
||||
(void)argc;
|
||||
@ -676,7 +718,7 @@ static int cmd_showcruft( int argc, char **argv )
|
||||
|
||||
int filesFound = showcruft( rootInfo, "/" );
|
||||
|
||||
cerr << autosprintf("Found %i invalid file(s).", filesFound) << "\n";
|
||||
cout << autosprintf("Found %i invalid file(s).", filesFound) << "\n";
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user