vest/
lib.rs

1#![crate_name = "vest"]
2#![crate_type = "lib"]
3//! Vest is a *formally verified* library for parsing and serializing binary data, using combinators.
4//!
5//! # Background
6//!
7//! **Parsing and serialization of binary data**
8//!
9//! In the context of binary formats, parsing refers to the process of interpreting raw byte
10//! sequences as structured data, while serialization refers to the reverse process of encoding
11//! structured data as raw byte sequences. Binary formats are essential in domains like network
12//! protocols, file systems, and embedded systems, where data is often transmitted or stored in
13//! a compact binary form.
14//!
15//! **Formally verified parsing and serialization**
16//!
17//! Binary formats are notoriously difficult to parse and serialize correctly, due to the
18//! complexity of the formats and the potential for errors in the implementation. Vest aims to
19//! address this problem by *formally verifying* the correctness and security of the parsing and
20//! serialization code using the Rust type system and [Verus](https://github.com/verus-lang/verus),
21//! a deductive verification tool for Rust.
22//!
23//! We don't use `unsafe` so the Rust type system provides us with strong guarantees about the
24//! memory safety of the code. We use Verus to verify the more nuanced properties of the code,
25//! such as the top-level round-trip properties of the parsing and serialization functions.
26//! - For every binary sequence `b`, if `parse(b)` succeeds, producing a result `(n, m)`, then
27//! `serialize(m)` should reproduce the original input `b`, truncated to `n` bytes.
28//! - For every structured data `m`, if `serialize(m)` succeeds, producing a binary sequence `b`,
29//! then `parse(b)` should successfully consuming the entire input `b` and produce the original
30//! structured data `m`.
31//!
32//! These round-trip properties ensure that the parsing and serialization functions are mutual
33//! inverses and hence immune to parser malleability attacks ([EverParse](https://www.microsoft.com/en-us/research/publication/everparse/))
34//! and format confusion attacks ([Comparse](https://dl.acm.org/doi/10.1145/3576915.3623201)).
35//!
36//! **Parser and serializer combinators**
37//!
38//! It's certainly possible to implement and verify parsers and serializers for single protocol
39//! formats or file formats manually, but this approach is tedious, and not reusable. Binary
40//! formats often share common patterns, such as fixed-size fields, variable-size fields, a
41//! sequence of fields, a tagged union of fields, etc. Vest provides a set of parser and serializer
42//! combinators that can be used to build complex parsers and serializers from simple ones, where
43//! the properties of the combinators are verified once and for all.
44//!
45//! # Example: Parsing and serializing a pair of bytes
46//!
47//! ```text
48//! use vest::regular::bytes::Bytes;
49//!
50//! let pair_of_bytes = (Bytes(1), Bytes(2));
51//!
52//! let input = &[0x10; 10];
53//! let (consumed, (a, b)) = pair_of_bytes.parse(input)?;
54//!
55//! let mut output = vec![0x00; 40];
56//! let written = pair_of_bytes.serialize((a, b), &mut output, 0)?;
57//!
58//! proof { pair_of_bytes.theorem_parse_serialize_roundtrip(input@); }
59//! assert(written == consumed);
60//! assert(&output[..written]@, &input[..written]@);
61//! ```
62//!
63//! # Example: Constructing a new combinator
64//!
65//! ```text
66//! use vest::regular::uints::U8;
67//! use vest::regular::refined::{Refined, Pred};
68//!
69//! pub struct EvenU8;
70//! impl Pred for EvenU8 {
71//!     type Input<'a> = u8;
72//!     fn apply(&self, i: &Self::Input<'_>) -> bool {
73//!         *i % 2 == 0
74//!     }
75//! }
76//!
77//! let even_u8 = Refined { inner: U8, predicate: EvenU8 };
78//!
79//! let mut output = vec![0x00; 40];
80//! let ten = 10u8;
81//! let written = even_u8.serialize(ten, &mut output, 0)?;
82//!
83//! let (consumed, parsed) = even_u8.parse(output.as_slice())?;
84//!
85//! proof { even_u8.theorem_serialize_parse_roundtrip(ten@); }
86//! assert(written == consumed);
87//! assert(parsed@, ten@);
88//! ```
89
90// mod examples;
91/// Definitions for parser and serializer combinators and their properties.
92pub mod properties;
93/// Regular parser and serializer combinators.
94pub mod regular;
95/// Utility functions and types.
96pub mod utils;
97//// Constant-time parser and serializer combinators.
98// mod secret;
99/// Error types
100#[allow(missing_docs)]
101pub mod errors;