func TestCiphertextRange(t *testing.T) { var ranges []testRange ranges = append(ranges, testRange{0, 70000}, testRange{0, 10}, testRange{234, 6511}, testRange{65444, 54}, testRange{6654, 8945}) key := make([]byte, cryptocore.KeyLen) cc := cryptocore.New(key, cryptocore.BackendOpenSSL, DefaultIVBits) f := New(cc, DefaultBS) for _, r := range ranges { blocks := f.ExplodePlainRange(r.offset, r.length) alignedOffset, alignedLength := blocks[0].JointCiphertextRange(blocks) skipBytes := blocks[0].Skip if alignedLength < r.length { t.Errorf("alignedLength=%d is smaller than length=%d", alignedLength, r.length) } if (alignedOffset-HeaderLen)%f.cipherBS != 0 { t.Errorf("alignedOffset=%d is not aligned", alignedOffset) } if r.offset%f.plainBS != 0 && skipBytes == 0 { t.Errorf("skipBytes=0") } } }
func TestSplitRange(t *testing.T) { var ranges []testRange ranges = append(ranges, testRange{0, 70000}, testRange{0, 10}, testRange{234, 6511}, testRange{65444, 54}, testRange{0, 1024 * 1024}, testRange{0, 65536}, testRange{6654, 8945}) key := make([]byte, cryptocore.KeyLen) cc := cryptocore.New(key, cryptocore.BackendOpenSSL, DefaultIVBits) f := New(cc, DefaultBS) for _, r := range ranges { parts := f.ExplodePlainRange(r.offset, r.length) var lastBlockNo uint64 = 1 << 63 for _, p := range parts { if p.BlockNo == lastBlockNo { t.Errorf("Duplicate block number %d", p.BlockNo) } lastBlockNo = p.BlockNo if p.Length > DefaultBS || p.Skip >= DefaultBS { t.Errorf("Test fail: n=%d, length=%d, offset=%d\n", p.BlockNo, p.Length, p.Skip) } } } }
// 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{}, } }
func TestBlockNo(t *testing.T) { key := make([]byte, cryptocore.KeyLen) cc := cryptocore.New(key, cryptocore.BackendOpenSSL, DefaultIVBits) f := New(cc, DefaultBS) b := f.CipherOffToBlockNo(788) if b != 0 { t.Errorf("actual: %d", b) } b = f.CipherOffToBlockNo(HeaderLen + f.cipherBS) if b != 1 { t.Errorf("actual: %d", b) } b = f.PlainOffToBlockNo(788) if b != 0 { t.Errorf("actual: %d", b) } b = f.PlainOffToBlockNo(f.plainBS) if b != 1 { t.Errorf("actual: %d", b) } }
// 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 }