mirror of
https://github.com/Noratrieb/tls.git
synced 2026-01-14 16:45:02 +01:00
moves
This commit is contained in:
parent
d4b0e9809f
commit
b930bc0c5d
4 changed files with 199 additions and 182 deletions
70
src/crypto/aead.rs
Normal file
70
src/crypto/aead.rs
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
use ring::aead::Nonce;
|
||||||
|
|
||||||
|
use crate::proto;
|
||||||
|
|
||||||
|
use super::{keys, TlsCiphertext, TlsInnerPlaintext};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub struct AeadKey {
|
||||||
|
key: ring::aead::LessSafeKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AeadKey {
|
||||||
|
fn new(algorithm: proto::CipherSuite, key_bytes: &[u8]) -> Self {
|
||||||
|
Self {
|
||||||
|
key: ring::aead::LessSafeKey::new(
|
||||||
|
ring::aead::UnboundKey::new(proto_algo_to_ring(algorithm), key_bytes)
|
||||||
|
.expect("invalid key"),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn proto_algo_to_ring(algo: proto::CipherSuite) -> &'static ring::aead::Algorithm {
|
||||||
|
match algo {
|
||||||
|
proto::CipherSuite::TLS_AES_128_GCM_SHA256 => &ring::aead::AES_128_GCM,
|
||||||
|
proto::CipherSuite::TLS_AES_256_GCM_SHA384 => &ring::aead::AES_256_GCM,
|
||||||
|
proto::CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => &ring::aead::CHACHA20_POLY1305,
|
||||||
|
proto::CipherSuite::TLS_AES_128_CCM_SHA256 => todo!("TLS_AES_128_CCM_SHA256"),
|
||||||
|
proto::CipherSuite::TLS_AES_128_CCM_8_SHA256 => todo!("TLS_AES_128_CCM_8_SHA256"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encrypt(key: AeadKey, message: &[u8], seq: u8, nonce: Nonce) -> Vec<u8> {
|
||||||
|
let total_len = message.len() + key.key.algorithm().tag_len();
|
||||||
|
let mut ciphertext_payload = Vec::with_capacity(total_len);
|
||||||
|
ciphertext_payload.extend_from_slice(message);
|
||||||
|
|
||||||
|
// FIXME: fill out the AAD properly
|
||||||
|
let aad = ring::aead::Aad::from([0; 5]);
|
||||||
|
key.key
|
||||||
|
.seal_in_place_append_tag(nonce, aad, &mut ciphertext_payload)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
ciphertext_payload
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decrypt(key: AeadKey, msg: &mut [u8], nonce: ring::aead::Nonce) {
|
||||||
|
// FIXME: fill out the AAD properly
|
||||||
|
let aad = ring::aead::Aad::from([0; 5]);
|
||||||
|
key.key.open_in_place(nonce, aad, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlsCiphertext {
|
||||||
|
pub fn decrypt(mut self, secret: &[u8], nonce: Nonce) -> TlsInnerPlaintext {
|
||||||
|
let key = keys::hkdf_expand_label::<sha2::Sha256>(secret, b"key", &[]);
|
||||||
|
let iv = keys::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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,69 +1,16 @@
|
||||||
//! Module for encrypting `TLSPlaintext` records.
|
use sha2::{digest::OutputSizeUser, Digest};
|
||||||
|
|
||||||
use crate::proto::{
|
|
||||||
self,
|
|
||||||
ser_de::{proto_enum, proto_struct, Value},
|
|
||||||
Handshake,
|
|
||||||
};
|
|
||||||
use hkdf::{hmac::Hmac, HmacImpl};
|
|
||||||
use ring::aead::{self, Nonce};
|
|
||||||
pub use seq::{SeqId, SeqIdGen};
|
|
||||||
use sha2::{
|
|
||||||
digest::{
|
|
||||||
core_api::{self, CoreProxy},
|
|
||||||
generic_array::ArrayLength,
|
|
||||||
typenum::Unsigned,
|
|
||||||
OutputSizeUser,
|
|
||||||
},
|
|
||||||
Digest,
|
|
||||||
};
|
|
||||||
use x25519_dalek::SharedSecret;
|
use x25519_dalek::SharedSecret;
|
||||||
|
|
||||||
pub struct TlsCiphertext {
|
use crate::proto::{self, ser_de::Value};
|
||||||
/// The encrypted [`TlsInnerPlaintext`] record.
|
|
||||||
pub encrypted_record: Vec<u8>,
|
|
||||||
}
|
|
||||||
impl From<Vec<u8>> for TlsCiphertext {
|
|
||||||
fn from(value: Vec<u8>) -> Self {
|
|
||||||
TlsCiphertext {
|
|
||||||
encrypted_record: value,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trait TlsHasher: OutputSizeUser {
|
use super::{CryptoProvider, TlsHasher};
|
||||||
const ZEROED: &'static [u8];
|
|
||||||
fn expand(ikm: &[u8], label: &[u8], okm: &mut [u8]) -> Result<(), hkdf::InvalidLength>;
|
|
||||||
fn extract(salt: &[u8], ikm: &[u8]) -> Vec<u8>;
|
|
||||||
}
|
|
||||||
macro_rules! impl_hkdf_hasher {
|
|
||||||
() => {
|
|
||||||
const ZEROED: &'static [u8] =
|
|
||||||
&[0; <<Self as OutputSizeUser>::OutputSize as Unsigned>::USIZE];
|
|
||||||
fn expand(ikm: &[u8], label: &[u8], okm: &mut [u8]) -> Result<(), hkdf::InvalidLength> {
|
|
||||||
hkdf::Hkdf::<Self>::new(None, ikm).expand(&label, okm)
|
|
||||||
}
|
|
||||||
fn extract(salt: &[u8], ikm: &[u8]) -> Vec<u8> {
|
|
||||||
hkdf::Hkdf::<Self>::extract(Some(&[]), &[])
|
|
||||||
.0
|
|
||||||
.as_slice()
|
|
||||||
.to_vec()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
impl TlsHasher for sha2::Sha256 {
|
|
||||||
impl_hkdf_hasher!();
|
|
||||||
}
|
|
||||||
impl TlsHasher for sha2::Sha384 {
|
|
||||||
impl_hkdf_hasher!();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Key Schedule
|
// Key Schedule
|
||||||
// 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: TlsHasher>(secret: &[u8], label: &[u8], context: &[u8]) -> Vec<u8> {
|
pub(super) fn hkdf_expand_label<H: TlsHasher>(secret: &[u8], label: &[u8], context: &[u8]) -> Vec<u8> {
|
||||||
proto_struct! {
|
proto::ser_de::proto_struct! {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct HkdfLabel {
|
pub struct HkdfLabel {
|
||||||
pub length: u16,
|
pub length: u16,
|
||||||
|
|
@ -93,25 +40,10 @@ fn hkdf_expand_label<H: TlsHasher>(secret: &[u8], label: &[u8], context: &[u8])
|
||||||
/// 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: TlsHasher>(secret: &[u8], label: &[u8], messages_hash: &[u8]) -> Vec<u8> {
|
pub(super) fn derive_secret<H: TlsHasher>(secret: &[u8], label: &[u8], messages_hash: &[u8]) -> Vec<u8> {
|
||||||
hkdf_expand_label::<H>(secret, label, messages_hash)
|
hkdf_expand_label::<H>(secret, label, messages_hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CryptoProvider {
|
|
||||||
zeroed_of_hash_size: &'static [u8],
|
|
||||||
hkdf_extract: fn(salt: &[u8], ikm: &[u8]) -> Vec<u8>,
|
|
||||||
derive_secret: fn(secret: &[u8], label: &[u8], messages_hash: &[u8]) -> Vec<u8>,
|
|
||||||
}
|
|
||||||
impl CryptoProvider {
|
|
||||||
fn new<H: TlsHasher>() -> Self {
|
|
||||||
CryptoProvider {
|
|
||||||
zeroed_of_hash_size: H::ZEROED,
|
|
||||||
hkdf_extract: H::extract,
|
|
||||||
derive_secret: derive_secret::<H>,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct TranscriptHash {
|
pub struct TranscriptHash {
|
||||||
state: sha2::Sha256,
|
state: sha2::Sha256,
|
||||||
}
|
}
|
||||||
|
|
@ -121,9 +53,9 @@ impl TranscriptHash {
|
||||||
state: sha2::Sha256::new(),
|
state: sha2::Sha256::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn handshake(&mut self, handshake: &Handshake) {
|
pub fn handshake(&mut self, handshake: &proto::Handshake) {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
handshake.write(&mut buf);
|
proto::ser_de::Value::write(handshake, &mut buf).unwrap();
|
||||||
self.state.update(&buf);
|
self.state.update(&buf);
|
||||||
}
|
}
|
||||||
pub fn get_current(&self) -> Vec<u8> {
|
pub fn get_current(&self) -> Vec<u8> {
|
||||||
|
|
@ -256,104 +188,3 @@ impl KeysAfterServerHello {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AeadKey {
|
|
||||||
key: aead::LessSafeKey,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AeadKey {
|
|
||||||
fn new(algorithm: proto::CipherSuite, key_bytes: &[u8]) -> Self {
|
|
||||||
Self {
|
|
||||||
key: aead::LessSafeKey::new(
|
|
||||||
aead::UnboundKey::new(proto_algo_to_ring(algorithm), key_bytes)
|
|
||||||
.expect("invalid key"),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod seq {
|
|
||||||
use std::cell::Cell;
|
|
||||||
|
|
||||||
use ring::aead::{self, Nonce};
|
|
||||||
|
|
||||||
/// The sequence ID generator.
|
|
||||||
/// There is a separate one maintained for reading and writing.
|
|
||||||
pub struct SeqIdGen {
|
|
||||||
next: Cell<u64>,
|
|
||||||
}
|
|
||||||
impl SeqIdGen {
|
|
||||||
pub fn new() -> SeqIdGen {
|
|
||||||
SeqIdGen { next: Cell::new(0) }
|
|
||||||
}
|
|
||||||
pub fn next(&self) -> SeqId {
|
|
||||||
let next = self.next.get();
|
|
||||||
self.next.set(next.checked_add(1).unwrap());
|
|
||||||
SeqId(next)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Don't implement `Clone` to ensure every seq id is only used once.
|
|
||||||
pub struct SeqId(u64);
|
|
||||||
impl SeqId {
|
|
||||||
pub fn to_nonce(self) -> Nonce {
|
|
||||||
let mut nonce = [0; aead::NONCE_LEN];
|
|
||||||
nonce[4..].copy_from_slice(&self.0.to_be_bytes());
|
|
||||||
Nonce::assume_unique_for_key(nonce)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn proto_algo_to_ring(algo: proto::CipherSuite) -> &'static aead::Algorithm {
|
|
||||||
match algo {
|
|
||||||
proto::CipherSuite::TLS_AES_128_GCM_SHA256 => &aead::AES_128_GCM,
|
|
||||||
proto::CipherSuite::TLS_AES_256_GCM_SHA384 => &aead::AES_256_GCM,
|
|
||||||
proto::CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => &aead::CHACHA20_POLY1305,
|
|
||||||
proto::CipherSuite::TLS_AES_128_CCM_SHA256 => todo!("TLS_AES_128_CCM_SHA256"),
|
|
||||||
proto::CipherSuite::TLS_AES_128_CCM_8_SHA256 => todo!("TLS_AES_128_CCM_8_SHA256"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn encrypt(key: AeadKey, message: &[u8], seq: u8, nonce: Nonce) -> Vec<u8> {
|
|
||||||
let total_len = message.len() + key.key.algorithm().tag_len();
|
|
||||||
let mut ciphertext_payload = Vec::with_capacity(total_len);
|
|
||||||
ciphertext_payload.extend_from_slice(message);
|
|
||||||
|
|
||||||
// FIXME: fill out the AAD properly
|
|
||||||
let aad = aead::Aad::from([0; 5]);
|
|
||||||
key.key
|
|
||||||
.seal_in_place_append_tag(nonce, aad, &mut ciphertext_payload)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
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 {
|
|
||||||
/// The `TLSPlaintext.fragment`` value
|
|
||||||
pub content: Vec<u8>,
|
|
||||||
/// The `TLSPlaintext.type` value
|
|
||||||
pub content_type: u8,
|
|
||||||
pub padding_len: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TlsCiphertext {
|
|
||||||
pub fn decrypt(mut self, secret: &[u8], nonce: Nonce) -> TlsInnerPlaintext {
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
116
src/crypto/mod.rs
Normal file
116
src/crypto/mod.rs
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
//! Cryptographic operations.
|
||||||
|
|
||||||
|
pub mod aead;
|
||||||
|
pub mod keys;
|
||||||
|
|
||||||
|
use crate::proto::{
|
||||||
|
self,
|
||||||
|
ser_de::{proto_enum, proto_struct, Value},
|
||||||
|
Handshake,
|
||||||
|
};
|
||||||
|
use hkdf::{hmac::Hmac, HmacImpl};
|
||||||
|
use ring::aead::Nonce;
|
||||||
|
pub use seq::{SeqId, SeqIdGen};
|
||||||
|
use sha2::{
|
||||||
|
digest::{
|
||||||
|
core_api::{self, CoreProxy},
|
||||||
|
generic_array::ArrayLength,
|
||||||
|
typenum::Unsigned,
|
||||||
|
OutputSizeUser,
|
||||||
|
},
|
||||||
|
Digest,
|
||||||
|
};
|
||||||
|
use x25519_dalek::SharedSecret;
|
||||||
|
|
||||||
|
pub struct TlsCiphertext {
|
||||||
|
/// The encrypted [`TlsInnerPlaintext`] record.
|
||||||
|
pub encrypted_record: Vec<u8>,
|
||||||
|
}
|
||||||
|
impl From<Vec<u8>> for TlsCiphertext {
|
||||||
|
fn from(value: Vec<u8>) -> Self {
|
||||||
|
TlsCiphertext {
|
||||||
|
encrypted_record: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait TlsHasher: OutputSizeUser {
|
||||||
|
const ZEROED: &'static [u8];
|
||||||
|
fn expand(ikm: &[u8], label: &[u8], okm: &mut [u8]) -> Result<(), hkdf::InvalidLength>;
|
||||||
|
fn extract(salt: &[u8], ikm: &[u8]) -> Vec<u8>;
|
||||||
|
}
|
||||||
|
macro_rules! impl_hkdf_hasher {
|
||||||
|
() => {
|
||||||
|
const ZEROED: &'static [u8] =
|
||||||
|
&[0; <<Self as OutputSizeUser>::OutputSize as Unsigned>::USIZE];
|
||||||
|
fn expand(ikm: &[u8], label: &[u8], okm: &mut [u8]) -> Result<(), hkdf::InvalidLength> {
|
||||||
|
hkdf::Hkdf::<Self>::new(None, ikm).expand(&label, okm)
|
||||||
|
}
|
||||||
|
fn extract(salt: &[u8], ikm: &[u8]) -> Vec<u8> {
|
||||||
|
hkdf::Hkdf::<Self>::extract(Some(&[]), &[])
|
||||||
|
.0
|
||||||
|
.as_slice()
|
||||||
|
.to_vec()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
impl TlsHasher for sha2::Sha256 {
|
||||||
|
impl_hkdf_hasher!();
|
||||||
|
}
|
||||||
|
impl TlsHasher for sha2::Sha384 {
|
||||||
|
impl_hkdf_hasher!();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CryptoProvider {
|
||||||
|
zeroed_of_hash_size: &'static [u8],
|
||||||
|
hkdf_extract: fn(salt: &[u8], ikm: &[u8]) -> Vec<u8>,
|
||||||
|
derive_secret: fn(secret: &[u8], label: &[u8], messages_hash: &[u8]) -> Vec<u8>,
|
||||||
|
}
|
||||||
|
impl CryptoProvider {
|
||||||
|
fn new<H: TlsHasher>() -> Self {
|
||||||
|
CryptoProvider {
|
||||||
|
zeroed_of_hash_size: H::ZEROED,
|
||||||
|
hkdf_extract: H::extract,
|
||||||
|
derive_secret: keys::derive_secret::<H>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod seq {
|
||||||
|
use std::cell::Cell;
|
||||||
|
|
||||||
|
use ring::aead::{self, Nonce};
|
||||||
|
|
||||||
|
/// The sequence ID generator.
|
||||||
|
/// There is a separate one maintained for reading and writing.
|
||||||
|
pub struct SeqIdGen {
|
||||||
|
next: Cell<u64>,
|
||||||
|
}
|
||||||
|
impl SeqIdGen {
|
||||||
|
pub fn new() -> SeqIdGen {
|
||||||
|
SeqIdGen { next: Cell::new(0) }
|
||||||
|
}
|
||||||
|
pub fn next(&self) -> SeqId {
|
||||||
|
let next = self.next.get();
|
||||||
|
self.next.set(next.checked_add(1).unwrap());
|
||||||
|
SeqId(next)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Don't implement `Clone` to ensure every seq id is only used once.
|
||||||
|
pub struct SeqId(u64);
|
||||||
|
impl SeqId {
|
||||||
|
pub fn to_nonce(self) -> Nonce {
|
||||||
|
let mut nonce = [0; aead::NONCE_LEN];
|
||||||
|
nonce[4..].copy_from_slice(&self.0.to_be_bytes());
|
||||||
|
Nonce::assume_unique_for_key(nonce)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TlsInnerPlaintext {
|
||||||
|
/// The `TLSPlaintext.fragment`` value
|
||||||
|
pub content: Vec<u8>,
|
||||||
|
/// The `TLSPlaintext.type` value
|
||||||
|
pub content_type: u8,
|
||||||
|
pub padding_len: u16,
|
||||||
|
}
|
||||||
10
src/lib.rs
10
src/lib.rs
|
|
@ -1,6 +1,6 @@
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
|
|
||||||
mod crypt;
|
mod crypto;
|
||||||
pub mod proto;
|
pub mod proto;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
|
@ -9,7 +9,7 @@ use std::{
|
||||||
io::{self, Read, Write},
|
io::{self, Read, Write},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crypt::{KeysAfterServerHello, TranscriptHash};
|
use crypto::keys::{KeysAfterServerHello, TranscriptHash};
|
||||||
use proto::{ser_de::Value, CipherSuite};
|
use proto::{ser_de::Value, CipherSuite};
|
||||||
|
|
||||||
use crate::proto::TLSPlaintext;
|
use crate::proto::TLSPlaintext;
|
||||||
|
|
@ -38,7 +38,7 @@ struct ClientSetupConnection<W> {
|
||||||
mod stream_state {
|
mod stream_state {
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
use crate::crypt::{SeqId, SeqIdGen};
|
use crate::crypto::{SeqId, SeqIdGen};
|
||||||
use crate::proto::{self, TLSPlaintext};
|
use crate::proto::{self, TLSPlaintext};
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
|
||||||
|
|
@ -317,7 +317,7 @@ impl<W: Read + Write> ClientSetupConnection<W> {
|
||||||
dh_shared_secret.as_bytes()
|
dh_shared_secret.as_bytes()
|
||||||
);
|
);
|
||||||
|
|
||||||
let keys = crypt::KeysAfterServerHello::compute(
|
let keys = KeysAfterServerHello::compute(
|
||||||
dh_shared_secret,
|
dh_shared_secret,
|
||||||
*cipher_suite,
|
*cipher_suite,
|
||||||
&transcript.borrow(),
|
&transcript.borrow(),
|
||||||
|
|
@ -336,7 +336,7 @@ impl<W: Read + Write> ClientSetupConnection<W> {
|
||||||
return unexpected_message!("expected ApplicationData, got {frame:?}");
|
return unexpected_message!("expected ApplicationData, got {frame:?}");
|
||||||
};
|
};
|
||||||
// Encrypted with server_handshake_traffic_secret
|
// Encrypted with server_handshake_traffic_secret
|
||||||
crypt::TlsCiphertext::from(data).decrypt(
|
crypto::TlsCiphertext::from(data).decrypt(
|
||||||
&keys
|
&keys
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue