1
2
3
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
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
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
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
82
83
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
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
104 func TestVerifyZipSum(t *testing.T) {
105 dir := t.TempDir()
106 zipfile := filepath.Join(dir, "v1.2.3.zip")
107 data := []byte("not really a zip, but it does not matter here")
108 if err := os.WriteFile(zipfile, data, 0666); err != nil {
109 t.Fatal(err)
110 }
111 sum := sha256.Sum256(data)
112
113 sumfile := filepath.Join(dir, "fips140.sum")
114 write := func(contents string) {
115 if err := os.WriteFile(sumfile, []byte(contents), 0666); err != nil {
116 t.Fatal(err)
117 }
118 }
119
120
121 write(fmt.Sprintf("# comment\n\nv1.2.3.zip %x\nother.zip 0000000000000000000000000000000000000000000000000000000000000000\n", sum[:]))
122 if err := verifyZipSum(zipfile, sumfile); err != nil {
123 t.Errorf("unexpected error: %v", err)
124 }
125
126
127 write("# only comments\n")
128 if err := verifyZipSum(zipfile, sumfile); err == nil {
129 t.Errorf("expected error when hash entry is missing")
130 }
131
132
133 write("v1.2.3.zip 0000000000000000000000000000000000000000000000000000000000000000\n")
134 if err := verifyZipSum(zipfile, sumfile); err == nil {
135 t.Errorf("expected error when hash does not match")
136 }
137
138
139 if err := verifyZipSum(zipfile, filepath.Join(dir, "does-not-exist.sum")); err == nil {
140 t.Errorf("expected error when sum file is missing")
141 }
142 }
143
View as plain text