libcryfs: Allow changing volume password
This commit is contained in:
parent
cf822d6a5b
commit
c5be03ad3a
@ -93,8 +93,6 @@ void CryConfigLoader::_checkMissingBlocksAreIntegrityViolations(CryConfigFile *c
|
|||||||
auto exclusiveClientId = configFile->config()->ExclusiveClientId();
|
auto exclusiveClientId = configFile->config()->ExclusiveClientId();
|
||||||
if (exclusiveClientId != none && *exclusiveClientId != myClientId) {
|
if (exclusiveClientId != none && *exclusiveClientId != myClientId) {
|
||||||
throw CryfsException("File system is in single-client mode and can only be used from the client that created it.", ErrorCode::SingleClientFileSystem);
|
throw CryfsException("File system is in single-client mode and can only be used from the client that created it.", ErrorCode::SingleClientFileSystem);
|
||||||
configFile->config()->SetExclusiveClientId(none);
|
|
||||||
configFile->save();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +108,15 @@ either<CryConfigFile::LoadError, CryConfigLoader::ConfigLoadResult> CryConfigLoa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::optional<CryConfigFile::LoadError> CryConfigLoader::changeEncryptionKey(bf::path filename, bool allowFilesystemUpgrade, bool allowReplacedFilesystem, unique_ref<CryKeyProvider> newKeyProvider) {
|
||||||
|
auto config = _loadConfig(filename, allowFilesystemUpgrade, allowReplacedFilesystem, CryConfigFile::Access::ReadWrite);
|
||||||
|
if (config.is_left()) {
|
||||||
|
return config.left();
|
||||||
|
}
|
||||||
|
CryConfigFile(filename, *config.right().configFile->config(), CryConfigEncryptorFactory::deriveNewKey(newKeyProvider.get()), CryConfigFile::Access::ReadWrite).save();
|
||||||
|
return none;
|
||||||
|
}
|
||||||
|
|
||||||
CryConfigLoader::ConfigLoadResult CryConfigLoader::_createConfig(bf::path filename, bool allowReplacedFilesystem) {
|
CryConfigLoader::ConfigLoadResult CryConfigLoader::_createConfig(bf::path filename, bool allowReplacedFilesystem) {
|
||||||
auto config = _creator.create(_cipherFromCommandLine, _blocksizeBytesFromCommandLine, _missingBlockIsIntegrityViolationFromCommandLine, allowReplacedFilesystem);
|
auto config = _creator.create(_cipherFromCommandLine, _blocksizeBytesFromCommandLine, _missingBlockIsIntegrityViolationFromCommandLine, allowReplacedFilesystem);
|
||||||
auto result = CryConfigFile::create(std::move(filename), config.config, _keyProvider.get());
|
auto result = CryConfigFile::create(std::move(filename), config.config, _keyProvider.get());
|
||||||
|
@ -26,6 +26,7 @@ public:
|
|||||||
|
|
||||||
cpputils::either<CryConfigFile::LoadError, CryConfigLoader::ConfigLoadResult> loadOrCreate(boost::filesystem::path filename, bool allowFilesystemUpgrade, bool allowReplacedFilesystem);
|
cpputils::either<CryConfigFile::LoadError, CryConfigLoader::ConfigLoadResult> loadOrCreate(boost::filesystem::path filename, bool allowFilesystemUpgrade, bool allowReplacedFilesystem);
|
||||||
cpputils::either<CryConfigFile::LoadError, CryConfigLoader::ConfigLoadResult> load(boost::filesystem::path filename, bool allowFilesystemUpgrade, bool allowReplacedFilesystem, CryConfigFile::Access access);
|
cpputils::either<CryConfigFile::LoadError, CryConfigLoader::ConfigLoadResult> load(boost::filesystem::path filename, bool allowFilesystemUpgrade, bool allowReplacedFilesystem, CryConfigFile::Access access);
|
||||||
|
boost::optional<CryConfigFile::LoadError> changeEncryptionKey(boost::filesystem::path filename, bool allowFilesystemUpgrade, bool allowReplacedFilesystem, cpputils::unique_ref<CryKeyProvider> newKeyProvider);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cpputils::either<CryConfigFile::LoadError, CryConfigLoader::ConfigLoadResult> _loadConfig(boost::filesystem::path filename, bool allowFilesystemUpgrade, bool allowReplacedFilesystem, CryConfigFile::Access access);
|
cpputils::either<CryConfigFile::LoadError, CryConfigLoader::ConfigLoadResult> _loadConfig(boost::filesystem::path filename, bool allowFilesystemUpgrade, bool allowReplacedFilesystem, CryConfigFile::Access access);
|
||||||
|
@ -11,21 +11,23 @@ namespace cryfs {
|
|||||||
CryPresetPasswordBasedKeyProvider::CryPresetPasswordBasedKeyProvider(std::string password, unique_ref<PasswordBasedKDF> kdf, SizedData* returnedHash)
|
CryPresetPasswordBasedKeyProvider::CryPresetPasswordBasedKeyProvider(std::string password, unique_ref<PasswordBasedKDF> kdf, SizedData* returnedHash)
|
||||||
: _password(std::move(password)), _kdf(std::move(kdf)), _returnedHash(returnedHash) {}
|
: _password(std::move(password)), _kdf(std::move(kdf)), _returnedHash(returnedHash) {}
|
||||||
|
|
||||||
|
void CryPresetPasswordBasedKeyProvider::saveEncryptionKey(EncryptionKey encryptionKey) {
|
||||||
|
if (_returnedHash != nullptr) {
|
||||||
|
_returnedHash->size = encryptionKey.binaryLength();
|
||||||
|
_returnedHash->data = new unsigned char[_returnedHash->size];
|
||||||
|
memcpy(_returnedHash->data, encryptionKey.data(), _returnedHash->size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
EncryptionKey CryPresetPasswordBasedKeyProvider::requestKeyForExistingFilesystem(size_t keySize, const Data& kdfParameters) {
|
EncryptionKey CryPresetPasswordBasedKeyProvider::requestKeyForExistingFilesystem(size_t keySize, const Data& kdfParameters) {
|
||||||
EncryptionKey encryptionKey = _kdf->deriveExistingKey(keySize, _password, kdfParameters);
|
EncryptionKey encryptionKey = _kdf->deriveExistingKey(keySize, _password, kdfParameters);
|
||||||
if (_returnedHash != nullptr) {
|
saveEncryptionKey(encryptionKey);
|
||||||
_returnedHash->data = static_cast<unsigned char*>(encryptionKey.data());
|
|
||||||
_returnedHash->size = encryptionKey.binaryLength();
|
|
||||||
}
|
|
||||||
return encryptionKey;
|
return encryptionKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
CryPresetPasswordBasedKeyProvider::KeyResult CryPresetPasswordBasedKeyProvider::requestKeyForNewFilesystem(size_t keySize) {
|
CryPresetPasswordBasedKeyProvider::KeyResult CryPresetPasswordBasedKeyProvider::requestKeyForNewFilesystem(size_t keySize) {
|
||||||
auto keyResult = _kdf->deriveNewKey(keySize, _password);
|
auto keyResult = _kdf->deriveNewKey(keySize, _password);
|
||||||
if (_returnedHash != nullptr) {
|
saveEncryptionKey(keyResult.key);
|
||||||
_returnedHash->data = static_cast<unsigned char*>(keyResult.key.data());
|
|
||||||
_returnedHash->size = keyResult.key.binaryLength();
|
|
||||||
}
|
|
||||||
return {std::move(keyResult.key), std::move(keyResult.kdfParameters)};
|
return {std::move(keyResult.key), std::move(keyResult.kdfParameters)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ namespace cryfs {
|
|||||||
KeyResult requestKeyForNewFilesystem(size_t keySize) override;
|
KeyResult requestKeyForNewFilesystem(size_t keySize) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void saveEncryptionKey(cpputils::EncryptionKey encryptionKey);
|
||||||
|
|
||||||
std::string _password;
|
std::string _password;
|
||||||
cpputils::unique_ref<cpputils::PasswordBasedKDF> _kdf;
|
cpputils::unique_ref<cpputils::PasswordBasedKDF> _kdf;
|
||||||
SizedData* _returnedHash;
|
SizedData* _returnedHash;
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
jlong cryfs_init(JNIEnv *env, jstring jbaseDir, jstring jlocalSateDir, jbyteArray jpassword,
|
jlong cryfs_init(JNIEnv *env, jstring jbaseDir, jstring jlocalSateDir, jbyteArray jpassword,
|
||||||
jbyteArray jgivenHash, jobject returnedHash, jboolean createBaseDir,
|
jbyteArray jgivenHash, jobject returnedHash, jboolean createBaseDir,
|
||||||
jstring jcipher);
|
jstring jcipher);
|
||||||
|
jboolean cryfs_change_encryption_key(JNIEnv *env,
|
||||||
|
jstring jbaseDir, jstring jlocalStateDir,
|
||||||
|
jbyteArray jcurrentPassword, jbyteArray jgivenHash,
|
||||||
|
jbyteArray jnewPassword, jobject jreturnedHash);
|
||||||
jlong cryfs_create(JNIEnv* env, jlong fusePtr, jstring jpath, mode_t mode);
|
jlong cryfs_create(JNIEnv* env, jlong fusePtr, jstring jpath, mode_t mode);
|
||||||
jlong cryfs_open(JNIEnv* env, jlong fusePtr, jstring jpath, jint flags);
|
jlong cryfs_open(JNIEnv* env, jlong fusePtr, jstring jpath, jint flags);
|
||||||
jint cryfs_read(JNIEnv* env, jlong fusePtr, jlong fileHandle, jbyteArray jbuffer, jlong offset);
|
jint cryfs_read(JNIEnv* env, jlong fusePtr, jlong fileHandle, jbyteArray jbuffer, jlong offset);
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <cryfs-cli/Cli.h>
|
#include <cryfs-cli/Cli.h>
|
||||||
#include <fspp/fuse/Fuse.h>
|
#include <fspp/fuse/Fuse.h>
|
||||||
|
#include <cryfs/impl/config/CryKeyProvider.h>
|
||||||
|
#include <cryfs/impl/config/CryDirectKeyProvider.h>
|
||||||
|
#include <cryfs/impl/config/CryPresetPasswordBasedKeyProvider.h>
|
||||||
|
|
||||||
using boost::none;
|
using boost::none;
|
||||||
using cpputils::Random;
|
using cpputils::Random;
|
||||||
@ -11,6 +14,14 @@ using fspp::fuse::Fuse;
|
|||||||
|
|
||||||
std::set<jlong> validFusePtrs;
|
std::set<jlong> validFusePtrs;
|
||||||
|
|
||||||
|
void setReturnedPasswordHash(JNIEnv* env, jobject jreturnedHash, const SizedData& returnedHash) {
|
||||||
|
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));
|
||||||
|
delete[] returnedHash.data;
|
||||||
|
env->SetObjectField(jreturnedHash, value, jpasswordHash);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" jlong
|
extern "C" jlong
|
||||||
cryfs_init(JNIEnv *env, jstring jbaseDir, jstring jlocalStateDir, jbyteArray jpassword,
|
cryfs_init(JNIEnv *env, jstring jbaseDir, jstring jlocalStateDir, jbyteArray jpassword,
|
||||||
jbyteArray jgivenHash, jobject jreturnedHash, jboolean createBaseDir,
|
jbyteArray jgivenHash, jobject jreturnedHash, jboolean createBaseDir,
|
||||||
@ -48,19 +59,65 @@ cryfs_init(JNIEnv *env, jstring jbaseDir, jstring jlocalStateDir, jbyteArray jpa
|
|||||||
if (jpassword == NULL) {
|
if (jpassword == NULL) {
|
||||||
env->ReleaseByteArrayElements(jgivenHash, reinterpret_cast<jbyte*>(credentials.givenHash.data), 0);
|
env->ReleaseByteArrayElements(jgivenHash, reinterpret_cast<jbyte*>(credentials.givenHash.data), 0);
|
||||||
}
|
}
|
||||||
|
if (credentials.returnedHash != nullptr) {
|
||||||
|
setReturnedPasswordHash(env, jreturnedHash, returnedHash);
|
||||||
|
}
|
||||||
jlong fusePtr = reinterpret_cast<jlong>(fuse);
|
jlong fusePtr = reinterpret_cast<jlong>(fuse);
|
||||||
if (fusePtr != 0) {
|
if (fusePtr != 0) {
|
||||||
validFusePtrs.insert(fusePtr);
|
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;
|
return fusePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" jboolean cryfs_change_encryption_key(JNIEnv* env, jstring jbaseDir, jstring jlocalStateDir,
|
||||||
|
jbyteArray jcurrentPassword, jbyteArray jgivenHash,
|
||||||
|
jbyteArray jnewPassword, jobject jreturnedHash) {
|
||||||
|
using namespace cryfs;
|
||||||
|
|
||||||
|
const char* baseDir = env->GetStringUTFChars(jbaseDir, NULL);
|
||||||
|
const char* localStateDir = env->GetStringUTFChars(jlocalStateDir, NULL);
|
||||||
|
|
||||||
|
struct SizedData givenHash;
|
||||||
|
std::unique_ptr<CryKeyProvider> currentKeyProvider;
|
||||||
|
if (jcurrentPassword == NULL) {
|
||||||
|
givenHash.data = reinterpret_cast<unsigned char*>(env->GetByteArrayElements(jgivenHash, NULL));
|
||||||
|
givenHash.size = env->GetArrayLength(jgivenHash);
|
||||||
|
currentKeyProvider = std::make_unique<CryDirectKeyProvider>(givenHash);
|
||||||
|
} else {
|
||||||
|
jbyte* currentPassword = env->GetByteArrayElements(jcurrentPassword, NULL);
|
||||||
|
currentKeyProvider = std::make_unique<CryPresetPasswordBasedKeyProvider>(
|
||||||
|
reinterpret_cast<const char*>(currentPassword),
|
||||||
|
cpputils::make_unique_ref<SCrypt>(SCrypt::DefaultSettings),
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
env->ReleaseByteArrayElements(jcurrentPassword, currentPassword, 0);
|
||||||
|
}
|
||||||
|
struct SizedData returnedHash = {nullptr, 0};
|
||||||
|
jbyte* newPassword = env->GetByteArrayElements(jnewPassword, NULL);
|
||||||
|
cpputils::unique_ref<CryKeyProvider> newKeyProvider = cpputils::make_unique_ref<CryPresetPasswordBasedKeyProvider>(
|
||||||
|
reinterpret_cast<const char*>(newPassword),
|
||||||
|
cpputils::make_unique_ref<SCrypt>(SCrypt::DefaultSettings),
|
||||||
|
jreturnedHash == NULL ? nullptr : &returnedHash
|
||||||
|
);
|
||||||
|
env->ReleaseByteArrayElements(jnewPassword, newPassword, 0);
|
||||||
|
CryConfigLoader configLoader = CryConfigLoader(
|
||||||
|
Random::OSRandom(), std::move(*cpputils::nullcheck(std::move(currentKeyProvider))),
|
||||||
|
LocalStateDir(localStateDir), none, none, none
|
||||||
|
);
|
||||||
|
env->ReleaseStringUTFChars(jlocalStateDir, localStateDir);
|
||||||
|
|
||||||
|
auto result = configLoader.changeEncryptionKey(boost::filesystem::path(baseDir) / "cryfs.config", false, false, std::move(newKeyProvider));
|
||||||
|
|
||||||
|
if (jcurrentPassword == NULL) {
|
||||||
|
env->ReleaseByteArrayElements(jgivenHash, reinterpret_cast<jbyte*>(givenHash.data), 0);
|
||||||
|
}
|
||||||
|
env->ReleaseStringUTFChars(jbaseDir, baseDir);
|
||||||
|
if (returnedHash.data != nullptr) {
|
||||||
|
setReturnedPasswordHash(env, jreturnedHash, returnedHash);
|
||||||
|
}
|
||||||
|
return result == none;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" jlong cryfs_create(JNIEnv* env, jlong fusePtr, jstring jpath, mode_t mode) {
|
extern "C" jlong cryfs_create(JNIEnv* env, jlong fusePtr, jstring jpath, mode_t mode) {
|
||||||
Fuse* fuse = reinterpret_cast<Fuse*>(fusePtr);
|
Fuse* fuse = reinterpret_cast<Fuse*>(fusePtr);
|
||||||
const char* path = env->GetStringUTFChars(jpath, NULL);
|
const char* path = env->GetStringUTFChars(jpath, NULL);
|
||||||
|
Loading…
Reference in New Issue
Block a user