Alternative TLS implementation in Go
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

199 linhas
5.5 KiB

  1. // Copyright 2009 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. // The handshake goroutine reads handshake messages from the record processor
  6. // and outputs messages to be written on another channel. It updates the record
  7. // processor with the state of the connection via the control channel. In the
  8. // case of handshake messages that need synchronous processing (because they
  9. // affect the handling of the next record) the record processor knows about
  10. // them and either waits for a control message (Finished) or includes a reply
  11. // channel in the message (ChangeCipherSpec).
  12. import (
  13. "crypto/hmac"
  14. "crypto/rc4"
  15. "crypto/rsa"
  16. "crypto/sha1"
  17. "crypto/subtle"
  18. "io"
  19. "os"
  20. )
  21. type cipherSuite struct {
  22. id uint16 // The number of this suite on the wire.
  23. hashLength, cipherKeyLength int
  24. // TODO(agl): need a method to create the cipher and hash interfaces.
  25. }
  26. var cipherSuites = []cipherSuite{
  27. cipherSuite{TLS_RSA_WITH_RC4_128_SHA, 20, 16},
  28. }
  29. func (c *Conn) serverHandshake() os.Error {
  30. config := c.config
  31. msg, err := c.readHandshake()
  32. if err != nil {
  33. return err
  34. }
  35. clientHello, ok := msg.(*clientHelloMsg)
  36. if !ok {
  37. return c.sendAlert(alertUnexpectedMessage)
  38. }
  39. vers, ok := mutualVersion(clientHello.vers)
  40. if !ok {
  41. return c.sendAlert(alertProtocolVersion)
  42. }
  43. c.vers = vers
  44. c.haveVers = true
  45. finishedHash := newFinishedHash()
  46. finishedHash.Write(clientHello.marshal())
  47. hello := new(serverHelloMsg)
  48. // We only support a single ciphersuite so we look for it in the list
  49. // of client supported suites.
  50. //
  51. // TODO(agl): Add additional cipher suites.
  52. var suite *cipherSuite
  53. for _, id := range clientHello.cipherSuites {
  54. for _, supported := range cipherSuites {
  55. if supported.id == id {
  56. suite = &supported
  57. break
  58. }
  59. }
  60. }
  61. foundCompression := false
  62. // We only support null compression, so check that the client offered it.
  63. for _, compression := range clientHello.compressionMethods {
  64. if compression == compressionNone {
  65. foundCompression = true
  66. break
  67. }
  68. }
  69. if suite == nil || !foundCompression {
  70. return c.sendAlert(alertHandshakeFailure)
  71. }
  72. hello.vers = vers
  73. hello.cipherSuite = suite.id
  74. t := uint32(config.Time())
  75. hello.random = make([]byte, 32)
  76. hello.random[0] = byte(t >> 24)
  77. hello.random[1] = byte(t >> 16)
  78. hello.random[2] = byte(t >> 8)
  79. hello.random[3] = byte(t)
  80. _, err = io.ReadFull(config.Rand, hello.random[4:])
  81. if err != nil {
  82. return c.sendAlert(alertInternalError)
  83. }
  84. hello.compressionMethod = compressionNone
  85. if clientHello.nextProtoNeg {
  86. hello.nextProtoNeg = true
  87. hello.nextProtos = config.NextProtos
  88. }
  89. finishedHash.Write(hello.marshal())
  90. c.writeRecord(recordTypeHandshake, hello.marshal())
  91. if len(config.Certificates) == 0 {
  92. return c.sendAlert(alertInternalError)
  93. }
  94. certMsg := new(certificateMsg)
  95. certMsg.certificates = config.Certificates[0].Certificate
  96. finishedHash.Write(certMsg.marshal())
  97. c.writeRecord(recordTypeHandshake, certMsg.marshal())
  98. helloDone := new(serverHelloDoneMsg)
  99. finishedHash.Write(helloDone.marshal())
  100. c.writeRecord(recordTypeHandshake, helloDone.marshal())
  101. msg, err = c.readHandshake()
  102. if err != nil {
  103. return err
  104. }
  105. ckx, ok := msg.(*clientKeyExchangeMsg)
  106. if !ok {
  107. return c.sendAlert(alertUnexpectedMessage)
  108. }
  109. finishedHash.Write(ckx.marshal())
  110. preMasterSecret := make([]byte, 48)
  111. _, err = io.ReadFull(config.Rand, preMasterSecret[2:])
  112. if err != nil {
  113. return c.sendAlert(alertInternalError)
  114. }
  115. err = rsa.DecryptPKCS1v15SessionKey(config.Rand, config.Certificates[0].PrivateKey, ckx.ciphertext, preMasterSecret)
  116. if err != nil {
  117. return c.sendAlert(alertHandshakeFailure)
  118. }
  119. // We don't check the version number in the premaster secret. For one,
  120. // by checking it, we would leak information about the validity of the
  121. // encrypted pre-master secret. Secondly, it provides only a small
  122. // benefit against a downgrade attack and some implementations send the
  123. // wrong version anyway. See the discussion at the end of section
  124. // 7.4.7.1 of RFC 4346.
  125. masterSecret, clientMAC, serverMAC, clientKey, serverKey :=
  126. keysFromPreMasterSecret11(preMasterSecret, clientHello.random, hello.random, suite.hashLength, suite.cipherKeyLength)
  127. cipher, _ := rc4.NewCipher(clientKey)
  128. c.in.prepareCipherSpec(cipher, hmac.New(sha1.New(), clientMAC))
  129. c.readRecord(recordTypeChangeCipherSpec)
  130. if err := c.error(); err != nil {
  131. return err
  132. }
  133. if hello.nextProtoNeg {
  134. msg, err = c.readHandshake()
  135. if err != nil {
  136. return err
  137. }
  138. nextProto, ok := msg.(*nextProtoMsg)
  139. if !ok {
  140. return c.sendAlert(alertUnexpectedMessage)
  141. }
  142. finishedHash.Write(nextProto.marshal())
  143. c.clientProtocol = nextProto.proto
  144. }
  145. msg, err = c.readHandshake()
  146. if err != nil {
  147. return err
  148. }
  149. clientFinished, ok := msg.(*finishedMsg)
  150. if !ok {
  151. return c.sendAlert(alertUnexpectedMessage)
  152. }
  153. verify := finishedHash.clientSum(masterSecret)
  154. if len(verify) != len(clientFinished.verifyData) ||
  155. subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
  156. return c.sendAlert(alertHandshakeFailure)
  157. }
  158. finishedHash.Write(clientFinished.marshal())
  159. cipher2, _ := rc4.NewCipher(serverKey)
  160. c.out.prepareCipherSpec(cipher2, hmac.New(sha1.New(), serverMAC))
  161. c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
  162. finished := new(finishedMsg)
  163. finished.verifyData = finishedHash.serverSum(masterSecret)
  164. c.writeRecord(recordTypeHandshake, finished.marshal())
  165. c.handshakeComplete = true
  166. c.cipherSuite = TLS_RSA_WITH_RC4_128_SHA
  167. return nil
  168. }