# API Error Handling (`api/error`)
This module establishes the core error handling infrastructure for the DCRYPT library. It defines the primary `Error` enum, a unified `Result` type, extension traits for easier error manipulation, and mechanisms for secure error reporting in constant-time contexts.
## Core Components
1. **`Error` Enum (`types.rs`)**:
The central error type used across the DCRYPT API. It covers a range of common cryptographic error scenarios:
* `InvalidKey`: Issues with cryptographic keys (e.g., wrong size, invalid format).
* `InvalidSignature`: Signature verification failures or malformed signatures.
* `DecryptionFailed`: General failure during decryption (often implies failed authentication in AEAD).
* `InvalidCiphertext`: Ciphertext is malformed or has an invalid structure.
* `InvalidLength`: Data provided has an incorrect length for the operation.
* `InvalidParameter`: A general parameter provided to a function is invalid.
* `SerializationError`: Failure during serialization or deserialization of cryptographic objects.
* `RandomGenerationError`: Failure during the generation of random numbers or cryptographic material.
* `NotImplemented`: A requested feature or algorithm is not implemented.
* `AuthenticationFailed`: Explicit failure of an authentication check (e.g., MAC or AEAD tag mismatch).
* `Other`: A catch-all for other types of errors, often wrapping errors from underlying libraries or system calls.
Each variant includes a `context` field (`&'static str`) and, when the `std` feature is enabled, an optional `message` field (`String`) for more detailed error information. The `Error` enum implements `Debug`, `Clone`, `PartialEq`, `Eq`, `Display`, and `std::error::Error` (if `std` is enabled).
2. **`Result<T>` Type Alias (`types.rs`)**:
A standard alias for `core::result::Result<T, api::Error>`, used throughout the DCRYPT ecosystem for fallible operations.
3. **`ErrorRegistry` (`registry.rs`)**:
* `pub static ERROR_REGISTRY: ErrorRegistry`: A globally accessible static instance of the error registry.
* **Purpose**: Designed for secure error handling in constant-time code. Instead of immediately returning an error (which might create a timing-dependent branch), constant-time functions can store an error in this registry and continue execution with dummy data. The caller can then check `ERROR_REGISTRY.has_error()` after the constant-time section.
* Methods: `new()`, `store(error)`, `clear()`, `has_error()`, `get_error()` (std-only, for retrieving a clone of the stored error).
* **Memory Management**: In `std` mode, it uses `Box` to store the error. In `no_std` mode, it can only indicate the presence of an error, not store the error itself.
4. **Error Handling Traits (`traits.rs`)**:
* **`ResultExt<T, E>`**: An extension trait for `core::result::Result<T, E>`.
* `wrap_err()`: Maps an `Err` to a new error type.
* `with_context(context: &'static str)`: Adds static context to an error that can be converted into `api::Error`.
* `with_message(message: impl Into<String>)` (std-only): Adds a dynamic message to an error.
* **`SecureErrorHandling<T, E>`**:
* `secure_unwrap(default: T, on_error: F) -> T`: Unwraps a `Result`. On `Err`, it stores the error (generated by `on_error`) in `ERROR_REGISTRY` and returns the `default` value. This helps maintain constant-time flow.
* **`ConstantTimeResult<T, E>`**:
* `ct_is_ok() -> bool`, `ct_is_err() -> bool`: Constant-time checks for `Ok` or `Err` (conceptual, actual constant-time relies on `subtle::Choice`).
* `ct_map(ok_fn, err_fn) -> U`: Maps `Ok(T)` or `Err(E)` to `U` using provided functions, conceptually in constant time.
5. **Validation Utilities (`validate.rs`)**:
A collection of helper functions for validating inputs and conditions, returning `api::Result<()>` or `api::Result<T>` on success, or an appropriate `api::Error` variant on failure.
* `parameter()` / `check_parameter()`: General condition check.
* `length()`, `min_length()`, `max_length()`, `range_length()`: For validating data lengths.
* `authentication()`: For authentication results.
* `key()`, `signature()`, `ciphertext()`: For validating formats of specific cryptographic types.
* `not_implemented()`: Convenience for returning `Error::NotImplemented`.
## Error Propagation and Conversion
- Errors from lower-level crates (like `algorithms::Error`) typically implement `From<LowerLevelError> for api::Error` or are wrapped.
- The `ResultExt` trait helps in adding context as errors propagate up the call stack.
- The `Error` enum itself provides `with_context()` and `with_message()` methods for further enrichment.
## Example of Secure Error Handling
```rust
use dcrypt_api::error::{Error, Result, SecureErrorHandling, ERROR_REGISTRY};
// Simulates a constant-time operation that might fail
fn constant_time_operation(succeed: bool) -> Result<u32> {
if succeed {
Ok(42)
} else {
Err(Error::Other { context: "dummy failure", #[cfg(feature="std")] message: "".into() })
}
}
fn example_secure_handling() {
ERROR_REGISTRY.clear(); // Clear any previous errors
let result_value = constant_time_operation(false)
.secure_unwrap(0, || Error::DecryptionFailed {
context: "constant_time_decryption",
#[cfg(feature="std")]
message: "Operation failed".into(),
});
// At this point, result_value is 0 (the default)
// The actual error is stored in ERROR_REGISTRY
if ERROR_REGISTRY.has_error() {
println!("Operation failed, default value {} used.", result_value);
// Optionally, retrieve and log the error if in `std` mode
#[cfg(feature="std")]
if let Some(err) = ERROR_REGISTRY.get_error::<Error>() {
println!("Stored error: {}", err);
}
ERROR_REGISTRY.clear();
} else {
println!("Operation succeeded with value: {}", result_value);
}
}
```
This error module provides a robust foundation for handling errors consistently and securely throughout the DCRYPT library.