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();
|
||||
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);
|
||||
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) {
|
||||
auto config = _creator.create(_cipherFromCommandLine, _blocksizeBytesFromCommandLine, _missingBlockIsIntegrityViolationFromCommandLine, allowReplacedFilesystem);
|
||||
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> 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:
|
||||
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)
|
||||
: _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 encryptionKey = _kdf->deriveExistingKey(keySize, _password, kdfParameters);
|
||||
if (_returnedHash != nullptr) {
|
||||
_returnedHash->data = static_cast<unsigned char*>(encryptionKey.data());
|
||||
_returnedHash->size = encryptionKey.binaryLength();
|
||||
}
|
||||
saveEncryptionKey(encryptionKey);
|
||||
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();
|
||||
}
|
||||
saveEncryptionKey(keyResult.key);
|
||||
return {std::move(keyResult.key), std::move(keyResult.kdfParameters)};
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,8 @@ namespace cryfs {
|
||||
KeyResult requestKeyForNewFilesystem(size_t keySize) override;
|
||||
|
||||
private:
|
||||
void saveEncryptionKey(cpputils::EncryptionKey encryptionKey);
|
||||
|
||||
std::string _password;
|
||||
cpputils::unique_ref<cpputils::PasswordBasedKDF> _kdf;
|
||||
SizedData* _returnedHash;
|
||||
|
@ -3,6 +3,10 @@
|
||||
jlong cryfs_init(JNIEnv *env, jstring jbaseDir, jstring jlocalSateDir, jbyteArray jpassword,
|
||||
jbyteArray jgivenHash, jobject returnedHash, jboolean createBaseDir,
|
||||
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_open(JNIEnv* env, jlong fusePtr, jstring jpath, jint flags);
|
||||
jint cryfs_read(JNIEnv* env, jlong fusePtr, jlong fileHandle, jbyteArray jbuffer, jlong offset);
|
||||
|
@ -1,6 +1,9 @@
|
||||
#include <jni.h>
|
||||
#include <cryfs-cli/Cli.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 cpputils::Random;
|
||||
@ -11,6 +14,14 @@ using fspp::fuse::Fuse;
|
||||
|
||||
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
|
||||
cryfs_init(JNIEnv *env, jstring jbaseDir, jstring jlocalStateDir, jbyteArray jpassword,
|
||||
jbyteArray jgivenHash, jobject jreturnedHash, jboolean createBaseDir,
|
||||
@ -48,19 +59,65 @@ cryfs_init(JNIEnv *env, jstring jbaseDir, jstring jlocalStateDir, jbyteArray jpa
|
||||
if (jpassword == NULL) {
|
||||
env->ReleaseByteArrayElements(jgivenHash, reinterpret_cast<jbyte*>(credentials.givenHash.data), 0);
|
||||
}
|
||||
if (credentials.returnedHash != nullptr) {
|
||||
setReturnedPasswordHash(env, jreturnedHash, returnedHash);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
Fuse* fuse = reinterpret_cast<Fuse*>(fusePtr);
|
||||
const char* path = env->GetStringUTFChars(jpath, NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user