tlsutil.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. // Copyright (C) 2014 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. package tlsutil
  7. import (
  8. "crypto/ecdsa"
  9. "crypto/ed25519"
  10. "crypto/elliptic"
  11. "crypto/rsa"
  12. "crypto/tls"
  13. "crypto/x509"
  14. "crypto/x509/pkix"
  15. "encoding/pem"
  16. "errors"
  17. "fmt"
  18. "math/big"
  19. "net"
  20. "os"
  21. "time"
  22. "github.com/syncthing/syncthing/lib/rand"
  23. )
  24. var (
  25. ErrIdentificationFailed = errors.New("failed to identify socket type")
  26. // The list of cipher suites we will use / suggest for TLS 1.2 connections.
  27. cipherSuites = []uint16{
  28. // Suites that are good and fast on hardware *without* AES-NI.
  29. tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
  30. tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
  31. // Suites that are good and fast on hardware with AES-NI. These are
  32. // reordered from the Go default to put the 256 bit ciphers above the
  33. // 128 bit ones - because that looks cooler, even though there is
  34. // probably no relevant difference in strength yet.
  35. tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
  36. tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
  37. tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
  38. tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
  39. // The rest of the suites, minus DES stuff.
  40. tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
  41. tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
  42. tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
  43. tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
  44. tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
  45. tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
  46. tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
  47. tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
  48. tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
  49. tls.TLS_RSA_WITH_AES_128_CBC_SHA,
  50. tls.TLS_RSA_WITH_AES_256_CBC_SHA,
  51. }
  52. )
  53. // SecureDefault returns a tls.Config with reasonable, secure defaults set.
  54. // This variant allows only TLS 1.3.
  55. func SecureDefaultTLS13() *tls.Config {
  56. return &tls.Config{
  57. // TLS 1.3 is the minimum we accept
  58. MinVersion: tls.VersionTLS13,
  59. ClientSessionCache: tls.NewLRUClientSessionCache(0),
  60. }
  61. }
  62. // SecureDefaultWithTLS12 returns a tls.Config with reasonable, secure
  63. // defaults set. This variant allows TLS 1.2.
  64. func SecureDefaultWithTLS12() *tls.Config {
  65. // paranoia
  66. cs := make([]uint16, len(cipherSuites))
  67. copy(cs, cipherSuites)
  68. return &tls.Config{
  69. // TLS 1.2 is the minimum we accept
  70. MinVersion: tls.VersionTLS12,
  71. // The cipher suite lists built above. These are ignored in TLS 1.3.
  72. CipherSuites: cs,
  73. // We've put some thought into this choice and would like it to
  74. // matter.
  75. PreferServerCipherSuites: true,
  76. // We support HTTP/2 and HTTP/1.1
  77. NextProtos: []string{"h2", "http/1.1"},
  78. ClientSessionCache: tls.NewLRUClientSessionCache(0),
  79. }
  80. }
  81. // generateCertificate generates a PEM formatted key pair and self-signed
  82. // certificate in memory. The compatible flag indicates whether we aim for
  83. // compatibility (browsers) or maximum efficiency/security (sync
  84. // connections).
  85. func generateCertificate(commonName string, lifetimeDays int, compatible bool) (*pem.Block, *pem.Block, error) {
  86. var pub, priv any
  87. var err error
  88. var sigAlgo x509.SignatureAlgorithm
  89. if compatible {
  90. // For browser connections we prefer ECDSA-P256
  91. sigAlgo = x509.ECDSAWithSHA256
  92. var pk *ecdsa.PrivateKey
  93. pk, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  94. if err == nil {
  95. priv = pk
  96. pub = pk.Public()
  97. }
  98. } else {
  99. // For sync connections we use Ed25519
  100. sigAlgo = x509.PureEd25519
  101. pub, priv, err = ed25519.GenerateKey(rand.Reader)
  102. }
  103. if err != nil {
  104. return nil, nil, fmt.Errorf("generate key: %w", err)
  105. }
  106. notBefore := time.Now().Truncate(24 * time.Hour)
  107. notAfter := notBefore.Add(time.Duration(lifetimeDays*24) * time.Hour)
  108. // NOTE: update lib/api.shouldRegenerateCertificate() appropriately if
  109. // you add or change attributes in here, especially DNSNames or
  110. // IPAddresses.
  111. template := x509.Certificate{
  112. SerialNumber: new(big.Int).SetUint64(rand.Uint64()),
  113. Subject: pkix.Name{
  114. CommonName: commonName,
  115. Organization: []string{"Syncthing"},
  116. OrganizationalUnit: []string{"Automatically Generated"},
  117. },
  118. DNSNames: []string{commonName},
  119. NotBefore: notBefore,
  120. NotAfter: notAfter,
  121. SignatureAlgorithm: sigAlgo,
  122. KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
  123. ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
  124. BasicConstraintsValid: true,
  125. }
  126. derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, pub, priv)
  127. if err != nil {
  128. return nil, nil, fmt.Errorf("create cert: %w", err)
  129. }
  130. certBlock := &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}
  131. keyBlock, err := pemBlockForKey(priv)
  132. if err != nil {
  133. return nil, nil, fmt.Errorf("save key: %w", err)
  134. }
  135. return certBlock, keyBlock, nil
  136. }
  137. // NewCertificate generates and returns a new TLS certificate, saved to the
  138. // given PEM files. The compatible flag indicates whether we aim for
  139. // compatibility (browsers) or maximum efficiency/security (sync
  140. // connections).
  141. func NewCertificate(certFile, keyFile string, commonName string, lifetimeDays int, compatible bool) (tls.Certificate, error) {
  142. certBlock, keyBlock, err := generateCertificate(commonName, lifetimeDays, compatible)
  143. if err != nil {
  144. return tls.Certificate{}, err
  145. }
  146. certOut, err := os.Create(certFile)
  147. if err != nil {
  148. return tls.Certificate{}, fmt.Errorf("save cert: %w", err)
  149. }
  150. if err = pem.Encode(certOut, certBlock); err != nil {
  151. return tls.Certificate{}, fmt.Errorf("save cert: %w", err)
  152. }
  153. if err = certOut.Close(); err != nil {
  154. return tls.Certificate{}, fmt.Errorf("save cert: %w", err)
  155. }
  156. keyOut, err := os.OpenFile(keyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
  157. if err != nil {
  158. return tls.Certificate{}, fmt.Errorf("save key: %w", err)
  159. }
  160. if err = pem.Encode(keyOut, keyBlock); err != nil {
  161. return tls.Certificate{}, fmt.Errorf("save key: %w", err)
  162. }
  163. if err = keyOut.Close(); err != nil {
  164. return tls.Certificate{}, fmt.Errorf("save key: %w", err)
  165. }
  166. return tls.X509KeyPair(pem.EncodeToMemory(certBlock), pem.EncodeToMemory(keyBlock))
  167. }
  168. // NewCertificateInMemory generates and returns a new TLS certificate, kept
  169. // only in memory.
  170. func NewCertificateInMemory(commonName string, lifetimeDays int) (tls.Certificate, error) {
  171. certBlock, keyBlock, err := generateCertificate(commonName, lifetimeDays, false)
  172. if err != nil {
  173. return tls.Certificate{}, err
  174. }
  175. return tls.X509KeyPair(pem.EncodeToMemory(certBlock), pem.EncodeToMemory(keyBlock))
  176. }
  177. type DowngradingListener struct {
  178. net.Listener
  179. TLSConfig *tls.Config
  180. }
  181. func (l *DowngradingListener) Accept() (net.Conn, error) {
  182. conn, isTLS, err := l.AcceptNoWrapTLS()
  183. // We failed to identify the socket type, pretend that everything is fine,
  184. // and pass it to the underlying handler, and let them deal with it.
  185. if err == ErrIdentificationFailed {
  186. return conn, nil
  187. }
  188. if err != nil {
  189. return conn, err
  190. }
  191. if isTLS {
  192. return tls.Server(conn, l.TLSConfig), nil
  193. }
  194. return conn, nil
  195. }
  196. func (l *DowngradingListener) AcceptNoWrapTLS() (net.Conn, bool, error) {
  197. conn, err := l.Listener.Accept()
  198. if err != nil {
  199. return nil, false, err
  200. }
  201. union := &UnionedConnection{Conn: conn}
  202. conn.SetReadDeadline(time.Now().Add(1 * time.Second))
  203. n, err := conn.Read(union.first[:])
  204. conn.SetReadDeadline(time.Time{})
  205. if err != nil || n == 0 {
  206. // We hit a read error here, but the Accept() call succeeded so we must not return an error.
  207. // We return the connection as is with a special error which handles this
  208. // special case in Accept().
  209. return conn, false, ErrIdentificationFailed
  210. }
  211. return union, union.first[0] == 0x16, nil
  212. }
  213. type UnionedConnection struct {
  214. net.Conn
  215. first [1]byte
  216. firstDone bool
  217. }
  218. func (c *UnionedConnection) Read(b []byte) (n int, err error) {
  219. if !c.firstDone {
  220. if len(b) == 0 {
  221. // this probably doesn't happen, but handle it anyway
  222. return 0, nil
  223. }
  224. b[0] = c.first[0]
  225. c.firstDone = true
  226. return 1, nil
  227. }
  228. return c.Conn.Read(b)
  229. }
  230. func pemBlockForKey(priv interface{}) (*pem.Block, error) {
  231. switch k := priv.(type) {
  232. case *rsa.PrivateKey:
  233. return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}, nil
  234. case *ecdsa.PrivateKey:
  235. b, err := x509.MarshalECPrivateKey(k)
  236. if err != nil {
  237. return nil, err
  238. }
  239. return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}, nil
  240. case ed25519.PrivateKey:
  241. bs, err := x509.MarshalPKCS8PrivateKey(k)
  242. if err != nil {
  243. return nil, err
  244. }
  245. return &pem.Block{Type: "PRIVATE KEY", Bytes: bs}, nil
  246. default:
  247. return nil, fmt.Errorf("unknown key type: %T", priv)
  248. }
  249. }