You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

440 lines
12 KiB

  1. // Copyright 2010 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. package tls
  5. import (
  6. "bytes"
  7. "crypto/ecdsa"
  8. "crypto/rsa"
  9. "crypto/x509"
  10. "encoding/pem"
  11. "fmt"
  12. "io"
  13. "net"
  14. "os"
  15. "os/exec"
  16. "path/filepath"
  17. "strconv"
  18. "testing"
  19. "time"
  20. )
  21. // Note: see comment in handshake_test.go for details of how the reference
  22. // tests work.
  23. // blockingSource is an io.Reader that blocks a Read call until it's closed.
  24. type blockingSource chan bool
  25. func (b blockingSource) Read([]byte) (n int, err error) {
  26. <-b
  27. return 0, io.EOF
  28. }
  29. // clientTest represents a test of the TLS client handshake against a reference
  30. // implementation.
  31. type clientTest struct {
  32. // name is a freeform string identifying the test and the file in which
  33. // the expected results will be stored.
  34. name string
  35. // command, if not empty, contains a series of arguments for the
  36. // command to run for the reference server.
  37. command []string
  38. // config, if not nil, contains a custom Config to use for this test.
  39. config *Config
  40. // cert, if not empty, contains a DER-encoded certificate for the
  41. // reference server.
  42. cert []byte
  43. // key, if not nil, contains either a *rsa.PrivateKey or
  44. // *ecdsa.PrivateKey which is the private key for the reference server.
  45. key interface{}
  46. }
  47. var defaultServerCommand = []string{"openssl", "s_server"}
  48. // connFromCommand starts the reference server process, connects to it and
  49. // returns a recordingConn for the connection. The stdin return value is a
  50. // blockingSource for the stdin of the child process. It must be closed before
  51. // Waiting for child.
  52. func (test *clientTest) connFromCommand() (conn *recordingConn, child *exec.Cmd, stdin blockingSource, err error) {
  53. cert := testRSACertificate
  54. if len(test.cert) > 0 {
  55. cert = test.cert
  56. }
  57. certPath := tempFile(string(cert))
  58. defer os.Remove(certPath)
  59. var key interface{} = testRSAPrivateKey
  60. if test.key != nil {
  61. key = test.key
  62. }
  63. var pemType string
  64. var derBytes []byte
  65. switch key := key.(type) {
  66. case *rsa.PrivateKey:
  67. pemType = "RSA"
  68. derBytes = x509.MarshalPKCS1PrivateKey(key)
  69. case *ecdsa.PrivateKey:
  70. pemType = "EC"
  71. var err error
  72. derBytes, err = x509.MarshalECPrivateKey(key)
  73. if err != nil {
  74. panic(err)
  75. }
  76. default:
  77. panic("unknown key type")
  78. }
  79. var pemOut bytes.Buffer
  80. pem.Encode(&pemOut, &pem.Block{Type: pemType + " PRIVATE KEY", Bytes: derBytes})
  81. keyPath := tempFile(string(pemOut.Bytes()))
  82. defer os.Remove(keyPath)
  83. var command []string
  84. if len(test.command) > 0 {
  85. command = append(command, test.command...)
  86. } else {
  87. command = append(command, defaultServerCommand...)
  88. }
  89. command = append(command, "-cert", certPath, "-certform", "DER", "-key", keyPath)
  90. // serverPort contains the port that OpenSSL will listen on. OpenSSL
  91. // can't take "0" as an argument here so we have to pick a number and
  92. // hope that it's not in use on the machine. Since this only occurs
  93. // when -update is given and thus when there's a human watching the
  94. // test, this isn't too bad.
  95. const serverPort = 24323
  96. command = append(command, "-accept", strconv.Itoa(serverPort))
  97. cmd := exec.Command(command[0], command[1:]...)
  98. stdin = blockingSource(make(chan bool))
  99. cmd.Stdin = stdin
  100. var out bytes.Buffer
  101. cmd.Stdout = &out
  102. cmd.Stderr = &out
  103. if err := cmd.Start(); err != nil {
  104. return nil, nil, nil, err
  105. }
  106. // OpenSSL does print an "ACCEPT" banner, but it does so *before*
  107. // opening the listening socket, so we can't use that to wait until it
  108. // has started listening. Thus we are forced to poll until we get a
  109. // connection.
  110. var tcpConn net.Conn
  111. for i := uint(0); i < 5; i++ {
  112. var err error
  113. tcpConn, err = net.DialTCP("tcp", nil, &net.TCPAddr{
  114. IP: net.IPv4(127, 0, 0, 1),
  115. Port: serverPort,
  116. })
  117. if err == nil {
  118. break
  119. }
  120. time.Sleep((1 << i) * 5 * time.Millisecond)
  121. }
  122. if tcpConn == nil {
  123. close(stdin)
  124. out.WriteTo(os.Stdout)
  125. cmd.Process.Kill()
  126. return nil, nil, nil, cmd.Wait()
  127. }
  128. record := &recordingConn{
  129. Conn: tcpConn,
  130. }
  131. return record, cmd, stdin, nil
  132. }
  133. func (test *clientTest) dataPath() string {
  134. return filepath.Join("testdata", "Client-"+test.name)
  135. }
  136. func (test *clientTest) loadData() (flows [][]byte, err error) {
  137. in, err := os.Open(test.dataPath())
  138. if err != nil {
  139. return nil, err
  140. }
  141. defer in.Close()
  142. return parseTestData(in)
  143. }
  144. func (test *clientTest) run(t *testing.T, write bool) {
  145. var clientConn, serverConn net.Conn
  146. var recordingConn *recordingConn
  147. var childProcess *exec.Cmd
  148. var stdin blockingSource
  149. if write {
  150. var err error
  151. recordingConn, childProcess, stdin, err = test.connFromCommand()
  152. if err != nil {
  153. t.Fatalf("Failed to start subcommand: %s", err)
  154. }
  155. clientConn = recordingConn
  156. } else {
  157. clientConn, serverConn = net.Pipe()
  158. }
  159. config := test.config
  160. if config == nil {
  161. config = testConfig
  162. }
  163. client := Client(clientConn, config)
  164. doneChan := make(chan bool)
  165. go func() {
  166. if _, err := client.Write([]byte("hello\n")); err != nil {
  167. t.Logf("Client.Write failed: %s", err)
  168. }
  169. client.Close()
  170. clientConn.Close()
  171. doneChan <- true
  172. }()
  173. if !write {
  174. flows, err := test.loadData()
  175. if err != nil {
  176. t.Fatalf("%s: failed to load data from %s", test.name, test.dataPath())
  177. }
  178. for i, b := range flows {
  179. if i%2 == 1 {
  180. serverConn.Write(b)
  181. continue
  182. }
  183. bb := make([]byte, len(b))
  184. _, err := io.ReadFull(serverConn, bb)
  185. if err != nil {
  186. t.Fatalf("%s #%d: %s", test.name, i, err)
  187. }
  188. if !bytes.Equal(b, bb) {
  189. t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", test.name, i, bb, b)
  190. }
  191. }
  192. serverConn.Close()
  193. }
  194. <-doneChan
  195. if write {
  196. path := test.dataPath()
  197. out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
  198. if err != nil {
  199. t.Fatalf("Failed to create output file: %s", err)
  200. }
  201. defer out.Close()
  202. recordingConn.Close()
  203. close(stdin)
  204. childProcess.Process.Kill()
  205. childProcess.Wait()
  206. if len(recordingConn.flows) < 3 {
  207. childProcess.Stdout.(*bytes.Buffer).WriteTo(os.Stdout)
  208. t.Fatalf("Client connection didn't work")
  209. }
  210. recordingConn.WriteTo(out)
  211. fmt.Printf("Wrote %s\n", path)
  212. }
  213. }
  214. func runClientTestForVersion(t *testing.T, template *clientTest, prefix, option string) {
  215. test := *template
  216. test.name = prefix + test.name
  217. if len(test.command) == 0 {
  218. test.command = defaultClientCommand
  219. }
  220. test.command = append([]string(nil), test.command...)
  221. test.command = append(test.command, option)
  222. test.run(t, *update)
  223. }
  224. func runClientTestTLS10(t *testing.T, template *clientTest) {
  225. runClientTestForVersion(t, template, "TLSv10-", "-tls1")
  226. }
  227. func runClientTestTLS11(t *testing.T, template *clientTest) {
  228. runClientTestForVersion(t, template, "TLSv11-", "-tls1_1")
  229. }
  230. func runClientTestTLS12(t *testing.T, template *clientTest) {
  231. runClientTestForVersion(t, template, "TLSv12-", "-tls1_2")
  232. }
  233. func TestHandshakeClientRSARC4(t *testing.T) {
  234. test := &clientTest{
  235. name: "RSA-RC4",
  236. command: []string{"openssl", "s_server", "-cipher", "RC4-SHA"},
  237. }
  238. runClientTestTLS10(t, test)
  239. runClientTestTLS11(t, test)
  240. runClientTestTLS12(t, test)
  241. }
  242. func TestHandshakeClientECDHERSAAES(t *testing.T) {
  243. test := &clientTest{
  244. name: "ECDHE-RSA-AES",
  245. command: []string{"openssl", "s_server", "-cipher", "ECDHE-RSA-AES128-SHA"},
  246. }
  247. runClientTestTLS10(t, test)
  248. runClientTestTLS11(t, test)
  249. runClientTestTLS12(t, test)
  250. }
  251. func TestHandshakeClientECDHEECDSAAES(t *testing.T) {
  252. test := &clientTest{
  253. name: "ECDHE-ECDSA-AES",
  254. command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA"},
  255. cert: testECDSACertificate,
  256. key: testECDSAPrivateKey,
  257. }
  258. runClientTestTLS10(t, test)
  259. runClientTestTLS11(t, test)
  260. runClientTestTLS12(t, test)
  261. }
  262. func TestHandshakeClientECDHEECDSAAESGCM(t *testing.T) {
  263. test := &clientTest{
  264. name: "ECDHE-ECDSA-AES-GCM",
  265. command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-GCM-SHA256"},
  266. cert: testECDSACertificate,
  267. key: testECDSAPrivateKey,
  268. }
  269. runClientTestTLS12(t, test)
  270. }
  271. func TestHandshakeClientCertRSA(t *testing.T) {
  272. config := *testConfig
  273. cert, _ := X509KeyPair([]byte(clientCertificatePEM), []byte(clientKeyPEM))
  274. config.Certificates = []Certificate{cert}
  275. test := &clientTest{
  276. name: "ClientCert-RSA-RSA",
  277. command: []string{"openssl", "s_server", "-cipher", "RC4-SHA", "-verify", "1"},
  278. config: &config,
  279. }
  280. runClientTestTLS10(t, test)
  281. runClientTestTLS12(t, test)
  282. test = &clientTest{
  283. name: "ClientCert-RSA-ECDSA",
  284. command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA", "-verify", "1"},
  285. config: &config,
  286. cert: testECDSACertificate,
  287. key: testECDSAPrivateKey,
  288. }
  289. runClientTestTLS10(t, test)
  290. runClientTestTLS12(t, test)
  291. }
  292. func TestHandshakeClientCertECDSA(t *testing.T) {
  293. config := *testConfig
  294. cert, _ := X509KeyPair([]byte(clientECDSACertificatePEM), []byte(clientECDSAKeyPEM))
  295. config.Certificates = []Certificate{cert}
  296. test := &clientTest{
  297. name: "ClientCert-ECDSA-RSA",
  298. command: []string{"openssl", "s_server", "-cipher", "RC4-SHA", "-verify", "1"},
  299. config: &config,
  300. }
  301. runClientTestTLS10(t, test)
  302. runClientTestTLS12(t, test)
  303. test = &clientTest{
  304. name: "ClientCert-ECDSA-ECDSA",
  305. command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA", "-verify", "1"},
  306. config: &config,
  307. cert: testECDSACertificate,
  308. key: testECDSAPrivateKey,
  309. }
  310. runClientTestTLS10(t, test)
  311. runClientTestTLS12(t, test)
  312. }
  313. func TestClientResumption(t *testing.T) {
  314. serverConfig := &Config{
  315. CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA},
  316. Certificates: testConfig.Certificates,
  317. }
  318. clientConfig := &Config{
  319. CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
  320. InsecureSkipVerify: true,
  321. ClientSessionCache: NewLRUClientSessionCache(32),
  322. }
  323. testResumeState := func(test string, didResume bool) {
  324. hs, err := testHandshake(clientConfig, serverConfig)
  325. if err != nil {
  326. t.Fatalf("%s: handshake failed: %s", test, err)
  327. }
  328. if hs.DidResume != didResume {
  329. t.Fatalf("%s resumed: %v, expected: %v", test, hs.DidResume, didResume)
  330. }
  331. }
  332. testResumeState("Handshake", false)
  333. testResumeState("Resume", true)
  334. if _, err := io.ReadFull(serverConfig.rand(), serverConfig.SessionTicketKey[:]); err != nil {
  335. t.Fatalf("Failed to invalidate SessionTicketKey")
  336. }
  337. testResumeState("InvalidSessionTicketKey", false)
  338. testResumeState("ResumeAfterInvalidSessionTicketKey", true)
  339. clientConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA}
  340. testResumeState("DifferentCipherSuite", false)
  341. testResumeState("DifferentCipherSuiteRecovers", true)
  342. clientConfig.ClientSessionCache = nil
  343. testResumeState("WithoutSessionCache", false)
  344. }
  345. func TestLRUClientSessionCache(t *testing.T) {
  346. // Initialize cache of capacity 4.
  347. cache := NewLRUClientSessionCache(4)
  348. cs := make([]ClientSessionState, 6)
  349. keys := []string{"0", "1", "2", "3", "4", "5", "6"}
  350. // Add 4 entries to the cache and look them up.
  351. for i := 0; i < 4; i++ {
  352. cache.Put(keys[i], &cs[i])
  353. }
  354. for i := 0; i < 4; i++ {
  355. if s, ok := cache.Get(keys[i]); !ok || s != &cs[i] {
  356. t.Fatalf("session cache failed lookup for added key: %s", keys[i])
  357. }
  358. }
  359. // Add 2 more entries to the cache. First 2 should be evicted.
  360. for i := 4; i < 6; i++ {
  361. cache.Put(keys[i], &cs[i])
  362. }
  363. for i := 0; i < 2; i++ {
  364. if s, ok := cache.Get(keys[i]); ok || s != nil {
  365. t.Fatalf("session cache should have evicted key: %s", keys[i])
  366. }
  367. }
  368. // Touch entry 2. LRU should evict 3 next.
  369. cache.Get(keys[2])
  370. cache.Put(keys[0], &cs[0])
  371. if s, ok := cache.Get(keys[3]); ok || s != nil {
  372. t.Fatalf("session cache should have evicted key 3")
  373. }
  374. // Update entry 0 in place.
  375. cache.Put(keys[0], &cs[3])
  376. if s, ok := cache.Get(keys[0]); !ok || s != &cs[3] {
  377. t.Fatalf("session cache failed update for key 0")
  378. }
  379. // Adding a nil entry is valid.
  380. cache.Put(keys[0], nil)
  381. if s, ok := cache.Get(keys[0]); !ok || s != nil {
  382. t.Fatalf("failed to add nil entry to cache")
  383. }
  384. }