Skip to content

Commit e6c29ed

Browse files
noise: send early data with 2nd and 3rd handshake message
1 parent 0fe5519 commit e6c29ed

File tree

4 files changed

+44
-32
lines changed

4 files changed

+44
-32
lines changed

p2p/security/noise/handshake.go

+17-16
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,7 @@ func (s *secureSession) runHandshake(ctx context.Context) (err error) {
7878
if s.initiator {
7979
// stage 0 //
8080
// Handshake Msg Len = len(DH ephemeral key)
81-
var ed []byte
82-
if s.initiatorEarlyDataHandler != nil {
83-
ed = s.initiatorEarlyDataHandler.Send(ctx, s.insecureConn, s.remoteID)
84-
}
85-
if err := s.sendHandshakeMessage(hs, ed, hbuf); err != nil {
81+
if err := s.sendHandshakeMessage(hs, nil, hbuf); err != nil {
8682
return fmt.Errorf("error sending handshake message: %w", err)
8783
}
8884

@@ -103,7 +99,11 @@ func (s *secureSession) runHandshake(ctx context.Context) (err error) {
10399

104100
// stage 2 //
105101
// Handshake Msg Len = len(DHT static key) + MAC(static key is encrypted) + len(Payload) + MAC(payload is encrypted)
106-
payload, err := s.generateHandshakePayload(kp, nil)
102+
var ed []byte
103+
if s.initiatorEarlyDataHandler != nil {
104+
ed = s.initiatorEarlyDataHandler.Send(ctx, s.insecureConn, s.remoteID)
105+
}
106+
payload, err := s.generateHandshakePayload(kp, ed)
107107
if err != nil {
108108
return err
109109
}
@@ -113,15 +113,9 @@ func (s *secureSession) runHandshake(ctx context.Context) (err error) {
113113
return nil
114114
} else {
115115
// stage 0 //
116-
initialPayload, err := s.readHandshakeMessage(hs)
117-
if err != nil {
116+
if _, err := s.readHandshakeMessage(hs); err != nil {
118117
return fmt.Errorf("error reading handshake message: %w", err)
119118
}
120-
if s.responderEarlyDataHandler != nil {
121-
if err := s.responderEarlyDataHandler.Received(ctx, s.insecureConn, initialPayload); err != nil {
122-
return err
123-
}
124-
}
125119

126120
// stage 1 //
127121
// Handshake Msg Len = len(DH ephemeral key) + len(DHT static key) + MAC(static key is encrypted) + len(Payload) +
@@ -143,9 +137,16 @@ func (s *secureSession) runHandshake(ctx context.Context) (err error) {
143137
if err != nil {
144138
return fmt.Errorf("error reading handshake message: %w", err)
145139
}
146-
// we don't expect any early data on this message
147-
_, err = s.handleRemoteHandshakePayload(plaintext, hs.PeerStatic())
148-
return err
140+
rcvdEd, err := s.handleRemoteHandshakePayload(plaintext, hs.PeerStatic())
141+
if err != nil {
142+
return err
143+
}
144+
if s.responderEarlyDataHandler != nil {
145+
if err := s.responderEarlyDataHandler.Received(ctx, s.insecureConn, rcvdEd); err != nil {
146+
return err
147+
}
148+
}
149+
return nil
149150
}
150151
}
151152

p2p/security/noise/session_transport.go

+8-11
Original file line numberDiff line numberDiff line change
@@ -22,27 +22,24 @@ func Prologue(prologue []byte) SessionOption {
2222
}
2323
}
2424

25-
// EarlyDataHandler defines what the application payload is for either the first
26-
// (if initiator) or second (if responder) handshake message. And defines the
25+
// EarlyDataHandler defines what the application payload is for either the second
26+
// (if initiator) or third (if responder) handshake message, and defines the
2727
// logic for handling the other side's early data. Note the early data in the
28-
// first handshake message is **unencrypted**, but will be retroactively
29-
// authenticated if the handshake completes.
28+
// second handshake message is encrypted, but the peer is not authenticated at that point.
3029
type EarlyDataHandler interface {
31-
// Send for the initiator is called for the client before sending the first
32-
// handshake message. Defines the application payload for the first message.
33-
// This payload is sent **unencrypted**.
34-
// Send for the responder is called before sending the second handshake message. This is encrypted.
30+
// Send for the initiator is called for the client before sending the third
31+
// handshake message. Defines the application payload for the third message.
32+
// Send for the responder is called before sending the second handshake message.
3533
Send(context.Context, net.Conn, peer.ID) []byte
3634
// Received for the initiator is called when the second handshake message
3735
// from the responder is received.
38-
// Received for the responder is called when the first handshake message
36+
// Received for the responder is called when the third handshake message
3937
// from the initiator is received.
4038
Received(context.Context, net.Conn, []byte) error
4139
}
4240

4341
// EarlyData sets the `EarlyDataHandler` for the initiator and responder roles.
44-
// See `EarlyDataHandler` for more details. Note: an initiator's early data will
45-
// be sent **unencrypted** in the first handshake message.
42+
// See `EarlyDataHandler` for more details.
4643
func EarlyData(initiator, responder EarlyDataHandler) SessionOption {
4744
return func(s *SessionTransport) error {
4845
s.initiatorEarlyDataHandler = initiator

p2p/security/noise/transport_test.go

+14-3
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,12 @@ func TestEarlyDataAccepted(t *testing.T) {
465465

466466
conn, err := initTransport.SecureOutbound(context.Background(), respConn, tpt.localID)
467467
require.NoError(t, err)
468+
select {
469+
case <-time.After(500 * time.Millisecond):
470+
t.Fatal("timeout")
471+
case err := <-errChan:
472+
require.NoError(t, err)
473+
}
468474
defer conn.Close()
469475
}
470476

@@ -494,7 +500,6 @@ func TestEarlyDataAccepted(t *testing.T) {
494500

495501
func TestEarlyDataRejected(t *testing.T) {
496502
handshake := func(t *testing.T, client, server EarlyDataHandler) (clientErr, serverErr error) {
497-
t.Helper()
498503
initTransport, err := newTestTransport(t, crypto.Ed25519, 2048).WithSessionOptions(EarlyData(client, nil))
499504
require.NoError(t, err)
500505
tpt := newTestTransport(t, crypto.Ed25519, 2048)
@@ -509,7 +514,13 @@ func TestEarlyDataRejected(t *testing.T) {
509514
errChan <- err
510515
}()
511516

512-
_, clientErr = initTransport.SecureOutbound(context.Background(), respConn, tpt.localID)
517+
// As early data is sent with the last handshake message, the handshake will appear
518+
// to succeed for the client.
519+
var conn sec.SecureConn
520+
conn, clientErr = initTransport.SecureOutbound(context.Background(), respConn, tpt.localID)
521+
if clientErr == nil {
522+
_, clientErr = conn.Read([]byte{0})
523+
}
513524

514525
select {
515526
case <-time.After(500 * time.Millisecond):
@@ -541,7 +552,7 @@ func TestEarlyDataRejected(t *testing.T) {
541552
})
542553
}
543554

544-
func TestEarlyDataAcceptedWithNoHandler(t *testing.T) {
555+
func TestEarlyfffDataAcceptedWithNoHandler(t *testing.T) {
545556
clientEDH := &earlyDataHandler{
546557
send: func(ctx context.Context, conn net.Conn, id peer.ID) []byte { return []byte("foobar") },
547558
}

p2p/transport/webtransport/transport_test.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,11 @@ func TestHashVerification(t *testing.T) {
162162
})
163163

164164
t.Run("fails when adding a wrong hash", func(t *testing.T) {
165-
_, err := tr2.Dial(context.Background(), ln.Multiaddr().Encapsulate(foobarHash), serverID)
166-
require.Error(t, err)
165+
conn, err := tr2.Dial(context.Background(), ln.Multiaddr().Encapsulate(foobarHash), serverID)
166+
if err != nil {
167+
_, err = conn.AcceptStream()
168+
require.Error(t, err)
169+
}
167170
})
168171

169172
require.NoError(t, ln.Close())

0 commit comments

Comments
 (0)