fe11_verify_engine_api/lib.rs
1// SPDX-License-Identifier: Apache-2.0
2//! C ABI for the optional Fe11 verification engine, independent of PKCS#11 tables.
3//!
4//! All requests are synchronous: no input pointer is retained after return. The caller
5//! pins the component image before invoking anything other than GetInterface.
6//! Inputs stay initialized, immutable and readable for their full lengths until
7//! return; output slots are aligned, exclusively writable and disjoint from inputs.
8//! Integer representations accept all bit patterns and
9//! are validated by the callee. The calling thread must not reenter this engine
10//! during a request. Calls from different threads are independent. No Rust
11//! allocation crosses the ownership boundary: an owned byte view is released by
12//! the originating component. The caller never reconstructs or frees that owner.
13#![no_std]
14use core::ffi::c_void;
15
16// This table exposes public verification services. Version and exact table
17// size are checked before either side consumes any service fields.
18/// Version of the public component ABI.
19pub const ABI_VERSION: u32 = 2;
20/// NUL-terminated exported discovery symbol.
21pub const ENTRY_POINT: &[u8] = b"Fe11_VerifyEngine_GetInterface\0";
22
23/// Service completion and failure codes.
24pub mod status {
25 /// The service completed; a verification verdict is reported separately.
26 pub const OK: u32 = 0;
27 /// The request representation or parameter combination was refused.
28 pub const INVALID_REQUEST: u32 = 1;
29 /// A required implementation or exact preparation is unavailable.
30 pub const UNAVAILABLE: u32 = 2;
31 /// The engine failed while executing the request.
32 pub const ENGINE_FAILURE: u32 = 3;
33 /// A required allocation failed.
34 pub const ALLOCATION_FAILURE: u32 = 4;
35}
36/// Public-key representation codes.
37pub mod key_format {
38 /// Complete DER-encoded SubjectPublicKeyInfo.
39 pub const SPKI_DER: u32 = 1;
40 /// Algorithm-specific raw public-key bytes.
41 pub const RAW_PUBLIC: u32 = 2;
42}
43/// Signature verification scheme codes.
44pub mod scheme {
45 /// RSA PKCS#1 v1.5 signature verification with an explicit digest.
46 pub const RSA_PKCS1: u32 = 1;
47 /// RSA-PSS verification with explicit digest, MGF1 digest and salt length.
48 pub const RSA_PSS: u32 = 2;
49 /// Digest-based signature scheme; the supplied engine accepts EC public keys.
50 pub const DIGEST_SIGNATURE: u32 = 3;
51 /// Pure Ed25519 or Ed448 verification.
52 pub const PURE_EDDSA: u32 = 4;
53 /// ML-DSA or SLH-DSA verification with explicit message framing.
54 pub const PQC: u32 = 5;
55 /// Explicit RFC8032 instance, context and original-message input.
56 pub const EDDSA: u32 = 6;
57}
58/// Instance codes for scheme::EDDSA in VerificationRequest::message_encoding.
59/// The ABI layout is unchanged; older engines may reject the added scheme.
60pub mod eddsa_instance {
61 /// Pure Ed25519 with an empty context.
62 pub const ED25519: u32 = 1;
63 /// Ed25519ctx with the supplied context.
64 pub const ED25519_CONTEXT: u32 = 2;
65 /// Ed25519ph with original-message input and the supplied context.
66 pub const ED25519_PREHASH: u32 = 3;
67 /// Ed448 with the supplied context.
68 pub const ED448: u32 = 4;
69 /// Ed448ph with original-message input and the supplied context.
70 pub const ED448_PREHASH: u32 = 5;
71}
72/// Borrowed bytes; null is accepted only with a zero length. Identifier fields
73/// contain UTF-8 names without NUL; ordinary data fields are unrestricted bytes.
74#[repr(C)]
75#[derive(Clone, Copy)]
76pub struct Bytes {
77 /// Start of readable input storage; NULL is valid only when length is zero.
78 pub pointer: *const u8,
79 /// Number of readable bytes starting at pointer.
80 pub length: usize,
81}
82impl Bytes {
83 /// Empty descriptor with a null pointer and zero length.
84 pub const EMPTY: Self = Self {
85 pointer: core::ptr::null(),
86 length: 0,
87 };
88 /// Borrow a slice as a descriptor; the caller preserves its storage through use.
89 pub fn from_slice(bytes: &[u8]) -> Self {
90 Self {
91 pointer: bytes.as_ptr(),
92 length: bytes.len(),
93 }
94 }
95}
96/// Engine-owned allocation. Only release(owner), exactly once, may destroy it.
97/// The view stays readable until release. None of these fields may be modified
98/// to construct a different allocation; even a zero-length owned view is released.
99#[repr(C)]
100#[derive(Clone, Copy)]
101pub struct OwnedBytes {
102 /// Opaque allocation token returned by the engine; release once through that engine.
103 pub owner: *mut c_void,
104 /// Readable result view whose lifetime ends when owner is released.
105 pub bytes: Bytes,
106}
107impl OwnedBytes {
108 /// Empty descriptor with a null pointer or owner and zero length.
109 pub const EMPTY: Self = Self {
110 owner: core::ptr::null_mut(),
111 bytes: Bytes::EMPTY,
112 };
113}
114/// Versions reported by the selected component and its private crypto library.
115#[repr(C)]
116#[derive(Clone, Copy)]
117pub struct Information {
118 /// Component ABI version; compare with ABI_VERSION.
119 pub abi_version: u32,
120 /// Size in bytes of this Information representation.
121 pub structure_size: u32,
122 /// Component package version as major, minor and patch numbers.
123 pub implementation_version: [u32; 3],
124 /// Numeric version of the component's private OpenSSL library.
125 pub openssl_version: u64,
126}
127/// Implementations required for a future verification, without a key. Names are
128/// UTF-8 without NUL; digest names may be empty when not needed. Success reports
129/// that each implementation can be fetched in the engine's private context. It
130/// does not establish that their combination or a future key can be initialized;
131/// explicit public-key verification uses the exact-key Probe to establish its
132/// own operation requirements. No private possession-proof policy is provided.
133#[repr(C)]
134#[derive(Clone, Copy)]
135pub struct VerificationAlgorithms {
136 /// UTF-8 key-management algorithm name without NUL bytes.
137 pub key_algorithm: Bytes,
138 /// UTF-8 signature implementation name without NUL bytes.
139 pub signature_algorithm: Bytes,
140 /// UTF-8 digest name, or empty when the requested scheme uses none.
141 pub digest: Bytes,
142 /// UTF-8 MGF digest name, or empty when the requested scheme uses none.
143 pub mgf_digest: Bytes,
144}
145/// Exact public verification parameters. Empty digest names mean no digest;
146/// unused fields must be zero/empty. PQC encoding is 1 for engine framing and
147/// 0 when Fe11 already supplied its exact FIPS frame. Context is not applied twice.
148/// For scheme::EDDSA, message_encoding is an eddsa_instance code, digest/MGF
149/// names and salt must be empty/zero, and input is the original message.
150#[repr(C)]
151#[derive(Clone, Copy)]
152pub struct VerificationRequest {
153 /// UTF-8 public-key algorithm name without NUL bytes.
154 pub algorithm: Bytes,
155 /// Public-key representation selected from key_format.
156 pub key_format: u32,
157 /// Complete public-key encoding in the selected format, borrowed through the call.
158 pub key: Bytes,
159 /// Signature operation selected from scheme.
160 pub scheme: u32,
161 /// Explicit message-digest name; empty for a scheme without a separate digest.
162 pub digest: Bytes,
163 /// RSA-PSS MGF1 digest name; empty for other schemes.
164 pub mgf_digest: Bytes,
165 /// Exact RSA-PSS salt length in bytes; zero for other schemes.
166 pub salt_length: u64,
167 /// EdDSA or PQC domain-separation context; empty when unused.
168 pub context: Bytes,
169 /// For EDDSA, an eddsa_instance code; for PQC, 1 for engine framing or 0 for an already framed message; zero otherwise.
170 pub message_encoding: u32,
171}
172/// Parameters for a synchronous whole-message digest request.
173#[repr(C)]
174#[derive(Clone, Copy)]
175pub struct DigestRequest {
176 /// UTF-8 digest implementation name without NUL bytes.
177 pub algorithm: Bytes,
178 /// Requested digest length in bytes; exact method width for a fixed-size hash.
179 pub output_length: usize,
180 /// Zero selects a fixed-size hash; one selects extendable output.
181 pub xof: u32,
182 /// Complete input message borrowed through this synchronous request.
183 pub message: Bytes,
184}
185/// Read component/engine versions into the caller's exact-sized output slot.
186/// This may initialize the private engine; the image must already be pinned.
187pub type ReadInformation =
188 unsafe extern "C" fn(output: *mut Information, output_size: usize) -> u32;
189
190/// Import the public key and prepare the exact parameters without verification.
191/// OK establishes preparation availability, not validity of a future signature.
192pub type Probe =
193 unsafe extern "C" fn(request: *const VerificationRequest, request_size: usize) -> u32;
194
195/// Check implementation availability without generating/importing a key or
196/// performing a PKCS#11 operation. See VerificationAlgorithms for the limited
197/// meaning of success; missing implementations return UNAVAILABLE.
198pub type CheckVerificationAlgorithms =
199 unsafe extern "C" fn(request: *const VerificationAlgorithms, request_size: usize) -> u32;
200
201/// Verify one message/signature pair. OK with verified=0 is a signature mismatch;
202/// engine/parameter failures have a non-OK status and never claim a mismatch.
203pub type Verify = unsafe extern "C" fn(
204 request: *const VerificationRequest,
205 request_size: usize,
206 message: Bytes,
207 signature: Bytes,
208 verified: *mut u32,
209) -> u32;
210
211/// Hash one whole message. On success the caller copies the result then releases
212/// its owner; no output allocation belongs to the caller's allocator.
213pub type Digest = unsafe extern "C" fn(
214 request: *const DigestRequest,
215 request_size: usize,
216 output: *mut OwnedBytes,
217) -> u32;
218
219/// Consume an unmodified owner returned by this image, exactly once. Null is a
220/// no-op. Every borrowed view of the allocation becomes invalid after this call.
221pub type Release = unsafe extern "C" fn(owner: *mut c_void);
222
223/// Function pointers use the C calling convention on every supported target.
224/// Every request receives its structure size; mismatched sizes are refused before
225/// dereferencing fields. Valid output slots are empty/zero on non-OK return;
226/// invalid output size/alignment is rejected without accessing that storage. Probe
227/// prepares the exact operation without signing or issuing any PKCS#11 call.
228#[repr(C)]
229#[derive(Clone, Copy)]
230pub struct Interface {
231 /// Size in bytes of this exact Interface representation.
232 pub structure_size: u32,
233 /// Version governing the layout and service contracts.
234 pub abi_version: u32,
235 /// Optional version-information service; Fe11 requires it when selecting an engine.
236 pub information: Option<ReadInformation>,
237 /// Optional exact-key verification preparation service.
238 pub probe: Option<Probe>,
239 /// Optional keyless implementation-availability service.
240 pub verification_algorithms: Option<CheckVerificationAlgorithms>,
241 /// Optional message/signature verification service; requires the preparation service.
242 pub verify: Option<Verify>,
243 /// Optional whole-message hashing service; returned allocations require release.
244 pub digest: Option<Digest>,
245 /// Optional originating-allocator release service for OwnedBytes results.
246 pub release: Option<Release>,
247}
248/// GetInterface performs no OpenSSL initialization. A successful call copies the
249/// exact requested ABI table into the caller's storage; it never returns a table
250/// pointer with an inferred suffix length. Version/size mismatch writes nothing.
251pub type GetInterface =
252 unsafe extern "C" fn(requested_version: u32, output: *mut Interface, output_size: usize) -> u32;