Skip to content

Commit

Permalink
Minor docs tweaks (#316)
Browse files Browse the repository at this point in the history
* Improve home page

* Add video and poster

* Add some overview

---------

Co-authored-by: Michael Mera <[email protected]>
  • Loading branch information
maxammann and michaelmera committed May 15, 2024
1 parent a8c6986 commit c838ce0
Show file tree
Hide file tree
Showing 10 changed files with 1,980 additions and 701 deletions.
4 changes: 4 additions & 0 deletions docs/docs/libafl-architecture_new.drawio.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
137 changes: 133 additions & 4 deletions docs/docs/overview.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,140 @@
---
title: 'Overview'
---
import Architecture from './libafl-architecture_new.drawio.svg';

:::warning[Ongoing Work]

This page is currently under development. Information presented here might be incomplete or outdated.
# What is tlspuffin?

:::
The tlspuffin fuzzer is the reference implementation for the [Dolev-Yao fuzzing approach](https://www.computer.org/csdl/pds/api/csdl/proceedings/download-article/1Ub234bjuWA/pdf).
The fuzzer mostly fuzzes TLS implementations like OpenSSL, LibreSSL, or wolfSSL, but can also fuzz other cryptographic protocols like SSH. Internally, puffin uses [LibAFL](https://aflplus.plus/libafl-book/) to drive the fuzzing loop.

## Fuzzing Loop

The following image shows the terminology and the flow of test cases through the fuzzer. We typically start the fuzzing with some "happy protocol flows" in the corpus.

<Architecture />

- **State:** Comprising "Corpus" and "Objectives," this stores all test cases with their traces and metadata, with the Objectives focusing specifically on cases that have triggered security violations.
- **Scheduler:** This selects and schedules test cases from the Corpus for mutation and re-testing, based on various strategic criteria.
- **Mutational Stage:** The "Mutator" alters a trace from a scheduled test case to create a mutated test case, which is then sent to the harness.
- **Harness:** The harness executes the mutated test case in the Program Under Test (PUT) and observes the execution.
- **Feedback:** This component evaluates the observed outcomes of the test case execution, adding interesting cases to the Corpus for further testing.
- **Objective Oracle:** It checks test cases for violations of security policies, adding those that do violate to the Objectives for focused analysis.

## Implementation

From an implementation perspective, several modules exist to make the fuzzer reusable:

- [puffin](https://github.com/tlspuffin/tlspuffin/tree/main/puffin) - Core fuzzing engine which is protocol agnostic.
- [tlspuffin](https://github.com/tlspuffin/tlspuffin/tree/main/tlspuffin) - TLS fuzzer which uses puffin and is implementation agnostic.
- [sshpuffin (WIP)](https://github.com/tlspuffin/tlspuffin/tree/main/sshpuffin) - SSH fuzzer which uses puffin and is implementation agnostic.
- [puts](https://github.com/tlspuffin/tlspuffin/tree/main/puts) - Linkable Programs Under Test that can be linked with tlspuffin or sshpuffin.


```mermaid
graph TD;
tlspuffin-- trait ProtocolBehavior -->puffin;
sshpuffin-- trait ProtocolBehavior -->puffin;
puffin-->LibAFL;
puffin-->puts;
puts-- trait Put -->wolfSSL;
puts-- trait Put -->OpenSSL;
puts-->...;
```

The interfaces between the modules are defined by the following Rust traits which define what a protocol is and what a Put is.

#### Protocol

```Rust
pub trait ProtocolBehavior: 'static {
type Claim: Claim;
type SecurityViolationPolicy: SecurityViolationPolicy<Self::Claim>;

type ProtocolMessage: ProtocolMessage<Self::OpaqueProtocolMessage>;
type OpaqueProtocolMessage: OpaqueProtocolMessage;

type Matcher: Matcher
+ for<'a> TryFrom<&'a MessageResult<Self::ProtocolMessage, Self::OpaqueProtocolMessage>>;

/// Get the signature that is used in the protocol
fn signature() -> &'static Signature;

/// Creates a sane initial seed corpus.
fn create_corpus() -> Vec<(Trace<Self::Matcher>, &'static str)>;
}

pub struct MessageResult<M: ProtocolMessage<O>, O: OpaqueProtocolMessage>(pub Option<M>, pub O);

/// A structured message. This type defines how all possible messages of a protocol.
/// Usually this is implemented using an `enum`.
pub trait ProtocolMessage<O: OpaqueProtocolMessage>: Clone + Debug {
fn create_opaque(&self) -> O;
fn debug(&self, info: &str);
fn extract_knowledge(&self) -> Result<Vec<Box<dyn VariableData>>, Error>;
}

/// A non-structured version of [`ProtocolMessage`]. This can be used for example for encrypted messages
/// which do not have a structure.
pub trait OpaqueProtocolMessage: Clone + Debug + Codec {
fn debug(&self, info: &str);

fn extract_knowledge(&self) -> Result<Vec<Box<dyn VariableData>>, Error>;
}
```


#### Put

```Rust
pub trait Put<PB: ProtocolBehavior>:
Stream<PB::ProtocolMessage, PB::OpaqueProtocolMessage> + 'static
{
/// Process incoming buffer, internal progress, can fill in the output buffer
fn progress(&mut self, agent_name: &AgentName) -> Result<(), Error>;

/// In-place reset of the state
fn reset(&mut self, agent_name: AgentName) -> Result<(), Error>;

fn descriptor(&self) -> &AgentDescriptor;

/// Register a new claim for agent_name
#[cfg(feature = "claims")]
fn register_claimer(&mut self, agent_name: AgentName);

/// Remove all claims in self
#[cfg(feature = "claims")]
fn deregister_claimer(&mut self);

/// Propagate agent changes to the PUT
fn rename_agent(&mut self, agent_name: AgentName) -> Result<(), Error>;

/// Returns a textual representation of the state in which self is
fn describe_state(&self) -> &str;

/// Checks whether the Put is in a good state
fn is_state_successful(&self) -> bool;

/// Make the PUT used by self deterministic in the future by making its PRNG "deterministic"
/// Now subsumed by Factory-level functions to reseed globally: `determinism_reseed`
fn determinism_reseed(&mut self) -> Result<(), Error>;

/// checks whether a agent is reusable with the descriptor
fn is_reusable_with(&self, other: &AgentDescriptor) -> bool {
let agent_descriptor = self.descriptor();
agent_descriptor.typ == other.typ && agent_descriptor.tls_version == other.tls_version
}

/// Shut down the PUT by consuming it and returning a string that summarizes the execution.
fn shutdown(&mut self) -> String;

/// Returns a textual representation of the version of the PUT used by self
fn version() -> String
where
Self: Sized;
}
```

# What Is tlspuffin?
8 changes: 7 additions & 1 deletion docs/docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,14 @@ const config: Config = {
prism: {
theme: prismThemes.github,
darkTheme: prismThemes.dracula,
},
}
} satisfies Preset.ThemeConfig,
themes: ['@docusaurus/theme-mermaid'],
// In order for Mermaid code blocks in Markdown to work,
// you also need to enable the Remark plugin with this option
markdown: {
mermaid: true,
},
};

export default config;
Loading

0 comments on commit c838ce0

Please sign in to comment.