github.com/Psiphon-Labs/tls-tris@v0.0.0-20230824155421-58bf6d336a9a/subcerts_test.go (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package tls 6 7 import ( 8 "crypto" 9 "crypto/x509" 10 "encoding/asn1" 11 "encoding/pem" 12 "errors" 13 "fmt" 14 "testing" 15 "time" 16 ) 17 18 // A PEM-encoded "delegation certificate", an X.509 certificate with the 19 // DelegationUsage extension. The extension is defined in 20 // specified in https://tools.ietf.org/html/draft-ietf-tls-subcerts-02. 21 const DcCertWithDelegationUsage = `-----BEGIN CERTIFICATE----- 22 MIIBejCCASGgAwIBAgIQXXtl0v50W2OadoW0QwLUlzAKBggqhkjOPQQDAjAUMRIw 23 EAYDVQQKEwlBY21lIEluYy4wHhcNMTgwNzMwMjAxMTE5WhcNMTgwODA2MjAxMTE5 24 WjAUMRIwEAYDVQQKEwlBY21lIEluYy4wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC 25 AATcQuuaUNJ3kqKGs4DBdJVd7zWzyGANT4uBNGVkZ2cgaDsdFnx99fGibfgoWer8 26 HLt9Z+S6Hs+8bDPBHNgTR/Lfo1UwUzAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAww 27 CgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAPBgNVHREECDAGhwR/AAABMA0GCSsG 28 AQQBgtpLLAQAMAoGCCqGSM49BAMCA0cAMEQCIEMdIkwwmzQAJ6RSDT3wcrsySx2B 29 5Lvx5HGzc43Fgu9eAiAi4sFXnizFBVUL43qXZBq4ARw17o0JW3/7eec1xttQhw== 30 -----END CERTIFICATE----- 31 ` 32 33 // The PEM-encoded "delegation key", the secret key associated with the 34 // delegation certificate. This is a key for ECDSA with P256 and SHA256. 35 const DcKeyWithDelegationUsage = `-----BEGIN EC PRIVATE KEY----- 36 MHcCAQEEIAS/pGktmxK1hlt3gF4N2nkMrJnoZihvOO63nnNcxXQroAoGCCqGSM49 37 AwEHoUQDQgAE3ELrmlDSd5KihrOAwXSVXe81s8hgDU+LgTRlZGdnIGg7HRZ8ffXx 38 om34KFnq/By7fWfkuh7PvGwzwRzYE0fy3w== 39 -----END EC PRIVATE KEY----- 40 ` 41 42 // A certificate without the DelegationUsage extension. 43 const DcCertWithoutDelegationUsage = `-----BEGIN CERTIFICATE----- 44 MIIBajCCAQ+gAwIBAgIRAMUg/VFqJaWWJwZ9iHoMjqIwCgYIKoZIzj0EAwIwEjEQ 45 MA4GA1UEChMHQWNtZSBDbzAeFw0xODA3MzAyMDExMTlaFw0xOTA3MzAyMDExMTla 46 MBIxEDAOBgNVBAoTB0FjbWUgQ28wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATA 47 n+oeWSvSNHhEskSRgkkerCQDoV/NA+r3S5AtCOFT5AYLt8xltSTWerFI/YlZLIcL 48 xlJPT7T+XpBnfS6xaAuxo0YwRDAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYI 49 KwYBBQUHAwEwDAYDVR0TAQH/BAIwADAPBgNVHREECDAGhwR/AAABMAoGCCqGSM49 50 BAMCA0kAMEYCIQCFGWnoJmwH1rxNCKBJWVDBKDTSsYhySRk4h9RPyR8bUwIhAJxc 51 KFyrowMTan791RJnyANH/4uYhmvkfhfrFGSTXUli 52 -----END CERTIFICATE----- 53 ` 54 55 // The secret key associatted with DcCertWithoutDelegationUsage. 56 const DcKeyWithoutDelegationUsage = `-----BEGIN EC PRIVATE KEY----- 57 MHcCAQEEIEP82pOhzx0tKkky9t0OmUo9MHgmfdAHxDN2cHmWGqOhoAoGCCqGSM49 58 AwEHoUQDQgAEwJ/qHlkr0jR4RLJEkYJJHqwkA6FfzQPq90uQLQjhU+QGC7fMZbUk 59 1nqxSP2JWSyHC8ZST0+0/l6QZ30usWgLsQ== 60 -----END EC PRIVATE KEY----- 61 ` 62 63 // dcTestDC stores delegated credentials and their secret keys. 64 type dcTestDC struct { 65 Name string 66 Version int 67 Scheme int 68 DC []byte 69 PrivateKey []byte 70 } 71 72 // Use with maxVersion == VersionTLS13. 73 const DcTestDataTLS13PEM = `-----BEGIN DC TEST DATA----- 74 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 118 jreml8HfVQ== 119 -----END DC TEST DATA-----` 120 121 // Parses the input PEM block containing the test DCs. 122 func dcLoadTestData(in []byte, out *[]dcTestDC) error { 123 block, _ := pem.Decode(in) 124 if block == nil { 125 return errors.New("failed to decode DC tests PEM block") 126 } 127 128 // Parse the DER-encoded test DCs. 129 _, err := asn1.Unmarshal(block.Bytes, out) 130 if err != nil { 131 return errors.New("failed to unmarshal DC test ASN.1 data") 132 } 133 134 // Check that the test data is for the right version. This should be 135 // maxVersion, defined in common.go. 136 for _, test := range *out { 137 dc, err := unmarshalDelegatedCredential(test.DC) 138 if err != nil { 139 return err 140 } 141 142 // Sanity check that test version matches the version encoded by the DC. 143 testVersion := uint16(test.Version) 144 if dc.cred.expectedVersion != testVersion { 145 return fmt.Errorf( 146 "test version doesn't match credential version: got: 0x0%04x; want: 0x%04x", 147 testVersion, dc.cred.expectedVersion) 148 } 149 150 // With the exception of "badvers" and "tsl12", all test DCs should have 151 // the expected verison. 152 if test.Name != "badvers" && test.Name != "tls12" && testVersion != maxVersion { 153 return fmt.Errorf( 154 "encountered test with wrong version: got: 0x0%04x; want: 0x%04x", 155 test.Version, maxVersion) 156 } 157 } 158 return nil 159 } 160 161 var dcTestDCs []dcTestDC 162 var dcTestConfig *Config 163 var dcTestDelegationCert Certificate 164 var dcTestCert Certificate 165 var dcTestNow time.Time 166 167 func init() { 168 // Load the DC test data. 169 var testData []byte 170 if maxVersion != 0x0304 { 171 panic(fmt.Errorf("no test data for version %04x", maxVersion)) 172 } 173 testData = []byte(DcTestDataTLS13PEM) 174 175 err := dcLoadTestData(testData, &dcTestDCs) 176 if err != nil { 177 panic(err) 178 } 179 180 // The base configuration for the client and server. 181 dcTestConfig = &Config{ 182 Time: func() time.Time { 183 return dcTestNow 184 }, 185 Rand: zeroSource{}, 186 Certificates: nil, 187 MinVersion: VersionTLS10, 188 MaxVersion: VersionTLS13, 189 CipherSuites: allCipherSuites(), 190 } 191 192 // The delegation certificate. 193 dcTestDelegationCert, err = X509KeyPair([]byte(DcCertWithDelegationUsage), []byte(DcKeyWithDelegationUsage)) 194 if err != nil { 195 panic(err) 196 } 197 dcTestDelegationCert.Leaf, err = x509.ParseCertificate(dcTestDelegationCert.Certificate[0]) 198 if err != nil { 199 panic(err) 200 } 201 202 // A certificate without the the DelegationUsage extension for X.509. 203 dcTestCert, err = X509KeyPair([]byte(DcCertWithoutDelegationUsage), []byte(DcKeyWithoutDelegationUsage)) 204 if err != nil { 205 panic(err) 206 } 207 dcTestCert.Leaf, err = x509.ParseCertificate(dcTestCert.Certificate[0]) 208 if err != nil { 209 panic(err) 210 } 211 212 // For testing purposes, use the point at which the test DCs were generated 213 // as the current time. This is the same as the time at which the 214 // delegation certificate was generated. 215 dcTestNow = dcTestDelegationCert.Leaf.NotBefore 216 217 // Make these roots of these certificates the client's trusted CAs. 218 dcTestConfig.RootCAs = x509.NewCertPool() 219 220 raw := dcTestDelegationCert.Certificate[len(dcTestDelegationCert.Certificate)-1] 221 root, err := x509.ParseCertificate(raw) 222 if err != nil { 223 panic(err) 224 } 225 dcTestConfig.RootCAs.AddCert(root) 226 227 raw = dcTestCert.Certificate[len(dcTestCert.Certificate)-1] 228 root, err = x509.ParseCertificate(raw) 229 if err != nil { 230 panic(err) 231 } 232 dcTestConfig.RootCAs.AddCert(root) 233 } 234 235 // Executes the handshake with the given configuration and returns true if the 236 // delegated credential extension was successfully negotiated. 237 func testConnWithDC(t *testing.T, clientConfig, serverConfig *Config) (bool, error) { 238 ln := newLocalListener(t) 239 defer ln.Close() 240 241 // Listen for and serve a single client connection. 242 srvCh := make(chan *Conn, 1) 243 var serr error 244 go func() { 245 sconn, err := ln.Accept() 246 if err != nil { 247 serr = err 248 srvCh <- nil 249 return 250 } 251 srv := Server(sconn, serverConfig) 252 if err := srv.Handshake(); err != nil { 253 serr = fmt.Errorf("handshake: %v", err) 254 srvCh <- nil 255 return 256 } 257 srvCh <- srv 258 }() 259 260 // Dial the server. 261 cli, err := Dial("tcp", ln.Addr().String(), clientConfig) 262 if err != nil { 263 return false, err 264 } 265 defer cli.Close() 266 267 srv := <-srvCh 268 if srv == nil { 269 return false, serr 270 } 271 272 // Return true if the client's conn.dc structure was instantiated. 273 st := cli.ConnectionState() 274 return (st.DelegatedCredential != nil), nil 275 } 276 277 // Checks that the client suppports a version >= 1.2 and accepts delegated 278 // credentials. If so, it returns the delegation certificate; otherwise it 279 // returns a plain certificate. 280 func testServerGetCertificate(ch *ClientHelloInfo) (*Certificate, error) { 281 versOk := false 282 for _, vers := range ch.SupportedVersions { 283 versOk = versOk || (vers >= uint16(VersionTLS12)) 284 } 285 286 if versOk && ch.AcceptsDelegatedCredential { 287 return &dcTestDelegationCert, nil 288 } 289 return &dcTestCert, nil 290 } 291 292 // Various test cases for handshakes involving DCs. 293 var dcTesters = []struct { 294 clientDC bool 295 serverDC bool 296 clientSkipVerify bool 297 clientMaxVers uint16 298 serverMaxVers uint16 299 nowOffset time.Duration 300 dcTestName string 301 expectSuccess bool 302 expectDC bool 303 name string 304 }{ 305 {true, true, false, VersionTLS13, VersionTLS13, 0, "tls13p256", true, true, "tls13"}, 306 {true, true, false, VersionTLS13, VersionTLS13, 0, "tls13p521", true, true, "tls13"}, 307 {true, false, false, VersionTLS13, VersionTLS13, 0, "tls13p256", true, false, "server no dc"}, 308 {true, true, false, VersionTLS12, VersionTLS13, 0, "tls13p256", true, false, "client old"}, 309 {true, true, false, VersionTLS13, VersionTLS12, 0, "tls13p256", true, false, "server old"}, 310 {true, true, false, VersionTLS13, VersionTLS13, 0, "badkey", false, false, "bad key"}, 311 {true, true, true, VersionTLS13, VersionTLS13, 0, "badsig", true, true, "bad key, skip verify"}, 312 {true, true, false, VersionTLS13, VersionTLS13, dcMaxTTL, "tls13", false, false, "expired dc"}, 313 {true, true, false, VersionTLS13, VersionTLS13, 0, "badvers", false, false, "dc wrong version"}, 314 {true, true, false, VersionTLS12, VersionTLS12, 0, "tls12", true, false, "tls12"}, 315 } 316 317 // Tests the handshake with the delegated credential extension for each test 318 // case in dcTests. 319 func TestDCHandshake(t *testing.T) { 320 clientConfig := dcTestConfig.Clone() 321 serverConfig := dcTestConfig.Clone() 322 serverConfig.GetCertificate = testServerGetCertificate 323 324 for i, tester := range dcTesters { 325 clientConfig.MaxVersion = tester.clientMaxVers 326 serverConfig.MaxVersion = tester.serverMaxVers 327 clientConfig.InsecureSkipVerify = tester.clientSkipVerify 328 clientConfig.AcceptDelegatedCredential = tester.clientDC 329 clientConfig.Time = func() time.Time { 330 return dcTestNow.Add(time.Duration(tester.nowOffset)) 331 } 332 333 if tester.serverDC { 334 serverConfig.GetDelegatedCredential = func( 335 ch *ClientHelloInfo, vers uint16) ([]byte, crypto.PrivateKey, error) { 336 if vers < VersionTLS13 { 337 return nil, nil, nil 338 } 339 for _, test := range dcTestDCs { 340 if test.Name == tester.dcTestName { 341 sk, err := x509.ParseECPrivateKey(test.PrivateKey) 342 if err != nil { 343 return nil, nil, err 344 } 345 return test.DC, sk, nil 346 } 347 } 348 return nil, nil, fmt.Errorf("Test DC with name '%s' not found", tester.dcTestName) 349 } 350 } else { 351 serverConfig.GetDelegatedCredential = nil 352 } 353 354 usedDC, err := testConnWithDC(t, clientConfig, serverConfig) 355 if err != nil && tester.expectSuccess { 356 t.Errorf("test #%d (%s) fails: %s", i+1, tester.name, err) 357 } else if err == nil && !tester.expectSuccess { 358 t.Errorf("test #%d (%s) succeeds; expected failure", i+1, tester.name) 359 } 360 361 if usedDC != tester.expectDC { 362 t.Errorf("test #%d (%s) usedDC = %v; expected %v", i+1, tester.name, usedDC, tester.expectDC) 363 } 364 } 365 }