use ytls_record::Content;
use ytls_record::MsgType;
use ytls_record::Record;
mod r_server_hello;
mod s_client_finished;
mod s_client_hello;
mod r_encrypted_extensions;
mod r_server_certificate_verify;
mod r_server_certificates;
mod r_server_handshake_finished;
use ytls_traits::CryptoConfig;
use ytls_traits::{TlsLeftIn, TlsLeftOut};
use ytls_traits::CryptoSha256HkdfExtractProcessor;
use ytls_traits::CryptoSha256HkdfGenProcessor;
use ytls_traits::CryptoSha256TranscriptProcessor;
use ytls_traits::CryptoSha384TranscriptProcessor;
use ytls_traits::CryptoX25519Processor;
use ytls_keys::Tls13Keys;
use ytls_traits::SecretStore;
use ytls_traits::Tls13KeyScheduleApSha256;
use ytls_traits::Tls13KeyScheduleDerivedSha256;
use ytls_traits::Tls13KeyScheduleHandshakeSha256;
use ytls_traits::Tls13KeyScheduleInit;
use rand_core::CryptoRng;
use crate::TlsServerCtxConfig;
use crate::{CtxError, Rfc8446Error};
use ytls_util::Nonce12;
use ytls_keys::Tls13KeysHandshakeSha256;
pub struct ServerHandshakeCtx<Config, Crypto, Rng> {
config: Config,
crypto: Crypto,
rng: Rng,
downstream_found_host: bool,
group_x25519_supported: bool,
chacha20_poly1305_sha256_supported: bool,
sig_alg_ed25519_supported: bool,
tls13_supported: bool,
extended_main_secret: bool,
record_size_limit: u16,
signed_cert_ts: bool,
sig_alg_rsa_pkcs1_sha256_supported: bool,
client_random: Option<[u8; 32]>,
client_x25519_pk: Option<[u8; 32]>,
client_session_id: Option<[u8; 100]>,
client_session_len: usize,
public_key: Option<[u8; 32]>,
shared_secret: Option<[u8; 32]>,
key_share: [u8; 36],
handshake_server_key: Option<[u8; 32]>,
handshake_client_key: Option<[u8; 32]>,
handshake_server_iv: Option<Nonce12>,
handshake_client_iv: Option<Nonce12>,
handshake_finished_server_key: Option<[u8; 32]>,
handshake_finished_client_key: Option<[u8; 32]>,
signature_cert_verify: Option<[u8; 100]>,
signature_cert_verify_len: usize,
cert_verify_hash: Option<[u8; 32]>,
hello_hash: Option<[u8; 32]>,
hash_finished: Option<[u8; 32]>,
is_complete: bool,
}
impl<Config, Crypto, Rng> ServerHandshakeCtx<Config, Crypto, Rng>
where
Config: TlsServerCtxConfig,
Crypto: CryptoConfig,
Rng: CryptoRng,
{
pub fn with_required(config: Config, crypto: Crypto, rng: Rng) -> Self {
Self {
config,
crypto,
rng,
downstream_found_host: false,
group_x25519_supported: false,
chacha20_poly1305_sha256_supported: false,
sig_alg_ed25519_supported: false,
tls13_supported: false,
extended_main_secret: false,
record_size_limit: 0,
signed_cert_ts: false,
sig_alg_rsa_pkcs1_sha256_supported: false,
client_random: None,
client_x25519_pk: None,
client_session_id: None,
client_session_len: 0,
public_key: None,
shared_secret: None,
key_share: [0; 36],
handshake_server_key: None,
handshake_client_key: None,
handshake_server_iv: None,
handshake_client_iv: None,
handshake_finished_server_key: None,
handshake_finished_client_key: None,
cert_verify_hash: None,
hello_hash: None,
hash_finished: None,
signature_cert_verify: None,
signature_cert_verify_len: 0,
is_complete: false,
}
}
}
use ytls_traits::CtxApplicationProcessor;
use ytls_traits::CtxHandshakeProcessor;
use ytls_traits::HandshakeComplete;
impl<Config, Crypto, Rng> CtxHandshakeProcessor for ServerHandshakeCtx<Config, Crypto, Rng>
where
Config: TlsServerCtxConfig,
Crypto: CryptoConfig,
Rng: CryptoRng,
{
type Error = CtxError;
#[inline]
fn spin_handshake<Li: TlsLeftIn, Lo: TlsLeftOut, Ks: SecretStore>(
&mut self,
li: &mut Li,
lo: &mut Lo,
ks: &mut Ks,
) -> Result<Option<HandshakeComplete>, Self::Error> {
if self.is_complete {
return Ok(Some(HandshakeComplete));
}
let init_data = li.left_buf_in();
let init_len = init_data.len();
let mut data = init_data;
if init_len == 0 {
return Ok(None);
}
#[allow(unused_assignments)]
let mut consumed = 0;
loop {
let (rec, remaining) =
Record::parse_client(self, data).map_err(|e| CtxError::Record(e))?;
consumed = init_len - remaining.len();
if self.shared_secret.is_none() {
if let Some(pk) = self.client_x25519_pk {
let x25519_ctx = self.crypto.x25519_init(&mut self.rng);
self.public_key = Some(x25519_ctx.x25519_public_key());
self.shared_secret = Some(x25519_ctx.x25519_shared_secret(&pk));
self.key_share = self.key_share_x25519();
}
}
match rec.content() {
Content::ChangeCipherSpec => {
}
Content::ApplicationData => {
let key = match self.handshake_client_key {
Some(k) => k,
None => return Err(CtxError::Bug(
"Did not have client key for decrypting. Was supposed to be guarded.",
)),
};
let nonce: [u8; 12] = match self.handshake_client_iv {
None => return Err(CtxError::MissingHandshakeIv),
Some(ref mut n) => match n.use_and_incr() {
Some(cur) => cur,
None => return Err(CtxError::ExhaustedIv),
},
};
let cipher = Crypto::aead_chaha20poly1305(&key);
let full_payload = rec.as_bytes();
let full_payload_len = full_payload.len();
let mut tag: [u8; 16] = [0; 16];
let body_len = full_payload_len - 16;
let mut body: [u8; 8192] = [0; 8192];
body[0..body_len].copy_from_slice(&full_payload[0..body_len]);
tag.copy_from_slice(&full_payload[body_len..body_len + 16]);
let additional_data = rec.header_as_bytes();
use ytls_traits::CryptoChaCha20Poly1305Processor;
cipher
.decrypt_in_place(&nonce, &additional_data, &mut body[0..body_len], &tag)
.map_err(|_| CtxError::Rfc8446(Rfc8446Error::Decrypt))?;
use ytls_record::{WrappedMsgType, WrappedRecord};
let r = WrappedRecord::parse_client(&body[0..body_len])
.map_err(|_| CtxError::Rfc8446(Rfc8446Error::Unexpected))?;
use ytls_record::HandshakeMsg;
match r.msg() {
WrappedMsgType::Handshake(HandshakeMsg {
msg: MsgType::ClientFinished(f),
..
}) => {
self.check_client_finished(&f)?;
self.is_complete = true;
break;
}
WrappedMsgType::Alert(_alert) => {
}
_ => {
return Err(CtxError::Rfc8446(Rfc8446Error::Unexpected));
}
}
}
Content::Handshake(content) => {
let msg = content.msg();
match msg {
MsgType::ClientFinished(_) => {
return Err(CtxError::Rfc8446(Rfc8446Error::Unexpected));
}
MsgType::ClientHello(_h) => {
let shared_secret = match self.shared_secret {
Some(s) => s,
None => {
return Err(CtxError::Bug(
"Supposed to have shared secret and was not guarded.",
))
}
};
let mut transcript = Crypto::sha256_init();
transcript.sha256_update(rec.as_bytes());
self.do_server_hello(lo, &mut transcript)?;
let mut transcript_more = transcript.sha256_fork();
let hello_hash = transcript.sha256_finalize();
self.hello_hash = Some(hello_hash);
let k = Tls13Keys::<Crypto>::no_psk_with_crypto_and_sha256();
let hs_k = k.dh_x25519(&shared_secret, &hello_hash);
let mut server_handshake_iv: [u8; 12] = [0; 12];
let mut server_handshake_key: [u8; 32] = [0; 32];
let mut server_handshake_finished_key: [u8; 32] = [0; 32];
hs_k.handshake_server_iv(&mut server_handshake_iv);
hs_k.handshake_server_key(&mut server_handshake_key);
hs_k.handshake_server_finished_key(&mut server_handshake_finished_key);
self.handshake_server_key = Some(server_handshake_key);
self.handshake_server_iv =
Some(Nonce12::from_ks_iv(&server_handshake_iv));
self.handshake_finished_server_key =
Some(server_handshake_finished_key);
let mut client_handshake_iv: [u8; 12] = [0; 12];
let mut client_handshake_key: [u8; 32] = [0; 32];
let mut client_handshake_finished_key: [u8; 32] = [0; 32];
hs_k.handshake_client_iv(&mut client_handshake_iv);
hs_k.handshake_client_key(&mut client_handshake_key);
hs_k.handshake_client_finished_key(&mut client_handshake_finished_key);
self.handshake_client_key = Some(client_handshake_key);
self.handshake_client_iv =
Some(Nonce12::from_ks_iv(&client_handshake_iv));
self.handshake_finished_client_key =
Some(client_handshake_finished_key);
self.do_encrypted_extensions(lo, &mut transcript_more)?;
self.do_server_certificates(lo, &mut transcript_more)?;
self.do_server_certificate_verify(lo, &mut transcript_more)?;
self.do_server_handshake_finished(lo, &mut transcript_more)?;
let finish_handshake_hash =
transcript_more.sha256_fork().sha256_finalize();
self.hash_finished = Some(finish_handshake_hash);
let ap_k = hs_k.finished_handshake(&finish_handshake_hash);
let mut server_application_iv: [u8; 12] = [0; 12];
let mut server_application_key: [u8; 32] = [0; 32];
let mut client_application_iv: [u8; 12] = [0; 12];
let mut client_application_key: [u8; 32] = [0; 32];
ap_k.application_server_key(&mut server_application_key);
ap_k.application_server_iv(&mut server_application_iv);
ap_k.application_client_key(&mut client_application_key);
ap_k.application_client_iv(&mut client_application_iv);
ks.store_ap_client_key(&client_application_key);
ks.store_ap_client_iv(&client_application_iv);
ks.store_ap_server_key(&server_application_key);
ks.store_ap_server_iv(&server_application_iv);
}
_ => return Err(CtxError::Rfc8446(Rfc8446Error::Unexpected)),
}
}
Content::Alert(_alert) => {
}
}
if remaining.len() == 0 {
break;
}
data = remaining;
}
li.left_buf_mark_discard_in(consumed);
if self.is_complete {
return Ok(Some(HandshakeComplete));
}
Ok(None)
}
}