Source file src/crypto/internal/fips/check/check_test.go

     1  // Copyright 2024 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package check_test
     6  
     7  import (
     8  	. "crypto/internal/fips/check"
     9  	"crypto/internal/fips/check/checktest"
    10  	"fmt"
    11  	"internal/abi"
    12  	"internal/godebug"
    13  	"os"
    14  	"os/exec"
    15  	"runtime"
    16  	"testing"
    17  	"unicode"
    18  	"unsafe"
    19  )
    20  
    21  const enableFIPSTest = true
    22  
    23  func TestVerify(t *testing.T) {
    24  	if *Verified {
    25  		t.Logf("verified")
    26  		return
    27  	}
    28  
    29  	if godebug.New("#fips140").Value() == "on" {
    30  		t.Fatalf("GODEBUG=fips140=on but verification did not run")
    31  	}
    32  
    33  	if !enableFIPSTest {
    34  		return
    35  	}
    36  
    37  	if !Supported() {
    38  		t.Skipf("skipping on %s-%s", runtime.GOOS, runtime.GOARCH)
    39  	}
    40  
    41  	cmd := exec.Command(os.Args[0], "-test.v")
    42  	cmd.Env = append(cmd.Environ(), "GODEBUG=fips140=on")
    43  	out, err := cmd.CombinedOutput()
    44  	if err != nil {
    45  		t.Fatalf("GODEBUG=fips140=on %v failed: %v\n%s", cmd.Args, err, out)
    46  	}
    47  	t.Logf("exec'ed GODEBUG=fips140=on and succeeded:\n%s", out)
    48  }
    49  
    50  func TestInfo(t *testing.T) {
    51  	if !enableFIPSTest {
    52  		return
    53  	}
    54  
    55  	if !Supported() {
    56  		t.Skipf("skipping on %s-%s", runtime.GOOS, runtime.GOARCH)
    57  	}
    58  
    59  	// Check that the checktest symbols are initialized properly.
    60  	if checktest.NOPTRDATA != 1 {
    61  		t.Errorf("checktest.NOPTRDATA = %d, want 1", checktest.NOPTRDATA)
    62  	}
    63  	if checktest.RODATA != 2 {
    64  		t.Errorf("checktest.RODATA = %d, want 2", checktest.RODATA)
    65  	}
    66  	if checktest.DATA.P != &checktest.NOPTRDATA {
    67  		t.Errorf("checktest.DATA.P = %p, want &checktest.NOPTRDATA (%p)", checktest.DATA.P, &checktest.NOPTRDATA)
    68  	}
    69  	if checktest.DATA.X != 3 {
    70  		t.Errorf("checktest.DATA.X = %d, want 3", checktest.DATA.X)
    71  	}
    72  	if checktest.NOPTRBSS != 0 {
    73  		t.Errorf("checktest.NOPTRBSS = %d, want 0", checktest.NOPTRBSS)
    74  	}
    75  	if checktest.BSS != nil {
    76  		t.Errorf("checktest.BSS = %p, want nil", checktest.BSS)
    77  	}
    78  
    79  	// Check that the checktest symbols are in the right go:fipsinfo sections.
    80  	sect := func(i int, name string, p unsafe.Pointer) {
    81  		s := Linkinfo.Sects[i]
    82  		if !(uintptr(s.Start) <= uintptr(p) && uintptr(p) < uintptr(s.End)) {
    83  			t.Errorf("checktest.%s (%#x) not in section #%d (%#x..%#x)", name, p, i, s.Start, s.End)
    84  		}
    85  	}
    86  	sect(0, "TEXT", unsafe.Pointer(abi.FuncPCABIInternal(checktest.TEXT)))
    87  	sect(1, "RODATA", unsafe.Pointer(&checktest.RODATA))
    88  	sect(2, "NOPTRDATA", unsafe.Pointer(&checktest.NOPTRDATA))
    89  	sect(3, "DATA", unsafe.Pointer(&checktest.DATA))
    90  
    91  	// Check that some symbols are not in FIPS sections.
    92  	no := func(name string, p unsafe.Pointer, ix ...int) {
    93  		for _, i := range ix {
    94  			s := Linkinfo.Sects[i]
    95  			if uintptr(s.Start) <= uintptr(p) && uintptr(p) < uintptr(s.End) {
    96  				t.Errorf("%s (%#x) unexpectedly in section #%d (%#x..%#x)", name, p, i, s.Start, s.End)
    97  			}
    98  		}
    99  	}
   100  
   101  	// Check that the symbols are not in unexpected sections (that is, no overlaps).
   102  	no("checktest.TEXT", unsafe.Pointer(abi.FuncPCABIInternal(checktest.TEXT)), 1, 2, 3)
   103  	no("checktest.RODATA", unsafe.Pointer(&checktest.RODATA), 0, 2, 3)
   104  	no("checktest.NOPTRDATA", unsafe.Pointer(&checktest.NOPTRDATA), 0, 1, 3)
   105  	no("checktest.DATA", unsafe.Pointer(&checktest.DATA), 0, 1, 2)
   106  
   107  	// Check that non-FIPS symbols are not in any of the sections.
   108  	no("fmt.Printf", unsafe.Pointer(abi.FuncPCABIInternal(fmt.Printf)), 0, 1, 2, 3)     // TEXT
   109  	no("unicode.Categories", unsafe.Pointer(&unicode.Categories), 0, 1, 2, 3)           // BSS
   110  	no("unicode.ASCII_Hex_Digit", unsafe.Pointer(&unicode.ASCII_Hex_Digit), 0, 1, 2, 3) // DATA
   111  
   112  	// Check that we have enough data in total.
   113  	// On arm64 the fips sections in this test currently total 23 kB.
   114  	n := uintptr(0)
   115  	for _, s := range Linkinfo.Sects {
   116  		n += uintptr(s.End) - uintptr(s.Start)
   117  	}
   118  	if n < 16*1024 {
   119  		t.Fatalf("fips sections not big enough: %d, want at least 16 kB", n)
   120  	}
   121  }
   122  

View as plain text