From f75f932620dfee8fce8ec64e3db3bd4132541661 Mon Sep 17 00:00:00 2001 From: benma's agent Date: Tue, 13 Oct 2026 11:06:19 +0200 Subject: [PATCH] u2fhid: reject oversized outgoing payloads U2F HID permits one initialization packet and at most 128 continuation packets, limiting payloads to 7609 bytes with 64-byte reports. sendFrame previously emitted continuation sequence numbers above 127, and payloads larger than 65535 bytes also had their advertised length truncated. Reject payloads above the protocol limit before allocating packet buffers or writing to the device. Derive the limit from the report payload sizes. --- communication/u2fhid/u2fhid.go | 11 +++++++++-- communication/u2fhid/u2fhid_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/communication/u2fhid/u2fhid.go b/communication/u2fhid/u2fhid.go index 2b58b4a..65af17e 100644 --- a/communication/u2fhid/u2fhid.go +++ b/communication/u2fhid/u2fhid.go @@ -83,6 +83,15 @@ func (communication *Communication) sendFrame(msg string) error { if dataLen == 0 { return nil } + const ( + initPayloadSize = writeReportSize - 7 + contPayloadSize = writeReportSize - 5 + // Continuation sequence numbers range from 0 to 127. + maxPayloadSize = initPayloadSize + 128*contPayloadSize + ) + if dataLen > maxPayloadSize { + return errp.Newf("message too large: %d bytes exceeds maximum of %d", dataLen, maxPayloadSize) + } readBuffer := bytes.NewBufferString(msg) out := newBuffer() @@ -90,8 +99,6 @@ func (communication *Communication) sendFrame(msg string) error { // Calculate how large the `out` buffer should be. Round up to an equal // number of writeReportSize sized bytes outLen := writeReportSize - initPayloadSize := writeReportSize - 7 - contPayloadSize := writeReportSize - 5 if dataLen > initPayloadSize { contLen := dataLen - initPayloadSize outLen += ((contLen + contPayloadSize - 1) / contPayloadSize) * writeReportSize diff --git a/communication/u2fhid/u2fhid_test.go b/communication/u2fhid/u2fhid_test.go index fa2ce1f..8943cec 100644 --- a/communication/u2fhid/u2fhid_test.go +++ b/communication/u2fhid/u2fhid_test.go @@ -108,6 +108,12 @@ func TestSendFrame(t *testing.T) { chunkSize: 1, expectedFrames: strings.Repeat("d", 64*3), }, + { + name: "maximum payload", + input: strings.Repeat("e", 7609), + chunkSize: 64, + expectedFrames: strings.Repeat("e", 7609), + }, } for _, tt := range tests { @@ -177,3 +183,24 @@ func TestSendFrame(t *testing.T) { }) } } + +func TestSendFrameRejectsOversizedMessages(t *testing.T) { + for _, tt := range []struct { + name string + size int + }{ + {name: "one byte over maximum", size: 7610}, + {name: "length exceeds uint16", size: 1 << 16}, + } { + t.Run(tt.name, func(t *testing.T) { + rw := &testRW{} + comm := NewCommunication(rw, 0xab) + if err := comm.SendFrame(strings.Repeat("a", tt.size)); err == nil { + t.Error("expected oversized message to be rejected") + } + if rw.writeBuffer.Len() != 0 { + t.Error("oversized message wrote packets to the device") + } + }) + } +}