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.

403 lignes
12 KiB

  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. }