go.dedis.ch/onet/v4@v4.0.0-pre1/network/tls.go (about)

     1  package network
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/ecdsa"
     6  	"crypto/elliptic"
     7  	"crypto/rand"
     8  	"crypto/tls"
     9  	"crypto/x509"
    10  	"crypto/x509/pkix"
    11  	"encoding/asn1"
    12  	"encoding/hex"
    13  	"math/big"
    14  	"net"
    15  	"time"
    16  
    17  	"go.dedis.ch/kyber/v4"
    18  	"go.dedis.ch/kyber/v4/sign/schnorr"
    19  	"go.dedis.ch/kyber/v4/util/encoding"
    20  	"go.dedis.ch/kyber/v4/util/random"
    21  	"go.dedis.ch/onet/v4/log"
    22  	"golang.org/x/xerrors"
    23  )
    24  
    25  // About our TLS strategy:
    26  //
    27  // The design goals were:
    28  // 1. use vanilla TLS for conode/conode communication, in order to ease deployment
    29  //    anxiety with industrial partners. ("If it's not TLS, it's not allowed." Sigh.)
    30  // 2. zero config: whatever config we have in an existing private.toml should be enough
    31  // 3. mutual authentication: each side should end up with proof that the other side is
    32  //    holding the secret key associated with the public key they claim to have.
    33  //
    34  // In order to achieve #1, we limit ourselves to TLS 1.2. This means that the TLS
    35  // private key must be different than the conode private key (which may be from a suite
    36  // not supported in TLS 1.2).
    37  //
    38  // In order to achieve #2, we use self-signed TLS certificates, with a private key
    39  // that is created on server boot and stored in RAM. Because the certificates are
    40  // self-signed, there is no need to pay a CA, nor to load the private key
    41  // or certificate from disk.
    42  //
    43  // In order to achieve #3, we include an extension in the certificate, which
    44  // proves that the same entity that holds the TLS private key (i.e. the signing
    45  // key for the self-signed TLS cert) also holds the conode's private key.
    46  // We do this by hashing a nonce provided by the peer (in order to prove that this
    47  // is a fresh challenge response) and the ASN.1 encoded CommonName of the certificate.
    48  // The CN is always the hex-encoded form of the conode's public key.
    49  //
    50  // Because each side needs a nonce which is controlled by the opposite party in the
    51  // mutual authentication, but TLS does not support sending application data before the handshake,
    52  // we need to find places in the normal TLS 1.2 handshake where we can "tunnel" the nonce
    53  // through. On the TLS client side, we use ClientHelloInfo.ServerName. On the
    54  // the TLS server side, we use the ClientCAs field.
    55  //
    56  // There is a risk that with a less customizable TLS implementation than
    57  // Go's, it would not be possible to send the nonces through like this. However,
    58  // for the moment we are not targeting other languages than Go on the conode/conode
    59  // communication channel.
    60  
    61  // TODO: Websockets.
    62  // All of this is completely unrelated to HTTPS security on the websocket side. For
    63  // that, we will implement an opt-in Let's Encrypt client in websocket.go.
    64  
    65  // certMaker holds the data necessary to make a certificate on the fly
    66  // and give it to crypto/tls via the GetCertificate and
    67  // GetClientCertificate callbacks in the tls.Config structure.
    68  type certMaker struct {
    69  	si      *ServerIdentity
    70  	suite   Suite
    71  	subj    pkix.Name
    72  	subjDer []byte // the subject encoded in ASN.1 DER format
    73  	k       *ecdsa.PrivateKey
    74  }
    75  
    76  func newCertMaker(s Suite, si *ServerIdentity) (*certMaker, error) {
    77  	cm := &certMaker{
    78  		si:    si,
    79  		suite: s,
    80  	}
    81  
    82  	k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    83  	if err != nil {
    84  		return nil, xerrors.Errorf("key generation: %v", err)
    85  	}
    86  	cm.k = k
    87  
    88  	// This used to be "CommonName: cm.si.Public.String()", which
    89  	// results in the "old style" CommonName encoding in pubFromCN.
    90  	// This worked ok for ed25519 and nist, but not for bn256.g1. See
    91  	// dedis/onet#485.
    92  	cm.subj = pkix.Name{CommonName: pubToCN(cm.si.Public)}
    93  	der, err := asn1.Marshal(cm.subj.CommonName)
    94  	if err != nil {
    95  		return nil, xerrors.Errorf("marshaling: %v", err)
    96  	}
    97  	cm.subjDer = der
    98  	return cm, nil
    99  }
   100  
   101  func (cm *certMaker) getCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
   102  	cert, err := cm.get([]byte(hello.ServerName))
   103  	if err != nil {
   104  		return nil, xerrors.Errorf("certificate: %v", err)
   105  	}
   106  	return cert, nil
   107  }
   108  
   109  func (cm *certMaker) getClientCertificate(req *tls.CertificateRequestInfo) (*tls.Certificate, error) {
   110  	if len(req.AcceptableCAs) == 0 {
   111  		return nil, xerrors.New("server did not provide a nonce in AcceptableCAs")
   112  	}
   113  	cert, err := cm.get(req.AcceptableCAs[0])
   114  	if err != nil {
   115  		return nil, xerrors.Errorf("certififcate: %v", err)
   116  	}
   117  	return cert, nil
   118  }
   119  
   120  func (cm *certMaker) get(nonce []byte) (*tls.Certificate, error) {
   121  	if len(nonce) != nonceSize {
   122  		return nil, xerrors.New("nonce is the wrong size")
   123  	}
   124  
   125  	// Create a signature that proves that:
   126  	// 1. since the nonce was generated by the peer,
   127  	// 2. for this public key,
   128  	// 3. we have control of the private key that is associated with the public
   129  	// key named in the CN.
   130  	//
   131  	// Do this using the same standardized ASN.1 marshaling that x509 uses so
   132  	// that anyone trying to check these signatures themselves in another language
   133  	// will be able to easily do so with their own x509 + kyber implementation.
   134  	buf := bytes.NewBuffer(nonce)
   135  	buf.Write(cm.subjDer)
   136  	sig, err := schnorr.Sign(cm.suite, cm.si.GetPrivate(), buf.Bytes())
   137  	if err != nil {
   138  		return nil, xerrors.Errorf("signature verification: %v", err)
   139  	}
   140  
   141  	// Even though the serial number is not used in the DEDIS signature,
   142  	// we set it to a big random number. This is what TLS clients expect:
   143  	// that two certs from the same issuer with different public keys will
   144  	// have different serial numbers.
   145  	serial := new(big.Int)
   146  	r := random.Bits(128, true, random.New())
   147  	serial.SetBytes(r)
   148  
   149  	tmpl := &x509.Certificate{
   150  		BasicConstraintsValid: true,
   151  		MaxPathLen:            1,
   152  		IsCA:                  false,
   153  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
   154  		NotAfter:              time.Now().Add(2 * time.Hour),
   155  		NotBefore:             time.Now().Add(-5 * time.Minute),
   156  		SerialNumber:          serial,
   157  		SignatureAlgorithm:    x509.ECDSAWithSHA384,
   158  		Subject:               cm.subj,
   159  		ExtraExtensions: []pkix.Extension{
   160  			{
   161  				Id:       oidDedisSig,
   162  				Critical: false,
   163  				Value:    sig,
   164  			},
   165  		},
   166  	}
   167  
   168  	cDer, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, cm.k.Public(), cm.k)
   169  	if err != nil {
   170  		return nil, xerrors.Errorf("certificate: %v", err)
   171  	}
   172  	certs, err := x509.ParseCertificates(cDer)
   173  	if err != nil {
   174  		return nil, xerrors.Errorf("certificate: %v", err)
   175  	}
   176  	if len(certs) < 1 {
   177  		return nil, xerrors.New("no certificate found")
   178  	}
   179  
   180  	return &tls.Certificate{
   181  		PrivateKey:  cm.k,
   182  		Certificate: [][]byte{cDer},
   183  		Leaf:        certs[0],
   184  	}, nil
   185  }
   186  
   187  // See https://github.com/dedis/Coding/tree/master/mib/cothority.mib
   188  var oidDedisSig = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 51281, 1, 1}
   189  
   190  // We want to copy a tls.Config, but it has a sync.Once in it that we
   191  // should not copy. This is ripped from the Go source, where they
   192  // needed to solve the same problem.
   193  //
   194  // See https://github.com/golang/go/issues/12099
   195  func cloneTLSClientConfig(cfg *tls.Config) *tls.Config {
   196  	if cfg == nil {
   197  		return &tls.Config{}
   198  	}
   199  	return &tls.Config{
   200  		Rand:                     cfg.Rand,
   201  		Time:                     cfg.Time,
   202  		Certificates:             cfg.Certificates,
   203  		NameToCertificate:        cfg.NameToCertificate,
   204  		GetCertificate:           cfg.GetCertificate,
   205  		RootCAs:                  cfg.RootCAs,
   206  		NextProtos:               cfg.NextProtos,
   207  		ServerName:               cfg.ServerName,
   208  		ClientAuth:               cfg.ClientAuth,
   209  		ClientCAs:                cfg.ClientCAs,
   210  		InsecureSkipVerify:       cfg.InsecureSkipVerify,
   211  		CipherSuites:             cfg.CipherSuites,
   212  		PreferServerCipherSuites: cfg.PreferServerCipherSuites,
   213  		ClientSessionCache:       cfg.ClientSessionCache,
   214  		MinVersion:               cfg.MinVersion,
   215  		MaxVersion:               cfg.MaxVersion,
   216  		CurvePreferences:         cfg.CurvePreferences,
   217  	}
   218  }
   219  
   220  // NewTLSListener makes a new TCPListener that is configured for TLS.
   221  func NewTLSListener(si *ServerIdentity, suite Suite) (*TCPListener, error) {
   222  	l, err := NewTLSListenerWithListenAddr(si, suite, "")
   223  	if err != nil {
   224  		return nil, xerrors.Errorf("tls listener: %v", err)
   225  	}
   226  	return l, nil
   227  }
   228  
   229  // NewTLSListenerWithListenAddr makes a new TCPListener that is configured
   230  // for TLS and listening on the given address.
   231  // TODO: Why can't we just use NewTCPListener like usual, but detect
   232  // the ConnType from the ServerIdentity?
   233  func NewTLSListenerWithListenAddr(si *ServerIdentity, suite Suite,
   234  	listenAddr string) (*TCPListener, error) {
   235  	tcp, err := NewTCPListenerWithListenAddr(si.Address, suite, listenAddr)
   236  	if err != nil {
   237  		return nil, xerrors.Errorf("tls listener: %v", err)
   238  	}
   239  
   240  	cfg, err := tlsConfig(suite, si)
   241  	if err != nil {
   242  		return nil, xerrors.Errorf("tls config: %v", err)
   243  	}
   244  
   245  	// This callback will be called for every new client, which
   246  	// gives us a chance to set the nonce that will be sent down to them.
   247  	cfg.GetConfigForClient = func(client *tls.ClientHelloInfo) (*tls.Config, error) {
   248  		// Copy the global config, set the nonce in the copy.
   249  		cfg2 := cloneTLSClientConfig(cfg)
   250  
   251  		// Go's TLS server calls cfg.ClientCAs.Subjects() in order to
   252  		// form the data the client will eventually find in
   253  		// AcceptableCAs. So we tunnel our nonce through to there
   254  		// from here.
   255  		cfg2.ClientCAs = x509.NewCertPool()
   256  		vrf, nonce := makeVerifier(suite, nil)
   257  		cfg2.VerifyPeerCertificate = vrf
   258  		cfg2.ClientCAs.AddCert(&x509.Certificate{
   259  			RawSubject: nonce,
   260  		})
   261  		log.Lvl2("Got new connection request from:", client.Conn.RemoteAddr().String())
   262  		return cfg2, nil
   263  	}
   264  
   265  	// This is "any client cert" because we do not want crypto/tls
   266  	// to run Verify. However, since we provide a VerifyPeerCertificate
   267  	// callback, it will still call us.
   268  	cfg.ClientAuth = tls.RequireAnyClientCert
   269  
   270  	tcp.listener = tls.NewListener(tcp.listener, cfg)
   271  	return tcp, nil
   272  }
   273  
   274  // NewTLSAddress returns a new Address that has type TLS with the given
   275  // address addr.
   276  func NewTLSAddress(addr string) Address {
   277  	return NewAddress(TLS, addr)
   278  }
   279  
   280  // This is the prototype expected in tls.Config.VerifyPeerCertificate.
   281  type verifier func(rawCerts [][]byte, vrf [][]*x509.Certificate) (err error)
   282  
   283  // makeVerifier creates the nonce, and also a closure that has access to the nonce
   284  // so that the caller can put the nonce where it needs to go out. When the peer
   285  // gives us a certificate back, crypto/tls calls the verifier with arguments we
   286  // can't control. But the verifier still has access to the nonce because it's in the
   287  // closure.
   288  func makeVerifier(suite Suite, them *ServerIdentity) (verifier, []byte) {
   289  	nonce := mkNonce(suite)
   290  	return func(rawCerts [][]byte, vrf [][]*x509.Certificate) (err error) {
   291  		var cn string
   292  		defer func() {
   293  			if err == nil {
   294  				log.Lvl3("verify cert ->", cn)
   295  			} else {
   296  				log.Lvl3("verify cert ->", err)
   297  			}
   298  		}()
   299  
   300  		if len(rawCerts) != 1 {
   301  			return xerrors.New("expected exactly one certificate")
   302  		}
   303  		certs, err := x509.ParseCertificates(rawCerts[0])
   304  		if err != nil {
   305  			return err
   306  		}
   307  		if len(certs) != 1 {
   308  			return xerrors.New("expected exactly one certificate")
   309  		}
   310  		cert := certs[0]
   311  
   312  		// Check that the certificate is self-signed as expected and not expired.
   313  		self := x509.NewCertPool()
   314  		self.AddCert(cert)
   315  		opts := x509.VerifyOptions{
   316  			Roots: self,
   317  		}
   318  		_, err = cert.Verify(opts)
   319  		if err != nil {
   320  			return xerrors.Errorf("certificate verification: %v", err)
   321  		}
   322  
   323  		// When we know who we are connecting to (e.g. client mode):
   324  		// Check that the CN is the same as the public key.
   325  		if them != nil {
   326  			err = cert.VerifyHostname(pubToCN(them.Public))
   327  			if err != nil {
   328  				return xerrors.Errorf("certificate verification: %v", err)
   329  			}
   330  		}
   331  
   332  		// Check that our extension exists.
   333  		var sig []byte
   334  		for _, x := range cert.Extensions {
   335  			if oidDedisSig.Equal(x.Id) {
   336  				sig = x.Value
   337  				break
   338  			}
   339  		}
   340  		if sig == nil {
   341  			return xerrors.New("DEDIS signature not found")
   342  		}
   343  
   344  		// Check that the DEDIS signature is valid w.r.t. si.Public.
   345  		cn = cert.Subject.CommonName
   346  		pub, err := pubFromCN(suite, cn)
   347  		if err != nil {
   348  			return xerrors.Errorf("decoding key: %v", err)
   349  		}
   350  
   351  		buf := bytes.NewBuffer(nonce)
   352  		subAsn1, err := asn1.Marshal(cn)
   353  		if err != nil {
   354  			return xerrors.Errorf("marshaling: %v", err)
   355  		}
   356  		buf.Write(subAsn1)
   357  		err = schnorr.Verify(suite, pub, buf.Bytes(), sig)
   358  		if err != nil {
   359  			return xerrors.Errorf("certificate verification: %v", err)
   360  		}
   361  
   362  		return nil
   363  	}, nonce
   364  }
   365  
   366  func pubFromCN(suite kyber.Group, cn string) (kyber.Point, error) {
   367  	if len(cn) < 1 {
   368  		return nil, xerrors.New("commonName is missing a type byte")
   369  	}
   370  	tp := cn[0]
   371  
   372  	switch tp {
   373  	case 'Z':
   374  		// New style encoding: unhex and then unmarshal.
   375  		buf, err := hex.DecodeString(cn[1:])
   376  		if err != nil {
   377  			return nil, xerrors.Errorf("decoding key: %v", err)
   378  		}
   379  		r := bytes.NewBuffer(buf)
   380  
   381  		pub := suite.Point()
   382  		_, err = pub.UnmarshalFrom(r)
   383  		if err != nil {
   384  			return nil, xerrors.Errorf("unmarshaling: %v", err)
   385  		}
   386  		return pub, nil
   387  
   388  	default:
   389  		// Old style encoding: simply StringHexToPoint
   390  		pub, err := encoding.StringHexToPoint(suite, cn)
   391  		if err != nil {
   392  			return nil, xerrors.Errorf("encoding key: %v", err)
   393  		}
   394  		return pub, nil
   395  	}
   396  }
   397  
   398  func pubToCN(pub kyber.Point) string {
   399  	w := &bytes.Buffer{}
   400  	pub.MarshalTo(w)
   401  	return "Z" + hex.EncodeToString(w.Bytes())
   402  }
   403  
   404  // tlsConfig returns a generic config that has things set as both the server
   405  // and client need them. The returned config is customized after tlsConfig returns.
   406  func tlsConfig(suite Suite, us *ServerIdentity) (*tls.Config, error) {
   407  	cm, err := newCertMaker(suite, us)
   408  	if err != nil {
   409  		return nil, xerrors.Errorf("certificate: %v", err)
   410  	}
   411  
   412  	return &tls.Config{
   413  		GetCertificate:       cm.getCertificate,
   414  		GetClientCertificate: cm.getClientCertificate,
   415  		// InsecureSkipVerify means that crypto/tls will not be checking
   416  		// the cert for us.
   417  		InsecureSkipVerify: true,
   418  		// Thus, we need to have our own verification function. It
   419  		// needs to be set in the caller, once we know the nonce.
   420  	}, nil
   421  }
   422  
   423  // NewTLSConn will open a TCPConn to the given server over TLS.
   424  // It will check that the remote server has proven
   425  // it holds the given Public key by self-signing a certificate
   426  // linked to that key.
   427  func NewTLSConn(us *ServerIdentity, them *ServerIdentity, suite Suite) (conn *TCPConn, err error) {
   428  	log.Lvl2("NewTLSConn to:", them)
   429  	if them.Address.ConnType() != TLS {
   430  		return nil, xerrors.New("not a tls server")
   431  	}
   432  
   433  	if us.GetPrivate() == nil {
   434  		return nil, xerrors.New("private key is not set")
   435  	}
   436  
   437  	cfg, err := tlsConfig(suite, us)
   438  	if err != nil {
   439  		return nil, xerrors.Errorf("tls config: %v", err)
   440  	}
   441  	vrf, nonce := makeVerifier(suite, them)
   442  	cfg.VerifyPeerCertificate = vrf
   443  
   444  	netAddr := them.Address.NetworkAddress()
   445  	for i := 1; i <= MaxRetryConnect; i++ {
   446  		var c net.Conn
   447  		cfg.ServerName = string(nonce)
   448  		c, err = tls.DialWithDialer(&net.Dialer{Timeout: timeout}, "tcp", netAddr, cfg)
   449  		if err == nil {
   450  			conn = &TCPConn{
   451  				conn:  c,
   452  				suite: suite,
   453  			}
   454  			return
   455  		}
   456  		err = xerrors.Errorf("dial: %v", err)
   457  		if i < MaxRetryConnect {
   458  			time.Sleep(WaitRetry)
   459  		}
   460  	}
   461  	if err == nil {
   462  		err = xerrors.Errorf("timeout: %w", ErrTimeout)
   463  	}
   464  	return
   465  }
   466  
   467  const nonceSize = 256 / 8
   468  
   469  func mkNonce(s Suite) []byte {
   470  	var buf [nonceSize]byte
   471  	random.Bytes(buf[:], s.RandomStream())
   472  	// In order for the nonce to safely pass through cfg.ServerName,
   473  	// it needs to avoid the characters , [ ] and %.
   474  	for bytes.ContainsAny(buf[:], ".[]%") {
   475  		random.Bytes(buf[:], s.RandomStream())
   476  	}
   477  	return buf[:]
   478  }