Allow opening volumes with password hash
This commit is contained in:
parent
356cf8a160
commit
cf822d6a5b
10
src/cpp-utils/SizedData.h
Normal file
10
src/cpp-utils/SizedData.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#ifndef CPPUTILS_SIZEDDATA_H
|
||||
#define CPPUTILS_SIZEDDATA_H
|
||||
|
||||
struct SizedData {
|
||||
unsigned char* data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
#endif
|
@ -11,6 +11,7 @@
|
||||
#include <cpp-utils/io/DontEchoStdinToStdoutRAII.h>
|
||||
#include <cryfs/impl/filesystem/CryDevice.h>
|
||||
#include <cryfs/impl/config/CryConfigLoader.h>
|
||||
#include <cryfs/impl/config/CryDirectKeyProvider.h>
|
||||
#include <cryfs/impl/config/CryPresetPasswordBasedKeyProvider.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
@ -89,9 +90,9 @@ namespace cryfs_cli {
|
||||
basedirMetadata.save();
|
||||
}
|
||||
|
||||
CryConfigLoader::ConfigLoadResult Cli::_loadOrCreateConfig(const ProgramOptions &options, const LocalStateDir& localStateDir, unique_ptr<string> password) {
|
||||
CryConfigLoader::ConfigLoadResult Cli::_loadOrCreateConfig(const ProgramOptions &options, const LocalStateDir& localStateDir, Credentials credentials) {
|
||||
auto configFile = _determineConfigFile(options);
|
||||
auto config = _loadOrCreateConfigFile(std::move(configFile), localStateDir, std::move(password), options.cipher(), options.blocksizeBytes(), options.allowFilesystemUpgrade(), options.missingBlockIsIntegrityViolation(), options.allowReplacedFilesystem());
|
||||
auto config = _loadOrCreateConfigFile(std::move(configFile), localStateDir, credentials, options.cipher(), options.blocksizeBytes(), options.allowFilesystemUpgrade(), options.missingBlockIsIntegrityViolation(), options.allowReplacedFilesystem());
|
||||
if (config.is_left()) {
|
||||
switch(config.left()) {
|
||||
case CryConfigFile::LoadError::DecryptionFailed:
|
||||
@ -104,24 +105,30 @@ namespace cryfs_cli {
|
||||
return std::move(config.right());
|
||||
}
|
||||
|
||||
either<CryConfigFile::LoadError, CryConfigLoader::ConfigLoadResult> Cli::_loadOrCreateConfigFile(bf::path configFilePath, LocalStateDir localStateDir, unique_ptr<string> password, const optional<string> &cipher, const optional<uint32_t> &blocksizeBytes, bool allowFilesystemUpgrade, const optional<bool> &missingBlockIsIntegrityViolation, bool allowReplacedFilesystem) {
|
||||
// TODO Instead of passing in _askPasswordXXX functions to KeyProvider, only pass in console and move logic to the key provider,
|
||||
// for example by having a separate CryPasswordBasedKeyProvider / CryNoninteractivePasswordBasedKeyProvider.
|
||||
auto keyProvider = make_unique_ref<CryPresetPasswordBasedKeyProvider>(
|
||||
*password.get(),
|
||||
make_unique_ref<SCrypt>(_scryptSettings)
|
||||
unique_ref<CryKeyProvider> Cli::_createKeyProvider(Credentials credentials) {
|
||||
if (credentials.password == none) {
|
||||
return make_unique_ref<CryDirectKeyProvider>(credentials.givenHash);
|
||||
} else {
|
||||
return make_unique_ref<CryPresetPasswordBasedKeyProvider>(
|
||||
*credentials.password,
|
||||
make_unique_ref<SCrypt>(_scryptSettings),
|
||||
credentials.returnedHash
|
||||
);
|
||||
return CryConfigLoader(_keyGenerator, std::move(keyProvider), std::move(localStateDir), cipher, blocksizeBytes, missingBlockIsIntegrityViolation).loadOrCreate(std::move(configFilePath), allowFilesystemUpgrade, allowReplacedFilesystem);
|
||||
}
|
||||
}
|
||||
|
||||
fspp::fuse::Fuse* Cli::initFilesystem(const ProgramOptions &options, unique_ptr<string> password) {
|
||||
either<CryConfigFile::LoadError, CryConfigLoader::ConfigLoadResult> Cli::_loadOrCreateConfigFile(bf::path configFilePath, LocalStateDir localStateDir, Credentials credentials, const optional<string> &cipher, const optional<uint32_t> &blocksizeBytes, bool allowFilesystemUpgrade, const optional<bool> &missingBlockIsIntegrityViolation, bool allowReplacedFilesystem) {
|
||||
return CryConfigLoader(_keyGenerator, _createKeyProvider(credentials), std::move(localStateDir), cipher, blocksizeBytes, missingBlockIsIntegrityViolation).loadOrCreate(std::move(configFilePath), allowFilesystemUpgrade, allowReplacedFilesystem);
|
||||
}
|
||||
|
||||
fspp::fuse::Fuse* Cli::initFilesystem(const ProgramOptions &options, Credentials credentials) {
|
||||
cpputils::showBacktraceOnCrash();
|
||||
cpputils::set_thread_name("cryfs");
|
||||
try {
|
||||
_sanityChecks(options);
|
||||
LocalStateDir localStateDir(options.localStateDir());
|
||||
auto blockStore = make_unique_ref<OnDiskBlockStore2>(options.baseDir());
|
||||
auto config = _loadOrCreateConfig(options, localStateDir, std::move(password));
|
||||
auto config = _loadOrCreateConfig(options, localStateDir, credentials);
|
||||
fspp::fuse::Fuse* fuse = nullptr;
|
||||
|
||||
auto onIntegrityViolation = [&fuse] () {
|
||||
|
@ -5,11 +5,13 @@
|
||||
#include <fspp/fuse/Fuse.h>
|
||||
#include "program_options/ProgramOptions.h"
|
||||
#include <cryfs/impl/config/CryConfigFile.h>
|
||||
#include <cryfs/impl/config/CryKeyProvider.h>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <cpp-utils/tempfile/TempFile.h>
|
||||
#include <cpp-utils/io/Console.h>
|
||||
#include <cpp-utils/random/RandomGenerator.h>
|
||||
#include <cpp-utils/network/HttpClient.h>
|
||||
#include <cpp-utils/SizedData.h>
|
||||
#include <cryfs/impl/filesystem/CryDevice.h>
|
||||
#include "CallAfterTimeout.h"
|
||||
#include <cryfs/impl/config/CryConfigLoader.h>
|
||||
@ -18,16 +20,20 @@
|
||||
namespace cryfs_cli {
|
||||
class Cli final {
|
||||
public:
|
||||
struct Credentials {
|
||||
boost::optional<string> password;
|
||||
SizedData givenHash;
|
||||
SizedData* returnedHash;
|
||||
};
|
||||
Cli(cpputils::RandomGenerator &keyGenerator, const cpputils::SCryptSettings& scryptSettings);
|
||||
fspp::fuse::Fuse* initFilesystem(const program_options::ProgramOptions &options, std::unique_ptr<string> password);
|
||||
fspp::fuse::Fuse* initFilesystem(const program_options::ProgramOptions &options, Credentials credentials);
|
||||
|
||||
private:
|
||||
void _checkForUpdates(cpputils::unique_ref<cpputils::HttpClient> httpClient);
|
||||
cryfs::CryConfigLoader::ConfigLoadResult _loadOrCreateConfig(const program_options::ProgramOptions &options, const cryfs::LocalStateDir& localStateDir, std::unique_ptr<string> password);
|
||||
cryfs::CryConfigLoader::ConfigLoadResult _loadOrCreateConfig(const program_options::ProgramOptions &options, const cryfs::LocalStateDir& localStateDir, Credentials credentials);
|
||||
void _checkConfigIntegrity(const boost::filesystem::path& basedir, const cryfs::LocalStateDir& localStateDir, const cryfs::CryConfigFile& config, bool allowReplacedFilesystem);
|
||||
cpputils::either<cryfs::CryConfigFile::LoadError, cryfs::CryConfigLoader::ConfigLoadResult> _loadOrCreateConfigFile(boost::filesystem::path configFilePath, cryfs::LocalStateDir localStateDir, std::unique_ptr<string> password, const boost::optional<std::string> &cipher, const boost::optional<uint32_t> &blocksizeBytes, bool allowFilesystemUpgrade, const boost::optional<bool> &missingBlockIsIntegrityViolation, bool allowReplacedFilesystem);
|
||||
cpputils::unique_ref<cryfs::CryKeyProvider> _createKeyProvider(Credentials credentials);
|
||||
cpputils::either<cryfs::CryConfigFile::LoadError, cryfs::CryConfigLoader::ConfigLoadResult> _loadOrCreateConfigFile(boost::filesystem::path configFilePath, cryfs::LocalStateDir localStateDir, Credentials credentials, const boost::optional<std::string> &cipher, const boost::optional<uint32_t> &blocksizeBytes, bool allowFilesystemUpgrade, const boost::optional<bool> &missingBlockIsIntegrityViolation, bool allowReplacedFilesystem);
|
||||
boost::filesystem::path _determineConfigFile(const program_options::ProgramOptions &options);
|
||||
void _initLogfile();
|
||||
void _sanityChecks(const program_options::ProgramOptions &options);
|
||||
void _checkDirAccessible(const boost::filesystem::path &dir, const std::string &name, bool createMissingDir, cryfs::ErrorCode errorCode);
|
||||
void _sanityCheckFilesystem(cryfs::CryDevice *device);
|
||||
|
@ -19,6 +19,7 @@ set(LIB_SOURCES
|
||||
impl/config/CryKeyProvider.cpp
|
||||
impl/config/CryPasswordBasedKeyProvider.cpp
|
||||
impl/config/CryPresetPasswordBasedKeyProvider.cpp
|
||||
impl/config/CryDirectKeyProvider.cpp
|
||||
impl/filesystem/CryOpenFile.cpp
|
||||
impl/filesystem/fsblobstore/utils/DirEntry.cpp
|
||||
impl/filesystem/fsblobstore/utils/DirEntryList.cpp
|
||||
|
18
src/cryfs/impl/config/CryDirectKeyProvider.cpp
Normal file
18
src/cryfs/impl/config/CryDirectKeyProvider.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
#include "CryDirectKeyProvider.h"
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
CryDirectKeyProvider::CryDirectKeyProvider(SizedData encryptionKey) : _encryptionKey(encryptionKey) {}
|
||||
|
||||
cpputils::EncryptionKey CryDirectKeyProvider::requestKeyForExistingFilesystem(size_t keySize, const cpputils::Data& kdfParameters) {
|
||||
ASSERT(_encryptionKey.size == keySize, "CryDirectKeyProvider: Invalid key size requested");
|
||||
cpputils::EncryptionKey encryptionKey = cpputils::EncryptionKey::Null(_encryptionKey.size);
|
||||
memcpy(encryptionKey.data(), _encryptionKey.data, _encryptionKey.size);
|
||||
return encryptionKey;
|
||||
}
|
||||
|
||||
CryKeyProvider::KeyResult CryDirectKeyProvider::requestKeyForNewFilesystem(size_t keySize) {
|
||||
throw std::logic_error("CryDirectKeyProvider can't be used for new filesystems");
|
||||
}
|
||||
|
||||
}
|
25
src/cryfs/impl/config/CryDirectKeyProvider.h
Normal file
25
src/cryfs/impl/config/CryDirectKeyProvider.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#ifndef CRYFS_CRYDIRECTKEYPROVIDER_H
|
||||
#define CRYFS_CRYDIRECTKEYPROVIDER_H
|
||||
|
||||
#include "CryKeyProvider.h"
|
||||
#include <cpp-utils/SizedData.h>
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
class CryDirectKeyProvider final : public CryKeyProvider {
|
||||
public:
|
||||
explicit CryDirectKeyProvider(SizedData encryptionKey);
|
||||
|
||||
cpputils::EncryptionKey requestKeyForExistingFilesystem(size_t keySize, const cpputils::Data& kdfParameters) override;
|
||||
KeyResult requestKeyForNewFilesystem(size_t keySize) override;
|
||||
|
||||
private:
|
||||
SizedData _encryptionKey;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CryDirectKeyProvider);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -8,15 +8,24 @@ using cpputils::Data;
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
CryPresetPasswordBasedKeyProvider::CryPresetPasswordBasedKeyProvider(std::string password, unique_ref<PasswordBasedKDF> kdf)
|
||||
: _password(std::move(password)), _kdf(std::move(kdf)) {}
|
||||
CryPresetPasswordBasedKeyProvider::CryPresetPasswordBasedKeyProvider(std::string password, unique_ref<PasswordBasedKDF> kdf, SizedData* returnedHash)
|
||||
: _password(std::move(password)), _kdf(std::move(kdf)), _returnedHash(returnedHash) {}
|
||||
|
||||
EncryptionKey CryPresetPasswordBasedKeyProvider::requestKeyForExistingFilesystem(size_t keySize, const Data& kdfParameters) {
|
||||
return _kdf->deriveExistingKey(keySize, _password, kdfParameters);
|
||||
EncryptionKey encryptionKey = _kdf->deriveExistingKey(keySize, _password, kdfParameters);
|
||||
if (_returnedHash != nullptr) {
|
||||
_returnedHash->data = static_cast<unsigned char*>(encryptionKey.data());
|
||||
_returnedHash->size = encryptionKey.binaryLength();
|
||||
}
|
||||
return encryptionKey;
|
||||
}
|
||||
|
||||
CryPresetPasswordBasedKeyProvider::KeyResult CryPresetPasswordBasedKeyProvider::requestKeyForNewFilesystem(size_t keySize) {
|
||||
auto keyResult = _kdf->deriveNewKey(keySize, _password);
|
||||
if (_returnedHash != nullptr) {
|
||||
_returnedHash->data = static_cast<unsigned char*>(keyResult.key.data());
|
||||
_returnedHash->size = keyResult.key.binaryLength();
|
||||
}
|
||||
return {std::move(keyResult.key), std::move(keyResult.kdfParameters)};
|
||||
}
|
||||
|
||||
|
@ -5,12 +5,17 @@
|
||||
#include "CryKeyProvider.h"
|
||||
#include <functional>
|
||||
#include <cpp-utils/crypto/kdf/PasswordBasedKDF.h>
|
||||
#include <cpp-utils/SizedData.h>
|
||||
|
||||
namespace cryfs {
|
||||
|
||||
class CryPresetPasswordBasedKeyProvider final : public CryKeyProvider {
|
||||
public:
|
||||
explicit CryPresetPasswordBasedKeyProvider(std::string password, cpputils::unique_ref<cpputils::PasswordBasedKDF> kdf);
|
||||
explicit CryPresetPasswordBasedKeyProvider(
|
||||
std::string password,
|
||||
cpputils::unique_ref<cpputils::PasswordBasedKDF> kdf,
|
||||
SizedData* returnedHash
|
||||
);
|
||||
|
||||
cpputils::EncryptionKey requestKeyForExistingFilesystem(size_t keySize, const cpputils::Data& kdfParameters) override;
|
||||
KeyResult requestKeyForNewFilesystem(size_t keySize) override;
|
||||
@ -18,6 +23,7 @@ namespace cryfs {
|
||||
private:
|
||||
std::string _password;
|
||||
cpputils::unique_ref<cpputils::PasswordBasedKDF> _kdf;
|
||||
SizedData* _returnedHash;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CryPresetPasswordBasedKeyProvider);
|
||||
};
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include <jni.h>
|
||||
|
||||
jlong cryfs_init(JNIEnv* env, jstring jbaseDir, jstring jlocalSateDir, jbyteArray jpassword, jboolean createBaseDir, jstring jcipher);
|
||||
jlong cryfs_init(JNIEnv *env, jstring jbaseDir, jstring jlocalSateDir, jbyteArray jpassword,
|
||||
jbyteArray jgivenHash, jobject returnedHash, jboolean createBaseDir,
|
||||
jstring jcipher);
|
||||
jlong cryfs_create(JNIEnv* env, jlong fusePtr, jstring jpath, mode_t mode);
|
||||
jlong cryfs_open(JNIEnv* env, jlong fusePtr, jstring jpath, jint flags);
|
||||
jint cryfs_read(JNIEnv* env, jlong fusePtr, jlong fileHandle, jbyteArray jbuffer, jlong offset);
|
||||
|
@ -2,8 +2,6 @@
|
||||
#include <cryfs-cli/Cli.h>
|
||||
#include <fspp/fuse/Fuse.h>
|
||||
|
||||
using std::unique_ptr;
|
||||
using std::make_unique;
|
||||
using boost::none;
|
||||
using cpputils::Random;
|
||||
using cpputils::SCrypt;
|
||||
@ -13,7 +11,10 @@ using fspp::fuse::Fuse;
|
||||
|
||||
std::set<jlong> validFusePtrs;
|
||||
|
||||
extern "C" jlong cryfs_init(JNIEnv* env, jstring jbaseDir, jstring jlocalStateDir, jbyteArray jpassword, jboolean createBaseDir, jstring jcipher) {
|
||||
extern "C" jlong
|
||||
cryfs_init(JNIEnv *env, jstring jbaseDir, jstring jlocalStateDir, jbyteArray jpassword,
|
||||
jbyteArray jgivenHash, jobject jreturnedHash, jboolean createBaseDir,
|
||||
jstring jcipher) {
|
||||
const char* baseDir = env->GetStringUTFChars(jbaseDir, NULL);
|
||||
const char* localStateDir = env->GetStringUTFChars(jlocalStateDir, NULL);
|
||||
boost::optional<string> cipher = none;
|
||||
@ -24,17 +25,38 @@ extern "C" jlong cryfs_init(JNIEnv* env, jstring jbaseDir, jstring jlocalStateDi
|
||||
}
|
||||
auto &keyGenerator = Random::OSRandom();
|
||||
ProgramOptions options = ProgramOptions(baseDir, none, localStateDir, false, false, createBaseDir, cipher, none, false, none);
|
||||
char* password = reinterpret_cast<char*>(env->GetByteArrayElements(jpassword, NULL));
|
||||
|
||||
Fuse* fuse = Cli(keyGenerator, SCrypt::DefaultSettings).initFilesystem(options, make_unique<string>(password));
|
||||
|
||||
env->ReleaseByteArrayElements(jpassword, reinterpret_cast<jbyte*>(password), 0);
|
||||
env->ReleaseStringUTFChars(jbaseDir, baseDir);
|
||||
env->ReleaseStringUTFChars(jlocalStateDir, localStateDir);
|
||||
struct SizedData returnedHash;
|
||||
struct Cli::Credentials credentials;
|
||||
credentials.returnedHash = nullptr;
|
||||
if (jpassword == NULL) {
|
||||
credentials.password = none;
|
||||
credentials.givenHash.data = reinterpret_cast<unsigned char*>(env->GetByteArrayElements(jgivenHash, NULL));
|
||||
credentials.givenHash.size = env->GetArrayLength(jgivenHash);
|
||||
} else {
|
||||
jbyte* password = env->GetByteArrayElements(jpassword, NULL);
|
||||
credentials.password = string(reinterpret_cast<const char*>(password));
|
||||
env->ReleaseByteArrayElements(jpassword, password, 0);
|
||||
if (jreturnedHash != NULL) {
|
||||
credentials.returnedHash = &returnedHash;
|
||||
}
|
||||
}
|
||||
|
||||
Fuse* fuse = Cli(keyGenerator, SCrypt::DefaultSettings).initFilesystem(options, credentials);
|
||||
|
||||
if (jpassword == NULL) {
|
||||
env->ReleaseByteArrayElements(jgivenHash, reinterpret_cast<jbyte*>(credentials.givenHash.data), 0);
|
||||
}
|
||||
jlong fusePtr = reinterpret_cast<jlong>(fuse);
|
||||
if (fusePtr != 0) {
|
||||
validFusePtrs.insert(fusePtr);
|
||||
if (credentials.returnedHash != nullptr) {
|
||||
jfieldID value = env->GetFieldID(env->GetObjectClass(jreturnedHash), "value", "Ljava/lang/Object;");
|
||||
jbyteArray jpasswordHash = env->NewByteArray(returnedHash.size);
|
||||
env->SetByteArrayRegion(jpasswordHash, 0, returnedHash.size, reinterpret_cast<const jbyte*>(returnedHash.data));
|
||||
env->SetObjectField(jreturnedHash, value, jpasswordHash);
|
||||
}
|
||||
}
|
||||
return fusePtr;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user