clientHello.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. package crypt
  2. import (
  3. "strings"
  4. )
  5. type CurveID uint16
  6. type SignatureScheme uint16
  7. const (
  8. statusTypeOCSP uint8 = 1
  9. extensionServerName uint16 = 0
  10. extensionStatusRequest uint16 = 5
  11. extensionSupportedCurves uint16 = 10
  12. extensionSupportedPoints uint16 = 11
  13. extensionSignatureAlgorithms uint16 = 13
  14. extensionALPN uint16 = 16
  15. extensionSCT uint16 = 18 // https://tools.ietf.org/html/rfc6962#section-6
  16. extensionSessionTicket uint16 = 35
  17. extensionNextProtoNeg uint16 = 13172 // not IANA assigned
  18. extensionRenegotiationInfo uint16 = 0xff01
  19. scsvRenegotiation uint16 = 0x00ff
  20. )
  21. type ClientHelloMsg struct {
  22. raw []byte
  23. vers uint16
  24. random []byte
  25. sessionId []byte
  26. cipherSuites []uint16
  27. compressionMethods []uint8
  28. nextProtoNeg bool
  29. serverName string
  30. ocspStapling bool
  31. scts bool
  32. supportedCurves []CurveID
  33. supportedPoints []uint8
  34. ticketSupported bool
  35. sessionTicket []uint8
  36. supportedSignatureAlgorithms []SignatureScheme
  37. secureRenegotiation []byte
  38. secureRenegotiationSupported bool
  39. alpnProtocols []string
  40. }
  41. func (m *ClientHelloMsg) GetServerName() string {
  42. return m.serverName
  43. }
  44. func (m *ClientHelloMsg) Unmarshal(data []byte) bool {
  45. if len(data) < 42 {
  46. return false
  47. }
  48. m.raw = data
  49. m.vers = uint16(data[4])<<8 | uint16(data[5])
  50. m.random = data[6:38]
  51. sessionIdLen := int(data[38])
  52. if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
  53. return false
  54. }
  55. m.sessionId = data[39 : 39+sessionIdLen]
  56. data = data[39+sessionIdLen:]
  57. if len(data) < 2 {
  58. return false
  59. }
  60. // cipherSuiteLen is the number of bytes of cipher suite numbers. Since
  61. // they are uint16s, the number must be even.
  62. cipherSuiteLen := int(data[0])<<8 | int(data[1])
  63. if cipherSuiteLen%2 == 1 || len(data) < 2+cipherSuiteLen {
  64. return false
  65. }
  66. numCipherSuites := cipherSuiteLen / 2
  67. m.cipherSuites = make([]uint16, numCipherSuites)
  68. for i := 0; i < numCipherSuites; i++ {
  69. m.cipherSuites[i] = uint16(data[2+2*i])<<8 | uint16(data[3+2*i])
  70. if m.cipherSuites[i] == scsvRenegotiation {
  71. m.secureRenegotiationSupported = true
  72. }
  73. }
  74. data = data[2+cipherSuiteLen:]
  75. if len(data) < 1 {
  76. return false
  77. }
  78. compressionMethodsLen := int(data[0])
  79. if len(data) < 1+compressionMethodsLen {
  80. return false
  81. }
  82. m.compressionMethods = data[1 : 1+compressionMethodsLen]
  83. data = data[1+compressionMethodsLen:]
  84. m.nextProtoNeg = false
  85. m.serverName = ""
  86. m.ocspStapling = false
  87. m.ticketSupported = false
  88. m.sessionTicket = nil
  89. m.supportedSignatureAlgorithms = nil
  90. m.alpnProtocols = nil
  91. m.scts = false
  92. if len(data) == 0 {
  93. // ClientHello is optionally followed by extension data
  94. return true
  95. }
  96. if len(data) < 2 {
  97. return false
  98. }
  99. extensionsLength := int(data[0])<<8 | int(data[1])
  100. data = data[2:]
  101. if extensionsLength != len(data) {
  102. return false
  103. }
  104. for len(data) != 0 {
  105. if len(data) < 4 {
  106. return false
  107. }
  108. extension := uint16(data[0])<<8 | uint16(data[1])
  109. length := int(data[2])<<8 | int(data[3])
  110. data = data[4:]
  111. if len(data) < length {
  112. return false
  113. }
  114. switch extension {
  115. case extensionServerName:
  116. d := data[:length]
  117. if len(d) < 2 {
  118. return false
  119. }
  120. namesLen := int(d[0])<<8 | int(d[1])
  121. d = d[2:]
  122. if len(d) != namesLen {
  123. return false
  124. }
  125. for len(d) > 0 {
  126. if len(d) < 3 {
  127. return false
  128. }
  129. nameType := d[0]
  130. nameLen := int(d[1])<<8 | int(d[2])
  131. d = d[3:]
  132. if len(d) < nameLen {
  133. return false
  134. }
  135. if nameType == 0 {
  136. m.serverName = string(d[:nameLen])
  137. // An SNI value may not include a
  138. // trailing dot. See
  139. // https://tools.ietf.org/html/rfc6066#section-3.
  140. if strings.HasSuffix(m.serverName, ".") {
  141. return false
  142. }
  143. break
  144. }
  145. d = d[nameLen:]
  146. }
  147. case extensionNextProtoNeg:
  148. if length > 0 {
  149. return false
  150. }
  151. m.nextProtoNeg = true
  152. case extensionStatusRequest:
  153. m.ocspStapling = length > 0 && data[0] == statusTypeOCSP
  154. case extensionSupportedCurves:
  155. // https://tools.ietf.org/html/rfc4492#section-5.5.1
  156. if length < 2 {
  157. return false
  158. }
  159. l := int(data[0])<<8 | int(data[1])
  160. if l%2 == 1 || length != l+2 {
  161. return false
  162. }
  163. numCurves := l / 2
  164. m.supportedCurves = make([]CurveID, numCurves)
  165. d := data[2:]
  166. for i := 0; i < numCurves; i++ {
  167. m.supportedCurves[i] = CurveID(d[0])<<8 | CurveID(d[1])
  168. d = d[2:]
  169. }
  170. case extensionSupportedPoints:
  171. // https://tools.ietf.org/html/rfc4492#section-5.5.2
  172. if length < 1 {
  173. return false
  174. }
  175. l := int(data[0])
  176. if length != l+1 {
  177. return false
  178. }
  179. m.supportedPoints = make([]uint8, l)
  180. copy(m.supportedPoints, data[1:])
  181. case extensionSessionTicket:
  182. // https://tools.ietf.org/html/rfc5077#section-3.2
  183. m.ticketSupported = true
  184. m.sessionTicket = data[:length]
  185. case extensionSignatureAlgorithms:
  186. // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
  187. if length < 2 || length&1 != 0 {
  188. return false
  189. }
  190. l := int(data[0])<<8 | int(data[1])
  191. if l != length-2 {
  192. return false
  193. }
  194. n := l / 2
  195. d := data[2:]
  196. m.supportedSignatureAlgorithms = make([]SignatureScheme, n)
  197. for i := range m.supportedSignatureAlgorithms {
  198. m.supportedSignatureAlgorithms[i] = SignatureScheme(d[0])<<8 | SignatureScheme(d[1])
  199. d = d[2:]
  200. }
  201. case extensionRenegotiationInfo:
  202. if length == 0 {
  203. return false
  204. }
  205. d := data[:length]
  206. l := int(d[0])
  207. d = d[1:]
  208. if l != len(d) {
  209. return false
  210. }
  211. m.secureRenegotiation = d
  212. m.secureRenegotiationSupported = true
  213. case extensionALPN:
  214. if length < 2 {
  215. return false
  216. }
  217. l := int(data[0])<<8 | int(data[1])
  218. if l != length-2 {
  219. return false
  220. }
  221. d := data[2:length]
  222. for len(d) != 0 {
  223. stringLen := int(d[0])
  224. d = d[1:]
  225. if stringLen == 0 || stringLen > len(d) {
  226. return false
  227. }
  228. m.alpnProtocols = append(m.alpnProtocols, string(d[:stringLen]))
  229. d = d[stringLen:]
  230. }
  231. case extensionSCT:
  232. m.scts = true
  233. if length != 0 {
  234. return false
  235. }
  236. }
  237. data = data[length:]
  238. }
  239. return true
  240. }