Alternative TLS implementation in Go
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

411 lines
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 trs
  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. }