@@ -29,6 +29,7 @@ type Conn struct {
29
29
conn net.Conn
30
30
isClient bool
31
31
handshakeFn func (context.Context ) error // (*Conn).clientHandshake or serverHandshake
32
+ quic * quicState // nil for non-QUIC connections
32
33
33
34
// isHandshakeComplete is true if the connection is currently transferring
34
35
// application data (i.e. is not currently processing a handshake).
@@ -176,7 +177,8 @@ type halfConn struct {
176
177
nextCipher any // next encryption state
177
178
nextMac hash.Hash // next MAC algorithm
178
179
179
- trafficSecret []byte // current TLS 1.3 traffic secret
180
+ level QUICEncryptionLevel // current QUIC encryption level
181
+ trafficSecret []byte // current TLS 1.3 traffic secret
180
182
}
181
183
182
184
type permanentError struct {
@@ -221,8 +223,9 @@ func (hc *halfConn) changeCipherSpec() error {
221
223
return nil
222
224
}
223
225
224
- func (hc * halfConn ) setTrafficSecret (suite * cipherSuiteTLS13 , secret []byte ) {
226
+ func (hc * halfConn ) setTrafficSecret (suite * cipherSuiteTLS13 , level QUICEncryptionLevel , secret []byte ) {
225
227
hc .trafficSecret = secret
228
+ hc .level = level
226
229
key , iv := suite .trafficKey (secret )
227
230
hc .cipher = suite .aead (key , iv )
228
231
for i := range hc .seq {
@@ -613,6 +616,10 @@ func (c *Conn) readRecordOrCCS(expectChangeCipherSpec bool) error {
613
616
}
614
617
c .input .Reset (nil )
615
618
619
+ if c .quic != nil {
620
+ return c .in .setErrorLocked (errors .New ("tls: internal error: attempted to read record with QUIC transport" ))
621
+ }
622
+
616
623
// Read header, payload.
617
624
if err := c .readFromUntil (c .conn , recordHeaderLen ); err != nil {
618
625
// RFC 8446, Section 6.1 suggests that EOF without an alertCloseNotify
@@ -702,6 +709,9 @@ func (c *Conn) readRecordOrCCS(expectChangeCipherSpec bool) error {
702
709
return c .in .setErrorLocked (c .sendAlert (alertUnexpectedMessage ))
703
710
704
711
case recordTypeAlert :
712
+ if c .quic != nil {
713
+ return c .in .setErrorLocked (c .sendAlert (alertUnexpectedMessage ))
714
+ }
705
715
if len (data ) != 2 {
706
716
return c .in .setErrorLocked (c .sendAlert (alertUnexpectedMessage ))
707
717
}
@@ -819,6 +829,10 @@ func (c *Conn) readFromUntil(r io.Reader, n int) error {
819
829
820
830
// sendAlertLocked sends a TLS alert message.
821
831
func (c * Conn ) sendAlertLocked (err alert ) error {
832
+ if c .quic != nil {
833
+ return c .out .setErrorLocked (& net.OpError {Op : "local error" , Err : err })
834
+ }
835
+
822
836
switch err {
823
837
case alertNoRenegotiation , alertCloseNotify :
824
838
c .tmp [0 ] = alertLevelWarning
@@ -953,6 +967,19 @@ var outBufPool = sync.Pool{
953
967
// writeRecordLocked writes a TLS record with the given type and payload to the
954
968
// connection and updates the record layer state.
955
969
func (c * Conn ) writeRecordLocked (typ recordType , data []byte ) (int , error ) {
970
+ if c .quic != nil {
971
+ if typ != recordTypeHandshake {
972
+ return 0 , errors .New ("tls: internal error: sending non-handshake message to QUIC transport" )
973
+ }
974
+ c .quicWriteCryptoData (c .out .level , data )
975
+ if ! c .buffering {
976
+ if _ , err := c .flush (); err != nil {
977
+ return 0 , err
978
+ }
979
+ }
980
+ return len (data ), nil
981
+ }
982
+
956
983
outBufPtr := outBufPool .Get ().(* []byte )
957
984
outBuf := * outBufPtr
958
985
defer func () {
@@ -1037,28 +1064,40 @@ func (c *Conn) writeChangeCipherRecord() error {
1037
1064
return err
1038
1065
}
1039
1066
1067
+ // readHandshakeBytes reads handshake data until c.hand contains at least n bytes.
1068
+ func (c * Conn ) readHandshakeBytes (n int ) error {
1069
+ if c .quic != nil {
1070
+ return c .quicReadHandshakeBytes (n )
1071
+ }
1072
+ for c .hand .Len () < n {
1073
+ if err := c .readRecord (); err != nil {
1074
+ return err
1075
+ }
1076
+ }
1077
+ return nil
1078
+ }
1079
+
1040
1080
// readHandshake reads the next handshake message from
1041
1081
// the record layer. If transcript is non-nil, the message
1042
1082
// is written to the passed transcriptHash.
1043
1083
func (c * Conn ) readHandshake (transcript transcriptHash ) (any , error ) {
1044
- for c .hand .Len () < 4 {
1045
- if err := c .readRecord (); err != nil {
1046
- return nil , err
1047
- }
1084
+ if err := c .readHandshakeBytes (4 ); err != nil {
1085
+ return nil , err
1048
1086
}
1049
-
1050
1087
data := c .hand .Bytes ()
1051
1088
n := int (data [1 ])<< 16 | int (data [2 ])<< 8 | int (data [3 ])
1052
1089
if n > maxHandshake {
1053
1090
c .sendAlertLocked (alertInternalError )
1054
1091
return nil , c .in .setErrorLocked (fmt .Errorf ("tls: handshake message of length %d bytes exceeds maximum of %d bytes" , n , maxHandshake ))
1055
1092
}
1056
- for c .hand .Len () < 4 + n {
1057
- if err := c .readRecord (); err != nil {
1058
- return nil , err
1059
- }
1093
+ if err := c .readHandshakeBytes (4 + n ); err != nil {
1094
+ return nil , err
1060
1095
}
1061
1096
data = c .hand .Next (4 + n )
1097
+ return c .unmarshalHandshakeMessage (data , transcript )
1098
+ }
1099
+
1100
+ func (c * Conn ) unmarshalHandshakeMessage (data []byte , transcript transcriptHash ) (handshakeMessage , error ) {
1062
1101
var m handshakeMessage
1063
1102
switch data [0 ] {
1064
1103
case typeHelloRequest :
@@ -1249,7 +1288,6 @@ func (c *Conn) handlePostHandshakeMessage() error {
1249
1288
if err != nil {
1250
1289
return err
1251
1290
}
1252
-
1253
1291
c .retryCount ++
1254
1292
if c .retryCount > maxUselessRecords {
1255
1293
c .sendAlert (alertUnexpectedMessage )
@@ -1261,20 +1299,28 @@ func (c *Conn) handlePostHandshakeMessage() error {
1261
1299
return c .handleNewSessionTicket (msg )
1262
1300
case * keyUpdateMsg :
1263
1301
return c .handleKeyUpdate (msg )
1264
- default :
1265
- c .sendAlert (alertUnexpectedMessage )
1266
- return fmt .Errorf ("tls: received unexpected handshake message of type %T" , msg )
1267
1302
}
1303
+ // The QUIC layer is supposed to treat an unexpected post-handshake CertificateRequest
1304
+ // as a QUIC-level PROTOCOL_VIOLATION error (RFC 9001, Section 4.4). Returning an
1305
+ // unexpected_message alert here doesn't provide it with enough information to distinguish
1306
+ // this condition from other unexpected messages. This is probably fine.
1307
+ c .sendAlert (alertUnexpectedMessage )
1308
+ return fmt .Errorf ("tls: received unexpected handshake message of type %T" , msg )
1268
1309
}
1269
1310
1270
1311
func (c * Conn ) handleKeyUpdate (keyUpdate * keyUpdateMsg ) error {
1312
+ if c .quic != nil {
1313
+ c .sendAlert (alertUnexpectedMessage )
1314
+ return c .in .setErrorLocked (errors .New ("tls: received unexpected key update message" ))
1315
+ }
1316
+
1271
1317
cipherSuite := cipherSuiteTLS13ByID (c .cipherSuite )
1272
1318
if cipherSuite == nil {
1273
1319
return c .in .setErrorLocked (c .sendAlert (alertInternalError ))
1274
1320
}
1275
1321
1276
1322
newSecret := cipherSuite .nextTrafficSecret (c .in .trafficSecret )
1277
- c .in .setTrafficSecret (cipherSuite , newSecret )
1323
+ c .in .setTrafficSecret (cipherSuite , QUICEncryptionLevelInitial , newSecret )
1278
1324
1279
1325
if keyUpdate .updateRequested {
1280
1326
c .out .Lock ()
@@ -1293,7 +1339,7 @@ func (c *Conn) handleKeyUpdate(keyUpdate *keyUpdateMsg) error {
1293
1339
}
1294
1340
1295
1341
newSecret := cipherSuite .nextTrafficSecret (c .out .trafficSecret )
1296
- c .out .setTrafficSecret (cipherSuite , newSecret )
1342
+ c .out .setTrafficSecret (cipherSuite , QUICEncryptionLevelInitial , newSecret )
1297
1343
}
1298
1344
1299
1345
return nil
@@ -1454,12 +1500,15 @@ func (c *Conn) handshakeContext(ctx context.Context) (ret error) {
1454
1500
// this cancellation. In the former case, we need to close the connection.
1455
1501
defer cancel ()
1456
1502
1457
- // Start the "interrupter" goroutine, if this context might be canceled.
1458
- // (The background context cannot).
1459
- //
1460
- // The interrupter goroutine waits for the input context to be done and
1461
- // closes the connection if this happens before the function returns.
1462
- if ctx .Done () != nil {
1503
+ if c .quic != nil {
1504
+ c .quic .cancelc = handshakeCtx .Done ()
1505
+ c .quic .cancel = cancel
1506
+ } else if ctx .Done () != nil {
1507
+ // Start the "interrupter" goroutine, if this context might be canceled.
1508
+ // (The background context cannot).
1509
+ //
1510
+ // The interrupter goroutine waits for the input context to be done and
1511
+ // closes the connection if this happens before the function returns.
1463
1512
done := make (chan struct {})
1464
1513
interruptRes := make (chan error , 1 )
1465
1514
defer func () {
@@ -1510,6 +1559,30 @@ func (c *Conn) handshakeContext(ctx context.Context) (ret error) {
1510
1559
panic ("tls: internal error: handshake returned an error but is marked successful" )
1511
1560
}
1512
1561
1562
+ if c .quic != nil {
1563
+ if c .handshakeErr == nil {
1564
+ c .quicHandshakeComplete ()
1565
+ // Provide the 1-RTT read secret now that the handshake is complete.
1566
+ // The QUIC layer MUST NOT decrypt 1-RTT packets prior to completing
1567
+ // the handshake (RFC 9001, Section 5.7).
1568
+ c .quicSetReadSecret (QUICEncryptionLevelApplication , c .cipherSuite , c .in .trafficSecret )
1569
+ } else {
1570
+ var a alert
1571
+ c .out .Lock ()
1572
+ if ! errors .As (c .out .err , & a ) {
1573
+ a = alertInternalError
1574
+ }
1575
+ c .out .Unlock ()
1576
+ // Return an error which wraps both the handshake error and
1577
+ // any alert error we may have sent, or alertInternalError
1578
+ // if we didn't send an alert.
1579
+ // Truncate the text of the alert to 0 characters.
1580
+ c .handshakeErr = fmt .Errorf ("%w%.0w" , c .handshakeErr , AlertError (a ))
1581
+ }
1582
+ close (c .quic .blockedc )
1583
+ close (c .quic .signalc )
1584
+ }
1585
+
1513
1586
return c .handshakeErr
1514
1587
}
1515
1588
0 commit comments