Source file src/cmd/go/internal/fips140/fips_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 fips140
     6  
     7  import (
     8  	"crypto/sha256"
     9  	"flag"
    10  	"fmt"
    11  	"internal/testenv"
    12  	"maps"
    13  	"os"
    14  	"path/filepath"
    15  	"slices"
    16  	"strings"
    17  	"testing"
    18  )
    19  
    20  var update = flag.Bool("update", false, "update GOROOT/lib/fips140/fips140.sum")
    21  
    22  func TestSums(t *testing.T) {
    23  	lib := filepath.Join(testenv.GOROOT(t), "lib/fips140")
    24  	file := filepath.Join(lib, "fips140.sum")
    25  	sums, err := os.ReadFile(file)
    26  	if err != nil {
    27  		t.Fatal(err)
    28  	}
    29  	lines := strings.SplitAfter(string(sums), "\n")
    30  
    31  	zips, err := filepath.Glob(filepath.Join(lib, "*.zip"))
    32  	if err != nil {
    33  		t.Fatal(err)
    34  	}
    35  
    36  	format := func(name string, sum [32]byte) string {
    37  		return fmt.Sprintf("%s %x\n", name, sum[:])
    38  	}
    39  
    40  	want := make(map[string]string)
    41  	for _, zip := range zips {
    42  		data, err := os.ReadFile(zip)
    43  		if err != nil {
    44  			t.Fatal(err)
    45  		}
    46  		name := filepath.Base(zip)
    47  		want[name] = format(name, sha256.Sum256(data))
    48  	}
    49  
    50  	// Process diff, deleting or correcting stale lines.
    51  	var diff []string
    52  	have := make(map[string]bool)
    53  	for i, line := range lines {
    54  		if line == "" {
    55  			continue
    56  		}
    57  		if strings.HasPrefix(line, "#") || line == "\n" {
    58  			// comment, preserve
    59  			diff = append(diff, " "+line)
    60  			continue
    61  		}
    62  		name, _, _ := strings.Cut(line, " ")
    63  		if want[name] == "" {
    64  			lines[i] = ""
    65  			diff = append(diff, "-"+line)
    66  			continue
    67  		}
    68  		have[name] = true
    69  		fixed := want[name]
    70  		delete(want, name)
    71  		if line == fixed {
    72  			diff = append(diff, " "+line)
    73  		} else {
    74  			// zip hashes should never change once listed
    75  			t.Errorf("policy violation: zip file hash is changing:\n-%s+%s", line, fixed)
    76  			lines[i] = fixed
    77  			diff = append(diff, "-"+line, "+"+fixed)
    78  		}
    79  	}
    80  
    81  	// Add missing lines.
    82  	// Sort keys to avoid non-determinism, but overall file is not sorted.
    83  	// It will end up time-ordered instead.
    84  	for _, name := range slices.Sorted(maps.Keys(want)) {
    85  		line := want[name]
    86  		lines = append(lines, line)
    87  		diff = append(diff, "+"+line)
    88  	}
    89  
    90  	// Show diffs or update file.
    91  	fixed := strings.Join(lines, "")
    92  	if fixed != string(sums) {
    93  		if *update && !t.Failed() {
    94  			t.Logf("updating GOROOT/lib/fips140/fips140.sum:\n%s", strings.Join(diff, ""))
    95  			if err := os.WriteFile(file, []byte(fixed), 0666); err != nil {
    96  				t.Fatal(err)
    97  			}
    98  			return
    99  		}
   100  		t.Errorf("GOROOT/lib/fips140/fips140.sum out of date. changes needed:\n%s", strings.Join(diff, ""))
   101  	}
   102  }
   103  

View as plain text