1
2
3
4
5 package fipstest
6
7 import (
8 "crypto/rand"
9 "crypto/x509"
10 "encoding/pem"
11 "fmt"
12 "internal/testenv"
13 "io/fs"
14 "os"
15 "regexp"
16 "strings"
17 "testing"
18
19
20 _ "crypto/internal/fips140/aes"
21 _ "crypto/internal/fips140/aes/gcm"
22 _ "crypto/internal/fips140/drbg"
23 "crypto/internal/fips140/ecdh"
24 "crypto/internal/fips140/ecdsa"
25 "crypto/internal/fips140/ed25519"
26 _ "crypto/internal/fips140/hkdf"
27 _ "crypto/internal/fips140/hmac"
28 "crypto/internal/fips140/mlkem"
29 "crypto/internal/fips140/rsa"
30 "crypto/internal/fips140/sha256"
31 _ "crypto/internal/fips140/sha3"
32 _ "crypto/internal/fips140/sha512"
33 _ "crypto/internal/fips140/tls12"
34 _ "crypto/internal/fips140/tls13"
35 )
36
37 func findAllCASTs(t *testing.T) map[string]struct{} {
38 testenv.MustHaveSource(t)
39
40
41
42 cmd := testenv.Command(t, testenv.GoToolPath(t), "list", "-f", `{{.Dir}}`, "crypto/internal/fips140")
43 out, err := cmd.CombinedOutput()
44 if err != nil {
45 t.Fatalf("go list: %v\n%s", err, out)
46 }
47 fipsDir := strings.TrimSpace(string(out))
48 t.Logf("FIPS module directory: %s", fipsDir)
49
50
51 allCASTs := make(map[string]struct{})
52 castRe := regexp.MustCompile(`fips140\.(CAST|PCT)\("([^"]+)"`)
53 if err := fs.WalkDir(os.DirFS(fipsDir), ".", func(path string, d fs.DirEntry, err error) error {
54 if err != nil {
55 return err
56 }
57 if d.IsDir() || !strings.HasSuffix(path, ".go") {
58 return nil
59 }
60 data, err := os.ReadFile(fipsDir + "/" + path)
61 if err != nil {
62 return err
63 }
64 for _, m := range castRe.FindAllSubmatch(data, -1) {
65 allCASTs[string(m[2])] = struct{}{}
66 }
67 return nil
68 }); err != nil {
69 t.Fatalf("WalkDir: %v", err)
70 }
71
72 return allCASTs
73 }
74
75
76 func TestConditionals(t *testing.T) {
77 mlkem.GenerateKey768()
78 k, err := ecdh.GenerateKey(ecdh.P256(), rand.Reader)
79 if err != nil {
80 t.Fatal(err)
81 }
82 ecdh.ECDH(ecdh.P256(), k, k.PublicKey())
83 kDSA, err := ecdsa.GenerateKey(ecdsa.P256(), rand.Reader)
84 if err != nil {
85 t.Fatal(err)
86 }
87 ecdsa.SignDeterministic(ecdsa.P256(), sha256.New, kDSA, make([]byte, 32))
88 k25519, err := ed25519.GenerateKey()
89 if err != nil {
90 t.Fatal(err)
91 }
92 ed25519.Sign(k25519, make([]byte, 32))
93 rsa.VerifyPKCS1v15(&rsa.PublicKey{}, "", nil, nil)
94
95 block, _ := pem.Decode([]byte(strings.ReplaceAll(
96 `-----BEGIN RSA TESTING KEY-----
97 MIIEowIBAAKCAQEAsPnoGUOnrpiSqt4XynxA+HRP7S+BSObI6qJ7fQAVSPtRkqso
98 tWxQYLEYzNEx5ZSHTGypibVsJylvCfuToDTfMul8b/CZjP2Ob0LdpYrNH6l5hvFE
99 89FU1nZQF15oVLOpUgA7wGiHuEVawrGfey92UE68mOyUVXGweJIVDdxqdMoPvNNU
100 l86BU02vlBiESxOuox+dWmuVV7vfYZ79Toh/LUK43YvJh+rhv4nKuF7iHjVjBd9s
101 B6iDjj70HFldzOQ9r8SRI+9NirupPTkF5AKNe6kUhKJ1luB7S27ZkvB3tSTT3P59
102 3VVJvnzOjaA1z6Cz+4+eRvcysqhrRgFlwI9TEwIDAQABAoIBAEEYiyDP29vCzx/+
103 dS3LqnI5BjUuJhXUnc6AWX/PCgVAO+8A+gZRgvct7PtZb0sM6P9ZcLrweomlGezI
104 FrL0/6xQaa8bBr/ve/a8155OgcjFo6fZEw3Dz7ra5fbSiPmu4/b/kvrg+Br1l77J
105 aun6uUAs1f5B9wW+vbR7tzbT/mxaUeDiBzKpe15GwcvbJtdIVMa2YErtRjc1/5B2
106 BGVXyvlJv0SIlcIEMsHgnAFOp1ZgQ08aDzvilLq8XVMOahAhP1O2A3X8hKdXPyrx
107 IVWE9bS9ptTo+eF6eNl+d7htpKGEZHUxinoQpWEBTv+iOoHsVunkEJ3vjLP3lyI/
108 fY0NQ1ECgYEA3RBXAjgvIys2gfU3keImF8e/TprLge1I2vbWmV2j6rZCg5r/AS0u
109 pii5CvJ5/T5vfJPNgPBy8B/yRDs+6PJO1GmnlhOkG9JAIPkv0RBZvR0PMBtbp6nT
110 Y3yo1lwamBVBfY6rc0sLTzosZh2aGoLzrHNMQFMGaauORzBFpY5lU50CgYEAzPHl
111 u5DI6Xgep1vr8QvCUuEesCOgJg8Yh1UqVoY/SmQh6MYAv1I9bLGwrb3WW/7kqIoD
112 fj0aQV5buVZI2loMomtU9KY5SFIsPV+JuUpy7/+VE01ZQM5FdY8wiYCQiVZYju9X
113 Wz5LxMNoz+gT7pwlLCsC4N+R8aoBk404aF1gum8CgYAJ7VTq7Zj4TFV7Soa/T1eE
114 k9y8a+kdoYk3BASpCHJ29M5R2KEA7YV9wrBklHTz8VzSTFTbKHEQ5W5csAhoL5Fo
115 qoHzFFi3Qx7MHESQb9qHyolHEMNx6QdsHUn7rlEnaTTyrXh3ifQtD6C0yTmFXUIS
116 CW9wKApOrnyKJ9nI0HcuZQKBgQCMtoV6e9VGX4AEfpuHvAAnMYQFgeBiYTkBKltQ
117 XwozhH63uMMomUmtSG87Sz1TmrXadjAhy8gsG6I0pWaN7QgBuFnzQ/HOkwTm+qKw
118 AsrZt4zeXNwsH7QXHEJCFnCmqw9QzEoZTrNtHJHpNboBuVnYcoueZEJrP8OnUG3r
119 UjmopwKBgAqB2KYYMUqAOvYcBnEfLDmyZv9BTVNHbR2lKkMYqv5LlvDaBxVfilE0
120 2riO4p6BaAdvzXjKeRrGNEKoHNBpOSfYCOM16NjL8hIZB1CaV3WbT5oY+jp7Mzd5
121 7d56RZOE+ERK2uz/7JX9VSsM/LbH9pJibd4e8mikDS9ntciqOH/3
122 -----END RSA TESTING KEY-----`, "TESTING KEY", "PRIVATE KEY")))
123 if _, err := x509.ParsePKCS1PrivateKey(block.Bytes); err != nil {
124 t.Fatal(err)
125 }
126 t.Log("completed successfully")
127 }
128
129 func TestCASTFailures(t *testing.T) {
130 testenv.MustHaveExec(t)
131
132 allCASTs := findAllCASTs(t)
133 if len(allCASTs) == 0 {
134 t.Fatal("no CASTs found")
135 }
136
137 for name := range allCASTs {
138 t.Run(name, func(t *testing.T) {
139 t.Parallel()
140 cmd := testenv.Command(t, testenv.Executable(t), "-test.run=TestConditionals", "-test.v")
141 cmd = testenv.CleanCmdEnv(cmd)
142 cmd.Env = append(cmd.Env, fmt.Sprintf("GODEBUG=failfipscast=%s,fips140=on", name))
143 out, err := cmd.CombinedOutput()
144 if err == nil {
145 t.Error(err)
146 } else {
147 t.Logf("CAST/PCT %s failed and caused the program to exit or the test to fail", name)
148 t.Logf("%s", out)
149 }
150 if strings.Contains(string(out), "completed successfully") {
151 t.Errorf("CAST/PCT %s failure did not stop the program", name)
152 }
153 })
154 }
155 }
156
View as plain text