trussed-rsa-types 0.2.0

Helper types for the trussed-rsa-alloc backend
Documentation
// Copyright (C) Nitrokey GmbH
// SPDX-License-Identifier: Apache-2.0 or MIT

#![no_std]

use heapless_bytes::Bytes;
use serde::{Deserialize, Serialize};
use trussed_core::types::SerializedKey;

/// Error type
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
#[non_exhaustive]
pub enum ErrorKind {
    /// Error occured during serialization
    SerializeBufferFull,
    /// Serialization failed. This indicates an internal error.
    /// If encountered, please report
    SerializeCustom,
    /// The structure failed to deserialize
    Deseralization,
}

/// Error during serialization.
/// This means that the serialization failed, likely
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct Error {
    kind: ErrorKind,
}

pub(crate) fn postcard_serialize_bytes<T: serde::Serialize, const N: usize>(
    object: &T,
) -> postcard::Result<Bytes<N>> {
    let mut vec = Bytes::new();
    vec.resize_to_capacity();
    let serialized = postcard::to_slice(object, &mut vec)?.len();
    vec.resize(serialized, 0).unwrap();
    Ok(vec)
}

/// Structure containing the public part of an RSA key
///
/// Given how Trussed extensions are implemented, this structure cannot be sent as-is to the backend,
/// and is instead sent as a byte array.
/// You can use [`serialize`](RsaPublicParts::serialize) and [`deserialize`](RsaPublicParts::deserialize) functions
/// to convert to and from tha byte array format
#[derive(Serialize, Deserialize)]
pub struct RsaPublicParts<'d> {
    /// big-endian integer representing the modulus of an RSA key
    pub n: &'d [u8],
    /// big-endian integer representing the public exponent of an RSA key
    pub e: &'d [u8],
}

impl<'d> RsaPublicParts<'d> {
    pub fn serialize(&self) -> Result<SerializedKey, Error> {
        use postcard::Error as PError;
        postcard_serialize_bytes(self).map_err(|err| match err {
            PError::SerializeBufferFull => Error {
                kind: ErrorKind::SerializeBufferFull,
            },
            _ => Error {
                kind: ErrorKind::SerializeCustom,
            },
        })
    }

    pub fn deserialize(data: &'d [u8]) -> Result<Self, Error> {
        postcard::from_bytes(data).map_err(|_err| Error {
            kind: ErrorKind::Deseralization,
        })
    }
}

/// Format for private RSA key import
///
/// Given how Trussed extensions are implemented, this structure cannot be sent as-is to the backend,
/// and is instead sent as a byte array.
/// You can use [`serialize`](RsaImportFormat::serialize) and [`deserialize`](RsaImportFormat::deserialize) functions
/// to convert to and from tha byte array format
#[derive(Debug, Deserialize, Serialize)]
pub struct RsaImportFormat<'d> {
    /// big-endian integer representing the exponent of the public part of the RSA key
    pub e: &'d [u8],
    /// big-endian integer representing the first prime of a private RSA key
    pub p: &'d [u8],
    /// big-endian integer representing the second prime of a private RSA key
    pub q: &'d [u8],
}

impl<'d> RsaImportFormat<'d> {
    pub fn serialize(&self) -> Result<SerializedKey, Error> {
        use postcard::Error as PError;
        postcard_serialize_bytes(self).map_err(|err| match err {
            PError::SerializeBufferFull => Error {
                kind: ErrorKind::SerializeBufferFull,
            },
            _ => Error {
                kind: ErrorKind::SerializeCustom,
            },
        })
    }

    pub fn deserialize(data: &'d [u8]) -> Result<Self, Error> {
        postcard::from_bytes(data).map_err(|_err| Error {
            kind: ErrorKind::Deseralization,
        })
    }
}