選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

key_agreement.go 12 KiB

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年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  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 tls
  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) generateServerKeyExchange(config *Config, sk crypto.PrivateKey, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
  22. return nil, nil
  23. }
  24. func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, sk crypto.PrivateKey, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
  25. if len(ckx.ciphertext) < 2 {
  26. return nil, errClientKeyExchange
  27. }
  28. ciphertext := ckx.ciphertext
  29. if version != VersionSSL30 {
  30. ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
  31. if ciphertextLen != len(ckx.ciphertext)-2 {
  32. return nil, errClientKeyExchange
  33. }
  34. ciphertext = ckx.ciphertext[2:]
  35. }
  36. priv, ok := sk.(crypto.Decrypter)
  37. if !ok {
  38. return nil, errors.New("tls: certificate private key does not implement crypto.Decrypter")
  39. }
  40. // Perform constant time RSA PKCS#1 v1.5 decryption
  41. preMasterSecret, err := priv.Decrypt(config.rand(), ciphertext, &rsa.PKCS1v15DecryptOptions{SessionKeyLen: 48})
  42. if err != nil {
  43. return nil, err
  44. }
  45. // We don't check the version number in the premaster secret. For one,
  46. // by checking it, we would leak information about the validity of the
  47. // encrypted pre-master secret. Secondly, it provides only a small
  48. // benefit against a downgrade attack and some implementations send the
  49. // wrong version anyway. See the discussion at the end of section
  50. // 7.4.7.1 of RFC 4346.
  51. return preMasterSecret, nil
  52. }
  53. func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, pk crypto.PublicKey, skx *serverKeyExchangeMsg) error {
  54. return errors.New("tls: unexpected ServerKeyExchange")
  55. }
  56. func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, pk crypto.PublicKey) ([]byte, *clientKeyExchangeMsg, error) {
  57. preMasterSecret := make([]byte, 48)
  58. preMasterSecret[0] = byte(clientHello.vers >> 8)
  59. preMasterSecret[1] = byte(clientHello.vers)
  60. _, err := io.ReadFull(config.rand(), preMasterSecret[2:])
  61. if err != nil {
  62. return nil, nil, err
  63. }
  64. encrypted, err := rsa.EncryptPKCS1v15(config.rand(), pk.(*rsa.PublicKey), preMasterSecret)
  65. if err != nil {
  66. return nil, nil, err
  67. }
  68. ckx := new(clientKeyExchangeMsg)
  69. ckx.ciphertext = make([]byte, len(encrypted)+2)
  70. ckx.ciphertext[0] = byte(len(encrypted) >> 8)
  71. ckx.ciphertext[1] = byte(len(encrypted))
  72. copy(ckx.ciphertext[2:], encrypted)
  73. return preMasterSecret, ckx, nil
  74. }
  75. // sha1Hash calculates a SHA1 hash over the given byte slices.
  76. func sha1Hash(slices [][]byte) []byte {
  77. hsha1 := sha1.New()
  78. for _, slice := range slices {
  79. hsha1.Write(slice)
  80. }
  81. return hsha1.Sum(nil)
  82. }
  83. // md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
  84. // concatenation of an MD5 and SHA1 hash.
  85. func md5SHA1Hash(slices [][]byte) []byte {
  86. md5sha1 := make([]byte, md5.Size+sha1.Size)
  87. hmd5 := md5.New()
  88. for _, slice := range slices {
  89. hmd5.Write(slice)
  90. }
  91. copy(md5sha1, hmd5.Sum(nil))
  92. copy(md5sha1[md5.Size:], sha1Hash(slices))
  93. return md5sha1
  94. }
  95. // hashForServerKeyExchange hashes the given slices and returns their digest
  96. // using the given hash function.
  97. func hashForServerKeyExchange(sigType uint8, hashFunc crypto.Hash, version uint16, slices ...[]byte) ([]byte, error) {
  98. if version >= VersionTLS12 {
  99. h := hashFunc.New()
  100. for _, slice := range slices {
  101. h.Write(slice)
  102. }
  103. digest := h.Sum(nil)
  104. return digest, nil
  105. }
  106. if sigType == signatureECDSA {
  107. return sha1Hash(slices), nil
  108. }
  109. return md5SHA1Hash(slices), nil
  110. }
  111. func curveForCurveID(id CurveID) (elliptic.Curve, bool) {
  112. switch id {
  113. case CurveP256:
  114. return elliptic.P256(), true
  115. case CurveP384:
  116. return elliptic.P384(), true
  117. case CurveP521:
  118. return elliptic.P521(), true
  119. default:
  120. return nil, false
  121. }
  122. }
  123. // ecdheKeyAgreement implements a TLS key agreement where the server
  124. // generates an ephemeral EC public/private key pair and signs it. The
  125. // pre-master secret is then calculated using ECDH. The signature may
  126. // either be ECDSA or RSA.
  127. type ecdheKeyAgreement struct {
  128. version uint16
  129. isRSA bool
  130. privateKey []byte
  131. curveid CurveID
  132. // publicKey is used to store the peer's public value when X25519 is
  133. // being used.
  134. publicKey []byte
  135. // x and y are used to store the peer's public value when one of the
  136. // NIST curves is being used.
  137. x, y *big.Int
  138. }
  139. func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, sk crypto.PrivateKey, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
  140. preferredCurves := config.curvePreferences()
  141. NextCandidate:
  142. for _, candidate := range preferredCurves {
  143. for _, c := range clientHello.supportedCurves {
  144. if candidate == c {
  145. ka.curveid = c
  146. break NextCandidate
  147. }
  148. }
  149. }
  150. if ka.curveid == 0 {
  151. return nil, errors.New("tls: no supported elliptic curves offered")
  152. }
  153. var ecdhePublic []byte
  154. if ka.curveid == X25519 {
  155. var scalar, public [32]byte
  156. if _, err := io.ReadFull(config.rand(), scalar[:]); err != nil {
  157. return nil, err
  158. }
  159. curve25519.ScalarBaseMult(&public, &scalar)
  160. ka.privateKey = scalar[:]
  161. ecdhePublic = public[:]
  162. } else {
  163. curve, ok := curveForCurveID(ka.curveid)
  164. if !ok {
  165. return nil, errors.New("tls: preferredCurves includes unsupported curve")
  166. }
  167. var x, y *big.Int
  168. var err error
  169. ka.privateKey, x, y, err = elliptic.GenerateKey(curve, config.rand())
  170. if err != nil {
  171. return nil, err
  172. }
  173. ecdhePublic = elliptic.Marshal(curve, x, y)
  174. }
  175. // http://tools.ietf.org/html/rfc4492#section-5.4
  176. serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
  177. serverECDHParams[0] = 3 // named curve
  178. serverECDHParams[1] = byte(ka.curveid >> 8)
  179. serverECDHParams[2] = byte(ka.curveid)
  180. serverECDHParams[3] = byte(len(ecdhePublic))
  181. copy(serverECDHParams[4:], ecdhePublic)
  182. priv, ok := sk.(crypto.Signer)
  183. if !ok {
  184. return nil, errors.New("tls: certificate private key does not implement crypto.Signer")
  185. }
  186. signatureAlgorithm, sigType, hashFunc, err := pickSignatureAlgorithm(priv.Public(), clientHello.supportedSignatureAlgorithms, supportedSignatureAlgorithms, ka.version)
  187. if err != nil {
  188. return nil, err
  189. }
  190. if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA {
  191. return nil, errors.New("tls: certificate cannot be used with the selected cipher suite")
  192. }
  193. digest, err := hashForServerKeyExchange(sigType, hashFunc, ka.version, clientHello.random, hello.random, serverECDHParams)
  194. if err != nil {
  195. return nil, err
  196. }
  197. var sig []byte
  198. signOpts := crypto.SignerOpts(hashFunc)
  199. if sigType == signatureRSAPSS {
  200. signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: hashFunc}
  201. }
  202. sig, err = priv.Sign(config.rand(), digest, signOpts)
  203. if err != nil {
  204. return nil, errors.New("tls: failed to sign ECDHE parameters: " + err.Error())
  205. }
  206. skx := new(serverKeyExchangeMsg)
  207. sigAndHashLen := 0
  208. if ka.version >= VersionTLS12 {
  209. sigAndHashLen = 2
  210. }
  211. skx.key = make([]byte, len(serverECDHParams)+sigAndHashLen+2+len(sig))
  212. copy(skx.key, serverECDHParams)
  213. k := skx.key[len(serverECDHParams):]
  214. if ka.version >= VersionTLS12 {
  215. k[0] = byte(signatureAlgorithm >> 8)
  216. k[1] = byte(signatureAlgorithm)
  217. k = k[2:]
  218. }
  219. k[0] = byte(len(sig) >> 8)
  220. k[1] = byte(len(sig))
  221. copy(k[2:], sig)
  222. return skx, nil
  223. }
  224. func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, sk crypto.PrivateKey, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
  225. if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
  226. return nil, errClientKeyExchange
  227. }
  228. if ka.curveid == X25519 {
  229. if len(ckx.ciphertext) != 1+32 {
  230. return nil, errClientKeyExchange
  231. }
  232. var theirPublic, sharedKey, scalar [32]byte
  233. copy(theirPublic[:], ckx.ciphertext[1:])
  234. copy(scalar[:], ka.privateKey)
  235. curve25519.ScalarMult(&sharedKey, &scalar, &theirPublic)
  236. return sharedKey[:], nil
  237. }
  238. curve, ok := curveForCurveID(ka.curveid)
  239. if !ok {
  240. panic("internal error")
  241. }
  242. x, y := elliptic.Unmarshal(curve, ckx.ciphertext[1:]) // Unmarshal also checks whether the given point is on the curve
  243. if x == nil {
  244. return nil, errClientKeyExchange
  245. }
  246. x, _ = curve.ScalarMult(x, y, ka.privateKey)
  247. curveSize := (curve.Params().BitSize + 7) >> 3
  248. xBytes := x.Bytes()
  249. if len(xBytes) == curveSize {
  250. return xBytes, nil
  251. }
  252. preMasterSecret := make([]byte, curveSize)
  253. copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
  254. return preMasterSecret, nil
  255. }
  256. func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, pk crypto.PublicKey, skx *serverKeyExchangeMsg) error {
  257. if len(skx.key) < 4 {
  258. return errServerKeyExchange
  259. }
  260. if skx.key[0] != 3 { // named curve
  261. return errors.New("tls: server selected unsupported curve")
  262. }
  263. ka.curveid = CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
  264. publicLen := int(skx.key[3])
  265. if publicLen+4 > len(skx.key) {
  266. return errServerKeyExchange
  267. }
  268. serverECDHParams := skx.key[:4+publicLen]
  269. publicKey := serverECDHParams[4:]
  270. sig := skx.key[4+publicLen:]
  271. if len(sig) < 2 {
  272. return errServerKeyExchange
  273. }
  274. if ka.curveid == X25519 {
  275. if len(publicKey) != 32 {
  276. return errors.New("tls: bad X25519 public value")
  277. }
  278. ka.publicKey = publicKey
  279. } else {
  280. curve, ok := curveForCurveID(ka.curveid)
  281. if !ok {
  282. return errors.New("tls: server selected unsupported curve")
  283. }
  284. ka.x, ka.y = elliptic.Unmarshal(curve, publicKey) // Unmarshal also checks whether the given point is on the curve
  285. if ka.x == nil {
  286. return errServerKeyExchange
  287. }
  288. }
  289. var signatureAlgorithm SignatureScheme
  290. if ka.version >= VersionTLS12 {
  291. // handle SignatureAndHashAlgorithm
  292. signatureAlgorithm = SignatureScheme(sig[0])<<8 | SignatureScheme(sig[1])
  293. sig = sig[2:]
  294. if len(sig) < 2 {
  295. return errServerKeyExchange
  296. }
  297. }
  298. _, sigType, hashFunc, err := pickSignatureAlgorithm(pk, []SignatureScheme{signatureAlgorithm}, clientHello.supportedSignatureAlgorithms, ka.version)
  299. if err != nil {
  300. return err
  301. }
  302. if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA {
  303. return errServerKeyExchange
  304. }
  305. sigLen := int(sig[0])<<8 | int(sig[1])
  306. if sigLen+2 != len(sig) {
  307. return errServerKeyExchange
  308. }
  309. sig = sig[2:]
  310. digest, err := hashForServerKeyExchange(sigType, hashFunc, ka.version, clientHello.random, serverHello.random, serverECDHParams)
  311. if err != nil {
  312. return err
  313. }
  314. return verifyHandshakeSignature(sigType, pk, hashFunc, digest, sig)
  315. }
  316. func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, pk crypto.PublicKey) ([]byte, *clientKeyExchangeMsg, error) {
  317. if ka.curveid == 0 {
  318. return nil, nil, errors.New("tls: missing ServerKeyExchange message")
  319. }
  320. var serialized, preMasterSecret []byte
  321. if ka.curveid == X25519 {
  322. var ourPublic, theirPublic, sharedKey, scalar [32]byte
  323. if _, err := io.ReadFull(config.rand(), scalar[:]); err != nil {
  324. return nil, nil, err
  325. }
  326. copy(theirPublic[:], ka.publicKey)
  327. curve25519.ScalarBaseMult(&ourPublic, &scalar)
  328. curve25519.ScalarMult(&sharedKey, &scalar, &theirPublic)
  329. serialized = ourPublic[:]
  330. preMasterSecret = sharedKey[:]
  331. } else {
  332. curve, ok := curveForCurveID(ka.curveid)
  333. if !ok {
  334. panic("internal error")
  335. }
  336. priv, mx, my, err := elliptic.GenerateKey(curve, config.rand())
  337. if err != nil {
  338. return nil, nil, err
  339. }
  340. x, _ := curve.ScalarMult(ka.x, ka.y, priv)
  341. preMasterSecret = make([]byte, (curve.Params().BitSize+7)>>3)
  342. xBytes := x.Bytes()
  343. copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
  344. serialized = elliptic.Marshal(curve, mx, my)
  345. }
  346. ckx := new(clientKeyExchangeMsg)
  347. ckx.ciphertext = make([]byte, 1+len(serialized))
  348. ckx.ciphertext[0] = byte(len(serialized))
  349. copy(ckx.ciphertext[1:], serialized)
  350. return preMasterSecret, ckx, nil
  351. }