2024-11-05 13:52:13 -05:00
|
|
|
// Copyright 2024 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
2024-11-14 12:41:47 +01:00
|
|
|
package fipstest
|
2024-11-05 13:52:13 -05:00
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
. "crypto/internal/fips/check"
|
|
|
|
|
"crypto/internal/fips/check/checktest"
|
|
|
|
|
"fmt"
|
|
|
|
|
"internal/abi"
|
2024-11-14 12:56:46 +01:00
|
|
|
"internal/asan"
|
2024-11-05 13:52:13 -05:00
|
|
|
"internal/godebug"
|
2024-11-14 12:41:47 +01:00
|
|
|
"internal/testenv"
|
2024-11-05 13:52:13 -05:00
|
|
|
"os"
|
|
|
|
|
"runtime"
|
|
|
|
|
"testing"
|
|
|
|
|
"unicode"
|
|
|
|
|
"unsafe"
|
|
|
|
|
)
|
|
|
|
|
|
2024-11-06 11:30:25 -05:00
|
|
|
const enableFIPSTest = true
|
2024-11-05 13:52:13 -05:00
|
|
|
|
2024-11-14 12:41:47 +01:00
|
|
|
func TestFIPSCheckVerify(t *testing.T) {
|
|
|
|
|
if Verified {
|
2024-11-05 13:52:13 -05:00
|
|
|
t.Logf("verified")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if godebug.New("#fips140").Value() == "on" {
|
|
|
|
|
t.Fatalf("GODEBUG=fips140=on but verification did not run")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !enableFIPSTest {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !Supported() {
|
|
|
|
|
t.Skipf("skipping on %s-%s", runtime.GOOS, runtime.GOARCH)
|
|
|
|
|
}
|
2024-11-14 12:56:46 +01:00
|
|
|
if asan.Enabled {
|
|
|
|
|
// Verification panics with asan; don't bother.
|
|
|
|
|
t.Skipf("skipping with -asan")
|
|
|
|
|
return
|
|
|
|
|
}
|
2024-11-05 13:52:13 -05:00
|
|
|
|
2024-11-14 12:41:47 +01:00
|
|
|
cmd := testenv.Command(t, os.Args[0], "-test.v", "-test.run=TestFIPSCheck")
|
2024-11-05 13:52:13 -05:00
|
|
|
cmd.Env = append(cmd.Environ(), "GODEBUG=fips140=on")
|
|
|
|
|
out, err := cmd.CombinedOutput()
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("GODEBUG=fips140=on %v failed: %v\n%s", cmd.Args, err, out)
|
|
|
|
|
}
|
|
|
|
|
t.Logf("exec'ed GODEBUG=fips140=on and succeeded:\n%s", out)
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-14 12:41:47 +01:00
|
|
|
func TestFIPSCheckInfo(t *testing.T) {
|
2024-11-05 13:52:13 -05:00
|
|
|
if !enableFIPSTest {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !Supported() {
|
|
|
|
|
t.Skipf("skipping on %s-%s", runtime.GOOS, runtime.GOARCH)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check that the checktest symbols are initialized properly.
|
|
|
|
|
if checktest.NOPTRDATA != 1 {
|
|
|
|
|
t.Errorf("checktest.NOPTRDATA = %d, want 1", checktest.NOPTRDATA)
|
|
|
|
|
}
|
|
|
|
|
if checktest.RODATA != 2 {
|
|
|
|
|
t.Errorf("checktest.RODATA = %d, want 2", checktest.RODATA)
|
|
|
|
|
}
|
|
|
|
|
if checktest.DATA.P != &checktest.NOPTRDATA {
|
|
|
|
|
t.Errorf("checktest.DATA.P = %p, want &checktest.NOPTRDATA (%p)", checktest.DATA.P, &checktest.NOPTRDATA)
|
|
|
|
|
}
|
|
|
|
|
if checktest.DATA.X != 3 {
|
|
|
|
|
t.Errorf("checktest.DATA.X = %d, want 3", checktest.DATA.X)
|
|
|
|
|
}
|
|
|
|
|
if checktest.NOPTRBSS != 0 {
|
|
|
|
|
t.Errorf("checktest.NOPTRBSS = %d, want 0", checktest.NOPTRBSS)
|
|
|
|
|
}
|
|
|
|
|
if checktest.BSS != nil {
|
|
|
|
|
t.Errorf("checktest.BSS = %p, want nil", checktest.BSS)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check that the checktest symbols are in the right go:fipsinfo sections.
|
|
|
|
|
sect := func(i int, name string, p unsafe.Pointer) {
|
|
|
|
|
s := Linkinfo.Sects[i]
|
|
|
|
|
if !(uintptr(s.Start) <= uintptr(p) && uintptr(p) < uintptr(s.End)) {
|
|
|
|
|
t.Errorf("checktest.%s (%#x) not in section #%d (%#x..%#x)", name, p, i, s.Start, s.End)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sect(0, "TEXT", unsafe.Pointer(abi.FuncPCABIInternal(checktest.TEXT)))
|
|
|
|
|
sect(1, "RODATA", unsafe.Pointer(&checktest.RODATA))
|
|
|
|
|
sect(2, "NOPTRDATA", unsafe.Pointer(&checktest.NOPTRDATA))
|
|
|
|
|
sect(3, "DATA", unsafe.Pointer(&checktest.DATA))
|
|
|
|
|
|
|
|
|
|
// Check that some symbols are not in FIPS sections.
|
|
|
|
|
no := func(name string, p unsafe.Pointer, ix ...int) {
|
|
|
|
|
for _, i := range ix {
|
|
|
|
|
s := Linkinfo.Sects[i]
|
|
|
|
|
if uintptr(s.Start) <= uintptr(p) && uintptr(p) < uintptr(s.End) {
|
|
|
|
|
t.Errorf("%s (%#x) unexpectedly in section #%d (%#x..%#x)", name, p, i, s.Start, s.End)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check that the symbols are not in unexpected sections (that is, no overlaps).
|
|
|
|
|
no("checktest.TEXT", unsafe.Pointer(abi.FuncPCABIInternal(checktest.TEXT)), 1, 2, 3)
|
|
|
|
|
no("checktest.RODATA", unsafe.Pointer(&checktest.RODATA), 0, 2, 3)
|
|
|
|
|
no("checktest.NOPTRDATA", unsafe.Pointer(&checktest.NOPTRDATA), 0, 1, 3)
|
|
|
|
|
no("checktest.DATA", unsafe.Pointer(&checktest.DATA), 0, 1, 2)
|
|
|
|
|
|
|
|
|
|
// Check that non-FIPS symbols are not in any of the sections.
|
|
|
|
|
no("fmt.Printf", unsafe.Pointer(abi.FuncPCABIInternal(fmt.Printf)), 0, 1, 2, 3) // TEXT
|
|
|
|
|
no("unicode.Categories", unsafe.Pointer(&unicode.Categories), 0, 1, 2, 3) // BSS
|
|
|
|
|
no("unicode.ASCII_Hex_Digit", unsafe.Pointer(&unicode.ASCII_Hex_Digit), 0, 1, 2, 3) // DATA
|
|
|
|
|
|
|
|
|
|
// Check that we have enough data in total.
|
|
|
|
|
// On arm64 the fips sections in this test currently total 23 kB.
|
|
|
|
|
n := uintptr(0)
|
|
|
|
|
for _, s := range Linkinfo.Sects {
|
|
|
|
|
n += uintptr(s.End) - uintptr(s.Start)
|
|
|
|
|
}
|
|
|
|
|
if n < 16*1024 {
|
|
|
|
|
t.Fatalf("fips sections not big enough: %d, want at least 16 kB", n)
|
|
|
|
|
}
|
|
|
|
|
}
|