#![warn(missing_docs)]
mod aead;
mod alert;
mod certificates;
mod cipher_suites;
mod client_hello;
mod config;
mod error;
mod extensions;
mod handshake;
mod key_schedule;
mod record;
mod server_hello;
mod state;
use std::ffi::c_int;
use crylib::hash::Sha256;
use crylib::hkdf;
use handshake::handshake_client;
use state::ShakeState;
use state::TlsStatus;
pub use alert::turtls_stringify_alert;
pub use alert::TurtlsAlert;
pub use cipher_suites::TurtlsCipherList;
pub use config::{turtls_get_config, TurtlsConfig};
pub use error::{turtls_get_error, turtls_get_tls_error, TurtlsError};
pub use extensions::app_proto::turtls_app_proto;
pub use extensions::TurtlsExts;
pub use record::TurtlsIo;
pub use state::TurtlsConn;
#[no_mangle]
pub extern "C" fn turtls_new(io: TurtlsIo) -> *mut TurtlsConn {
Box::leak(TurtlsConn::new(io))
}
#[no_mangle]
pub unsafe extern "C" fn turtls_free(tls_conn: *mut TurtlsConn) {
if tls_conn.is_null() || !tls_conn.is_aligned() {
return;
}
let _ = unsafe { Box::from_raw(tls_conn) };
}
#[no_mangle]
pub unsafe extern "C" fn turtls_connect(tls_conn: *mut TurtlsConn) -> c_int {
assert!(!tls_conn.is_null() && tls_conn.is_aligned());
let tls_conn = unsafe { &mut *tls_conn };
loop {
match tls_conn.state {
TlsStatus::None => {
match ShakeState::new(&tls_conn.config) {
Ok(state) => tls_conn.state = TlsStatus::Shake(state),
Err(err) => {
tls_conn.gloabl_state.error.turtls_error = err;
return -1;
},
}
tls_conn.gloabl_state.secret =
hkdf::extract::<{ Sha256::HASH_SIZE }, { Sha256::BLOCK_SIZE }, Sha256>(
&[0; Sha256::HASH_SIZE],
&[0; Sha256::HASH_SIZE],
);
},
TlsStatus::Shake(ref mut shake_state) => {
if let Err(()) =
handshake_client(shake_state, &mut tls_conn.gloabl_state, &tls_conn.config)
{
return -1;
}
todo!()
},
TlsStatus::App { .. } => {
return 1;
},
}
}
}
#[no_mangle]
pub unsafe extern "C" fn turtls_close(tls_conn: *mut TurtlsConn) {
if tls_conn.is_null() || !tls_conn.is_aligned() {
return;
}
let tls_conn = unsafe { &mut *tls_conn };
if let TlsStatus::None = tls_conn.state {
return;
}
tls_conn.gloabl_state.rl.close_raw(TurtlsAlert::CloseNotify);
tls_conn.state = TlsStatus::None;
}