cfsslscan_handshake.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package tls
  2. // SayHello constructs a simple Client Hello to a server, parses its serverHelloMsg response
  3. // and returns the negotiated ciphersuite ID, and, if an EC cipher suite, the curve ID
  4. func (c *Conn) SayHello(newSigAls []SignatureAndHash) (cipherID, curveType uint16, curveID CurveID, version uint16, certs [][]byte, err error) {
  5. // Set the supported signatures and hashes to the set `newSigAls`
  6. supportedSignatureAlgorithms := make([]signatureAndHash, len(newSigAls))
  7. for i := range newSigAls {
  8. supportedSignatureAlgorithms[i] = newSigAls[i].internal()
  9. }
  10. hello := &clientHelloMsg{
  11. vers: c.config.maxVersion(),
  12. compressionMethods: []uint8{compressionNone},
  13. random: make([]byte, 32),
  14. ocspStapling: true,
  15. serverName: c.config.ServerName,
  16. supportedCurves: c.config.curvePreferences(),
  17. supportedPoints: []uint8{pointFormatUncompressed},
  18. nextProtoNeg: len(c.config.NextProtos) > 0,
  19. secureRenegotiation: true,
  20. cipherSuites: c.config.cipherSuites(),
  21. signatureAndHashes: supportedSignatureAlgorithms,
  22. }
  23. serverHello, err := c.sayHello(hello)
  24. if err != nil {
  25. return
  26. }
  27. // Prime the connection, if necessary, for key
  28. // exchange messages by reading off the certificate
  29. // message and, if necessary, the OCSP stapling
  30. // message
  31. var msg interface{}
  32. msg, err = c.readHandshake()
  33. if err != nil {
  34. return
  35. }
  36. certMsg, ok := msg.(*certificateMsg)
  37. if !ok || len(certMsg.certificates) == 0 {
  38. err = unexpectedMessageError(certMsg, msg)
  39. return
  40. }
  41. certs = certMsg.certificates
  42. if serverHello.ocspStapling {
  43. msg, err = c.readHandshake()
  44. if err != nil {
  45. return
  46. }
  47. certStatusMsg, ok := msg.(*certificateStatusMsg)
  48. if !ok {
  49. err = unexpectedMessageError(certStatusMsg, msg)
  50. return
  51. }
  52. }
  53. if CipherSuites[serverHello.cipherSuite].EllipticCurve {
  54. var skx *serverKeyExchangeMsg
  55. skx, err = c.exchangeKeys()
  56. if err != nil {
  57. return
  58. }
  59. if skx.raw[0] != typeServerKeyExchange {
  60. err = unexpectedMessageError(skx, msg)
  61. return
  62. }
  63. if len(skx.key) < 4 {
  64. err = unexpectedMessageError(skx, msg)
  65. return
  66. }
  67. curveType = uint16(skx.key[0])
  68. // If we have a named curve, report which one it is.
  69. if curveType == 3 {
  70. curveID = CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
  71. }
  72. }
  73. cipherID, version = serverHello.cipherSuite, serverHello.vers
  74. return
  75. }
  76. // sayHello is the backend to SayHello that returns a full serverHelloMsg for processing.
  77. func (c *Conn) sayHello(hello *clientHelloMsg) (serverHello *serverHelloMsg, err error) {
  78. c.writeRecord(recordTypeHandshake, hello.marshal())
  79. msg, err := c.readHandshake()
  80. if err != nil {
  81. return
  82. }
  83. serverHello, ok := msg.(*serverHelloMsg)
  84. if !ok {
  85. return nil, unexpectedMessageError(serverHello, msg)
  86. }
  87. return
  88. }
  89. // exchangeKeys continues the handshake to receive the serverKeyExchange message,
  90. // from which we can extract elliptic curve parameters
  91. func (c *Conn) exchangeKeys() (serverKeyExchange *serverKeyExchangeMsg, err error) {
  92. msg, err := c.readHandshake()
  93. if err != nil {
  94. return
  95. }
  96. serverKeyExchange, ok := msg.(*serverKeyExchangeMsg)
  97. if !ok {
  98. return nil, unexpectedMessageError(serverKeyExchange, msg)
  99. }
  100. return
  101. }