From ccc257aeb942b9fb8df53efb8e8ad595689ebe31 Mon Sep 17 00:00:00 2001 From: occheung Date: Fri, 27 Nov 2020 13:28:27 +0800 Subject: [PATCH] server certificate: handled --- src/session.rs | 59 ++++++++++++++++-------- src/tls.rs | 119 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 158 insertions(+), 20 deletions(-) diff --git a/src/session.rs b/src/session.rs index 6c7598a..841cfc4 100644 --- a/src/session.rs +++ b/src/session.rs @@ -1561,6 +1561,20 @@ impl<'a> Session<'a> { self.hash.update(encryption_extension_slice); } + pub(crate) fn server_update_for_sent_certificate( + &mut self, + certificate_slice: &[u8] + ) { + self.hash.update(certificate_slice); + } + + pub(crate) fn server_update_for_sent_certificate_verify( + &mut self, + certificate_verify_slice: &[u8] + ) { + self.hash.update(certificate_verify_slice); + } + pub(crate) fn verify_session_id_echo(&self, session_id_echo: &[u8]) -> bool { if let Some(session_id_inner) = self.session_id { session_id_inner == session_id_echo @@ -1635,7 +1649,11 @@ impl<'a> Session<'a> { } } - pub(crate) fn get_client_certificate_verify_signature(&self, rng: &mut R) + pub(crate) fn get_certificate_verify_signature( + &self, + rng: &mut R, + role: TlsRole + ) -> (crate::tls_packet::SignatureScheme, alloc::vec::Vec) { if let Some((private_key, client_certificate)) = &self.cert_private_key { @@ -1709,36 +1727,39 @@ impl<'a> Session<'a> { match private_key { CertificatePrivateKey::RSA { cert_rsa_private_key } => { + macro_rules! make_transcript_hash { + ($hash: ty) => { + { + <$hash>::new() + .chain(&[0x20; 64]) + .chain({ + match role { + TlsRole::Client => "TLS 1.3, client CertificateVerify", + TlsRole::Server => "TLS 1.3, server CertificateVerify", + _ => unreachable!() + } + }) + .chain(&[0x00]) + .chain(&transcript_hash) + .finalize() + } + } + } let sig_alg = self.client_cert_verify_sig_alg.unwrap(); let verify_hash: Vec = match sig_alg { rsa_pkcs1_sha256 | rsa_pss_rsae_sha256 | rsa_pss_pss_sha256 => { Vec::from_slice( - &sha2::Sha256::new() - .chain(&[0x20; 64]) - .chain("TLS 1.3, client CertificateVerify") - .chain(&[0x00]) - .chain(&transcript_hash) - .finalize() + &make_transcript_hash!(Sha256) ).unwrap() }, rsa_pkcs1_sha384 | rsa_pss_rsae_sha384 | rsa_pss_pss_sha384 => { Vec::from_slice( - &sha2::Sha384::new() - .chain(&[0x20; 64]) - .chain("TLS 1.3, client CertificateVerify") - .chain(&[0x00]) - .chain(&transcript_hash) - .finalize() + &make_transcript_hash!(Sha384) ).unwrap() }, rsa_pkcs1_sha512 | rsa_pss_rsae_sha512 | rsa_pss_pss_sha512 => { Vec::from_slice( - &sha2::Sha512::new() - .chain(&[0x20; 64]) - .chain("TLS 1.3, client CertificateVerify") - .chain(&[0x00]) - .chain(&transcript_hash) - .finalize() + &make_transcript_hash!(Sha512) ).unwrap() }, _ => unreachable!() diff --git a/src/tls.rs b/src/tls.rs index 5c20e95..43e04c3 100644 --- a/src/tls.rs +++ b/src/tls.rs @@ -365,7 +365,10 @@ impl<'s> TlsSocket<'s> { { let session = self.session.borrow(); let (sig_alg, signature) = session - .get_client_certificate_verify_signature(&mut self.rng); + .get_certificate_verify_signature( + &mut self.rng, + TlsRole::Client + ); let signature_length: u16 = u16::try_from(signature.len()).unwrap(); NetworkEndian::write_u24( @@ -513,6 +516,120 @@ impl<'s> TlsSocket<'s> { ); } + // TODO: Option to allow a certificate request + + // Construct and send server certificate handshake content + let mut inner_plaintext = { + let mut inner_plaintext: Vec = Vec::new(); + let session = self.session.borrow(); + let certificates = session.get_private_certificate_slices().clone(); + + // Handshake level, client certificate byte followed by length (u24) + // Certificate struct: + // request_context = X509: 0 (u8), + // certificate_list to be determined (u24) + let mut certificates_total_length: u32 = 0; + + // Append place holder bytes (8 of them) in the buffer vector + // Simpily copy the the headers back into the vector + // when all certificates are appended into the vector + inner_plaintext.extend_from_slice(&[11, 0, 0, 0, 0, 0, 0, 0]); + + // Certificate Entry struct(s) + if let Some(certificate_list) = certificates { + for cert in certificate_list.iter() { + // cert_data length, to be determined (u24) + let mut cert_data_length: [u8; 3] = [0, 0, 0]; + // extensions: no extension needed + let extension: [u8; 2] = [0, 0]; + + let certificate_length: u32 = u32::try_from(cert.len()).unwrap(); + + NetworkEndian::write_u24( + &mut cert_data_length, + certificate_length + ); + + // Update length in Certificate struct + certificates_total_length += + // cert_data (len & data) AND extension (len & data) + 3 + certificate_length + 2 + 0; + + inner_plaintext.extend_from_slice(&cert_data_length); + inner_plaintext.extend_from_slice(cert); + inner_plaintext.extend_from_slice(&extension); + } + } + + // Write total certificate length into Certificate struct + NetworkEndian::write_u24( + &mut inner_plaintext[5..8], + certificates_total_length + ); + + // Write the length of the entire handshake + NetworkEndian::write_u24( + &mut inner_plaintext[1..4], + // 4 bytes for the Certificate struct header + certificates_total_length + 4 + ); + + // Inner plaintext: record type + inner_plaintext.push(22); + inner_plaintext + }; + + self.send_application_slice(sockets, &mut inner_plaintext.clone())?; + + // Update session + { + self.session.borrow_mut() + .server_update_for_sent_certificate(&inner_plaintext); + } + + // Construct and send certificate verify + let mut inner_plaintext = { + let mut inner_plaintext = Vec::new(); + inner_plaintext.extend_from_slice(&[ + 15, + 0, 0, 0, + 0, 0, + 0, 0 + ]); + let session = self.session.borrow(); + let (sig_alg, signature) = session.get_certificate_verify_signature( + &mut self.rng, + TlsRole::Server + ); + let signature_length: u16 = u16::try_from(signature.len()).unwrap(); + NetworkEndian::write_u24( + &mut inner_plaintext[1..4], + (signature_length + 4).into() + ); + NetworkEndian::write_u16( + &mut inner_plaintext[4..6], + sig_alg.try_into().unwrap() + ); + NetworkEndian::write_u16( + &mut inner_plaintext[6..8], + signature_length + ); + inner_plaintext.extend_from_slice(&signature); + inner_plaintext.push(22); // Content type byte + inner_plaintext + }; + + self.send_application_slice( + sockets, + &mut inner_plaintext.clone() + )?; + + { + self.session.borrow_mut() + .server_update_for_sent_certificate_verify( + &inner_plaintext[..] + ); + } } // Other states regarding server role