gitee.com/lh-her-team/common@v1.5.1/crypto/tls/gm_handshake_client.go (about) 1 // Copyright 2017 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 5 package tls 6 7 import ( 8 "bytes" 9 "crypto" 10 "crypto/ecdsa" 11 "crypto/rsa" 12 "crypto/subtle" 13 "errors" 14 "fmt" 15 "io" 16 "strconv" 17 "sync/atomic" 18 19 gox509 "crypto/x509" 20 21 "gitee.com/lh-her-team/common/crypto/x509" 22 "github.com/tjfoc/gmsm/sm2" 23 ) 24 25 type clientHandshakeStateGM struct { 26 c *Conn 27 serverHello *serverHelloMsg 28 hello *clientHelloMsg 29 suite *cipherSuite 30 finishedHash finishedHash 31 masterSecret []byte 32 session *ClientSessionState 33 } 34 35 func makeClientHelloGM(config *Config) (*clientHelloMsg, error) { 36 if len(config.ServerName) == 0 && !config.InsecureSkipVerify { 37 return nil, errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config") 38 } 39 nextProtosLength := 0 40 for _, proto := range config.NextProtos { 41 if l := len(proto); l == 0 || l > 255 { 42 return nil, errors.New("tls: invalid NextProtos value") 43 } else { 44 nextProtosLength += 1 + l 45 } 46 } 47 if nextProtosLength > 0xffff { 48 return nil, errors.New("tls: NextProtos values too large") 49 } 50 hello := &clientHelloMsg{ 51 vers: config.GMSupport.GetVersion(), 52 compressionMethods: []uint8{compressionNone}, 53 random: make([]byte, 32), 54 alpnProtocols: config.NextProtos, 55 } 56 possibleCipherSuites := getCipherSuites(config) 57 hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites)) 58 NextCipherSuite: 59 for _, suiteId := range possibleCipherSuites { 60 for _, suite := range config.GMSupport.cipherSuites() { 61 if suite.id != suiteId { 62 continue 63 } 64 hello.cipherSuites = append(hello.cipherSuites, suiteId) 65 continue NextCipherSuite 66 } 67 } 68 _, err := io.ReadFull(config.rand(), hello.random) 69 if err != nil { 70 return nil, errors.New("tls: short read from Rand: " + err.Error()) 71 } 72 return hello, nil 73 } 74 75 // Does the handshake, either a full one or resumes old session. 76 // Requires hs.c, hs.hello, and, optionally, hs.session to be set. 77 func (hs *clientHandshakeStateGM) handshake() error { 78 c := hs.c 79 // send ClientHello 80 if _, err := c.writeRecord(recordTypeHandshake, hs.hello.marshal()); err != nil { 81 return err 82 } 83 msg, err := c.readHandshake() 84 if err != nil { 85 return err 86 } 87 var ok bool 88 if hs.serverHello, ok = msg.(*serverHelloMsg); !ok { 89 c.sendAlert(alertUnexpectedMessage) 90 return unexpectedMessageError(hs.serverHello, msg) 91 } 92 if hs.serverHello.vers != VersionGMSSL { 93 hs.c.sendAlert(alertProtocolVersion) 94 return fmt.Errorf("tls: server selected unsupported protocol version %x, while expecting %x", hs.serverHello.vers, VersionGMSSL) 95 } 96 c.vers = hs.serverHello.vers 97 c.haveVers = true 98 c.in.version = hs.serverHello.vers 99 c.out.version = hs.serverHello.vers 100 if err = hs.pickCipherSuite(); err != nil { 101 return err 102 } 103 isResume, err := hs.processServerHello() 104 if err != nil { 105 return err 106 } 107 hs.finishedHash = newFinishedHashGM(hs.suite) 108 // No signatures of the handshake are needed in a resumption. 109 // Otherwise, in a full handshake, if we don't have any certificates 110 // configured then we will never send a CertificateVerify message and 111 // thus no signatures are needed in that case either. 112 if isResume || (len(c.config.Certificates) == 0 && c.config.GetClientCertificate == nil) { 113 hs.finishedHash.discardHandshakeBuffer() 114 } 115 hs.finishedHash.Write(hs.hello.marshal()) 116 hs.finishedHash.Write(hs.serverHello.marshal()) 117 c.buffering = true 118 if isResume { 119 if err := hs.establishKeys(); err != nil { 120 return err 121 } 122 if err := hs.readSessionTicket(); err != nil { 123 return err 124 } 125 if err := hs.readFinished(c.serverFinished[:]); err != nil { 126 return err 127 } 128 c.clientFinishedIsFirst = false 129 if err := hs.sendFinished(c.clientFinished[:]); err != nil { 130 return err 131 } 132 if _, err := c.flush(); err != nil { 133 return err 134 } 135 } else { 136 if err := hs.doFullHandshake(); err != nil { 137 return err 138 } 139 if err := hs.establishKeys(); err != nil { 140 return err 141 } 142 if err := hs.sendFinished(c.clientFinished[:]); err != nil { 143 return err 144 } 145 if _, err := c.flush(); err != nil { 146 return err 147 } 148 c.clientFinishedIsFirst = true 149 if err := hs.readSessionTicket(); err != nil { 150 return err 151 } 152 if err := hs.readFinished(c.serverFinished[:]); err != nil { 153 return err 154 } 155 } 156 c.ekm = ekmFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random) 157 c.didResume = isResume 158 atomic.StoreUint32(&c.handshakeStatus, 1) 159 return nil 160 } 161 162 func (hs *clientHandshakeStateGM) pickCipherSuite() error { 163 if hs.suite = mutualCipherSuiteGM(hs.hello.cipherSuites, hs.serverHello.cipherSuite); hs.suite == nil { 164 hs.c.sendAlert(alertHandshakeFailure) 165 return errors.New("tls: server chose an unconfigured cipher suite") 166 } 167 hs.c.cipherSuite = hs.suite.id 168 return nil 169 } 170 171 func (hs *clientHandshakeStateGM) doFullHandshake() error { 172 c := hs.c 173 msg, err := c.readHandshake() 174 if err != nil { 175 return err 176 } 177 certMsg, ok := msg.(*certificateMsg) 178 if !ok || len(certMsg.certificates) == 0 { 179 c.sendAlert(alertUnexpectedMessage) 180 return unexpectedMessageError(certMsg, msg) 181 } 182 // mod by syl only one cert 183 // Thanks to dual certificates mechanism, length of certificates in GMT0024 must great than 2 184 if c.config.GMSupport.EncCertEnable { 185 if len(certMsg.certificates) < 2 { 186 c.sendAlert(alertInsufficientSecurity) 187 return fmt.Errorf("tls: length of certificates in GMT0024 must great than 2") 188 } 189 } 190 hs.finishedHash.Write(certMsg.marshal()) 191 if c.handshakes == 0 { 192 // If this is the first handshake on a connection, process and 193 // (optionally) verify the server's certificates. 194 certs := make([]*x509.Certificate, len(certMsg.certificates)) 195 for i, asn1Data := range certMsg.certificates { 196 cert, err := x509.ParseCertificate(asn1Data) 197 if err != nil { 198 c.sendAlert(alertBadCertificate) 199 return errors.New("tls: failed to parse certificate from server: " + err.Error()) 200 } 201 _, ok := cert.PublicKey.ToStandardKey().(*sm2.PublicKey) 202 if !ok { 203 c.sendAlert(alertUnsupportedCertificate) 204 return fmt.Errorf("tls: pubkey type of cert is error, expect sm2.publicKey") 205 } 206 if c.config.GMSupport.EncCertEnable { 207 //cert[0] is for signature while cert[1] is for encipher, refer to GMT0024 208 //check key usage 209 switch i { 210 case 0: 211 if cert.KeyUsage == 0 || (cert.KeyUsage&(gox509.KeyUsageDigitalSignature|cert.KeyUsage&gox509.KeyUsageContentCommitment)) == 0 { 212 c.sendAlert(alertInsufficientSecurity) 213 return fmt.Errorf("tls: the keyusage of cert[0] does not exist or is not for KeyUsageDigitalSignature/KeyUsageContentCommitment, value:%d", cert.KeyUsage) 214 } 215 case len(certs) - 1: 216 if cert.KeyUsage == 0 || (cert.KeyUsage&(gox509.KeyUsageDataEncipherment|gox509.KeyUsageKeyEncipherment|gox509.KeyUsageKeyAgreement)) == 0 { 217 c.sendAlert(alertInsufficientSecurity) 218 return fmt.Errorf("tls: the keyusage of cert[1] does not exist or is not for KeyUsageDataEncipherment/KeyUsageKeyEncipherment/KeyUsageKeyAgreement, value:%d", cert.KeyUsage) 219 } 220 } 221 } 222 certs[i] = cert 223 } 224 if !c.config.InsecureSkipVerify { 225 opts := x509.VerifyOptions{ 226 Roots: c.config.RootCAs, 227 CurrentTime: c.config.time(), 228 DNSName: c.config.ServerName, 229 Intermediates: x509.NewCertPool(), 230 } 231 if opts.Roots == nil { 232 opts.Roots = x509.NewCertPool() 233 } 234 for _, rootca := range getCAs() { 235 opts.Roots.AddCert(rootca) 236 } 237 /** 238 TASSL certificate chain: 239 1. signCert + rootCA + encCert 240 **/ 241 for i, cert := range certs { 242 if c.config.GMSupport.EncCertEnable { 243 if i == 0 || i == len(certs)-1 { 244 c.verifiedChains, err = certs[i].Verify(opts) 245 if err != nil { 246 _ = c.sendAlert(alertBadCertificate) 247 return err 248 } 249 continue 250 } 251 } else { 252 if i == 0 { 253 c.verifiedChains, err = certs[i].Verify(opts) 254 if err != nil { 255 _ = c.sendAlert(alertBadCertificate) 256 return err 257 } 258 continue 259 } 260 } 261 opts.Intermediates.AddCert(cert) 262 } 263 } 264 if c.config.VerifyPeerCertificate != nil { 265 if err := c.config.VerifyPeerCertificate(certMsg.certificates, c.verifiedChains); err != nil { 266 c.sendAlert(alertBadCertificate) 267 return err 268 } 269 } 270 pubKey := certs[0].PublicKey.ToStandardKey() 271 switch pubKey.(type) { 272 case *sm2.PublicKey, *ecdsa.PublicKey, *rsa.PublicKey: 273 break 274 default: 275 c.sendAlert(alertUnsupportedCertificate) 276 return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey) 277 } 278 c.peerCertificates = certs 279 } else { 280 // This is a renegotiation handshake. We require that the 281 // server's identity (i.e. leaf certificate) is unchanged and 282 // thus any previous trust decision is still valid. 283 // 284 // See https://mitls.org/pages/attacks/3SHAKE for the 285 // motivation behind this requirement. 286 if !bytes.Equal(c.peerCertificates[0].Raw, certMsg.certificates[0]) { 287 c.sendAlert(alertBadCertificate) 288 return errors.New("tls: server's identity changed during renegotiation") 289 } 290 } 291 msg, err = c.readHandshake() 292 if err != nil { 293 return err 294 } 295 keyAgreement := hs.suite.ka(c.vers) 296 if ka, ok := keyAgreement.(*eccKeyAgreementGM); ok { 297 if c.config.GMSupport.EncCertEnable { 298 encCert := c.peerCertificates[len(c.peerCertificates)-1] 299 ka.encipherCert = encCert 300 } else { 301 ka.encipherCert = c.peerCertificates[0] 302 } 303 } 304 skx, ok := msg.(*serverKeyExchangeMsg) 305 if ok { 306 hs.finishedHash.Write(skx.marshal()) 307 err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, c.peerCertificates[0], skx) 308 if err != nil { 309 c.sendAlert(alertUnexpectedMessage) 310 return err 311 } 312 msg, err = c.readHandshake() 313 if err != nil { 314 return err 315 } 316 } 317 var chainToSend *Certificate 318 var certRequested bool 319 certReq, ok := msg.(*certificateRequestMsgGM) 320 if ok { 321 certRequested = true 322 hs.finishedHash.Write(certReq.marshal()) 323 if chainToSend, err = hs.getCertificate(certReq); err != nil || chainToSend.Certificate == nil { 324 c.sendAlert(alertInternalError) 325 return err 326 } 327 msg, err = c.readHandshake() 328 if err != nil { 329 return err 330 } 331 } 332 shd, ok := msg.(*serverHelloDoneMsg) 333 if !ok { 334 c.sendAlert(alertUnexpectedMessage) 335 return unexpectedMessageError(shd, msg) 336 } 337 hs.finishedHash.Write(shd.marshal()) 338 // If the server requested a certificate then we have to send a 339 // Certificate message, even if it's empty because we don't have a 340 // certificate to send. 341 if certRequested { 342 certMsg = new(certificateMsg) 343 certMsg.certificates = chainToSend.Certificate 344 hs.finishedHash.Write(certMsg.marshal()) 345 if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil { 346 return err 347 } 348 } 349 var ( 350 preMasterSecret []byte 351 ckx *clientKeyExchangeMsg 352 ) 353 if c.config.GMSupport.EncCertEnable { 354 preMasterSecret, ckx, err = keyAgreement.generateClientKeyExchange(c.config, hs.hello, c.peerCertificates[1]) 355 } else { 356 preMasterSecret, ckx, err = keyAgreement.generateClientKeyExchange(c.config, hs.hello, c.peerCertificates[0]) 357 } 358 if err != nil { 359 c.sendAlert(alertInternalError) 360 return err 361 } 362 if ckx != nil { 363 hs.finishedHash.Write(ckx.marshal()) 364 if _, err := c.writeRecord(recordTypeHandshake, ckx.marshal()); err != nil { 365 return err 366 } 367 } 368 if chainToSend != nil && len(chainToSend.Certificate) > 0 { 369 certVerify := &certificateVerifyMsg{} 370 key, ok := chainToSend.PrivateKey.(crypto.Signer) 371 if !ok { 372 c.sendAlert(alertInternalError) 373 return fmt.Errorf("tls: client certificate private key of type %T does not implement crypto.Signer", chainToSend.PrivateKey) 374 } 375 digest := hs.finishedHash.client.Sum(nil) 376 certVerify.signature, err = key.Sign(c.config.rand(), digest, nil) 377 if err != nil { 378 c.sendAlert(alertInternalError) 379 return err 380 } 381 hs.finishedHash.Write(certVerify.marshal()) 382 if _, err := c.writeRecord(recordTypeHandshake, certVerify.marshal()); err != nil { 383 return err 384 } 385 } 386 hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random) 387 if err := c.config.writeKeyLog(keyLogLabelTLS12, hs.hello.random, hs.masterSecret); err != nil { 388 c.sendAlert(alertInternalError) 389 return errors.New("tls: failed to write to key log: " + err.Error()) 390 } 391 hs.finishedHash.discardHandshakeBuffer() 392 return nil 393 } 394 395 func (hs *clientHandshakeStateGM) establishKeys() error { 396 c := hs.c 397 clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := 398 keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) 399 var clientCipher, serverCipher interface{} 400 var clientHash, serverHash macFunction 401 if hs.suite.cipher != nil { 402 clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */) 403 clientHash = hs.suite.mac(c.vers, clientMAC) 404 serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */) 405 serverHash = hs.suite.mac(c.vers, serverMAC) 406 } else { 407 clientCipher = hs.suite.aead(clientKey, clientIV) 408 serverCipher = hs.suite.aead(serverKey, serverIV) 409 } 410 c.in.prepareCipherSpec(c.vers, serverCipher, serverHash) 411 c.out.prepareCipherSpec(c.vers, clientCipher, clientHash) 412 return nil 413 } 414 415 func (hs *clientHandshakeStateGM) serverResumedSession() bool { 416 // If the server responded with the same sessionId then it means the 417 // sessionTicket is being used to resume a TLS session. 418 return hs.session != nil && hs.hello.sessionId != nil && 419 bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId) 420 } 421 422 func (hs *clientHandshakeStateGM) processServerHello() (bool, error) { 423 c := hs.c 424 if hs.serverHello.compressionMethod != compressionNone { 425 c.sendAlert(alertUnexpectedMessage) 426 return false, errors.New("tls: server selected unsupported compression format") 427 } 428 if c.handshakes == 0 && hs.serverHello.secureRenegotiationSupported { 429 c.secureRenegotiation = true 430 if len(hs.serverHello.secureRenegotiation) != 0 { 431 c.sendAlert(alertHandshakeFailure) 432 return false, errors.New("tls: initial handshake had non-empty renegotiation extension") 433 } 434 } 435 if c.handshakes > 0 && c.secureRenegotiation { 436 var expectedSecureRenegotiation [24]byte 437 copy(expectedSecureRenegotiation[:], c.clientFinished[:]) 438 copy(expectedSecureRenegotiation[12:], c.serverFinished[:]) 439 if !bytes.Equal(hs.serverHello.secureRenegotiation, expectedSecureRenegotiation[:]) { 440 c.sendAlert(alertHandshakeFailure) 441 return false, errors.New("tls: incorrect renegotiation extension contents") 442 } 443 } 444 clientDidALPN := len(hs.hello.alpnProtocols) > 0 445 serverHasALPN := len(hs.serverHello.alpnProtocol) > 0 446 if !clientDidALPN && serverHasALPN { 447 c.sendAlert(alertHandshakeFailure) 448 return false, errors.New("tls: server advertised unrequested ALPN extension") 449 } 450 if serverHasALPN { 451 c.clientProtocol = hs.serverHello.alpnProtocol 452 c.clientProtocolFallback = false 453 } 454 c.scts = hs.serverHello.scts 455 if !hs.serverResumedSession() { 456 return false, nil 457 } 458 if hs.session.vers != c.vers { 459 c.sendAlert(alertHandshakeFailure) 460 return false, errors.New("tls: server resumed a session with a different version") 461 } 462 if hs.session.cipherSuite != hs.suite.id { 463 c.sendAlert(alertHandshakeFailure) 464 return false, errors.New("tls: server resumed a session with a different cipher suite") 465 } 466 // Restore masterSecret and peerCerts from previous state 467 hs.masterSecret = hs.session.masterSecret 468 c.peerCertificates = hs.session.serverCertificates 469 c.verifiedChains = hs.session.verifiedChains 470 return true, nil 471 } 472 473 func (hs *clientHandshakeStateGM) readFinished(out []byte) error { 474 c := hs.c 475 if err := c.readChangeCipherSpec(); err != nil { 476 return err 477 } 478 msg, err := c.readHandshake() 479 if err != nil { 480 return err 481 } 482 serverFinished, ok := msg.(*finishedMsg) 483 if !ok { 484 c.sendAlert(alertUnexpectedMessage) 485 return unexpectedMessageError(serverFinished, msg) 486 } 487 verify := hs.finishedHash.serverSum(hs.masterSecret) 488 if len(verify) != len(serverFinished.verifyData) || 489 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 { 490 c.sendAlert(alertHandshakeFailure) 491 return errors.New("tls: server's Finished message was incorrect") 492 } 493 hs.finishedHash.Write(serverFinished.marshal()) 494 copy(out, verify) 495 return nil 496 } 497 498 func (hs *clientHandshakeStateGM) readSessionTicket() error { 499 if !hs.serverHello.ticketSupported { 500 return nil 501 } 502 c := hs.c 503 msg, err := c.readHandshake() 504 if err != nil { 505 return err 506 } 507 sessionTicketMsg, ok := msg.(*newSessionTicketMsg) 508 if !ok { 509 c.sendAlert(alertUnexpectedMessage) 510 return unexpectedMessageError(sessionTicketMsg, msg) 511 } 512 hs.finishedHash.Write(sessionTicketMsg.marshal()) 513 hs.session = &ClientSessionState{ 514 sessionTicket: sessionTicketMsg.ticket, 515 vers: c.vers, 516 cipherSuite: hs.suite.id, 517 masterSecret: hs.masterSecret, 518 serverCertificates: c.peerCertificates, 519 verifiedChains: c.verifiedChains, 520 } 521 return nil 522 } 523 524 func (hs *clientHandshakeStateGM) sendFinished(out []byte) error { 525 c := hs.c 526 if _, err := c.writeRecord(recordTypeChangeCipherSpec, []byte{1}); err != nil { 527 return err 528 } 529 finished := new(finishedMsg) 530 finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret) 531 hs.finishedHash.Write(finished.marshal()) 532 if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil { 533 return err 534 } 535 copy(out, finished.verifyData) 536 return nil 537 } 538 539 func (hs *clientHandshakeStateGM) getCertificate(certReq *certificateRequestMsgGM) (*Certificate, error) { 540 c := hs.c 541 chainToSend := new(Certificate) 542 if c.config.GetClientCertificate != nil { 543 var signatureSchemes []SignatureScheme 544 return c.config.GetClientCertificate(&CertificateRequestInfo{ 545 AcceptableCAs: certReq.certificateAuthorities, 546 SignatureSchemes: signatureSchemes, 547 }) 548 } 549 // RFC 4346 on the certificateAuthorities field: A list of the 550 // distinguished names of acceptable certificate authorities. 551 // These distinguished names may specify a desired 552 // distinguished name for a root CA or for a subordinate CA; 553 // thus, this message can be used to describe both known roots 554 // and a desired authorization space. If the 555 // certificate_authorities list is empty then the client MAY 556 // send any certificate of the appropriate 557 // ClientCertificateType, unless there is some external 558 // arrangement to the contrary. 559 560 // We need to search our list of client certs for one 561 // where SignatureAlgorithm is acceptable to the server and the 562 // Issuer is in certReq.certificateAuthorities 563 findCert: 564 for i, chain := range c.config.Certificates { 565 for j, cert := range chain.Certificate { 566 x509Cert := chain.Leaf 567 // parse the certificate if this isn't the leaf 568 // node, or if chain.Leaf was nil 569 if j != 0 || x509Cert == nil { 570 var err error 571 cmCert, err := x509.ParseCertificate(cert) 572 if err != nil { 573 c.sendAlert(alertInternalError) 574 return nil, errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error()) 575 } 576 x509Cert, err = x509.HerbtCertToX509Cert(cmCert) 577 if err != nil { 578 c.sendAlert(alertInternalError) 579 return nil, errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error()) 580 } 581 } 582 var isGMCert bool 583 if x509Cert.PublicKeyAlgorithm == gox509.ECDSA { 584 pubKey, ok := x509Cert.PublicKey.(*ecdsa.PublicKey) 585 if ok && pubKey.Curve == sm2.P256Sm2() { 586 isGMCert = true 587 } 588 if _, ok = x509Cert.PublicKey.(*sm2.PublicKey); ok { 589 isGMCert = true 590 } 591 } 592 if !isGMCert { 593 continue findCert 594 } 595 if len(certReq.certificateAuthorities) == 0 { 596 // they gave us an empty list, so just take the 597 // first cert from c.config.Certificates 598 // return &chain, nil 599 if chainToSend.Certificate == nil { 600 chainToSend.Certificate = chain.Certificate 601 chainToSend.PrivateKey = chain.PrivateKey 602 } else { 603 chainToSend.Certificate = append(chainToSend.Certificate, chain.Certificate...) 604 } 605 } 606 for _, ca := range certReq.certificateAuthorities { 607 if bytes.Equal(x509Cert.RawIssuer, ca) { 608 // return &chain, nil 609 if chainToSend.Certificate == nil { 610 chainToSend.Certificate = chain.Certificate 611 chainToSend.PrivateKey = chain.PrivateKey 612 } else { 613 chainToSend.Certificate = append(chainToSend.Certificate, chain.Certificate...) 614 } 615 } 616 } 617 } 618 } 619 // No acceptable certificate found. Don't send a certificate. 620 // return new(Certificate), nil 621 return chainToSend, nil 622 }