1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
//! Safe Rust client for the [wolfHSM](https://github.com/wolfSSL/wolfHSM)
//! hardware security module, wrapping the wolfHSM C client library.
//!
//! # Quick start
//!
//! ```no_run
//! use wolfhsm::{Client, Transport};
//!
//! # fn main() -> Result<(), wolfhsm::Error> {
//! let mut client = Client::connect(
//! Transport::Tcp { ip: "127.0.0.1".into(), port: 8080 },
//! 1,
//! )?;
//!
//! let digest = [0u8; 32]; // SHA-256 of the data to sign
//! let sig = client.with_ecc_p256_key(|key, client| {
//! key.sign_digest(client, &digest)
//! })?;
//! # let _ = sig;
//! # Ok(())
//! # }
//! ```
//!
//! # Why `&mut Client` is required for every operation
//!
//! The wolfHSM communication layer is a request/response protocol over a
//! socket. Only one request can be in-flight at a time. Requiring `&mut
//! Client` on every method enforces this at the type level — the borrow
//! checker prevents two callers from interleaving requests.
//!
//! `Client` is `Send` (ownership can be moved to another thread) but not
//! `Sync` (it cannot be shared). For concurrent HSM access, open multiple
//! `Client` connections.
//!
//! # Why key operations use closures instead of RAII drop types
//!
//! HSM key handles occupy RAM cache slots on the server. When you are done
//! with a key it must be explicitly evicted via a network request to the
//! server, which requires `&mut Client`.
//!
//! A drop-based RAII type cannot carry `&mut Client` inside it — Rust does
//! not allow a struct to hold `&mut Client` and then also accept `&mut
//! Client` in its own `Drop` impl without unsafe code. The closure pattern
//! sidesteps this:
//!
//! ```no_run
//! # use wolfhsm::{Client, Transport};
//! # fn main() -> Result<(), wolfhsm::Error> {
//! # let mut client = Client::connect(Transport::Tcp { ip: "127.0.0.1".into(), port: 8080 }, 1)?;
//! let digest = [0u8; 32];
//! let (pub_der, sig) = client.with_ecc_p256_key(|key, client| {
//! let pub_der = key.public_key_der(client)?;
//! let sig = key.sign_digest(client, &digest)?;
//! Ok((pub_der, sig))
//! })?;
//! # Ok(())
//! # }
//! ```
//!
//! `with_ecc_p256_key` generates the key, runs the closure, and always evicts
//! the cache slot — even when the closure returns `Err`.
//!
//! # Feature flags
//!
//! | Feature | What it enables |
//! |---------|----------------|
//! | `cert` | Certificate management (`wh_Client_Cert*` API) |
//! | `auth` | Authentication and user management (`wh_Client_Auth*` API) |
//! | `she` | SHE (Secure Hardware Extension) automotive key management |
//! | `mldsa` | ML-DSA (Dilithium) key support; requires `HAVE_DILITHIUM` in wolfSSL |
//!
//! # Transport variants
//!
//! | Variant | Mechanism |
//! |---------|-----------|
//! | [`Transport::Tcp`] | TCP/IP socket |
//! | [`Transport::Uds`] | Unix domain socket |
//! | [`Transport::Shm`] | POSIX shared memory (same host, zero-copy) |
pub use Error;
pub use Transport;
pub use ;
pub use KeyId;
pub use ;
pub use ;
pub use ;
pub use SheKeyId;