diff options
Diffstat (limited to 'internal/cryptocore/cryptocore.go')
-rw-r--r-- | internal/cryptocore/cryptocore.go | 74 |
1 files changed, 50 insertions, 24 deletions
diff --git a/internal/cryptocore/cryptocore.go b/internal/cryptocore/cryptocore.go index 7e1d238..5244104 100644 --- a/internal/cryptocore/cryptocore.go +++ b/internal/cryptocore/cryptocore.go @@ -51,46 +51,72 @@ type CryptoCore struct { // Even though the "GCMIV128" feature flag is now mandatory, we must still // support 96-bit IVs here because they were used for encrypting the master // key in gocryptfs.conf up to gocryptfs v1.2. v1.3 switched to 128 bits. -func New(key []byte, aeadType AEADTypeEnum, IVBitLen int) *CryptoCore { +func New(key []byte, aeadType AEADTypeEnum, IVBitLen int, useHKDF bool) *CryptoCore { if len(key) != KeyLen { log.Panic(fmt.Sprintf("Unsupported key length %d", len(key))) } // We want the IV size in bytes IVLen := IVBitLen / 8 - // Name encryption always uses built-in Go AES through blockCipher. - // Content encryption uses BlockCipher only if useOpenssl=false. - blockCipher, err := aes.NewCipher(key) - if err != nil { - log.Panic(err) + // Initialize EME for filename encryption. + var emeCipher *eme.EMECipher + { + emeKey := key + if useHKDF { + info := "EME filename encryption" + emeKey = hkdfDerive(key, info, KeyLen) + } + emeBlockCipher, err := aes.NewCipher(emeKey) + if err != nil { + log.Panic(err) + } + emeCipher = eme.New(emeBlockCipher) } - emeCipher := eme.New(blockCipher) + // Initilize an AEAD cipher for file content encryption. var aeadCipher cipher.AEAD - switch aeadType { - case BackendOpenSSL: - if IVLen != 16 { - log.Panic("stupidgcm only supports 128-bit IVs") + if aeadType == BackendOpenSSL || aeadType == BackendGoGCM { + gcmKey := key + if useHKDF { + info := "AES-GCM file content encryption" + gcmKey = hkdfDerive(key, info, KeyLen) } - aeadCipher = stupidgcm.New(key) - case BackendGoGCM: - aeadCipher, err = cipher.NewGCMWithNonceSize(blockCipher, IVLen) - case BackendAESSIV: + switch aeadType { + case BackendOpenSSL: + if IVLen != 16 { + log.Panic("stupidgcm only supports 128-bit IVs") + } + aeadCipher = stupidgcm.New(gcmKey) + case BackendGoGCM: + goGcmBlockCipher, err := aes.NewCipher(gcmKey) + if err != nil { + log.Panic(err) + } + aeadCipher, err = cipher.NewGCMWithNonceSize(goGcmBlockCipher, IVLen) + if err != nil { + log.Panic(err) + } + } + } else if aeadType == BackendAESSIV { if IVLen != 16 { // SIV supports any nonce size, but we only use 16. log.Panic("AES-SIV must use 16-byte nonces") } - // AES-SIV uses 1/2 of the key for authentication, 1/2 for - // encryption, so we need a 64-bytes key for AES-256. Derive it from - // the master key by hashing it with SHA-512. - key64 := sha512.Sum512(key) - aeadCipher = siv_aead.New(key64[:]) - default: + var key64 []byte + if useHKDF { + info := "AES-SIV file content encryption" + key64 = hkdfDerive(key, info, siv_aead.KeyLen) + } else { + // AES-SIV uses 1/2 of the key for authentication, 1/2 for + // encryption, so we need a 64-bytes key for AES-256. Derive it from + // the master key by hashing it with SHA-512. + s := sha512.Sum512(key) + key64 = s[:] + } + aeadCipher = siv_aead.New(key64) + } else { log.Panic("unknown backend cipher") } - if err != nil { - log.Panic(err) - } return &CryptoCore{ EMECipher: emeCipher, |