Alternative TLS implementation in Go
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

369 lignes
11 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. import (
  6. "crypto"
  7. "crypto/hmac"
  8. "crypto/md5"
  9. "crypto/sha1"
  10. "crypto/sha256"
  11. "crypto/sha512"
  12. "errors"
  13. "hash"
  14. )
  15. // Split a premaster secret in two as specified in RFC 4346, section 5.
  16. func splitPreMasterSecret(secret []byte) (s1, s2 []byte) {
  17. s1 = secret[0 : (len(secret)+1)/2]
  18. s2 = secret[len(secret)/2:]
  19. return
  20. }
  21. // pHash implements the P_hash function, as defined in RFC 4346, section 5.
  22. func pHash(result, secret, seed []byte, hash func() hash.Hash) {
  23. h := hmac.New(hash, secret)
  24. h.Write(seed)
  25. a := h.Sum(nil)
  26. j := 0
  27. for j < len(result) {
  28. h.Reset()
  29. h.Write(a)
  30. h.Write(seed)
  31. b := h.Sum(nil)
  32. todo := len(b)
  33. if j+todo > len(result) {
  34. todo = len(result) - j
  35. }
  36. copy(result[j:j+todo], b)
  37. j += todo
  38. h.Reset()
  39. h.Write(a)
  40. a = h.Sum(nil)
  41. }
  42. }
  43. // prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, section 5.
  44. func prf10(result, secret, label, seed []byte) {
  45. hashSHA1 := sha1.New
  46. hashMD5 := md5.New
  47. labelAndSeed := make([]byte, len(label)+len(seed))
  48. copy(labelAndSeed, label)
  49. copy(labelAndSeed[len(label):], seed)
  50. s1, s2 := splitPreMasterSecret(secret)
  51. pHash(result, s1, labelAndSeed, hashMD5)
  52. result2 := make([]byte, len(result))
  53. pHash(result2, s2, labelAndSeed, hashSHA1)
  54. for i, b := range result2 {
  55. result[i] ^= b
  56. }
  57. }
  58. // prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, section 5.
  59. func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) {
  60. return func(result, secret, label, seed []byte) {
  61. labelAndSeed := make([]byte, len(label)+len(seed))
  62. copy(labelAndSeed, label)
  63. copy(labelAndSeed[len(label):], seed)
  64. pHash(result, secret, labelAndSeed, hashFunc)
  65. }
  66. }
  67. // prf30 implements the SSL 3.0 pseudo-random function, as defined in
  68. // www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6.
  69. func prf30(result, secret, label, seed []byte) {
  70. hashSHA1 := sha1.New()
  71. hashMD5 := md5.New()
  72. done := 0
  73. i := 0
  74. // RFC 5246 section 6.3 says that the largest PRF output needed is 128
  75. // bytes. Since no more ciphersuites will be added to SSLv3, this will
  76. // remain true. Each iteration gives us 16 bytes so 10 iterations will
  77. // be sufficient.
  78. var b [11]byte
  79. for done < len(result) {
  80. for j := 0; j <= i; j++ {
  81. b[j] = 'A' + byte(i)
  82. }
  83. hashSHA1.Reset()
  84. hashSHA1.Write(b[:i+1])
  85. hashSHA1.Write(secret)
  86. hashSHA1.Write(seed)
  87. digest := hashSHA1.Sum(nil)
  88. hashMD5.Reset()
  89. hashMD5.Write(secret)
  90. hashMD5.Write(digest)
  91. done += copy(result[done:], hashMD5.Sum(nil))
  92. i++
  93. }
  94. }
  95. const (
  96. tlsRandomLength = 32 // Length of a random nonce in TLS 1.1.
  97. masterSecretLength = 48 // Length of a master secret in TLS 1.1.
  98. finishedVerifyLength = 12 // Length of verify_data in a Finished message.
  99. )
  100. var masterSecretLabel = []byte("master secret")
  101. var keyExpansionLabel = []byte("key expansion")
  102. var clientFinishedLabel = []byte("client finished")
  103. var serverFinishedLabel = []byte("server finished")
  104. func prfAndHashForVersion(version uint16, suite *cipherSuite) (func(result, secret, label, seed []byte), crypto.Hash) {
  105. switch version {
  106. case VersionSSL30:
  107. return prf30, crypto.Hash(0)
  108. case VersionTLS10, VersionTLS11:
  109. return prf10, crypto.Hash(0)
  110. case VersionTLS12:
  111. if suite.flags&suiteSHA384 != 0 {
  112. return prf12(sha512.New384), crypto.SHA384
  113. }
  114. return prf12(sha256.New), crypto.SHA256
  115. default:
  116. panic("unknown version")
  117. }
  118. }
  119. func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) {
  120. prf, _ := prfAndHashForVersion(version, suite)
  121. return prf
  122. }
  123. // masterFromPreMasterSecret generates the master secret from the pre-master
  124. // secret. See http://tools.ietf.org/html/rfc5246#section-8.1
  125. func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte {
  126. seed := make([]byte, 0, len(clientRandom)+len(serverRandom))
  127. seed = append(seed, clientRandom...)
  128. seed = append(seed, serverRandom...)
  129. masterSecret := make([]byte, masterSecretLength)
  130. prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed)
  131. return masterSecret
  132. }
  133. // keysFromMasterSecret generates the connection keys from the master
  134. // secret, given the lengths of the MAC key, cipher key and IV, as defined in
  135. // RFC 2246, section 6.3.
  136. func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
  137. seed := make([]byte, 0, len(serverRandom)+len(clientRandom))
  138. seed = append(seed, serverRandom...)
  139. seed = append(seed, clientRandom...)
  140. n := 2*macLen + 2*keyLen + 2*ivLen
  141. keyMaterial := make([]byte, n)
  142. prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed)
  143. clientMAC = keyMaterial[:macLen]
  144. keyMaterial = keyMaterial[macLen:]
  145. serverMAC = keyMaterial[:macLen]
  146. keyMaterial = keyMaterial[macLen:]
  147. clientKey = keyMaterial[:keyLen]
  148. keyMaterial = keyMaterial[keyLen:]
  149. serverKey = keyMaterial[:keyLen]
  150. keyMaterial = keyMaterial[keyLen:]
  151. clientIV = keyMaterial[:ivLen]
  152. keyMaterial = keyMaterial[ivLen:]
  153. serverIV = keyMaterial[:ivLen]
  154. return
  155. }
  156. // lookupTLSHash looks up the corresponding crypto.Hash for a given
  157. // TLS hash identifier.
  158. func lookupTLSHash(hash uint8) (crypto.Hash, error) {
  159. switch hash {
  160. case hashSHA1:
  161. return crypto.SHA1, nil
  162. case hashSHA256:
  163. return crypto.SHA256, nil
  164. case hashSHA384:
  165. return crypto.SHA384, nil
  166. default:
  167. return 0, errors.New("tls: unsupported hash algorithm")
  168. }
  169. }
  170. func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash {
  171. var buffer []byte
  172. if version == VersionSSL30 || version >= VersionTLS12 {
  173. buffer = []byte{}
  174. }
  175. prf, hash := prfAndHashForVersion(version, cipherSuite)
  176. if hash != 0 {
  177. return finishedHash{hash.New(), hash.New(), nil, nil, buffer, version, prf}
  178. }
  179. return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), buffer, version, prf}
  180. }
  181. // A finishedHash calculates the hash of a set of handshake messages suitable
  182. // for including in a Finished message.
  183. type finishedHash struct {
  184. client hash.Hash
  185. server hash.Hash
  186. // Prior to TLS 1.2, an additional MD5 hash is required.
  187. clientMD5 hash.Hash
  188. serverMD5 hash.Hash
  189. // In TLS 1.2, a full buffer is sadly required.
  190. buffer []byte
  191. version uint16
  192. prf func(result, secret, label, seed []byte)
  193. }
  194. func (h *finishedHash) Write(msg []byte) (n int, err error) {
  195. h.client.Write(msg)
  196. h.server.Write(msg)
  197. if h.version < VersionTLS12 {
  198. h.clientMD5.Write(msg)
  199. h.serverMD5.Write(msg)
  200. }
  201. if h.buffer != nil {
  202. h.buffer = append(h.buffer, msg...)
  203. }
  204. return len(msg), nil
  205. }
  206. func (h finishedHash) Sum() []byte {
  207. if h.version >= VersionTLS12 {
  208. return h.client.Sum(nil)
  209. }
  210. out := make([]byte, 0, md5.Size+sha1.Size)
  211. out = h.clientMD5.Sum(out)
  212. return h.client.Sum(out)
  213. }
  214. // finishedSum30 calculates the contents of the verify_data member of a SSLv3
  215. // Finished message given the MD5 and SHA1 hashes of a set of handshake
  216. // messages.
  217. func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic []byte) []byte {
  218. md5.Write(magic)
  219. md5.Write(masterSecret)
  220. md5.Write(ssl30Pad1[:])
  221. md5Digest := md5.Sum(nil)
  222. md5.Reset()
  223. md5.Write(masterSecret)
  224. md5.Write(ssl30Pad2[:])
  225. md5.Write(md5Digest)
  226. md5Digest = md5.Sum(nil)
  227. sha1.Write(magic)
  228. sha1.Write(masterSecret)
  229. sha1.Write(ssl30Pad1[:40])
  230. sha1Digest := sha1.Sum(nil)
  231. sha1.Reset()
  232. sha1.Write(masterSecret)
  233. sha1.Write(ssl30Pad2[:40])
  234. sha1.Write(sha1Digest)
  235. sha1Digest = sha1.Sum(nil)
  236. ret := make([]byte, len(md5Digest)+len(sha1Digest))
  237. copy(ret, md5Digest)
  238. copy(ret[len(md5Digest):], sha1Digest)
  239. return ret
  240. }
  241. var ssl3ClientFinishedMagic = [4]byte{0x43, 0x4c, 0x4e, 0x54}
  242. var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52}
  243. // clientSum returns the contents of the verify_data member of a client's
  244. // Finished message.
  245. func (h finishedHash) clientSum(masterSecret []byte) []byte {
  246. if h.version == VersionSSL30 {
  247. return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic[:])
  248. }
  249. out := make([]byte, finishedVerifyLength)
  250. h.prf(out, masterSecret, clientFinishedLabel, h.Sum())
  251. return out
  252. }
  253. // serverSum returns the contents of the verify_data member of a server's
  254. // Finished message.
  255. func (h finishedHash) serverSum(masterSecret []byte) []byte {
  256. if h.version == VersionSSL30 {
  257. return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic[:])
  258. }
  259. out := make([]byte, finishedVerifyLength)
  260. h.prf(out, masterSecret, serverFinishedLabel, h.Sum())
  261. return out
  262. }
  263. // selectClientCertSignatureAlgorithm returns a signatureAndHash to sign a
  264. // client's CertificateVerify with, or an error if none can be found.
  265. func (h finishedHash) selectClientCertSignatureAlgorithm(serverList []signatureAndHash, sigType uint8) (signatureAndHash, error) {
  266. if h.version < VersionTLS12 {
  267. // Nothing to negotiate before TLS 1.2.
  268. return signatureAndHash{signature: sigType}, nil
  269. }
  270. for _, v := range serverList {
  271. if v.signature == sigType && isSupportedSignatureAndHash(v, supportedSignatureAlgorithms) {
  272. return v, nil
  273. }
  274. }
  275. return signatureAndHash{}, errors.New("tls: no supported signature algorithm found for signing client certificate")
  276. }
  277. // hashForClientCertificate returns a digest, hash function, and TLS 1.2 hash
  278. // id suitable for signing by a TLS client certificate.
  279. func (h finishedHash) hashForClientCertificate(signatureAndHash signatureAndHash, masterSecret []byte) ([]byte, crypto.Hash, error) {
  280. if (h.version == VersionSSL30 || h.version >= VersionTLS12) && h.buffer == nil {
  281. panic("a handshake hash for a client-certificate was requested after discarding the handshake buffer")
  282. }
  283. if h.version == VersionSSL30 {
  284. if signatureAndHash.signature != signatureRSA {
  285. return nil, 0, errors.New("tls: unsupported signature type for client certificate")
  286. }
  287. md5Hash := md5.New()
  288. md5Hash.Write(h.buffer)
  289. sha1Hash := sha1.New()
  290. sha1Hash.Write(h.buffer)
  291. return finishedSum30(md5Hash, sha1Hash, masterSecret, nil), crypto.MD5SHA1, nil
  292. }
  293. if h.version >= VersionTLS12 {
  294. hashAlg, err := lookupTLSHash(signatureAndHash.hash)
  295. if err != nil {
  296. return nil, 0, err
  297. }
  298. hash := hashAlg.New()
  299. hash.Write(h.buffer)
  300. return hash.Sum(nil), hashAlg, nil
  301. }
  302. if signatureAndHash.signature == signatureECDSA {
  303. return h.server.Sum(nil), crypto.SHA1, nil
  304. }
  305. return h.Sum(), crypto.MD5SHA1, nil
  306. }
  307. // discardHandshakeBuffer is called when there is no more need to
  308. // buffer the entirety of the handshake messages.
  309. func (h *finishedHash) discardHandshakeBuffer() {
  310. h.buffer = nil
  311. }