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 }