Skip to content

Commit 26437d0

Browse files
committed
rustls-wolfcrypt-provider/error.rs: improve error handling with categorized errors
Add detailed error categories for wolfSSL error codes while maintaining the original API. Implement Display trait and add internal error checking mechanism. Keep no_std compatibility and add comprehensive tests.
1 parent 25fbfae commit 26437d0

File tree

1 file changed

+121
-16
lines changed

1 file changed

+121
-16
lines changed
Lines changed: 121 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,79 @@
1-
/// Custom error type for cryptographic operations, only indicating failure.
2-
/// Errors are generalized to avoid the leaking of information.
1+
use core::fmt;
2+
3+
/// Custom error type for cryptographic operations.
4+
/// Groups common wolfCrypt error types into categories.
35
#[derive(Debug)]
46
pub enum WCError {
7+
/// Operation completed successfully (ret = 0)
8+
Success,
9+
/// Generic failure (-1)
510
Failure,
11+
/// Memory-related errors (MEMORY_E, MP_MEM, etc.)
12+
Memory,
13+
/// Invalid arguments or state (BAD_FUNC_ARG, BAD_STATE_E, etc.)
14+
InvalidArgument,
15+
/// Buffer-related errors (BUFFER_E, RSA_BUFFER_E, etc.)
16+
Buffer,
17+
/// Authentication failures (MAC_CMP_FAILED_E, AES_GCM_AUTH_E, etc.)
18+
Authentication,
19+
/// Random number generation errors (RNG_FAILURE_E, MISSING_RNG_E, etc.)
20+
RandomError,
21+
/// ASN parsing errors (ASN_PARSE_E and related)
22+
ASNParse,
23+
/// Key-related errors (RSA_KEY_PAIR_E, ECC_PRIV_KEY_E, etc.)
24+
KeyError,
25+
/// Feature not available (NOT_COMPILED_IN, CRYPTOCB_UNAVAILABLE, etc.)
26+
NotAvailable,
27+
}
28+
29+
impl fmt::Display for WCError {
30+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31+
match self {
32+
WCError::Success => write!(f, "Operation successful"),
33+
WCError::Failure => write!(f, "Operation failed"),
34+
WCError::Memory => write!(f, "Memory allocation error"),
35+
WCError::InvalidArgument => write!(f, "Invalid argument or state"),
36+
WCError::Buffer => write!(f, "Buffer error"),
37+
WCError::Authentication => write!(f, "Authentication failed"),
38+
WCError::RandomError => write!(f, "Random number generation error"),
39+
WCError::ASNParse => write!(f, "ASN parsing error"),
40+
WCError::KeyError => write!(f, "Key-related error"),
41+
WCError::NotAvailable => write!(f, "Feature not available"),
42+
}
43+
}
644
}
745

846
/// A result type for cryptographic operations.
947
pub type WCResult = Result<(), WCError>;
1048

49+
/// Internal function to map wolfCrypt error codes to WCError variants
50+
fn check_error(ret: i32) -> WCResult {
51+
match ret {
52+
0 => Ok(()),
53+
-1 => Err(WCError::Failure),
54+
-125 => Err(WCError::Memory),
55+
-173 => Err(WCError::InvalidArgument),
56+
-132 => Err(WCError::Buffer),
57+
-181..=-180 | -213 => Err(WCError::Authentication),
58+
-199 | -236 => Err(WCError::RandomError),
59+
-162..=-140 => Err(WCError::ASNParse),
60+
-262 | -216 => Err(WCError::KeyError),
61+
-174 | -271 => Err(WCError::NotAvailable),
62+
_ => Err(WCError::Failure),
63+
}
64+
}
65+
1166
/// Checks if the FFI return value is `0` (indicating success).
1267
/// Returns `Ok(())` if success, otherwise returns `Err(CryptoError::Failure)`
1368
/// if the value is not `0`.
1469
///
1570
/// # Arguments
16-
/// * `stat` - The return value from the FFI call (i32).
71+
/// * `ret` - The return value from the FFI call (i32).
1772
///
1873
/// # Returns
1974
/// `CryptoResult` indicating either success or failure.
2075
pub fn check_if_zero(ret: i32) -> WCResult {
21-
if ret == 0 {
22-
Ok(())
23-
} else {
24-
Err(WCError::Failure)
25-
}
76+
check_error(ret)
2677
}
2778

2879
/// Checks if the FFI return value is `1` (indicating success).
@@ -35,10 +86,10 @@ pub fn check_if_zero(ret: i32) -> WCResult {
3586
/// # Returns
3687
/// `CryptoResult` indicating either success or failure.
3788
pub fn check_if_one(stat: i32) -> WCResult {
38-
if stat == 1 {
39-
Ok(())
40-
} else {
41-
Err(WCError::Failure)
89+
match stat {
90+
1 => Ok(()),
91+
0 => Err(WCError::Failure),
92+
_ => check_error(stat)
4293
}
4394
}
4495

@@ -52,9 +103,63 @@ pub fn check_if_one(stat: i32) -> WCResult {
52103
/// # Returns
53104
/// `CryptoResult` indicating either success or failure.
54105
pub fn check_if_greater_than_zero(ret: i32) -> WCResult {
55-
if ret > 0 {
56-
Ok(())
57-
} else {
58-
Err(WCError::Failure)
106+
match ret {
107+
x if x > 0 => Ok(()),
108+
0 => Err(WCError::Failure),
109+
_ => check_error(ret)
110+
}
111+
}
112+
113+
#[cfg(test)]
114+
mod tests {
115+
use super::*;
116+
117+
#[test]
118+
fn test_error_display() {
119+
assert_eq!(WCError::Success.to_string(), "Operation successful");
120+
assert_eq!(WCError::Failure.to_string(), "Operation failed");
121+
assert_eq!(WCError::Memory.to_string(), "Memory allocation error");
122+
assert_eq!(WCError::InvalidArgument.to_string(), "Invalid argument or state");
123+
assert_eq!(WCError::Buffer.to_string(), "Buffer error");
124+
assert_eq!(WCError::Authentication.to_string(), "Authentication failed");
125+
assert_eq!(WCError::RandomError.to_string(), "Random number generation error");
126+
assert_eq!(WCError::ASNParse.to_string(), "ASN parsing error");
127+
assert_eq!(WCError::KeyError.to_string(), "Key-related error");
128+
assert_eq!(WCError::NotAvailable.to_string(), "Feature not available");
129+
}
130+
131+
#[test]
132+
fn test_check_error() {
133+
assert!(check_error(0).is_ok());
134+
assert!(matches!(check_error(-1), Err(WCError::Failure)));
135+
assert!(matches!(check_error(-125), Err(WCError::Memory)));
136+
assert!(matches!(check_error(-173), Err(WCError::InvalidArgument)));
137+
assert!(matches!(check_error(-132), Err(WCError::Buffer)));
138+
assert!(matches!(check_error(-180), Err(WCError::Authentication)));
139+
assert!(matches!(check_error(-199), Err(WCError::RandomError)));
140+
assert!(matches!(check_error(-140), Err(WCError::ASNParse)));
141+
assert!(matches!(check_error(-262), Err(WCError::KeyError)));
142+
assert!(matches!(check_error(-174), Err(WCError::NotAvailable)));
143+
}
144+
145+
#[test]
146+
fn test_check_if_zero() {
147+
assert!(check_if_zero(0).is_ok());
148+
assert!(matches!(check_if_zero(-1), Err(WCError::Failure)));
149+
assert!(matches!(check_if_zero(-125), Err(WCError::Memory)));
150+
}
151+
152+
#[test]
153+
fn test_check_if_one() {
154+
assert!(check_if_one(1).is_ok());
155+
assert!(check_if_one(0).is_err());
156+
assert!(matches!(check_if_one(-1), Err(WCError::Failure)));
157+
}
158+
159+
#[test]
160+
fn test_check_if_greater_than_zero() {
161+
assert!(check_if_greater_than_zero(1).is_ok());
162+
assert!(check_if_greater_than_zero(0).is_err());
163+
assert!(matches!(check_if_greater_than_zero(-1), Err(WCError::Failure)));
59164
}
60165
}

0 commit comments

Comments
 (0)