Skip to content

Commit a4264bb

Browse files
authored
Merge pull request #2660 from CortexFoundation/dev
use Whoareyou.ChallengeData instead of storing encoded packet
2 parents af6dd8d + e07b3e5 commit a4264bb

File tree

5 files changed

+55
-39
lines changed

5 files changed

+55
-39
lines changed

cmd/devp2p/internal/v5test/discv5tests.go

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func (s *Suite) AllTests() []utesting.Test {
5151
{Name: "Ping", Fn: s.TestPing},
5252
{Name: "PingLargeRequestID", Fn: s.TestPingLargeRequestID},
5353
{Name: "PingMultiIP", Fn: s.TestPingMultiIP},
54-
{Name: "PingHandshakeInterrupted", Fn: s.TestPingHandshakeInterrupted},
54+
{Name: "HandshakeResend", Fn: s.TestHandshakeResend},
5555
{Name: "TalkRequest", Fn: s.TestTalkRequest},
5656
{Name: "FindnodeZeroDistance", Fn: s.TestFindnodeZeroDistance},
5757
{Name: "FindnodeResults", Fn: s.TestFindnodeResults},
@@ -157,32 +157,37 @@ the attempt from a different IP.`)
157157
}
158158
}
159159

160-
// This test starts a handshake, but doesn't finish it and sends a second ordinary message
161-
// packet instead of a handshake message packet. The remote node should respond with
162-
// another WHOAREYOU challenge for the second packet.
163-
func (s *Suite) TestPingHandshakeInterrupted(t *utesting.T) {
164-
t.Log(`TestPingHandshakeInterrupted starts a handshake, but doesn't finish it and sends a second ordinary message
165-
packet instead of a handshake message packet. The remote node should respond with
166-
another WHOAREYOU challenge for the second packet.`)
167-
160+
// TestHandshakeResend starts a handshake, but doesn't finish it and sends a second ordinary message
161+
// packet instead of a handshake message packet. The remote node should repeat the previous WHOAREYOU
162+
// challenge for the first PING.
163+
func (s *Suite) TestHandshakeResend(t *utesting.T) {
168164
conn, l1 := s.listen1(t)
169165
defer conn.close()
170166

171167
// First PING triggers challenge.
172168
ping := &v5wire.Ping{ReqID: conn.nextReqID()}
173169
conn.write(l1, ping, nil)
170+
var challenge1 *v5wire.Whoareyou
174171
switch resp := conn.read(l1).(type) {
175172
case *v5wire.Whoareyou:
173+
challenge1 = resp
176174
t.Logf("got WHOAREYOU for PING")
177175
default:
178176
t.Fatal("expected WHOAREYOU, got", resp)
179177
}
180178

181179
// Send second PING.
182180
ping2 := &v5wire.Ping{ReqID: conn.nextReqID()}
183-
switch resp := conn.reqresp(l1, ping2).(type) {
184-
case *v5wire.Pong:
185-
checkPong(t, resp, ping2, l1)
181+
conn.write(l1, ping2, nil)
182+
switch resp := conn.read(l1).(type) {
183+
case *v5wire.Whoareyou:
184+
if resp.Nonce != challenge1.Nonce {
185+
t.Fatalf("wrong nonce %x in WHOAREYOU (want %x)", resp.Nonce[:], challenge1.Nonce[:])
186+
}
187+
if !bytes.Equal(resp.ChallengeData, challenge1.ChallengeData) {
188+
t.Fatalf("wrong ChallengeData in resent WHOAREYOU (want %x)", resp.ChallengeData, challenge1.ChallengeData)
189+
}
190+
resp.Node = conn.remote
186191
default:
187192
t.Fatal("expected WHOAREYOU, got", resp)
188193
}

p2p/discover/v5_udp_test.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -856,10 +856,10 @@ type testCodecFrame struct {
856856
}
857857

858858
func (c *testCodec) Encode(toID enode.ID, addr string, p v5wire.Packet, _ *v5wire.Whoareyou) ([]byte, v5wire.Nonce, error) {
859-
// To match the behavior of v5wire.Codec, we return the cached encoding of
860-
// WHOAREYOU challenges.
861-
if wp, ok := p.(*v5wire.Whoareyou); ok && len(wp.Encoded) > 0 {
862-
return wp.Encoded, wp.Nonce, nil
859+
if wp, ok := p.(*v5wire.Whoareyou); ok && len(wp.ChallengeData) > 0 {
860+
// To match the behavior of v5wire.Codec, we return the cached encoding of
861+
// WHOAREYOU challenges.
862+
return wp.ChallengeData, wp.Nonce, nil
863863
}
864864

865865
c.ctr++
@@ -874,7 +874,7 @@ func (c *testCodec) Encode(toID enode.ID, addr string, p v5wire.Packet, _ *v5wir
874874
// Store recently sent challenges.
875875
if w, ok := p.(*v5wire.Whoareyou); ok {
876876
w.Nonce = authTag
877-
w.Encoded = frame
877+
w.ChallengeData = frame
878878
if c.sentChallenges == nil {
879879
c.sentChallenges = make(map[enode.ID]*v5wire.Whoareyou)
880880
}
@@ -911,6 +911,7 @@ func (c *testCodec) decodeFrame(input []byte) (frame testCodecFrame, p v5wire.Pa
911911
case v5wire.WhoareyouPacket:
912912
dec := new(v5wire.Whoareyou)
913913
err = rlp.DecodeBytes(frame.Packet, &dec)
914+
dec.ChallengeData = bytes.Clone(input)
914915
p = dec
915916
default:
916917
p, err = v5wire.DecodeMessage(frame.Ptype, frame.Packet)

p2p/discover/v5wire/encoding.go

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,16 @@ func (c *Codec) Encode(id enode.ID, addr string, packet Packet, challenge *Whoar
190190
)
191191
switch {
192192
case packet.Kind() == WhoareyouPacket:
193-
// just send the WHOAREYOU packet raw again, rather than the re-encoded challenge data
194193
w := packet.(*Whoareyou)
195-
if len(w.Encoded) > 0 {
196-
return w.Encoded, w.Nonce, nil
194+
if len(w.ChallengeData) > 0 {
195+
// This WHOAREYOU packet was encoded before, so it's a resend.
196+
// The unmasked packet content is stored in w.ChallengeData.
197+
// Just apply the masking again to finish encoding.
198+
c.buf.Reset()
199+
c.buf.Write(w.ChallengeData)
200+
copy(head.IV[:], w.ChallengeData)
201+
enc := applyMasking(id, head.IV, c.buf.Bytes())
202+
return enc, w.Nonce, nil
197203
}
198204
head, err = c.encodeWhoareyou(id, packet.(*Whoareyou))
199205
case challenge != nil:
@@ -228,7 +234,6 @@ func (c *Codec) Encode(id enode.ID, addr string, packet Packet, challenge *Whoar
228234
if err != nil {
229235
return nil, Nonce{}, err
230236
}
231-
challenge.Encoded = bytes.Clone(enc)
232237
c.sc.storeSentHandshake(id, addr, challenge)
233238
return enc, head.Nonce, err
234239
}
@@ -246,14 +251,10 @@ func (c *Codec) Encode(id enode.ID, addr string, packet Packet, challenge *Whoar
246251

247252
// EncodeRaw encodes a packet with the given header.
248253
func (c *Codec) EncodeRaw(id enode.ID, head Header, msgdata []byte) ([]byte, error) {
254+
// header
249255
c.writeHeaders(&head)
250-
251-
// Apply masking.
252-
masked := c.buf.Bytes()[sizeofMaskingIV:]
253-
mask := head.mask(id)
254-
mask.XORKeyStream(masked[:], masked[:])
255-
256-
// Write message data.
256+
applyMasking(id, head.IV, c.buf.Bytes())
257+
// message data
257258
c.buf.Write(msgdata)
258259
return c.buf.Bytes(), nil
259260
}
@@ -463,7 +464,7 @@ func (c *Codec) Decode(inputData []byte, addr string) (src enode.ID, n *enode.No
463464
// Unmask the static header.
464465
var head Header
465466
copy(head.IV[:], input[:sizeofMaskingIV])
466-
mask := head.mask(c.localnode.ID())
467+
mask := createMask(c.localnode.ID(), head.IV)
467468
staticHeader := input[sizeofMaskingIV:sizeofStaticPacketData]
468469
mask.XORKeyStream(staticHeader, staticHeader)
469470

@@ -679,10 +680,17 @@ func (h *StaticHeader) checkValid(packetLen int, protocolID [6]byte) error {
679680
}
680681

681682
// mask returns a cipher for 'masking' / 'unmasking' packet headers.
682-
func (h *Header) mask(destID enode.ID) cipher.Stream {
683+
func createMask(destID enode.ID, iv [16]byte) cipher.Stream {
683684
block, err := aes.NewCipher(destID[:16])
684685
if err != nil {
685686
panic("can't create cipher")
686687
}
687-
return cipher.NewCTR(block, h.IV[:])
688+
return cipher.NewCTR(block, iv[:])
689+
}
690+
691+
func applyMasking(destID enode.ID, iv [16]byte, packet []byte) []byte {
692+
masked := packet[sizeofMaskingIV:]
693+
mask := createMask(destID, iv)
694+
mask.XORKeyStream(masked[:], masked[:])
695+
return packet
688696
}

p2p/discover/v5wire/msg.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,20 @@ type (
6363

6464
// WHOAREYOU contains the handshake challenge.
6565
Whoareyou struct {
66-
ChallengeData []byte // Encoded challenge
67-
Nonce Nonce // Nonce of request packet
68-
IDNonce [16]byte // Identity proof data
69-
RecordSeq uint64 // ENR sequence number of recipient
66+
Nonce Nonce // Nonce of request packet
67+
IDNonce [16]byte // Identity proof data
68+
RecordSeq uint64 // ENR sequence number of recipient
7069

7170
// Node is the locally known node record of recipient.
7271
// This must be set by the caller of Encode.
73-
Node *enode.Node
72+
Node *enode.Node `rlp:"-"`
7473

75-
sent mclock.AbsTime // for handshake GC.
74+
// ChallengeData stores the unmasked encoding of the whole packet. This is the
75+
// input data for verification. It is assigned by both Encode and Decode
76+
// operations.
77+
ChallengeData []byte `rlp:"-"`
7678

77-
// Encoded is packet raw data for sending out, but should not be include in the RLP encoding.
78-
Encoded []byte `rlp:"-"`
79+
sent mclock.AbsTime // for handshake GC.
7980
}
8081

8182
// PING is sent during liveness checks.

rlp/raw_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package rlp
1818

1919
import (
2020
"bytes"
21+
"errors"
2122
"fmt"
2223
"io"
2324
"reflect"

0 commit comments

Comments
 (0)