Alternative TLS implementation in Go
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

5 роки тому
crypto/tls: decouple handshake signatures from the handshake hash. Prior to TLS 1.2, the handshake had a pleasing property that one could incrementally hash it and, from that, get the needed hashes for both the CertificateVerify and Finished messages. TLS 1.2 introduced negotiation for the signature and hash and it became possible for the handshake hash to be, say, SHA-384, but for the CertificateVerify to sign the handshake with SHA-1. The problem is that one doesn't know in advance which hashes will be needed and thus the handshake needs to be buffered. Go ignored this, always kept a single handshake hash, and any signatures over the handshake had to use that hash. However, there are a set of servers that inspect the client's offered signature hash functions and will abort the handshake if one of the server's certificates is signed with a hash function outside of that set. https://robertsspaceindustries.com/ is an example of such a server. Clearly not a lot of thought happened when that server code was written, but its out there and we have to deal with it. This change decouples the handshake hash from the CertificateVerify hash. This lays the groundwork for advertising support for SHA-384 but doesn't actually make that change in the interests of reviewability. Updating the advertised hash functions will cause changes in many of the testdata/ files and some errors might get lost in the noise. This change only needs to update four testdata/ files: one because a SHA-384-based handshake is now being signed with SHA-256 and the others because the TLS 1.2 CertificateRequest message now includes SHA-1. This change also has the effect of adding support for client-certificates in SSLv3 servers. However, SSLv3 is now disabled by default so this should be moot. It would be possible to avoid much of this change and just support SHA-384 for the ServerKeyExchange as the SKX only signs over the nonces and SKX params (a design mistake in TLS). However, that would leave Go in the odd situation where it advertised support for SHA-384, but would only use the handshake hash when signing client certificates. I fear that'll just cause problems in the future. Much of this code was written by davidben@ for the purposes of testing BoringSSL. Partly addresses #9757 Change-Id: I5137a472b6076812af387a5a69fc62c7373cd485 Reviewed-on: https://go-review.googlesource.com/9415 Run-TryBot: Adam Langley <agl@golang.org> Reviewed-by: Adam Langley <agl@golang.org>
9 роки тому
crypto/tls: decouple handshake signatures from the handshake hash. Prior to TLS 1.2, the handshake had a pleasing property that one could incrementally hash it and, from that, get the needed hashes for both the CertificateVerify and Finished messages. TLS 1.2 introduced negotiation for the signature and hash and it became possible for the handshake hash to be, say, SHA-384, but for the CertificateVerify to sign the handshake with SHA-1. The problem is that one doesn't know in advance which hashes will be needed and thus the handshake needs to be buffered. Go ignored this, always kept a single handshake hash, and any signatures over the handshake had to use that hash. However, there are a set of servers that inspect the client's offered signature hash functions and will abort the handshake if one of the server's certificates is signed with a hash function outside of that set. https://robertsspaceindustries.com/ is an example of such a server. Clearly not a lot of thought happened when that server code was written, but its out there and we have to deal with it. This change decouples the handshake hash from the CertificateVerify hash. This lays the groundwork for advertising support for SHA-384 but doesn't actually make that change in the interests of reviewability. Updating the advertised hash functions will cause changes in many of the testdata/ files and some errors might get lost in the noise. This change only needs to update four testdata/ files: one because a SHA-384-based handshake is now being signed with SHA-256 and the others because the TLS 1.2 CertificateRequest message now includes SHA-1. This change also has the effect of adding support for client-certificates in SSLv3 servers. However, SSLv3 is now disabled by default so this should be moot. It would be possible to avoid much of this change and just support SHA-384 for the ServerKeyExchange as the SKX only signs over the nonces and SKX params (a design mistake in TLS). However, that would leave Go in the odd situation where it advertised support for SHA-384, but would only use the handshake hash when signing client certificates. I fear that'll just cause problems in the future. Much of this code was written by davidben@ for the purposes of testing BoringSSL. Partly addresses #9757 Change-Id: I5137a472b6076812af387a5a69fc62c7373cd485 Reviewed-on: https://go-review.googlesource.com/9415 Run-TryBot: Adam Langley <agl@golang.org> Reviewed-by: Adam Langley <agl@golang.org>
9 роки тому
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. // Copyright 2010 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 th5
  5. import (
  6. "crypto"
  7. "crypto/elliptic"
  8. "crypto/md5"
  9. "crypto/rsa"
  10. "crypto/sha1"
  11. "errors"
  12. "io"
  13. "math/big"
  14. "golang.org/x/crypto/curve25519"
  15. )
  16. var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message")
  17. var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message")
  18. // rsaKeyAgreement implements the standard TLS key agreement where the client
  19. // encrypts the pre-master secret to the server's public key.
  20. type rsaKeyAgreement struct{}
  21. func (ka rsaKeyAgreement) NegotiatedGroup() CurveID {
  22. return CurveID(0)
  23. }
  24. func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, sk crypto.PrivateKey, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
  25. return nil, nil
  26. }
  27. func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, sk crypto.PrivateKey, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
  28. if len(ckx.ciphertext) < 2 {
  29. return nil, errClientKeyExchange
  30. }
  31. ciphertext := ckx.ciphertext
  32. if version != VersionSSL30 {
  33. ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
  34. if ciphertextLen != len(ckx.ciphertext)-2 {
  35. return nil, errClientKeyExchange
  36. }
  37. ciphertext = ckx.ciphertext[2:]
  38. }
  39. priv, ok := sk.(crypto.Decrypter)
  40. if !ok {
  41. return nil, errors.New("tls: certificate private key does not implement crypto.Decrypter")
  42. }
  43. // Perform constant time RSA PKCS#1 v1.5 decryption
  44. preMasterSecret, err := priv.Decrypt(config.rand(), ciphertext, &rsa.PKCS1v15DecryptOptions{SessionKeyLen: 48})
  45. if err != nil {
  46. return nil, err
  47. }
  48. // We don't check the version number in the premaster secret. For one,
  49. // by checking it, we would leak information about the validity of the
  50. // encrypted pre-master secret. Secondly, it provides only a small
  51. // benefit against a downgrade attack and some implementations send the
  52. // wrong version anyway. See the discussion at the end of section
  53. // 7.4.7.1 of RFC 4346.
  54. return preMasterSecret, nil
  55. }
  56. func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, pk crypto.PublicKey, skx *serverKeyExchangeMsg) error {
  57. return errors.New("tls: unexpected ServerKeyExchange")
  58. }
  59. func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, pk crypto.PublicKey) ([]byte, *clientKeyExchangeMsg, error) {
  60. preMasterSecret := make([]byte, 48)
  61. preMasterSecret[0] = byte(clientHello.vers >> 8)
  62. preMasterSecret[1] = byte(clientHello.vers)
  63. _, err := io.ReadFull(config.rand(), preMasterSecret[2:])
  64. if err != nil {
  65. return nil, nil, err
  66. }
  67. encrypted, err := rsa.EncryptPKCS1v15(config.rand(), pk.(*rsa.PublicKey), preMasterSecret)
  68. if err != nil {
  69. return nil, nil, err
  70. }
  71. ckx := new(clientKeyExchangeMsg)
  72. ckx.ciphertext = make([]byte, len(encrypted)+2)
  73. ckx.ciphertext[0] = byte(len(encrypted) >> 8)
  74. ckx.ciphertext[1] = byte(len(encrypted))
  75. copy(ckx.ciphertext[2:], encrypted)
  76. return preMasterSecret, ckx, nil
  77. }
  78. // sha1Hash calculates a SHA1 hash over the given byte slices.
  79. func sha1Hash(slices [][]byte) []byte {
  80. hsha1 := sha1.New()
  81. for _, slice := range slices {
  82. hsha1.Write(slice)
  83. }
  84. return hsha1.Sum(nil)
  85. }
  86. // md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
  87. // concatenation of an MD5 and SHA1 hash.
  88. func md5SHA1Hash(slices [][]byte) []byte {
  89. md5sha1 := make([]byte, md5.Size+sha1.Size)
  90. hmd5 := md5.New()
  91. for _, slice := range slices {
  92. hmd5.Write(slice)
  93. }
  94. copy(md5sha1, hmd5.Sum(nil))
  95. copy(md5sha1[md5.Size:], sha1Hash(slices))
  96. return md5sha1
  97. }
  98. // hashForServerKeyExchange hashes the given slices and returns their digest
  99. // using the given hash function.
  100. func hashForServerKeyExchange(sigType uint8, hashFunc crypto.Hash, version uint16, slices ...[]byte) ([]byte, error) {
  101. if version >= VersionTLS12 {
  102. h := hashFunc.New()
  103. for _, slice := range slices {
  104. h.Write(slice)
  105. }
  106. digest := h.Sum(nil)
  107. return digest, nil
  108. }
  109. if sigType == signatureECDSA {
  110. return sha1Hash(slices), nil
  111. }
  112. return md5SHA1Hash(slices), nil
  113. }
  114. func curveForCurveID(id CurveID) (elliptic.Curve, bool) {
  115. switch id {
  116. case CurveP256:
  117. return elliptic.P256(), true
  118. case CurveP384:
  119. return elliptic.P384(), true
  120. case CurveP521:
  121. return elliptic.P521(), true
  122. default:
  123. return nil, false
  124. }
  125. }
  126. // ecdheKeyAgreement implements a TLS key agreement where the server
  127. // generates an ephemeral EC public/private key pair and signs it. The
  128. // pre-master secret is then calculated using ECDH. The signature may
  129. // either be ECDSA or RSA.
  130. type ecdheKeyAgreement struct {
  131. version uint16
  132. isRSA bool
  133. privateKey []byte
  134. curveid CurveID
  135. // publicKey is used to store the peer's public value when X25519 is
  136. // being used.
  137. publicKey []byte
  138. // x and y are used to store the peer's public value when one of the
  139. // NIST curves is being used.
  140. x, y *big.Int
  141. }
  142. func (ka *ecdheKeyAgreement) NegotiatedGroup() CurveID {
  143. return ka.curveid
  144. }
  145. func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, sk crypto.PrivateKey, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
  146. preferredCurves := config.curvePreferences()
  147. NextCandidate:
  148. for _, candidate := range preferredCurves {
  149. for _, c := range clientHello.supportedCurves {
  150. if candidate == c {
  151. ka.curveid = c
  152. break NextCandidate
  153. }
  154. }
  155. }
  156. if ka.curveid == 0 {
  157. return nil, errors.New("tls: no supported elliptic curves offered")
  158. }
  159. var ecdhePublic []byte
  160. if ka.curveid == X25519 {
  161. var scalar, public [32]byte
  162. if _, err := io.ReadFull(config.rand(), scalar[:]); err != nil {
  163. return nil, err
  164. }
  165. curve25519.ScalarBaseMult(&public, &scalar)
  166. ka.privateKey = scalar[:]
  167. ecdhePublic = public[:]
  168. } else {
  169. curve, ok := curveForCurveID(ka.curveid)
  170. if !ok {
  171. return nil, errors.New("tls: preferredCurves includes unsupported curve")
  172. }
  173. var x, y *big.Int
  174. var err error
  175. ka.privateKey, x, y, err = elliptic.GenerateKey(curve, config.rand())
  176. if err != nil {
  177. return nil, err
  178. }
  179. ecdhePublic = elliptic.Marshal(curve, x, y)
  180. }
  181. // http://tools.ietf.org/html/rfc4492#section-5.4
  182. serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
  183. serverECDHParams[0] = 3 // named curve
  184. serverECDHParams[1] = byte(ka.curveid >> 8)
  185. serverECDHParams[2] = byte(ka.curveid)
  186. serverECDHParams[3] = byte(len(ecdhePublic))
  187. copy(serverECDHParams[4:], ecdhePublic)
  188. priv, ok := sk.(crypto.Signer)
  189. if !ok {
  190. return nil, errors.New("tls: certificate private key does not implement crypto.Signer")
  191. }
  192. signatureAlgorithm, sigType, hashFunc, err := pickSignatureAlgorithm(priv.Public(), clientHello.supportedSignatureAlgorithms, supportedSignatureAlgorithms, ka.version)
  193. if err != nil {
  194. return nil, err
  195. }
  196. if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA {
  197. return nil, errors.New("tls: certificate cannot be used with the selected cipher suite")
  198. }
  199. digest, err := hashForServerKeyExchange(sigType, hashFunc, ka.version, clientHello.random, hello.random, serverECDHParams)
  200. if err != nil {
  201. return nil, err
  202. }
  203. var sig []byte
  204. signOpts := crypto.SignerOpts(hashFunc)
  205. if sigType == signatureRSAPSS {
  206. signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: hashFunc}
  207. }
  208. sig, err = priv.Sign(config.rand(), digest, signOpts)
  209. if err != nil {
  210. return nil, errors.New("tls: failed to sign ECDHE parameters: " + err.Error())
  211. }
  212. skx := new(serverKeyExchangeMsg)
  213. sigAndHashLen := 0
  214. if ka.version >= VersionTLS12 {
  215. sigAndHashLen = 2
  216. }
  217. skx.key = make([]byte, len(serverECDHParams)+sigAndHashLen+2+len(sig))
  218. copy(skx.key, serverECDHParams)
  219. k := skx.key[len(serverECDHParams):]
  220. if ka.version >= VersionTLS12 {
  221. k[0] = byte(signatureAlgorithm >> 8)
  222. k[1] = byte(signatureAlgorithm)
  223. k = k[2:]
  224. }
  225. k[0] = byte(len(sig) >> 8)
  226. k[1] = byte(len(sig))
  227. copy(k[2:], sig)
  228. return skx, nil
  229. }
  230. func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, sk crypto.PrivateKey, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
  231. if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
  232. return nil, errClientKeyExchange
  233. }
  234. if ka.curveid == X25519 {
  235. if len(ckx.ciphertext) != 1+32 {
  236. return nil, errClientKeyExchange
  237. }
  238. var theirPublic, sharedKey, scalar [32]byte
  239. copy(theirPublic[:], ckx.ciphertext[1:])
  240. copy(scalar[:], ka.privateKey)
  241. curve25519.ScalarMult(&sharedKey, &scalar, &theirPublic)
  242. return sharedKey[:], nil
  243. }
  244. curve, ok := curveForCurveID(ka.curveid)
  245. if !ok {
  246. panic("internal error")
  247. }
  248. x, y := elliptic.Unmarshal(curve, ckx.ciphertext[1:]) // Unmarshal also checks whether the given point is on the curve
  249. if x == nil {
  250. return nil, errClientKeyExchange
  251. }
  252. x, _ = curve.ScalarMult(x, y, ka.privateKey)
  253. curveSize := (curve.Params().BitSize + 7) >> 3
  254. xBytes := x.Bytes()
  255. if len(xBytes) == curveSize {
  256. return xBytes, nil
  257. }
  258. preMasterSecret := make([]byte, curveSize)
  259. copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
  260. return preMasterSecret, nil
  261. }
  262. func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, pk crypto.PublicKey, skx *serverKeyExchangeMsg) error {
  263. if len(skx.key) < 4 {
  264. return errServerKeyExchange
  265. }
  266. if skx.key[0] != 3 { // named curve
  267. return errors.New("tls: server selected unsupported curve")
  268. }
  269. ka.curveid = CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
  270. publicLen := int(skx.key[3])
  271. if publicLen+4 > len(skx.key) {
  272. return errServerKeyExchange
  273. }
  274. serverECDHParams := skx.key[:4+publicLen]
  275. publicKey := serverECDHParams[4:]
  276. sig := skx.key[4+publicLen:]
  277. if len(sig) < 2 {
  278. return errServerKeyExchange
  279. }
  280. if ka.curveid == X25519 {
  281. if len(publicKey) != 32 {
  282. return errors.New("tls: bad X25519 public value")
  283. }
  284. ka.publicKey = publicKey
  285. } else {
  286. curve, ok := curveForCurveID(ka.curveid)
  287. if !ok {
  288. return errors.New("tls: server selected unsupported curve")
  289. }
  290. ka.x, ka.y = elliptic.Unmarshal(curve, publicKey) // Unmarshal also checks whether the given point is on the curve
  291. if ka.x == nil {
  292. return errServerKeyExchange
  293. }
  294. }
  295. var signatureAlgorithm SignatureScheme
  296. if ka.version >= VersionTLS12 {
  297. // handle SignatureAndHashAlgorithm
  298. signatureAlgorithm = SignatureScheme(sig[0])<<8 | SignatureScheme(sig[1])
  299. sig = sig[2:]
  300. if len(sig) < 2 {
  301. return errServerKeyExchange
  302. }
  303. }
  304. _, sigType, hashFunc, err := pickSignatureAlgorithm(pk, []SignatureScheme{signatureAlgorithm}, clientHello.supportedSignatureAlgorithms, ka.version)
  305. if err != nil {
  306. return err
  307. }
  308. if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA {
  309. return errServerKeyExchange
  310. }
  311. sigLen := int(sig[0])<<8 | int(sig[1])
  312. if sigLen+2 != len(sig) {
  313. return errServerKeyExchange
  314. }
  315. sig = sig[2:]
  316. digest, err := hashForServerKeyExchange(sigType, hashFunc, ka.version, clientHello.random, serverHello.random, serverECDHParams)
  317. if err != nil {
  318. return err
  319. }
  320. return verifyHandshakeSignature(sigType, pk, hashFunc, digest, sig)
  321. }
  322. func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, pk crypto.PublicKey) ([]byte, *clientKeyExchangeMsg, error) {
  323. if ka.curveid == 0 {
  324. return nil, nil, errors.New("tls: missing ServerKeyExchange message")
  325. }
  326. var serialized, preMasterSecret []byte
  327. if ka.curveid == X25519 {
  328. var ourPublic, theirPublic, sharedKey, scalar [32]byte
  329. if _, err := io.ReadFull(config.rand(), scalar[:]); err != nil {
  330. return nil, nil, err
  331. }
  332. copy(theirPublic[:], ka.publicKey)
  333. curve25519.ScalarBaseMult(&ourPublic, &scalar)
  334. curve25519.ScalarMult(&sharedKey, &scalar, &theirPublic)
  335. serialized = ourPublic[:]
  336. preMasterSecret = sharedKey[:]
  337. } else {
  338. curve, ok := curveForCurveID(ka.curveid)
  339. if !ok {
  340. panic("internal error")
  341. }
  342. priv, mx, my, err := elliptic.GenerateKey(curve, config.rand())
  343. if err != nil {
  344. return nil, nil, err
  345. }
  346. x, _ := curve.ScalarMult(ka.x, ka.y, priv)
  347. preMasterSecret = make([]byte, (curve.Params().BitSize+7)>>3)
  348. xBytes := x.Bytes()
  349. copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
  350. serialized = elliptic.Marshal(curve, mx, my)
  351. }
  352. ckx := new(clientKeyExchangeMsg)
  353. ckx.ciphertext = make([]byte, 1+len(serialized))
  354. ckx.ciphertext[0] = byte(len(serialized))
  355. copy(ckx.ciphertext[1:], serialized)
  356. return preMasterSecret, ckx, nil
  357. }