diff --git a/gumble/gumble/udp15_test.go b/gumble/gumble/udp15_test.go index e38599f..3870938 100644 --- a/gumble/gumble/udp15_test.go +++ b/gumble/gumble/udp15_test.go @@ -31,6 +31,33 @@ func TestAdvanceIV(t *testing.T) { } } +// Regression coverage for the native IV carry path at the 255->256 wrap. +func TestCryptState15DecryptsAcrossIVByteWrap(t *testing.T) { + key := mustDecodeHex("93360b0f86a926c4561563469026eb94") + clientNonce := mustDecodeHex("ff000000000000000000000000000000") + serverNonce := mustDecodeHex("ff000000000000000000000000000000") + out, in := &cryptState15{}, &cryptState15{} + if err := out.setup15(key, clientNonce, serverNonce); err != nil { + t.Fatal(err) + } + if err := in.setup15(key, clientNonce, serverNonce); err != nil { + t.Fatal(err) + } + for _, payload := range [][]byte{[]byte("wrap-1"), []byte("wrap-2")} { + packet, err := out.encrypt15(payload) + if err != nil { + t.Fatal(err) + } + plain, err := in.decrypt15(packet) + if err != nil || !bytes.Equal(plain, payload) { + t.Fatalf("wrap decrypt %q: %v", plain, err) + } + } + if in.decryptIV[0] != 1 || in.decryptIV[1] != 1 { + t.Fatalf("unexpected wrapped IV %x", in.decryptIV[:2]) + } +} + // Test OCB round-trip: encrypt then decrypt should recover plaintext. func TestOCB15RoundTrip(t *testing.T) { key := mustDecodeHex("000102030405060708090a0b0c0d0e0f")