| // 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. |
| |
| package fips140 |
| |
| import ( |
| "crypto/sha256" |
| "flag" |
| "fmt" |
| "internal/testenv" |
| "maps" |
| "os" |
| "path/filepath" |
| "slices" |
| "strings" |
| "testing" |
| ) |
| |
| var update = flag.Bool("update", false, "update GOROOT/lib/fips140/fips140.sum") |
| |
| func TestSums(t *testing.T) { |
| lib := filepath.Join(testenv.GOROOT(t), "lib/fips140") |
| file := filepath.Join(lib, "fips140.sum") |
| sums, err := os.ReadFile(file) |
| if err != nil { |
| t.Fatal(err) |
| } |
| lines := strings.SplitAfter(string(sums), "\n") |
| |
| zips, err := filepath.Glob(filepath.Join(lib, "*.zip")) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| format := func(name string, sum [32]byte) string { |
| return fmt.Sprintf("%s %x\n", name, sum[:]) |
| } |
| |
| want := make(map[string]string) |
| for _, zip := range zips { |
| data, err := os.ReadFile(zip) |
| if err != nil { |
| t.Fatal(err) |
| } |
| name := filepath.Base(zip) |
| want[name] = format(name, sha256.Sum256(data)) |
| } |
| |
| // Process diff, deleting or correcting stale lines. |
| var diff []string |
| have := make(map[string]bool) |
| for i, line := range lines { |
| if line == "" { |
| continue |
| } |
| if strings.HasPrefix(line, "#") || line == "\n" { |
| // comment, preserve |
| diff = append(diff, " "+line) |
| continue |
| } |
| name, _, _ := strings.Cut(line, " ") |
| if want[name] == "" { |
| lines[i] = "" |
| diff = append(diff, "-"+line) |
| continue |
| } |
| have[name] = true |
| fixed := want[name] |
| delete(want, name) |
| if line == fixed { |
| diff = append(diff, " "+line) |
| } else { |
| // zip hashes should never change once listed |
| t.Errorf("policy violation: zip file hash is changing:\n-%s+%s", line, fixed) |
| lines[i] = fixed |
| diff = append(diff, "-"+line, "+"+fixed) |
| } |
| } |
| |
| // Add missing lines. |
| // Sort keys to avoid non-determinism, but overall file is not sorted. |
| // It will end up time-ordered instead. |
| for _, name := range slices.Sorted(maps.Keys(want)) { |
| line := want[name] |
| lines = append(lines, line) |
| diff = append(diff, "+"+line) |
| } |
| |
| // Show diffs or update file. |
| fixed := strings.Join(lines, "") |
| if fixed != string(sums) { |
| if *update && !t.Failed() { |
| t.Logf("updating GOROOT/lib/fips140/fips140.sum:\n%s", strings.Join(diff, "")) |
| if err := os.WriteFile(file, []byte(fixed), 0666); err != nil { |
| t.Fatal(err) |
| } |
| return |
| } |
| t.Errorf("GOROOT/lib/fips140/fips140.sum out of date. changes needed:\n%s", strings.Join(diff, "")) |
| } |
| } |