noxtls 0.1.3

TLS/DTLS protocol and connection state machine for the noxtls Rust stack.
Documentation
// Copyright (c) 2019-2026, Argenox Technologies LLC
// All rights reserved.
//
// SPDX-License-Identifier: GPL-2.0-only OR LicenseRef-Argenox-Commercial-License
//
// This file is part of the NoxTLS Library.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by the
// Free Software Foundation; version 2 of the License.
//
// Alternatively, this file may be used under the terms of a commercial
// license from Argenox Technologies LLC.
//
// See `noxtls/LICENSE` and `noxtls/LICENSE.md` in this repository for full details.
// CONTACT: info@argenox.com

use crate::internal_alloc::Vec;
use noxtls_core::Result;
use noxtls_psa::{
    KeyDecryptRequest as PsaKeyDecryptRequest, KeyDeriveRequest as PsaKeyDeriveRequest,
    KeySignRequest as PsaKeySignRequest, PsaCryptoBackend, PsaDecryptAlgorithm, PsaDeriveAlgorithm,
    PsaExternalKeyHandle, PsaProvider, PsaSignAlgorithm,
};

use super::{
    ExternalKeyHandle, ExternalKeyProvider, KeyDecryptAlgorithm, KeyDecryptRequest,
    KeyDeriveAlgorithm, KeyDeriveRequest, KeySignAlgorithm, KeySignRequest,
};

/// Adapts `noxtls-psa` backends to the `ExternalKeyProvider` trait boundary.
#[derive(Clone, Debug)]
pub struct PsaExternalKeyProvider<B: PsaCryptoBackend> {
    provider: PsaProvider<B>,
}

impl<B: PsaCryptoBackend> PsaExternalKeyProvider<B> {
    /// Constructs a provider adapter from a concrete PSA backend.
    ///
    /// # Arguments
    ///
    /// * `backend` — Concrete PSA backend implementation used for all operations.
    ///
    /// # Returns
    ///
    /// New adapter implementing [`ExternalKeyProvider`].
    pub fn new(backend: B) -> Self {
        Self {
            provider: PsaProvider::new(backend),
        }
    }

    /// Converts an external key handle into PSA-owned identifier bytes.
    ///
    /// # Arguments
    ///
    /// * `handle` — noxtls external key handle from provider requests.
    ///
    /// # Returns
    ///
    /// Converted PSA handle carrying an owned identifier copy.
    fn convert_handle(handle: &ExternalKeyHandle) -> PsaExternalKeyHandle {
        PsaExternalKeyHandle::new(handle.as_bytes().to_vec())
    }
}

impl<B: PsaCryptoBackend> ExternalKeyProvider for PsaExternalKeyProvider<B> {
    /// Executes signing operations through the PSA provider backend.
    ///
    /// # Arguments
    ///
    /// * `request` — noxtls signing request containing key handle and algorithm.
    ///
    /// # Returns
    ///
    /// Signature bytes generated by the backend.
    ///
    /// # Errors
    ///
    /// Returns backend/provider errors for invalid handles, policy violations, or sign failures.
    fn sign(&self, request: &KeySignRequest<'_>) -> Result<Vec<u8>> {
        let algorithm = match request.algorithm {
            KeySignAlgorithm::RsaPkcs1Sha256 => PsaSignAlgorithm::RsaPkcs1Sha256,
            KeySignAlgorithm::RsaPssSha256 => PsaSignAlgorithm::RsaPssSha256,
        };
        let handle = Self::convert_handle(request.handle);
        let mapped = PsaKeySignRequest {
            handle: &handle,
            algorithm,
            message: request.message,
            salt: request.salt,
        };
        self.provider.sign(&mapped)
    }

    /// Executes decrypt operations through the PSA provider backend.
    ///
    /// # Arguments
    ///
    /// * `request` — noxtls decrypt request containing key handle and algorithm.
    ///
    /// # Returns
    ///
    /// Plaintext bytes returned by the backend.
    ///
    /// # Errors
    ///
    /// Returns a uniform decrypt failure error for backend decrypt failures.
    fn decrypt(&self, request: &KeyDecryptRequest<'_>) -> Result<Vec<u8>> {
        let algorithm = match request.algorithm {
            KeyDecryptAlgorithm::RsaPkcs1v15 => PsaDecryptAlgorithm::RsaPkcs1v15,
            KeyDecryptAlgorithm::RsaOaepSha256 => PsaDecryptAlgorithm::RsaOaepSha256,
        };
        let handle = Self::convert_handle(request.handle);
        let mapped = PsaKeyDecryptRequest {
            handle: &handle,
            algorithm,
            ciphertext: request.ciphertext,
            label: request.label,
        };
        self.provider.decrypt(&mapped)
    }

    /// Executes key-derivation operations through the PSA provider backend.
    ///
    /// # Arguments
    ///
    /// * `request` — noxtls derive request containing key handle and peer public key.
    ///
    /// # Returns
    ///
    /// Shared secret bytes derived by the backend.
    ///
    /// # Errors
    ///
    /// Returns backend/provider errors for invalid handles, policy violations, or derive failures.
    fn derive_shared_secret(&self, request: &KeyDeriveRequest<'_>) -> Result<Vec<u8>> {
        let algorithm = match request.algorithm {
            KeyDeriveAlgorithm::X25519 => PsaDeriveAlgorithm::X25519,
        };
        let handle = Self::convert_handle(request.handle);
        let mapped = PsaKeyDeriveRequest {
            handle: &handle,
            algorithm,
            peer_public_key: request.peer_public_key,
        };
        self.provider.derive(&mapped)
    }
}