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}