mirror of
https://github.com/Noratrieb/tls.git
synced 2026-01-14 08:35:03 +01:00
attempt to decrypt
This commit is contained in:
parent
b930bc0c5d
commit
0f93d225e7
7 changed files with 174 additions and 252 deletions
228
Cargo.lock
generated
228
Cargo.lock
generated
|
|
@ -2,6 +2,41 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aead"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-common",
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aes"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cipher",
|
||||||
|
"cpufeatures",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aes-gcm"
|
||||||
|
version = "0.10.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1"
|
||||||
|
dependencies = [
|
||||||
|
"aead",
|
||||||
|
"aes",
|
||||||
|
"cipher",
|
||||||
|
"ctr",
|
||||||
|
"ghash",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
version = "0.10.4"
|
version = "0.10.4"
|
||||||
|
|
@ -11,30 +46,28 @@ dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bumpalo"
|
|
||||||
version = "3.16.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cc"
|
|
||||||
version = "1.0.99"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cipher"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-common",
|
||||||
|
"inout",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cpufeatures"
|
name = "cpufeatures"
|
||||||
version = "0.2.12"
|
version = "0.2.12"
|
||||||
|
|
@ -51,9 +84,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
|
"rand_core",
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ctr"
|
||||||
|
version = "0.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
|
||||||
|
dependencies = [
|
||||||
|
"cipher",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "curve25519-dalek"
|
name = "curve25519-dalek"
|
||||||
version = "4.1.2"
|
version = "4.1.2"
|
||||||
|
|
@ -119,6 +162,16 @@ dependencies = [
|
||||||
"wasi",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ghash"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1"
|
||||||
|
dependencies = [
|
||||||
|
"opaque-debug",
|
||||||
|
"polyval",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hkdf"
|
name = "hkdf"
|
||||||
version = "0.12.4"
|
version = "0.12.4"
|
||||||
|
|
@ -138,12 +191,12 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "inout"
|
||||||
version = "0.3.69"
|
version = "0.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
|
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wasm-bindgen",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -153,16 +206,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "opaque-debug"
|
||||||
version = "0.4.21"
|
version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "once_cell"
|
|
||||||
version = "1.19.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "platforms"
|
name = "platforms"
|
||||||
|
|
@ -170,6 +217,18 @@ version = "3.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7"
|
checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "polyval"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"opaque-debug",
|
||||||
|
"universal-hash",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.17"
|
version = "0.2.17"
|
||||||
|
|
@ -224,21 +283,6 @@ dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ring"
|
|
||||||
version = "0.16.20"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
"libc",
|
|
||||||
"once_cell",
|
|
||||||
"spin",
|
|
||||||
"untrusted",
|
|
||||||
"web-sys",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_version"
|
name = "rustc_version"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|
@ -285,12 +329,6 @@ dependencies = [
|
||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "spin"
|
|
||||||
version = "0.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
|
|
@ -312,10 +350,10 @@ dependencies = [
|
||||||
name = "tls"
|
name = "tls"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"aes-gcm",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"hkdf",
|
"hkdf",
|
||||||
"rand",
|
"rand",
|
||||||
"ring",
|
|
||||||
"sha2",
|
"sha2",
|
||||||
"x25519-dalek",
|
"x25519-dalek",
|
||||||
]
|
]
|
||||||
|
|
@ -333,10 +371,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "untrusted"
|
name = "universal-hash"
|
||||||
version = "0.7.1"
|
version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-common",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
|
|
@ -350,92 +392,6 @@ version = "0.11.0+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen"
|
|
||||||
version = "0.2.92"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"wasm-bindgen-macro",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen-backend"
|
|
||||||
version = "0.2.92"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
|
|
||||||
dependencies = [
|
|
||||||
"bumpalo",
|
|
||||||
"log",
|
|
||||||
"once_cell",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
"wasm-bindgen-shared",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen-macro"
|
|
||||||
version = "0.2.92"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
|
|
||||||
dependencies = [
|
|
||||||
"quote",
|
|
||||||
"wasm-bindgen-macro-support",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen-macro-support"
|
|
||||||
version = "0.2.92"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
"wasm-bindgen-backend",
|
|
||||||
"wasm-bindgen-shared",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-bindgen-shared"
|
|
||||||
version = "0.2.92"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "web-sys"
|
|
||||||
version = "0.3.69"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
|
|
||||||
dependencies = [
|
|
||||||
"js-sys",
|
|
||||||
"wasm-bindgen",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi"
|
|
||||||
version = "0.3.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
|
||||||
dependencies = [
|
|
||||||
"winapi-i686-pc-windows-gnu",
|
|
||||||
"winapi-x86_64-pc-windows-gnu",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-i686-pc-windows-gnu"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "x25519-dalek"
|
name = "x25519-dalek"
|
||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
aes-gcm = "0.10.3"
|
||||||
byteorder = "1.4.3"
|
byteorder = "1.4.3"
|
||||||
hkdf = "0.12.3"
|
hkdf = "0.12.3"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
ring = "0.16.20"
|
|
||||||
sha2 = "0.10.8"
|
sha2 = "0.10.8"
|
||||||
x25519-dalek = "2.0.0"
|
x25519-dalek = "2.0.0"
|
||||||
|
|
|
||||||
|
|
@ -1,70 +1,51 @@
|
||||||
use ring::aead::Nonce;
|
//! Symmetric AEAD-based record encryption.
|
||||||
|
//! <https://datatracker.ietf.org/doc/html/rfc8446#section-5.2>
|
||||||
|
|
||||||
|
use aes_gcm::{
|
||||||
|
aead::{Aead, Payload},
|
||||||
|
Aes128Gcm, KeyInit,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::proto;
|
use crate::proto;
|
||||||
|
|
||||||
use super::{keys, TlsCiphertext, TlsInnerPlaintext};
|
use super::{keys, TlsInnerPlaintext};
|
||||||
|
|
||||||
|
pub type AeadKey = aes_gcm::Key<Aes128Gcm>;
|
||||||
|
pub type Nonce = aes_gcm::Nonce<<Aes128Gcm as aes_gcm::AeadCore>::NonceSize>;
|
||||||
|
|
||||||
|
fn decrypt(key: &AeadKey, ciphertext: &[u8], nonce: &Nonce, additional_data: &[u8]) -> Vec<u8> {
|
||||||
pub struct AeadKey {
|
let cipher = Aes128Gcm::new(key);
|
||||||
key: ring::aead::LessSafeKey,
|
cipher
|
||||||
|
.decrypt(
|
||||||
|
nonce,
|
||||||
|
Payload {
|
||||||
|
msg: ciphertext,
|
||||||
|
aad: additional_data,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AeadKey {
|
pub fn decrypt_ciphertext(
|
||||||
fn new(algorithm: proto::CipherSuite, key_bytes: &[u8]) -> Self {
|
encrypted_record: &[u8],
|
||||||
Self {
|
secret: &[u8],
|
||||||
key: ring::aead::LessSafeKey::new(
|
nonce: Nonce,
|
||||||
ring::aead::UnboundKey::new(proto_algo_to_ring(algorithm), key_bytes)
|
) -> TlsInnerPlaintext {
|
||||||
.expect("invalid key"),
|
// <https://datatracker.ietf.org/doc/html/rfc8446#section-7.3>
|
||||||
),
|
let key = keys::hkdf_expand_label::<sha2::Sha256>(secret, b"key", &[], 128/8);
|
||||||
}
|
|
||||||
}
|
let key = aes_gcm::Key::<Aes128Gcm>::from_slice(&key[0..(128 / 8)]);
|
||||||
}
|
|
||||||
|
// TLS v1.2 0x03, 0x03
|
||||||
|
let mut additional_data = [proto::TLSPlaintext::APPLICATION_DATA, 0x03, 0x03, 0, 0];
|
||||||
fn proto_algo_to_ring(algo: proto::CipherSuite) -> &'static ring::aead::Algorithm {
|
let ciphertext_len = encrypted_record.as_ref().len() as u16;
|
||||||
match algo {
|
additional_data[3..].copy_from_slice(&ciphertext_len.to_be_bytes());
|
||||||
proto::CipherSuite::TLS_AES_128_GCM_SHA256 => &ring::aead::AES_128_GCM,
|
|
||||||
proto::CipherSuite::TLS_AES_256_GCM_SHA384 => &ring::aead::AES_256_GCM,
|
let result = decrypt(key, encrypted_record, &nonce, &additional_data);
|
||||||
proto::CipherSuite::TLS_CHACHA20_POLY1305_SHA256 => &ring::aead::CHACHA20_POLY1305,
|
|
||||||
proto::CipherSuite::TLS_AES_128_CCM_SHA256 => todo!("TLS_AES_128_CCM_SHA256"),
|
TlsInnerPlaintext {
|
||||||
proto::CipherSuite::TLS_AES_128_CCM_8_SHA256 => todo!("TLS_AES_128_CCM_8_SHA256"),
|
content: result,
|
||||||
}
|
content_type: 0,
|
||||||
}
|
padding_len: 0,
|
||||||
|
|
||||||
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,4 +1,4 @@
|
||||||
use sha2::{digest::OutputSizeUser, Digest};
|
use sha2::Digest;
|
||||||
use x25519_dalek::SharedSecret;
|
use x25519_dalek::SharedSecret;
|
||||||
|
|
||||||
use crate::proto::{self, ser_de::Value};
|
use crate::proto::{self, ser_de::Value};
|
||||||
|
|
@ -9,7 +9,12 @@ use super::{CryptoProvider, TlsHasher};
|
||||||
// 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
|
||||||
pub(super) 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],
|
||||||
|
length: usize,
|
||||||
|
) -> Vec<u8> {
|
||||||
proto::ser_de::proto_struct! {
|
proto::ser_de::proto_struct! {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct HkdfLabel {
|
pub struct HkdfLabel {
|
||||||
|
|
@ -21,7 +26,7 @@ pub(super) fn hkdf_expand_label<H: TlsHasher>(secret: &[u8], label: &[u8], conte
|
||||||
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 as OutputSizeUser>::output_size().try_into().unwrap(),
|
length: length.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);
|
||||||
|
|
@ -34,14 +39,18 @@ pub(super) fn hkdf_expand_label<H: TlsHasher>(secret: &[u8], label: &[u8], conte
|
||||||
|
|
||||||
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 as OutputSizeUser>::output_size()].to_vec()
|
okm[..length].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.
|
||||||
pub(super) fn derive_secret<H: TlsHasher>(secret: &[u8], label: &[u8], messages_hash: &[u8]) -> Vec<u8> {
|
pub(super) fn derive_secret<H: TlsHasher>(
|
||||||
hkdf_expand_label::<H>(secret, label, messages_hash)
|
secret: &[u8],
|
||||||
|
label: &[u8],
|
||||||
|
messages_hash: &[u8],
|
||||||
|
) -> Vec<u8> {
|
||||||
|
hkdf_expand_label::<H>(secret, label, messages_hash, H::output_size())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TranscriptHash {
|
pub struct TranscriptHash {
|
||||||
|
|
@ -117,7 +126,6 @@ impl TranscriptHash {
|
||||||
|
|
||||||
pub struct KeysAfterServerHello {
|
pub struct KeysAfterServerHello {
|
||||||
provider: CryptoProvider,
|
provider: CryptoProvider,
|
||||||
handhske_secret: Vec<u8>,
|
|
||||||
pub client_handshake_traffic_secret: Vec<u8>,
|
pub client_handshake_traffic_secret: Vec<u8>,
|
||||||
pub server_handshake_traffic_secret: Vec<u8>,
|
pub server_handshake_traffic_secret: Vec<u8>,
|
||||||
master_secret: Vec<u8>,
|
master_secret: Vec<u8>,
|
||||||
|
|
@ -167,20 +175,20 @@ impl KeysAfterServerHello {
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
provider,
|
provider,
|
||||||
handhske_secret,
|
|
||||||
client_handshake_traffic_secret,
|
client_handshake_traffic_secret,
|
||||||
server_handshake_traffic_secret,
|
server_handshake_traffic_secret,
|
||||||
master_secret,
|
master_secret,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
fn after_handshake(self, transcript: &TranscriptHash) {
|
fn after_handshake(self, transcript: &TranscriptHash) {
|
||||||
let client_application_traffic_secret_0 = (self.provider.derive_secret)(
|
let _client_application_traffic_secret_0 = (self.provider.derive_secret)(
|
||||||
&self.master_secret,
|
&self.master_secret,
|
||||||
b"c ap traffic",
|
b"c ap traffic",
|
||||||
&transcript.get_current(),
|
&transcript.get_current(),
|
||||||
);
|
);
|
||||||
let server_application_traffic_secret_0 = (self.provider.derive_secret)(
|
let _server_application_traffic_secret_0 = (self.provider.derive_secret)(
|
||||||
&self.master_secret,
|
&self.master_secret,
|
||||||
b"s ap traffic",
|
b"s ap traffic",
|
||||||
&transcript.get_current(),
|
&transcript.get_current(),
|
||||||
|
|
|
||||||
|
|
@ -3,36 +3,8 @@
|
||||||
pub mod aead;
|
pub mod aead;
|
||||||
pub mod keys;
|
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};
|
pub use seq::{SeqId, SeqIdGen};
|
||||||
use sha2::{
|
use sha2::digest::{typenum::Unsigned, OutputSizeUser};
|
||||||
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 {
|
trait TlsHasher: OutputSizeUser {
|
||||||
const ZEROED: &'static [u8];
|
const ZEROED: &'static [u8];
|
||||||
|
|
@ -47,7 +19,7 @@ macro_rules! impl_hkdf_hasher {
|
||||||
hkdf::Hkdf::<Self>::new(None, ikm).expand(&label, okm)
|
hkdf::Hkdf::<Self>::new(None, ikm).expand(&label, okm)
|
||||||
}
|
}
|
||||||
fn extract(salt: &[u8], ikm: &[u8]) -> Vec<u8> {
|
fn extract(salt: &[u8], ikm: &[u8]) -> Vec<u8> {
|
||||||
hkdf::Hkdf::<Self>::extract(Some(&[]), &[])
|
hkdf::Hkdf::<Self>::extract(Some(salt), ikm)
|
||||||
.0
|
.0
|
||||||
.as_slice()
|
.as_slice()
|
||||||
.to_vec()
|
.to_vec()
|
||||||
|
|
@ -79,7 +51,7 @@ impl CryptoProvider {
|
||||||
mod seq {
|
mod seq {
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
use ring::aead::{self, Nonce};
|
use super::aead::Nonce;
|
||||||
|
|
||||||
/// The sequence ID generator.
|
/// The sequence ID generator.
|
||||||
/// There is a separate one maintained for reading and writing.
|
/// There is a separate one maintained for reading and writing.
|
||||||
|
|
@ -100,13 +72,14 @@ mod seq {
|
||||||
pub struct SeqId(u64);
|
pub struct SeqId(u64);
|
||||||
impl SeqId {
|
impl SeqId {
|
||||||
pub fn to_nonce(self) -> Nonce {
|
pub fn to_nonce(self) -> Nonce {
|
||||||
let mut nonce = [0; aead::NONCE_LEN];
|
let mut nonce = [0; 12];
|
||||||
nonce[4..].copy_from_slice(&self.0.to_be_bytes());
|
nonce[4..].copy_from_slice(&self.0.to_be_bytes());
|
||||||
Nonce::assume_unique_for_key(nonce)
|
Nonce::from(nonce)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct TlsInnerPlaintext {
|
pub struct TlsInnerPlaintext {
|
||||||
/// The `TLSPlaintext.fragment`` value
|
/// The `TLSPlaintext.fragment`` value
|
||||||
pub content: Vec<u8>,
|
pub content: Vec<u8>,
|
||||||
|
|
|
||||||
16
src/lib.rs
16
src/lib.rs
|
|
@ -1,5 +1,3 @@
|
||||||
#![allow(unused)]
|
|
||||||
|
|
||||||
mod crypto;
|
mod crypto;
|
||||||
pub mod proto;
|
pub mod proto;
|
||||||
|
|
||||||
|
|
@ -10,7 +8,10 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crypto::keys::{KeysAfterServerHello, TranscriptHash};
|
use crypto::keys::{KeysAfterServerHello, TranscriptHash};
|
||||||
use proto::{ser_de::Value, CipherSuite};
|
use proto::{
|
||||||
|
ser_de::{FrameReader, Value},
|
||||||
|
CipherSuite, TlsCiphertext,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::proto::TLSPlaintext;
|
use crate::proto::TLSPlaintext;
|
||||||
|
|
||||||
|
|
@ -117,6 +118,7 @@ https://datatracker.ietf.org/doc/html/rfc8446#appendix-A.1
|
||||||
CONNECTED
|
CONNECTED
|
||||||
```
|
```
|
||||||
*/
|
*/
|
||||||
|
#[allow(dead_code)]
|
||||||
enum ConnectState {
|
enum ConnectState {
|
||||||
Start,
|
Start,
|
||||||
WaitServerHello {
|
WaitServerHello {
|
||||||
|
|
@ -216,7 +218,7 @@ impl<W: Read + Write> ClientSetupConnection<W> {
|
||||||
cipher_suites,
|
cipher_suites,
|
||||||
transcript,
|
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() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -332,11 +334,13 @@ impl<W: Read + Write> ClientSetupConnection<W> {
|
||||||
if frame.should_drop() {
|
if frame.should_drop() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let proto::TLSPlaintext::ApplicationData { data } = frame else {
|
// Frame is a TLSCiphertext.
|
||||||
|
let proto::TLSPlaintext::ApplicationData { data: encrypted_record } = frame else {
|
||||||
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
|
||||||
crypto::TlsCiphertext::from(data).decrypt(
|
crypto::aead::decrypt_ciphertext(
|
||||||
|
&encrypted_record,
|
||||||
&keys
|
&keys
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
|
|
||||||
10
src/proto.rs
10
src/proto.rs
|
|
@ -38,11 +38,11 @@ pub enum TLSPlaintext {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TLSPlaintext {
|
impl TLSPlaintext {
|
||||||
const INVALID: u8 = 0;
|
pub const INVALID: u8 = 0;
|
||||||
const CHANGE_CIPHER_SPEC: u8 = 20;
|
pub const CHANGE_CIPHER_SPEC: u8 = 20;
|
||||||
const ALERT: u8 = 21;
|
pub const ALERT: u8 = 21;
|
||||||
const HANDSHAKE: u8 = 22;
|
pub const HANDSHAKE: u8 = 22;
|
||||||
const APPLICATION_DATA: u8 = 23;
|
pub const APPLICATION_DATA: u8 = 23;
|
||||||
|
|
||||||
pub fn write(&self, w: &mut impl Write) -> io::Result<()> {
|
pub fn write(&self, w: &mut impl Write) -> io::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue