Skip to main content

noxtls_psa/
error.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
18use noxtls_core::{Error, Result};
19
20/// Enumerates normalized PSA status classes used by the public adapter layer.
21#[derive(Copy, Clone, Debug, Eq, PartialEq)]
22pub enum PsaResultCode {
23    /// The operation completed successfully.
24    Success,
25    /// A supplied argument or encoded payload is invalid.
26    InvalidArgument,
27    /// The requested operation is not permitted by key policy.
28    NotPermitted,
29    /// The key handle is unknown or no longer valid.
30    InvalidHandle,
31    /// Operation failed because output or input buffer sizes are insufficient.
32    BufferTooSmall,
33    /// Operation failed due to capability not present in the target backend.
34    NotSupported,
35    /// Signature, MAC, or decrypt checks failed.
36    InvalidSignature,
37    /// A generic backend failure was returned.
38    GenericError,
39}
40
41/// Carries a normalized PSA error class and optional backend detail.
42#[derive(Clone, Debug, Eq, PartialEq)]
43pub struct PsaError {
44    /// Normalized status class for API consumers.
45    pub code: PsaResultCode,
46    /// Optional backend-specific numeric status code.
47    pub detail_status: Option<i32>,
48}
49
50impl PsaError {
51    /// Constructs a new normalized PSA error object.
52    ///
53    /// # Arguments
54    ///
55    /// * `code` - Normalized status class derived from PSA backend behavior.
56    /// * `detail_status` - Optional backend status integer for diagnostics.
57    ///
58    /// # Returns
59    ///
60    /// A new [`PsaError`] value with caller-provided fields.
61    pub fn new(code: PsaResultCode, detail_status: Option<i32>) -> Self {
62        Self {
63            code,
64            detail_status,
65        }
66    }
67
68    /// Converts this PSA error to a `noxtls-core` error with uniform posture.
69    ///
70    /// # Arguments
71    ///
72    /// * `self` - Error instance produced by PSA wrapper or provider layers.
73    ///
74    /// # Returns
75    ///
76    /// A [`noxtls_core::Error`] suited for protocol/provider integration.
77    pub fn to_noxtls_error(&self) -> Error {
78        match self.code {
79            PsaResultCode::Success => Error::CryptoFailure("psa success mapped as error"),
80            PsaResultCode::InvalidArgument => Error::ParseFailure("psa invalid argument"),
81            PsaResultCode::NotPermitted => Error::StateError("psa operation not permitted"),
82            PsaResultCode::InvalidHandle => Error::StateError("psa key handle invalid"),
83            PsaResultCode::BufferTooSmall => Error::InvalidLength("psa buffer too small"),
84            PsaResultCode::NotSupported => Error::UnsupportedFeature("psa capability unavailable"),
85            PsaResultCode::InvalidSignature => {
86                Error::CryptoFailure("psa cryptographic operation failed")
87            }
88            PsaResultCode::GenericError => Error::CryptoFailure("psa backend failure"),
89        }
90    }
91}
92
93/// Converts a raw PSA status code to a normalized [`PsaResultCode`].
94///
95/// # Arguments
96///
97/// * `status` - Backend-provided status integer from PSA-like API surface.
98///
99/// # Returns
100///
101/// A normalized status class that can be mapped to stable noxtls errors.
102pub fn normalize_psa_status(status: i32) -> PsaResultCode {
103    match status {
104        0 => PsaResultCode::Success,
105        -133 => PsaResultCode::NotPermitted,
106        -134 => PsaResultCode::InvalidArgument,
107        -136 => PsaResultCode::InvalidHandle,
108        -138 => PsaResultCode::BufferTooSmall,
109        -1344 => PsaResultCode::InvalidSignature,
110        -1345 => PsaResultCode::NotSupported,
111        _ => PsaResultCode::GenericError,
112    }
113}
114
115/// Translates a raw PSA status into a `noxtls-core` result.
116///
117/// # Arguments
118///
119/// * `status` - Raw PSA status integer where zero indicates success.
120///
121/// # Returns
122///
123/// Returns `Ok(())` when status is success, otherwise a mapped noxtls error.
124///
125/// # Errors
126///
127/// Returns mapped [`noxtls_core::Error`] for any non-zero status.
128pub fn map_status_to_result(status: i32) -> Result<()> {
129    let normalized = normalize_psa_status(status);
130    if normalized == PsaResultCode::Success {
131        Ok(())
132    } else {
133        Err(PsaError::new(normalized, Some(status)).to_noxtls_error())
134    }
135}