Skip to main content

noxtls_psa/
ffi.rs

1// Copyright (c) 2019-2026, Argenox Technologies LLC
2// All rights reserved.
3//
4// SPDX-License-Identifier: GPL-2.0-only OR LicenseRef-Argenox-Commercial-License
5//
6// This file is part of the NoxTLS Library.
7//
8// This program is free software: you can redistribute it and/or modify
9// it under the terms of the GNU General Public License as published by the
10// Free Software Foundation; version 2 of the License.
11//
12// Alternatively, this file may be used under the terms of a commercial
13// license from Argenox Technologies LLC.
14//
15// See `noxtls/LICENSE` and `noxtls/LICENSE.md` in this repository for full details.
16// CONTACT: info@argenox.com
17
18#[cfg(feature = "alloc")]
19use alloc::vec::Vec;
20use noxtls_core::{Error, Result};
21
22use crate::provider::{
23    AeadEncryptRequest, AeadEncryptResponse, KeyDecryptRequest, KeyDeriveRequest, KeySignRequest,
24    PsaCryptoBackend,
25};
26
27/// Implements the PSA backend trait for FFI-backed targets.
28#[derive(Clone, Debug, Default)]
29pub struct FfiPsaBackend;
30
31impl FfiPsaBackend {
32    /// Creates a new FFI-backed backend adapter.
33    ///
34    /// # Arguments
35    ///
36    /// * `()` - This constructor has no parameters.
37    ///
38    /// # Returns
39    ///
40    /// A default [`FfiPsaBackend`] instance.
41    pub fn new() -> Self {
42        Self
43    }
44
45    /// Returns whether this build includes direct PSA FFI shims.
46    ///
47    /// # Arguments
48    ///
49    /// * `self` - Backend instance for capability checks.
50    ///
51    /// # Returns
52    ///
53    /// `true` when the `mbedtls-psa-ffi` feature is enabled, otherwise `false`.
54    pub fn has_ffi_shims(&self) -> bool {
55        cfg!(feature = "mbedtls-psa-ffi")
56    }
57}
58
59impl PsaCryptoBackend for FfiPsaBackend {
60    /// Signs input digest bytes using a key handle and algorithm selected in request.
61    ///
62    /// # Arguments
63    ///
64    /// * `self` - Backend instance receiving sign request dispatch.
65    /// * `request` - Sign request carrying key handle, algorithm, and digest bytes.
66    ///
67    /// # Returns
68    ///
69    /// Signature bytes if supported by this backend implementation.
70    ///
71    /// # Errors
72    ///
73    /// Returns [`Error::UnsupportedFeature`] until concrete FFI hooks are linked.
74    fn sign(&self, request: &KeySignRequest<'_>) -> Result<Vec<u8>> {
75        let _ = request;
76        Err(Error::UnsupportedFeature(
77            "psa ffi sign unavailable without linked backend",
78        ))
79    }
80
81    /// Decrypts ciphertext bytes using a key handle and requested mechanism.
82    ///
83    /// # Arguments
84    ///
85    /// * `self` - Backend instance receiving decrypt request dispatch.
86    /// * `request` - Decrypt request containing handle, algorithm, and ciphertext.
87    ///
88    /// # Returns
89    ///
90    /// Decrypted plaintext bytes if backend supports this operation.
91    ///
92    /// # Errors
93    ///
94    /// Returns [`Error::UnsupportedFeature`] until concrete FFI hooks are linked.
95    fn decrypt(&self, request: &KeyDecryptRequest<'_>) -> Result<Vec<u8>> {
96        let _ = request;
97        Err(Error::UnsupportedFeature(
98            "psa ffi decrypt unavailable without linked backend",
99        ))
100    }
101
102    /// Derives shared-secret bytes for a key handle and peer public key.
103    ///
104    /// # Arguments
105    ///
106    /// * `self` - Backend instance receiving derive request dispatch.
107    /// * `request` - Derive request with handle, algorithm, and peer public bytes.
108    ///
109    /// # Returns
110    ///
111    /// Shared secret bytes derived by the configured algorithm.
112    ///
113    /// # Errors
114    ///
115    /// Returns [`Error::UnsupportedFeature`] until concrete FFI hooks are linked.
116    fn derive(&self, request: &KeyDeriveRequest<'_>) -> Result<Vec<u8>> {
117        let _ = request;
118        Err(Error::UnsupportedFeature(
119            "psa ffi derive unavailable without linked backend",
120        ))
121    }
122
123    /// Fills the output buffer with random bytes from PSA entropy source.
124    ///
125    /// # Arguments
126    ///
127    /// * `self` - Backend instance receiving random generation request.
128    /// * `out` - Mutable byte slice to fill with random output.
129    ///
130    /// # Returns
131    ///
132    /// `Ok(())` when random bytes were produced.
133    ///
134    /// # Errors
135    ///
136    /// Returns [`Error::UnsupportedFeature`] until concrete FFI hooks are linked.
137    fn random(&self, out: &mut [u8]) -> Result<()> {
138        let _ = out;
139        Err(Error::UnsupportedFeature(
140            "psa ffi random unavailable without linked backend",
141        ))
142    }
143
144    /// Computes SHA-256 digest for the input payload.
145    ///
146    /// # Arguments
147    ///
148    /// * `self` - Backend instance receiving hash request dispatch.
149    /// * `input` - Bytes to hash with SHA-256.
150    ///
151    /// # Returns
152    ///
153    /// A 32-byte SHA-256 digest.
154    ///
155    /// # Errors
156    ///
157    /// Returns [`Error::UnsupportedFeature`] until concrete FFI hooks are linked.
158    fn sha256(&self, input: &[u8]) -> Result<[u8; 32]> {
159        let _ = input;
160        Err(Error::UnsupportedFeature(
161            "psa ffi sha256 unavailable without linked backend",
162        ))
163    }
164
165    /// Encrypts plaintext bytes with AES-GCM and returns ciphertext plus tag.
166    ///
167    /// # Arguments
168    ///
169    /// * `self` - Backend instance receiving AEAD encryption request.
170    /// * `request` - AES-GCM request with key, nonce, AAD, and plaintext.
171    ///
172    /// # Returns
173    ///
174    /// Ciphertext and 16-byte tag on successful encryption.
175    ///
176    /// # Errors
177    ///
178    /// Returns [`Error::UnsupportedFeature`] until concrete FFI hooks are linked.
179    fn aes_gcm_encrypt(&self, request: &AeadEncryptRequest<'_>) -> Result<AeadEncryptResponse> {
180        let _ = request;
181        Err(Error::UnsupportedFeature(
182            "psa ffi aes-gcm unavailable without linked backend",
183        ))
184    }
185}