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:
Valient Gough 2013-03-06 08:02:23 +00:00
parent 63c2d1c539
commit 95750d4539
16 changed files with 422 additions and 75 deletions

View File

@ -7,12 +7,16 @@ set (ENCFS_VERSION "${ENCFS_MAJOR}.${ENCFS_MINOR}")
option (BUILD_SHARED_LIBS "Build dynamic link libraries" OFF) option (BUILD_SHARED_LIBS "Build dynamic link libraries" OFF)
option (WITH_OPENSSL "WithOpenSSL" ON) option (WITH_OPENSSL "WithOpenSSL" OFF)
option (WITH_COMMON_CRYPTO "WithCommonCrypto" 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) 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} set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
"${CMAKE_SOURCE_DIR}/CMakeModules/") "${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/valgrind.h HAVE_VALGRIND_VALGRIND_H)
check_include_file_cxx (valgrind/memcheck.h HAVE_VALGRIND_MEMCHECK_H) check_include_file_cxx (valgrind/memcheck.h HAVE_VALGRIND_MEMCHECK_H)
if (WITH_COMMON_CRYPTO) # Used with CommonCrypto
check_include_file_cxx (Security/SecRandom.h HAVE_SEC_RANDOM_H) check_include_file_cxx (Security/SecRandom.h HAVE_SEC_RANDOM_H)
endif (WITH_COMMON_CRYPTO)
if (WITH_OPENSSL)
# TODO: move this to cipher directory.
find_package (OpenSSL REQUIRED)
include (OpenSSLTests)
endif (WITH_OPENSSL)
# Check if xattr functions take extra argument. # Check if xattr functions take extra argument.
include (CheckCXXSourceCompiles) include (CheckCXXSourceCompiles)

View 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()

View File

@ -15,6 +15,7 @@
#cmakedefine WITH_OPENSSL #cmakedefine WITH_OPENSSL
#cmakedefine WITH_COMMON_CRYPTO #cmakedefine WITH_COMMON_CRYPTO
#cmakedefine WITH_BOTAN
#cmakedefine HAVE_SEC_RANDOM_H #cmakedefine HAVE_SEC_RANDOM_H
#cmakedefine HAVE_EVP_BF #cmakedefine HAVE_EVP_BF

View File

@ -153,7 +153,7 @@ TEST(BlockEncryptionTest, BlockCipher) {
Registry<BlockCipher> registry = BlockCipher::GetRegistry(); Registry<BlockCipher> registry = BlockCipher::GetRegistry();
shared_ptr<PBKDF> pbkdf( shared_ptr<PBKDF> pbkdf(
PBKDF::GetRegistry().CreateForMatch(NAME_PKCS5_PBKDF2_HMAC_SHA1)); PBKDF::GetRegistry().CreateForMatch(NAME_PBKDF2_HMAC_SHA1));
list<string> ciphers = registry.GetAll(); list<string> ciphers = registry.GetAll();
for (const string &name : ciphers) { for (const string &name : ciphers) {

View File

@ -6,9 +6,15 @@ if (WITH_COMMON_CRYPTO)
set (EXTRA_LIBS ${SECURITY_FRAMEWORK}) set (EXTRA_LIBS ${SECURITY_FRAMEWORK})
set (EXTRA_SOURCE CommonCrypto.cpp) set (EXTRA_SOURCE CommonCrypto.cpp)
elseif (WITH_OPENSSL) elseif (WITH_OPENSSL)
find_package (OpenSSL REQUIRED)
include (OpenSSLTests)
include_directories (${OPENSSL_INCLUDE_DIR}) include_directories (${OPENSSL_INCLUDE_DIR})
set (EXTRA_LIBS ${OPENSSL_LIBRARIES}) set (EXTRA_LIBS ${OPENSSL_LIBRARIES})
set (EXTRA_SOURCE openssl.cpp) 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) endif (WITH_COMMON_CRYPTO)
add_library (encfs-cipher add_library (encfs-cipher

View File

@ -43,7 +43,7 @@ CipherKey::CipherKey(const byte *data, int length)
: _valid(true) : _valid(true)
{ {
_mem.reset(new SecureMem(length)); _mem.reset(new SecureMem(length));
memcpy(_mem->data, data, length); memcpy(_mem->data(), data, length);
} }
CipherKey::CipherKey(const CipherKey& src) CipherKey::CipherKey(const CipherKey& src)
@ -64,12 +64,12 @@ void CipherKey::operator = (const CipherKey& src)
byte *CipherKey::data() const byte *CipherKey::data() const
{ {
return !_mem ? NULL : _mem->data; return !_mem ? NULL : _mem->data();
} }
int CipherKey::size() const int CipherKey::size() const
{ {
return !_mem ? 0 : _mem->size; return !_mem ? 0 : _mem->size();
} }
void CipherKey::reset() void CipherKey::reset()

View File

@ -49,6 +49,10 @@
#include "cipher/openssl.h" #include "cipher/openssl.h"
#endif #endif
#ifdef WITH_BOTAN
#include "cipher/botan.h"
#endif
using std::list; using std::list;
using std::string; using std::string;
using std::vector; using std::vector;
@ -70,6 +74,9 @@ void CipherV1::init(bool threaded) {
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
OpenSSL::init(threaded); OpenSSL::init(threaded);
#endif #endif
#ifdef WITH_BOTAN
Botan_init(threaded);
#endif
} }
void CipherV1::shutdown(bool threaded) { void CipherV1::shutdown(bool threaded) {
@ -103,22 +110,22 @@ bool BytesToKey(const byte *data, int dataLen,
{ {
sha1->init(); sha1->init();
if( addmd++ ) if( addmd++ )
sha1->update(mdBuf.data, mdBuf.size); sha1->update(mdBuf.data(), mdBuf.size());
sha1->update(data, dataLen); sha1->update(data, dataLen);
sha1->write(mdBuf.data); sha1->write(mdBuf.data());
for(unsigned int i=1; i < rounds; ++i) for(unsigned int i=1; i < rounds; ++i)
{ {
sha1->init(); sha1->init();
sha1->update(mdBuf.data, mdBuf.size); sha1->update(mdBuf.data(), mdBuf.size());
sha1->write(mdBuf.data); sha1->write(mdBuf.data());
} }
int offset = 0; int offset = 0;
int toCopy = MIN( remaining, (int)mdBuf.size - offset ); int toCopy = MIN( remaining, mdBuf.size() - offset );
if( toCopy ) if( toCopy )
{ {
memcpy( key->data(), mdBuf.data+offset, toCopy ); memcpy( key->data(), mdBuf.data()+offset, toCopy );
key += toCopy; key += toCopy;
remaining -= toCopy; remaining -= toCopy;
offset += toCopy; offset += toCopy;
@ -144,7 +151,7 @@ int CipherV1::TimedPBKDF2(const char *pass, int passlen,
VALGRIND_CHECK_MEM_IS_DEFINED(salt, saltlen); VALGRIND_CHECK_MEM_IS_DEFINED(salt, saltlen);
#endif #endif
Registry<PBKDF> registry = PBKDF::GetRegistry(); Registry<PBKDF> registry = PBKDF::GetRegistry();
shared_ptr<PBKDF> impl(registry.CreateForMatch(NAME_PKCS5_PBKDF2_HMAC_SHA1)); shared_ptr<PBKDF> impl(registry.CreateForMatch(NAME_PBKDF2_HMAC_SHA1));
if (!impl) if (!impl)
return -1; return -1;
@ -291,7 +298,7 @@ bool CipherV1::initCiphers(const Interface &iface, const Interface &realIface,
_keySize = keyRange.closest(keyLength) / 8; _keySize = keyRange.closest(keyLength) / 8;
_pbkdf.reset(PBKDF::GetRegistry().CreateForMatch( _pbkdf.reset(PBKDF::GetRegistry().CreateForMatch(
NAME_PKCS5_PBKDF2_HMAC_SHA1)); NAME_PBKDF2_HMAC_SHA1));
if (!_pbkdf) { if (!_pbkdf) {
LOG(ERROR) << "PBKDF missing"; LOG(ERROR) << "PBKDF missing";
return false; return false;
@ -401,7 +408,7 @@ bool CipherV1::setKey(const CipherKey &keyIv) {
// Key is actually key plus iv, so extract the different parts. // Key is actually key plus iv, so extract the different parts.
CipherKey key(_keySize); CipherKey key(_keySize);
memcpy(key.data(), keyIv.data(), _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) if (_blockCipher->setKey(key)
&& _streamCipher->setKey(key) && _streamCipher->setKey(key)
@ -518,11 +525,11 @@ void CipherV1::writeKey(const CipherKey &ckey, byte *out)
rAssert( _keySet ); rAssert( _keySet );
SecureMem tmpBuf(ckey.size()); SecureMem tmpBuf(ckey.size());
memcpy(tmpBuf.data, ckey.data(), tmpBuf.size); memcpy(tmpBuf.data(), ckey.data(), tmpBuf.size());
unsigned int checksum = reduceMac32( unsigned int checksum = reduceMac32(
MAC_64(tmpBuf.data, tmpBuf.size, NULL)); MAC_64(tmpBuf.data(), tmpBuf.size(), NULL));
streamEncode(tmpBuf.data, tmpBuf.size, checksum); streamEncode(tmpBuf.data(), tmpBuf.size(), checksum);
// first N bytes contain HMAC derived checksum.. // first N bytes contain HMAC derived checksum..
for(int i=1; i<=KEY_CHECKSUM_BYTES; ++i) for(int i=1; i<=KEY_CHECKSUM_BYTES; ++i)
@ -531,7 +538,7 @@ void CipherV1::writeKey(const CipherKey &ckey, byte *out)
checksum >>= 8; 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) 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 void CipherV1::setIVec(byte *ivec, uint64_t seed) const
{ {
rAssert( _keySet ); rAssert( _keySet );
memcpy( ivec, _iv->data, _ivLength ); memcpy( ivec, _iv->data(), _ivLength );
if (iface.major() < 3) if (iface.major() < 3)
{ {
// Backward compatible mode. // Backward compatible mode.

View File

@ -40,17 +40,19 @@
namespace encfs { namespace encfs {
namespace commoncrypto { namespace commoncrypto {
class PbkdfPkcs5HmacSha1CC : public PBKDF { class PbkdfPkcs5Hmac : public PBKDF {
CCPseudoRandomAlgorithm prf_;
public: public:
PbkdfPkcs5HmacSha1CC() {} PbkdfPkcs5Hmac(CCPseudoRandomAlgorithm prf)
virtual ~PbkdfPkcs5HmacSha1CC() {} : prf_(prf) {}
virtual ~PbkdfPkcs5Hmac() {}
virtual bool makeKey(const char *password, int passwordLength, virtual bool makeKey(const char *password, int passwordLength,
const byte *salt, int saltLength, const byte *salt, int saltLength,
int numIterations, int numIterations,
CipherKey *outKey) { CipherKey *outKey) {
int ret = CCKeyDerivationPBKDF(kCCPBKDF2, password, passwordLength, int ret = CCKeyDerivationPBKDF(kCCPBKDF2, password, passwordLength,
salt, saltLength, kCCPRFHmacAlgSHA1, salt, saltLength, prf_,
numIterations, numIterations,
outKey->data(), outKey->size()); outKey->data(), outKey->size());
if (ret != 0) { if (ret != 0) {
@ -86,16 +88,37 @@ public:
#endif #endif
return true; return true;
} }
};
class PbkdfPkcs5HmacSha1CC : public PbkdfPkcs5Hmac {
public:
PbkdfPkcs5HmacSha1CC() : PbkdfPkcs5Hmac(kCCPRFHmacAlgSHA1) {}
~PbkdfPkcs5HmacSha1CC() {}
static Properties GetProperties() { static Properties GetProperties() {
Properties props; Properties props;
props.mode = NAME_PKCS5_PBKDF2_HMAC_SHA1; props.mode = NAME_PBKDF2_HMAC_SHA1;
props.library = "CommonCrypto"; props.library = "CommonCrypto";
return props; return props;
} }
}; };
REGISTER_CLASS(PbkdfPkcs5HmacSha1CC, PBKDF); 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 { class CCCipher : public BlockCipher {
CipherKey key; CipherKey key;
CCAlgorithm algorithm; CCAlgorithm algorithm;

View File

@ -47,6 +47,10 @@
# include <openssl/buffer.h> # include <openssl/buffer.h>
#endif #endif
#ifdef WITH_BOTAN
# include <botan/botan.h>
#endif
namespace encfs { namespace encfs {
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
@ -61,14 +65,16 @@ static void freeBlock( byte *block, int size )
OPENSSL_cleanse(block, size); OPENSSL_cleanse(block, size);
OPENSSL_free(block); OPENSSL_free(block);
} }
#elif defined(WITH_COMMON_CRYPTO)
#else
static byte *allocBlock(int size) { static byte *allocBlock(int size) {
byte *block = new byte[size]; byte *block = new byte[size];
return block; return block;
} }
unsigned char cleanse_ctr = 0; unsigned char cleanse_ctr = 0;
static void freeBlock(byte *data, int len) { static void cleanBlock(byte *data, int len) {
byte *p = data; byte *p = data;
size_t loop = len, ctr = cleanse_ctr; size_t loop = len, ctr = cleanse_ctr;
while(loop--) while(loop--)
@ -81,8 +87,8 @@ static void freeBlock(byte *data, int len) {
if(p) if(p)
ctr += (63 + (size_t)p); ctr += (63 + (size_t)p);
cleanse_ctr = (unsigned char)ctr; cleanse_ctr = (unsigned char)ctr;
delete[] data;
} }
#endif #endif
void MemBlock::allocate(int size) void MemBlock::allocate(int size)
@ -94,38 +100,49 @@ void MemBlock::allocate(int size)
MemBlock::~MemBlock() MemBlock::~MemBlock()
{ {
freeBlock(data, size); cleanBlock(data, size);
delete[] data;
} }
SecureMem::SecureMem(int len) SecureMem::SecureMem(int len)
#ifdef WITH_BOTAN
: data_(len)
#endif
{ {
rAssert(len > 0); rAssert(len > 0);
data = allocBlock(len); #ifndef WITH_BOTAN
if (data) data_ = allocBlock(len);
if (data_)
{ {
size = len; size_ = len;
mlock(data, size); mlock(data_, size_);
} else } else
{ {
size = 0; size_ = 0;
} }
#endif
} }
SecureMem::~SecureMem() SecureMem::~SecureMem()
{ {
if (size) #ifdef WITH_BOTAN
data_.destroy();
#else
if (size_)
{ {
freeBlock(data, size); cleanBlock(data_, size_);
munlock(data, size); delete[] data_;
munlock(data_, size_);
data = NULL; data_ = NULL;
size = 0; size_ = 0;
} }
#endif
} }
bool operator == (const SecureMem &a, const SecureMem &b) { bool operator == (const SecureMem &a, const SecureMem &b) {
return (a.size == b.size) && return (a.size() == b.size()) &&
(memcmp(a.data, b.data, a.size) == 0); (memcmp(a.data(), b.data(), a.size()) == 0);
} }
} // namespace encfs } // namespace encfs

View File

@ -21,12 +21,18 @@
#ifndef _MemoryPool_incl_ #ifndef _MemoryPool_incl_
#define _MemoryPool_incl_ #define _MemoryPool_incl_
#include "base/config.h"
#include "base/types.h" #include "base/types.h"
#ifdef WITH_BOTAN
#include <botan/secmem.h>
#endif
namespace encfs { namespace encfs {
/* /*
Memory Pool for fixed sized objects. Memory Pool for fixed sized objects.
Use SecureMem if storing sensitive information.
Usage: Usage:
MemBlock mb; MemBlock mb;
@ -55,13 +61,37 @@ inline MemBlock::MemBlock()
class SecureMem class SecureMem
{ {
public: public:
int size; byte* data() const;
byte *data; int size() const;
explicit SecureMem(int len); explicit SecureMem(int len);
~SecureMem(); ~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); bool operator == (const SecureMem &a, const SecureMem &b);
} // namespace encfs } // namespace encfs

View File

@ -10,7 +10,8 @@
namespace encfs { namespace encfs {
// Well-known algorithms. // 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. // Password Based Key Derivation Function.
class PBKDF class PBKDF

View File

@ -34,7 +34,7 @@ namespace {
TEST(PKCS5_PBKDF2_HMAC_SHA1, PBKDF) { TEST(PKCS5_PBKDF2_HMAC_SHA1, PBKDF) {
Registry<PBKDF> registry = PBKDF::GetRegistry(); Registry<PBKDF> registry = PBKDF::GetRegistry();
shared_ptr<PBKDF> impl( registry.CreateForMatch(NAME_PKCS5_PBKDF2_HMAC_SHA1)); shared_ptr<PBKDF> impl( registry.CreateForMatch(NAME_PBKDF2_HMAC_SHA1));
ASSERT_FALSE(!impl); ASSERT_FALSE(!impl);
// Test cases from rfc6070 // 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 } // namespace

141
cipher/botan.cpp Normal file
View 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
View 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

View File

@ -33,8 +33,6 @@
#include <valgrind/memcheck.h> #include <valgrind/memcheck.h>
#endif #endif
#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>
@ -449,7 +447,7 @@ class PbkdfPkcs5HmacSha1 : public PBKDF {
static Properties GetProperties() { static Properties GetProperties() {
Properties props; Properties props;
props.mode = NAME_PKCS5_PBKDF2_HMAC_SHA1; props.mode = NAME_PBKDF2_HMAC_SHA1;
props.library = "OpenSSL"; props.library = "OpenSSL";
return props; return props;
} }

View File

@ -1350,11 +1350,11 @@ std::string readPassword( int FD )
while(1) 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) if(rdSize > 0)
{ {
result.append( (char*)buf->data, rdSize ); result.append( (char*)buf->data(), rdSize );
} else } else
break; break;
} }
@ -1441,7 +1441,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((char *)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;
@ -1451,13 +1451,13 @@ SecureMem *passwordFromStdin()
{ {
SecureMem *buf = new SecureMem(MaxPassBuf); 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) if (res)
{ {
// Kill the trailing newline. // Kill the trailing newline.
int last = strnlen((char *)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';
} }
return buf; return buf;
@ -1469,7 +1469,7 @@ SecureMem *passwordFromPrompt()
// xgroup(common) // xgroup(common)
char *res = readpassphrase( _("EncFS Password: "), 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) if (!res)
{ {
delete buf; delete buf;
@ -1488,13 +1488,13 @@ SecureMem *passwordFromPrompts()
{ {
// xgroup(common) // xgroup(common)
char *res1 = readpassphrase(_("New Encfs Password: "), 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) // xgroup(common)
char *res2 = readpassphrase(_("Verify Encfs Password: "), 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 if(res1 && res2
&& !strncmp((char*)buf->data, (char*)buf2->data, MaxPassBuf)) && !strncmp((char*)buf->data(), (char*)buf2->data(), MaxPassBuf))
{ {
break; break;
} else } else
@ -1520,8 +1520,8 @@ CipherKey getUserKey(const EncfsConfig &config, bool useStdin)
if (password) if (password)
{ {
userKey = decryptKey(config, (char*)password->data, userKey = decryptKey(config, (char*)password->data(),
strlen((char*)password->data)); strlen((char*)password->data()));
delete password; delete password;
} }
@ -1536,8 +1536,8 @@ CipherKey getUserKey( const EncfsConfig &config, const std::string &passProg,
if (password) if (password)
{ {
result = decryptKey(config, (char*)password->data, result = decryptKey(config, (char*)password->data(),
strlen((char*)password->data)); strlen((char*)password->data()));
delete password; delete password;
} }
@ -1560,8 +1560,8 @@ CipherKey getNewUserKey(EncfsConfig &config,
if (password) if (password)
{ {
result = makeNewKey(config, (char*)password->data, result = makeNewKey(config, (char*)password->data(),
strlen((char*)password->data)); strlen((char*)password->data()));
delete password; delete password;
} }