modkit_security/
bin_codec.rs

1use crate::SecurityContext;
2use postcard::Error as PostcardError;
3use thiserror::Error;
4
5pub const SECCTX_BIN_VERSION: u8 = 1;
6
7#[derive(Debug, Error)]
8pub enum SecCtxEncodeError {
9    #[error("security context serialization failed: {0:?}")]
10    Postcard(#[from] PostcardError),
11}
12
13#[derive(Debug, Error)]
14pub enum SecCtxDecodeError {
15    #[error("empty secctx blob")]
16    Empty,
17
18    #[error("unsupported secctx version: {0}")]
19    UnsupportedVersion(u8),
20
21    #[error("security context deserialization failed: {0:?}")]
22    Postcard(#[from] PostcardError),
23}
24
25/// Encode `SecurityContext` into a versioned binary blob using `postcard`.
26/// This does not do any signing or encryption, it is just a transport format.
27///
28/// # Errors
29/// Returns `SecCtxEncodeError` if postcard serialization fails.
30pub fn encode_bin(ctx: &SecurityContext) -> Result<Vec<u8>, SecCtxEncodeError> {
31    let mut buf = Vec::with_capacity(64);
32    buf.push(SECCTX_BIN_VERSION);
33
34    let payload = postcard::to_allocvec(ctx)?;
35    buf.extend_from_slice(&payload);
36
37    Ok(buf)
38}
39
40/// Decode `SecurityContext` from a versioned binary blob produced by `encode_bin()`.
41///
42/// # Errors
43/// Returns `SecCtxDecodeError::Empty` if the input is empty.
44/// Returns `SecCtxDecodeError::UnsupportedVersion` if the version byte is not supported.
45/// Returns `SecCtxDecodeError::Postcard` if postcard deserialization fails.
46pub fn decode_bin(bytes: &[u8]) -> Result<SecurityContext, SecCtxDecodeError> {
47    if bytes.is_empty() {
48        return Err(SecCtxDecodeError::Empty);
49    }
50
51    let version = bytes[0];
52    if version != SECCTX_BIN_VERSION {
53        return Err(SecCtxDecodeError::UnsupportedVersion(version));
54    }
55
56    let payload = &bytes[1..];
57
58    let ctx: SecurityContext = postcard::from_bytes(payload)?;
59
60    Ok(ctx)
61}