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.

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