| Crates.io | dimpl |
| lib.rs | dimpl |
| version | 0.2.4 |
| created_at | 2025-09-27 11:38:38.607965+00 |
| updated_at | 2026-01-25 18:56:58.805408+00 |
| description | DTLS 1.2 implementation (Sans‑IO, Sync) |
| homepage | |
| repository | https://github.com/algesten/dimpl |
| max_upload_size | |
| id | 1857216 |
| size | 572,469 |
dimpl — DTLS 1.2 implementation (Sans‑IO, Sync)
dimpl is a focused DTLS 1.2 implementation aimed at WebRTC. It is a Sans‑IO state machine you embed into your own UDP/RTC event loop: you feed incoming datagrams, poll for outgoing records or timers, and wire up certificate verification and SRTP key export yourself.
forbid(unsafe_code) throughout the crate.dimpl was built as a support package for str0m, with WebRTC as its primary use case, which currently uses DTLS 1.2. The author is not a cryptography expert; however, our understanding is that DTLS 1.2 is acceptable provided we narrow the protocol's scope—for example, by supporting only specific cipher suites and hash algorithms and by requiring the Extended Master Secret extension.
If you are interested in extending this crate to support DTLS 1.3 and/or additional cipher suites or hash algorithms, we welcome collaboration, but we are not planning to lead such initiatives.
ECDHE_ECDSA_AES256_GCM_SHA384ECDHE_ECDSA_AES128_GCM_SHA256SRTP_AEAD_AES_256_GCM,
SRTP_AEAD_AES_128_GCM, and SRTP_AES128_CM_SHA1_80 (RFC 5764, RFC 7714).During the handshake the engine emits Output::PeerCert with the peer's
leaf certificate (DER). The crate uses that certificate to verify DTLS
handshake messages, but it does not perform any PKI validation. Your
application is responsible for validating the peer certificate according to
your policy (fingerprint, chain building, name/EKU checks, pinning, etc.).
Drive the engine with three calls:
Dtls::handle_packet — feed an entire received UDP datagram.Dtls::poll_output — drain pending output: DTLS records, timers, events.Dtls::handle_timeout — trigger retransmissions/time‑based progress.The output is an Output enum with borrowed references into your provided buffer:
Packet(&[u8]): send on your UDP socketTimeout(Instant): schedule a timer and call handle_timeout at/after itConnected: handshake completePeerCert(&[u8]): peer leaf certificate (DER) — validate in your appKeyingMaterial(KeyingMaterial, SrtpProfile): DTLS‑SRTP exportApplicationData(&[u8]): plaintext received from peeruse std::sync::Arc;
use std::time::Instant;
use dimpl::{certificate, Config, Dtls, Output};
// Stub I/O to keep the example focused on the state machine
enum Event { Udp(Vec<u8>), Timer(Instant) }
fn wait_next_event(_next_wake: Option<Instant>) -> Event { Event::Udp(Vec::new()) }
fn send_udp(_bytes: &[u8]) {}
fn example_event_loop(mut dtls: Dtls) -> Result<(), dimpl::Error> {
let mut next_wake: Option<Instant> = None;
loop {
// Drain engine output until we have to wait for I/O or a timer
let mut out_buf = vec![0u8; 2048];
loop {
match dtls.poll_output(&mut out_buf) {
Output::Packet(p) => send_udp(p),
Output::Timeout(t) => { next_wake = Some(t); break; }
Output::Connected => {
// DTLS established — application may start sending
}
Output::PeerCert(_der) => {
// Inspect peer leaf certificate if desired
}
Output::KeyingMaterial(_km, _profile) => {
// Provide to SRTP stack
}
Output::ApplicationData(_data) => {
// Deliver plaintext to application
}
}
}
// Block waiting for either UDP input or the scheduled timeout
match wait_next_event(next_wake) {
Event::Udp(pkt) => dtls.handle_packet(&pkt)?,
Event::Timer(now) => dtls.handle_timeout(now)?,
}
}
}
fn mk_dtls_client() -> Dtls {
let cert = certificate::generate_self_signed_certificate().unwrap();
let cfg = Arc::new(Config::default());
let mut dtls = Dtls::new(cfg, cert);
dtls.set_active(true); // client role
dtls
}
// Putting it together
let dtls = mk_dtls_client();
let _ = example_event_loop(dtls);
Rust 1.81.0
License: MIT OR Apache-2.0