aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2026-09-22 14:15:18 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2026-09-22 23:05:45 +0200
commit6ece77bc487c8aa697e3c092197621c4f3e5ccb8 (patch)
treebe4200ff3977685360c4664593f1bf0aa81eafcb
parentupdater: compare hashes directly with crypto/subtle (diff)
downloadwireguard-windows-master.tar.xz
wireguard-windows-master.zip
overlay: stub out crypto/rand FIPS140 garbageHEADmaster
The Go crypto library used to be simple and nice and an example of how to do things well. Unfortunately, the addition of FIPS140 to it has brought disgusting enterprise patterns and gummed up the code. One place this really comes out is in the insane infrastructure behind the RNG. It really only should be calling the system random functions and nothing more. But in contemporary Go, simply calling into the RNG brings along with it in the binary: - A bizarre voodoo magic userspace entropy collector - A specialized SHA384 implementation for said entropy collector - An AES implementation - An AES-NI accelerated AES implementation - A CTR implementation for AES - A GCM implementation for AES - Some CPU detection code - An implementation of some FIPS-specified DRBG algorithm - An HMAC implementation - A SHA256 implementation - An AVX2-accelerated SHA256 implementation - A SHA3 implementation (including cSHAKE) - An AVX2-accelerated SHA3 implementation - A SHA512 implementation - Some generic XOR-bytes routines - The actual syscall wrappers for getting random numbers Obviously this is completely insane. There's a tangled mess of components including eachother, a disorganized patchwork of FIPS code and BoringCrypto code and enterprisey API hooks and self checks and auto-included initializers. It seems like a mess of a library these days. So, here we beat down this madness by using a Go build overlay to replace various parts of the crypto library with stub functions. This is pretty nasty. But at least it compiles out some of this junk. I'm trying to fix this upstream in the meanwhile [1], and so we'll see what comes of that. Link: https://github.com/golang/go/issues/81639 Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--.overlay/crypto/internal/boring/notboring.go26
-rw-r--r--.overlay/crypto/internal/fips140/check/check.go8
-rw-r--r--.overlay/crypto/internal/fips140/drbg/rand.go33
-rw-r--r--.overlay/crypto/internal/fips140/ecdh/ecdh.go24
-rw-r--r--.overlay/crypto/internal/fips140/ed25519/cast.go9
-rw-r--r--.overlay/crypto/internal/fips140/fips140.go43
-rw-r--r--.overlay/crypto/internal/fips140/sha512/sha512block_amd64.go20
-rw-r--r--.overlay/crypto/internal/fips140/sha512/sha512block_arm64.go20
-rw-r--r--.overlay/crypto/internal/fips140deps/cpu/cpu.go15
-rw-r--r--.overlay/crypto/internal/fips140only/fips140only.go11
-rw-r--r--.overlay/crypto/rand/rand.go24
-rw-r--r--.overlay/overlay.json24
-rw-r--r--Makefile5
-rw-r--r--build.bat2
-rw-r--r--embeddable-dll-service/build.bat2
15 files changed, 262 insertions, 4 deletions
diff --git a/.overlay/crypto/internal/boring/notboring.go b/.overlay/crypto/internal/boring/notboring.go
new file mode 100644
index 00000000..4ea6a530
--- /dev/null
+++ b/.overlay/crypto/internal/boring/notboring.go
@@ -0,0 +1,26 @@
+//go:build !(boringcrypto && linux && (amd64 || arm64) && !android && !msan && cgo)
+
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2026 WireGuard LLC. All Rights Reserved.
+ */
+
+package boring
+
+const available = false
+
+type randReader int
+
+const RandReader = randReader(0)
+
+func (randReader) Read([]byte) (int, error) { panic("") }
+
+type PublicKeyECDH struct{}
+type PrivateKeyECDH struct{}
+
+func ECDH(*PrivateKeyECDH, *PublicKeyECDH) ([]byte, error) { panic("") }
+func GenerateKeyECDH(string) (*PrivateKeyECDH, []byte, error) { panic("") }
+func NewPrivateKeyECDH(string, []byte) (*PrivateKeyECDH, error) { panic("") }
+func NewPublicKeyECDH(string, []byte) (*PublicKeyECDH, error) { panic("") }
+func (*PublicKeyECDH) Bytes() []byte { panic("") }
+func (*PrivateKeyECDH) PublicKey() (*PublicKeyECDH, error) { panic("") }
diff --git a/.overlay/crypto/internal/fips140/check/check.go b/.overlay/crypto/internal/fips140/check/check.go
new file mode 100644
index 00000000..82319e10
--- /dev/null
+++ b/.overlay/crypto/internal/fips140/check/check.go
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2026 WireGuard LLC. All Rights Reserved.
+ */
+
+package check
+
+const Verified = false
diff --git a/.overlay/crypto/internal/fips140/drbg/rand.go b/.overlay/crypto/internal/fips140/drbg/rand.go
new file mode 100644
index 00000000..bd500845
--- /dev/null
+++ b/.overlay/crypto/internal/fips140/drbg/rand.go
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2026 WireGuard LLC. All Rights Reserved.
+ */
+
+package drbg
+
+import (
+ "crypto/internal/sysrand"
+ "io"
+)
+
+func Read(b []byte) {
+ sysrand.Read(b)
+}
+
+func SetTestingReader(io.Reader) {
+ panic("")
+}
+
+type DefaultReader struct{}
+
+func (DefaultReader) defaultReader() {}
+
+func IsDefaultReader(r io.Reader) bool {
+ _, ok := r.(interface{ defaultReader() })
+ return ok
+}
+
+func ReadWithReader(r io.Reader, b []byte) error {
+ Read(b)
+ return nil
+}
diff --git a/.overlay/crypto/internal/fips140/ecdh/ecdh.go b/.overlay/crypto/internal/fips140/ecdh/ecdh.go
new file mode 100644
index 00000000..86406e4a
--- /dev/null
+++ b/.overlay/crypto/internal/fips140/ecdh/ecdh.go
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2026 WireGuard LLC. All Rights Reserved.
+ */
+
+package ecdh
+
+import "io"
+
+type PrivateKey struct{}
+type PublicKey struct{}
+type Curve struct{}
+
+func (*PrivateKey) Bytes() []byte { panic("") }
+func (*PrivateKey) PublicKey() *PublicKey { panic("") }
+func (*PublicKey) Bytes() []byte { panic("") }
+func P224() *Curve { panic("") }
+func P256() *Curve { panic("") }
+func P384() *Curve { panic("") }
+func P521() *Curve { panic("") }
+func GenerateKey(*Curve, io.Reader) (*PrivateKey, error) { panic("") }
+func NewPrivateKey(*Curve, []byte) (*PrivateKey, error) { panic("") }
+func NewPublicKey(*Curve, []byte) (*PublicKey, error) { panic("") }
+func ECDH(*Curve, *PrivateKey, *PublicKey) ([]byte, error) { panic("") }
diff --git a/.overlay/crypto/internal/fips140/ed25519/cast.go b/.overlay/crypto/internal/fips140/ed25519/cast.go
new file mode 100644
index 00000000..8ede70d7
--- /dev/null
+++ b/.overlay/crypto/internal/fips140/ed25519/cast.go
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2026 WireGuard LLC. All Rights Reserved.
+ */
+
+package ed25519
+
+func fipsSelfTest() {}
+func fipsPCT(*PrivateKey) {}
diff --git a/.overlay/crypto/internal/fips140/fips140.go b/.overlay/crypto/internal/fips140/fips140.go
new file mode 100644
index 00000000..0e98ed5d
--- /dev/null
+++ b/.overlay/crypto/internal/fips140/fips140.go
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2026 WireGuard LLC. All Rights Reserved.
+ */
+
+package fips140
+
+const (
+ Enabled = false
+ debug = false
+)
+
+func Supported() error {
+ panic("")
+}
+
+func Name() string {
+ panic("")
+}
+
+func Version() string {
+ panic("")
+}
+
+func CAST(string, func() error) {
+ panic("")
+}
+
+func PCT(string, func() error) {
+ panic("")
+}
+
+func RecordApproved() {}
+
+func RecordNonApproved() {}
+
+func ResetServiceIndicator() {
+ panic("")
+}
+
+func ServiceIndicator() bool {
+ panic("")
+}
diff --git a/.overlay/crypto/internal/fips140/sha512/sha512block_amd64.go b/.overlay/crypto/internal/fips140/sha512/sha512block_amd64.go
new file mode 100644
index 00000000..6760eeb3
--- /dev/null
+++ b/.overlay/crypto/internal/fips140/sha512/sha512block_amd64.go
@@ -0,0 +1,20 @@
+//go:build !purego
+
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2026 WireGuard LLC. All Rights Reserved.
+ */
+
+package sha512
+
+import "crypto/internal/fips140deps/cpu"
+
+//go:noescape
+func blockAVX2(dig *Digest, p []byte)
+func block(dig *Digest, p []byte) {
+ if cpu.HasSHA512AVX2() {
+ blockAVX2(dig, p)
+ } else {
+ blockGeneric(dig, p)
+ }
+}
diff --git a/.overlay/crypto/internal/fips140/sha512/sha512block_arm64.go b/.overlay/crypto/internal/fips140/sha512/sha512block_arm64.go
new file mode 100644
index 00000000..c4af4d07
--- /dev/null
+++ b/.overlay/crypto/internal/fips140/sha512/sha512block_arm64.go
@@ -0,0 +1,20 @@
+//go:build !purego
+
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2026 WireGuard LLC. All Rights Reserved.
+ */
+
+package sha512
+
+import "crypto/internal/fips140deps/cpu"
+
+//go:noescape
+func blockSHA512(dig *Digest, p []byte)
+func block(dig *Digest, p []byte) {
+ if cpu.HasSHA512ARM64() {
+ blockSHA512(dig, p)
+ } else {
+ blockGeneric(dig, p)
+ }
+}
diff --git a/.overlay/crypto/internal/fips140deps/cpu/cpu.go b/.overlay/crypto/internal/fips140deps/cpu/cpu.go
new file mode 100644
index 00000000..8616d0b7
--- /dev/null
+++ b/.overlay/crypto/internal/fips140deps/cpu/cpu.go
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2026 WireGuard LLC. All Rights Reserved.
+ */
+
+package cpu
+
+import "internal/cpu"
+
+func HasSHA512AVX2() bool {
+ return cpu.X86.HasAVX && cpu.X86.HasAVX2 && cpu.X86.HasBMI2
+}
+func HasSHA512ARM64() bool {
+ return cpu.ARM64.HasSHA512
+}
diff --git a/.overlay/crypto/internal/fips140only/fips140only.go b/.overlay/crypto/internal/fips140only/fips140only.go
new file mode 100644
index 00000000..0027fa1e
--- /dev/null
+++ b/.overlay/crypto/internal/fips140only/fips140only.go
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2026 WireGuard LLC. All Rights Reserved.
+ */
+
+package fips140only
+
+import "hash"
+
+func Enforced() bool { return false }
+func ApprovedHash(hash.Hash) bool { panic("") }
diff --git a/.overlay/crypto/rand/rand.go b/.overlay/crypto/rand/rand.go
new file mode 100644
index 00000000..03d083ad
--- /dev/null
+++ b/.overlay/crypto/rand/rand.go
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2026 WireGuard LLC. All Rights Reserved.
+ */
+
+package rand
+
+import (
+ "crypto/internal/sysrand"
+ "io"
+)
+
+func Read(b []byte) (n int, err error) {
+ sysrand.Read(b) // Should panic on failure or short read
+ return len(b), nil
+}
+
+type reader struct{}
+
+func (r reader) Read(b []byte) (n int, err error) {
+ return Read(b)
+}
+
+var Reader io.Reader = reader{}
diff --git a/.overlay/overlay.json b/.overlay/overlay.json
new file mode 100644
index 00000000..bf24ad63
--- /dev/null
+++ b/.overlay/overlay.json
@@ -0,0 +1,24 @@
+{
+ "Replace": {
+ ".deps/go/src/crypto/internal/boring/notboring.go": ".overlay/crypto/internal/boring/notboring.go",
+ ".deps/go/src/crypto/internal/fips140/cast.go": "",
+ ".deps/go/src/crypto/internal/fips140/check/check.go": ".overlay/crypto/internal/fips140/check/check.go",
+ ".deps/go/src/crypto/internal/fips140/drbg/cast.go": "",
+ ".deps/go/src/crypto/internal/fips140/drbg/ctrdrbg.go": "",
+ ".deps/go/src/crypto/internal/fips140/drbg/entropy_fips140.go": "",
+ ".deps/go/src/crypto/internal/fips140/drbg/entropy_wasm.go": "",
+ ".deps/go/src/crypto/internal/fips140/drbg/rand.go": ".overlay/crypto/internal/fips140/drbg/rand.go",
+ ".deps/go/src/crypto/internal/fips140/ecdh/cast.go": "",
+ ".deps/go/src/crypto/internal/fips140/ecdh/ecdh.go": ".overlay/crypto/internal/fips140/ecdh/ecdh.go",
+ ".deps/go/src/crypto/internal/fips140/ed25519/cast.go": ".overlay/crypto/internal/fips140/ed25519/cast.go",
+ ".deps/go/src/crypto/internal/fips140/fips140.go": ".overlay/crypto/internal/fips140/fips140.go",
+ ".deps/go/src/crypto/internal/fips140/indicator.go": "",
+ ".deps/go/src/crypto/internal/fips140/sha512/cast.go": "",
+ ".deps/go/src/crypto/internal/fips140/sha512/sha512block_amd64.go": ".overlay/crypto/internal/fips140/sha512/sha512block_amd64.go",
+ ".deps/go/src/crypto/internal/fips140/sha512/sha512block_arm64.go": ".overlay/crypto/internal/fips140/sha512/sha512block_arm64.go",
+ ".deps/go/src/crypto/internal/fips140deps/cpu/cpu.go": ".overlay/crypto/internal/fips140deps/cpu/cpu.go",
+ ".deps/go/src/crypto/internal/fips140only/fips140only.go": ".overlay/crypto/internal/fips140only/fips140only.go",
+ ".deps/go/src/crypto/rand/rand.go": ".overlay/crypto/rand/rand.go",
+ ".deps/go/src/crypto/rand/util.go": ""
+ }
+}
diff --git a/Makefile b/Makefile
index c7f52213..5ba601ba 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,6 @@
-GOFLAGS := -tags load_wgnt_from_rsrc -ldflags="-H windowsgui -s -w" -trimpath -buildvcs=false -v
+GOFLAGS := -overlay .overlay/overlay.json -tags load_wgnt_from_rsrc -ldflags="-H windowsgui -s -w" -trimpath -buildvcs=false -v
export GOOS := windows
+export PWD := $(CURDIR)
export PATH := $(CURDIR)/.deps/go/bin:$(PATH)
VERSION := $(shell sed -n 's/^\s*Number\s*=\s*"\([0-9.]\+\)"$$/\1/p' version/version.go)
@@ -9,7 +10,7 @@ comma := ,
RCFLAGS := -DWIREGUARD_VERSION_ARRAY=$(subst $(space),$(comma),$(wordlist 1,4,$(subst .,$(space),$(VERSION)) 0 0 0 0)) -DWIREGUARD_VERSION_STR=$(VERSION) -O coff -c 65001
rwildcard=$(foreach d,$(filter-out .deps,$(wildcard $1*)),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
-SOURCE_FILES := $(call rwildcard,,*.go) .deps/go/prepared go.mod go.sum
+SOURCE_FILES := $(call rwildcard,,*.go) $(call rwildcard,.overlay/,*) .deps/go/prepared go.mod go.sum
RESOURCE_FILES := resources.rc version/version.go manifest.xml $(patsubst %.svg,%.ico,$(wildcard ui/icon/*.svg)) .deps/wireguard-nt/prepared
DEPLOYMENT_HOST ?= winvm
diff --git a/build.bat b/build.bat
index cf826fe6..d8339a67 100644
--- a/build.bat
+++ b/build.bat
@@ -73,7 +73,7 @@ if exist .deps\prepared goto :render
echo [+] Assembling resources %1
%~2-w64-mingw32-windres -I ".deps\wireguard-nt\bin\%~1" -DWIREGUARD_VERSION_ARRAY=%WIREGUARD_VERSION_ARRAY% -DWIREGUARD_VERSION_STR=%WIREGUARD_VERSION% -i resources.rc -o "resources_%~3.syso" -O coff -c 65001 || exit /b %errorlevel%
echo [+] Building program %1
- go build -tags load_wgnt_from_rsrc -ldflags="-H windowsgui -s -w" -trimpath -buildvcs=false -v -o "%~1\wireguard.exe" || exit /b 1
+ go build -overlay .overlay/overlay.json -tags load_wgnt_from_rsrc -ldflags="-H windowsgui -s -w" -trimpath -buildvcs=false -v -o "%~1\wireguard.exe" || exit /b 1
if not exist "%~1\wg.exe" (
echo [+] Building command line tools %1
del .deps\src\*.exe .deps\src\*.o .deps\src\wincompat\*.o .deps\src\wincompat\*.lib 2> NUL
diff --git a/embeddable-dll-service/build.bat b/embeddable-dll-service/build.bat
index aa3cdfea..6f7e339a 100644
--- a/embeddable-dll-service/build.bat
+++ b/embeddable-dll-service/build.bat
@@ -39,7 +39,7 @@ if exist ..\.deps\prepared goto :build
set GOARCH=%~3
mkdir %1 >NUL 2>&1
echo [+] Building library %1
- go build -buildmode c-shared -ldflags="-w -s" -trimpath -v -o "%~1/tunnel.dll" || exit /b 1
+ go -C .. build -overlay .overlay/overlay.json -buildmode c-shared -ldflags="-w -s" -trimpath -v -o "%BUILDDIR%%~1/tunnel.dll" ./embeddable-dll-service || exit /b 1
del "%~1\tunnel.h"
goto :eof