mlspp-sys 0.3.1

Messaging Layer Security system bindings crate in Rust
# mlspp-sys

[![Crates.io](https://img.shields.io/crates/v/mlspp-sys)](https://crates.io/crates/mlspp-sys)
[![docs.rs](https://img.shields.io/docsrs/mlspp-sys)](https://docs.rs/mlspp-sys)
[![License: MIT](https://img.shields.io/crates/l/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

| Feature | Default | Description |
|---------|---------|-------------|
| `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