diff --git a/encfs/FSConfig.h b/encfs/FSConfig.h index 26fb0d0..15b67b2 100644 --- a/encfs/FSConfig.h +++ b/encfs/FSConfig.h @@ -67,6 +67,8 @@ struct EncFSConfig { int kdfIterations; long desiredKDFDuration; + bool plainData; // do not encrypt file content + int blockMACBytes; // MAC headers on blocks.. int blockMACRandBytes; // number of random bytes in the block header @@ -79,6 +81,7 @@ struct EncFSConfig { EncFSConfig() : keyData(), salt() { cfgType = Config_None; subVersion = 0; + plainData = false; blockMACBytes = 0; blockMACRandBytes = 0; uniqueIV = false; diff --git a/encfs/FileUtils.cpp b/encfs/FileUtils.cpp index e5490bc..8f067f2 100644 --- a/encfs/FileUtils.cpp +++ b/encfs/FileUtils.cpp @@ -319,6 +319,7 @@ bool readV6Config(const char *configFile, EncFSConfig *cfg, ConfigInfo *info) { config->read("keySize", &cfg->keySize); config->read("blockSize", &cfg->blockSize); + config->read("plainData", &cfg->plainData); config->read("uniqueIV", &cfg->uniqueIV); config->read("chainedNameIV", &cfg->chainedNameIV); config->read("externalIVChaining", &cfg->externalIVChaining); @@ -547,6 +548,7 @@ bool writeV6Config(const char *configFile, const EncFSConfig *cfg) { addEl(doc, config, "nameAlg", cfg->nameIface); addEl(doc, config, "keySize", cfg->keySize); addEl(doc, config, "blockSize", cfg->blockSize); + addEl(doc, config, "plainData", (int)cfg->plainData); addEl(doc, config, "uniqueIV", (int)cfg->uniqueIV); addEl(doc, config, "chainedNameIV", (int)cfg->chainedNameIV); addEl(doc, config, "externalIVChaining", (int)cfg->externalIVChaining); @@ -875,6 +877,20 @@ static bool boolDefaultYes(const char *prompt) { return boolDefault(prompt, true); } +/** + * Ask the user to select plain data + */ +static bool selectPlainData(bool insecure) { + bool plainData = false; + if (insecure) { + plainData = boolDefaultNo( + _("You used --insecure, you can then disable file data encryption\n" + "which is of course abolutely discouraged.\n" + "Disable file data encryption?")); + } + return plainData; +} + /** * Ask the user whether to enable block MAC and random header bytes */ @@ -1020,6 +1036,7 @@ RootPtr createV6Config(EncFS_Context *ctx, Interface nameIOIface; // selectNameCoding() int blockMACBytes = 0; // selectBlockMAC() int blockMACRandBytes = 0; // selectBlockMAC() + bool plainData = false; // selectPlainData() bool uniqueIV = true; // selectUniqueIV() bool chainedIV = true; // selectChainedIV() bool externalIV = false; // selectExternalChainedIV() @@ -1100,30 +1117,42 @@ RootPtr createV6Config(EncFS_Context *ctx, alg = selectCipherAlgorithm(); keySize = selectKeySize(alg); blockSize = selectBlockSize(alg); + plainData = selectPlainData(opts->insecure); nameIOIface = selectNameCoding(); - if (reverseEncryption) { - cout << _("reverse encryption - chained IV and MAC disabled") << "\n"; - uniqueIV = selectUniqueIV(false); - /* If uniqueIV is off, writing can be allowed, because there - * is no header that could be overwritten. - * So if it is on, enforce readOnly. */ - if (uniqueIV) { - opts->readOnly = true; - } - } else { - chainedIV = selectChainedIV(); - uniqueIV = selectUniqueIV(true); - if (chainedIV && uniqueIV) { - externalIV = selectExternalChainedIV(); + if (plainData) { + cout << _("plain data - IV, MAC and file-hole disabled") << "\n"; + allowHoles = false; + chainedIV = false; + externalIV = false; + uniqueIV = false; + blockMACBytes = 0; + blockMACRandBytes = 0; + } + else { + if (reverseEncryption) { + cout << _("reverse encryption - chained IV and MAC disabled") << "\n"; + uniqueIV = selectUniqueIV(false); + /* If uniqueIV is off, writing can be allowed, because there + * is no header that could be overwritten. + * So if it is on, enforce readOnly. */ + if (uniqueIV) { + opts->readOnly = true; + } } else { - // xgroup(setup) - cout << _("External chained IV disabled, as both 'IV chaining'\n" - "and 'unique IV' features are required for this option.") - << "\n"; - externalIV = false; + chainedIV = selectChainedIV(); + uniqueIV = selectUniqueIV(true); + if (chainedIV && uniqueIV) { + externalIV = selectExternalChainedIV(); + } else { + // xgroup(setup) + cout << _("External chained IV disabled, as both 'IV chaining'\n" + "and 'unique IV' features are required for this option.") + << "\n"; + externalIV = false; + } + selectBlockMAC(&blockMACBytes, &blockMACRandBytes, opts->requireMac); + allowHoles = selectZeroBlockPassThrough(); } - selectBlockMAC(&blockMACBytes, &blockMACRandBytes, opts->requireMac); - allowHoles = selectZeroBlockPassThrough(); } } @@ -1143,6 +1172,7 @@ RootPtr createV6Config(EncFS_Context *ctx, config->cipherIface = cipher->interface(); config->keySize = keySize; config->blockSize = blockSize; + config->plainData = plainData; config->nameIface = nameIOIface; config->creator = "EncFS " VERSION; config->subVersion = V6SubVersion; @@ -1234,7 +1264,13 @@ RootPtr createV6Config(EncFS_Context *ctx, nameCoder->setReverseEncryption(reverseEncryption); FSConfigPtr fsConfig(new FSConfig); - fsConfig->cipher = cipher; + if (plainData) { + static Interface NullInterface("nullCipher", 1, 0, 0); + fsConfig->cipher = Cipher::New(NullInterface, 0); + } + else { + fsConfig->cipher = cipher; + } fsConfig->key = volumeKey; fsConfig->nameCoding = nameCoder; fsConfig->config = config; @@ -1664,7 +1700,17 @@ RootPtr initFS(EncFS_Context *ctx, const std::shared_ptr &opts) { nameCoder->setReverseEncryption(opts->reverseEncryption); FSConfigPtr fsConfig(new FSConfig); - fsConfig->cipher = cipher; + if (config->plainData) { + if (! opts->insecure) { + cout << _("Configuration use plainData but you did not use --insecure\n"); + return rootInfo; + } + static Interface NullInterface("nullCipher", 1, 0, 0); + fsConfig->cipher = Cipher::New(NullInterface, 0); + } + else { + fsConfig->cipher = cipher; + } fsConfig->key = volumeKey; fsConfig->nameCoding = nameCoder; fsConfig->config = config; diff --git a/encfs/FileUtils.h b/encfs/FileUtils.h index ea9f50f..1406915 100644 --- a/encfs/FileUtils.h +++ b/encfs/FileUtils.h @@ -96,6 +96,8 @@ struct EncFS_Opts { bool readOnly; // Mount read-only + bool insecure; // Allow to use plain data / to disable data encoding + bool requireMac; // Throw an error if MAC is disabled ConfigMode configMode; @@ -116,6 +118,7 @@ struct EncFS_Opts { configMode = Config_Prompt; noCache = false; readOnly = false; + insecure = false; requireMac = false; } }; diff --git a/encfs/encfs.pod b/encfs/encfs.pod index 5137be6..e5b0817 100644 --- a/encfs/encfs.pod +++ b/encfs/encfs.pod @@ -17,7 +17,7 @@ encfs - mounts or creates an encrypted virtual filesystem =head1 SYNOPSIS B [B<--version>] [B<-v>|B<--verbose>] [B<-c>|B<--config>] [B<-t>|B<--syslogtag>] -[B<-s>] [B<-f>] [B<--annotate>] [B<--standard>] [B<--paranoia>] +[B<-s>] [B<-f>] [B<--annotate>] [B<--standard>] [B<--paranoia>] [B<--insecure>] [B<--reverse>] [B<--reversewrite>] [B<--extpass=program>] [B<-S>|B<--stdinpass>] [B<--anykey>] [B<--forcedecode>] [B<-require-macs>] [B<-i MINUTES>|B<--idle=MINUTES>] [B<-m>|B<--ondemand>] [B<--delaymount>] [B<-u>|B<--unmount>] @@ -97,6 +97,11 @@ When not creating a filesystem, this flag does nothing. Same as B<--standard>, but for B mode. +=item B<--insecure> + +Allows you to disable data encoding, thus to pass plain data as is. Fully +discouraged of course! + =item B<--reverse> Normally B provides a plaintext view of data on demand: it stores diff --git a/encfs/main.cpp b/encfs/main.cpp index 1c61b7c..c79cada 100644 --- a/encfs/main.cpp +++ b/encfs/main.cpp @@ -48,6 +48,7 @@ #define LONG_OPT_ANNOTATE 513 #define LONG_OPT_NOCACHE 514 #define LONG_OPT_REQUIRE_MAC 515 +#define LONG_OPT_INSECURE 516 using namespace std; using namespace encfs; @@ -221,6 +222,7 @@ static bool processArgs(int argc, char *argv[], out->opts->annotate = false; out->opts->reverseEncryption = false; out->opts->requireMac = false; + out->opts->insecure = false; out->opts->unmount = false; bool useDefaultFlags = true; @@ -260,6 +262,7 @@ static bool processArgs(int argc, char *argv[], {"standard", 0, nullptr, '1'}, // standard configuration {"paranoia", 0, nullptr, '2'}, // standard configuration {"require-macs", 0, nullptr, LONG_OPT_REQUIRE_MAC}, // require MACs + {"insecure", 0, nullptr, LONG_OPT_INSECURE},// allows to use null data encryption {"config", 1, nullptr, 'c'}, // command-line-supplied config location {"unmount", 1, nullptr, 'u'}, // unmount {nullptr, 0, nullptr, 0}}; @@ -307,6 +310,9 @@ static bool processArgs(int argc, char *argv[], case LONG_OPT_REQUIRE_MAC: out->opts->requireMac = true; break; + case LONG_OPT_INSECURE: + out->opts->insecure = true; + break; case 'c': /* Take config file path from command * line instead of ENV variable */ diff --git a/integration/normal.t.pl b/integration/normal.t.pl index 7cbe932..6c5fadf 100755 --- a/integration/normal.t.pl +++ b/integration/normal.t.pl @@ -441,7 +441,7 @@ sub create_unmount_remount # Unmount portable_unmount($mnt); - # Mount again, testing -c as the same time + # Mount again, testing -c at the same time rename("$crypt/.encfs6.xml", "$crypt/.encfs6_moved.xml"); system("./build/encfs -c $crypt/.encfs6_moved.xml --extpass=\"echo test\" $crypt $mnt 2>&1"); ok( $? == 0, "encfs command returns 0") || return;