handshake: fin
This commit is contained in:
parent
0042fea902
commit
ee9b31e3de
@ -8,6 +8,7 @@ edition = "2018"
|
||||
hkdf = "0.9.0"
|
||||
sha-1 = { version = "0.9.1", default-features = false }
|
||||
sha2 = { version = "0.9.1", default-features = false }
|
||||
hmac = "0.10.1"
|
||||
byteorder = { version = "1.3.4", default-features = false }
|
||||
num_enum = { version = "0.5.1", default-features = false }
|
||||
log = "0.4.11"
|
||||
|
25
src/fake_rng.rs
Normal file
25
src/fake_rng.rs
Normal file
@ -0,0 +1,25 @@
|
||||
// A blank implementor of RngCore that is NOT random
|
||||
// Justification: RSA padding scheme for verifying PSS signature
|
||||
// 1. Why is there a static lifetime bound?
|
||||
// 2. Why need random? It is just signature verification.
|
||||
// Anyway, the RSAPublicKey::verify() method does NOT care about random at all :)
|
||||
|
||||
use rand_core::{RngCore, Error};
|
||||
|
||||
pub (crate) struct FakeRandom {}
|
||||
|
||||
impl RngCore for FakeRandom {
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
0
|
||||
}
|
||||
|
||||
fn next_u64(&mut self) -> u64 {
|
||||
0
|
||||
}
|
||||
|
||||
fn fill_bytes(&mut self, dest: &mut [u8]) {}
|
||||
|
||||
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ pub mod buffer;
|
||||
pub mod key;
|
||||
pub mod session;
|
||||
pub mod certificate;
|
||||
pub mod fake_rng;
|
||||
|
||||
use nom::error::ParseError;
|
||||
|
||||
|
35
src/parse.rs
35
src/parse.rs
@ -177,6 +177,21 @@ pub(crate) fn parse_handshake(bytes: &[u8]) -> IResult<&[u8], HandshakeRepr> {
|
||||
|
||||
Ok((rest, repr))
|
||||
},
|
||||
Finished => {
|
||||
// Parse Finished, the size is determined
|
||||
// Pre-split the slice and then parse for Finished
|
||||
// i.e. check for completeness
|
||||
let (rest, possible_verify_data) = take(repr.length)(rest)?;
|
||||
let (_, handshake_data) = complete(
|
||||
parse_finished
|
||||
)(possible_verify_data)?;
|
||||
|
||||
repr.handshake_data = HandshakeData::Finished(
|
||||
handshake_data
|
||||
);
|
||||
|
||||
Ok((rest, repr))
|
||||
}
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
@ -381,17 +396,22 @@ fn parse_certificate_verify(bytes: &[u8]) -> IResult<&[u8], CertificateVerify> {
|
||||
signature_length
|
||||
))(bytes)?;
|
||||
|
||||
log::info!("Sig scheme: {:?}, sig:len: {:?}, rest_len: {:?}",
|
||||
signature_scheme,
|
||||
signature_length,
|
||||
rest.len()
|
||||
);
|
||||
|
||||
let signature_scheme = SignatureScheme::try_from(
|
||||
NetworkEndian::read_u16(signature_scheme)
|
||||
).unwrap();
|
||||
let signature_length = NetworkEndian::read_u16(signature_length);
|
||||
|
||||
let (_, signature) = complete(
|
||||
take(signature_length)
|
||||
)(rest)?;
|
||||
// Take the signature portion out
|
||||
let (rest, signature) = take(signature_length)(rest)?;
|
||||
|
||||
Ok((
|
||||
&[],
|
||||
rest,
|
||||
CertificateVerify {
|
||||
algorithm: signature_scheme,
|
||||
signature_length,
|
||||
@ -400,6 +420,13 @@ fn parse_certificate_verify(bytes: &[u8]) -> IResult<&[u8], CertificateVerify> {
|
||||
))
|
||||
}
|
||||
|
||||
fn parse_finished(bytes: &[u8]) -> IResult<&[u8], Finished> {
|
||||
Ok((
|
||||
&[],
|
||||
Finished { verify_data: bytes }
|
||||
))
|
||||
}
|
||||
|
||||
fn parse_extension(bytes: &[u8], handshake_type: HandshakeType) -> IResult<&[u8], Extension> {
|
||||
let extension_type = take(2_usize);
|
||||
let length = take(2_usize);
|
||||
|
227
src/session.rs
227
src/session.rs
@ -1,6 +1,6 @@
|
||||
use p256::{ EncodedPoint, ecdh::EphemeralSecret };
|
||||
use heapless::{ Vec, consts::* };
|
||||
use sha2::{ Digest, Sha256, Sha384, digest::FixedOutput };
|
||||
use sha2::{ Digest, Sha256, Sha384, Sha512, digest::FixedOutput };
|
||||
use aes_gcm::{ Aes128Gcm, Aes256Gcm, aes::Aes128 };
|
||||
use aes_gcm::{ AeadInPlace, NewAead, aead::Buffer };
|
||||
use chacha20poly1305::ChaCha20Poly1305;
|
||||
@ -8,7 +8,10 @@ use ccm::Ccm;
|
||||
use hkdf::Hkdf;
|
||||
use generic_array::GenericArray;
|
||||
use byteorder::{ByteOrder, NetworkEndian, BigEndian};
|
||||
use rsa::RSAPublicKey;
|
||||
use rsa::{RSAPublicKey, PublicKey, PaddingScheme, Hash as RSAHash};
|
||||
use hmac::{ Hmac, Mac, NewMac };
|
||||
|
||||
use rand_core::RngCore;
|
||||
|
||||
use core::convert::AsRef;
|
||||
use core::cell::RefCell;
|
||||
@ -16,7 +19,9 @@ use core::cell::RefCell;
|
||||
use crate::tls::TlsState;
|
||||
use crate::tls_packet::CipherSuite;
|
||||
use crate::key::*;
|
||||
use crate::tls_packet::SignatureScheme;
|
||||
use crate::Error;
|
||||
use crate::fake_rng::FakeRandom;
|
||||
|
||||
type Aes128Ccm = Ccm<Aes128, U16, U12>;
|
||||
|
||||
@ -157,13 +162,23 @@ impl Session {
|
||||
let client_handshake_traffic_secret = derive_secret(
|
||||
&handshake_secret_hkdf,
|
||||
"c hs traffic",
|
||||
self.hash.get_sha256_clone()
|
||||
self.hash.get_sha256_clone().unwrap()
|
||||
);
|
||||
|
||||
let server_handshake_traffic_secret = derive_secret(
|
||||
&handshake_secret_hkdf,
|
||||
"s hs traffic",
|
||||
self.hash.get_sha256_clone()
|
||||
self.hash.get_sha256_clone().unwrap()
|
||||
);
|
||||
|
||||
// Store client_handshake_traffic_secret and
|
||||
// server_handshake_traffic_secret
|
||||
// Initial values of both secrets don't matter
|
||||
self.client_traffic_secret.replace(
|
||||
Vec::from_slice(&client_handshake_traffic_secret).unwrap()
|
||||
);
|
||||
self.server_traffic_secret.replace(
|
||||
Vec::from_slice(&server_handshake_traffic_secret).unwrap()
|
||||
);
|
||||
|
||||
let client_handshake_traffic_secret_hkdf = Hkdf::<Sha256>::from_prk(&client_handshake_traffic_secret).unwrap();
|
||||
@ -335,13 +350,23 @@ impl Session {
|
||||
let client_handshake_traffic_secret = derive_secret(
|
||||
&handshake_secret_hkdf,
|
||||
"c hs traffic",
|
||||
self.hash.get_sha384_clone()
|
||||
self.hash.get_sha384_clone().unwrap()
|
||||
);
|
||||
|
||||
let server_handshake_traffic_secret = derive_secret(
|
||||
&handshake_secret_hkdf,
|
||||
"s hs traffic",
|
||||
self.hash.get_sha384_clone()
|
||||
self.hash.get_sha384_clone().unwrap()
|
||||
);
|
||||
|
||||
// Store client_handshake_traffic_secret and
|
||||
// server_handshake_traffic_secret
|
||||
// Initial values of both secrets don't matter
|
||||
self.client_traffic_secret.replace(
|
||||
Vec::from_slice(&client_handshake_traffic_secret).unwrap()
|
||||
);
|
||||
self.server_traffic_secret.replace(
|
||||
Vec::from_slice(&server_handshake_traffic_secret).unwrap()
|
||||
);
|
||||
|
||||
let client_handshake_traffic_secret_hkdf = Hkdf::<Sha384>::from_prk(&client_handshake_traffic_secret).unwrap();
|
||||
@ -445,6 +470,184 @@ impl Session {
|
||||
self.state = TlsState::WAIT_CV;
|
||||
}
|
||||
|
||||
pub(crate) fn client_update_for_wait_cv(
|
||||
&mut self,
|
||||
cert_verify_slice: &[u8],
|
||||
signature_algorithm: SignatureScheme,
|
||||
signature: &[u8]
|
||||
)
|
||||
{
|
||||
// Clone the transcript hash from ClientHello all the way to Certificate
|
||||
let transcript_hash: Vec<u8, U64> = if let Ok(sha256) = self.hash.get_sha256_clone() {
|
||||
Vec::from_slice(&sha256.finalize()).unwrap()
|
||||
} else if let Ok(sha384) = self.hash.get_sha384_clone() {
|
||||
Vec::from_slice(&sha384.finalize()).unwrap()
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
// Handle Ed25519 and p256 separately
|
||||
// These 2 algorithms have a mandated hash function
|
||||
if signature_algorithm == SignatureScheme::ecdsa_secp256r1_sha256 ||
|
||||
signature_algorithm == SignatureScheme::ed25519
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
|
||||
// Get verification hash, and verify the signature
|
||||
use crate::tls_packet::SignatureScheme::*;
|
||||
|
||||
let get_rsa_padding_scheme = |sig_alg: SignatureScheme| -> PaddingScheme {
|
||||
match signature_algorithm {
|
||||
rsa_pkcs1_sha256 => {
|
||||
PaddingScheme::new_pkcs1v15_sign(Some(RSAHash::SHA2_256))
|
||||
},
|
||||
rsa_pkcs1_sha384 => {
|
||||
PaddingScheme::new_pkcs1v15_sign(Some(RSAHash::SHA2_384))
|
||||
},
|
||||
rsa_pkcs1_sha512 => {
|
||||
PaddingScheme::new_pkcs1v15_sign(Some(RSAHash::SHA2_512))
|
||||
},
|
||||
rsa_pss_rsae_sha256 | rsa_pss_pss_sha256 => {
|
||||
PaddingScheme::new_pss::<Sha256, FakeRandom>(FakeRandom{})
|
||||
},
|
||||
rsa_pss_rsae_sha384 | rsa_pss_pss_sha384 => {
|
||||
PaddingScheme::new_pss::<Sha384, FakeRandom>(FakeRandom{})
|
||||
},
|
||||
rsa_pss_rsae_sha512 | rsa_pss_pss_sha512 => {
|
||||
PaddingScheme::new_pss::<Sha512, FakeRandom>(FakeRandom{})
|
||||
},
|
||||
_ => unreachable!()
|
||||
}
|
||||
};
|
||||
|
||||
match signature_algorithm {
|
||||
rsa_pkcs1_sha256 | rsa_pss_rsae_sha256 | rsa_pss_pss_sha256 => {
|
||||
let verify_hash = Sha256::new()
|
||||
.chain(&[0x20; 64])
|
||||
.chain("TLS 1.3, server CertificateVerify")
|
||||
.chain(&[0])
|
||||
.chain(&transcript_hash)
|
||||
.finalize();
|
||||
let padding = get_rsa_padding_scheme(signature_algorithm);
|
||||
let verify_result = self.cert_rsa_public_key.take().unwrap().verify(
|
||||
padding, &verify_hash, signature
|
||||
);
|
||||
log::info!("Algorithm {:?} Certificate verify: {:?}", signature_algorithm, verify_result);
|
||||
if verify_result.is_err() {
|
||||
todo!()
|
||||
}
|
||||
},
|
||||
rsa_pkcs1_sha384 | rsa_pss_rsae_sha384 | rsa_pss_pss_sha384 => {
|
||||
let verify_hash = Sha384::new()
|
||||
.chain(&[0x20; 64])
|
||||
.chain("TLS 1.3, server CertificateVerify")
|
||||
.chain(&[0])
|
||||
.chain(&transcript_hash)
|
||||
.finalize();
|
||||
let padding = get_rsa_padding_scheme(signature_algorithm);
|
||||
let verify_result = self.cert_rsa_public_key.take().unwrap().verify(
|
||||
padding, &verify_hash, signature
|
||||
);
|
||||
log::info!("Algorithm {:?} Certificate verify: {:?}", signature_algorithm, verify_result);
|
||||
if verify_result.is_err() {
|
||||
todo!()
|
||||
}
|
||||
},
|
||||
rsa_pkcs1_sha512 | rsa_pss_rsae_sha512 | rsa_pss_pss_sha512 => {
|
||||
let verify_hash = Sha512::new()
|
||||
.chain(&[0x20; 64])
|
||||
.chain("TLS 1.3, server CertificateVerify")
|
||||
.chain(&[0])
|
||||
.chain(&transcript_hash)
|
||||
.finalize();
|
||||
let padding = get_rsa_padding_scheme(signature_algorithm);
|
||||
let verify_result = self.cert_rsa_public_key.take().unwrap().verify(
|
||||
padding, &verify_hash, signature
|
||||
);
|
||||
if verify_result.is_err() {
|
||||
todo!()
|
||||
}
|
||||
},
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
// Usual procedures: update hash
|
||||
self.hash.update(cert_verify_slice);
|
||||
|
||||
// At last, update client state
|
||||
self.state = TlsState::WAIT_FINISHED;
|
||||
}
|
||||
|
||||
pub(crate) fn client_update_for_wait_finished(
|
||||
&mut self,
|
||||
server_finished_slice: &[u8],
|
||||
server_verify_data: &[u8]
|
||||
)
|
||||
{
|
||||
// Take hash from session
|
||||
if let Ok(sha256) = self.hash.get_sha256_clone() {
|
||||
let hkdf = Hkdf::<Sha256>::from_prk(
|
||||
self.server_traffic_secret.as_ref().unwrap()
|
||||
).unwrap();
|
||||
|
||||
// Compute finished_key
|
||||
let mut okm: GenericArray::<u8, <Sha256 as Digest>::OutputSize> =
|
||||
Default::default();
|
||||
hkdf_expand_label(&hkdf, "finished", "", &mut okm);
|
||||
|
||||
// Get transcript hash
|
||||
let transcript_hash = sha256.finalize();
|
||||
|
||||
// Compute verify_data
|
||||
// let computed_verify_data = Sha256::new()
|
||||
// .chain(&okm)
|
||||
// .chain(&transcript_hash)
|
||||
// .finalize();
|
||||
let mut hmac = Hmac::<Sha256>::new_varkey(&okm).unwrap();
|
||||
hmac.update(&transcript_hash);
|
||||
log::info!("HMAC: {:?}", hmac);
|
||||
log::info!("Received data: {:?}", server_verify_data);
|
||||
hmac.verify(server_verify_data).unwrap();
|
||||
|
||||
} else if let Ok(sha384) = self.hash.get_sha384_clone() {
|
||||
let hkdf = Hkdf::<Sha384>::from_prk(
|
||||
self.server_traffic_secret.as_ref().unwrap()
|
||||
).unwrap();
|
||||
|
||||
// Compute finished_key
|
||||
let mut okm: GenericArray::<u8, <Sha384 as Digest>::OutputSize> =
|
||||
Default::default();
|
||||
hkdf_expand_label(&hkdf, "finished", "", &mut okm);
|
||||
|
||||
// Get transcript hash
|
||||
let transcript_hash = sha384.finalize();
|
||||
|
||||
// Compute verify_data
|
||||
// let computed_verify_data = Sha384::new()
|
||||
// .chain(&okm)
|
||||
// .chain(&transcript_hash)
|
||||
// .finalize();
|
||||
// log::info!("Computed data: {:?}", computed_verify_data);
|
||||
// log::info!("Received data: {:?}", server_verify_data);
|
||||
// assert_eq!(computed_verify_data.as_slice(), server_verify_data);
|
||||
let mut hmac = Hmac::<Sha384>::new_varkey(&okm).unwrap();
|
||||
hmac.update(&transcript_hash);
|
||||
log::info!("HMAC: {:?}", hmac);
|
||||
log::info!("Received data: {:?}", server_verify_data);
|
||||
hmac.verify(server_verify_data).unwrap();
|
||||
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
// Usual procedures: update hash
|
||||
self.hash.update(server_finished_slice);
|
||||
|
||||
// At last, update client state
|
||||
self.state = TlsState::SERVER_CONNECTED;
|
||||
}
|
||||
|
||||
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
|
||||
@ -586,19 +789,19 @@ impl Hash {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_sha256_clone(&mut self) -> Sha256 {
|
||||
pub(crate) fn get_sha256_clone(&mut self) -> Result<Sha256, ()> {
|
||||
if let Self::Sha256 { sha256 } = self {
|
||||
sha256.clone()
|
||||
Ok(sha256.clone())
|
||||
} else {
|
||||
unreachable!()
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_sha384_clone(&mut self) -> Sha384 {
|
||||
pub(crate) fn get_sha384_clone(&mut self) -> Result<Sha384, ()> {
|
||||
if let Self::Sha384 { sha384 } = self {
|
||||
sha384.clone()
|
||||
Ok(sha384.clone())
|
||||
} else {
|
||||
unreachable!()
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
101
src/tls.rs
101
src/tls.rs
@ -54,6 +54,7 @@ pub(crate) enum TlsState {
|
||||
WAIT_CERT,
|
||||
WAIT_CV,
|
||||
WAIT_FINISHED,
|
||||
SERVER_CONNECTED, // Additional state, for client to send Finished after server Finished
|
||||
CONNECTED,
|
||||
}
|
||||
|
||||
@ -65,7 +66,7 @@ pub struct TlsSocket<R: 'static + RngCore + CryptoRng>
|
||||
session: RefCell<Session>,
|
||||
}
|
||||
|
||||
impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
||||
impl<R: 'static + RngCore + CryptoRng> TlsSocket<R> {
|
||||
pub fn new<'a, 'b, 'c>(
|
||||
sockets: &mut SocketSet<'a, 'b, 'c>,
|
||||
rx_buffer: TcpSocketBuffer<'b>,
|
||||
@ -174,6 +175,14 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
||||
// No need to send anything
|
||||
TlsState::WAIT_CV => {},
|
||||
|
||||
// Last step of server authentication
|
||||
// TLS Client wait for server's Finished handshake
|
||||
// No need to send anything
|
||||
TlsState::WAIT_FINISHED => {}
|
||||
|
||||
// Send client Finished to end handshake
|
||||
TlsState::SERVER_CONNECTED => {}
|
||||
|
||||
_ => todo!()
|
||||
}
|
||||
|
||||
@ -380,7 +389,7 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
||||
// Practically, nothing will be done about cookies/server name
|
||||
// Extension processing is therefore skipped
|
||||
// Update hash of the session, get EE by taking appropriate length of data
|
||||
|
||||
// Length of handshake header is 4
|
||||
let (handshake_slice, ee_slice) =
|
||||
take::<_, _, (&[u8], ErrorKind)>(
|
||||
might_be_ee.length + 4
|
||||
@ -440,12 +449,12 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
||||
|
||||
// TODO: Process Certificate
|
||||
let cert = might_be_cert.get_asn1_der_certificate().unwrap();
|
||||
log::info!("Certificate Acquisition");
|
||||
log::info!("Validation {:?}",
|
||||
log::info!("Certificate validation {:?}",
|
||||
validate_root_certificate(cert)
|
||||
);
|
||||
|
||||
// Update session TLS state to WAIT_CV
|
||||
// Length of handshake header is 4
|
||||
let (handshake_slice, cert_slice) =
|
||||
take::<_, _, (&[u8], ErrorKind)>(
|
||||
might_be_cert.length + 4
|
||||
@ -457,8 +466,6 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
||||
&cert_slice,
|
||||
cert.return_rsa_public_key().unwrap()
|
||||
);
|
||||
|
||||
|
||||
},
|
||||
|
||||
// In this stage, server will eventually send a CertificateVerify
|
||||
@ -471,9 +478,7 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
||||
}
|
||||
|
||||
// Pull out the `payload` from TlsRepr, decrypt as CV
|
||||
// Keep 1 copy to update hash
|
||||
let mut payload = repr.payload.take().unwrap();
|
||||
let cert_slice = payload.clone();
|
||||
|
||||
// Instantiate associated data and decrypt
|
||||
let mut array: [u8; 5] = [0; 5];
|
||||
@ -491,10 +496,86 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
||||
|
||||
// Parse the certificate from TLS payload
|
||||
let parse_result = parse_inner_plaintext_for_handshake(&payload);
|
||||
let (_, mut handshake_vec) = parse_result
|
||||
let (_, (handshake_slice, mut handshake_vec)) = parse_result
|
||||
.map_err(|_| Error::Unrecognized)?;
|
||||
|
||||
// Get hash from session, validate signature
|
||||
// Ensure that it is CertificateVerify
|
||||
let might_be_cert_verify = handshake_vec.remove(0);
|
||||
if might_be_cert_verify.get_msg_type() != HandshakeType::CertificateVerify {
|
||||
// Process the other handshakes in "handshake_vec"
|
||||
todo!()
|
||||
}
|
||||
|
||||
// Take out the portion for CertificateVerify
|
||||
// Length of handshake header is 4
|
||||
let (handshake_slice, cert_verify_slice) =
|
||||
take::<_, _, (&[u8], ErrorKind)>(
|
||||
might_be_cert_verify.length + 4
|
||||
)(handshake_slice)
|
||||
.map_err(|_| Error::Unrecognized)?;
|
||||
|
||||
// Perform verification, update TLS state if successful
|
||||
let (sig_alg, signature) = might_be_cert_verify.get_signature().unwrap();
|
||||
self.session.borrow_mut()
|
||||
.client_update_for_wait_cv(
|
||||
cert_verify_slice,
|
||||
sig_alg,
|
||||
signature
|
||||
);
|
||||
},
|
||||
|
||||
// Client will receive a Finished handshake from server
|
||||
TlsState::WAIT_FINISHED => {
|
||||
// Finished is disguised as Application Data
|
||||
if !repr.is_application_data() {
|
||||
// Abort communication, this affect IV calculation
|
||||
todo!()
|
||||
}
|
||||
|
||||
// Pull out the `payload` from TlsRepr, decrypt as Finished
|
||||
let mut payload = repr.payload.take().unwrap();
|
||||
|
||||
// Instantiate associated data and decrypt
|
||||
let mut array: [u8; 5] = [0; 5];
|
||||
let mut buffer = TlsBuffer::new(&mut array);
|
||||
buffer.write_u8(repr.content_type.into())?;
|
||||
buffer.write_u16(repr.version.into())?;
|
||||
buffer.write_u16(repr.length)?;
|
||||
let associated_data: &[u8] = buffer.into();
|
||||
{
|
||||
self.session.borrow_mut().decrypt_in_place(
|
||||
associated_data,
|
||||
&mut payload
|
||||
);
|
||||
}
|
||||
log::info!("decrypted wait_fin payload: {:?}", payload);
|
||||
|
||||
// Parse the TLS inner ciphertext as a Finished handshake
|
||||
let parse_result = parse_inner_plaintext_for_handshake(&payload);
|
||||
let (_, (handshake_slice, mut handshake_vec)) = parse_result
|
||||
.map_err(|_| Error::Unrecognized)?;
|
||||
|
||||
// Ensure that it is Finished
|
||||
let might_be_server_finished = handshake_vec.remove(0);
|
||||
if might_be_server_finished.get_msg_type() != HandshakeType::Finished {
|
||||
// Process the other handshakes in "handshake_vec"
|
||||
todo!()
|
||||
}
|
||||
|
||||
// Take out the portion for server Finished
|
||||
// Length of handshake header is 4
|
||||
let (handshake_slice, server_finished_slice) =
|
||||
take::<_, _, (&[u8], ErrorKind)>(
|
||||
might_be_server_finished.length + 4
|
||||
)(handshake_slice)
|
||||
.map_err(|_| Error::Unrecognized)?;
|
||||
|
||||
// Perform verification, update TLS state if successful
|
||||
self.session.borrow_mut()
|
||||
.client_update_for_wait_finished(
|
||||
server_finished_slice,
|
||||
might_be_server_finished.get_verify_data().unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
_ => {},
|
||||
|
@ -114,10 +114,6 @@ impl<'a> TlsRepr<'a> {
|
||||
self.handshake.is_none() &&
|
||||
self.payload.is_some()
|
||||
}
|
||||
|
||||
pub(crate) fn decrypt_ee(&self, shared_secret: &SharedSecret) -> HandshakeRepr {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
|
||||
@ -177,6 +173,32 @@ impl<'a, 'b> HandshakeRepr<'a> {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_signature(&self) -> Result<(SignatureScheme, &[u8]), ()> {
|
||||
if self.msg_type != HandshakeType::CertificateVerify {
|
||||
return Err(())
|
||||
};
|
||||
if let HandshakeData::CertificateVerify(
|
||||
cert_verify
|
||||
) = &self.handshake_data {
|
||||
Ok((cert_verify.algorithm, cert_verify.signature))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_verify_data(self) -> Result<&'a [u8], ()> {
|
||||
if self.msg_type != HandshakeType::Finished {
|
||||
return Err(())
|
||||
};
|
||||
if let HandshakeData::Finished(
|
||||
fin
|
||||
) = &self.handshake_data {
|
||||
Ok(fin.verify_data)
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
|
||||
@ -212,6 +234,8 @@ pub(crate) enum HandshakeData<'a> {
|
||||
EncryptedExtensions(EncryptedExtensions),
|
||||
Certificate(Certificate<'a>),
|
||||
CertificateVerify(CertificateVerify<'a>),
|
||||
FinishedNeedParse,
|
||||
Finished(Finished<'a>),
|
||||
}
|
||||
|
||||
impl<'a> HandshakeData<'a> {
|
||||
@ -731,3 +755,8 @@ pub(crate) struct CertificateVerify<'a> {
|
||||
pub(crate) signature_length: u16,
|
||||
pub(crate) signature: &'a [u8],
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct Finished<'a> {
|
||||
pub(crate) verify_data: &'a [u8]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user