github.com/Carcraftz/utls@v0.0.0-20220413235215-6b7c52fd78b6/u_public.go (about) 1 // Copyright 2017 Google Inc. 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 "crypto" 9 "crypto/x509" 10 "hash" 11 ) 12 13 // ClientHandshakeState includes both TLS 1.3-only and TLS 1.2-only states, 14 // only one of them will be used, depending on negotiated version. 15 // 16 // ClientHandshakeState will be converted into and from either 17 // - clientHandshakeState (TLS 1.2) 18 // - clientHandshakeStateTLS13 (TLS 1.3) 19 // uTLS will call .handshake() on one of these private internal states, 20 // to perform TLS handshake using standard crypto/tls implementation. 21 type ClientHandshakeState struct { 22 C *Conn 23 ServerHello *ServerHelloMsg 24 Hello *ClientHelloMsg 25 MasterSecret []byte 26 Session *ClientSessionState 27 28 State12 TLS12OnlyState 29 State13 TLS13OnlyState 30 31 uconn *UConn 32 } 33 34 // TLS 1.3 only 35 type TLS13OnlyState struct { 36 Suite *CipherSuiteTLS13 37 EcdheParams map[CurveID]EcdheParameters // XXX/yawning - annoying 38 EarlySecret []byte 39 BinderKey []byte 40 CertReq *CertificateRequestMsgTLS13 41 UsingPSK bool 42 SentDummyCCS bool 43 Transcript hash.Hash 44 TrafficSecret []byte // client_application_traffic_secret_0 45 CertCompAlgs []CertCompressionAlgo 46 } 47 48 // TLS 1.2 and before only 49 type TLS12OnlyState struct { 50 FinishedHash FinishedHash 51 Suite CipherSuite 52 } 53 54 func (chs *ClientHandshakeState) toPrivate13() *clientHandshakeStateTLS13 { 55 if chs == nil { 56 return nil 57 } else { 58 return &clientHandshakeStateTLS13{ 59 c: chs.C, 60 serverHello: chs.ServerHello.getPrivatePtr(), 61 hello: chs.Hello.getPrivatePtr(), 62 ecdheParams: ecdheParamMapToPrivate(chs.State13.EcdheParams), 63 64 session: chs.Session, 65 earlySecret: chs.State13.EarlySecret, 66 binderKey: chs.State13.BinderKey, 67 68 certReq: chs.State13.CertReq.toPrivate(), 69 usingPSK: chs.State13.UsingPSK, 70 sentDummyCCS: chs.State13.SentDummyCCS, 71 suite: chs.State13.Suite.toPrivate(), 72 transcript: chs.State13.Transcript, 73 masterSecret: chs.MasterSecret, 74 trafficSecret: chs.State13.TrafficSecret, 75 certCompAlgs: chs.State13.CertCompAlgs, 76 77 uconn: chs.uconn, 78 } 79 } 80 } 81 82 func (chs13 *clientHandshakeStateTLS13) toPublic13() *ClientHandshakeState { 83 if chs13 == nil { 84 return nil 85 } else { 86 tls13State := TLS13OnlyState{ 87 EcdheParams: ecdheParamMapToPublic(chs13.ecdheParams), 88 EarlySecret: chs13.earlySecret, 89 BinderKey: chs13.binderKey, 90 CertReq: chs13.certReq.toPublic(), 91 UsingPSK: chs13.usingPSK, 92 SentDummyCCS: chs13.sentDummyCCS, 93 Suite: chs13.suite.toPublic(), 94 TrafficSecret: chs13.trafficSecret, 95 Transcript: chs13.transcript, 96 CertCompAlgs: chs13.certCompAlgs, 97 } 98 return &ClientHandshakeState{ 99 C: chs13.c, 100 ServerHello: chs13.serverHello.getPublicPtr(), 101 Hello: chs13.hello.getPublicPtr(), 102 103 Session: chs13.session, 104 105 MasterSecret: chs13.masterSecret, 106 107 State13: tls13State, 108 109 uconn: chs13.uconn, 110 } 111 } 112 } 113 114 func (chs *ClientHandshakeState) toPrivate12() *clientHandshakeState { 115 if chs == nil { 116 return nil 117 } else { 118 return &clientHandshakeState{ 119 c: chs.C, 120 serverHello: chs.ServerHello.getPrivatePtr(), 121 hello: chs.Hello.getPrivatePtr(), 122 suite: chs.State12.Suite.getPrivatePtr(), 123 session: chs.Session, 124 125 masterSecret: chs.MasterSecret, 126 127 finishedHash: chs.State12.FinishedHash.getPrivateObj(), 128 129 uconn: chs.uconn, 130 } 131 } 132 } 133 134 func (chs12 *clientHandshakeState) toPublic12() *ClientHandshakeState { 135 if chs12 == nil { 136 return nil 137 } else { 138 tls12State := TLS12OnlyState{ 139 Suite: chs12.suite.getPublicObj(), 140 FinishedHash: chs12.finishedHash.getPublicObj(), 141 } 142 return &ClientHandshakeState{ 143 C: chs12.c, 144 ServerHello: chs12.serverHello.getPublicPtr(), 145 Hello: chs12.hello.getPublicPtr(), 146 147 Session: chs12.session, 148 149 MasterSecret: chs12.masterSecret, 150 151 State12: tls12State, 152 153 uconn: chs12.uconn, 154 } 155 } 156 } 157 158 type EcdheParameters interface { 159 ecdheParameters 160 } 161 162 func ecdheParamMapToPublic(src map[CurveID]ecdheParameters) map[CurveID]EcdheParameters { 163 dst := make(map[CurveID]EcdheParameters) 164 for curveID, param := range src { 165 dst[curveID] = EcdheParameters(param) 166 } 167 return dst 168 } 169 170 func ecdheParamMapToPrivate(src map[CurveID]EcdheParameters) map[CurveID]ecdheParameters { 171 dst := make(map[CurveID]ecdheParameters) 172 for curveID, param := range src { 173 dst[curveID] = ecdheParameters(param) 174 } 175 return dst 176 } 177 178 type CertificateRequestMsgTLS13 struct { 179 Raw []byte 180 OcspStapling bool 181 Scts bool 182 SupportedSignatureAlgorithms []SignatureScheme 183 SupportedSignatureAlgorithmsCert []SignatureScheme 184 CertificateAuthorities [][]byte 185 } 186 187 func (crm *certificateRequestMsgTLS13) toPublic() *CertificateRequestMsgTLS13 { 188 if crm == nil { 189 return nil 190 } else { 191 return &CertificateRequestMsgTLS13{ 192 Raw: crm.raw, 193 OcspStapling: crm.ocspStapling, 194 Scts: crm.scts, 195 SupportedSignatureAlgorithms: crm.supportedSignatureAlgorithms, 196 SupportedSignatureAlgorithmsCert: crm.supportedSignatureAlgorithmsCert, 197 CertificateAuthorities: crm.certificateAuthorities, 198 } 199 } 200 } 201 202 func (crm *CertificateRequestMsgTLS13) toPrivate() *certificateRequestMsgTLS13 { 203 if crm == nil { 204 return nil 205 } else { 206 return &certificateRequestMsgTLS13{ 207 raw: crm.Raw, 208 ocspStapling: crm.OcspStapling, 209 scts: crm.Scts, 210 supportedSignatureAlgorithms: crm.SupportedSignatureAlgorithms, 211 supportedSignatureAlgorithmsCert: crm.SupportedSignatureAlgorithmsCert, 212 certificateAuthorities: crm.CertificateAuthorities, 213 } 214 } 215 } 216 217 type CipherSuiteTLS13 struct { 218 Id uint16 219 KeyLen int 220 Aead func(key, fixedNonce []byte) aead 221 Hash crypto.Hash 222 } 223 224 func (c *cipherSuiteTLS13) toPublic() *CipherSuiteTLS13 { 225 if c == nil { 226 return nil 227 } else { 228 return &CipherSuiteTLS13{ 229 Id: c.id, 230 KeyLen: c.keyLen, 231 Aead: c.aead, 232 Hash: c.hash, 233 } 234 } 235 } 236 237 func (c *CipherSuiteTLS13) toPrivate() *cipherSuiteTLS13 { 238 if c == nil { 239 return nil 240 } else { 241 return &cipherSuiteTLS13{ 242 id: c.Id, 243 keyLen: c.KeyLen, 244 aead: c.Aead, 245 hash: c.Hash, 246 } 247 } 248 } 249 250 type ServerHelloMsg struct { 251 Raw []byte 252 Vers uint16 253 Random []byte 254 SessionId []byte 255 CipherSuite uint16 256 CompressionMethod uint8 257 NextProtoNeg bool 258 NextProtos []string 259 OcspStapling bool 260 Scts [][]byte 261 Ems bool 262 TicketSupported bool 263 SecureRenegotiation []byte 264 SecureRenegotiationSupported bool 265 AlpnProtocol string 266 267 // 1.3 268 SupportedVersion uint16 269 ServerShare keyShare 270 SelectedIdentityPresent bool 271 SelectedIdentity uint16 272 Cookie []byte // HelloRetryRequest extension 273 SelectedGroup CurveID // HelloRetryRequest extension 274 275 } 276 277 func (shm *ServerHelloMsg) getPrivatePtr() *serverHelloMsg { 278 if shm == nil { 279 return nil 280 } else { 281 return &serverHelloMsg{ 282 raw: shm.Raw, 283 vers: shm.Vers, 284 random: shm.Random, 285 sessionId: shm.SessionId, 286 cipherSuite: shm.CipherSuite, 287 compressionMethod: shm.CompressionMethod, 288 nextProtoNeg: shm.NextProtoNeg, 289 nextProtos: shm.NextProtos, 290 ocspStapling: shm.OcspStapling, 291 scts: shm.Scts, 292 ems: shm.Ems, 293 ticketSupported: shm.TicketSupported, 294 secureRenegotiation: shm.SecureRenegotiation, 295 secureRenegotiationSupported: shm.SecureRenegotiationSupported, 296 alpnProtocol: shm.AlpnProtocol, 297 supportedVersion: shm.SupportedVersion, 298 serverShare: shm.ServerShare, 299 selectedIdentityPresent: shm.SelectedIdentityPresent, 300 selectedIdentity: shm.SelectedIdentity, 301 cookie: shm.Cookie, 302 selectedGroup: shm.SelectedGroup, 303 } 304 } 305 } 306 307 func (shm *serverHelloMsg) getPublicPtr() *ServerHelloMsg { 308 if shm == nil { 309 return nil 310 } else { 311 return &ServerHelloMsg{ 312 Raw: shm.raw, 313 Vers: shm.vers, 314 Random: shm.random, 315 SessionId: shm.sessionId, 316 CipherSuite: shm.cipherSuite, 317 CompressionMethod: shm.compressionMethod, 318 NextProtoNeg: shm.nextProtoNeg, 319 NextProtos: shm.nextProtos, 320 OcspStapling: shm.ocspStapling, 321 Scts: shm.scts, 322 Ems: shm.ems, 323 TicketSupported: shm.ticketSupported, 324 SecureRenegotiation: shm.secureRenegotiation, 325 SecureRenegotiationSupported: shm.secureRenegotiationSupported, 326 AlpnProtocol: shm.alpnProtocol, 327 SupportedVersion: shm.supportedVersion, 328 ServerShare: shm.serverShare, 329 SelectedIdentityPresent: shm.selectedIdentityPresent, 330 SelectedIdentity: shm.selectedIdentity, 331 Cookie: shm.cookie, 332 SelectedGroup: shm.selectedGroup, 333 } 334 } 335 } 336 337 type ClientHelloMsg struct { 338 Raw []byte 339 Vers uint16 340 Random []byte 341 SessionId []byte 342 CipherSuites []uint16 343 CompressionMethods []uint8 344 NextProtoNeg bool 345 ServerName string 346 OcspStapling bool 347 Scts bool 348 Ems bool // [UTLS] actually implemented due to its prevalence 349 SupportedCurves []CurveID 350 SupportedPoints []uint8 351 TicketSupported bool 352 SessionTicket []uint8 353 SupportedSignatureAlgorithms []SignatureScheme 354 SecureRenegotiation []byte 355 SecureRenegotiationSupported bool 356 AlpnProtocols []string 357 358 // 1.3 359 SupportedSignatureAlgorithmsCert []SignatureScheme 360 SupportedVersions []uint16 361 Cookie []byte 362 KeyShares []KeyShare 363 EarlyData bool 364 PskModes []uint8 365 PskIdentities []pskIdentity 366 PskBinders [][]byte 367 } 368 369 func (chm *ClientHelloMsg) getPrivatePtr() *clientHelloMsg { 370 if chm == nil { 371 return nil 372 } else { 373 return &clientHelloMsg{ 374 raw: chm.Raw, 375 vers: chm.Vers, 376 random: chm.Random, 377 sessionId: chm.SessionId, 378 cipherSuites: chm.CipherSuites, 379 compressionMethods: chm.CompressionMethods, 380 nextProtoNeg: chm.NextProtoNeg, 381 serverName: chm.ServerName, 382 ocspStapling: chm.OcspStapling, 383 scts: chm.Scts, 384 ems: chm.Ems, 385 supportedCurves: chm.SupportedCurves, 386 supportedPoints: chm.SupportedPoints, 387 ticketSupported: chm.TicketSupported, 388 sessionTicket: chm.SessionTicket, 389 supportedSignatureAlgorithms: chm.SupportedSignatureAlgorithms, 390 secureRenegotiation: chm.SecureRenegotiation, 391 secureRenegotiationSupported: chm.SecureRenegotiationSupported, 392 alpnProtocols: chm.AlpnProtocols, 393 394 supportedSignatureAlgorithmsCert: chm.SupportedSignatureAlgorithmsCert, 395 supportedVersions: chm.SupportedVersions, 396 cookie: chm.Cookie, 397 keyShares: KeyShares(chm.KeyShares).ToPrivate(), 398 earlyData: chm.EarlyData, 399 pskModes: chm.PskModes, 400 pskIdentities: chm.PskIdentities, 401 pskBinders: chm.PskBinders, 402 } 403 } 404 } 405 406 func (chm *clientHelloMsg) getPublicPtr() *ClientHelloMsg { 407 if chm == nil { 408 return nil 409 } else { 410 return &ClientHelloMsg{ 411 Raw: chm.raw, 412 Vers: chm.vers, 413 Random: chm.random, 414 SessionId: chm.sessionId, 415 CipherSuites: chm.cipherSuites, 416 CompressionMethods: chm.compressionMethods, 417 NextProtoNeg: chm.nextProtoNeg, 418 ServerName: chm.serverName, 419 OcspStapling: chm.ocspStapling, 420 Scts: chm.scts, 421 Ems: chm.ems, 422 SupportedCurves: chm.supportedCurves, 423 SupportedPoints: chm.supportedPoints, 424 TicketSupported: chm.ticketSupported, 425 SessionTicket: chm.sessionTicket, 426 SupportedSignatureAlgorithms: chm.supportedSignatureAlgorithms, 427 SecureRenegotiation: chm.secureRenegotiation, 428 SecureRenegotiationSupported: chm.secureRenegotiationSupported, 429 AlpnProtocols: chm.alpnProtocols, 430 431 SupportedSignatureAlgorithmsCert: chm.supportedSignatureAlgorithmsCert, 432 SupportedVersions: chm.supportedVersions, 433 Cookie: chm.cookie, 434 KeyShares: keyShares(chm.keyShares).ToPublic(), 435 EarlyData: chm.earlyData, 436 PskModes: chm.pskModes, 437 PskIdentities: chm.pskIdentities, 438 PskBinders: chm.pskBinders, 439 } 440 } 441 } 442 443 // A CipherSuite is a specific combination of key agreement, cipher and MAC 444 // function. All cipher suites currently assume RSA key agreement. 445 type CipherSuite struct { 446 Id uint16 447 // the lengths, in bytes, of the key material needed for each component. 448 KeyLen int 449 MacLen int 450 IvLen int 451 Ka func(version uint16) keyAgreement 452 // flags is a bitmask of the suite* values, above. 453 Flags int 454 Cipher func(key, iv []byte, isRead bool) interface{} 455 Mac func(version uint16, macKey []byte) macFunction 456 Aead func(key, fixedNonce []byte) aead 457 } 458 459 func (cs *CipherSuite) getPrivatePtr() *cipherSuite { 460 if cs == nil { 461 return nil 462 } else { 463 return &cipherSuite{ 464 id: cs.Id, 465 keyLen: cs.KeyLen, 466 macLen: cs.MacLen, 467 ivLen: cs.IvLen, 468 ka: cs.Ka, 469 flags: cs.Flags, 470 cipher: cs.Cipher, 471 mac: cs.Mac, 472 aead: cs.Aead, 473 } 474 } 475 } 476 477 func (cs *cipherSuite) getPublicObj() CipherSuite { 478 if cs == nil { 479 return CipherSuite{} 480 } else { 481 return CipherSuite{ 482 Id: cs.id, 483 KeyLen: cs.keyLen, 484 MacLen: cs.macLen, 485 IvLen: cs.ivLen, 486 Ka: cs.ka, 487 Flags: cs.flags, 488 Cipher: cs.cipher, 489 Mac: cs.mac, 490 Aead: cs.aead, 491 } 492 } 493 } 494 495 // A FinishedHash calculates the hash of a set of handshake messages suitable 496 // for including in a Finished message. 497 type FinishedHash struct { 498 Client hash.Hash 499 Server hash.Hash 500 501 // Prior to TLS 1.2, an additional MD5 hash is required. 502 ClientMD5 hash.Hash 503 ServerMD5 hash.Hash 504 505 // In TLS 1.2, a full buffer is sadly required. 506 Buffer []byte 507 508 Version uint16 509 Prf func(result, secret, label, seed []byte) 510 } 511 512 func (fh *FinishedHash) getPrivateObj() finishedHash { 513 if fh == nil { 514 return finishedHash{} 515 } else { 516 return finishedHash{ 517 client: fh.Client, 518 server: fh.Server, 519 clientMD5: fh.ClientMD5, 520 serverMD5: fh.ServerMD5, 521 buffer: fh.Buffer, 522 version: fh.Version, 523 prf: fh.Prf, 524 } 525 } 526 } 527 528 func (fh *finishedHash) getPublicObj() FinishedHash { 529 if fh == nil { 530 return FinishedHash{} 531 } else { 532 return FinishedHash{ 533 Client: fh.client, 534 Server: fh.server, 535 ClientMD5: fh.clientMD5, 536 ServerMD5: fh.serverMD5, 537 Buffer: fh.buffer, 538 Version: fh.version, 539 Prf: fh.prf} 540 } 541 } 542 543 // TLS 1.3 Key Share. See RFC 8446, Section 4.2.8. 544 type KeyShare struct { 545 Group CurveID 546 Data []byte 547 } 548 549 type KeyShares []KeyShare 550 type keyShares []keyShare 551 552 func (kss keyShares) ToPublic() []KeyShare { 553 var KSS []KeyShare 554 for _, ks := range kss { 555 KSS = append(KSS, KeyShare{Data: ks.data, Group: ks.group}) 556 } 557 return KSS 558 } 559 func (KSS KeyShares) ToPrivate() []keyShare { 560 var kss []keyShare 561 for _, KS := range KSS { 562 kss = append(kss, keyShare{data: KS.Data, group: KS.Group}) 563 } 564 return kss 565 } 566 567 // ClientSessionState is public, but all its fields are private. Let's add setters, getters and constructor 568 569 // ClientSessionState contains the state needed by clients to resume TLS sessions. 570 func MakeClientSessionState( 571 SessionTicket []uint8, 572 Vers uint16, 573 CipherSuite uint16, 574 MasterSecret []byte, 575 ServerCertificates []*x509.Certificate, 576 VerifiedChains [][]*x509.Certificate) *ClientSessionState { 577 css := ClientSessionState{sessionTicket: SessionTicket, 578 vers: Vers, 579 cipherSuite: CipherSuite, 580 masterSecret: MasterSecret, 581 serverCertificates: ServerCertificates, 582 verifiedChains: VerifiedChains} 583 return &css 584 } 585 586 // Encrypted ticket used for session resumption with server 587 func (css *ClientSessionState) SessionTicket() []uint8 { 588 return css.sessionTicket 589 } 590 591 // SSL/TLS version negotiated for the session 592 func (css *ClientSessionState) Vers() uint16 { 593 return css.vers 594 } 595 596 // Ciphersuite negotiated for the session 597 func (css *ClientSessionState) CipherSuite() uint16 { 598 return css.cipherSuite 599 } 600 601 // MasterSecret generated by client on a full handshake 602 func (css *ClientSessionState) MasterSecret() []byte { 603 return css.masterSecret 604 } 605 606 // Certificate chain presented by the server 607 func (css *ClientSessionState) ServerCertificates() []*x509.Certificate { 608 return css.serverCertificates 609 } 610 611 // Certificate chains we built for verification 612 func (css *ClientSessionState) VerifiedChains() [][]*x509.Certificate { 613 return css.verifiedChains 614 } 615 616 func (css *ClientSessionState) SetSessionTicket(SessionTicket []uint8) { 617 css.sessionTicket = SessionTicket 618 } 619 func (css *ClientSessionState) SetVers(Vers uint16) { 620 css.vers = Vers 621 } 622 func (css *ClientSessionState) SetCipherSuite(CipherSuite uint16) { 623 css.cipherSuite = CipherSuite 624 } 625 func (css *ClientSessionState) SetMasterSecret(MasterSecret []byte) { 626 css.masterSecret = MasterSecret 627 } 628 func (css *ClientSessionState) SetServerCertificates(ServerCertificates []*x509.Certificate) { 629 css.serverCertificates = ServerCertificates 630 } 631 func (css *ClientSessionState) SetVerifiedChains(VerifiedChains [][]*x509.Certificate) { 632 css.verifiedChains = VerifiedChains 633 }