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