Skip to content

Commit

Permalink
test(qbase): add test for writing initial packet with transparent keys
Browse files Browse the repository at this point in the history
  • Loading branch information
huster-zhangpeng committed Nov 27, 2024
1 parent 4cba836 commit fc5d8ad
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 3 deletions.
2 changes: 1 addition & 1 deletion gm-quic/examples/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ async fn run(options: Opt) -> Result<(), Box<dyn std::error::Error>> {
.install_default()
.expect("Failed to install rustls crypto provider");

let server = QuicServer::buidler()
let server = QuicServer::builder()
.with_supported_versions([0x00000001u32])
.without_cert_verifier()
.with_single_cert_files(options.cert, options.key)?
Expand Down
2 changes: 1 addition & 1 deletion gm-quic/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub struct QuicServer {

impl QuicServer {
/// Start to build a QuicServer.
pub fn buidler() -> QuicServerBuilder<TlsServerConfigBuilder<WantsVerifier>> {
pub fn builder() -> QuicServerBuilder<TlsServerConfigBuilder<WantsVerifier>> {
QuicServerBuilder {
passive_listening: false,
supported_versions: Vec::with_capacity(2),
Expand Down
2 changes: 1 addition & 1 deletion h3-shim/examples/h3-server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ pub async fn run(opt: Opt) -> Result<(), Box<dyn std::error::Error + Send + Sync
}
let Certs { cert, key } = opt.certs;

let quic_server = ::gm_quic::QuicServer::buidler()
let quic_server = ::gm_quic::QuicServer::builder()
.with_supported_versions([1u32])
.without_cert_verifier()
.enable_sni()
Expand Down
1 change: 1 addition & 0 deletions qbase/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ thiserror = { workspace = true }

[dev-dependencies]
tokio = { workspace = true, features = ["test-util", "macros"] }
rustls = { workspace = true, features = ["ring"] }
151 changes: 151 additions & 0 deletions qbase/src/packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,3 +391,154 @@ unsafe impl BufMut for PacketWriter<'_> {
UninitSlice::new(&mut self.buffer[self.cursor..self.end])
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::frame::CryptoFrame;

struct TransparentKeys(rustls::quic::DirectionalKeys);

impl TransparentKeys {
pub fn new() -> Self {
rustls::crypto::ring::default_provider()
.install_default()
.expect("Failed to install ring crypto provider");
let suite = rustls::crypto::ring::default_provider()
.cipher_suites
.iter()
.find_map(|cs| match (cs.suite(), cs.tls13()) {
(rustls::CipherSuite::TLS13_AES_128_GCM_SHA256, Some(suite)) => {
Some(suite.quic_suite())
}
_ => None,
})
.flatten()
.unwrap();

let pk = suite.keys(
"meanless".as_bytes(),
rustls::Side::Client,
rustls::quic::Version::V1,
);
TransparentKeys(pk.local)
}
}

impl rustls::quic::PacketKey for TransparentKeys {
fn decrypt_in_place<'a>(
&self,
_packet_number: u64,
_header: &[u8],
payload: &'a mut [u8],
) -> Result<&'a [u8], rustls::Error> {
Ok(&payload[..payload.len() - self.tag_len()])
}

fn encrypt_in_place(
&self,
_packet_number: u64,
_header: &[u8],
_payload: &mut [u8],
) -> Result<rustls::quic::Tag, rustls::Error> {
Ok(rustls::quic::Tag::from("transparent_keys".as_bytes()))
}

fn confidentiality_limit(&self) -> u64 {
self.0.packet.confidentiality_limit()
}

fn integrity_limit(&self) -> u64 {
self.0.packet.integrity_limit()
}

fn tag_len(&self) -> usize {
self.0.packet.tag_len()
}
}

impl rustls::quic::HeaderProtectionKey for TransparentKeys {
fn decrypt_in_place(
&self,
_sample: &[u8],
_first_byte: &mut u8,
_payload: &mut [u8],
) -> Result<(), rustls::Error> {
Ok(())
}

fn encrypt_in_place(
&self,
_sample: &[u8],
_first_byte: &mut u8,
_payload: &mut [u8],
) -> Result<(), rustls::Error> {
Ok(())
}

fn sample_len(&self) -> usize {
self.0.header.sample_len()
}
}

#[test]
fn test_initial_packet_writer() {
let mut buffer = vec![0u8; 128];
let header = LongHeaderBuilder::with_cid(
ConnectionId::from_slice("testdcid".as_bytes()),
ConnectionId::from_slice("testscid".as_bytes()),
)
.initial(Vec::with_capacity(0));

let pn = (0, PacketNumber::encode(0, 0));
let tag_len = 16;

let mut writer = PacketWriter::new(&header, &mut buffer, pn, tag_len).unwrap();
let frame = CryptoFrame {
length: VarInt::from_u32(12),
offset: VarInt::from_u32(0),
};
writer.dump_frame_with_data(frame, "client_hello".as_bytes());

assert!(writer.is_ack_eliciting());
assert!(writer.in_flight());

let transparent_keys = TransparentKeys::new();
let packet = writer.encrypt_long_packet(&transparent_keys, &transparent_keys);
assert!(packet.is_ack_eliciting());
assert!(packet.in_flight());
assert_eq!(packet.len(), 58);
assert_eq!(
packet.deref(),
[
// initial packet:
// header form (1) = 1,, long header
// fixed bit (1) = 1,
// long packet type (2) = 0, initial packet
// reserved bits (2) = 0,
// packet number length (2) = 0, 1 byte
192, // first byte
0, 0, 0, 1, // quic version
// destination connection id, "testdcid"
8, // dcid length
b't', b'e', b's', b't', b'd', b'c', b'i', b'd', // dcid bytes
// source connection id, "testscid"
8, // scid length
b't', b'e', b's', b't', b's', b'c', b'i', b'd', // scid bytes
0, // token length, no token
64, 16, // payload length, 2 bytes encoded varint
0, // encoded packet number
// crypto frame header
6, // crypto frame type
0, // crypto frame offset
12, // crypto frame length
// crypto frame data, "client hello"
b'c', b'l', b'i', b'e', b'n', b't', b'_', b'h', b'e', b'l', b'l', b'o',
// tag, "transparent_keys"
b't', b'r', b'a', b'n', b's', b'p', b'a', b'r', b'e', b'n', b't', b'_', b'k', b'e',
b'y', b's',
]
.as_slice()
);
}
}

0 comments on commit fc5d8ad

Please sign in to comment.