diff options
Diffstat (limited to 'cryptfs/config_file.go')
-rw-r--r-- | cryptfs/config_file.go | 188 |
1 files changed, 0 insertions, 188 deletions
diff --git a/cryptfs/config_file.go b/cryptfs/config_file.go deleted file mode 100644 index 013b82d..0000000 --- a/cryptfs/config_file.go +++ /dev/null @@ -1,188 +0,0 @@ -package cryptfs - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "log" -) -import "os" - -const ( - // The dot "." is not used in base64url (RFC4648), hence - // we can never clash with an encrypted file. - ConfDefaultName = "gocryptfs.conf" -) - -type ConfFile struct { - // File the config is saved to. Not exported to JSON. - filename string - // Encrypted AES key, unlocked using a password hashed with scrypt - EncryptedKey []byte - // Stores parameters for scrypt hashing (key derivation) - ScryptObject scryptKdf - // The On-Disk-Format version this filesystem uses - Version uint16 - // List of feature flags this filesystem has enabled. - // If gocryptfs encounters a feature flag it does not support, it will refuse - // mounting. This mechanism is analogous to the ext4 feature flags that are - // stored in the superblock. - FeatureFlags []string -} - -// CreateConfFile - create a new config with a random key encrypted with -// "password" and write it to "filename". -// Uses scrypt with cost parameter logN. -func CreateConfFile(filename string, password string, plaintextNames bool, logN int) error { - var cf ConfFile - cf.filename = filename - cf.Version = HEADER_CURRENT_VERSION - - // Generate new random master key - key := RandBytes(KEY_LEN) - - // Encrypt it using the password - // This sets ScryptObject and EncryptedKey - cf.EncryptKey(key, password, logN) - - // Set feature flags - cf.FeatureFlags = append(cf.FeatureFlags, FlagGCMIV128) - if plaintextNames { - cf.FeatureFlags = append(cf.FeatureFlags, FlagPlaintextNames) - } else { - cf.FeatureFlags = append(cf.FeatureFlags, FlagDirIV) - cf.FeatureFlags = append(cf.FeatureFlags, FlagEMENames) - } - - // Write file to disk - return cf.WriteFile() -} - -// LoadConfFile - read config file from disk and decrypt the -// contained key using password. -// -// Returns the decrypted key and the ConfFile object -func LoadConfFile(filename string, password string) ([]byte, *ConfFile, error) { - var cf ConfFile - cf.filename = filename - - // Read from disk - js, err := ioutil.ReadFile(filename) - if err != nil { - return nil, nil, err - } - - // Unmarshal - err = json.Unmarshal(js, &cf) - if err != nil { - Warn.Printf("Failed to unmarshal config file") - return nil, nil, err - } - - if cf.Version != HEADER_CURRENT_VERSION { - return nil, nil, fmt.Errorf("Unsupported on-disk format %d", cf.Version) - } - - for _, flag := range cf.FeatureFlags { - if cf.isFeatureFlagKnown(flag) == false { - return nil, nil, fmt.Errorf("Unsupported feature flag %s", flag) - } - } - - // Generate derived key from password - scryptHash := cf.ScryptObject.DeriveKey(password) - - // Unlock master key using password-based key - // We use stock go GCM instead of OpenSSL here as speed is not important - // and we get better error messages - cfs := NewCryptFS(scryptHash, false, false, false) - key, err := cfs.DecryptBlock(cf.EncryptedKey, 0, nil) - if err != nil { - Warn.Printf("failed to unlock master key: %s", err.Error()) - Warn.Printf("Password incorrect.") - return nil, nil, err - } - - return key, &cf, nil -} - -// EncryptKey - encrypt "key" using an scrypt hash generated from "password" -// and store it in cf.EncryptedKey. -// Uses scrypt with cost parameter logN and stores the scrypt parameters in -// cf.ScryptObject. -func (cf *ConfFile) EncryptKey(key []byte, password string, logN int) { - // Generate derived key from password - cf.ScryptObject = NewScryptKdf(logN) - scryptHash := cf.ScryptObject.DeriveKey(password) - - // Lock master key using password-based key - cfs := NewCryptFS(scryptHash, false, false, false) - cf.EncryptedKey = cfs.EncryptBlock(key, 0, nil) -} - -// WriteFile - write out config in JSON format to file "filename.tmp" -// then rename over "filename". -// This way a password change atomically replaces the file. -func (cf *ConfFile) WriteFile() error { - 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) - if err != nil { - return err - } - js, err := json.MarshalIndent(cf, "", "\t") - if err != nil { - return err - } - _, err = fd.Write(js) - if err != nil { - return err - } - err = fd.Sync() - if err != nil { - return err - } - err = fd.Close() - if err != nil { - return err - } - err = os.Rename(tmp, cf.filename) - if err != nil { - return err - } - - return nil -} - -const ( - // Understood Feature Flags. - // Also teach isFeatureFlagKnown() about any additions and - // add it to CreateConfFile() if you want to have it enabled by default. - FlagPlaintextNames = "PlaintextNames" - FlagDirIV = "DirIV" - FlagEMENames = "EMENames" - FlagGCMIV128 = "GCMIV128" -) - -// Verify that we understand a feature flag -func (cf *ConfFile) isFeatureFlagKnown(flag string) bool { - switch flag { - case FlagPlaintextNames, FlagDirIV, FlagEMENames, FlagGCMIV128: - return true - default: - return false - } -} - -// isFeatureFlagSet - is the feature flag "flagWant" enabled? -func (cf *ConfFile) IsFeatureFlagSet(flagWant string) bool { - if !cf.isFeatureFlagKnown(flagWant) { - log.Panicf("BUG: Tried to use unsupported feature flag %s", flagWant) - } - for _, flag := range cf.FeatureFlags { - if flag == flagWant { - return true - } - } - return false -} |