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 "golang.org/x/mod/sumdb/dirhash"
20 )
21
22 var update = flag.Bool("update", false, "update GOROOT/lib/fips140/fips140.sum")
23
24 func TestSums(t *testing.T) {
25 lib := filepath.Join(testenv.GOROOT(t), "lib/fips140")
26 file := filepath.Join(lib, "fips140.sum")
27 sums, err := os.ReadFile(file)
28 if err != nil {
29 t.Fatal(err)
30 }
31 lines := strings.SplitAfter(string(sums), "\n")
32
33 zips, err := filepath.Glob(filepath.Join(lib, "*.zip"))
34 if err != nil {
35 t.Fatal(err)
36 }
37
38 format := func(name string, sum [32]byte, ziphash string) string {
39 return fmt.Sprintf("%s %x %s\n", name, sum[:], ziphash)
40 }
41
42 want := make(map[string]string)
43 for _, zip := range zips {
44 data, err := os.ReadFile(zip)
45 if err != nil {
46 t.Fatal(err)
47 }
48 ziphash, err := dirhash.HashZip(zip, dirhash.DefaultHash)
49 if err != nil {
50 t.Fatal(err)
51 }
52 name := filepath.Base(zip)
53 want[name] = format(name, sha256.Sum256(data), ziphash)
54 }
55
56
57 var diff []string
58 have := make(map[string]bool)
59 for i, line := range lines {
60 if line == "" {
61 continue
62 }
63 if strings.HasPrefix(line, "#") || line == "\n" {
64
65 diff = append(diff, " "+line)
66 continue
67 }
68 name, _, _ := strings.Cut(line, " ")
69 if want[name] == "" {
70 lines[i] = ""
71 diff = append(diff, "-"+line)
72 continue
73 }
74 have[name] = true
75 fixed := want[name]
76 delete(want, name)
77 if line == fixed {
78 diff = append(diff, " "+line)
79 } else {
80
81 t.Errorf("policy violation: zip file hash is changing:\n-%s+%s", line, fixed)
82 lines[i] = fixed
83 diff = append(diff, "-"+line, "+"+fixed)
84 }
85 }
86
87
88
89
90 for _, name := range slices.Sorted(maps.Keys(want)) {
91 line := want[name]
92 lines = append(lines, line)
93 diff = append(diff, "+"+line)
94 }
95
96
97 fixed := strings.Join(lines, "")
98 if fixed != string(sums) {
99 if *update && !t.Failed() {
100 t.Logf("updating GOROOT/lib/fips140/fips140.sum:\n%s", strings.Join(diff, ""))
101 if err := os.WriteFile(file, []byte(fixed), 0666); err != nil {
102 t.Fatal(err)
103 }
104 return
105 }
106 t.Errorf("GOROOT/lib/fips140/fips140.sum out of date. changes needed:\n%s", strings.Join(diff, ""))
107 }
108 }
109
110 func TestVerifyZipSum(t *testing.T) {
111 dir := t.TempDir()
112 zipfile := filepath.Join(dir, "v1.2.3.zip")
113 data := []byte("not really a zip, but it does not matter here")
114 if err := os.WriteFile(zipfile, data, 0666); err != nil {
115 t.Fatal(err)
116 }
117 sum := sha256.Sum256(data)
118
119 sumfile := filepath.Join(dir, "fips140.sum")
120 write := func(contents string) {
121 if err := os.WriteFile(sumfile, []byte(contents), 0666); err != nil {
122 t.Fatal(err)
123 }
124 }
125
126 const (
127 zeroSum = "0000000000000000000000000000000000000000000000000000000000000000"
128 ziphash = "h1:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
129 )
130
131
132 write(fmt.Sprintf("# comment\n\nv1.2.3.zip %x %s\nother.zip %s h1:other=\n", sum[:], ziphash, zeroSum))
133 if err := verifyZipSum(zipfile, sumfile); err != nil {
134 t.Errorf("unexpected error: %v", err)
135 }
136
137
138 write("# only comments\n")
139 if err := verifyZipSum(zipfile, sumfile); err == nil {
140 t.Errorf("expected error when hash entry is missing")
141 }
142
143
144 write(fmt.Sprintf("v1.2.3.zip %s %s\n", zeroSum, ziphash))
145 if err := verifyZipSum(zipfile, sumfile); err == nil {
146 t.Errorf("expected error when hash does not match")
147 }
148
149
150 if err := verifyZipSum(zipfile, filepath.Join(dir, "does-not-exist.sum")); err == nil {
151 t.Errorf("expected error when sum file is missing")
152 }
153 }
154
View as plain text