diff options
author | Frank Denis | 2025-02-25 15:03:50 +0100 |
---|---|---|
committer | Jakob Unterwurzacher | 2025-03-12 20:43:23 +0100 |
commit | 779a850e0fb967aac79124c7e18b14706d5f2652 (patch) | |
tree | 5220a72c4b22a01c74f8d48f4787c4dae9cb1cbe /internal/stupidgcm | |
parent | 106470d940f7d9fa584463c92f7b2f4f51bce215 (diff) |
Add optional support for AEGIS encryption
AEGIS is a new family of authenticated encryption algorithms that offers
stronger security, higher usage limits, and better performance than AES-GCM.
This pull request adds support for a new `-aegis` command-line flag, allowing
AEGIS-128X2 to be used as an alternative to AES-GCM on CPUs with AES acceleration.
It also introduces the ability to use ciphers with different key sizes.
More information on AEGIS is available here:
- https://cfrg.github.io/draft-irtf-cfrg-aegis-aead/draft-irtf-cfrg-aegis-aead.html
- https://github.com/cfrg/draft-irtf-cfrg-aegis-aead
gocryptfs -speed speed on Apple M1:
AES-GCM-256-OpenSSL 3718.79 MB/s
AES-GCM-256-Go 5083.43 MB/s (selected in auto mode)
AES-SIV-512-Go 625.20 MB/s
XChaCha20-Poly1305-OpenSSL 1358.63 MB/s (selected in auto mode)
XChaCha20-Poly1305-Go 832.11 MB/s
Aegis128X2-Go 11818.73 MB/s
gocryptfs -speed speed on AMD Zen 4:
AES-GCM-256-OpenSSL 5215.86 MB/s
AES-GCM-256-Go 6918.01 MB/s (selected in auto mode)
AES-SIV-512-Go 449.61 MB/s
XChaCha20-Poly1305-OpenSSL 2643.48 MB/s
XChaCha20-Poly1305-Go 3727.46 MB/s (selected in auto mode)
Aegis128X2-Go 28109.92 MB/s
Diffstat (limited to 'internal/stupidgcm')
-rw-r--r-- | internal/stupidgcm/Makefile | 8 | ||||
-rw-r--r-- | internal/stupidgcm/aegis.go | 57 | ||||
-rw-r--r-- | internal/stupidgcm/aegis_test.go | 16 | ||||
-rw-r--r-- | internal/stupidgcm/chacha.go | 4 | ||||
-rw-r--r-- | internal/stupidgcm/chacha_test.go | 4 | ||||
-rw-r--r-- | internal/stupidgcm/common.go | 4 | ||||
-rw-r--r-- | internal/stupidgcm/common_test.go | 2 | ||||
-rw-r--r-- | internal/stupidgcm/doc.go | 6 | ||||
-rw-r--r-- | internal/stupidgcm/gcm.go | 4 | ||||
-rw-r--r-- | internal/stupidgcm/gcm_test.go | 4 | ||||
-rw-r--r-- | internal/stupidgcm/locking.go | 4 | ||||
-rw-r--r-- | internal/stupidgcm/openssl.go | 4 | ||||
-rw-r--r-- | internal/stupidgcm/without_aegis.go | 28 | ||||
-rw-r--r-- | internal/stupidgcm/without_openssl.go | 4 | ||||
-rw-r--r-- | internal/stupidgcm/xchacha.go | 4 | ||||
-rw-r--r-- | internal/stupidgcm/xchacha_test.go | 4 |
16 files changed, 133 insertions, 24 deletions
diff --git a/internal/stupidgcm/Makefile b/internal/stupidgcm/Makefile index 143819d..d8f7d2e 100644 --- a/internal/stupidgcm/Makefile +++ b/internal/stupidgcm/Makefile @@ -3,11 +3,15 @@ test: gcc # All three ways of building this must work go build go build -tags without_openssl - CGO_ENABLED=0 go build -tags without_openssl + go build -tags without_aegis + go build -tags without_openssl,without_aegis + CGO_ENABLED=0 go build -tags without_openssl,without_aegis # Likewise, all three ways of testing this must work go test -v go test -v -tags without_openssl - CGO_ENABLED=0 go test -v -tags without_openssl + go test -v -tags without_aegis + go test -v -tags without_openssl,without_aegis + CGO_ENABLED=0 go test -v -tags without_openssl,without_aegis .PHONY: gcc gcc: diff --git a/internal/stupidgcm/aegis.go b/internal/stupidgcm/aegis.go new file mode 100644 index 0000000..8975055 --- /dev/null +++ b/internal/stupidgcm/aegis.go @@ -0,0 +1,57 @@ +//go:build !without_aegis && cgo +// +build !without_aegis,cgo + +package stupidgcm + +import ( + "crypto/cipher" + "log" + + "github.com/aegis-aead/go-libaegis/aegis128x2" + "github.com/aegis-aead/go-libaegis/common" +) + +const ( + // BuiltWithoutAegis indicates if aegis been disabled at compile-time + BuiltWithoutAegis = !common.Available + + // Aegis supports 16 and 32 bit tags + AegisTagLen = 16 +) + +type stupidAegis struct { + aead cipher.AEAD +} + +// Verify that we satisfy the cipher.AEAD interface +var _ cipher.AEAD = &stupidAegis{} + +func (*stupidAegis) NonceSize() int { + return aegis128x2.NonceSize +} + +func (*stupidAegis) Overhead() int { + return AegisTagLen +} + +func NewAegis(key []byte) cipher.AEAD { + aead, err := aegis128x2.New(key, AegisTagLen) + if err != nil { + log.Panic(err) + } + return &stupidAegis{ + aead: aead, + } +} + +func (x *stupidAegis) Seal(dst, nonce, plaintext, additionalData []byte) []byte { + return x.aead.Seal(dst, nonce, plaintext, additionalData) +} + +func (x *stupidAegis) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { + return x.aead.Open(dst, nonce, ciphertext, additionalData) +} + +func (x *stupidAegis) Wipe() { + x.aead.(*aegis128x2.Aegis128X2).Wipe() +} diff --git a/internal/stupidgcm/aegis_test.go b/internal/stupidgcm/aegis_test.go new file mode 100644 index 0000000..36ef763 --- /dev/null +++ b/internal/stupidgcm/aegis_test.go @@ -0,0 +1,16 @@ +//go:build !without_aegis && cgo +// +build !without_aegis,cgo + +package stupidgcm + +import "testing" + +func TestStupidAegis(t *testing.T) { + if BuiltWithoutAegis { + t.Skip("Aegis support has been disabled at compile-time") + } + key := randBytes(16) + c := NewAegis(key) + + testCiphers(t, c, c) +} diff --git a/internal/stupidgcm/chacha.go b/internal/stupidgcm/chacha.go index de0c2e8..dcdcb3a 100644 --- a/internal/stupidgcm/chacha.go +++ b/internal/stupidgcm/chacha.go @@ -1,5 +1,5 @@ -//go:build !without_openssl -// +build !without_openssl +//go:build !without_openssl && cgo +// +build !without_openssl,cgo package stupidgcm diff --git a/internal/stupidgcm/chacha_test.go b/internal/stupidgcm/chacha_test.go index 542ff15..4fa038b 100644 --- a/internal/stupidgcm/chacha_test.go +++ b/internal/stupidgcm/chacha_test.go @@ -1,5 +1,5 @@ -//go:build !without_openssl -// +build !without_openssl +//go:build !without_openssl && cgo +// +build !without_openssl,cgo package stupidgcm diff --git a/internal/stupidgcm/common.go b/internal/stupidgcm/common.go index d88dc62..c5dd338 100644 --- a/internal/stupidgcm/common.go +++ b/internal/stupidgcm/common.go @@ -1,5 +1,5 @@ -//go:build !without_openssl -// +build !without_openssl +//go:build !without_openssl && cgo +// +build !without_openssl,cgo package stupidgcm diff --git a/internal/stupidgcm/common_test.go b/internal/stupidgcm/common_test.go index 7f38e90..47fee7c 100644 --- a/internal/stupidgcm/common_test.go +++ b/internal/stupidgcm/common_test.go @@ -246,6 +246,8 @@ func testWipe(t *testing.T, c cipher.AEAD) { t.Fatal("c2.key is not zeroed") } } + case *stupidAegis: + c2.Wipe() // AEGIS has its own Wipe method default: t.Fatalf("BUG: unhandled type %T", c2) } diff --git a/internal/stupidgcm/doc.go b/internal/stupidgcm/doc.go index dce82ae..f5d4177 100644 --- a/internal/stupidgcm/doc.go +++ b/internal/stupidgcm/doc.go @@ -1,5 +1,5 @@ -// Package stupidgcm wraps OpenSSL to provide a cipher.AEAD interface for -// authenticated encryption algorithms. +// Package stupidgcm wraps OpenSSL and libaegis to provide a cipher.AEAD +// interface for authenticated encryption algorithms. // // The supported algorithms are: // @@ -9,6 +9,8 @@ // // (3) XChaCha20-Poly1305 (OpenSSL EVP_chacha20_poly1305 + Go HChaCha20) // +// (4) AEGIS (go-libaegis) +// // 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. diff --git a/internal/stupidgcm/gcm.go b/internal/stupidgcm/gcm.go index 2e5aac4..738021e 100644 --- a/internal/stupidgcm/gcm.go +++ b/internal/stupidgcm/gcm.go @@ -1,5 +1,5 @@ -//go:build !without_openssl -// +build !without_openssl +//go:build !without_openssl && cgo +// +build !without_openssl,cgo package stupidgcm diff --git a/internal/stupidgcm/gcm_test.go b/internal/stupidgcm/gcm_test.go index c730a87..6c15287 100644 --- a/internal/stupidgcm/gcm_test.go +++ b/internal/stupidgcm/gcm_test.go @@ -1,5 +1,5 @@ -//go:build !without_openssl -// +build !without_openssl +//go:build !without_openssl && cgo +// +build !without_openssl,cgo // We compare against Go's built-in GCM implementation. Since stupidgcm only // supports 128-bit IVs and Go only supports that from 1.5 onward, we cannot diff --git a/internal/stupidgcm/locking.go b/internal/stupidgcm/locking.go index 04cf232..29f8332 100644 --- a/internal/stupidgcm/locking.go +++ b/internal/stupidgcm/locking.go @@ -1,5 +1,5 @@ -//go:build !without_openssl -// +build !without_openssl +//go:build !without_openssl && cgo +// +build !without_openssl,cgo package stupidgcm diff --git a/internal/stupidgcm/openssl.go b/internal/stupidgcm/openssl.go index 8c950f8..0360629 100644 --- a/internal/stupidgcm/openssl.go +++ b/internal/stupidgcm/openssl.go @@ -1,5 +1,5 @@ -//go:build !without_openssl -// +build !without_openssl +//go:build !without_openssl && cgo +// +build !without_openssl,cgo package stupidgcm diff --git a/internal/stupidgcm/without_aegis.go b/internal/stupidgcm/without_aegis.go new file mode 100644 index 0000000..efd665c --- /dev/null +++ b/internal/stupidgcm/without_aegis.go @@ -0,0 +1,28 @@ +//go:build without_aegis || !cgo +// +build without_aegis !cgo + +package stupidgcm + +import ( + "fmt" + "os" + + "crypto/cipher" + + "github.com/rfjakob/gocryptfs/v2/internal/exitcodes" +) + +const ( + // BuiltWithoutAegis indicates if openssl been disabled at compile-time + BuiltWithoutAegis = true +) + +type stupidAegis struct { + aead cipher.AEAD +} + +func NewAegis(_ []byte) cipher.AEAD { + fmt.Fprintln(os.Stderr, "I have been compiled without aegis support but you are still trying to use aegis") + os.Exit(exitcodes.Aegis) + return nil +} diff --git a/internal/stupidgcm/without_openssl.go b/internal/stupidgcm/without_openssl.go index fcef793..1901c78 100644 --- a/internal/stupidgcm/without_openssl.go +++ b/internal/stupidgcm/without_openssl.go @@ -1,5 +1,5 @@ -//go:build without_openssl -// +build without_openssl +//go:build without_openssl || !cgo +// +build without_openssl !cgo package stupidgcm diff --git a/internal/stupidgcm/xchacha.go b/internal/stupidgcm/xchacha.go index 3c121ba..0187da8 100644 --- a/internal/stupidgcm/xchacha.go +++ b/internal/stupidgcm/xchacha.go @@ -1,5 +1,5 @@ -//go:build !without_openssl -// +build !without_openssl +//go:build !without_openssl && cgo +// +build !without_openssl,cgo // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/internal/stupidgcm/xchacha_test.go b/internal/stupidgcm/xchacha_test.go index 676a023..bd62c04 100644 --- a/internal/stupidgcm/xchacha_test.go +++ b/internal/stupidgcm/xchacha_test.go @@ -1,5 +1,5 @@ -//go:build !without_openssl -// +build !without_openssl +//go:build !without_openssl && cgo +// +build !without_openssl,cgo package stupidgcm |