github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/gmtls/handshake_client.go (about) 1 // Copyright (c) 2022 zhaochun 2 // gmgo is licensed under Mulan PSL v2. 3 // You can use this software according to the terms and conditions of the Mulan PSL v2. 4 // You may obtain a copy of Mulan PSL v2 at: 5 // http://license.coscl.org.cn/MulanPSL2 6 // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 7 // See the Mulan PSL v2 for more details. 8 9 /* 10 gmtls是基于`golang/go`的`tls`包实现的国密改造版本。 11 对应版权声明: thrid_licenses/github.com/golang/go/LICENSE 12 */ 13 14 package gmtls 15 16 import ( 17 "bytes" 18 "context" 19 "crypto" 20 "crypto/ecdsa" 21 "crypto/ed25519" 22 "crypto/rsa" 23 "crypto/subtle" 24 "errors" 25 "fmt" 26 "hash" 27 "io" 28 "net" 29 "strings" 30 "sync/atomic" 31 "time" 32 33 "gitee.com/zhaochuninhefei/zcgolog/zclog" 34 "github.com/hxx258456/ccgo/sm2" 35 "github.com/hxx258456/ccgo/x509" 36 ) 37 38 type clientHandshakeState struct { 39 c *Conn 40 ctx context.Context 41 serverHello *serverHelloMsg 42 hello *clientHelloMsg 43 suite *cipherSuite 44 finishedHash finishedHash 45 masterSecret []byte 46 session *ClientSessionState 47 } 48 49 // 生成ClientHello 50 func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) { 51 config := c.config 52 if len(config.ServerName) == 0 && !config.InsecureSkipVerify { 53 // 如果没有指定 InsecureSkipVerify 那么就必须设置 ServerName 54 return nil, nil, errors.New("gmtls: either ServerName or InsecureSkipVerify must be specified in the tls.Config") 55 } 56 57 nextProtosLength := 0 58 for _, proto := range config.NextProtos { 59 if l := len(proto); l == 0 || l > 255 { 60 return nil, nil, errors.New("gmtls: invalid NextProtos value") 61 } else { 62 nextProtosLength += 1 + l 63 } 64 } 65 if nextProtosLength > 0xffff { 66 return nil, nil, errors.New("gmtls: NextProtos values too large") 67 } 68 // 获取客户端支持的tls协议版本列表,tls1.3使用该扩展信息 69 supportedVersions := config.supportedVersions() 70 if len(supportedVersions) == 0 { 71 return nil, nil, errors.New("gmtls: no supported versions satisfy MinVersion and MaxVersion") 72 } 73 // 获取客户端支持的最高版本tls协议,tls1.2及以前的版本使用该属性 74 clientHelloVersion := config.maxSupportedVersion() 75 // 出于兼容性原因,ClientHello 开头的版本上限为 TLS 1.2。 76 // 对于更高的tls1.3版本,使用 supported_versions 扩展。 77 // See RFC 8446, Section 4.2.1. 78 if clientHelloVersion > VersionTLS12 { 79 clientHelloVersion = VersionTLS12 80 } 81 82 hello := &clientHelloMsg{ 83 vers: clientHelloVersion, 84 compressionMethods: []uint8{compressionNone}, // tls1.3不再支持压缩 85 random: make([]byte, 32), 86 sessionId: make([]byte, 32), 87 ocspStapling: true, 88 scts: true, 89 serverName: hostnameInSNI(config.ServerName), // 服务端域名,使用DNS域名即可 90 supportedCurves: config.curvePreferences(), // 支持的曲线ID 91 supportedPoints: []uint8{pointFormatUncompressed}, // 曲线上的点坐标序列化时不压缩 92 secureRenegotiationSupported: true, // 是否支持安全重协商 93 alpnProtocols: config.NextProtos, // ALPN协议列表 94 supportedVersions: supportedVersions, // 客户端支持的tls协议版本列表 95 } 96 // 如果不是第一次握手,将上次握手时客户端发送的Finished消息作为 安全重协商 字段。 97 if c.handshakes > 0 { 98 hello.secureRenegotiation = c.clientFinished[:] 99 } 100 // 预置的tls1.0-1.2密码学套件列表 101 preferenceOrder := cipherSuitesPreferenceOrder 102 if !hasAESGCMHardwareSupport { 103 preferenceOrder = cipherSuitesPreferenceOrderNoAES 104 } 105 // 配置要求的tls1.0-1.2密码学套件列表 106 configCipherSuites := config.cipherSuites() 107 hello.cipherSuites = make([]uint16, 0, len(configCipherSuites)) 108 // 从预置的tls1.0-1.2密码学套件列表中筛选满足配置的密码套件 109 for _, suiteId := range preferenceOrder { 110 suite := mutualCipherSuite(configCipherSuites, suiteId) 111 if suite == nil { 112 continue 113 } 114 // Don't advertise TLS 1.2-only cipher suites unless 115 // we're attempting TLS 1.2. 116 if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 { 117 continue 118 } 119 // 将筛选出的密码套件加入hello消息的密码套件列表 120 hello.cipherSuites = append(hello.cipherSuites, suiteId) 121 } 122 // 填充客户端随机数 123 _, err := io.ReadFull(config.rand(), hello.random) 124 if err != nil { 125 return nil, nil, errors.New("gmtls: short read from Rand: " + err.Error()) 126 } 127 128 // A random session ID is used to detect when the server accepted a ticket 129 // and is resuming a session (see RFC 5077). In TLS 1.3, it's always set as 130 // a compatibility measure (see RFC 8446, Section 4.1.2). 131 if _, err := io.ReadFull(config.rand(), hello.sessionId); err != nil { 132 return nil, nil, errors.New("gmtls: short read from Rand: " + err.Error()) 133 } 134 // tls1.2以上版本需要传输支持的签名算法 135 // GMSSL也需要传输支持的签名算法 136 if hello.vers >= VersionTLS12 || hello.vers == VersionGMSSL { 137 hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms 138 } 139 140 // 对于TLS1.3,需要额外传输一些扩展信息 141 var params ecdheParameters 142 if hello.supportedVersions[0] == VersionTLS13 || hello.supportedVersions[0] == VersionGMSSL { 143 // 在密码套件中加入tls1.3的密码套件 144 // tls1.3的密码套件是固定的,不允许客户端自行配置选择 145 if hasAESGCMHardwareSupport { 146 hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13...) 147 } else { 148 hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13NoAES...) 149 } 150 // 设置密钥协商的曲线为配置的首个曲线,目前默认是sm2P256 151 curveID := config.curvePreferences()[0] 152 // var curve elliptic.Curve 153 var curveOk bool 154 var curveName string 155 if curveName, curveOk = CheckCurveNameById(curveID); !curveOk { 156 return nil, nil, errors.New("gmtls: CurvePreferences includes unsupported curve") 157 } 158 // 生成ecdheParameters 159 params, err = generateECDHEParameters(config.rand(), curveID) 160 if err != nil { 161 return nil, nil, err 162 } 163 zclog.Debugf("===== 客户端基于曲线 %s 生成密钥交换算法参数\n", curveName) 164 // 将曲线ID与客户端公钥设置为ClientHello中的密钥交换算法参数 165 hello.keyShares = []keyShare{{group: curveID, data: params.PublicKey()}} 166 } 167 168 return hello, params, nil 169 } 170 171 // 客户端握手 172 func (c *Conn) clientHandshake(ctx context.Context) (err error) { 173 zclog.Debug("===== 开始客户端握手过程") 174 if c.config == nil { 175 c.config = defaultConfig() 176 } 177 178 // This may be a renegotiation handshake, in which case some fields 179 // need to be reset. 180 c.didResume = false 181 // 生成ClientHello消息: tls协议版本列表,密码套件列表,客户端密钥交换算法参数等 182 hello, ecdheParams, err := c.makeClientHello() 183 if err != nil { 184 return err 185 } 186 // 确保连接的serverName与ClientHello中的serverName相同 187 c.serverName = hello.serverName 188 // 尝试从当前连接中获取会话恢复信息 189 cacheKey, session, earlySecret, binderKey := c.loadSession(hello) 190 if cacheKey != "" && session != nil { 191 // 如果尝试会话恢复,那么在会话恢复发生错误时要删除客户端的该会话缓存 192 defer func() { 193 // If we got a handshake failure when resuming a session, throw away 194 // the session ticket. See RFC 5077, Section 3.2. 195 // 196 // RFC 8446 makes no mention of dropping tickets on failure, but it 197 // does require servers to abort on invalid binders, so we need to 198 // delete tickets to recover from a corrupted PSK. 199 if err != nil { 200 c.config.ClientSessionCache.Put(cacheKey, nil) 201 } 202 }() 203 } 204 // 向连接写入ClientHello 205 zclog.Debug("===== 客户端发出ClientHello") 206 if _, err := c.writeRecord(recordTypeHandshake, hello.marshal()); err != nil { 207 return err 208 } 209 // 从连接读取ServerHello 210 msg, err := c.readHandshake() 211 if err != nil { 212 return err 213 } 214 serverHello, ok := msg.(*serverHelloMsg) 215 if !ok { 216 _ = c.sendAlert(alertUnexpectedMessage) 217 return unexpectedMessageError(serverHello, msg) 218 } 219 zclog.Debug("===== 客户端读取到ServerHello") 220 // 协商tls版本 221 if err := c.pickTLSVersion(serverHello); err != nil { 222 return err 223 } 224 // If we are negotiating a protocol version that's lower than what we 225 // support, check for the server downgrade canaries. 226 // See RFC 8446, Section 4.1.3. 227 maxVers := c.config.maxSupportedVersion() 228 tls12Downgrade := string(serverHello.random[24:]) == downgradeCanaryTLS12 229 tls11Downgrade := string(serverHello.random[24:]) == downgradeCanaryTLS11 230 if maxVers == VersionTLS13 && c.vers <= VersionTLS12 && (tls12Downgrade || tls11Downgrade) || 231 maxVers == VersionTLS12 && c.vers <= VersionTLS11 && tls11Downgrade { 232 _ = c.sendAlert(alertIllegalParameter) 233 return errors.New("gmtls: downgrade attempt detected, possibly due to a MitM attack or a broken middlebox") 234 } 235 // GMSSL目前采用与tls1.3相同的处理 236 if c.vers == VersionTLS13 || c.vers == VersionGMSSL { 237 zclog.Debug("===== 客户端执行tls1.3或gmlssl协议的握手过程") 238 hs := &clientHandshakeStateTLS13{ 239 c: c, 240 ctx: ctx, 241 serverHello: serverHello, 242 hello: hello, 243 ecdheParams: ecdheParams, 244 session: session, 245 earlySecret: earlySecret, 246 binderKey: binderKey, 247 } 248 // tls1.3的握手过程在收到ServerHello之后与tls1.2不同,这里走不同的分支处理 249 // In TLS 1.3, session tickets are delivered after the handshake. 250 return hs.handshake() 251 } 252 zclog.Debug("===== 客户端执行tls1.2或更老版本的握手过程") 253 hs := &clientHandshakeState{ 254 c: c, 255 ctx: ctx, 256 serverHello: serverHello, 257 hello: hello, 258 session: session, 259 } 260 261 if err := hs.handshake(); err != nil { 262 return err 263 } 264 265 // If we had a successful handshake and hs.session is different from 266 // the one already cached - cache a new one. 267 if cacheKey != "" && hs.session != nil && session != hs.session { 268 c.config.ClientSessionCache.Put(cacheKey, hs.session) 269 } 270 271 return nil 272 } 273 274 // 从连接中获取会话恢复信息。 275 // 276 // 对于tls1.3,如果有可用的缓存会话,则会返回以下字段: 277 // - cacheKey 缓存会话key,值是服务端ServerName或ip地址 278 // - session 想要恢复的缓存会话 279 // - earlySecret 早期密钥,由session的主密钥扩展提炼而来 280 // - binderKey 绑定者密钥,由早期密钥派生而来 281 // 此外,还会在ClientHello中设置以下字段: 282 // - ticketSupported true,支持使用会话票据 283 // - pskModes 指定使用DHE密钥交换算法模式 284 // - pskIdentities 请求恢复的pskID集合,事实上只有一条pskid 285 // - pskBinders psk绑定者的散列信息 286 func (c *Conn) loadSession(hello *clientHelloMsg) (cacheKey string, 287 session *ClientSessionState, earlySecret, binderKey []byte) { 288 // 检查是否支持会话恢复 289 if c.config.SessionTicketsDisabled || c.config.ClientSessionCache == nil { 290 return "", nil, nil, nil 291 } 292 // 设置支持使用会话票据 293 hello.ticketSupported = true 294 // 检查tls最高版本是否tls1.3 或 GMSSL 295 if hello.supportedVersions[0] == VersionTLS13 || hello.supportedVersions[0] == VersionGMSSL { 296 // tls1.3开始,psk使用DHE算法模式。 297 // Require DHE on resumption as it guarantees forward secrecy against 298 // compromise of the session ticket key. See RFC 8446, Section 4.2.9. 299 hello.pskModes = []uint8{pskModeDHE} 300 } 301 // TODO: 疑惑: 握手次数非0,代表发生过重新协商?允许重新协商就不允许会话恢复? 302 // 但首次握手成功后,握手次数就是1了啊,这不会导致永远无法启用会话恢复? 303 // 感觉应该是 "c.handshakes > 1" ? 304 // Session resumption is not allowed if renegotiating because 305 // renegotiation is primarily used to allow a client to send a client 306 // certificate, which would be skipped if session resumption occurred. 307 if c.handshakes != 0 { 308 return "", nil, nil, nil 309 } 310 // 根据连接的servername或serverAddr获取对应的会话缓存 311 // Try to resume a previously negotiated TLS session, if available. 312 cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config) 313 session, ok := c.config.ClientSessionCache.Get(cacheKey) 314 if !ok || session == nil { 315 return cacheKey, nil, nil, nil 316 } 317 // 检查之前缓存的会话与本次ClientHello的tls版本是否匹配 318 // Check that version used for the previous session is still valid. 319 versOk := false 320 for _, v := range hello.supportedVersions { 321 if v == session.vers { 322 versOk = true 323 break 324 } 325 } 326 if !versOk { 327 return cacheKey, nil, nil, nil 328 } 329 // 检查缓存会话的服务端子证书的过期时间与域名 330 // Check that the cached server certificate is not expired, and that it's 331 // valid for the ServerName. This should be ensured by the cache key, but 332 // protect the application from a faulty ClientSessionCache implementation. 333 if !c.config.InsecureSkipVerify { 334 if len(session.verifiedChains) == 0 { 335 // The original connection had InsecureSkipVerify, while this doesn't. 336 return cacheKey, nil, nil, nil 337 } 338 serverCert := session.serverCertificates[0] 339 if c.config.time().After(serverCert.NotAfter) { 340 // Expired certificate, delete the entry. 341 c.config.ClientSessionCache.Put(cacheKey, nil) 342 return cacheKey, nil, nil, nil 343 } 344 if err := serverCert.VerifyHostname(c.config.ServerName); err != nil { 345 return cacheKey, nil, nil, nil 346 } 347 } 348 349 if session.vers != VersionTLS13 && session.vers != VersionGMSSL { 350 // In TLS 1.2 the cipher suite must match the resumed session. Ensure we 351 // are still offering it. 352 if mutualCipherSuite(hello.cipherSuites, session.cipherSuite) == nil { 353 return cacheKey, nil, nil, nil 354 } 355 // 对于tls1.2及之前的版本,如果密码套件匹配,则直接将缓存会话票据设置到ClientHello中。 356 hello.sessionTicket = session.sessionTicket 357 return 358 } 359 // 检查缓存的会话是否已经过期 360 // Check that the session ticket is not expired. 361 if c.config.time().After(session.useBy) { 362 c.config.ClientSessionCache.Put(cacheKey, nil) 363 return cacheKey, nil, nil, nil 364 } 365 // 获取缓存会话的密码套件 366 // In TLS 1.3 the KDF hash must match the resumed session. Ensure we 367 // offer at least one cipher suite with that hash. 368 cipherSuite := cipherSuiteTLS13ByID(session.cipherSuite) 369 if cipherSuite == nil { 370 return cacheKey, nil, nil, nil 371 } 372 // 检查缓存会话的密码套件是否与当前ClientHello支持的密码套件匹配 373 cipherSuiteOk := false 374 for _, offeredID := range hello.cipherSuites { 375 offeredSuite := cipherSuiteTLS13ByID(offeredID) 376 if offeredSuite != nil && offeredSuite.hash == cipherSuite.hash { 377 cipherSuiteOk = true 378 break 379 } 380 } 381 if !cipherSuiteOk { 382 return cacheKey, nil, nil, nil 383 } 384 // 设置psk扩展信息 385 // Set the pre_shared_key extension. See RFC 8446, Section 4.2.11.1. 386 // 票据年龄 : 会话获取时间到当前时间的毫秒数 387 ticketAge := uint32(c.config.time().Sub(session.receivedAt) / time.Millisecond) 388 // 会话的pskID 389 identity := pskIdentity{ 390 label: session.sessionTicket, 391 obfuscatedTicketAge: ticketAge + session.ageAdd, 392 } 393 // 设置到ClientHello的 pskIdentities 394 hello.pskIdentities = []pskIdentity{identity} 395 // 计算pskBinders 396 hello.pskBinders = [][]byte{make([]byte, cipherSuite.hash.Size())} 397 // Compute the PSK binders. See RFC 8446, Section 4.2.11.2. 398 // 根据会话的主密钥扩展出psk(pre-shared-key) 399 psk := cipherSuite.expandLabel(session.masterSecret, "resumption", 400 session.nonce, cipherSuite.hash.Size()) 401 // 再用psk提炼早期密钥 402 earlySecret = cipherSuite.extract(psk, nil) 403 // 根据早期密钥派生绑定者密钥 404 binderKey = cipherSuite.deriveSecret(earlySecret, resumptionBinderLabel, nil) 405 // 声明一个转录散列函数 406 transcript := cipherSuite.hash.New() 407 // 向转录散列写入不带pskBinders的ClientHello 408 transcript.Write(hello.marshalWithoutBinders()) 409 // 生成pskBinders: 使用绑定者密钥和转录散列生成的Finished消息散列 410 pskBinders := [][]byte{cipherSuite.finishedHash(binderKey, transcript)} 411 // 将 pskBinders 设置到ClientHello 412 hello.updateBinders(pskBinders) 413 414 return 415 } 416 417 // 选取本次tls通信的版本 418 func (c *Conn) pickTLSVersion(serverHello *serverHelloMsg) error { 419 peerVersion := serverHello.vers 420 if serverHello.supportedVersion != 0 { 421 peerVersion = serverHello.supportedVersion 422 } 423 // 按优先顺序匹配协议版本 424 vers, ok := c.config.mutualVersion([]uint16{peerVersion}) 425 if !ok { 426 _ = c.sendAlert(alertProtocolVersion) 427 return fmt.Errorf("gmtls: server selected unsupported protocol version %x", peerVersion) 428 } 429 // 将协商好的版本设置到tls连接中 430 c.vers = vers 431 c.haveVers = true 432 c.in.version = vers 433 c.out.version = vers 434 zclog.Debugln("===== gmtls/handshake_client.go pickTLSVersion 客户端确认本次tls连接使用的版本是:", ShowTLSVersion(int(c.vers))) 435 436 return nil 437 } 438 439 // tls1.2及更老版本在接收到 ServerHello 之后的握手过程。 440 // Does the handshake, either a full one or resumes old session. Requires hs.c, 441 // hs.hello, hs.serverHello, and, optionally, hs.session to be set. 442 func (hs *clientHandshakeState) handshake() error { 443 c := hs.c 444 // 处理 ServerHello 445 isResume, err := hs.processServerHello() 446 if err != nil { 447 return err 448 } 449 450 hs.finishedHash = newFinishedHash(c.vers, hs.suite) 451 452 // No signatures of the handshake are needed in a resumption. 453 // Otherwise, in a full handshake, if we don't have any certificates 454 // configured then we will never send a CertificateVerify message and 455 // thus no signatures are needed in that case either. 456 if isResume || (len(c.config.Certificates) == 0 && c.config.GetClientCertificate == nil) { 457 hs.finishedHash.discardHandshakeBuffer() 458 } 459 460 _, _ = hs.finishedHash.Write(hs.hello.marshal()) 461 _, _ = hs.finishedHash.Write(hs.serverHello.marshal()) 462 463 c.buffering = true 464 c.didResume = isResume 465 if isResume { 466 // 会话恢复处理 467 if err := hs.establishKeys(); err != nil { 468 return err 469 } 470 if err := hs.readSessionTicket(); err != nil { 471 return err 472 } 473 if err := hs.readFinished(c.serverFinished[:]); err != nil { 474 return err 475 } 476 c.clientFinishedIsFirst = false 477 // Make sure the connection is still being verified whether or not this 478 // is a resumption. Resumptions currently don't reverify certificates so 479 // they don't call verifyServerCertificate. See Issue 31641. 480 if c.config.VerifyConnection != nil { 481 if err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil { 482 _ = c.sendAlert(alertBadCertificate) 483 return err 484 } 485 } 486 if err := hs.sendFinished(c.clientFinished[:]); err != nil { 487 return err 488 } 489 if _, err := c.flush(); err != nil { 490 return err 491 } 492 } else { 493 // 非会话恢复,执行完整的握手过程 494 if err := hs.doFullHandshake(); err != nil { 495 return err 496 } 497 // 生成会话密钥 498 if err := hs.establishKeys(); err != nil { 499 return err 500 } 501 // 发送 ClientFinished 502 if err := hs.sendFinished(c.clientFinished[:]); err != nil { 503 return err 504 } 505 if _, err := c.flush(); err != nil { 506 return err 507 } 508 c.clientFinishedIsFirst = true 509 if err := hs.readSessionTicket(); err != nil { 510 return err 511 } 512 if err := hs.readFinished(c.serverFinished[:]); err != nil { 513 return err 514 } 515 } 516 517 c.ekm = ekmFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random) 518 atomic.StoreUint32(&c.handshakeStatus, 1) 519 520 return nil 521 } 522 523 // 客户端确认协商好的密码套件(tls1.2) 524 func (hs *clientHandshakeState) pickCipherSuite() error { 525 if hs.suite = mutualCipherSuite(hs.hello.cipherSuites, hs.serverHello.cipherSuite); hs.suite == nil { 526 _ = hs.c.sendAlert(alertHandshakeFailure) 527 return errors.New("gmtls: server chose an unconfigured cipher suite") 528 } 529 hs.c.cipherSuite = hs.suite.id 530 zclog.Debugf("===== 客户端确认协商好的密码套件: %s", CipherSuiteName(hs.suite.id)) 531 return nil 532 } 533 534 // tls1.2非会话恢复时的完整握手过程 535 func (hs *clientHandshakeState) doFullHandshake() error { 536 c := hs.c 537 // 读取 certificateMsg 服务端证书 538 msg, err := c.readHandshake() 539 if err != nil { 540 return err 541 } 542 certMsg, ok := msg.(*certificateMsg) 543 if !ok || len(certMsg.certificates) == 0 { 544 _ = c.sendAlert(alertUnexpectedMessage) 545 return unexpectedMessageError(certMsg, msg) 546 } 547 zclog.Debug("===== 客户端读取到服务端证书 certificateMsg") 548 _, _ = hs.finishedHash.Write(certMsg.marshal()) 549 550 msg, err = c.readHandshake() 551 if err != nil { 552 return err 553 } 554 555 cs, ok := msg.(*certificateStatusMsg) 556 if ok { 557 zclog.Debug("===== 客户端读取到 certificateStatusMsg") 558 // RFC4366 on Certificate Status Request: 559 // The server MAY return a "certificate_status" message. 560 561 if !hs.serverHello.ocspStapling { 562 // If a server returns a "CertificateStatus" message, then the 563 // server MUST have included an extension of type "status_request" 564 // with empty "extension_data" in the extended server hello. 565 566 _ = c.sendAlert(alertUnexpectedMessage) 567 return errors.New("gmtls: received unexpected CertificateStatus message") 568 } 569 _, _ = hs.finishedHash.Write(cs.marshal()) 570 // certificateStatusMsg 返回的是服务端装订的ocsp信息 571 c.ocspResponse = cs.response 572 573 msg, err = c.readHandshake() 574 if err != nil { 575 return err 576 } 577 } 578 579 if c.handshakes == 0 { 580 // 首次握手时验证服务端证书,成功时会将服务端证书塞到客户端的对方证书字段peerCertificates中 581 // If this is the first handshake on a connection, process and 582 // (optionally) verify the server's certificates. 583 if err := c.verifyServerCertificate(certMsg.certificates); err != nil { 584 return err 585 } 586 } else { 587 // 不是首次握手时,只需比较接收到的服务端证书是否还是之前验证过的服务端证书即可。 588 // This is a renegotiation handshake. We require that the 589 // server's identity (i.e. leaf certificate) is unchanged and 590 // thus any previous trust decision is still valid. 591 // 592 // See https://mitls.org/pages/attacks/3SHAKE for the 593 // motivation behind this requirement. 594 if !bytes.Equal(c.peerCertificates[0].Raw, certMsg.certificates[0]) { 595 _ = c.sendAlert(alertBadCertificate) 596 return errors.New("gmtls: server's identity changed during renegotiation") 597 } 598 } 599 // 根据具体的密码套件执行其密钥交换算法,计算密钥交换参数 600 keyAgreement := hs.suite.ka(c.vers) 601 602 skx, ok := msg.(*serverKeyExchangeMsg) 603 if ok { 604 zclog.Debug("===== 客户端读取到 serverKeyExchangeMsg") 605 _, _ = hs.finishedHash.Write(skx.marshal()) 606 err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, c.peerCertificates[0], skx) 607 if err != nil { 608 _ = c.sendAlert(alertUnexpectedMessage) 609 return err 610 } 611 612 msg, err = c.readHandshake() 613 if err != nil { 614 return err 615 } 616 } 617 618 var chainToSend *Certificate 619 var certRequested bool 620 certReq, ok := msg.(*certificateRequestMsg) 621 if ok { 622 zclog.Debug("===== 客户端读取到 certificateRequestMsg") 623 certRequested = true 624 _, _ = hs.finishedHash.Write(certReq.marshal()) 625 626 cri := certificateRequestInfoFromMsg(hs.ctx, c.vers, certReq) 627 if chainToSend, err = c.getClientCertificate(cri); err != nil { 628 _ = c.sendAlert(alertInternalError) 629 return err 630 } 631 } 632 633 shd, ok := msg.(*serverHelloDoneMsg) 634 if !ok { 635 zclog.Debug("===== 客户端读取到 serverHelloDoneMsg") 636 _ = c.sendAlert(alertUnexpectedMessage) 637 return unexpectedMessageError(shd, msg) 638 } 639 _, _ = hs.finishedHash.Write(shd.marshal()) 640 641 // If the server requested a certificate then we have to send a 642 // Certificate message, even if it's empty because we don't have a 643 // certificate to send. 644 if certRequested { 645 certMsg = new(certificateMsg) 646 certMsg.certificates = chainToSend.Certificate 647 _, _ = hs.finishedHash.Write(certMsg.marshal()) 648 if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil { 649 return err 650 } 651 zclog.Debug("===== 客户端发送 ClientCertificate") 652 } 653 654 preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, c.peerCertificates[0]) 655 if err != nil { 656 _ = c.sendAlert(alertInternalError) 657 return err 658 } 659 if ckx != nil { 660 _, _ = hs.finishedHash.Write(ckx.marshal()) 661 if _, err := c.writeRecord(recordTypeHandshake, ckx.marshal()); err != nil { 662 return err 663 } 664 zclog.Debug("===== 客户端发送 clientKeyExchangeMsg") 665 } 666 667 if chainToSend != nil && len(chainToSend.Certificate) > 0 { 668 certVerify := &certificateVerifyMsg{} 669 670 key, ok := chainToSend.PrivateKey.(crypto.Signer) 671 if !ok { 672 _ = c.sendAlert(alertInternalError) 673 return fmt.Errorf("gmtls: client certificate private key of type %T does not implement crypto.Signer", chainToSend.PrivateKey) 674 } 675 676 var sigType uint8 677 var sigHash x509.Hash 678 if c.vers >= VersionTLS12 { 679 signatureAlgorithm, err := selectSignatureScheme(c.vers, chainToSend, certReq.supportedSignatureAlgorithms) 680 if err != nil { 681 _ = c.sendAlert(alertIllegalParameter) 682 return err 683 } 684 sigType, sigHash, err = typeAndHashFromSignatureScheme(signatureAlgorithm) 685 if err != nil { 686 return c.sendAlert(alertInternalError) 687 } 688 certVerify.hasSignatureAlgorithm = true 689 certVerify.signatureAlgorithm = signatureAlgorithm 690 } else { 691 sigType, sigHash, err = legacyTypeAndHashFromPublicKey(key.Public()) 692 if err != nil { 693 _ = c.sendAlert(alertIllegalParameter) 694 return err 695 } 696 } 697 698 signed := hs.finishedHash.hashForClientCertificate(sigType, sigHash, hs.masterSecret) 699 signOpts := crypto.SignerOpts(sigHash) 700 if sigType == signatureRSAPSS { 701 signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: sigHash.HashFunc()} 702 } 703 certVerify.signature, err = key.Sign(c.config.rand(), signed, signOpts) 704 if err != nil { 705 _ = c.sendAlert(alertInternalError) 706 return err 707 } 708 709 _, _ = hs.finishedHash.Write(certVerify.marshal()) 710 if _, err := c.writeRecord(recordTypeHandshake, certVerify.marshal()); err != nil { 711 return err 712 } 713 zclog.Debug("===== 客户端发送 ClientCertVerify") 714 } 715 716 hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random) 717 if err := c.config.writeKeyLog(keyLogLabelTLS12, hs.hello.random, hs.masterSecret); err != nil { 718 _ = c.sendAlert(alertInternalError) 719 return errors.New("gmtls: failed to write to key log: " + err.Error()) 720 } 721 722 hs.finishedHash.discardHandshakeBuffer() 723 724 return nil 725 } 726 727 // 生成会话密钥(tls1.2) 728 func (hs *clientHandshakeState) establishKeys() error { 729 c := hs.c 730 731 clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := 732 keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) 733 var clientCipher, serverCipher interface{} 734 var clientHash, serverHash hash.Hash 735 if hs.suite.cipher != nil { 736 clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */) 737 clientHash = hs.suite.mac(clientMAC) 738 serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */) 739 serverHash = hs.suite.mac(serverMAC) 740 } else { 741 clientCipher = hs.suite.aead(clientKey, clientIV) 742 serverCipher = hs.suite.aead(serverKey, serverIV) 743 } 744 745 c.in.prepareCipherSpec(c.vers, serverCipher, serverHash) 746 c.out.prepareCipherSpec(c.vers, clientCipher, clientHash) 747 return nil 748 } 749 750 func (hs *clientHandshakeState) serverResumedSession() bool { 751 // If the server responded with the same sessionId then it means the 752 // sessionTicket is being used to resume a TLS session. 753 return hs.session != nil && hs.hello.sessionId != nil && 754 bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId) 755 } 756 757 // 处理tls1.2及更老版本的 ServerHello 758 func (hs *clientHandshakeState) processServerHello() (bool, error) { 759 c := hs.c 760 // 选取密码套件 761 if err := hs.pickCipherSuite(); err != nil { 762 return false, err 763 } 764 765 if hs.serverHello.compressionMethod != compressionNone { 766 _ = c.sendAlert(alertUnexpectedMessage) 767 return false, errors.New("gmtls: server selected unsupported compression format") 768 } 769 770 if c.handshakes == 0 && hs.serverHello.secureRenegotiationSupported { 771 c.secureRenegotiation = true 772 if len(hs.serverHello.secureRenegotiation) != 0 { 773 _ = c.sendAlert(alertHandshakeFailure) 774 return false, errors.New("gmtls: initial handshake had non-empty renegotiation extension") 775 } 776 } 777 778 if c.handshakes > 0 && c.secureRenegotiation { 779 var expectedSecureRenegotiation [24]byte 780 copy(expectedSecureRenegotiation[:], c.clientFinished[:]) 781 copy(expectedSecureRenegotiation[12:], c.serverFinished[:]) 782 if !bytes.Equal(hs.serverHello.secureRenegotiation, expectedSecureRenegotiation[:]) { 783 _ = c.sendAlert(alertHandshakeFailure) 784 return false, errors.New("gmtls: incorrect renegotiation extension contents") 785 } 786 } 787 788 if err := checkALPN(hs.hello.alpnProtocols, hs.serverHello.alpnProtocol); err != nil { 789 _ = c.sendAlert(alertUnsupportedExtension) 790 return false, err 791 } 792 c.clientProtocol = hs.serverHello.alpnProtocol 793 794 c.scts = hs.serverHello.scts 795 796 if !hs.serverResumedSession() { 797 return false, nil 798 } 799 800 if hs.session.vers != c.vers { 801 _ = c.sendAlert(alertHandshakeFailure) 802 return false, errors.New("gmtls: server resumed a session with a different version") 803 } 804 805 if hs.session.cipherSuite != hs.suite.id { 806 _ = c.sendAlert(alertHandshakeFailure) 807 return false, errors.New("gmtls: server resumed a session with a different cipher suite") 808 } 809 810 // Restore masterSecret, peerCerts, and ocspResponse from previous state 811 hs.masterSecret = hs.session.masterSecret 812 c.peerCertificates = hs.session.serverCertificates 813 c.verifiedChains = hs.session.verifiedChains 814 c.ocspResponse = hs.session.ocspResponse 815 // Let the ServerHello SCTs override the session SCTs from the original 816 // connection, if any are provided 817 if len(c.scts) == 0 && len(hs.session.scts) != 0 { 818 c.scts = hs.session.scts 819 } 820 821 return true, nil 822 } 823 824 // checkALPN ensure that the server's choice of ALPN protocol is compatible with 825 // the protocols that we advertised in the Client Hello. 826 func checkALPN(clientProtos []string, serverProto string) error { 827 if serverProto == "" { 828 return nil 829 } 830 if len(clientProtos) == 0 { 831 return errors.New("gmtls: server advertised unrequested ALPN extension") 832 } 833 for _, proto := range clientProtos { 834 if proto == serverProto { 835 return nil 836 } 837 } 838 return errors.New("gmtls: server selected unadvertised ALPN protocol") 839 } 840 841 func (hs *clientHandshakeState) readFinished(out []byte) error { 842 c := hs.c 843 844 if err := c.readChangeCipherSpec(); err != nil { 845 return err 846 } 847 zclog.Debug("===== 客户端读取到 ChangeCipherSpec") 848 849 msg, err := c.readHandshake() 850 if err != nil { 851 return err 852 } 853 serverFinished, ok := msg.(*finishedMsg) 854 if !ok { 855 _ = c.sendAlert(alertUnexpectedMessage) 856 return unexpectedMessageError(serverFinished, msg) 857 } 858 zclog.Debug("===== 客户端读取到 ServerFinished") 859 verify := hs.finishedHash.serverSum(hs.masterSecret) 860 if len(verify) != len(serverFinished.verifyData) || 861 subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 { 862 _ = c.sendAlert(alertHandshakeFailure) 863 return errors.New("gmtls: server's Finished message was incorrect") 864 } 865 _, _ = hs.finishedHash.Write(serverFinished.marshal()) 866 copy(out, verify) 867 return nil 868 } 869 870 func (hs *clientHandshakeState) readSessionTicket() error { 871 if !hs.serverHello.ticketSupported { 872 return nil 873 } 874 875 c := hs.c 876 msg, err := c.readHandshake() 877 if err != nil { 878 return err 879 } 880 sessionTicketMsg, ok := msg.(*newSessionTicketMsg) 881 if !ok { 882 _ = c.sendAlert(alertUnexpectedMessage) 883 return unexpectedMessageError(sessionTicketMsg, msg) 884 } 885 _, _ = hs.finishedHash.Write(sessionTicketMsg.marshal()) 886 zclog.Debug("===== 客户端读取到 SessionTicket") 887 hs.session = &ClientSessionState{ 888 sessionTicket: sessionTicketMsg.ticket, 889 vers: c.vers, 890 cipherSuite: hs.suite.id, 891 masterSecret: hs.masterSecret, 892 serverCertificates: c.peerCertificates, 893 verifiedChains: c.verifiedChains, 894 receivedAt: c.config.time(), 895 ocspResponse: c.ocspResponse, 896 scts: c.scts, 897 } 898 899 return nil 900 } 901 902 // 发送 ClientFinished (tls1.2) 903 func (hs *clientHandshakeState) sendFinished(out []byte) error { 904 c := hs.c 905 906 if _, err := c.writeRecord(recordTypeChangeCipherSpec, []byte{1}); err != nil { 907 return err 908 } 909 zclog.Debug("===== 客户端发送 ChangeCipherSpec") 910 finished := new(finishedMsg) 911 finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret) 912 _, _ = hs.finishedHash.Write(finished.marshal()) 913 if _, err := c.writeRecord(recordTypeHandshake, finished.marshal()); err != nil { 914 return err 915 } 916 zclog.Debug("===== 客户端发送 ClientFinished") 917 copy(out, finished.verifyData) 918 return nil 919 } 920 921 // 验证服务端证书 922 // verifyServerCertificate parses and verifies the provided chain, setting 923 // c.verifiedChains and c.peerCertificates or sending the appropriate alert. 924 func (c *Conn) verifyServerCertificate(certificates [][]byte) error { 925 certs := make([]*x509.Certificate, len(certificates)) 926 for i, asn1Data := range certificates { 927 cert, err := x509.ParseCertificate(asn1Data) 928 if err != nil { 929 _ = c.sendAlert(alertBadCertificate) 930 return errors.New("gmtls: failed to parse certificate from server: " + err.Error()) 931 } 932 certs[i] = cert 933 } 934 935 if !c.config.InsecureSkipVerify { 936 opts := x509.VerifyOptions{ 937 Roots: c.config.RootCAs, 938 CurrentTime: c.config.time(), 939 DNSName: c.config.ServerName, 940 Intermediates: x509.NewCertPool(), 941 } 942 for _, cert := range certs[1:] { 943 opts.Intermediates.AddCert(cert) 944 } 945 var err error 946 // 尝试构建证书信任链, certs[0]是子证书 947 c.verifiedChains, err = certs[0].Verify(opts) 948 if err != nil { 949 _ = c.sendAlert(alertBadCertificate) 950 return err 951 } 952 } 953 954 switch certs[0].PublicKey.(type) { 955 // 补充sm2条件 956 case *sm2.PublicKey, *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey: 957 break 958 default: 959 _ = c.sendAlert(alertUnsupportedCertificate) 960 return fmt.Errorf("gmtls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey) 961 } 962 // 将服务端的证书设置为对方证书 963 c.peerCertificates = certs 964 965 if c.config.VerifyPeerCertificate != nil { 966 // 执行额外的对方证书验证函数 967 if err := c.config.VerifyPeerCertificate(certificates, c.verifiedChains); err != nil { 968 _ = c.sendAlert(alertBadCertificate) 969 return err 970 } 971 } 972 973 if c.config.VerifyConnection != nil { 974 // 执行额外的连接验证函数 975 if err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil { 976 _ = c.sendAlert(alertBadCertificate) 977 return err 978 } 979 } 980 981 return nil 982 } 983 984 // certificateRequestInfoFromMsg generates a CertificateRequestInfo from a TLS 985 // <= 1.2 CertificateRequest, making an effort to fill in missing information. 986 func certificateRequestInfoFromMsg(ctx context.Context, vers uint16, certReq *certificateRequestMsg) *CertificateRequestInfo { 987 cri := &CertificateRequestInfo{ 988 AcceptableCAs: certReq.certificateAuthorities, 989 Version: vers, 990 ctx: ctx, 991 } 992 993 var rsaAvail, ecAvail bool 994 for _, certType := range certReq.certificateTypes { 995 switch certType { 996 case certTypeRSASign: 997 rsaAvail = true 998 case certTypeECDSASign: 999 ecAvail = true 1000 } 1001 } 1002 1003 if !certReq.hasSignatureAlgorithm { 1004 // Prior to TLS 1.2, signature schemes did not exist. In this case we 1005 // make up a list based on the acceptable certificate types, to help 1006 // GetClientCertificate and SupportsCertificate select the right certificate. 1007 // The hash part of the SignatureScheme is a lie here, because 1008 // TLS 1.0 and 1.1 always use MD5+SHA1 for RSA and SHA1 for ECDSA. 1009 switch { 1010 case rsaAvail && ecAvail: 1011 cri.SignatureSchemes = []SignatureScheme{ 1012 ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512, 1013 PKCS1WithSHA256, PKCS1WithSHA384, PKCS1WithSHA512, PKCS1WithSHA1, 1014 } 1015 case rsaAvail: 1016 cri.SignatureSchemes = []SignatureScheme{ 1017 PKCS1WithSHA256, PKCS1WithSHA384, PKCS1WithSHA512, PKCS1WithSHA1, 1018 } 1019 case ecAvail: 1020 cri.SignatureSchemes = []SignatureScheme{ 1021 ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512, 1022 } 1023 } 1024 return cri 1025 } 1026 1027 // Filter the signature schemes based on the certificate types. 1028 // See RFC 5246, Section 7.4.4 (where it calls this "somewhat complicated"). 1029 cri.SignatureSchemes = make([]SignatureScheme, 0, len(certReq.supportedSignatureAlgorithms)) 1030 for _, sigScheme := range certReq.supportedSignatureAlgorithms { 1031 sigType, _, err := typeAndHashFromSignatureScheme(sigScheme) 1032 if err != nil { 1033 continue 1034 } 1035 switch sigType { 1036 case signatureECDSA, signatureEd25519: 1037 if ecAvail { 1038 cri.SignatureSchemes = append(cri.SignatureSchemes, sigScheme) 1039 } 1040 case signatureRSAPSS, signaturePKCS1v15: 1041 if rsaAvail { 1042 cri.SignatureSchemes = append(cri.SignatureSchemes, sigScheme) 1043 } 1044 } 1045 } 1046 1047 return cri 1048 } 1049 1050 func (c *Conn) getClientCertificate(cri *CertificateRequestInfo) (*Certificate, error) { 1051 if c.config.GetClientCertificate != nil { 1052 return c.config.GetClientCertificate(cri) 1053 } 1054 1055 for _, chain := range c.config.Certificates { 1056 if err := cri.SupportsCertificate(&chain); err != nil { 1057 continue 1058 } 1059 return &chain, nil 1060 } 1061 1062 // No acceptable certificate found. Don't send a certificate. 1063 return new(Certificate), nil 1064 } 1065 1066 // 获取客户端会话缓存key,使用ServerName或serverAddr。 1067 // clientSessionCacheKey returns a key used to cache sessionTickets that could 1068 // be used to resume previously negotiated TLS sessions with a server. 1069 func clientSessionCacheKey(serverAddr net.Addr, config *Config) string { 1070 if len(config.ServerName) > 0 { 1071 return config.ServerName 1072 } 1073 return serverAddr.String() 1074 } 1075 1076 // 将name适配为SNI要求的格式。 1077 // 1078 // 不支持IPv4或IPv6格式,支持DNS域名。 1079 // 1080 // hostnameInSNI converts name into an appropriate hostname for SNI. 1081 // Literal IP addresses and absolute FQDNs are not permitted as SNI values. 1082 // See RFC 6066, Section 3. 1083 func hostnameInSNI(name string) string { 1084 host := name 1085 // 去除首尾的"[]"包裹 1086 if len(host) > 0 && host[0] == '[' && host[len(host)-1] == ']' { 1087 host = host[1 : len(host)-1] 1088 } 1089 // 去除"%"以后的内容 1090 if i := strings.LastIndex(host, "%"); i > 0 { 1091 host = host[:i] 1092 } 1093 // 检查host是ip的话是否合法,合法则返回空字符串 1094 if net.ParseIP(host) != nil { 1095 return "" 1096 } 1097 // 去除末尾的一个或多个"." 1098 for len(name) > 0 && name[len(name)-1] == '.' { 1099 name = name[:len(name)-1] 1100 } 1101 return name 1102 }