summaryrefslogtreecommitdiff
path: root/internal/configfile/config_file.go
diff options
context:
space:
mode:
authorJakob Unterwurzacher2021-08-21 21:43:26 +0200
committerJakob Unterwurzacher2021-08-23 16:00:41 +0200
commit97d8340bd81ddd60baac598d3e25ebfb4decb50c (patch)
tree2f5444d523ca142e847b0b51422bc51ad8203a75 /internal/configfile/config_file.go
parent4764a9bde093f6b61d0370653c6c9d12949ed145 (diff)
configfile: add Validate() function, support FlagXChaCha20Poly1305
We used to do validation using lists of mandatory feature flags. With the introduction of XChaCha20Poly1305, this became too simplistic, as it uses a different IV length, hence disabling GCMIV128. Add a dedicated function, Validate(), with open-coded validation logic. The validation and creation logic also gets XChaCha20Poly1305 support, and gocryptfs -init -xchacha now writes the flag into gocryptfs.conf.
Diffstat (limited to 'internal/configfile/config_file.go')
-rw-r--r--internal/configfile/config_file.go93
1 files changed, 40 insertions, 53 deletions
diff --git a/internal/configfile/config_file.go b/internal/configfile/config_file.go
index d457db6..dba6c47 100644
--- a/internal/configfile/config_file.go
+++ b/internal/configfile/config_file.go
@@ -88,40 +88,52 @@ type CreateArgs struct {
Fido2CredentialID []byte
Fido2HmacSalt []byte
DeterministicNames bool
+ XChaCha20Poly1305 bool
}
// Create - create a new config with a random key encrypted with
// "Password" and write it to "Filename".
// Uses scrypt with cost parameter "LogN".
func Create(args *CreateArgs) error {
- var cf ConfFile
- cf.filename = args.Filename
- cf.Creator = args.Creator
- cf.Version = contentenc.CurrentVersion
-
- // Set feature flags
- cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagGCMIV128])
- cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagHKDF])
+ cf := ConfFile{
+ filename: args.Filename,
+ Creator: args.Creator,
+ Version: contentenc.CurrentVersion,
+ }
+ // Feature flags
+ cf.setFeatureFlag(FlagHKDF)
+ if args.XChaCha20Poly1305 {
+ cf.setFeatureFlag(FlagXChaCha20Poly1305)
+ } else {
+ // 128-bit IVs are mandatory for AES-GCM (default is 96!) and AES-SIV,
+ // XChaCha20Poly1305 uses even an even longer IV of 192 bits.
+ cf.setFeatureFlag(FlagGCMIV128)
+ }
if args.PlaintextNames {
- cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagPlaintextNames])
+ cf.setFeatureFlag(FlagPlaintextNames)
} else {
if !args.DeterministicNames {
- cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagDirIV])
+ cf.setFeatureFlag(FlagDirIV)
}
- cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagEMENames])
- cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagLongNames])
- cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagRaw64])
+ cf.setFeatureFlag(FlagEMENames)
+ cf.setFeatureFlag(FlagLongNames)
+ cf.setFeatureFlag(FlagRaw64)
}
if args.AESSIV {
- cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagAESSIV])
+ cf.setFeatureFlag(FlagAESSIV)
}
if len(args.Fido2CredentialID) > 0 {
- cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagFIDO2])
+ cf.setFeatureFlag(FlagFIDO2)
cf.FIDO2 = &FIDO2Params{
CredentialID: args.Fido2CredentialID,
HMACSalt: args.Fido2HmacSalt,
}
}
+ // Catch bugs and invalid cli flag combinations early
+ cf.ScryptObject = NewScryptKDF(args.LogN)
+ if err := cf.Validate(); err != nil {
+ return err
+ }
{
// Generate new random master key
var key []byte
@@ -193,50 +205,22 @@ func Load(filename string) (*ConfFile, error) {
return nil, err
}
- if cf.Version != contentenc.CurrentVersion {
- return nil, fmt.Errorf("Unsupported on-disk format %d", cf.Version)
- }
-
- // Check that all set feature flags are known
- for _, flag := range cf.FeatureFlags {
- if !cf.isFeatureFlagKnown(flag) {
- return nil, fmt.Errorf("Unsupported feature flag %q", flag)
- }
- }
-
- // Check that all required feature flags are set
- var requiredFlags []flagIota
- if cf.IsFeatureFlagSet(FlagPlaintextNames) {
- requiredFlags = requiredFlagsPlaintextNames
- } else {
- requiredFlags = requiredFlagsNormal
- }
- deprecatedFs := false
- for _, i := range requiredFlags {
- if !cf.IsFeatureFlagSet(i) {
- fmt.Fprintf(os.Stderr, "Required feature flag %q is missing\n", knownFlags[i])
- deprecatedFs = true
- }
- }
- if deprecatedFs {
- fmt.Fprintf(os.Stderr, tlog.ColorYellow+`
- The filesystem was created by gocryptfs v0.6 or earlier. This version of
- gocryptfs can no longer mount the filesystem.
- Please download gocryptfs v0.11 and upgrade your filesystem,
- see https://github.com/rfjakob/gocryptfs/v2/wiki/Upgrading for instructions.
-
- If you have trouble upgrading, join the discussion at
- https://github.com/rfjakob/gocryptfs/v2/issues/29 .
-
-`+tlog.ColorReset)
-
- return nil, exitcodes.NewErr("Deprecated filesystem", exitcodes.DeprecatedFS)
+ if err := cf.Validate(); err != nil {
+ return nil, exitcodes.NewErr(err.Error(), exitcodes.DeprecatedFS)
}
// All good
return &cf, nil
}
+func (cf *ConfFile) setFeatureFlag(flag flagIota) {
+ if cf.IsFeatureFlagSet(flag) {
+ // Already set, ignore
+ return
+ }
+ cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[flag])
+}
+
// DecryptMasterKey decrypts the masterkey stored in cf.EncryptedKey using
// password.
func (cf *ConfFile) DecryptMasterKey(password []byte) (masterkey []byte, err error) {
@@ -293,6 +277,9 @@ func (cf *ConfFile) EncryptKey(key []byte, password []byte, logN int) {
// then rename over "filename".
// This way a password change atomically replaces the file.
func (cf *ConfFile) WriteFile() error {
+ if err := cf.Validate(); err != nil {
+ return err
+ }
tmp := cf.filename + ".tmp"
// 0400 permissions: gocryptfs.conf should be kept secret and never be written to.
fd, err := os.OpenFile(tmp, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0400)