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.

128 line
3.1 KiB

  1. // Copyright 2009 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. // This package partially implements the TLS 1.1 protocol, as specified in RFC 4346.
  5. package tls
  6. import (
  7. "io/ioutil"
  8. "net"
  9. "os"
  10. "encoding/pem"
  11. "crypto/rsa"
  12. "crypto/x509"
  13. )
  14. func Server(conn net.Conn, config *Config) *Conn {
  15. return &Conn{conn: conn, config: config}
  16. }
  17. func Client(conn net.Conn, config *Config) *Conn {
  18. return &Conn{conn: conn, config: config, isClient: true}
  19. }
  20. type Listener struct {
  21. listener net.Listener
  22. config *Config
  23. }
  24. func (l *Listener) Accept() (c net.Conn, err os.Error) {
  25. c, err = l.listener.Accept()
  26. if err != nil {
  27. return
  28. }
  29. c = Server(c, l.config)
  30. return
  31. }
  32. func (l *Listener) Close() os.Error { return l.listener.Close() }
  33. func (l *Listener) Addr() net.Addr { return l.listener.Addr() }
  34. // NewListener creates a Listener which accepts connections from an inner
  35. // Listener and wraps each connection with Server.
  36. // The configuration config must be non-nil and must have
  37. // at least one certificate.
  38. func NewListener(listener net.Listener, config *Config) (l *Listener) {
  39. l = new(Listener)
  40. l.listener = listener
  41. l.config = config
  42. return
  43. }
  44. func Listen(network, laddr string, config *Config) (net.Listener, os.Error) {
  45. if config == nil || len(config.Certificates) == 0 {
  46. return nil, os.NewError("tls.Listen: no certificates in configuration")
  47. }
  48. l, err := net.Listen(network, laddr)
  49. if err != nil {
  50. return nil, err
  51. }
  52. return NewListener(l, config), nil
  53. }
  54. func Dial(network, laddr, raddr string) (net.Conn, os.Error) {
  55. c, err := net.Dial(network, laddr, raddr)
  56. if err != nil {
  57. return nil, err
  58. }
  59. conn := Client(c, nil)
  60. err = conn.Handshake()
  61. if err == nil {
  62. return conn, nil
  63. }
  64. c.Close()
  65. return nil, err
  66. }
  67. // LoadX509KeyPair reads and parses a public/private key pair from a pair of
  68. // files. The files must contain PEM encoded data.
  69. func LoadX509KeyPair(certFile string, keyFile string) (cert Certificate, err os.Error) {
  70. certPEMBlock, err := ioutil.ReadFile(certFile)
  71. if err != nil {
  72. return
  73. }
  74. certDERBlock, _ := pem.Decode(certPEMBlock)
  75. if certDERBlock == nil {
  76. err = os.ErrorString("crypto/tls: failed to parse certificate PEM data")
  77. return
  78. }
  79. cert.Certificate = [][]byte{certDERBlock.Bytes}
  80. keyPEMBlock, err := ioutil.ReadFile(keyFile)
  81. if err != nil {
  82. return
  83. }
  84. keyDERBlock, _ := pem.Decode(keyPEMBlock)
  85. if keyDERBlock == nil {
  86. err = os.ErrorString("crypto/tls: failed to parse key PEM data")
  87. return
  88. }
  89. key, err := x509.ParsePKCS1PrivateKey(keyDERBlock.Bytes)
  90. if err != nil {
  91. err = os.ErrorString("crypto/tls: failed to parse key")
  92. return
  93. }
  94. cert.PrivateKey = key
  95. // We don't need to parse the public key for TLS, but we so do anyway
  96. // to check that it looks sane and matches the private key.
  97. x509Cert, err := x509.ParseCertificate(certDERBlock.Bytes)
  98. if err != nil {
  99. return
  100. }
  101. if x509Cert.PublicKeyAlgorithm != x509.RSA || x509Cert.PublicKey.(*rsa.PublicKey).N.Cmp(key.PublicKey.N) != 0 {
  102. err = os.ErrorString("crypto/tls: private key does not match public key")
  103. return
  104. }
  105. return
  106. }