mirror of
https://github.com/Noratrieb/tls.git
synced 2026-01-14 16:45:02 +01:00
more
This commit is contained in:
parent
c767352e43
commit
d4b0e9809f
2 changed files with 159 additions and 69 deletions
182
src/crypt.rs
182
src/crypt.rs
|
|
@ -3,15 +3,19 @@
|
||||||
use crate::proto::{
|
use crate::proto::{
|
||||||
self,
|
self,
|
||||||
ser_de::{proto_enum, proto_struct, Value},
|
ser_de::{proto_enum, proto_struct, Value},
|
||||||
|
Handshake,
|
||||||
};
|
};
|
||||||
use hkdf::{hmac::Hmac, HmacImpl};
|
use hkdf::{hmac::Hmac, HmacImpl};
|
||||||
use ring::aead::{self, Nonce};
|
use ring::aead::{self, Nonce};
|
||||||
pub use seq::{SeqId, SeqIdGen};
|
pub use seq::{SeqId, SeqIdGen};
|
||||||
use sha2::digest::{
|
use sha2::{
|
||||||
core_api::{self, CoreProxy},
|
digest::{
|
||||||
generic_array::ArrayLength,
|
core_api::{self, CoreProxy},
|
||||||
typenum::Unsigned,
|
generic_array::ArrayLength,
|
||||||
OutputSizeUser,
|
typenum::Unsigned,
|
||||||
|
OutputSizeUser,
|
||||||
|
},
|
||||||
|
Digest,
|
||||||
};
|
};
|
||||||
use x25519_dalek::SharedSecret;
|
use x25519_dalek::SharedSecret;
|
||||||
|
|
||||||
|
|
@ -27,7 +31,7 @@ impl From<Vec<u8>> for TlsCiphertext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait HkdfHasher: OutputSizeUser {
|
trait TlsHasher: OutputSizeUser {
|
||||||
const ZEROED: &'static [u8];
|
const ZEROED: &'static [u8];
|
||||||
fn expand(ikm: &[u8], label: &[u8], okm: &mut [u8]) -> Result<(), hkdf::InvalidLength>;
|
fn expand(ikm: &[u8], label: &[u8], okm: &mut [u8]) -> Result<(), hkdf::InvalidLength>;
|
||||||
fn extract(salt: &[u8], ikm: &[u8]) -> Vec<u8>;
|
fn extract(salt: &[u8], ikm: &[u8]) -> Vec<u8>;
|
||||||
|
|
@ -47,10 +51,10 @@ macro_rules! impl_hkdf_hasher {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
impl HkdfHasher for sha2::Sha256 {
|
impl TlsHasher for sha2::Sha256 {
|
||||||
impl_hkdf_hasher!();
|
impl_hkdf_hasher!();
|
||||||
}
|
}
|
||||||
impl HkdfHasher for sha2::Sha384 {
|
impl TlsHasher for sha2::Sha384 {
|
||||||
impl_hkdf_hasher!();
|
impl_hkdf_hasher!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,7 +62,7 @@ impl HkdfHasher for sha2::Sha384 {
|
||||||
// https://datatracker.ietf.org/doc/html/rfc8446#section-7.1
|
// https://datatracker.ietf.org/doc/html/rfc8446#section-7.1
|
||||||
|
|
||||||
// The Hash function used by Transcript-Hash and HKDF is the cipher suite hash algorithm
|
// The Hash function used by Transcript-Hash and HKDF is the cipher suite hash algorithm
|
||||||
fn hkdf_expand_label<H: HkdfHasher>(secret: &[u8], label: &[u8], context: &[u8]) -> Vec<u8> {
|
fn hkdf_expand_label<H: TlsHasher>(secret: &[u8], label: &[u8], context: &[u8]) -> Vec<u8> {
|
||||||
proto_struct! {
|
proto_struct! {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct HkdfLabel {
|
pub struct HkdfLabel {
|
||||||
|
|
@ -70,7 +74,7 @@ fn hkdf_expand_label<H: HkdfHasher>(secret: &[u8], label: &[u8], context: &[u8])
|
||||||
let mut hkdf_label = Vec::new();
|
let mut hkdf_label = Vec::new();
|
||||||
HkdfLabel {
|
HkdfLabel {
|
||||||
// Hash.length is its output length in bytes
|
// Hash.length is its output length in bytes
|
||||||
length: H::output_size().try_into().unwrap(),
|
length: <H as OutputSizeUser>::output_size().try_into().unwrap(),
|
||||||
label: {
|
label: {
|
||||||
let mut v = b"tls13 ".to_vec();
|
let mut v = b"tls13 ".to_vec();
|
||||||
v.extend_from_slice(label);
|
v.extend_from_slice(label);
|
||||||
|
|
@ -83,23 +87,23 @@ fn hkdf_expand_label<H: HkdfHasher>(secret: &[u8], label: &[u8], context: &[u8])
|
||||||
|
|
||||||
let mut okm = [0u8; 128];
|
let mut okm = [0u8; 128];
|
||||||
H::expand(secret, &hkdf_label, &mut okm).unwrap();
|
H::expand(secret, &hkdf_label, &mut okm).unwrap();
|
||||||
okm[..H::output_size()].to_vec()
|
okm[..<H as OutputSizeUser>::output_size()].to_vec()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Messages is the concatenation of the indicated handshake messages,
|
/// Messages is the concatenation of the indicated handshake messages,
|
||||||
/// including the handshake message type and length fields, but not
|
/// including the handshake message type and length fields, but not
|
||||||
/// including record layer headers.
|
/// including record layer headers.
|
||||||
fn derive_secret<H: HkdfHasher>(secret: &[u8], label: &[u8], messages: ()) -> Vec<u8> {
|
fn derive_secret<H: TlsHasher>(secret: &[u8], label: &[u8], messages_hash: &[u8]) -> Vec<u8> {
|
||||||
hkdf_expand_label::<H>(secret, label, &[])
|
hkdf_expand_label::<H>(secret, label, messages_hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CryptoProvider {
|
pub struct CryptoProvider {
|
||||||
zeroed_of_hash_size: &'static [u8],
|
zeroed_of_hash_size: &'static [u8],
|
||||||
hkdf_extract: fn(salt: &[u8], ikm: &[u8]) -> Vec<u8>,
|
hkdf_extract: fn(salt: &[u8], ikm: &[u8]) -> Vec<u8>,
|
||||||
derive_secret: fn(secret: &[u8], label: &[u8], messages: ()) -> Vec<u8>,
|
derive_secret: fn(secret: &[u8], label: &[u8], messages_hash: &[u8]) -> Vec<u8>,
|
||||||
}
|
}
|
||||||
impl CryptoProvider {
|
impl CryptoProvider {
|
||||||
fn new<H: HkdfHasher>() -> Self {
|
fn new<H: TlsHasher>() -> Self {
|
||||||
CryptoProvider {
|
CryptoProvider {
|
||||||
zeroed_of_hash_size: H::ZEROED,
|
zeroed_of_hash_size: H::ZEROED,
|
||||||
hkdf_extract: H::extract,
|
hkdf_extract: H::extract,
|
||||||
|
|
@ -108,6 +112,25 @@ impl CryptoProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct TranscriptHash {
|
||||||
|
state: sha2::Sha256,
|
||||||
|
}
|
||||||
|
impl TranscriptHash {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
state: sha2::Sha256::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn handshake(&mut self, handshake: &Handshake) {
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
handshake.write(&mut buf);
|
||||||
|
self.state.update(&buf);
|
||||||
|
}
|
||||||
|
pub fn get_current(&self) -> Vec<u8> {
|
||||||
|
self.state.clone().finalize().to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
```text
|
```text
|
||||||
0
|
0
|
||||||
|
|
@ -159,53 +182,79 @@ impl CryptoProvider {
|
||||||
= resumption_master_secret
|
= resumption_master_secret
|
||||||
```
|
```
|
||||||
*/
|
*/
|
||||||
pub fn compute_keys(shared_secret: SharedSecret, algo: proto::CipherSuite) {
|
|
||||||
let provider = match algo {
|
|
||||||
proto::CipherSuite::TLS_AES_128_GCM_SHA256 => CryptoProvider::new::<sha2::Sha256>(),
|
|
||||||
proto::CipherSuite::TLS_AES_256_GCM_SHA384 => CryptoProvider::new::<sha2::Sha384>(),
|
|
||||||
proto::CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => CryptoProvider::new::<sha2::Sha256>(),
|
|
||||||
proto::CipherSuite::TLS_AES_128_CCM_SHA256 => CryptoProvider::new::<sha2::Sha256>(),
|
|
||||||
proto::CipherSuite::TLS_AES_128_CCM_8_SHA256 => CryptoProvider::new::<sha2::Sha256>(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let early_secret =
|
pub struct KeysAfterServerHello {
|
||||||
(provider.hkdf_extract)(&provider.zeroed_of_hash_size, &provider.zeroed_of_hash_size);
|
provider: CryptoProvider,
|
||||||
|
handhske_secret: Vec<u8>,
|
||||||
|
pub client_handshake_traffic_secret: Vec<u8>,
|
||||||
|
pub server_handshake_traffic_secret: Vec<u8>,
|
||||||
|
master_secret: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
let handhske_secret = (provider.hkdf_extract)(
|
impl KeysAfterServerHello {
|
||||||
&(provider.derive_secret)(&early_secret, b"derived", (/*empty*/)),
|
pub fn compute(
|
||||||
shared_secret.as_bytes(),
|
shared_secret: SharedSecret,
|
||||||
);
|
algo: proto::CipherSuite,
|
||||||
|
transcript: &TranscriptHash,
|
||||||
|
) -> Self {
|
||||||
|
let provider = match algo {
|
||||||
|
proto::CipherSuite::TLS_AES_128_GCM_SHA256 => CryptoProvider::new::<sha2::Sha256>(),
|
||||||
|
proto::CipherSuite::TLS_AES_256_GCM_SHA384 => {
|
||||||
|
todo!("anyhting but SHA256")
|
||||||
|
// CryptoProvider::new::<sha2::Sha384>()
|
||||||
|
}
|
||||||
|
proto::CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => {
|
||||||
|
CryptoProvider::new::<sha2::Sha256>()
|
||||||
|
}
|
||||||
|
proto::CipherSuite::TLS_AES_128_CCM_SHA256 => CryptoProvider::new::<sha2::Sha256>(),
|
||||||
|
proto::CipherSuite::TLS_AES_128_CCM_8_SHA256 => CryptoProvider::new::<sha2::Sha256>(),
|
||||||
|
};
|
||||||
|
|
||||||
let client_handshake_traffic_secret = (provider.derive_secret)(
|
let early_secret =
|
||||||
&handhske_secret,
|
(provider.hkdf_extract)(&provider.zeroed_of_hash_size, &provider.zeroed_of_hash_size);
|
||||||
b"c hs traffic",
|
|
||||||
(/*clienthello..serverhello*/),
|
|
||||||
);
|
|
||||||
|
|
||||||
let server_handshake_traffic_secret = (provider.derive_secret)(
|
let handhske_secret = (provider.hkdf_extract)(
|
||||||
&handhske_secret,
|
&(provider.derive_secret)(&early_secret, b"derived", &transcript.get_current()),
|
||||||
b"s hs traffic",
|
shared_secret.as_bytes(),
|
||||||
(/*clienthello..serverhello*/),
|
);
|
||||||
);
|
|
||||||
|
|
||||||
let master_secret = (provider.hkdf_extract)(
|
let client_handshake_traffic_secret =
|
||||||
&(provider.derive_secret)(&handhske_secret, b"derived", (/*empty*/)),
|
(provider.derive_secret)(&handhske_secret, b"c hs traffic", &transcript.get_current());
|
||||||
&provider.zeroed_of_hash_size,
|
|
||||||
);
|
|
||||||
|
|
||||||
let client_application_traffic_secret_0 = (provider.derive_secret)(
|
let server_handshake_traffic_secret =
|
||||||
&master_secret,
|
(provider.derive_secret)(&handhske_secret, b"s hs traffic", &transcript.get_current());
|
||||||
b"c ap traffic",
|
|
||||||
(/*clienthello..server finished*/),
|
|
||||||
);
|
|
||||||
let server_application_traffic_secret_0 = (provider.derive_secret)(
|
|
||||||
&master_secret,
|
|
||||||
b"s ap traffic",
|
|
||||||
(/*clienthello..server finished*/),
|
|
||||||
);
|
|
||||||
|
|
||||||
|
let master_secret = (provider.hkdf_extract)(
|
||||||
|
&(provider.derive_secret)(
|
||||||
|
&handhske_secret,
|
||||||
|
b"derived",
|
||||||
|
&sha2::Sha256::new().finalize(),
|
||||||
|
),
|
||||||
|
&provider.zeroed_of_hash_size,
|
||||||
|
);
|
||||||
|
|
||||||
dbg!("keys");
|
Self {
|
||||||
|
provider,
|
||||||
|
handhske_secret,
|
||||||
|
client_handshake_traffic_secret,
|
||||||
|
server_handshake_traffic_secret,
|
||||||
|
master_secret,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn after_handshake(self, transcript: &TranscriptHash) {
|
||||||
|
let client_application_traffic_secret_0 = (self.provider.derive_secret)(
|
||||||
|
&self.master_secret,
|
||||||
|
b"c ap traffic",
|
||||||
|
&transcript.get_current(),
|
||||||
|
);
|
||||||
|
let server_application_traffic_secret_0 = (self.provider.derive_secret)(
|
||||||
|
&self.master_secret,
|
||||||
|
b"s ap traffic",
|
||||||
|
&transcript.get_current(),
|
||||||
|
);
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AeadKey {
|
pub struct AeadKey {
|
||||||
|
|
@ -264,13 +313,11 @@ fn proto_algo_to_ring(algo: proto::CipherSuite) -> &'static aead::Algorithm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encrypt(key: AeadKey, message: &[u8], seq: u8) -> Vec<u8> {
|
fn encrypt(key: AeadKey, message: &[u8], seq: u8, nonce: Nonce) -> Vec<u8> {
|
||||||
let total_len = message.len() + key.key.algorithm().tag_len();
|
let total_len = message.len() + key.key.algorithm().tag_len();
|
||||||
let mut ciphertext_payload = Vec::with_capacity(total_len);
|
let mut ciphertext_payload = Vec::with_capacity(total_len);
|
||||||
ciphertext_payload.extend_from_slice(message);
|
ciphertext_payload.extend_from_slice(message);
|
||||||
|
|
||||||
// FIXME: dont use zero obviously
|
|
||||||
let nonce = aead::Nonce::assume_unique_for_key([0; aead::NONCE_LEN]);
|
|
||||||
// FIXME: fill out the AAD properly
|
// FIXME: fill out the AAD properly
|
||||||
let aad = aead::Aad::from([0; 5]);
|
let aad = aead::Aad::from([0; 5]);
|
||||||
key.key
|
key.key
|
||||||
|
|
@ -280,6 +327,12 @@ fn encrypt(key: AeadKey, message: &[u8], seq: u8) -> Vec<u8> {
|
||||||
ciphertext_payload
|
ciphertext_payload
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn decrypt(key: AeadKey, msg: &mut [u8], nonce: Nonce) {
|
||||||
|
// FIXME: fill out the AAD properly
|
||||||
|
let aad = aead::Aad::from([0; 5]);
|
||||||
|
key.key.open_in_place(nonce, aad, msg);
|
||||||
|
}
|
||||||
|
|
||||||
pub struct TlsInnerPlaintext {
|
pub struct TlsInnerPlaintext {
|
||||||
/// The `TLSPlaintext.fragment`` value
|
/// The `TLSPlaintext.fragment`` value
|
||||||
pub content: Vec<u8>,
|
pub content: Vec<u8>,
|
||||||
|
|
@ -289,7 +342,18 @@ pub struct TlsInnerPlaintext {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TlsCiphertext {
|
impl TlsCiphertext {
|
||||||
pub fn decrypt(&self, key: AeadKey, nonce: Nonce) -> TlsInnerPlaintext {
|
pub fn decrypt(mut self, secret: &[u8], nonce: Nonce) -> TlsInnerPlaintext {
|
||||||
todo!()
|
let key = hkdf_expand_label::<sha2::Sha256>(secret, b"key", &[]);
|
||||||
|
let iv = hkdf_expand_label::<sha2::Sha256>(secret, b"iv", &[]);
|
||||||
|
|
||||||
|
let key = AeadKey::new(proto::CipherSuite::TLS_AES_128_GCM_SHA256, secret);
|
||||||
|
|
||||||
|
decrypt(key, &mut self.encrypted_record, nonce);
|
||||||
|
|
||||||
|
TlsInnerPlaintext {
|
||||||
|
content: self.encrypted_record,
|
||||||
|
content_type: 0,
|
||||||
|
padding_len: 0,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
46
src/lib.rs
46
src/lib.rs
|
|
@ -9,7 +9,8 @@ use std::{
|
||||||
io::{self, Read, Write},
|
io::{self, Read, Write},
|
||||||
};
|
};
|
||||||
|
|
||||||
use proto::CipherSuite;
|
use crypt::{KeysAfterServerHello, TranscriptHash};
|
||||||
|
use proto::{ser_de::Value, CipherSuite};
|
||||||
|
|
||||||
use crate::proto::TLSPlaintext;
|
use crate::proto::TLSPlaintext;
|
||||||
|
|
||||||
|
|
@ -122,8 +123,11 @@ enum ConnectState {
|
||||||
legacy_session_id: [u8; 32],
|
legacy_session_id: [u8; 32],
|
||||||
secret: RefCell<Option<x25519_dalek::EphemeralSecret>>,
|
secret: RefCell<Option<x25519_dalek::EphemeralSecret>>,
|
||||||
cipher_suites: Vec<CipherSuite>,
|
cipher_suites: Vec<CipherSuite>,
|
||||||
|
transcript: RefCell<TranscriptHash>,
|
||||||
|
},
|
||||||
|
WaitEncryptedExtensions {
|
||||||
|
keys: RefCell<Option<KeysAfterServerHello>>,
|
||||||
},
|
},
|
||||||
WaitEncryptedExtensions,
|
|
||||||
WaitCertificateRequest,
|
WaitCertificateRequest,
|
||||||
WaitCertificate,
|
WaitCertificate,
|
||||||
WaitCertificateVerify,
|
WaitCertificateVerify,
|
||||||
|
|
@ -193,18 +197,24 @@ impl<W: Read + Write> ClientSetupConnection<W> {
|
||||||
]
|
]
|
||||||
.into(),
|
.into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut transcript = TranscriptHash::new();
|
||||||
|
transcript.handshake(&handshake);
|
||||||
|
|
||||||
let plaintext = proto::TLSPlaintext::Handshake { handshake };
|
let plaintext = proto::TLSPlaintext::Handshake { handshake };
|
||||||
self.stream.write_flush_record(plaintext)?;
|
self.stream.write_flush_record(plaintext)?;
|
||||||
ConnectState::WaitServerHello {
|
ConnectState::WaitServerHello {
|
||||||
legacy_session_id,
|
legacy_session_id,
|
||||||
secret: RefCell::new(Some(secret)),
|
secret: RefCell::new(Some(secret)),
|
||||||
cipher_suites,
|
cipher_suites,
|
||||||
|
transcript: RefCell::new(transcript),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ConnectState::WaitServerHello {
|
ConnectState::WaitServerHello {
|
||||||
legacy_session_id,
|
legacy_session_id,
|
||||||
secret,
|
secret,
|
||||||
cipher_suites,
|
cipher_suites,
|
||||||
|
transcript,
|
||||||
} => {
|
} => {
|
||||||
let (frame, seq_id) = self.stream.read_record()?;
|
let (frame, seq_id) = self.stream.read_record()?;
|
||||||
if frame.should_drop() {
|
if frame.should_drop() {
|
||||||
|
|
@ -212,7 +222,7 @@ impl<W: Read + Write> ClientSetupConnection<W> {
|
||||||
}
|
}
|
||||||
let proto::TLSPlaintext::Handshake {
|
let proto::TLSPlaintext::Handshake {
|
||||||
handshake:
|
handshake:
|
||||||
proto::Handshake::ServerHello {
|
handshake @ proto::Handshake::ServerHello {
|
||||||
legacy_version,
|
legacy_version,
|
||||||
random,
|
random,
|
||||||
legacy_session_id_echo,
|
legacy_session_id_echo,
|
||||||
|
|
@ -220,7 +230,7 @@ impl<W: Read + Write> ClientSetupConnection<W> {
|
||||||
legacy_compression_method,
|
legacy_compression_method,
|
||||||
extensions,
|
extensions,
|
||||||
},
|
},
|
||||||
} = frame
|
} = &frame
|
||||||
else {
|
else {
|
||||||
return unexpected_message!("expected ServerHello, got {frame:?}");
|
return unexpected_message!("expected ServerHello, got {frame:?}");
|
||||||
};
|
};
|
||||||
|
|
@ -229,7 +239,7 @@ impl<W: Read + Write> ClientSetupConnection<W> {
|
||||||
return Err(ErrorKind::HelloRetryRequest.into());
|
return Err(ErrorKind::HelloRetryRequest.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if legacy_version != proto::LEGACY_TLSV12 {
|
if *legacy_version != proto::LEGACY_TLSV12 {
|
||||||
return unexpected_message!(
|
return unexpected_message!(
|
||||||
"unexpected TLS version in legacy_version field: {legacy_version:x?}"
|
"unexpected TLS version in legacy_version field: {legacy_version:x?}"
|
||||||
);
|
);
|
||||||
|
|
@ -247,12 +257,14 @@ impl<W: Read + Write> ClientSetupConnection<W> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if legacy_compression_method != 0 {
|
if *legacy_compression_method != 0 {
|
||||||
return unexpected_message!(
|
return unexpected_message!(
|
||||||
"legacy compression method MUST be zero: {legacy_compression_method}"
|
"legacy compression method MUST be zero: {legacy_compression_method}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transcript.borrow_mut().handshake(&handshake);
|
||||||
|
|
||||||
let mut supported_versions = false;
|
let mut supported_versions = false;
|
||||||
let mut server_key = None;
|
let mut server_key = None;
|
||||||
|
|
||||||
|
|
@ -305,11 +317,17 @@ impl<W: Read + Write> ClientSetupConnection<W> {
|
||||||
dh_shared_secret.as_bytes()
|
dh_shared_secret.as_bytes()
|
||||||
);
|
);
|
||||||
|
|
||||||
crypt::compute_keys(dh_shared_secret, cipher_suite);
|
let keys = crypt::KeysAfterServerHello::compute(
|
||||||
|
dh_shared_secret,
|
||||||
|
*cipher_suite,
|
||||||
|
&transcript.borrow(),
|
||||||
|
);
|
||||||
|
|
||||||
ConnectState::WaitEncryptedExtensions
|
ConnectState::WaitEncryptedExtensions {
|
||||||
|
keys: RefCell::new(Some(keys)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ConnectState::WaitEncryptedExtensions => {
|
ConnectState::WaitEncryptedExtensions { keys } => {
|
||||||
let (frame, seq_id) = self.stream.read_record()?;
|
let (frame, seq_id) = self.stream.read_record()?;
|
||||||
if frame.should_drop() {
|
if frame.should_drop() {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -317,7 +335,15 @@ impl<W: Read + Write> ClientSetupConnection<W> {
|
||||||
let proto::TLSPlaintext::ApplicationData { data } = frame else {
|
let proto::TLSPlaintext::ApplicationData { data } = frame else {
|
||||||
return unexpected_message!("expected ApplicationData, got {frame:?}");
|
return unexpected_message!("expected ApplicationData, got {frame:?}");
|
||||||
};
|
};
|
||||||
//crypt::TlsCiphertext::from(data).decrypt(key, seq_id.to_nonce());
|
// Encrypted with server_handshake_traffic_secret
|
||||||
|
crypt::TlsCiphertext::from(data).decrypt(
|
||||||
|
&keys
|
||||||
|
.borrow()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.server_handshake_traffic_secret,
|
||||||
|
seq_id.to_nonce(),
|
||||||
|
);
|
||||||
|
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue