mirror of
https://github.com/vgough/encfs.git
synced 2024-11-22 07:53:31 +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}
|
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
|
||||||
"${CMAKE_SOURCE_DIR}/CMakeModules/")
|
"${CMAKE_SOURCE_DIR}/CMakeModules/")
|
||||||
|
|
||||||
|
# Tweak compiler flags.
|
||||||
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall")
|
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_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})
|
||||||
@ -23,6 +43,7 @@ set (CPACK_SOURCE_IGNORE_FILES
|
|||||||
"/build/")
|
"/build/")
|
||||||
include (CPack)
|
include (CPack)
|
||||||
|
|
||||||
|
# Check for external files.
|
||||||
include (CheckIncludeFileCXX)
|
include (CheckIncludeFileCXX)
|
||||||
check_include_file_cxx (attr/xattr.h HAVE_ATTR_XATTR_H)
|
check_include_file_cxx (attr/xattr.h HAVE_ATTR_XATTR_H)
|
||||||
check_include_file_cxx (sys/xattr.h HAVE_SYS_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>
|
#include <sys/xattr.h>
|
||||||
int main() { getxattr(0,0,0,0,0,0); return 1; } " XATTR_ADD_OPT)
|
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)
|
# Libraries or programs used for multiple modules.
|
||||||
if (APPLE)
|
|
||||||
add_definitions (-D__FreeBSD__=10)
|
|
||||||
endif (APPLE)
|
|
||||||
|
|
||||||
find_package (Protobuf REQUIRED)
|
find_package (Protobuf REQUIRED)
|
||||||
include_directories (${PROTOBUF_INCLUDE_DIR})
|
include_directories (${PROTOBUF_INCLUDE_DIR})
|
||||||
|
|
||||||
@ -58,9 +75,16 @@ include_directories (${GLOG_INCLUDE_DIRS})
|
|||||||
|
|
||||||
find_program (POD2MAN pod2man)
|
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_BINARY_DIR})
|
||||||
include_directories (${Encfs_SOURCE_DIR})
|
include_directories (${Encfs_SOURCE_DIR})
|
||||||
|
|
||||||
|
# Subdirectories.
|
||||||
add_subdirectory(base)
|
add_subdirectory(base)
|
||||||
add_subdirectory(cipher)
|
add_subdirectory(cipher)
|
||||||
add_subdirectory(fs)
|
add_subdirectory(fs)
|
||||||
@ -68,3 +92,10 @@ add_subdirectory(encfs)
|
|||||||
add_subdirectory(util)
|
add_subdirectory(util)
|
||||||
add_subdirectory(po)
|
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
|
ConfigVar.cpp
|
||||||
Error.cpp
|
Error.cpp
|
||||||
Interface.cpp
|
Interface.cpp
|
||||||
|
Range.h
|
||||||
|
Registry.h
|
||||||
XmlReader.cpp
|
XmlReader.cpp
|
||||||
${PROTO_SRCS}
|
${PROTO_SRCS}
|
||||||
${PROTO_HDRS}
|
${PROTO_HDRS}
|
||||||
|
14
base/Range.h
14
base/Range.h
@ -21,6 +21,8 @@
|
|||||||
#ifndef _Range_incl_
|
#ifndef _Range_incl_
|
||||||
#define _Range_incl_
|
#define _Range_incl_
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
namespace encfs {
|
namespace encfs {
|
||||||
|
|
||||||
class Range
|
class Range
|
||||||
@ -42,6 +44,18 @@ public:
|
|||||||
int inc() const;
|
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)
|
inline Range::Range(int minMax)
|
||||||
{
|
{
|
||||||
this->minVal = 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)
|
link_directories (${Encfs_BINARY_DIR}/base)
|
||||||
|
|
||||||
enable_testing ()
|
|
||||||
find_package (GTest REQUIRED)
|
|
||||||
|
|
||||||
add_library (encfs-cipher
|
add_library (encfs-cipher
|
||||||
readpassphrase.cpp
|
|
||||||
BlockCipher.cpp
|
BlockCipher.cpp
|
||||||
Cipher.cpp
|
Cipher.cpp
|
||||||
CipherKey.cpp
|
CipherKey.cpp
|
||||||
|
MAC.cpp
|
||||||
MemoryPool.cpp
|
MemoryPool.cpp
|
||||||
NullCipher.cpp
|
NullCipher.cpp
|
||||||
openssl.cpp
|
openssl.cpp
|
||||||
|
PBKDF.cpp
|
||||||
|
readpassphrase.cpp
|
||||||
SSL_Cipher.cpp
|
SSL_Cipher.cpp
|
||||||
|
StreamCipher.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries (encfs-cipher
|
target_link_libraries (encfs-cipher
|
||||||
${OPENSSL_LIBRARIES}
|
${OPENSSL_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
#include_directories (${GTEST_INCLUDE_DIR})
|
if (GTEST_FOUND)
|
||||||
#add_executable (unittests
|
link_directories (${PROJECT_BINARY_DIR}/base)
|
||||||
#MemBlockFileIO.cpp
|
include_directories (${GTEST_INCLUDE_DIR})
|
||||||
#MemFileIO.cpp
|
|
||||||
#testing.cpp
|
|
||||||
#test_IO.cpp
|
|
||||||
#test_BlockIO.cpp
|
|
||||||
#)
|
|
||||||
|
|
||||||
#target_link_libraries (unittests
|
file (GLOB TEST_FILES "*_test.cpp")
|
||||||
#${GTEST_BOTH_LIBRARIES}
|
|
||||||
#encfs-fs
|
|
||||||
#encfs-base
|
|
||||||
#${GLOG_LIBRARIES}
|
|
||||||
#)
|
|
||||||
|
|
||||||
#add_test (UnitTests unittests)
|
add_executable (cipher-tests
|
||||||
#GTEST_ADD_TESTS (unittests "${UnitTestArgs}" test_IO.cpp test_BlockIO.cpp)
|
testing.cpp
|
||||||
#add_custom_target (test COMMAND ${CMAKE_CTEST_COMMAND} DEPENDS unittests)
|
${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)
|
SecureMem::SecureMem(int len)
|
||||||
{
|
{
|
||||||
rAssert(len > 0);
|
rAssert(len > 0);
|
||||||
data = (char *)OPENSSL_malloc(len);
|
data = (byte *)OPENSSL_malloc(len);
|
||||||
if (data)
|
if (data)
|
||||||
{
|
{
|
||||||
size = len;
|
size = len;
|
||||||
|
@ -29,7 +29,8 @@ namespace encfs {
|
|||||||
Memory Pool for fixed sized objects.
|
Memory Pool for fixed sized objects.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
MemBlock mb( size );
|
MemBlock mb;
|
||||||
|
mb.allocate( size );
|
||||||
// do things with storage in mb.data
|
// do things with storage in mb.data
|
||||||
byte *buffer = mb.data;
|
byte *buffer = mb.data;
|
||||||
|
|
||||||
@ -59,7 +60,7 @@ namespace MemoryPool
|
|||||||
struct SecureMem
|
struct SecureMem
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
char *data;
|
byte *data;
|
||||||
|
|
||||||
SecureMem(int len);
|
SecureMem(int len);
|
||||||
~SecureMem();
|
~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/SSL_Cipher.h"
|
||||||
#include "cipher/MemoryPool.h"
|
#include "cipher/MemoryPool.h"
|
||||||
|
#include "cipher/BlockCipher.h"
|
||||||
#include "base/Error.h"
|
#include "base/Error.h"
|
||||||
#include "base/Mutex.h"
|
#include "base/Mutex.h"
|
||||||
#include "base/Range.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
|
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,
|
const byte *data, int dataLen,
|
||||||
unsigned int rounds, byte *key, byte *iv)
|
unsigned int rounds, byte *key, byte *iv)
|
||||||
{
|
{
|
||||||
if( data == NULL || dataLen == 0 )
|
if( data == NULL || dataLen == 0 )
|
||||||
return 0; // OpenSSL returns nkey here, but why? It is a failure..
|
return 0; // OpenSSL returns nkey here, but why? It is a failure..
|
||||||
|
|
||||||
byte mdBuf[ EVP_MAX_MD_SIZE ];
|
byte mdBuf[ EVP_MAX_MD_SIZE ];
|
||||||
unsigned int mds=0;
|
unsigned int mds=0;
|
||||||
int addmd =0;
|
int addmd =0;
|
||||||
@ -110,7 +111,7 @@ int BytesToKey( int keyLen, int ivLen, const EVP_MD *md,
|
|||||||
{
|
{
|
||||||
memcpy( iv, mdBuf+offset, toCopy );
|
memcpy( iv, mdBuf+offset, toCopy );
|
||||||
iv += toCopy;
|
iv += toCopy;
|
||||||
niv -= toCopy;
|
niv -= toCopy;
|
||||||
offset += toCopy;
|
offset += toCopy;
|
||||||
}
|
}
|
||||||
if((nkey == 0) && (niv == 0)) break;
|
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,
|
int SSL_Cipher::TimedPBKDF2(const char *pass, int passlen,
|
||||||
const byte *salt, int saltlen,
|
const byte *salt, int saltlen,
|
||||||
int keylen, byte *out,
|
int keylen, byte *out,
|
||||||
long desiredPDFTime)
|
long desiredPDFTime)
|
||||||
{
|
{
|
||||||
int iter = 1000;
|
int iter = 1000;
|
||||||
timeval start, end;
|
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 *blockCipher = EVP_bf_cbc();
|
||||||
const EVP_CIPHER *streamCipher = EVP_bf_cfb();
|
const EVP_CIPHER *streamCipher = EVP_bf_cfb();
|
||||||
|
|
||||||
return shared_ptr<Cipher>( new SSL_Cipher(iface, BlowfishInterface,
|
return shared_ptr<Cipher>(
|
||||||
blockCipher, streamCipher, keyLen / 8) );
|
new SSL_Cipher(iface, BlowfishInterface,
|
||||||
|
blockCipher, streamCipher, keyLen / 8) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool BF_Cipher_registered = Cipher::Register(
|
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(
|
static bool AES_Cipher_registered = Cipher::Register(
|
||||||
"AES", "16 byte block cipher",
|
"AES", "16 byte block cipher",
|
||||||
AESInterface, AESKeyRange, AESBlockRange, NewAESCipher, true);
|
AESInterface, AESKeyRange, AESBlockRange, NewAESCipher, true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_EVP_AES_XTS)
|
#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(
|
static bool AES_XTS_Cipher_registered = Cipher::Register(
|
||||||
"AES_XTS", "Tweakable wide-block cipher",
|
"AES_XTS", "Tweakable wide-block cipher",
|
||||||
AesXtsInterface, AesXtsKeyRange, AesXtsBlockRange, NewAesXtsCipher, false);
|
AesXtsInterface, AesXtsKeyRange, AesXtsBlockRange, NewAesXtsCipher, false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class SSLKey : public AbstractCipherKey
|
class SSLKey : public AbstractCipherKey
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
|
|
||||||
unsigned int keySize; // in bytes
|
unsigned int keySize; // in bytes
|
||||||
unsigned int ivLength;
|
unsigned int ivLength;
|
||||||
|
|
||||||
// key data is first _keySize bytes,
|
// key data is first _keySize bytes,
|
||||||
// followed by iv of _ivLength bytes,
|
// followed by iv of _ivLength bytes,
|
||||||
SecureMem buf;
|
SecureMem buf;
|
||||||
|
|
||||||
EVP_CIPHER_CTX block_enc;
|
EVP_CIPHER_CTX block_enc;
|
||||||
EVP_CIPHER_CTX block_dec;
|
EVP_CIPHER_CTX block_dec;
|
||||||
EVP_CIPHER_CTX stream_enc;
|
EVP_CIPHER_CTX stream_enc;
|
||||||
EVP_CIPHER_CTX stream_dec;
|
EVP_CIPHER_CTX stream_dec;
|
||||||
|
|
||||||
HMAC_CTX mac_ctx;
|
HMAC_CTX mac_ctx;
|
||||||
|
|
||||||
SSLKey(int keySize, int ivLength);
|
SSLKey(int keySize, int ivLength);
|
||||||
~SSLKey();
|
~SSLKey();
|
||||||
};
|
};
|
||||||
|
|
||||||
SSLKey::SSLKey(int keySize_, int ivLength_)
|
SSLKey::SSLKey(int keySize_, int ivLength_)
|
||||||
: buf(keySize_ + ivLength_)
|
: buf(keySize_ + ivLength_)
|
||||||
{
|
{
|
||||||
rAssert(keySize_ >= 8);
|
rAssert(keySize_ >= 8);
|
||||||
rAssert(ivLength_ >= 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,
|
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 );
|
Lock lock( key->mutex );
|
||||||
// initialize the cipher context once so that we don't have to do it for
|
// 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_,
|
SSL_Cipher::SSL_Cipher(const Interface &iface_,
|
||||||
const Interface &realIface_,
|
const Interface &realIface_,
|
||||||
const EVP_CIPHER *blockCipher,
|
const EVP_CIPHER *blockCipher,
|
||||||
const EVP_CIPHER *streamCipher,
|
const EVP_CIPHER *streamCipher,
|
||||||
int keySize_)
|
int keySize_)
|
||||||
{
|
{
|
||||||
this->iface = iface_;
|
this->iface = iface_;
|
||||||
this->realIface = realIface_;
|
this->realIface = realIface_;
|
||||||
@ -393,8 +395,8 @@ SSL_Cipher::SSL_Cipher(const Interface &iface_,
|
|||||||
rAssert(_ivLength <= _keySize);
|
rAssert(_ivLength <= _keySize);
|
||||||
|
|
||||||
VLOG(1) << "allocated cipher " << iface.name()
|
VLOG(1) << "allocated cipher " << iface.name()
|
||||||
<< ", keySize " << _keySize
|
<< ", keySize " << _keySize
|
||||||
<< ", ivlength " << _ivLength;
|
<< ", ivlength " << _ivLength;
|
||||||
|
|
||||||
// EVP_CIPHER_key_length isn't useful for variable-length ciphers like
|
// EVP_CIPHER_key_length isn't useful for variable-length ciphers like
|
||||||
// Blowfish. Version 1 relied upon it incorrectly.
|
// Blowfish. Version 1 relied upon it incorrectly.
|
||||||
@ -402,8 +404,8 @@ SSL_Cipher::SSL_Cipher(const Interface &iface_,
|
|||||||
&& iface.major() == 1)
|
&& iface.major() == 1)
|
||||||
{
|
{
|
||||||
LOG(WARNING) << "Running in backward compatibilty mode for 1.0 - \n"
|
LOG(WARNING) << "Running in backward compatibilty mode for 1.0 - \n"
|
||||||
<< "key is really " << EVP_CIPHER_key_length( _blockCipher ) * 8
|
<< "key is really " << EVP_CIPHER_key_length( _blockCipher ) * 8
|
||||||
<< " bits, not " << _keySize * 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
|
This algorithm must remain constant for backward compatibility, as this key
|
||||||
is used to encipher/decipher the master key.
|
is used to encipher/decipher the master key.
|
||||||
*/
|
*/
|
||||||
CipherKey SSL_Cipher::newKey(const char *password, int passwdLength,
|
CipherKey SSL_Cipher::newKey(const char *password, int passwdLength,
|
||||||
int &iterationCount, long desiredDuration,
|
int &iterationCount, long desiredDuration,
|
||||||
const byte *salt, int saltLen)
|
const byte *salt, int saltLen)
|
||||||
{
|
{
|
||||||
shared_ptr<SSLKey> key( new SSLKey( _keySize, _ivLength) );
|
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)
|
if(bytes != (int)_keySize)
|
||||||
{
|
{
|
||||||
LOG(WARNING) << "newKey: BytesToKey returned " << bytes
|
LOG(WARNING) << "newKey: BytesToKey returned " << bytes
|
||||||
<< ", expecting " << _keySize << " key bytes";
|
<< ", expecting " << _keySize << " key bytes";
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
@ -499,7 +501,7 @@ CipherKey SSL_Cipher::newKey(const char *password, int passwdLength)
|
|||||||
|
|
||||||
This algorithm can change at any time without affecting backward
|
This algorithm can change at any time without affecting backward
|
||||||
compatibility.
|
compatibility.
|
||||||
*/
|
*/
|
||||||
CipherKey SSL_Cipher::newRandomKey()
|
CipherKey SSL_Cipher::newRandomKey()
|
||||||
{
|
{
|
||||||
const int bufLen = MAX_KEYLENGTH;
|
const int bufLen = MAX_KEYLENGTH;
|
||||||
@ -531,11 +533,11 @@ CipherKey SSL_Cipher::newRandomKey()
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Compute a 64-bit check value for the data using HMAC.
|
Compute a 64-bit check value for the data using HMAC.
|
||||||
*/
|
*/
|
||||||
static uint64_t _checksum_64(SSLKey *key,
|
static uint64_t _checksum_64(SSLKey *key,
|
||||||
const byte *data,
|
const byte *data,
|
||||||
int dataLen,
|
int dataLen,
|
||||||
uint64_t *chainedIV)
|
uint64_t *chainedIV)
|
||||||
{
|
{
|
||||||
rAssert( dataLen > 0 );
|
rAssert( dataLen > 0 );
|
||||||
Lock lock( key->mutex );
|
Lock lock( key->mutex );
|
||||||
@ -576,7 +578,7 @@ static uint64_t _checksum_64(SSLKey *key,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool SSL_Cipher::randomize( byte *buf, int len,
|
bool SSL_Cipher::randomize( byte *buf, int len,
|
||||||
bool strongRandom ) const
|
bool strongRandom ) const
|
||||||
{
|
{
|
||||||
// to avoid warnings of uninitialized data from valgrind
|
// to avoid warnings of uninitialized data from valgrind
|
||||||
memset(buf, 0, len);
|
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,
|
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);
|
shared_ptr<SSLKey> mk = dynamic_pointer_cast<SSLKey>(key);
|
||||||
uint64_t tmp = _checksum_64( mk.get(), data, len, chainedIV );
|
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,
|
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);
|
shared_ptr<SSLKey> mk = dynamic_pointer_cast<SSLKey>(masterKey);
|
||||||
rAssert(mk->keySize == _keySize);
|
rAssert(mk->keySize == _keySize);
|
||||||
@ -638,8 +640,8 @@ CipherKey SSL_Cipher::readKey(const byte *data,
|
|||||||
if(checksum2 != checksum && checkKey)
|
if(checksum2 != checksum && checkKey)
|
||||||
{
|
{
|
||||||
VLOG(1) << "checksum mismatch: expected " << checksum
|
VLOG(1) << "checksum mismatch: expected " << checksum
|
||||||
<< ", got " << checksum2
|
<< ", got " << checksum2
|
||||||
<< "on decode of " << _keySize + _ivLength << " bytes";
|
<< "on decode of " << _keySize + _ivLength << " bytes";
|
||||||
OPENSSL_cleanse(tmpBuf, sizeof(tmpBuf));
|
OPENSSL_cleanse(tmpBuf, sizeof(tmpBuf));
|
||||||
return CipherKey();
|
return CipherKey();
|
||||||
}
|
}
|
||||||
@ -656,7 +658,7 @@ CipherKey SSL_Cipher::readKey(const byte *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SSL_Cipher::writeKey(const CipherKey &ckey, 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);
|
shared_ptr<SSLKey> key = dynamic_pointer_cast<SSLKey>(ckey);
|
||||||
rAssert(key->keySize == _keySize);
|
rAssert(key->keySize == _keySize);
|
||||||
@ -771,7 +773,7 @@ void SSL_Cipher::setIVec_old(byte *ivec,
|
|||||||
{
|
{
|
||||||
unsigned int var1 = 0x060a4011 * seed;
|
unsigned int var1 = 0x060a4011 * seed;
|
||||||
unsigned int var2 = 0x0221040d * (seed ^ 0xD3FEA11C);
|
unsigned int var2 = 0x0221040d * (seed ^ 0xD3FEA11C);
|
||||||
|
|
||||||
memcpy( ivec, IVData(key), _ivLength );
|
memcpy( ivec, IVData(key), _ivLength );
|
||||||
|
|
||||||
ivec[0] ^= (var1 >> 24) & 0xff;
|
ivec[0] ^= (var1 >> 24) & 0xff;
|
||||||
@ -861,7 +863,7 @@ bool SSL_Cipher::streamEncode(byte *buf, int size,
|
|||||||
|
|
||||||
dstLen += tmpLen;
|
dstLen += tmpLen;
|
||||||
LOG_IF(ERROR, dstLen != size) << "encoding " << size
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@ -897,7 +899,7 @@ bool SSL_Cipher::streamDecode(byte *buf, int size,
|
|||||||
|
|
||||||
dstLen += tmpLen;
|
dstLen += tmpLen;
|
||||||
LOG_IF(ERROR, dstLen != size) << "encoding " << size
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@ -928,7 +930,7 @@ bool SSL_Cipher::blockEncode(byte *buf, int size,
|
|||||||
dstLen += tmpLen;
|
dstLen += tmpLen;
|
||||||
|
|
||||||
LOG_IF(ERROR, dstLen != size) << "encoding " << size
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@ -958,7 +960,7 @@ bool SSL_Cipher::blockDecode(byte *buf, int size,
|
|||||||
dstLen += tmpLen;
|
dstLen += tmpLen;
|
||||||
|
|
||||||
LOG_IF(ERROR, dstLen != size) << "decoding " << size
|
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;
|
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>
|
* 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
|
* 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
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
@ -20,10 +20,16 @@
|
|||||||
|
|
||||||
#include "cipher/openssl.h"
|
#include "cipher/openssl.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <ctime>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
|
|
||||||
|
#include "base/config.h"
|
||||||
|
|
||||||
#define NO_DES
|
#define NO_DES
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
@ -31,8 +37,345 @@
|
|||||||
#include <openssl/engine.h>
|
#include <openssl/engine.h>
|
||||||
#endif
|
#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 {
|
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()
|
unsigned long pthreads_thread_id()
|
||||||
{
|
{
|
||||||
return (unsigned long)pthread_self();
|
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
|
// initialize the SSL library
|
||||||
SSL_load_error_strings();
|
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
|
#ifndef OPENSSL_NO_ENGINE
|
||||||
ENGINE_cleanup();
|
ENGINE_cleanup();
|
||||||
@ -109,4 +452,10 @@ void openssl_shutdown(bool threaded)
|
|||||||
pthreads_locking_cleanup();
|
pthreads_locking_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenSSL::registerCiphers()
|
||||||
|
{
|
||||||
|
// Nothing required.. Just need to reference this code block to get static
|
||||||
|
// initializers.
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace encfs
|
} // namespace encfs
|
||||||
|
@ -21,10 +21,17 @@
|
|||||||
#ifndef _openssl_incl_
|
#ifndef _openssl_incl_
|
||||||
#define _openssl_incl_
|
#define _openssl_incl_
|
||||||
|
|
||||||
|
#include "base/Registry.h"
|
||||||
|
|
||||||
namespace encfs {
|
namespace encfs {
|
||||||
|
|
||||||
void openssl_init(bool isThreaded);
|
class OpenSSL {
|
||||||
void openssl_shutdown(bool isThreaded);
|
public:
|
||||||
|
static void init(bool isThreaded);
|
||||||
|
static void shutdown(bool isThreaded);
|
||||||
|
|
||||||
|
static void registerCiphers();
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace encfs
|
} // 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)
|
include_directories (${Encfs_SOURCE_DIR}/fs)
|
||||||
link_directories (${Encfs_BINARY_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)
|
include_directories (${CMAKE_BINARY_DIR}/base)
|
||||||
|
|
||||||
add_executable (encfs
|
add_executable (encfs
|
||||||
|
@ -578,7 +578,7 @@ int main(int argc, char *argv[])
|
|||||||
// encfs_oper.fsetattr_x
|
// encfs_oper.fsetattr_x
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
openssl_init( encfsArgs->isThreaded );
|
OpenSSL::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.
|
||||||
@ -671,7 +671,7 @@ int main(int argc, char *argv[])
|
|||||||
ctx->setRoot( shared_ptr<DirNode>() );
|
ctx->setRoot( shared_ptr<DirNode>() );
|
||||||
|
|
||||||
MemoryPool::destroyAll();
|
MemoryPool::destroyAll();
|
||||||
openssl_shutdown( encfsArgs->isThreaded );
|
OpenSSL::shutdown( encfsArgs->isThreaded );
|
||||||
|
|
||||||
return returnCode;
|
return returnCode;
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
find_package (FUSE REQUIRED)
|
protobuf_generate_cpp (PROTO_SRCS PROTO_HDRS ${PROJECT_SOURCE_DIR}/protos/fsconfig.proto)
|
||||||
include_directories (${FUSE_INCLUDE_DIR})
|
|
||||||
|
|
||||||
protobuf_generate_cpp (PROTO_SRCS PROTO_HDRS ${Encfs_SOURCE_DIR}/protos/fsconfig.proto)
|
include_directories (${PROJECT_BINARY_DIR}/base)
|
||||||
|
|
||||||
enable_testing ()
|
|
||||||
find_package (GTest)
|
|
||||||
|
|
||||||
include_directories (${Encfs_BINARY_DIR}/base)
|
|
||||||
add_library (encfs-fs
|
add_library (encfs-fs
|
||||||
encfs.cpp
|
encfs.cpp
|
||||||
Context.cpp
|
Context.cpp
|
||||||
@ -32,11 +26,11 @@ target_link_libraries (encfs-fs
|
|||||||
|
|
||||||
# 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 (${Encfs_BINARY_DIR}/base)
|
link_directories (${PROJECT_BINARY_DIR}/base)
|
||||||
link_directories (${Encfs_BINARY_DIR}/cipher)
|
link_directories (${PROJECT_BINARY_DIR}/cipher)
|
||||||
|
|
||||||
include_directories (${GTEST_INCLUDE_DIR})
|
include_directories (${GTEST_INCLUDE_DIR})
|
||||||
add_executable (unittests
|
add_executable (fs-tests
|
||||||
MemBlockFileIO.cpp
|
MemBlockFileIO.cpp
|
||||||
MemFileIO.cpp
|
MemFileIO.cpp
|
||||||
testing.cpp
|
testing.cpp
|
||||||
@ -44,7 +38,7 @@ if (GTEST_FOUND)
|
|||||||
test_BlockIO.cpp
|
test_BlockIO.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries (unittests
|
target_link_libraries (fs-tests
|
||||||
${GTEST_BOTH_LIBRARIES}
|
${GTEST_BOTH_LIBRARIES}
|
||||||
encfs-fs
|
encfs-fs
|
||||||
encfs-cipher
|
encfs-cipher
|
||||||
@ -52,8 +46,6 @@ if (GTEST_FOUND)
|
|||||||
${GLOG_LIBRARIES}
|
${GLOG_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_test (UnitTests unittests)
|
add_test (FSTests fs-tests)
|
||||||
GTEST_ADD_TESTS (unittests "${UnitTestArgs}" test_IO.cpp test_BlockIO.cpp)
|
GTEST_ADD_TESTS (fs-tests "${FSTestArgs}" test_IO.cpp test_BlockIO.cpp)
|
||||||
add_custom_target (test COMMAND ${CMAKE_CTEST_COMMAND} DEPENDS unittests)
|
|
||||||
|
|
||||||
endif (GTEST_FOUND)
|
endif (GTEST_FOUND)
|
||||||
|
@ -1349,7 +1349,7 @@ std::string readPassword( int FD )
|
|||||||
|
|
||||||
if(rdSize > 0)
|
if(rdSize > 0)
|
||||||
{
|
{
|
||||||
result.append( buf->data, rdSize );
|
result.append( (char*)buf->data, rdSize );
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1436,7 +1436,7 @@ SecureMem *passwordFromProgram(const std::string &passProg,
|
|||||||
|
|
||||||
SecureMem *result = new SecureMem(password.length()+1);
|
SecureMem *result = new SecureMem(password.length()+1);
|
||||||
if (result)
|
if (result)
|
||||||
strncpy(result->data, password.c_str(), result->size);
|
strncpy((char *)result->data, password.c_str(), result->size);
|
||||||
password.assign(password.length(), '\0');
|
password.assign(password.length(), '\0');
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -1446,11 +1446,11 @@ SecureMem *passwordFromStdin()
|
|||||||
{
|
{
|
||||||
SecureMem *buf = new SecureMem(MaxPassBuf);
|
SecureMem *buf = new SecureMem(MaxPassBuf);
|
||||||
|
|
||||||
char *res = fgets( buf->data, buf->size, stdin );
|
char *res = fgets( (char *)buf->data, buf->size, stdin );
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
// Kill the trailing newline.
|
// 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')
|
if (last > 0 && buf->data[last-1] == '\n')
|
||||||
buf->data[ last-1 ] = '\0';
|
buf->data[ last-1 ] = '\0';
|
||||||
}
|
}
|
||||||
@ -1464,7 +1464,7 @@ SecureMem *passwordFromPrompt()
|
|||||||
|
|
||||||
// xgroup(common)
|
// xgroup(common)
|
||||||
char *res = readpassphrase( _("EncFS Password: "),
|
char *res = readpassphrase( _("EncFS Password: "),
|
||||||
buf->data, buf->size-1, RPP_ECHO_OFF );
|
(char *)buf->data, buf->size-1, RPP_ECHO_OFF );
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
delete buf;
|
delete buf;
|
||||||
@ -1483,12 +1483,13 @@ SecureMem *passwordFromPrompts()
|
|||||||
{
|
{
|
||||||
// xgroup(common)
|
// xgroup(common)
|
||||||
char *res1 = readpassphrase(_("New Encfs Password: "),
|
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)
|
// xgroup(common)
|
||||||
char *res2 = readpassphrase(_("Verify Encfs Password: "),
|
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;
|
break;
|
||||||
} else
|
} else
|
||||||
@ -1514,7 +1515,8 @@ CipherKey getUserKey(const EncfsConfig &config, bool useStdin)
|
|||||||
|
|
||||||
if (password)
|
if (password)
|
||||||
{
|
{
|
||||||
userKey = decryptKey(config, password->data, strlen(password->data));
|
userKey = decryptKey(config, (char*)password->data,
|
||||||
|
strlen((char*)password->data));
|
||||||
delete password;
|
delete password;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1529,7 +1531,8 @@ CipherKey getUserKey( const EncfsConfig &config, const std::string &passProg,
|
|||||||
|
|
||||||
if (password)
|
if (password)
|
||||||
{
|
{
|
||||||
result = decryptKey(config, password->data, strlen(password->data));
|
result = decryptKey(config, (char*)password->data,
|
||||||
|
strlen((char*)password->data));
|
||||||
delete password;
|
delete password;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1552,7 +1555,8 @@ CipherKey getNewUserKey(EncfsConfig &config,
|
|||||||
|
|
||||||
if (password)
|
if (password)
|
||||||
{
|
{
|
||||||
result = makeNewKey(config, password->data, strlen(password->data));
|
result = makeNewKey(config, (char*)password->data,
|
||||||
|
strlen((char*)password->data));
|
||||||
delete password;
|
delete password;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,10 +8,6 @@ link_directories (${Encfs_BINARY_DIR}/cipher)
|
|||||||
include_directories (${Encfs_SOURCE_DIR}/fs)
|
include_directories (${Encfs_SOURCE_DIR}/fs)
|
||||||
link_directories (${Encfs_BINARY_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)
|
include_directories (${CMAKE_BINARY_DIR}/base)
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
#include "base/i18n.h"
|
#include "base/i18n.h"
|
||||||
|
|
||||||
#include "cipher/Cipher.h"
|
#include "cipher/Cipher.h"
|
||||||
|
#include "cipher/BlockCipher.h"
|
||||||
|
#include "cipher/MAC.h"
|
||||||
|
#include "cipher/StreamCipher.h"
|
||||||
|
|
||||||
#include "fs/FileUtils.h"
|
#include "fs/FileUtils.h"
|
||||||
#include "fs/Context.h"
|
#include "fs/Context.h"
|
||||||
@ -35,6 +38,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -52,6 +56,7 @@ using namespace encfs;
|
|||||||
|
|
||||||
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 );
|
||||||
|
static int showCiphers( int argc, char **argv );
|
||||||
static int chpasswd( int argc, char **argv );
|
static int chpasswd( int argc, char **argv );
|
||||||
static int chpasswdAutomaticly( int argc, char **argv );
|
static int chpasswdAutomaticly( int argc, char **argv );
|
||||||
static int cmd_ls( 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",
|
{"export", 2, 2, cmd_export, "(root dir) path",
|
||||||
// xgroup(usage)
|
// xgroup(usage)
|
||||||
gettext_noop(" -- decrypts a volume and writes results to path")},
|
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, "",
|
{"--version", 0, 0, showVersion, "",
|
||||||
// xgroup(usage)
|
// xgroup(usage)
|
||||||
gettext_noop(" -- print version number and exit")},
|
gettext_noop(" -- print version number and exit")},
|
||||||
@ -140,7 +148,7 @@ static bool checkDir( string &rootDir )
|
|||||||
{
|
{
|
||||||
if( !isDirectory( rootDir.c_str() ))
|
if( !isDirectory( rootDir.c_str() ))
|
||||||
{
|
{
|
||||||
cerr << autosprintf(_("directory %s does not exist.\n"),
|
cout << autosprintf(_("directory %s does not exist.\n"),
|
||||||
rootDir.c_str());
|
rootDir.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -155,11 +163,45 @@ static int showVersion( int argc, char **argv )
|
|||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
// xgroup(usage)
|
// xgroup(usage)
|
||||||
cerr << autosprintf(_("encfsctl version %s"), VERSION) << "\n";
|
cout << autosprintf(_("encfsctl version %s"), VERSION) << "\n";
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
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 )
|
static int showInfo( int argc, char **argv )
|
||||||
{
|
{
|
||||||
(void)argc;
|
(void)argc;
|
||||||
@ -676,7 +718,7 @@ static int cmd_showcruft( int argc, char **argv )
|
|||||||
|
|
||||||
int filesFound = showcruft( rootInfo, "/" );
|
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;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user