# mlspp-sys
[](https://crates.io/crates/mlspp-sys)
[](https://docs.rs/mlspp-sys)
[](LICENSE)
> **AI DISCLAIMER**: This project was initially generated by Claude "Opus 4.6" language model. The work were supervised heavily but **no warranties express or implied** etc etc.
Raw FFI bindings to [Cisco mlspp](https://github.com/cisco/mlspp), a C++
implementation of the **Messaging Layer Security (MLS)** protocol
([RFC 9420](https://www.rfc-editor.org/rfc/rfc9420.html)).
MLS is an end-to-end encryption protocol designed for group messaging. It
provides forward secrecy, post-compromise security, and efficient group
key management for groups of any size.
## Features
| `vendored` | **yes** | Build mlspp from the vendored source tree via CMake |
| `system` | no | Link against a system-installed mlspp |
| `libdave-compat` | no | Enable compatibility with Discord's `libdave` |
## Build requirements
When the `vendored` feature is enabled (default), building this crate requires:
- A **C++17** compiler (GCC 8+, Clang 7+, MSVC 2019+)
- **CMake** 3.16+
- **OpenSSL** development headers (or set `OPENSSL_ROOT_DIR`)
## Installation
Add to your `Cargo.toml`:
```toml
[dependencies]
mlspp-sys = "0.3"
```
## Usage
All functions are `unsafe` and follow C conventions. Here is a minimal example
that creates a cipher suite and generates a signing key:
```rust
use mlspp_sys::*;
use std::ptr;
fn main() {
unsafe {
// Create a cipher suite (MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 = 1)
let cs = mlspp_cipher_suite_create(1);
if cs.is_null() {
let err = mlspp_last_error();
panic!("failed to create cipher suite: {:?}", std::ffi::CStr::from_ptr(err));
}
// Generate a signature key pair
let sig_priv = mlspp_signature_private_key_generate(cs);
assert!(!sig_priv.is_null(), "key generation failed");
// Clean up
mlspp_signature_private_key_free(sig_priv);
mlspp_cipher_suite_free(cs);
}
}
```
## Memory management
The API uses two patterns:
- **Opaque handles** (`mlspp_state_t`, `mlspp_session_t`, etc.) are
heap-allocated pointers. Each has a corresponding `_free` function that must
be called exactly once.
- **Byte buffers** (`mlspp_bytes_t`) are `{data, len}` pairs. Free them with
`mlspp_bytes_free`. Do not call `free()` on the inner `data` pointer directly.
## Error handling
Functions that can fail return NULL (for handles) or `{NULL, 0}` (for byte
buffers). Call `mlspp_last_error()` to retrieve a thread-local error string.
On success, `mlspp_last_error()` returns NULL.
## API overview
The bindings expose two API levels:
- **Low-level (`State`)** — direct MLS group state management with full control
over proposals, commits, and application data protection.
- **High-level (`Client` / `Session`)** — a simplified API that manages key
generation and state transitions internally, suited for straightforward group
messaging.
## Safety
All functions are `unsafe`. Callers must ensure:
- Pointer arguments are non-null and point to valid, live objects
- Handles are not used after being freed
- Handles are not shared across threads without external synchronization
## License
MIT