Compare commits

..

54 Commits

Author SHA1 Message Date
Matéo Duparc 6388eaf433
libcryfs: update Boost-for-Android 2023-09-08 21:11:04 +02:00
Matéo Duparc bfbd412a36
libcryfs: update spdlog to v1.12.0 2023-09-07 17:23:22 +02:00
Matéo Duparc fb45c8e8b6
libcryfs: update to cryfs v0.11.4 2023-09-07 17:21:38 +02:00
Sebastian Messmer 2c86a6ed37 Mark 0.11.4 as released 2023-07-19 22:26:32 -07:00
Sebastian Messmer 804509aff9 Fixed build issue with Python 3.12 2023-07-13 19:30:13 -07:00
Sebastian Meßmer 245b84526e Disable broken CI job 2023-07-12 10:58:30 -07:00
Sebastian Messmer 2338bb24f8 Add Clang 10 to 15 to CI 2023-07-11 19:42:33 -07:00
Sebastian Messmer 8eb7e85cad Add GCC 11, 12, 13 to CI 2023-07-11 19:42:29 -07:00
Sebastian Messmer 3930a86a74 Fix CI
- Remove ubuntu 18.04 from CI because GitHub deprecated it
- Replace macos-10 with macos-11, macos-12 and macos-13
- Add ubuntu 22.04 to CI
- Fix Clang 11 build
2023-07-11 19:42:13 -07:00
Sebastian Meßmer 699a3c020c
Update ChangeLog.txt 2023-06-17 23:34:31 -07:00
Matéo Duparc 3c56f86d86
libcryfs: make cryfs_init return error code 2023-05-03 00:01:26 +02:00
Matéo Duparc f40c2bbdcd
libcryfs: update spdlog 2023-04-18 16:32:18 +02:00
Matéo Duparc 445b26395b
libcryfs: update spdlog 2023-03-15 18:56:57 +01:00
Sebastian Messmer 6198908e86 Mention https://github.com/cryfs/cryfs/pull/448 fix in changelog 2023-02-26 13:56:29 -08:00
Adam Williamson 3f249ff1cd Include stdexcept when using logic_error
Signed-off-by: Adam Williamson <awilliam@redhat.com>
2023-02-26 13:55:20 -08:00
Sebastian Messmer 7c7e788367 Fix conan version to 1.x because 2.0 doesn't work for us yet 2023-02-26 13:36:33 -08:00
Matéo Duparc 43de737624
libcryfs: Fix Crypto++ build 2023-02-03 22:02:44 +01:00
Matéo Duparc ba5df7390b
libcryfs: Fix typo & version 2023-02-01 23:52:19 +01:00
Matéo Duparc a1c3f814d5
libcryfs: Update to cryfs v0.11.3 2023-02-01 23:39:12 +01:00
Sebastian Messmer 9845175dca On some systems, when mounting a test file system, the OS asks for /.Trash and /.Trash-1000 and will unmount if the file system returns an error. So let's tell the operating system that those don't exist instead 2022-10-15 15:05:44 -07:00
Sebastian Messmer 2bbac4956b Add GCC 10 to CI 2022-10-12 23:57:58 -07:00
Sebastian Messmer 539c0db9b0 Fix CI apt-get timeouts by retrying more often 2022-10-12 11:06:11 -07:00
Sebastian Messmer 33e205f642 It's actually clang 7 not gcc 7 that we need to disable on CI, and we only need to disable it on macos. Linux can still run it. 2022-10-11 21:03:33 -07:00
Sebastian Messmer cbb47f5ded Re-add CI for Linux GCC 7, only remove GCC 7 CI on macos 2022-10-11 20:49:04 -07:00
Sebastian Messmer beadb781aa Remove GCC 7 from CI because the macos CI machines cannot install it anymore 2022-10-11 20:45:39 -07:00
Sebastian Messmer 19598c4539 Clarify fix statement 2022-10-11 18:56:51 -07:00
D Lamb bbc7acc30f minor: shebang python -> python3 (#439)
Co-authored-by: D Lamb <dlamb.gh@mm.st>
2022-10-11 18:56:45 -07:00
Sebastian Messmer c878243074 Mention Apple python fix 2022-10-11 18:54:02 -07:00
Onuralp Sezer 231a60a611 change unversioned python commandline into versioned python3 commandline (#413)
Signed-off-by: Onuralp SEZER <thunderbirdtr@fedoraproject.org>
2022-10-11 18:52:44 -07:00
Sebastian Messmer fd3c54fe69 Mention Apple Silicon build fix 2022-10-11 18:48:17 -07:00
Sebastian Messmer abaa72d39c Fix building on Apple Silicon Macs (see https://github.com/cryfs/homebrew-tap/issues/10 ) 2022-10-11 18:48:12 -07:00
Matéo Duparc dc82772e5e
More controllable file read/write 2022-09-23 20:54:23 +02:00
Matéo Duparc c0600c2624
libcryfs: Fix password length bug 2022-09-21 19:09:59 +02:00
Matéo Duparc 7bc65e9bde
libcryfs: Update Boost-for-Android 2022-09-20 16:15:20 +02:00
Bernhard Rosenkraenzer ee6250380f Fix build with fmt 9.0 (#433)
* Fix build with fmt 9.0

Co-authored-by: Sebastian Meßmer <smessmer@users.noreply.github.com>
2022-07-22 07:36:34 -05:00
Matéo Duparc c5be03ad3a
libcryfs: Allow changing volume password 2022-06-30 21:40:04 +02:00
Matéo Duparc cf822d6a5b
Allow opening volumes with password hash 2022-06-29 13:27:33 +02:00
Matéo Duparc 356cf8a160
libcryfs: Remove automatic version detection 2022-06-26 15:14:16 +02:00
Matéo Duparc cabe9180e7
libcryfs: Fix typo in README 2022-06-26 13:58:42 +02:00
Matéo Duparc 335815d25a
libcryfs: Genesis 2022-06-26 13:03:57 +02:00
Sebastian Messmer dc330fa22e Mention OpenMP fix 2022-02-21 21:22:55 -08:00
Antonio Rojas 3f50e7d238 Fix OpenMP support (#415)
Prevent crypto++ from building the library via an intermediate object target. This is not necessary as we are only building the static library, and breaks passing the build flags that enable openMP support.
2022-02-21 21:22:32 -08:00
Sebastian Messmer 0ef2693df6 Mark 0.11.1 as released 2021-12-23 09:06:28 +01:00
Sebastian Messmer fe71144377 Update to DokanY 1.2.2.1001 2021-12-22 22:18:19 +01:00
Sebastian Messmer 26ea5a0209 Fix Subprocess on Windows 2021-12-22 22:12:03 +01:00
Sebastian Messmer b68f1b4b9e Don't run SubprocessTest under TSAN since TSAN deadlocks with atfork handlers 2021-12-13 15:15:30 +01:00
Sebastian Messmer 31c9290487 Fix subprocess call sites 2021-12-12 13:14:05 +01:00
Sebastian Messmer c4bc749fa6 Process I/O needs to use the async API to avoid deadlocks 2021-12-12 13:00:22 +01:00
Sebastian Messmer e524468cc1 Disable tests that are broken on windows 2021-12-11 23:06:22 +01:00
Sebastian Messmer 67bd0ed295 Flush logs in test cases 2021-12-11 12:04:20 +01:00
Sebastian Messmer 69770c77d4 cryfs-unmount correctly unmounts paths that contain spaces 2021-12-10 17:51:52 +01:00
Sebastian Messmer afd6f0d317 Update to CryptoPP 8.6. This fixes a rare bug where CryptoPP 8.5 encrypts data wrongly, see https://github.com/weidai11/cryptopp/issues/1069 2021-12-10 09:10:29 +01:00
Sebastian Messmer 69370a5d15 Fix building of the range-v3 dependency. The conan remote URL for this dependency changed and we have to use the new URL. This broke the homebrew build as well. 2021-12-09 15:12:45 +01:00
Sebastian Messmer cd5121080a Clear conan cache in CI 2021-12-09 15:12:37 +01:00
29 changed files with 277 additions and 2389 deletions

View File

@ -42,5 +42,8 @@ if(MSVC)
add_definitions(/bigobj)
endif()
# Hardcoded version. Don't forget to change this when merging upstream!
set(GIT_VERSION "0.11.4-libcryfs")
add_subdirectory(vendor EXCLUDE_FROM_ALL)
add_subdirectory(src)

View File

@ -1,6 +1,13 @@
Version 0.12.0 (unreleased)
Version 0.11.4
---------------
* Updated to DokanY 1.3.0.1000
* Fixed build issue with GCC 13 (see https://github.com/cryfs/cryfs/pull/448 )
* Fixed build issue with Python 3.12 (see https://github.com/cryfs/cryfs/issues/459 )
Version 0.11.3
---------------
* Fixed build issue on systems with libfmt 9.0 (see https://github.com/cryfs/cryfs/issues/432 )
* Fixed build issue on Apple Silicon Macs (see https://github.com/cryfs/homebrew-tap/issues/10 )
* Fixed build issue on systems that only have `python3` but no `python` executable (see https://github.com/cryfs/homebrew-tap/issues/12 )
Version 0.11.2
---------------

View File

@ -1,4 +1,4 @@
libcryfs is a re-desing of the original [CryFS](https://github.com/cryfs/cryfs) code to work as a library. Volumes are not mounted with [FUSE](https://www.kernel.org/doc/html/latest/filesystems/fuse.html) but rather opened in memory and accessed through API calls. What the purpose ?
libcryfs is a re-design of the original [CryFS](https://github.com/cryfs/cryfs) code to work as a library. Volumes are not mounted with [FUSE](https://www.kernel.org/doc/html/latest/filesystems/fuse.html) but rather opened in memory and accessed through API calls. What's the purpose ?
- Allow the use of CryFS on platforms where FUSE is not available (such as Android)
- Reduce attack surface by restricting volumes access to only one process rather than one user
@ -14,6 +14,7 @@ Here is what has been modified from the original project:
- sh scripts, `cpack`, `doc`, `test` and `vendor/googletest` deleted
- Main program `cryfs-cli` removed
- boost build configured with [Boost-for-Android](https://github.com/moritz-wundke/Boost-for-Android)
- Automatic version detection removed
- Interactive mode removed (including any writes to stdout)
- Logging output redirected to logcat
- JNI API created in `src/jni`

10
src/cpp-utils/SizedData.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#ifndef CPPUTILS_SIZEDDATA_H
#define CPPUTILS_SIZEDDATA_H
struct SizedData {
unsigned char* data;
size_t size;
};
#endif

View File

@ -4,6 +4,7 @@
#include <thread>
#include <cpp-utils/macros.h>
#include <array>
#include <stdexcept>
namespace cpputils {

View File

@ -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)
);
return CryConfigLoader(_keyGenerator, std::move(keyProvider), std::move(localStateDir), cipher, blocksizeBytes, missingBlockIsIntegrityViolation).loadOrCreate(std::move(configFilePath), allowFilesystemUpgrade, allowReplacedFilesystem);
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
);
}
}
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] () {
@ -145,14 +152,12 @@ namespace cryfs_cli {
return make_shared<fspp::FilesystemImpl>(std::move(*_device));
};
fuse = new fspp::fuse::Fuse(initFilesystem, "cryfs", "cryfs@" + options.baseDir().string());
fuse = new fspp::fuse::Fuse(initFilesystem);
fuse->init();
return fuse;
} catch (const CryfsException &e) {
if (e.what() != string()) {
LOG(ERR, "Error {}: {}", static_cast<int>(e.errorCode()), e.what());
}
throw; // CryfsException is only thrown if setup goes wrong. Throw it through so that we get the correct process exit code.
} catch (const std::exception &e) {
LOG(ERR, "Crashed: {}", e.what());
} catch (...) {

View File

@ -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);

View File

@ -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

View File

@ -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());

View File

@ -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);

View 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");
}
}

View 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

View File

@ -8,15 +8,26 @@ 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) {}
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) {
return _kdf->deriveExistingKey(keySize, _password, kdfParameters);
EncryptionKey encryptionKey = _kdf->deriveExistingKey(keySize, _password, kdfParameters);
saveEncryptionKey(encryptionKey);
return encryptionKey;
}
CryPresetPasswordBasedKeyProvider::KeyResult CryPresetPasswordBasedKeyProvider::requestKeyForNewFilesystem(size_t keySize) {
auto keyResult = _kdf->deriveNewKey(keySize, _password);
saveEncryptionKey(keyResult.key);
return {std::move(keyResult.key), std::move(keyResult.kdfParameters)};
}

View File

@ -5,19 +5,27 @@
#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;
private:
void saveEncryptionKey(cpputils::EncryptionKey encryptionKey);
std::string _password;
cpputils::unique_ref<cpputils::PasswordBasedKDF> _kdf;
SizedData* _returnedHash;
DISALLOW_COPY_AND_ASSIGN(CryPresetPasswordBasedKeyProvider);
};

View File

@ -58,16 +58,8 @@ public:
// Remove the following line, if you don't want to output each fuse operation on the console
//#define FSPP_LOG 1
Fuse::~Fuse() {
for(char *arg : _argv) {
delete[] arg;
arg = nullptr;
}
_argv.clear();
}
Fuse::Fuse(std::function<shared_ptr<Filesystem> ()> init, std::string fstype, boost::optional<std::string> fsname)
:_init(std::move(init)), _fs(make_shared<InvalidFilesystem>()), _running(false), _fstype(std::move(fstype)), _fsname(std::move(fsname)) {
Fuse::Fuse(std::function<shared_ptr<Filesystem> ()> init)
:_init(std::move(init)), _fs(make_shared<InvalidFilesystem>()), _running(false) {
ASSERT(static_cast<bool>(_init), "Invalid init given");
}
@ -198,14 +190,14 @@ int Fuse::readlink(const bf::path &path, char *buf, size_t size) {
int Fuse::mkdir(const bf::path &path, ::mode_t mode) {
ThreadNameForDebugging _threadName("mkdir");
#ifdef FSPP_LOG
LOG(DEBUG, "mkdir({}, {})", path, mode);
LOG(DEBUG, "mkdir({}, {})", path.string(), mode);
#endif
try {
ASSERT(is_valid_fspp_path(path), "has to be an absolute path");
// DokanY seems to call mkdir("/"). Ignore that
if ("/" == path) {
#ifdef FSPP_LOG
LOG(DEBUG, "mkdir({}, {}): ignored", path, mode);
LOG(DEBUG, "mkdir({}, {}): ignored", path.string(), mode);
#endif
return 0;
}
@ -352,7 +344,7 @@ int Fuse::rename(const bf::path &from, const bf::path &to) {
//TODO
int Fuse::link(const bf::path &from, const bf::path &to) {
ThreadNameForDebugging _threadName("link");
LOG(WARN, "NOT IMPLEMENTED: link({}, {})", from, to);
LOG(WARN, "NOT IMPLEMENTED: link({}, {})", from.string(), to.string());
//auto real_from = _impl->RootDir() / from;
//auto real_to = _impl->RootDir() / to;
//int retstat = ::link(real_from.string().c_str(), real_to.string().c_str());

View File

@ -25,8 +25,7 @@ class Filesystem;
class Fuse final {
public:
explicit Fuse(std::function<std::shared_ptr<Filesystem> ()> init, std::string fstype, boost::optional<std::string> fsname);
~Fuse();
explicit Fuse(std::function<std::shared_ptr<Filesystem> ()> init);
bool running() const;
void stop();
@ -71,10 +70,7 @@ private:
std::function<std::shared_ptr<Filesystem> ()> _init;
std::shared_ptr<Filesystem> _fs;
std::vector<char*> _argv;
std::atomic<bool> _running;
std::string _fstype;
boost::optional<std::string> _fsname;
boost::optional<Context> _context;
::uid_t uid;
::gid_t gid;

View File

@ -1,8 +1,5 @@
project (gitversion)
include(gitversion.cmake)
get_git_version(GIT_VERSION)
set(SOURCES
gitversion.cpp
versionstring.cpp
@ -12,6 +9,9 @@ set(SOURCES
add_library(${PROJECT_NAME} STATIC ${SOURCES})
target_link_libraries(${PROJECT_NAME} PUBLIC boost)
if (NOT DEFINED GIT_VERSION)
message(FATAL_ERROR "GIT_VERSION not defined")
endif()
target_compile_definitions(${PROJECT_NAME} PRIVATE GIT_VERSION_STRING="${GIT_VERSION}")
target_add_boost(${PROJECT_NAME})
target_enable_style_warnings(${PROJECT_NAME})

View File

@ -1,3 +0,0 @@
include versioneer.py
include _version_source.py
include _version.py

View File

@ -1,487 +0,0 @@
# This file helps to compute a version number in source trees obtained from
# git-archive tarball (such as those provided by githubs download-from-tag
# feature). Distribution tarballs (built by setup.py sdist) and build
# directories (produced by setup.py build) will contain a much shorter file
# that just contains the computed version number.
# This file is released into the public domain. Generated by
# versioneer-0.15+dev (https://github.com/warner/python-versioneer)
"""Git implementation of _version.py."""
import errno
import os
import re
import subprocess
import sys
def get_keywords():
"""Get the keywords needed to look up the version information."""
# these strings will be replaced by git during git-archive.
# setup.py/versioneer.py will grep for the variable names, so they must
# each be defined on a line of their own. _version.py will just call
# get_keywords().
git_refnames = "$Format:%d$"
git_full = "$Format:%H$"
keywords = {"refnames": git_refnames, "full": git_full}
return keywords
class VersioneerConfig:
"""Container for Versioneer configuration parameters."""
def get_config():
"""Create, populate and return the VersioneerConfig() object."""
# these strings are filled in when 'setup.py versioneer' creates
# _version.py
cfg = VersioneerConfig()
cfg.VCS = "git"
cfg.style = "pep440"
cfg.tag_prefix = ""
cfg.parentdir_prefix = "cryfs-"
cfg.versionfile_source = "_version.py"
cfg.verbose = False
return cfg
class NotThisMethod(Exception):
"""Exception raised if a method is not valid for the current scenario."""
LONG_VERSION_PY = {}
HANDLERS = {}
def register_vcs_handler(vcs, method): # decorator
"""Decorator to mark a method as the handler for a particular VCS."""
def decorate(f):
"""Store f in HANDLERS[vcs][method]."""
if vcs not in HANDLERS:
HANDLERS[vcs] = {}
HANDLERS[vcs][method] = f
return f
return decorate
def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
"""Call the given command(s)."""
assert isinstance(commands, list)
p = None
for c in commands:
try:
dispcmd = str([c] + args)
# remember shell=False, so use git.cmd on windows, not just git
p = subprocess.Popen([c] + args, cwd=cwd, stdout=subprocess.PIPE,
stderr=(subprocess.PIPE if hide_stderr
else None))
break
except EnvironmentError:
e = sys.exc_info()[1]
if e.errno == errno.ENOENT:
continue
if verbose:
print("unable to run %s" % dispcmd)
print(e)
return None
else:
if verbose:
print("unable to find command, tried %s" % (commands,))
return None
stdout = p.communicate()[0].strip()
if sys.version_info[0] >= 3:
stdout = stdout.decode()
if p.returncode != 0:
if verbose:
print("unable to run %s (error)" % dispcmd)
return None
return stdout
def versions_from_parentdir(parentdir_prefix, root, verbose):
"""Try to determine the version from the parent directory name.
Source tarballs conventionally unpack into a directory that includes
both the project name and a version string.
"""
# -- (MESSMER) CHANGED FOLLOWING LINE TO LOOK IN ../.. instead of . --
dirname = os.path.basename(os.path.abspath(os.path.join(os.path.join(root, '..'), '..')))
if not dirname.startswith(parentdir_prefix):
if verbose:
print("guessing rootdir is '%s', but '%s' doesn't start with "
"prefix '%s'" % (root, dirname, parentdir_prefix))
raise NotThisMethod("rootdir doesn't start with parentdir_prefix")
return {"version": dirname[len(parentdir_prefix):],
"full-revisionid": None,
"dirty": False, "error": None}
@register_vcs_handler("git", "get_keywords")
def git_get_keywords(versionfile_abs):
"""Extract version information from the given file."""
# the code embedded in _version.py can just fetch the value of these
# keywords. When used from setup.py, we don't want to import _version.py,
# so we do it with a regexp instead. This function is not used from
# _version.py.
keywords = {}
try:
f = open(versionfile_abs, "r")
for line in f.readlines():
if line.strip().startswith("git_refnames ="):
mo = re.search(r'=\s*"(.*)"', line)
if mo:
keywords["refnames"] = mo.group(1)
if line.strip().startswith("git_full ="):
mo = re.search(r'=\s*"(.*)"', line)
if mo:
keywords["full"] = mo.group(1)
f.close()
except EnvironmentError:
pass
return keywords
@register_vcs_handler("git", "keywords")
def git_versions_from_keywords(keywords, tag_prefix, verbose):
"""Get version information from git keywords."""
if not keywords:
raise NotThisMethod("no keywords at all, weird")
refnames = keywords["refnames"].strip()
if refnames.startswith("$Format"):
if verbose:
print("keywords are unexpanded, not using")
raise NotThisMethod("unexpanded keywords, not a git-archive tarball")
refs = set([r.strip() for r in refnames.strip("()").split(",")])
# starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
# just "foo-1.0". If we see a "tag: " prefix, prefer those.
TAG = "tag: "
tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)])
if not tags:
# Either we're using git < 1.8.3, or there really are no tags. We use
# a heuristic: assume all version tags have a digit. The old git %d
# expansion behaves like git log --decorate=short and strips out the
# refs/heads/ and refs/tags/ prefixes that would let us distinguish
# between branches and tags. By ignoring refnames without digits, we
# filter out many common branch names like "release" and
# "stabilization", as well as "HEAD" and "master".
tags = set([r for r in refs if re.search(r'\d', r)])
if verbose:
print("discarding '%s', no digits" % ",".join(refs-tags))
if verbose:
print("likely tags: %s" % ",".join(sorted(tags)))
for ref in sorted(tags):
# sorting will prefer e.g. "2.0" over "2.0rc1"
if ref.startswith(tag_prefix):
r = ref[len(tag_prefix):]
if verbose:
print("picking %s" % r)
return {"version": r,
"full-revisionid": keywords["full"].strip(),
"dirty": False, "error": None
}
# no suitable tags, so version is "0+unknown", but full hex is still there
if verbose:
print("no suitable tags, using unknown + full revision id")
return {"version": "0+unknown",
"full-revisionid": keywords["full"].strip(),
"dirty": False, "error": "no suitable tags"}
@register_vcs_handler("git", "pieces_from_vcs")
def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
"""Get version from 'git describe' in the root of the source tree.
This only gets called if the git-archive 'subst' keywords were *not*
expanded, and _version.py hasn't already been rewritten with a short
version string, meaning we're inside a checked out source tree.
"""
if not os.path.exists(os.path.join(root, ".git")):
if verbose:
print("no .git in %s" % root)
raise NotThisMethod("no .git directory")
GITS = ["git"]
if sys.platform == "win32":
GITS = ["git.cmd", "git.exe"]
# if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty]
# if there isn't one, this yields HEX[-dirty] (no NUM)
describe_out = run_command(GITS, ["describe", "--tags", "--dirty",
"--always", "--long",
"--match", "%s*" % tag_prefix],
cwd=root)
# --long was added in git-1.5.5
if describe_out is None:
raise NotThisMethod("'git describe' failed")
describe_out = describe_out.strip()
full_out = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
if full_out is None:
raise NotThisMethod("'git rev-parse' failed")
full_out = full_out.strip()
pieces = {}
pieces["long"] = full_out
pieces["short"] = full_out[:7] # maybe improved later
pieces["error"] = None
# parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty]
# TAG might have hyphens.
git_describe = describe_out
# look for -dirty suffix
dirty = git_describe.endswith("-dirty")
pieces["dirty"] = dirty
if dirty:
git_describe = git_describe[:git_describe.rindex("-dirty")]
# now we have TAG-NUM-gHEX or HEX
if "-" in git_describe:
# TAG-NUM-gHEX
mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe)
if not mo:
# unparseable. Maybe git-describe is misbehaving?
pieces["error"] = ("unable to parse git-describe output: '%s'"
% describe_out)
return pieces
# tag
full_tag = mo.group(1)
if not full_tag.startswith(tag_prefix):
if verbose:
fmt = "tag '%s' doesn't start with prefix '%s'"
print(fmt % (full_tag, tag_prefix))
pieces["error"] = ("tag '%s' doesn't start with prefix '%s'"
% (full_tag, tag_prefix))
return pieces
pieces["closest-tag"] = full_tag[len(tag_prefix):]
# distance: number of commits since tag
pieces["distance"] = int(mo.group(2))
# commit: short hex revision ID
pieces["short"] = mo.group(3)
else:
# HEX: no tags
pieces["closest-tag"] = None
count_out = run_command(GITS, ["rev-list", "HEAD", "--count"],
cwd=root)
pieces["distance"] = int(count_out) # total number of commits
return pieces
def plus_or_dot(pieces):
"""Return a + if we don't already have one, else return a ."""
if "+" in pieces.get("closest-tag", ""):
return "."
return "+"
def render_pep440(pieces):
"""Build up version string, with post-release "local version identifier".
Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
Exceptions:
1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
"""
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"] or pieces["dirty"]:
rendered += plus_or_dot(pieces)
rendered += "%d.g%s" % (pieces["distance"], pieces["short"])
if pieces["dirty"]:
rendered += ".dirty"
else:
# exception #1
rendered = "0+untagged.%d.g%s" % (pieces["distance"],
pieces["short"])
if pieces["dirty"]:
rendered += ".dirty"
return rendered
def render_pep440_pre(pieces):
"""TAG[.post.devDISTANCE] -- No -dirty.
Exceptions:
1: no tags. 0.post.devDISTANCE
"""
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"]:
rendered += ".post.dev%d" % pieces["distance"]
else:
# exception #1
rendered = "0.post.dev%d" % pieces["distance"]
return rendered
def render_pep440_post(pieces):
"""TAG[.postDISTANCE[.dev0]+gHEX] .
The ".dev0" means dirty. Note that .dev0 sorts backwards
(a dirty tree will appear "older" than the corresponding clean one),
but you shouldn't be releasing software with -dirty anyways.
Exceptions:
1: no tags. 0.postDISTANCE[.dev0]
"""
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"] or pieces["dirty"]:
rendered += ".post%d" % pieces["distance"]
if pieces["dirty"]:
rendered += ".dev0"
rendered += plus_or_dot(pieces)
rendered += "g%s" % pieces["short"]
else:
# exception #1
rendered = "0.post%d" % pieces["distance"]
if pieces["dirty"]:
rendered += ".dev0"
rendered += "+g%s" % pieces["short"]
return rendered
def render_pep440_old(pieces):
"""TAG[.postDISTANCE[.dev0]] .
The ".dev0" means dirty.
Eexceptions:
1: no tags. 0.postDISTANCE[.dev0]
"""
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"] or pieces["dirty"]:
rendered += ".post%d" % pieces["distance"]
if pieces["dirty"]:
rendered += ".dev0"
else:
# exception #1
rendered = "0.post%d" % pieces["distance"]
if pieces["dirty"]:
rendered += ".dev0"
return rendered
def render_git_describe(pieces):
"""TAG[-DISTANCE-gHEX][-dirty].
Like 'git describe --tags --dirty --always'.
Exceptions:
1: no tags. HEX[-dirty] (note: no 'g' prefix)
"""
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
if pieces["distance"]:
rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
else:
# exception #1
rendered = pieces["short"]
if pieces["dirty"]:
rendered += "-dirty"
return rendered
def render_git_describe_long(pieces):
"""TAG-DISTANCE-gHEX[-dirty].
Like 'git describe --tags --dirty --always -long'.
The distance/hash is unconditional.
Exceptions:
1: no tags. HEX[-dirty] (note: no 'g' prefix)
"""
if pieces["closest-tag"]:
rendered = pieces["closest-tag"]
rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
else:
# exception #1
rendered = pieces["short"]
if pieces["dirty"]:
rendered += "-dirty"
return rendered
def render(pieces, style):
"""Render the given version pieces into the requested style."""
if pieces["error"]:
return {"version": "unknown",
"full-revisionid": pieces.get("long"),
"dirty": None,
"error": pieces["error"]}
if not style or style == "default":
style = "pep440" # the default
if style == "pep440":
rendered = render_pep440(pieces)
elif style == "pep440-pre":
rendered = render_pep440_pre(pieces)
elif style == "pep440-post":
rendered = render_pep440_post(pieces)
elif style == "pep440-old":
rendered = render_pep440_old(pieces)
elif style == "git-describe":
rendered = render_git_describe(pieces)
elif style == "git-describe-long":
rendered = render_git_describe_long(pieces)
else:
raise ValueError("unknown style '%s'" % style)
return {"version": rendered, "full-revisionid": pieces["long"],
"dirty": pieces["dirty"], "error": None}
def get_versions():
"""Get version information or return default if unable to do so."""
# I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
# __file__, we can work backwards from there to the root. Some
# py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
# case we can only use expanded keywords.
cfg = get_config()
verbose = cfg.verbose
try:
return git_versions_from_keywords(get_keywords(), cfg.tag_prefix,
verbose)
except NotThisMethod:
pass
try:
root = os.path.realpath(__file__)
# versionfile_source is the relative path from the top of the source
# tree (where the .git directory might live) to this file. Invert
# this to find the root from __file__.
for i in cfg.versionfile_source.split('/'):
root = os.path.dirname(root)
except NameError:
return {"version": "0+unknown", "full-revisionid": None,
"dirty": None,
"error": "unable to find root of source tree"}
try:
pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose)
return render(pieces, cfg.style)
except NotThisMethod:
pass
try:
if cfg.parentdir_prefix:
return versions_from_parentdir(cfg.parentdir_prefix, root, verbose)
except NotThisMethod:
pass
return {"version": "0+unknown", "full-revisionid": None,
"dirty": None,
"error": "unable to compute version"}

View File

@ -1,5 +0,0 @@
#!/usr/bin/env python
import versioneer
print(versioneer.get_version())

View File

@ -1,18 +0,0 @@
set(DIR_OF_GITVERSION_TOOL "${CMAKE_CURRENT_LIST_DIR}" CACHE INTERNAL "DIR_OF_GITVERSION_TOOL")
function (get_git_version OUTPUT_VARIABLE)
EXECUTE_PROCESS(COMMAND python3 ${DIR_OF_GITVERSION_TOOL}/getversion.py
WORKING_DIRECTORY ${DIR_OF_GITVERSION_TOOL}
OUTPUT_VARIABLE VERSION
ERROR_VARIABLE error
RESULT_VARIABLE result)
STRING(STRIP "${VERSION}" STRIPPED_VERSION)
SET(${OUTPUT_VARIABLE} "${STRIPPED_VERSION}" CACHE INTERNAL "${OUTPUT_VARIABLE}")
MESSAGE(STATUS "Building version ${${OUTPUT_VARIABLE}}")
IF(NOT ${result} EQUAL 0)
MESSAGE(FATAL_ERROR "Error running versioneer. Return code is: ${result}, error message is: ${error}")
ENDIF()
IF("${STRIPPED_VERSION}" STREQUAL "0+unknown")
MESSAGE(FATAL_ERROR "Unable to find git version information. Please build directly from a git repository (i.e. after git clone).")
ENDIF()
endfunction(get_git_version)

View File

@ -1,12 +0,0 @@
# See the docstring in versioneer.py for instructions. Note that you must
# re-run 'versioneer.py setup' after changing this section, and commit the
# resulting files.
[versioneer]
VCS = git
style = pep440
versionfile_source = _version.py
versionfile_build = None
tag_prefix =
parentdir_prefix = cryfs-

View File

@ -1,13 +0,0 @@
#!/usr/bin/env python
from setuptools import setup
import versioneer
setup(name='git-version',
version=versioneer.get_version(),
cmdclass=versioneer.get_cmdclass(),
description='Make git version information (e.g. git tag name, git commit id, ...) available to C++ source files.',
author='Sebastian Messmer',
author_email='messmer@cryfs.org',
license='LGPLv3'
)

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,16 @@
#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, jobject jerrorCode);
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);
jint cryfs_write(JNIEnv* env, jlong fusePtr, jlong fileHandle, jlong offset, jbyteArray jbuffer, jint size);
jint cryfs_read(JNIEnv* env, jlong fusePtr, jlong fileHandle, jlong fileOffset, jbyteArray buffer, jlong dstOffset, jlong length);
jint cryfs_write(JNIEnv* env, jlong fusePtr, jlong fileHandle, jlong fileOffset, jbyteArray buffer, jlong srcOffset, jlong length);
jint cryfs_truncate(JNIEnv* env, jlong fusePtr, jstring jpath, jlong size);
jint cryfs_unlink(JNIEnv* env, jlong fusePtr, jstring jpath);
jint cryfs_release(jlong fusePtr, jlong fileHandle);

View File

@ -1,9 +1,11 @@
#include <jni.h>
#include <cryfs-cli/Cli.h>
#include <fspp/fuse/Fuse.h>
#include <cryfs/impl/CryfsException.h>
#include <cryfs/impl/config/CryKeyProvider.h>
#include <cryfs/impl/config/CryDirectKeyProvider.h>
#include <cryfs/impl/config/CryPresetPasswordBasedKeyProvider.h>
using std::unique_ptr;
using std::make_unique;
using boost::none;
using cpputils::Random;
using cpputils::SCrypt;
@ -13,7 +15,21 @@ 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) {
jfieldID getValueField(JNIEnv* env, jobject object) {
return env->GetFieldID(env->GetObjectClass(object), "value", "Ljava/lang/Object;");
}
void setReturnedPasswordHash(JNIEnv* env, jobject jreturnedHash, const SizedData& returnedHash) {
jbyteArray jpasswordHash = env->NewByteArray(returnedHash.size);
env->SetByteArrayRegion(jpasswordHash, 0, returnedHash.size, reinterpret_cast<const jbyte*>(returnedHash.data));
delete[] returnedHash.data;
env->SetObjectField(jreturnedHash, getValueField(env, jreturnedHash), jpasswordHash);
}
extern "C" jlong
cryfs_init(JNIEnv *env, jstring jbaseDir, jstring jlocalStateDir, jbyteArray jpassword,
jbyteArray jgivenHash, jobject jreturnedHash, jboolean createBaseDir,
jstring jcipher, jobject jerrorCode) {
const char* baseDir = env->GetStringUTFChars(jbaseDir, NULL);
const char* localStateDir = env->GetStringUTFChars(jlocalStateDir, NULL);
boost::optional<string> cipher = none;
@ -22,16 +38,44 @@ extern "C" jlong cryfs_init(JNIEnv* env, jstring jbaseDir, jstring jlocalStateDi
cipher = boost::optional<string>(cipherName);
env->ReleaseStringUTFChars(jcipher, cipherName);
}
auto &keyGenerator = Random::OSRandom();
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->GetArrayLength(jpassword));
env->ReleaseByteArrayElements(jpassword, password, 0);
if (jreturnedHash != NULL) {
credentials.returnedHash = &returnedHash;
}
}
Fuse* fuse = 0;
try {
fuse = Cli(keyGenerator, SCrypt::DefaultSettings).initFilesystem(options, credentials);
} catch (const cryfs::CryfsException &e) {
int errorCode = static_cast<int>(e.errorCode());
if (e.what() != string()) {
LOG(cpputils::logging::ERR, "Error {}: {}", errorCode, e.what());
}
jclass integerClass = env->FindClass("java/lang/Integer");
jobject integer = env->NewObject(integerClass, env->GetMethodID(integerClass, "<init>", "(I)V"), errorCode);
env->SetObjectField(jerrorCode, getValueField(env, jerrorCode), integer);
}
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);
@ -39,6 +83,55 @@ extern "C" jlong cryfs_init(JNIEnv* env, jstring jbaseDir, jstring jlocalStateDi
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>(
string(reinterpret_cast<const char*>(currentPassword), env->GetArrayLength(jcurrentPassword)),
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>(
string(reinterpret_cast<const char*>(newPassword), env->GetArrayLength(jnewPassword)),
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);
@ -69,22 +162,21 @@ extern "C" jlong cryfs_open(JNIEnv* env, jlong fusePtr, jstring jpath, jint flag
}
}
extern "C" jint cryfs_read(JNIEnv* env, jlong fusePtr, jlong fileHandle, jbyteArray jbuffer, jlong offset) {
extern "C" jint cryfs_read(JNIEnv* env, jlong fusePtr, jlong fileHandle, jlong fileOffset, jbyteArray jbuffer, jlong dstOffset, jlong length) {
Fuse* fuse = reinterpret_cast<Fuse*>(fusePtr);
const jsize size = env->GetArrayLength(jbuffer);
char* buff = reinterpret_cast<char*>(env->GetByteArrayElements(jbuffer, NULL));
int result = fuse->read(buff, size, offset, fileHandle);
int result = fuse->read(buff+dstOffset, length, fileOffset, fileHandle);
env->ReleaseByteArrayElements(jbuffer, reinterpret_cast<jbyte*>(buff), 0);
return result;
}
extern "C" jint cryfs_write(JNIEnv* env, jlong fusePtr, jlong fileHandle, jlong offset, jbyteArray jbuffer, jint size) {
extern "C" jint cryfs_write(JNIEnv* env, jlong fusePtr, jlong fileHandle, jlong fileOffset, jbyteArray jbuffer, jlong srcOffset, jlong length) {
Fuse* fuse = reinterpret_cast<Fuse*>(fusePtr);
char* buff = reinterpret_cast<char*>(env->GetByteArrayElements(jbuffer, NULL));
int result = fuse->write(buff, size, offset, fileHandle);
int result = fuse->write(buff+srcOffset, length, fileOffset, fileHandle);
env->ReleaseByteArrayElements(jbuffer, reinterpret_cast<jbyte*>(buff), 0);
return result;

@ -1 +1 @@
Subproject commit 0e12fbd30cb70b668a117c0913a303acfdaae04f
Subproject commit c6012c576e30ff6000ddab0988d59bad849200ce

View File

@ -1146,7 +1146,7 @@ if (${CMAKE_VERSION} VERSION_GREATER "3.1" AND USE_OPENMP)
endif()
endif()
# If OpenMP wasn't found, try if we can find it in the default Homebrew location
# If OpenMP wasn't found, try if we can find it in the default Homebrew location (Intel Macs)
if((NOT OPENMP_FOUND) AND (NOT OPENMP_CXX_FOUND) AND EXISTS "/usr/local/opt/libomp/lib/libomp.dylib")
set(OpenMP_CXX_FLAGS "-Xpreprocessor -fopenmp -I/usr/local/opt/libomp/include")
set(OpenMP_CXX_LIB_NAMES omp)
@ -1154,9 +1154,23 @@ if (${CMAKE_VERSION} VERSION_GREATER "3.1" AND USE_OPENMP)
find_package(OpenMP)
if (OPENMP_FOUND OR OPENMP_CXX_FOUND)
message(STATUS "OpenMP: Found libomp in homebrew default location.")
message(STATUS "OpenMP: Found libomp in homebrew default location for Intel Macs.")
else()
message(FATAL_ERROR "OpenMP: Didn't find libomp. Tried homebrew default location but also didn't find it.")
message(FATAL_ERROR "OpenMP: Didn't find libomp. Tried homebrew default location for Intel Macs but also didn't find it.")
endif()
endif()
# If OpenMP wasn't found, try if we can find it in the default Homebrew location (Apple Silicon Macs)
if((NOT OPENMP_FOUND) AND (NOT OPENMP_CXX_FOUND) AND EXISTS "/opt/homebrew/opt/libomp/lib/libomp.dylib")
set(OpenMP_CXX_FLAGS "-Xpreprocessor -fopenmp -I/opt/homebrew/opt/libomp/include")
set(OpenMP_CXX_LIB_NAMES omp)
set(OpenMP_omp_LIBRARY /opt/homebrew/opt/libomp/lib/libomp.dylib)
find_package(OpenMP)
if (OPENMP_FOUND OR OPENMP_CXX_FOUND)
message(STATUS "OpenMP: Found libomp in homebrew default location for Apple Silicon Macs.")
else()
message(FATAL_ERROR "OpenMP: Didn't find libomp. Tried homebrew default location for Apple Silicon Macs but also didn't find it.")
endif()
endif()

2
vendor/spdlog vendored

@ -1 +1 @@
Subproject commit a26e174b367a60a51f0be83a81d6d066330cdd8f
Subproject commit 7e635fca68d014934b4af8a1cf874f63989352b7