// 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 cc := cryptocore.New(scryptHash, cryptocore.BackendGoGCM, 96) ce := contentenc.New(cc, 4096) cf.EncryptedKey = ce.EncryptBlock(key, 0, nil) }
// NewFS returns a new encrypted FUSE overlay filesystem. func NewFS(args Args) *FS { cryptoCore := cryptocore.New(args.Masterkey, args.CryptoBackend, contentenc.DefaultIVBits) contentEnc := contentenc.New(cryptoCore, contentenc.DefaultBS) nameTransform := nametransform.New(cryptoCore, args.LongNames, args.Raw64) return &FS{ FileSystem: pathfs.NewLoopbackFileSystem(args.Cipherdir), args: args, nameTransform: nameTransform, contentEnc: contentEnc, } }
// NewFS returns an encrypted FUSE overlay filesystem. // In this case (reverse mode) the backing directory is plain-text and // ReverseFS provides an encrypted view. func NewFS(args fusefrontend.Args) *ReverseFS { if args.CryptoBackend != cryptocore.BackendAESSIV { log.Panic("reverse mode must use AES-SIV, everything else is insecure") } initLongnameCache() cryptoCore := cryptocore.New(args.Masterkey, args.CryptoBackend, contentenc.DefaultIVBits) contentEnc := contentenc.New(cryptoCore, contentenc.DefaultBS) nameTransform := nametransform.New(cryptoCore, args.LongNames, args.Raw64) return &ReverseFS{ // pathfs.defaultFileSystem returns ENOSYS for all operations FileSystem: pathfs.NewDefaultFileSystem(), loopbackfs: pathfs.NewLoopbackFileSystem(args.Cipherdir), args: args, nameTransform: nameTransform, contentEnc: contentEnc, inoGen: newInoGen(), inoMap: map[fusefrontend.DevInoStruct]uint64{}, } }
// 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 { tlog.Warn.Printf("Failed to unmarshal config file") return nil, nil, err } if cf.Version != contentenc.CurrentVersion { return nil, 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, 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, "\033[33m"+` 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/wiki/Upgrading for instructions. If you have trouble upgrading, join the discussion at https://github.com/rfjakob/gocryptfs/issues/29 . `+"\033[0m") return nil, nil, fmt.Errorf("Deprecated filesystem") } if password == "" { // We have validated the config file, but without a password we cannot // decrypt the master key. Return only the parsed config. return nil, &cf, nil } // 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 we only use 96-bit IVs, // speed is not important and we get better error messages cc := cryptocore.New(scryptHash, cryptocore.BackendGoGCM, 96) ce := contentenc.New(cc, 4096) tlog.Warn.Enabled = false // Silence DecryptBlock() error messages on incorrect password key, err := ce.DecryptBlock(cf.EncryptedKey, 0, nil) tlog.Warn.Enabled = true if err != nil { tlog.Warn.Printf("failed to unlock master key: %s", err.Error()) return nil, nil, fmt.Errorf("Password incorrect.") } return key, &cf, err }