aboutsummaryrefslogtreecommitdiff
path: root/internal/stupidgcm
diff options
context:
space:
mode:
authorFrank Denis2025-02-25 15:03:50 +0100
committerJakob Unterwurzacher2025-03-12 20:43:23 +0100
commit779a850e0fb967aac79124c7e18b14706d5f2652 (patch)
tree5220a72c4b22a01c74f8d48f4787c4dae9cb1cbe /internal/stupidgcm
parent106470d940f7d9fa584463c92f7b2f4f51bce215 (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/Makefile8
-rw-r--r--internal/stupidgcm/aegis.go57
-rw-r--r--internal/stupidgcm/aegis_test.go16
-rw-r--r--internal/stupidgcm/chacha.go4
-rw-r--r--internal/stupidgcm/chacha_test.go4
-rw-r--r--internal/stupidgcm/common.go4
-rw-r--r--internal/stupidgcm/common_test.go2
-rw-r--r--internal/stupidgcm/doc.go6
-rw-r--r--internal/stupidgcm/gcm.go4
-rw-r--r--internal/stupidgcm/gcm_test.go4
-rw-r--r--internal/stupidgcm/locking.go4
-rw-r--r--internal/stupidgcm/openssl.go4
-rw-r--r--internal/stupidgcm/without_aegis.go28
-rw-r--r--internal/stupidgcm/without_openssl.go4
-rw-r--r--internal/stupidgcm/xchacha.go4
-rw-r--r--internal/stupidgcm/xchacha_test.go4
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