1use super::*;
2
3use libc::c_long;
4
5#[allow(non_camel_case_types)]
6#[repr(transparent)]
7struct CRYPTO_BUFFER {
8 _unused: c_void,
9}
10
11#[repr(C)]
12#[allow(non_camel_case_types)]
13pub(super) struct SSL_QUIC_METHOD {
14 set_read_secret: Option<
15 unsafe extern "C" fn(
16 ssl: *mut SSL,
17 level: crypto::Level,
18 cipher: *const SSL_CIPHER,
19 secret: *const u8,
20 secret_len: usize,
21 ) -> c_int,
22 >,
23
24 set_write_secret: Option<
25 unsafe extern "C" fn(
26 ssl: *mut SSL,
27 level: crypto::Level,
28 cipher: *const SSL_CIPHER,
29 secret: *const u8,
30 secret_len: usize,
31 ) -> c_int,
32 >,
33
34 add_handshake_data: Option<
35 unsafe extern "C" fn(
36 ssl: *mut SSL,
37 level: crypto::Level,
38 data: *const u8,
39 len: usize,
40 ) -> c_int,
41 >,
42
43 flush_flight: Option<extern "C" fn(ssl: *mut SSL) -> c_int>,
44
45 send_alert: Option<
46 extern "C" fn(ssl: *mut SSL, level: crypto::Level, alert: u8) -> c_int,
47 >,
48}
49
50#[cfg(test)]
51#[repr(C)]
52#[allow(non_camel_case_types)]
53struct SSL_PRIVATE_KEY_METHOD {
54 sign: Option<
55 unsafe extern "C" fn(
56 ssl: *mut SSL,
57 out: *mut u8,
58 out_len: *mut usize,
59 max_out: usize,
60 signature_algorithm: u16,
61 r#in: *const u8,
62 in_len: usize,
63 ) -> ssl_private_key_result_t,
64 >,
65
66 decrypt: Option<
67 unsafe extern "C" fn(
68 ssl: *mut SSL,
69 out: *mut u8,
70 out_len: *mut usize,
71 max_out: usize,
72 r#in: *const u8,
73 in_len: usize,
74 ) -> ssl_private_key_result_t,
75 >,
76
77 complete: Option<
78 unsafe extern "C" fn(
79 ssl: *mut SSL,
80 out: *mut u8,
81 out_len: *mut usize,
82 max_out: usize,
83 ) -> ssl_private_key_result_t,
84 >,
85}
86
87pub(super) static QUICHE_STREAM_METHOD: SSL_QUIC_METHOD = SSL_QUIC_METHOD {
88 set_read_secret: Some(set_read_secret),
89 set_write_secret: Some(set_write_secret),
90 add_handshake_data: Some(add_handshake_data),
91 flush_flight: Some(flush_flight),
92 send_alert: Some(send_alert),
93};
94
95impl Context {
96 pub fn set_early_data_enabled(&mut self, _enabled: bool) {
97 unsafe {
98 SSL_CTX_set_early_data_enabled(
99 self.as_mut_ptr(),
100 i32::from(_enabled),
101 );
102 }
103 }
104}
105
106impl Handshake {
107 pub fn set_quic_early_data_context(&mut self, context: &[u8]) -> Result<()> {
108 map_result(unsafe {
109 SSL_set_quic_early_data_context(
110 self.as_mut_ptr(),
111 context.as_ptr(),
112 context.len(),
113 )
114 })
115 }
116
117 pub fn set_session(&mut self, session: &[u8]) -> Result<()> {
118 unsafe {
119 let ctx = SSL_get_SSL_CTX(self.as_ptr());
120
121 if ctx.is_null() {
122 return Err(Error::TlsFail);
123 }
124
125 let session =
126 SSL_SESSION_from_bytes(session.as_ptr(), session.len(), ctx);
127
128 if session.is_null() {
129 return Err(Error::TlsFail);
130 }
131
132 let rc = SSL_set_session(self.as_mut_ptr(), session);
133 SSL_SESSION_free(session);
134
135 map_result(rc)
136 }
137 }
138
139 pub fn reset_early_data_reject(&mut self) {
140 unsafe { SSL_reset_early_data_reject(self.as_mut_ptr()) };
141 }
142
143 pub fn curve(&self) -> Option<String> {
144 let curve = unsafe {
145 let curve_id = SSL_get_curve_id(self.as_ptr());
146 if curve_id == 0 {
147 return None;
148 }
149
150 let curve_name = SSL_get_curve_name(curve_id);
151 match ffi::CStr::from_ptr(curve_name).to_str() {
152 Ok(v) => v,
153
154 Err(_) => return None,
155 }
156 };
157
158 Some(curve.to_string())
159 }
160
161 pub fn sigalg(&self) -> Option<String> {
162 let sigalg = unsafe {
163 let sigalg_id = SSL_get_peer_signature_algorithm(self.as_ptr());
164 if sigalg_id == 0 {
165 return None;
166 }
167
168 let sigalg_name = SSL_get_signature_algorithm_name(sigalg_id, 1);
169 match ffi::CStr::from_ptr(sigalg_name).to_str() {
170 Ok(v) => v,
171
172 Err(_) => return None,
173 }
174 };
175
176 Some(sigalg.to_string())
177 }
178
179 pub fn peer_cert_chain(&self) -> Option<Vec<&[u8]>> {
180 let cert_chain = unsafe {
181 let chain =
182 map_result_ptr(SSL_get0_peer_certificates(self.as_ptr())).ok()?;
183
184 let num = sk_num(chain);
185 if num == 0 {
186 return None;
187 }
188
189 let mut cert_chain = vec![];
190 for i in 0..num {
191 let buffer =
192 map_result_ptr(sk_value(chain, i) as *const CRYPTO_BUFFER)
193 .ok()?;
194
195 let out_len = CRYPTO_BUFFER_len(buffer);
196 if out_len == 0 {
197 return None;
198 }
199
200 let out = CRYPTO_BUFFER_data(buffer);
201 let slice = slice::from_raw_parts(out, out_len);
202
203 cert_chain.push(slice);
204 }
205
206 cert_chain
207 };
208
209 Some(cert_chain)
210 }
211
212 pub fn peer_cert(&self) -> Option<&[u8]> {
213 let peer_cert = unsafe {
214 let chain =
215 map_result_ptr(SSL_get0_peer_certificates(self.as_ptr())).ok()?;
216 if sk_num(chain) == 0 {
217 return None;
218 }
219
220 let buffer =
221 map_result_ptr(sk_value(chain, 0) as *const CRYPTO_BUFFER)
222 .ok()?;
223
224 let out_len = CRYPTO_BUFFER_len(buffer);
225 if out_len == 0 {
226 return None;
227 }
228
229 let out = CRYPTO_BUFFER_data(buffer);
230 slice::from_raw_parts(out, out_len)
231 };
232
233 Some(peer_cert)
234 }
235
236 #[cfg(test)]
238 pub fn set_failing_private_key_method(&mut self) {
239 extern "C" fn failing_sign(
240 _ssl: *mut SSL, _out: *mut u8, _out_len: *mut usize, _max_out: usize,
241 _signature_algorithm: u16, _in: *const u8, _in_len: usize,
242 ) -> ssl_private_key_result_t {
243 ssl_private_key_result_t::ssl_private_key_failure
244 }
245
246 extern "C" fn failing_decrypt(
247 _ssl: *mut SSL, _out: *mut u8, _out_len: *mut usize, _max_out: usize,
248 _in: *const u8, _in_len: usize,
249 ) -> ssl_private_key_result_t {
250 ssl_private_key_result_t::ssl_private_key_failure
251 }
252
253 extern "C" fn failing_complete(
254 _ssl: *mut SSL, _out: *mut u8, _out_len: *mut usize, _max_out: usize,
255 ) -> ssl_private_key_result_t {
256 ssl_private_key_result_t::ssl_private_key_failure
257 }
258
259 static QUICHE_PRIVATE_KEY_METHOD: SSL_PRIVATE_KEY_METHOD =
260 SSL_PRIVATE_KEY_METHOD {
261 decrypt: Some(failing_decrypt),
262 sign: Some(failing_sign),
263 complete: Some(failing_complete),
264 };
265
266 unsafe {
267 SSL_set_private_key_method(
268 self.as_mut_ptr(),
269 &QUICHE_PRIVATE_KEY_METHOD,
270 );
271 }
272 }
273
274 pub fn is_in_early_data(&self) -> bool {
275 unsafe { SSL_in_early_data(self.as_ptr()) == 1 }
276 }
277
278 pub fn early_data_reason(&self) -> u32 {
279 let reuse_reason_status =
280 unsafe { SSL_get_early_data_reason(self.as_ptr()) };
281 reuse_reason_status.0
282 }
283}
284
285pub(super) fn get_session_bytes(session: *mut SSL_SESSION) -> Result<Vec<u8>> {
286 let session_bytes = unsafe {
287 let mut out: *mut u8 = ptr::null_mut();
288 let mut out_len: usize = 0;
289
290 if SSL_SESSION_to_bytes(session, &mut out, &mut out_len) == 0 {
291 return Err(Error::TlsFail);
292 }
293 let session_bytes = slice::from_raw_parts(out, out_len).to_vec();
294 OPENSSL_free(out as *mut c_void);
295 session_bytes
296 };
297
298 Ok(session_bytes)
299}
300pub(super) const TLS_ERROR: c_int = 3;
301
302#[allow(non_camel_case_types)]
303#[repr(transparent)]
304#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
305pub struct ssl_early_data_reason_t(pub ::std::os::raw::c_uint);
306extern "C" {
307 pub(super) fn SSL_CTX_set_tlsext_ticket_keys(
309 ctx: *mut SSL_CTX, key: *const u8, key_len: usize,
310 ) -> c_int;
311 fn SSL_CTX_set_early_data_enabled(ctx: *mut SSL_CTX, enabled: i32);
312
313 pub(super) fn SSL_CTX_set1_groups_list(
317 ctx: *mut SSL_CTX, groups: *const c_char,
318 ) -> c_int;
319
320 pub(super) fn SSL_CTX_set_session_cache_mode(
321 ctx: *mut SSL_CTX, mode: c_int,
322 ) -> c_int;
323 pub(super) fn SSL_get_ex_new_index(
324 argl: c_long, argp: *const c_void, unused: *const c_void,
325 dup_unused: *const c_void, free_func: *const c_void,
326 ) -> c_int;
327
328 fn SSL_get_curve_id(ssl: *const SSL) -> u16;
329 fn SSL_get_curve_name(curve: u16) -> *const c_char;
330
331 fn SSL_get_peer_signature_algorithm(ssl: *const SSL) -> u16;
332 fn SSL_get_signature_algorithm_name(
333 sigalg: u16, include_curve: i32,
334 ) -> *const c_char;
335
336 fn SSL_get0_peer_certificates(ssl: *const SSL) -> *const STACK_OF;
337
338 pub(super) fn SSL_set_min_proto_version(ssl: *mut SSL, version: u16)
339 -> c_int;
340
341 pub(super) fn SSL_set_max_proto_version(ssl: *mut SSL, version: u16)
342 -> c_int;
343
344 pub(super) fn SSL_set_tlsext_host_name(
345 ssl: *mut SSL, name: *const c_char,
346 ) -> c_int;
347
348 fn SSL_set_quic_early_data_context(
349 ssl: *mut SSL, context: *const u8, context_len: usize,
350 ) -> c_int;
351
352 #[cfg(test)]
353 fn SSL_set_private_key_method(
354 ssl: *mut SSL, key_method: *const SSL_PRIVATE_KEY_METHOD,
355 );
356
357 fn SSL_reset_early_data_reject(ssl: *mut SSL);
358
359 fn SSL_in_early_data(ssl: *const SSL) -> c_int;
360
361 fn SSL_get_early_data_reason(ssl: *const SSL) -> ssl_early_data_reason_t;
362
363 fn SSL_SESSION_to_bytes(
364 session: *const SSL_SESSION, out: *mut *mut u8, out_len: *mut usize,
365 ) -> c_int;
366
367 fn SSL_SESSION_from_bytes(
368 input: *const u8, input_len: usize, ctx: *const SSL_CTX,
369 ) -> *mut SSL_SESSION;
370
371 fn sk_num(stack: *const STACK_OF) -> usize;
374
375 fn sk_value(stack: *const STACK_OF, idx: usize) -> *mut c_void;
376
377 fn CRYPTO_BUFFER_len(buffer: *const CRYPTO_BUFFER) -> usize;
380
381 fn CRYPTO_BUFFER_data(buffer: *const CRYPTO_BUFFER) -> *const u8;
382}