mirror of
https://github.com/vgough/encfs.git
synced 2024-11-25 01:13:12 +01:00
begin adding Botan support.
implement pbkdf-hmac-sha256 module for Botan and CommonCrypto. git-svn-id: http://encfs.googlecode.com/svn/trunk@98 db9cf616-1c43-0410-9cb8-a902689de0d6
This commit is contained in:
parent
63c2d1c539
commit
95750d4539
@ -7,12 +7,16 @@ set (ENCFS_VERSION "${ENCFS_MAJOR}.${ENCFS_MINOR}")
|
||||
|
||||
option (BUILD_SHARED_LIBS "Build dynamic link libraries" OFF)
|
||||
|
||||
option (WITH_OPENSSL "WithOpenSSL" ON)
|
||||
option (WITH_OPENSSL "WithOpenSSL" OFF)
|
||||
option (WITH_COMMON_CRYPTO "WithCommonCrypto" OFF)
|
||||
option (WITH_BOTAN "WithBotan" ON)
|
||||
|
||||
if (WITH_COMMON_CRYPTO)
|
||||
if (WITH_BOTAN)
|
||||
set (WITH_COMMON_CRYPTO OFF)
|
||||
set (WITH_OPENSSL OFF)
|
||||
endif (WITH_COMMON_CRYPTO)
|
||||
elseif (WITH_COMMON_CRYPTO)
|
||||
set (WITH_OPENSSL OFF)
|
||||
endif (WITH_BOTAN)
|
||||
|
||||
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
|
||||
"${CMAKE_SOURCE_DIR}/CMakeModules/")
|
||||
@ -61,15 +65,8 @@ check_include_file_cxx (tr1/tuple HAVE_TR1_TUPLE)
|
||||
check_include_file_cxx (valgrind/valgrind.h HAVE_VALGRIND_VALGRIND_H)
|
||||
check_include_file_cxx (valgrind/memcheck.h HAVE_VALGRIND_MEMCHECK_H)
|
||||
|
||||
if (WITH_COMMON_CRYPTO)
|
||||
check_include_file_cxx (Security/SecRandom.h HAVE_SEC_RANDOM_H)
|
||||
endif (WITH_COMMON_CRYPTO)
|
||||
|
||||
if (WITH_OPENSSL)
|
||||
# TODO: move this to cipher directory.
|
||||
find_package (OpenSSL REQUIRED)
|
||||
include (OpenSSLTests)
|
||||
endif (WITH_OPENSSL)
|
||||
# Used with CommonCrypto
|
||||
check_include_file_cxx (Security/SecRandom.h HAVE_SEC_RANDOM_H)
|
||||
|
||||
# Check if xattr functions take extra argument.
|
||||
include (CheckCXXSourceCompiles)
|
||||
|
46
CMakeModules/FindBotan.cmake
Normal file
46
CMakeModules/FindBotan.cmake
Normal file
@ -0,0 +1,46 @@
|
||||
# - Try to find the Botan library
|
||||
#
|
||||
# Once done this will define
|
||||
#
|
||||
# BOTAN_FOUND - System has Botan
|
||||
# BOTAN_INCLUDE_DIR - The Botan include directory
|
||||
# BOTAN_LIBRARIES - The libraries needed to use Botan
|
||||
# BOTAN_DEFINITIONS - Compiler switches required for using Botan
|
||||
|
||||
IF (BOTAN_INCLUDE_DIR AND BOTAN_LIBRARY)
|
||||
# in cache already
|
||||
SET(Botan_FIND_QUIETLY TRUE)
|
||||
ENDIF (BOTAN_INCLUDE_DIR AND BOTAN_LIBRARY)
|
||||
|
||||
IF (NOT WIN32)
|
||||
# try using pkg-config to get the directories and then use these values
|
||||
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||
# also fills in BOTAN_DEFINITIONS, although that isn't normally useful
|
||||
FIND_PACKAGE(PkgConfig)
|
||||
PKG_SEARCH_MODULE(PC_BOTAN botan-1.10 botan-1.9 botan-1.8 botan)
|
||||
SET(BOTAN_DEFINITIONS ${PC_BOTAN_CFLAGS})
|
||||
ENDIF (NOT WIN32)
|
||||
|
||||
FIND_PATH(BOTAN_INCLUDE_DIR botan/botan.h
|
||||
HINTS
|
||||
${PC_BOTAN_INCLUDEDIR}
|
||||
${PC_BOTAN_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
FIND_LIBRARY(BOTAN_LIBRARY NAMES ${PC_BOTAN_LIBRARIES}
|
||||
HINTS
|
||||
${PC_BOTAN_LIBDIR}
|
||||
${PC_BOTAN_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
MARK_AS_ADVANCED(BOTAN_INCLUDE_DIR BOTAN_LIBRARY)
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set BOTAN_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Botan DEFAULT_MSG BOTAN_LIBRARY BOTAN_INCLUDE_DIR)
|
||||
|
||||
IF(BOTAN_FOUND)
|
||||
SET(BOTAN_LIBRARIES ${BOTAN_LIBRARY})
|
||||
SET(BOTAN_INCLUDE_DIRS ${BOTAN_INCLUDE_DIR})
|
||||
ENDIF()
|
@ -15,6 +15,7 @@
|
||||
|
||||
#cmakedefine WITH_OPENSSL
|
||||
#cmakedefine WITH_COMMON_CRYPTO
|
||||
#cmakedefine WITH_BOTAN
|
||||
#cmakedefine HAVE_SEC_RANDOM_H
|
||||
|
||||
#cmakedefine HAVE_EVP_BF
|
||||
|
@ -153,7 +153,7 @@ TEST(BlockEncryptionTest, BlockCipher) {
|
||||
Registry<BlockCipher> registry = BlockCipher::GetRegistry();
|
||||
|
||||
shared_ptr<PBKDF> pbkdf(
|
||||
PBKDF::GetRegistry().CreateForMatch(NAME_PKCS5_PBKDF2_HMAC_SHA1));
|
||||
PBKDF::GetRegistry().CreateForMatch(NAME_PBKDF2_HMAC_SHA1));
|
||||
|
||||
list<string> ciphers = registry.GetAll();
|
||||
for (const string &name : ciphers) {
|
||||
|
@ -6,9 +6,15 @@ if (WITH_COMMON_CRYPTO)
|
||||
set (EXTRA_LIBS ${SECURITY_FRAMEWORK})
|
||||
set (EXTRA_SOURCE CommonCrypto.cpp)
|
||||
elseif (WITH_OPENSSL)
|
||||
find_package (OpenSSL REQUIRED)
|
||||
include (OpenSSLTests)
|
||||
include_directories (${OPENSSL_INCLUDE_DIR})
|
||||
set (EXTRA_LIBS ${OPENSSL_LIBRARIES})
|
||||
set (EXTRA_SOURCE openssl.cpp)
|
||||
elseif (WITH_BOTAN)
|
||||
find_package (Botan REQUIRED)
|
||||
set (EXTRA_LIBS ${BOTAN_LIBRARIES})
|
||||
set (EXTRA_SOURCE botan.cpp)
|
||||
endif (WITH_COMMON_CRYPTO)
|
||||
|
||||
add_library (encfs-cipher
|
||||
|
@ -43,7 +43,7 @@ CipherKey::CipherKey(const byte *data, int length)
|
||||
: _valid(true)
|
||||
{
|
||||
_mem.reset(new SecureMem(length));
|
||||
memcpy(_mem->data, data, length);
|
||||
memcpy(_mem->data(), data, length);
|
||||
}
|
||||
|
||||
CipherKey::CipherKey(const CipherKey& src)
|
||||
@ -64,12 +64,12 @@ void CipherKey::operator = (const CipherKey& src)
|
||||
|
||||
byte *CipherKey::data() const
|
||||
{
|
||||
return !_mem ? NULL : _mem->data;
|
||||
return !_mem ? NULL : _mem->data();
|
||||
}
|
||||
|
||||
int CipherKey::size() const
|
||||
{
|
||||
return !_mem ? 0 : _mem->size;
|
||||
return !_mem ? 0 : _mem->size();
|
||||
}
|
||||
|
||||
void CipherKey::reset()
|
||||
|
@ -49,6 +49,10 @@
|
||||
#include "cipher/openssl.h"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_BOTAN
|
||||
#include "cipher/botan.h"
|
||||
#endif
|
||||
|
||||
using std::list;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
@ -70,6 +74,9 @@ void CipherV1::init(bool threaded) {
|
||||
#ifdef WITH_OPENSSL
|
||||
OpenSSL::init(threaded);
|
||||
#endif
|
||||
#ifdef WITH_BOTAN
|
||||
Botan_init(threaded);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CipherV1::shutdown(bool threaded) {
|
||||
@ -103,22 +110,22 @@ bool BytesToKey(const byte *data, int dataLen,
|
||||
{
|
||||
sha1->init();
|
||||
if( addmd++ )
|
||||
sha1->update(mdBuf.data, mdBuf.size);
|
||||
sha1->update(mdBuf.data(), mdBuf.size());
|
||||
sha1->update(data, dataLen);
|
||||
sha1->write(mdBuf.data);
|
||||
sha1->write(mdBuf.data());
|
||||
|
||||
for(unsigned int i=1; i < rounds; ++i)
|
||||
{
|
||||
sha1->init();
|
||||
sha1->update(mdBuf.data, mdBuf.size);
|
||||
sha1->write(mdBuf.data);
|
||||
sha1->update(mdBuf.data(), mdBuf.size());
|
||||
sha1->write(mdBuf.data());
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
int toCopy = MIN( remaining, (int)mdBuf.size - offset );
|
||||
int toCopy = MIN( remaining, mdBuf.size() - offset );
|
||||
if( toCopy )
|
||||
{
|
||||
memcpy( key->data(), mdBuf.data+offset, toCopy );
|
||||
memcpy( key->data(), mdBuf.data()+offset, toCopy );
|
||||
key += toCopy;
|
||||
remaining -= toCopy;
|
||||
offset += toCopy;
|
||||
@ -144,7 +151,7 @@ int CipherV1::TimedPBKDF2(const char *pass, int passlen,
|
||||
VALGRIND_CHECK_MEM_IS_DEFINED(salt, saltlen);
|
||||
#endif
|
||||
Registry<PBKDF> registry = PBKDF::GetRegistry();
|
||||
shared_ptr<PBKDF> impl(registry.CreateForMatch(NAME_PKCS5_PBKDF2_HMAC_SHA1));
|
||||
shared_ptr<PBKDF> impl(registry.CreateForMatch(NAME_PBKDF2_HMAC_SHA1));
|
||||
if (!impl)
|
||||
return -1;
|
||||
|
||||
@ -291,7 +298,7 @@ bool CipherV1::initCiphers(const Interface &iface, const Interface &realIface,
|
||||
_keySize = keyRange.closest(keyLength) / 8;
|
||||
|
||||
_pbkdf.reset(PBKDF::GetRegistry().CreateForMatch(
|
||||
NAME_PKCS5_PBKDF2_HMAC_SHA1));
|
||||
NAME_PBKDF2_HMAC_SHA1));
|
||||
if (!_pbkdf) {
|
||||
LOG(ERROR) << "PBKDF missing";
|
||||
return false;
|
||||
@ -401,7 +408,7 @@ bool CipherV1::setKey(const CipherKey &keyIv) {
|
||||
// Key is actually key plus iv, so extract the different parts.
|
||||
CipherKey key(_keySize);
|
||||
memcpy(key.data(), keyIv.data(), _keySize);
|
||||
memcpy(_iv->data, keyIv.data() + _keySize, _ivLength);
|
||||
memcpy(_iv->data(), keyIv.data() + _keySize, _ivLength);
|
||||
|
||||
if (_blockCipher->setKey(key)
|
||||
&& _streamCipher->setKey(key)
|
||||
@ -518,11 +525,11 @@ void CipherV1::writeKey(const CipherKey &ckey, byte *out)
|
||||
rAssert( _keySet );
|
||||
|
||||
SecureMem tmpBuf(ckey.size());
|
||||
memcpy(tmpBuf.data, ckey.data(), tmpBuf.size);
|
||||
memcpy(tmpBuf.data(), ckey.data(), tmpBuf.size());
|
||||
|
||||
unsigned int checksum = reduceMac32(
|
||||
MAC_64(tmpBuf.data, tmpBuf.size, NULL));
|
||||
streamEncode(tmpBuf.data, tmpBuf.size, checksum);
|
||||
MAC_64(tmpBuf.data(), tmpBuf.size(), NULL));
|
||||
streamEncode(tmpBuf.data(), tmpBuf.size(), checksum);
|
||||
|
||||
// first N bytes contain HMAC derived checksum..
|
||||
for(int i=1; i<=KEY_CHECKSUM_BYTES; ++i)
|
||||
@ -531,7 +538,7 @@ void CipherV1::writeKey(const CipherKey &ckey, byte *out)
|
||||
checksum >>= 8;
|
||||
}
|
||||
|
||||
memcpy( out+KEY_CHECKSUM_BYTES, tmpBuf.data, tmpBuf.size );
|
||||
memcpy( out+KEY_CHECKSUM_BYTES, tmpBuf.data(), tmpBuf.size() );
|
||||
}
|
||||
|
||||
std::string CipherV1::encodeAsString(const CipherKey &key)
|
||||
@ -602,7 +609,7 @@ static void setIVec_old(byte *ivec, int ivLen, unsigned int seed)
|
||||
void CipherV1::setIVec(byte *ivec, uint64_t seed) const
|
||||
{
|
||||
rAssert( _keySet );
|
||||
memcpy( ivec, _iv->data, _ivLength );
|
||||
memcpy( ivec, _iv->data(), _ivLength );
|
||||
if (iface.major() < 3)
|
||||
{
|
||||
// Backward compatible mode.
|
||||
|
@ -40,17 +40,19 @@
|
||||
namespace encfs {
|
||||
namespace commoncrypto {
|
||||
|
||||
class PbkdfPkcs5HmacSha1CC : public PBKDF {
|
||||
class PbkdfPkcs5Hmac : public PBKDF {
|
||||
CCPseudoRandomAlgorithm prf_;
|
||||
public:
|
||||
PbkdfPkcs5HmacSha1CC() {}
|
||||
virtual ~PbkdfPkcs5HmacSha1CC() {}
|
||||
PbkdfPkcs5Hmac(CCPseudoRandomAlgorithm prf)
|
||||
: prf_(prf) {}
|
||||
virtual ~PbkdfPkcs5Hmac() {}
|
||||
|
||||
virtual bool makeKey(const char *password, int passwordLength,
|
||||
const byte *salt, int saltLength,
|
||||
int numIterations,
|
||||
CipherKey *outKey) {
|
||||
int ret = CCKeyDerivationPBKDF(kCCPBKDF2, password, passwordLength,
|
||||
salt, saltLength, kCCPRFHmacAlgSHA1,
|
||||
salt, saltLength, prf_,
|
||||
numIterations,
|
||||
outKey->data(), outKey->size());
|
||||
if (ret != 0) {
|
||||
@ -86,16 +88,37 @@ public:
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class PbkdfPkcs5HmacSha1CC : public PbkdfPkcs5Hmac {
|
||||
public:
|
||||
PbkdfPkcs5HmacSha1CC() : PbkdfPkcs5Hmac(kCCPRFHmacAlgSHA1) {}
|
||||
~PbkdfPkcs5HmacSha1CC() {}
|
||||
|
||||
static Properties GetProperties() {
|
||||
Properties props;
|
||||
props.mode = NAME_PKCS5_PBKDF2_HMAC_SHA1;
|
||||
props.mode = NAME_PBKDF2_HMAC_SHA1;
|
||||
props.library = "CommonCrypto";
|
||||
return props;
|
||||
}
|
||||
};
|
||||
REGISTER_CLASS(PbkdfPkcs5HmacSha1CC, PBKDF);
|
||||
|
||||
class PbkdfPkcs5HmacSha256CC : public PbkdfPkcs5Hmac {
|
||||
public:
|
||||
PbkdfPkcs5HmacSha256CC() : PbkdfPkcs5Hmac(kCCPRFHmacAlgSHA256) {}
|
||||
~PbkdfPkcs5HmacSha256CC() {}
|
||||
|
||||
static Properties GetProperties() {
|
||||
Properties props;
|
||||
props.mode = NAME_PBKDF2_HMAC_SHA256;
|
||||
props.library = "CommonCrypto";
|
||||
return props;
|
||||
}
|
||||
};
|
||||
REGISTER_CLASS(PbkdfPkcs5HmacSha256CC, PBKDF);
|
||||
|
||||
class CCCipher : public BlockCipher {
|
||||
CipherKey key;
|
||||
CCAlgorithm algorithm;
|
||||
|
@ -47,6 +47,10 @@
|
||||
# include <openssl/buffer.h>
|
||||
#endif
|
||||
|
||||
#ifdef WITH_BOTAN
|
||||
# include <botan/botan.h>
|
||||
#endif
|
||||
|
||||
namespace encfs {
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
@ -61,14 +65,16 @@ static void freeBlock( byte *block, int size )
|
||||
OPENSSL_cleanse(block, size);
|
||||
OPENSSL_free(block);
|
||||
}
|
||||
#elif defined(WITH_COMMON_CRYPTO)
|
||||
|
||||
#else
|
||||
|
||||
static byte *allocBlock(int size) {
|
||||
byte *block = new byte[size];
|
||||
return block;
|
||||
}
|
||||
|
||||
unsigned char cleanse_ctr = 0;
|
||||
static void freeBlock(byte *data, int len) {
|
||||
static void cleanBlock(byte *data, int len) {
|
||||
byte *p = data;
|
||||
size_t loop = len, ctr = cleanse_ctr;
|
||||
while(loop--)
|
||||
@ -81,8 +87,8 @@ static void freeBlock(byte *data, int len) {
|
||||
if(p)
|
||||
ctr += (63 + (size_t)p);
|
||||
cleanse_ctr = (unsigned char)ctr;
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void MemBlock::allocate(int size)
|
||||
@ -94,38 +100,49 @@ void MemBlock::allocate(int size)
|
||||
|
||||
MemBlock::~MemBlock()
|
||||
{
|
||||
freeBlock(data, size);
|
||||
cleanBlock(data, size);
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
SecureMem::SecureMem(int len)
|
||||
#ifdef WITH_BOTAN
|
||||
: data_(len)
|
||||
#endif
|
||||
{
|
||||
rAssert(len > 0);
|
||||
data = allocBlock(len);
|
||||
if (data)
|
||||
#ifndef WITH_BOTAN
|
||||
data_ = allocBlock(len);
|
||||
if (data_)
|
||||
{
|
||||
size = len;
|
||||
mlock(data, size);
|
||||
size_ = len;
|
||||
mlock(data_, size_);
|
||||
} else
|
||||
{
|
||||
size = 0;
|
||||
size_ = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SecureMem::~SecureMem()
|
||||
{
|
||||
if (size)
|
||||
#ifdef WITH_BOTAN
|
||||
data_.destroy();
|
||||
#else
|
||||
if (size_)
|
||||
{
|
||||
freeBlock(data, size);
|
||||
munlock(data, size);
|
||||
cleanBlock(data_, size_);
|
||||
delete[] data_;
|
||||
munlock(data_, size_);
|
||||
|
||||
data = NULL;
|
||||
size = 0;
|
||||
data_ = NULL;
|
||||
size_ = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool operator == (const SecureMem &a, const SecureMem &b) {
|
||||
return (a.size == b.size) &&
|
||||
(memcmp(a.data, b.data, a.size) == 0);
|
||||
return (a.size() == b.size()) &&
|
||||
(memcmp(a.data(), b.data(), a.size()) == 0);
|
||||
}
|
||||
|
||||
} // namespace encfs
|
||||
|
@ -21,12 +21,18 @@
|
||||
#ifndef _MemoryPool_incl_
|
||||
#define _MemoryPool_incl_
|
||||
|
||||
#include "base/config.h"
|
||||
#include "base/types.h"
|
||||
|
||||
#ifdef WITH_BOTAN
|
||||
#include <botan/secmem.h>
|
||||
#endif
|
||||
|
||||
namespace encfs {
|
||||
|
||||
/*
|
||||
Memory Pool for fixed sized objects.
|
||||
Use SecureMem if storing sensitive information.
|
||||
|
||||
Usage:
|
||||
MemBlock mb;
|
||||
@ -55,13 +61,37 @@ inline MemBlock::MemBlock()
|
||||
class SecureMem
|
||||
{
|
||||
public:
|
||||
int size;
|
||||
byte *data;
|
||||
byte* data() const;
|
||||
int size() const;
|
||||
|
||||
explicit SecureMem(int len);
|
||||
~SecureMem();
|
||||
|
||||
private:
|
||||
#ifdef WITH_BOTAN
|
||||
Botan::SecureVector<Botan::byte> data_;
|
||||
#else
|
||||
byte *data_;
|
||||
int size_;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef WITH_BOTAN
|
||||
inline byte* SecureMem::data() const {
|
||||
return const_cast<byte*>(data_.begin());
|
||||
}
|
||||
inline int SecureMem::size() const {
|
||||
return data_.size();
|
||||
}
|
||||
#else
|
||||
inline byte* SecureMem::data() const {
|
||||
return data_;
|
||||
}
|
||||
inline int SecureMem::size() const {
|
||||
return size_;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool operator == (const SecureMem &a, const SecureMem &b);
|
||||
|
||||
} // namespace encfs
|
||||
|
@ -10,7 +10,8 @@
|
||||
namespace encfs {
|
||||
|
||||
// Well-known algorithms.
|
||||
static const char NAME_PKCS5_PBKDF2_HMAC_SHA1[] = "PKCS5_PBKDF2_HMAC_SHA1";
|
||||
static const char NAME_PBKDF2_HMAC_SHA1[] = "PBKDF2_HMAC_SHA1";
|
||||
static const char NAME_PBKDF2_HMAC_SHA256[] = "PBKDF2_HMAC_SHA256";
|
||||
|
||||
// Password Based Key Derivation Function.
|
||||
class PBKDF
|
||||
|
@ -34,7 +34,7 @@ namespace {
|
||||
|
||||
TEST(PKCS5_PBKDF2_HMAC_SHA1, PBKDF) {
|
||||
Registry<PBKDF> registry = PBKDF::GetRegistry();
|
||||
shared_ptr<PBKDF> impl( registry.CreateForMatch(NAME_PKCS5_PBKDF2_HMAC_SHA1));
|
||||
shared_ptr<PBKDF> impl( registry.CreateForMatch(NAME_PBKDF2_HMAC_SHA1));
|
||||
ASSERT_FALSE(!impl);
|
||||
|
||||
// Test cases from rfc6070
|
||||
@ -68,6 +68,50 @@ TEST(PKCS5_PBKDF2_HMAC_SHA1, PBKDF) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PKCS5_PBKDF2_HMAC_SHA256, PBKDF) {
|
||||
Registry<PBKDF> registry = PBKDF::GetRegistry();
|
||||
shared_ptr<PBKDF> impl(
|
||||
registry.CreateForMatch(NAME_PBKDF2_HMAC_SHA256));
|
||||
ASSERT_FALSE(!impl);
|
||||
|
||||
// Test case 1
|
||||
{
|
||||
CipherKey key(32);
|
||||
bool ok = impl->makeKey("password", 8,
|
||||
(byte*)"salt", 4,
|
||||
1, &key);
|
||||
ASSERT_TRUE(ok);
|
||||
ASSERT_EQ("120fb6cffcf8b32c"
|
||||
"43e7225256c4f837"
|
||||
"a86548c92ccc3548"
|
||||
"0805987cb70be17b", stringToHex(key));
|
||||
}
|
||||
|
||||
// Test case 2
|
||||
{
|
||||
CipherKey key(40);
|
||||
bool ok = impl->makeKey("passwordPASSWORDpassword", 24,
|
||||
(byte*)"saltSALTsaltSALTsaltSALTsaltSALTsalt", 36,
|
||||
4096, &key);
|
||||
ASSERT_TRUE(ok);
|
||||
ASSERT_EQ("348c89dbcbd32b2f"
|
||||
"32d814b8116e84cf"
|
||||
"2b17347ebc180018"
|
||||
"1c4e2a1fb8dd53e1"
|
||||
"c635518c7dac47e9",
|
||||
stringToHex(key));
|
||||
}
|
||||
|
||||
// Test case 3
|
||||
{
|
||||
CipherKey key(16);
|
||||
bool ok = impl->makeKey("pass\0word", 9,
|
||||
(byte*)"sa\0lt", 5,
|
||||
4096, &key);
|
||||
ASSERT_TRUE(ok);
|
||||
ASSERT_EQ("89b69d0516f829893c696226650a8687", stringToHex(key));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
141
cipher/botan.cpp
Normal file
141
cipher/botan.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
|
||||
/*****************************************************************************
|
||||
* Author: Valient Gough <vgough@pobox.com>
|
||||
*
|
||||
*****************************************************************************
|
||||
* Copyright (c) 2013 Valient Gough
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "cipher/botan.h"
|
||||
#include "base/config.h"
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <botan/botan.h>
|
||||
|
||||
#include "base/Error.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"
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace Botan;
|
||||
|
||||
namespace encfs {
|
||||
namespace botan {
|
||||
|
||||
class PbkdfPkcs5Hmac : public PBKDF {
|
||||
Botan::PBKDF* pbkdf_;
|
||||
|
||||
public:
|
||||
PbkdfPkcs5Hmac(Botan::PBKDF* pbkdf) : pbkdf_(pbkdf) {}
|
||||
virtual ~PbkdfPkcs5Hmac() {
|
||||
delete pbkdf_;
|
||||
}
|
||||
|
||||
virtual bool makeKey(const char *password, int passwordLength,
|
||||
const byte *salt, int saltLength,
|
||||
int numIterations,
|
||||
CipherKey *outKey) {
|
||||
if (pbkdf_ == NULL) {
|
||||
// TODO: error message
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string pass;
|
||||
pass.assign(password, passwordLength);
|
||||
OctetString key = pbkdf_->derive_key(outKey->size(),
|
||||
pass,
|
||||
salt, saltLength,
|
||||
numIterations);
|
||||
memcpy(outKey->data(), key.begin(), outKey->size());
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual CipherKey randomKey(int length) {
|
||||
CipherKey key(length);
|
||||
rng.randomize(key.data(), key.size());
|
||||
return key;
|
||||
}
|
||||
|
||||
virtual bool pseudoRandom(byte *out, int length) {
|
||||
rng.randomize(out, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
AutoSeeded_RNG rng;
|
||||
};
|
||||
|
||||
class PbkdfPkcs5HmacSha1 : public PbkdfPkcs5Hmac {
|
||||
public:
|
||||
PbkdfPkcs5HmacSha1()
|
||||
: PbkdfPkcs5Hmac( get_pbkdf("PBKDF2(SHA-1)")) { }
|
||||
~PbkdfPkcs5HmacSha1() {}
|
||||
|
||||
static Properties GetProperties() {
|
||||
Properties props;
|
||||
props.mode = NAME_PBKDF2_HMAC_SHA1;
|
||||
props.library = "Botan";
|
||||
return props;
|
||||
}
|
||||
};
|
||||
REGISTER_CLASS(PbkdfPkcs5HmacSha1, PBKDF);
|
||||
|
||||
class PbkdfPkcs5HmacSha256 : public PbkdfPkcs5Hmac {
|
||||
public:
|
||||
PbkdfPkcs5HmacSha256()
|
||||
: PbkdfPkcs5Hmac( get_pbkdf("PBKDF2(SHA-256)")) { }
|
||||
~PbkdfPkcs5HmacSha256() {}
|
||||
|
||||
static Properties GetProperties() {
|
||||
Properties props;
|
||||
props.mode = NAME_PBKDF2_HMAC_SHA256;
|
||||
props.library = "Botan";
|
||||
return props;
|
||||
}
|
||||
};
|
||||
REGISTER_CLASS(PbkdfPkcs5HmacSha256, PBKDF);
|
||||
|
||||
|
||||
|
||||
} // namespace botan
|
||||
|
||||
static Botan::LibraryInitializer* initializer;
|
||||
|
||||
void Botan_init(bool threaded) {
|
||||
if (threaded) {
|
||||
initializer = new Botan::LibraryInitializer("thread_safe=true");
|
||||
} else {
|
||||
initializer = new Botan::LibraryInitializer();
|
||||
}
|
||||
}
|
||||
|
||||
void Botan_shutdown() {
|
||||
delete initializer;
|
||||
initializer = NULL;
|
||||
}
|
||||
|
||||
void Botan_registerCiphers() {
|
||||
// Just a reference to ensure static initializers are linked.
|
||||
}
|
||||
|
||||
} // namespace encfs
|
||||
|
36
cipher/botan.h
Normal file
36
cipher/botan.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_BOTAN_incl_
|
||||
#define _CIPHER_BOTAN_incl_
|
||||
|
||||
#include "base/Registry.h"
|
||||
|
||||
namespace encfs {
|
||||
|
||||
extern void Botan_init(bool threaded);
|
||||
extern void Botan_shutdown();
|
||||
extern void Botan_registerCiphers();
|
||||
|
||||
} // namespace encfs
|
||||
|
||||
#endif
|
||||
|
@ -33,8 +33,6 @@
|
||||
#include <valgrind/memcheck.h>
|
||||
#endif
|
||||
|
||||
#include "base/config.h"
|
||||
|
||||
#define NO_DES
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/rand.h>
|
||||
@ -449,7 +447,7 @@ class PbkdfPkcs5HmacSha1 : public PBKDF {
|
||||
|
||||
static Properties GetProperties() {
|
||||
Properties props;
|
||||
props.mode = NAME_PKCS5_PBKDF2_HMAC_SHA1;
|
||||
props.mode = NAME_PBKDF2_HMAC_SHA1;
|
||||
props.library = "OpenSSL";
|
||||
return props;
|
||||
}
|
||||
|
@ -1350,11 +1350,11 @@ std::string readPassword( int FD )
|
||||
|
||||
while(1)
|
||||
{
|
||||
ssize_t rdSize = recv(FD, buf->data, buf->size, 0);
|
||||
ssize_t rdSize = recv(FD, buf->data(), buf->size(), 0);
|
||||
|
||||
if(rdSize > 0)
|
||||
{
|
||||
result.append( (char*)buf->data, rdSize );
|
||||
result.append( (char*)buf->data(), rdSize );
|
||||
} else
|
||||
break;
|
||||
}
|
||||
@ -1441,7 +1441,7 @@ SecureMem *passwordFromProgram(const std::string &passProg,
|
||||
|
||||
SecureMem *result = new SecureMem(password.length()+1);
|
||||
if (result)
|
||||
strncpy((char *)result->data, password.c_str(), result->size);
|
||||
strncpy((char *)result->data(), password.c_str(), result->size());
|
||||
password.assign(password.length(), '\0');
|
||||
|
||||
return result;
|
||||
@ -1451,13 +1451,13 @@ SecureMem *passwordFromStdin()
|
||||
{
|
||||
SecureMem *buf = new SecureMem(MaxPassBuf);
|
||||
|
||||
char *res = fgets( (char *)buf->data, buf->size, stdin );
|
||||
char *res = fgets( (char *)buf->data(), buf->size(), stdin );
|
||||
if (res)
|
||||
{
|
||||
// Kill the trailing newline.
|
||||
int last = strnlen((char *)buf->data, buf->size);
|
||||
if (last > 0 && buf->data[last-1] == '\n')
|
||||
buf->data[ last-1 ] = '\0';
|
||||
int last = strnlen((char *)buf->data(), buf->size());
|
||||
if (last > 0 && buf->data()[last-1] == '\n')
|
||||
buf->data()[ last-1 ] = '\0';
|
||||
}
|
||||
|
||||
return buf;
|
||||
@ -1469,7 +1469,7 @@ SecureMem *passwordFromPrompt()
|
||||
|
||||
// xgroup(common)
|
||||
char *res = readpassphrase( _("EncFS Password: "),
|
||||
(char *)buf->data, buf->size-1, RPP_ECHO_OFF );
|
||||
(char *)buf->data(), buf->size()-1, RPP_ECHO_OFF );
|
||||
if (!res)
|
||||
{
|
||||
delete buf;
|
||||
@ -1488,13 +1488,13 @@ SecureMem *passwordFromPrompts()
|
||||
{
|
||||
// xgroup(common)
|
||||
char *res1 = readpassphrase(_("New Encfs Password: "),
|
||||
(char *)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: "),
|
||||
(char *)buf2->data, buf2->size-1, RPP_ECHO_OFF);
|
||||
(char *)buf2->data(), buf2->size()-1, RPP_ECHO_OFF);
|
||||
|
||||
if(res1 && res2
|
||||
&& !strncmp((char*)buf->data, (char*)buf2->data, MaxPassBuf))
|
||||
&& !strncmp((char*)buf->data(), (char*)buf2->data(), MaxPassBuf))
|
||||
{
|
||||
break;
|
||||
} else
|
||||
@ -1520,8 +1520,8 @@ CipherKey getUserKey(const EncfsConfig &config, bool useStdin)
|
||||
|
||||
if (password)
|
||||
{
|
||||
userKey = decryptKey(config, (char*)password->data,
|
||||
strlen((char*)password->data));
|
||||
userKey = decryptKey(config, (char*)password->data(),
|
||||
strlen((char*)password->data()));
|
||||
delete password;
|
||||
}
|
||||
|
||||
@ -1536,8 +1536,8 @@ CipherKey getUserKey( const EncfsConfig &config, const std::string &passProg,
|
||||
|
||||
if (password)
|
||||
{
|
||||
result = decryptKey(config, (char*)password->data,
|
||||
strlen((char*)password->data));
|
||||
result = decryptKey(config, (char*)password->data(),
|
||||
strlen((char*)password->data()));
|
||||
delete password;
|
||||
}
|
||||
|
||||
@ -1560,8 +1560,8 @@ CipherKey getNewUserKey(EncfsConfig &config,
|
||||
|
||||
if (password)
|
||||
{
|
||||
result = makeNewKey(config, (char*)password->data,
|
||||
strlen((char*)password->data));
|
||||
result = makeNewKey(config, (char*)password->data(),
|
||||
strlen((char*)password->data()));
|
||||
delete password;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user