sessionTicket_test.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /*
  2. * Copyright (c) 2016, Psiphon Inc.
  3. * All rights reserved.
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. package psiphon
  20. import (
  21. "crypto/rand"
  22. "crypto/rsa"
  23. "crypto/sha1"
  24. "crypto/x509"
  25. "crypto/x509/pkix"
  26. "encoding/pem"
  27. "errors"
  28. "io"
  29. "math/big"
  30. "net"
  31. "testing"
  32. "time"
  33. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
  34. tris "github.com/Psiphon-Labs/tls-tris"
  35. utls "github.com/refraction-networking/utls"
  36. )
  37. func TestObfuscatedSessionTicket(t *testing.T) {
  38. tlsProfiles := []string{
  39. protocol.TLS_PROFILE_CHROME_58,
  40. protocol.TLS_PROFILE_FIREFOX_55,
  41. protocol.TLS_PROFILE_RANDOMIZED,
  42. }
  43. for _, tlsProfile := range tlsProfiles {
  44. t.Run(tlsProfile, func(t *testing.T) {
  45. runObfuscatedSessionTicket(t, tlsProfile)
  46. })
  47. }
  48. }
  49. func runObfuscatedSessionTicket(t *testing.T, tlsProfile string) {
  50. var standardSessionTicketKey [32]byte
  51. rand.Read(standardSessionTicketKey[:])
  52. var obfuscatedSessionTicketSharedSecret [32]byte
  53. rand.Read(obfuscatedSessionTicketSharedSecret[:])
  54. clientConfig := &utls.Config{
  55. InsecureSkipVerify: true,
  56. }
  57. certificate, err := generateCertificate()
  58. if err != nil {
  59. t.Fatalf("generateCertificate failed: %s", err)
  60. }
  61. serverConfig := &tris.Config{
  62. Certificates: []tris.Certificate{*certificate},
  63. NextProtos: []string{"http/1.1"},
  64. MinVersion: utls.VersionTLS12,
  65. SessionTicketKey: obfuscatedSessionTicketSharedSecret,
  66. }
  67. serverConfig.SetSessionTicketKeys([][32]byte{
  68. standardSessionTicketKey, obfuscatedSessionTicketSharedSecret})
  69. testMessage := "test"
  70. result := make(chan error, 1)
  71. report := func(err error) {
  72. select {
  73. case result <- err:
  74. default:
  75. }
  76. }
  77. listening := make(chan string, 1)
  78. go func() {
  79. listener, err := tris.Listen("tcp", ":0", serverConfig)
  80. if err != nil {
  81. report(err)
  82. return
  83. }
  84. defer listener.Close()
  85. listening <- listener.Addr().String()
  86. for i := 0; i < 2; i++ {
  87. conn, err := listener.Accept()
  88. if err != nil {
  89. report(err)
  90. return
  91. }
  92. recv := make([]byte, len(testMessage))
  93. _, err = io.ReadFull(conn, recv)
  94. if err == nil && string(recv) != testMessage {
  95. err = errors.New("unexpected payload")
  96. }
  97. conn.Close()
  98. if err != nil {
  99. report(err)
  100. return
  101. }
  102. }
  103. // Sends nil on success
  104. report(nil)
  105. }()
  106. go func() {
  107. serverAddress := <-listening
  108. clientSessionCache := utls.NewLRUClientSessionCache(0)
  109. for i := 0; i < 2; i++ {
  110. tcpConn, err := net.Dial("tcp", serverAddress)
  111. if err != nil {
  112. report(err)
  113. return
  114. }
  115. defer tcpConn.Close()
  116. utlsClientHelloID := getUTLSClientHelloID(tlsProfile)
  117. tlsConn := utls.UClient(tcpConn, clientConfig, utlsClientHelloID)
  118. tlsConn.SetSessionCache(clientSessionCache)
  119. // The first connection will use an obfuscated session ticket and the
  120. // second connection will use a real session ticket issued by the server.
  121. var clientSessionState *utls.ClientSessionState
  122. if i == 0 {
  123. obfuscatedSessionState, err := tris.NewObfuscatedClientSessionState(
  124. obfuscatedSessionTicketSharedSecret)
  125. if err != nil {
  126. report(err)
  127. return
  128. }
  129. clientSessionState = utls.MakeClientSessionState(
  130. obfuscatedSessionState.SessionTicket,
  131. obfuscatedSessionState.Vers,
  132. obfuscatedSessionState.CipherSuite,
  133. obfuscatedSessionState.MasterSecret,
  134. nil,
  135. nil)
  136. tlsConn.SetSessionState(clientSessionState)
  137. }
  138. if protocol.TLSProfileIsRandomized(tlsProfile) {
  139. for {
  140. err = tlsConn.BuildHandshakeState()
  141. if err != nil {
  142. report(err)
  143. return
  144. }
  145. isTLS13 := false
  146. for _, v := range tlsConn.HandshakeState.Hello.SupportedVersions {
  147. if v == utls.VersionTLS13 {
  148. isTLS13 = true
  149. break
  150. }
  151. }
  152. if !isTLS13 && tris.ContainsObfuscatedSessionTicketCipherSuite(
  153. tlsConn.HandshakeState.Hello.CipherSuites) {
  154. break
  155. }
  156. utlsClientHelloID.Seed, _ = utls.NewPRNGSeed()
  157. tlsConn = utls.UClient(tcpConn, clientConfig, utlsClientHelloID)
  158. tlsConn.SetSessionCache(clientSessionCache)
  159. if i == 0 {
  160. tlsConn.SetSessionState(clientSessionState)
  161. }
  162. }
  163. }
  164. err = tlsConn.Handshake()
  165. if err != nil {
  166. report(err)
  167. return
  168. }
  169. if len(tlsConn.ConnectionState().PeerCertificates) > 0 {
  170. report(errors.New("unexpected certificate in handshake"))
  171. return
  172. }
  173. _, err = tlsConn.Write([]byte(testMessage))
  174. if err != nil {
  175. report(err)
  176. return
  177. }
  178. }
  179. }()
  180. err = <-result
  181. if err != nil {
  182. t.Fatalf("connect failed: %s", err)
  183. }
  184. }
  185. func generateCertificate() (*tris.Certificate, error) {
  186. rsaKey, err := rsa.GenerateKey(rand.Reader, 2048)
  187. if err != nil {
  188. return nil, err
  189. }
  190. publicKeyBytes, err := x509.MarshalPKIXPublicKey(rsaKey.Public())
  191. if err != nil {
  192. return nil, err
  193. }
  194. subjectKeyID := sha1.Sum(publicKeyBytes)
  195. template := x509.Certificate{
  196. SerialNumber: big.NewInt(1),
  197. Subject: pkix.Name{CommonName: "www.example.org"},
  198. NotBefore: time.Now().Add(-1 * time.Hour).UTC(),
  199. NotAfter: time.Now().Add(time.Hour).UTC(),
  200. KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
  201. ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
  202. BasicConstraintsValid: true,
  203. IsCA: true,
  204. SubjectKeyId: subjectKeyID[:],
  205. MaxPathLen: 1,
  206. Version: 2,
  207. }
  208. derCert, err := x509.CreateCertificate(
  209. rand.Reader,
  210. &template,
  211. &template,
  212. rsaKey.Public(),
  213. rsaKey)
  214. if err != nil {
  215. return nil, err
  216. }
  217. certificate := pem.EncodeToMemory(
  218. &pem.Block{
  219. Type: "CERTIFICATE",
  220. Bytes: derCert,
  221. },
  222. )
  223. privateKey := pem.EncodeToMemory(
  224. &pem.Block{
  225. Type: "RSA PRIVATE KEY",
  226. Bytes: x509.MarshalPKCS1PrivateKey(rsaKey),
  227. },
  228. )
  229. keyPair, err := tris.X509KeyPair(certificate, privateKey)
  230. if err != nil {
  231. return nil, err
  232. }
  233. return &keyPair, nil
  234. }