diff options
author | Jakob Unterwurzacher | 2021-08-21 12:08:37 +0200 |
---|---|---|
committer | Jakob Unterwurzacher | 2021-08-23 16:00:41 +0200 |
commit | 4764a9bde093f6b61d0370653c6c9d12949ed145 (patch) | |
tree | d71078f71ed3eb0c855e54a13e37b5051ca1bc94 /internal | |
parent | b02812f8b3609403e36c0c182fd2f01537dd6e82 (diff) |
Add partial XChaCha20-Poly1305 support (mount flag only)
Mount flag only at the moment, not saved to gocryptfs.conf.
https://github.com/rfjakob/gocryptfs/issues/452
Diffstat (limited to 'internal')
-rw-r--r-- | internal/configfile/feature_flags.go | 21 | ||||
-rw-r--r-- | internal/cryptocore/cryptocore.go | 30 | ||||
-rw-r--r-- | internal/cryptocore/hkdf.go | 7 |
3 files changed, 44 insertions, 14 deletions
diff --git a/internal/configfile/feature_flags.go b/internal/configfile/feature_flags.go index 45e1853..be5616f 100644 --- a/internal/configfile/feature_flags.go +++ b/internal/configfile/feature_flags.go @@ -28,19 +28,22 @@ const ( // FlagFIDO2 means that "-fido2" was used when creating the filesystem. // The masterkey is protected using a FIDO2 token instead of a password. FlagFIDO2 + // FlagXChaCha20Poly1305 means we use XChaCha20-Poly1305 file content encryption + FlagXChaCha20Poly1305 ) // knownFlags stores the known feature flags and their string representation var knownFlags = map[flagIota]string{ - FlagPlaintextNames: "PlaintextNames", - FlagDirIV: "DirIV", - FlagEMENames: "EMENames", - FlagGCMIV128: "GCMIV128", - FlagLongNames: "LongNames", - FlagAESSIV: "AESSIV", - FlagRaw64: "Raw64", - FlagHKDF: "HKDF", - FlagFIDO2: "FIDO2", + FlagPlaintextNames: "PlaintextNames", + FlagDirIV: "DirIV", + FlagEMENames: "EMENames", + FlagGCMIV128: "GCMIV128", + FlagLongNames: "LongNames", + FlagAESSIV: "AESSIV", + FlagRaw64: "Raw64", + FlagHKDF: "HKDF", + FlagFIDO2: "FIDO2", + FlagXChaCha20Poly1305: "XChaCha20Poly1305", } // Filesystems that do not have these feature flags set are deprecated. diff --git a/internal/cryptocore/cryptocore.go b/internal/cryptocore/cryptocore.go index 5da88db..3e6f5e8 100644 --- a/internal/cryptocore/cryptocore.go +++ b/internal/cryptocore/cryptocore.go @@ -10,6 +10,8 @@ import ( "log" "runtime" + "golang.org/x/crypto/chacha20poly1305" + "github.com/rfjakob/eme" "github.com/rfjakob/gocryptfs/v2/internal/siv_aead" @@ -29,11 +31,17 @@ type AEADTypeEnum int const ( // BackendOpenSSL specifies the OpenSSL backend. + // "AES-GCM-256-OpenSSL" in gocryptfs -speed. BackendOpenSSL AEADTypeEnum = 3 // BackendGoGCM specifies the Go based GCM backend. + // "AES-GCM-256-Go" in gocryptfs -speed. BackendGoGCM AEADTypeEnum = 4 // BackendAESSIV specifies an AESSIV backend. + // "AES-SIV-512-Go" in gocryptfs -speed. BackendAESSIV AEADTypeEnum = 5 + // BackendXChaCha20Poly1305 specifies XChaCha20-Poly1305-Go. + // "XChaCha20-Poly1305-Go" in gocryptfs -speed. + BackendXChaCha20Poly1305 AEADTypeEnum = 6 ) func (a AEADTypeEnum) String() string { @@ -78,7 +86,7 @@ func New(key []byte, aeadType AEADTypeEnum, IVBitLen int, useHKDF bool, forceDec if len(key) != KeyLen { log.Panicf("Unsupported key length of %d bytes", len(key)) } - if IVBitLen != 96 && IVBitLen != 128 { + if IVBitLen != 96 && IVBitLen != 128 && IVBitLen != chacha20poly1305.NonceSizeX*8 { log.Panicf("Unsupported IV length of %d bits", IVBitLen) } @@ -152,8 +160,26 @@ func New(key []byte, aeadType AEADTypeEnum, IVBitLen int, useHKDF bool, forceDec for i := range key64 { key64[i] = 0 } + } else if aeadType == BackendXChaCha20Poly1305 { + // We don't support legacy modes with XChaCha20-Poly1305 + if IVBitLen != chacha20poly1305.NonceSizeX*8 { + log.Panicf("XChaCha20-Poly1305 must use 192-bit IVs, you wanted %d", IVBitLen) + } + if !useHKDF { + log.Panic("XChaCha20-Poly1305 must use HKDF, but it is disabled") + } + derivedKey := hkdfDerive(key, hkdfInfoXChaChaPoly1305Content, chacha20poly1305.KeySize) + aeadCipher, err = chacha20poly1305.NewX(derivedKey) + if err != nil { + log.Panic(err) + } } else { - log.Panic("unknown backend cipher") + log.Panicf("unknown cipher backend %q", aeadType.String()) + } + + if aeadCipher.NonceSize()*8 != IVBitLen { + log.Panicf("Mismatched aeadCipher.NonceSize*8=%d and IVBitLen=%d bits", + aeadCipher.NonceSize()*8, IVBitLen) } return &CryptoCore{ diff --git a/internal/cryptocore/hkdf.go b/internal/cryptocore/hkdf.go index 87ca1b9..b56f507 100644 --- a/internal/cryptocore/hkdf.go +++ b/internal/cryptocore/hkdf.go @@ -10,9 +10,10 @@ import ( const ( // "info" data that HKDF mixes into the generated key to make it unique. // For convenience, we use a readable string. - hkdfInfoEMENames = "EME filename encryption" - hkdfInfoGCMContent = "AES-GCM file content encryption" - hkdfInfoSIVContent = "AES-SIV file content encryption" + hkdfInfoEMENames = "EME filename encryption" + hkdfInfoGCMContent = "AES-GCM file content encryption" + hkdfInfoSIVContent = "AES-SIV file content encryption" + hkdfInfoXChaChaPoly1305Content = "XChaCha20-Poly1305 file content encryption" ) // hkdfDerive derives "outLen" bytes from "masterkey" and "info" using |