mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-04 12:47:36 +03:00
uTLS is not yet bumped to the new version, so this commit breaks the dependencies relationship by getting rid of the local replace.
101 lines
3.1 KiB
Go
101 lines
3.1 KiB
Go
package testutils
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/refraction-networking/uquic/internal/handshake"
|
|
"github.com/refraction-networking/uquic/internal/protocol"
|
|
"github.com/refraction-networking/uquic/internal/wire"
|
|
)
|
|
|
|
// Utilities for simulating packet injection and man-in-the-middle (MITM) attacker tests.
|
|
// Do not use for non-testing purposes.
|
|
|
|
// writePacket returns a new raw packet with the specified header and payload
|
|
func writePacket(hdr *wire.ExtendedHeader, data []byte) []byte {
|
|
b, err := hdr.Append(nil, hdr.Version)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("failed to write header: %s", err))
|
|
}
|
|
return append(b, data...)
|
|
}
|
|
|
|
// packRawPayload returns a new raw payload containing given frames
|
|
func packRawPayload(version protocol.VersionNumber, frames []wire.Frame) []byte {
|
|
var b []byte
|
|
for _, cf := range frames {
|
|
var err error
|
|
b, err = cf.Append(b, version)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
return b
|
|
}
|
|
|
|
// ComposeInitialPacket returns an Initial packet encrypted under key
|
|
// (the original destination connection ID) containing specified frames
|
|
func ComposeInitialPacket(srcConnID protocol.ConnectionID, destConnID protocol.ConnectionID, version protocol.VersionNumber, key protocol.ConnectionID, frames []wire.Frame) []byte {
|
|
sealer, _ := handshake.NewInitialAEAD(key, protocol.PerspectiveServer, version)
|
|
|
|
// compose payload
|
|
var payload []byte
|
|
if len(frames) == 0 {
|
|
payload = make([]byte, protocol.MinInitialPacketSize)
|
|
} else {
|
|
payload = packRawPayload(version, frames)
|
|
}
|
|
|
|
// compose Initial header
|
|
payloadSize := len(payload)
|
|
pnLength := protocol.PacketNumberLen4
|
|
length := payloadSize + int(pnLength) + sealer.Overhead()
|
|
hdr := &wire.ExtendedHeader{
|
|
Header: wire.Header{
|
|
Type: protocol.PacketTypeInitial,
|
|
SrcConnectionID: srcConnID,
|
|
DestConnectionID: destConnID,
|
|
Length: protocol.ByteCount(length),
|
|
Version: version,
|
|
},
|
|
PacketNumberLen: pnLength,
|
|
PacketNumber: 0x0,
|
|
}
|
|
|
|
raw := writePacket(hdr, payload)
|
|
|
|
// encrypt payload and header
|
|
payloadOffset := len(raw) - payloadSize
|
|
var encrypted []byte
|
|
encrypted = sealer.Seal(encrypted, payload, hdr.PacketNumber, raw[:payloadOffset])
|
|
hdrBytes := raw[0:payloadOffset]
|
|
encrypted = append(hdrBytes, encrypted...)
|
|
pnOffset := payloadOffset - int(pnLength) // packet number offset
|
|
sealer.EncryptHeader(
|
|
encrypted[payloadOffset:payloadOffset+16], // first 16 bytes of payload (sample)
|
|
&encrypted[0], // first byte of header
|
|
encrypted[pnOffset:payloadOffset], // packet number bytes
|
|
)
|
|
return encrypted
|
|
}
|
|
|
|
// ComposeRetryPacket returns a new raw Retry Packet
|
|
func ComposeRetryPacket(
|
|
srcConnID protocol.ConnectionID,
|
|
destConnID protocol.ConnectionID,
|
|
origDestConnID protocol.ConnectionID,
|
|
token []byte,
|
|
version protocol.VersionNumber,
|
|
) []byte {
|
|
hdr := &wire.ExtendedHeader{
|
|
Header: wire.Header{
|
|
Type: protocol.PacketTypeRetry,
|
|
SrcConnectionID: srcConnID,
|
|
DestConnectionID: destConnID,
|
|
Token: token,
|
|
Version: version,
|
|
},
|
|
}
|
|
data := writePacket(hdr, nil)
|
|
return append(data, handshake.GetRetryIntegrityTag(data, origDestConnID, version)[:]...)
|
|
}
|