diff --git a/internal/stupidgcm/chacha.go b/internal/stupidgcm/chacha.go index 30d57e3..1117d97 100644 --- a/internal/stupidgcm/chacha.go +++ b/internal/stupidgcm/chacha.go @@ -35,6 +35,8 @@ func init() { // gocryptfs only uses ChaCha20-Poly1305 as a building block for OpenSSL // XChaCha20-Poly1305. This function is hot because it gets called once for each // block by XChaCha20-Poly1305. +// +// Only 32-bytes keys and 12-byte IVs are supported. func NewChacha20poly1305(key []byte) *stupidChacha20poly1305 { if len(key) != chacha20poly1305.KeySize { log.Panicf("Only %d-byte keys are supported, you passed %d bytes", chacha20poly1305.KeySize, len(key)) diff --git a/internal/stupidgcm/doc.go b/internal/stupidgcm/doc.go new file mode 100644 index 0000000..36c189b --- /dev/null +++ b/internal/stupidgcm/doc.go @@ -0,0 +1,59 @@ +// Package stupidgcm wraps OpenSSL to provide a cipher.AEAD interface for +// authenticated encryption algorithms. +// +// The supported algorithms are: +// +// (1) AES-GCM-256 (OpenSSL EVP_aes_256_gcm) +// +// (2) ChaCha20-Poly1305 (OpenSSL EVP_chacha20_poly1305) +// +// (3) XChaCha20-Poly1305 (OpenSSL EVP_chacha20_poly1305 + Go HChaCha20) +// +// The golang.org/x/crypto libraries provides implementations for all algorithms, +// and the test suite verifies that the implementation in this package gives +// the exact same results. +// +// However, OpenSSL has optimized assembly for almost all platforms, which Go +// does not. Example for a 32-bit ARM device (Odroid XU4): +// +// $ gocrypts -speed +// gocryptfs v2.1-68-gedf9d4c.stupidchacha; go-fuse v2.1.1-0.20210825171523-3ab5d95a30ae; 2021-09-04 go1.16.7 linux/arm +// AES-GCM-256-OpenSSL 56.84 MB/s (selected in auto mode) +// AES-GCM-256-Go 16.61 MB/s +// AES-SIV-512-Go 16.49 MB/s +// XChaCha20-Poly1305-Go 39.08 MB/s (use via -xchacha flag) +// XChaCha20-Poly1305-OpenSSL 141.82 MB/s +// +// This package is "stupid" in the sense that it only supports a narrow set of +// key- and iv-lengths, and panics if it does not like what you pass it. +// See the constructor functions for which restrictions apply for each algorithm. +// Also, it is only tested for block lengths up to 5000 bytes, because this is +// what gocryptfs uses. +// +// Corrupt ciphertexts never cause a panic. Instead, ErrAuth is returned on +// decryption. +// +// XChaCha20-Poly1305 +// +// The XChaCha20-Poly1305 implementation is more complicated than the others, +// because OpenSSL does not support XChaCha20-Poly1305 directly. Follow +// https://github.com/openssl/openssl/issues/5523 to get notified when it is +// accepted into OpenSSL. +// +// Fortunately, XChaCha20-Poly1305 is just ChaCha20-Poly1305 with some key+iv +// mixing using HChaCha20 in front: +// +// key (32 bytes), iv (24 bytes) +// | +// v +// HChaCha20 (provided by golang.org/x/crypto/chacha20) +// | +// v +// key2 (32 bytes), iv2 (16 bytes) +// | +// v +// ChaCha20-Poly1305 (OpenSSL EVP_chacha20_poly1305) +// +// As HChaCha20 is very fast, XChaCha20-Poly1305 gets almost the same throughput +// as ChaCha20-Poly1305 (for 4kiB blocks). +package stupidgcm diff --git a/internal/stupidgcm/gcm.go b/internal/stupidgcm/gcm.go index 0cadd3c..a9377b1 100644 --- a/internal/stupidgcm/gcm.go +++ b/internal/stupidgcm/gcm.go @@ -1,7 +1,5 @@ // +build !without_openssl -// Package stupidgcm is a thin wrapper for OpenSSL's GCM encryption and -// decryption functions. It only support 32-byte keys and 16-bit IVs. package stupidgcm // #include @@ -25,10 +23,9 @@ type stupidGCM struct { stupidAEADCommon } -// Verify that we satisfy the interface -var _ cipher.AEAD = &stupidGCM{} - -// New returns a new cipher.AEAD implementation.. +// New returns a new AES-GCM-256 cipher that satisfies the cipher.AEAD interface. +// +// Only 32-bytes keys and 16-byte IVs are supported. func New(keyIn []byte, forceDecode bool) cipher.AEAD { if len(keyIn) != keyLen { log.Panicf("Only %d-byte keys are supported", keyLen) diff --git a/internal/stupidgcm/xchacha.go b/internal/stupidgcm/xchacha.go index 055b7f7..deb6e2f 100644 --- a/internal/stupidgcm/xchacha.go +++ b/internal/stupidgcm/xchacha.go @@ -26,12 +26,15 @@ type stupidXchacha20poly1305 struct { wiped bool } -// NewXchacha20poly1305 returns a XChaCha20-Poly1305 AEAD that uses the given 256-bit key. +// NewXchacha20poly1305 returns a XChaCha20-Poly1305 cipher that satisfied the +// cipher.AEAD interface. // // XChaCha20-Poly1305 is a ChaCha20-Poly1305 variant that takes a longer nonce, // suitable to be generated randomly without risk of collisions. It should be // preferred when nonce uniqueness cannot be trivially ensured, or whenever // nonces are randomly generated. +// +// Only 32-bytes keys and 24-byte IVs are supported. func NewXchacha20poly1305(key []byte) cipher.AEAD { if len(key) != chacha20poly1305.KeySize { log.Panic("bad key length")