fe11_verify_engine/
lib.rs1#![deny(unsafe_op_in_unsafe_fn)]
9
10mod algorithms;
11mod boundary;
12mod context;
13mod digest;
14mod native;
15mod verification;
16
17use context::Context;
18use fe11_verify_engine_api as api;
19use std::{ffi::c_void, mem::size_of, panic::catch_unwind};
20
21#[derive(Clone, Copy)]
22enum Failure {
23 InvalidRequest,
24 Unavailable,
25 Engine,
26 Allocation,
27}
28
29type Result<T> = std::result::Result<T, Failure>;
30
31impl Failure {
32 fn status(self) -> u32 {
33 match self {
34 Self::InvalidRequest => api::status::INVALID_REQUEST,
35 Self::Unavailable => api::status::UNAVAILABLE,
36 Self::Engine => api::status::ENGINE_FAILURE,
37 Self::Allocation => api::status::ALLOCATION_FAILURE,
38 }
39 }
40}
41
42fn dispatch(action: impl FnOnce() -> Result<()> + std::panic::UnwindSafe) -> u32 {
45 match catch_unwind(action) {
46 Ok(Ok(())) => api::status::OK,
47 Ok(Err(failure)) => failure.status(),
48 Err(_) => api::status::ENGINE_FAILURE,
49 }
50}
51
52unsafe extern "C" fn information(output: *mut api::Information, size: usize) -> u32 {
53 if size != size_of::<api::Information>() || !boundary::output_is_aligned(output) {
54 return api::status::INVALID_REQUEST;
55 }
56 unsafe { output.write(std::mem::zeroed()) };
58 dispatch(|| {
59 let _context = Context::new()?;
60 let value = api::Information {
61 abi_version: api::ABI_VERSION,
62 structure_size: size_of::<api::Information>() as u32,
63 implementation_version: [
66 env!("CARGO_PKG_VERSION_MAJOR")
67 .parse()
68 .map_err(|_| Failure::Engine)?,
69 env!("CARGO_PKG_VERSION_MINOR")
70 .parse()
71 .map_err(|_| Failure::Engine)?,
72 env!("CARGO_PKG_VERSION_PATCH")
73 .parse()
74 .map_err(|_| Failure::Engine)?,
75 ],
76 openssl_version: unsafe { native::OpenSSL_version_num() } as u64,
78 };
79 unsafe { output.write(value) };
80 Ok(())
81 })
82}
83
84unsafe extern "C" fn verification_algorithms(
85 request: *const api::VerificationAlgorithms,
86 size: usize,
87) -> u32 {
88 dispatch(|| {
89 let request = unsafe { boundary::request(request, size) }?;
91 unsafe { algorithms::check(request) }
92 })
93}
94
95unsafe extern "C" fn probe(request: *const api::VerificationRequest, size: usize) -> u32 {
96 dispatch(|| {
97 let request = unsafe { boundary::request(request, size) }?;
99 unsafe { verification::run(request, None) }?;
100 Ok(())
101 })
102}
103
104unsafe extern "C" fn verify(
105 request: *const api::VerificationRequest,
106 size: usize,
107 message: api::Bytes,
108 signature: api::Bytes,
109 output: *mut u32,
110) -> u32 {
111 if !boundary::output_is_aligned(output) {
112 return api::status::INVALID_REQUEST;
113 }
114 unsafe { output.write(0) };
116 dispatch(|| {
117 let (request, message, signature) = unsafe {
118 (
119 boundary::request(request, size)?,
120 boundary::bytes(message)?,
121 boundary::bytes(signature)?,
122 )
123 };
124 let verified = unsafe { verification::run(request, Some((message, signature))) }?;
125 unsafe { output.write(u32::from(verified)) };
126 Ok(())
127 })
128}
129
130unsafe extern "C" fn digest(
131 request: *const api::DigestRequest,
132 size: usize,
133 output: *mut api::OwnedBytes,
134) -> u32 {
135 if !boundary::output_is_aligned(output) {
136 return api::status::INVALID_REQUEST;
137 }
138 unsafe { output.write(api::OwnedBytes::EMPTY) };
139 dispatch(|| {
140 let request = unsafe { boundary::request(request, size) }?;
141 let bytes = unsafe { digest::calculate(request) }?;
142 unsafe { output.write(bytes.publish()) };
144 Ok(())
145 })
146}
147
148unsafe extern "C" fn release(owner: *mut c_void) {
149 unsafe { boundary::release(owner) };
152}
153
154#[export_name = "Fe11_VerifyEngine_GetInterface"]
162pub unsafe extern "C" fn get_interface(
163 version: u32,
164 output: *mut api::Interface,
165 size: usize,
166) -> u32 {
167 if version != api::ABI_VERSION
168 || size != size_of::<api::Interface>()
169 || !boundary::output_is_aligned(output)
170 {
171 return api::status::INVALID_REQUEST;
172 }
173 let interface = api::Interface {
174 structure_size: size_of::<api::Interface>() as u32,
175 abi_version: api::ABI_VERSION,
176 information: Some(information),
177 probe: Some(probe),
178 verification_algorithms: Some(verification_algorithms),
179 verify: Some(verify),
180 digest: Some(digest),
181 release: Some(release),
182 };
183 unsafe { output.write(interface) };
185 api::status::OK
186}