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 "slices"
17 "strings"
18 "testing"
19
20
21 _ "crypto/internal/fips140/aes"
22 _ "crypto/internal/fips140/aes/gcm"
23 _ "crypto/internal/fips140/drbg"
24 "crypto/internal/fips140/ecdh"
25 "crypto/internal/fips140/ecdsa"
26 "crypto/internal/fips140/ed25519"
27 _ "crypto/internal/fips140/hkdf"
28 _ "crypto/internal/fips140/hmac"
29 "crypto/internal/fips140/mlkem"
30 "crypto/internal/fips140/rsa"
31 "crypto/internal/fips140/sha256"
32 _ "crypto/internal/fips140/sha3"
33 _ "crypto/internal/fips140/sha512"
34 _ "crypto/internal/fips140/tls12"
35 _ "crypto/internal/fips140/tls13"
36 )
37
38 var allCASTs = []string{
39 "AES-CBC",
40 "CTR_DRBG",
41 "CounterKDF",
42 "DetECDSA P-256 SHA2-512 sign",
43 "ECDH PCT",
44 "ECDSA P-256 SHA2-512 sign and verify",
45 "ECDSA PCT",
46 "Ed25519 sign and verify",
47 "Ed25519 sign and verify PCT",
48 "HKDF-SHA2-256",
49 "HMAC-SHA2-256",
50 "KAS-ECC-SSC P-256",
51 "ML-KEM PCT",
52 "ML-KEM PCT",
53 "ML-KEM PCT",
54 "ML-KEM PCT",
55 "ML-KEM-768",
56 "PBKDF2",
57 "RSA sign and verify PCT",
58 "RSASSA-PKCS-v1.5 2048-bit sign and verify",
59 "SHA2-256",
60 "SHA2-512",
61 "TLSv1.2-SHA2-256",
62 "TLSv1.3-SHA2-256",
63 "cSHAKE128",
64 }
65
66 func TestAllCASTs(t *testing.T) {
67 testenv.MustHaveSource(t)
68
69
70
71 cmd := testenv.Command(t, testenv.GoToolPath(t), "list", "-f", `{{.Dir}}`, "crypto/internal/fips140")
72 out, err := cmd.CombinedOutput()
73 if err != nil {
74 t.Fatalf("go list: %v\n%s", err, out)
75 }
76 fipsDir := strings.TrimSpace(string(out))
77 t.Logf("FIPS module directory: %s", fipsDir)
78
79
80 var foundCASTs []string
81 castRe := regexp.MustCompile(`fips140\.(CAST|PCT)\("([^"]+)"`)
82 if err := fs.WalkDir(os.DirFS(fipsDir), ".", func(path string, d fs.DirEntry, err error) error {
83 if err != nil {
84 return err
85 }
86 if d.IsDir() || !strings.HasSuffix(path, ".go") {
87 return nil
88 }
89 data, err := os.ReadFile(fipsDir + "/" + path)
90 if err != nil {
91 return err
92 }
93 for _, m := range castRe.FindAllSubmatch(data, -1) {
94 foundCASTs = append(foundCASTs, string(m[2]))
95 }
96 return nil
97 }); err != nil {
98 t.Fatalf("WalkDir: %v", err)
99 }
100
101 slices.Sort(foundCASTs)
102 if !slices.Equal(foundCASTs, allCASTs) {
103 t.Errorf("AllCASTs is out of date. Found CASTs: %#v", foundCASTs)
104 }
105 }
106
107
108 func TestConditionals(t *testing.T) {
109 mlkem.GenerateKey768()
110 k, err := ecdh.GenerateKey(ecdh.P256(), rand.Reader)
111 if err != nil {
112 t.Fatal(err)
113 }
114 ecdh.ECDH(ecdh.P256(), k, k.PublicKey())
115 kDSA, err := ecdsa.GenerateKey(ecdsa.P256(), rand.Reader)
116 if err != nil {
117 t.Fatal(err)
118 }
119 ecdsa.SignDeterministic(ecdsa.P256(), sha256.New, kDSA, make([]byte, 32))
120 k25519, err := ed25519.GenerateKey()
121 if err != nil {
122 t.Fatal(err)
123 }
124 ed25519.Sign(k25519, make([]byte, 32))
125 rsa.VerifyPKCS1v15(&rsa.PublicKey{}, "", nil, nil)
126
127 block, _ := pem.Decode([]byte(strings.ReplaceAll(
128 `-----BEGIN RSA TESTING KEY-----
129 MIIEowIBAAKCAQEAsPnoGUOnrpiSqt4XynxA+HRP7S+BSObI6qJ7fQAVSPtRkqso
130 tWxQYLEYzNEx5ZSHTGypibVsJylvCfuToDTfMul8b/CZjP2Ob0LdpYrNH6l5hvFE
131 89FU1nZQF15oVLOpUgA7wGiHuEVawrGfey92UE68mOyUVXGweJIVDdxqdMoPvNNU
132 l86BU02vlBiESxOuox+dWmuVV7vfYZ79Toh/LUK43YvJh+rhv4nKuF7iHjVjBd9s
133 B6iDjj70HFldzOQ9r8SRI+9NirupPTkF5AKNe6kUhKJ1luB7S27ZkvB3tSTT3P59
134 3VVJvnzOjaA1z6Cz+4+eRvcysqhrRgFlwI9TEwIDAQABAoIBAEEYiyDP29vCzx/+
135 dS3LqnI5BjUuJhXUnc6AWX/PCgVAO+8A+gZRgvct7PtZb0sM6P9ZcLrweomlGezI
136 FrL0/6xQaa8bBr/ve/a8155OgcjFo6fZEw3Dz7ra5fbSiPmu4/b/kvrg+Br1l77J
137 aun6uUAs1f5B9wW+vbR7tzbT/mxaUeDiBzKpe15GwcvbJtdIVMa2YErtRjc1/5B2
138 BGVXyvlJv0SIlcIEMsHgnAFOp1ZgQ08aDzvilLq8XVMOahAhP1O2A3X8hKdXPyrx
139 IVWE9bS9ptTo+eF6eNl+d7htpKGEZHUxinoQpWEBTv+iOoHsVunkEJ3vjLP3lyI/
140 fY0NQ1ECgYEA3RBXAjgvIys2gfU3keImF8e/TprLge1I2vbWmV2j6rZCg5r/AS0u
141 pii5CvJ5/T5vfJPNgPBy8B/yRDs+6PJO1GmnlhOkG9JAIPkv0RBZvR0PMBtbp6nT
142 Y3yo1lwamBVBfY6rc0sLTzosZh2aGoLzrHNMQFMGaauORzBFpY5lU50CgYEAzPHl
143 u5DI6Xgep1vr8QvCUuEesCOgJg8Yh1UqVoY/SmQh6MYAv1I9bLGwrb3WW/7kqIoD
144 fj0aQV5buVZI2loMomtU9KY5SFIsPV+JuUpy7/+VE01ZQM5FdY8wiYCQiVZYju9X
145 Wz5LxMNoz+gT7pwlLCsC4N+R8aoBk404aF1gum8CgYAJ7VTq7Zj4TFV7Soa/T1eE
146 k9y8a+kdoYk3BASpCHJ29M5R2KEA7YV9wrBklHTz8VzSTFTbKHEQ5W5csAhoL5Fo
147 qoHzFFi3Qx7MHESQb9qHyolHEMNx6QdsHUn7rlEnaTTyrXh3ifQtD6C0yTmFXUIS
148 CW9wKApOrnyKJ9nI0HcuZQKBgQCMtoV6e9VGX4AEfpuHvAAnMYQFgeBiYTkBKltQ
149 XwozhH63uMMomUmtSG87Sz1TmrXadjAhy8gsG6I0pWaN7QgBuFnzQ/HOkwTm+qKw
150 AsrZt4zeXNwsH7QXHEJCFnCmqw9QzEoZTrNtHJHpNboBuVnYcoueZEJrP8OnUG3r
151 UjmopwKBgAqB2KYYMUqAOvYcBnEfLDmyZv9BTVNHbR2lKkMYqv5LlvDaBxVfilE0
152 2riO4p6BaAdvzXjKeRrGNEKoHNBpOSfYCOM16NjL8hIZB1CaV3WbT5oY+jp7Mzd5
153 7d56RZOE+ERK2uz/7JX9VSsM/LbH9pJibd4e8mikDS9ntciqOH/3
154 -----END RSA TESTING KEY-----`, "TESTING KEY", "PRIVATE KEY")))
155 if _, err := x509.ParsePKCS1PrivateKey(block.Bytes); err != nil {
156 t.Fatal(err)
157 }
158 t.Log("completed successfully")
159 }
160
161 func TestCASTFailures(t *testing.T) {
162 moduleStatus(t)
163 testenv.MustHaveExec(t)
164
165 for _, name := range allCASTs {
166 t.Run(name, func(t *testing.T) {
167
168
169 if !testing.Verbose() {
170 t.Parallel()
171 }
172 t.Logf("CAST/PCT succeeded: %s", name)
173 t.Logf("Testing CAST/PCT failure...")
174 cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^TestConditionals$", "-test.v")
175 cmd.Env = append(cmd.Env, fmt.Sprintf("GODEBUG=failfipscast=%s,fips140=on", name))
176 out, err := cmd.CombinedOutput()
177 t.Logf("%s", out)
178 if err == nil {
179 t.Fatal("Test did not fail as expected")
180 }
181 if strings.Contains(string(out), "completed successfully") {
182 t.Errorf("CAST/PCT %s failure did not stop the program", name)
183 } else {
184 t.Logf("CAST/PCT %s failed as expected and caused the program to exit", name)
185 }
186 })
187 }
188 }
189
View as plain text