mirror of
https://github.com/Noratrieb/tls.git
synced 2026-01-14 16:45:02 +01:00
make progress
This commit is contained in:
parent
b4faf77116
commit
eea717987d
11 changed files with 574 additions and 343 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
|
@ -0,0 +1 @@
|
|||
use nix
|
||||
127
Cargo.lock
generated
127
Cargo.lock
generated
|
|
@ -13,24 +13,21 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.14.0"
|
||||
version = "3.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
|
||||
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.83"
|
||||
version = "1.0.99"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
|
|
@ -40,9 +37,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.9"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
|
||||
checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
|
@ -59,9 +56,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "curve25519-dalek"
|
||||
version = "4.1.1"
|
||||
version = "4.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c"
|
||||
checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
|
|
@ -75,9 +72,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "curve25519-dalek-derive"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b"
|
||||
checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -97,9 +94,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "fiat-crypto"
|
||||
version = "0.2.1"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d"
|
||||
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
|
|
@ -113,9 +110,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.10"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
|
||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
|
|
@ -124,9 +121,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hkdf"
|
||||
version = "0.12.3"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
|
||||
checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
|
||||
dependencies = [
|
||||
"hmac",
|
||||
]
|
||||
|
|
@ -142,36 +139,36 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.64"
|
||||
version = "0.3.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
|
||||
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.147"
|
||||
version = "0.2.155"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.20"
|
||||
version = "0.4.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.18.0"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "platforms"
|
||||
version = "3.1.2"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8"
|
||||
checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
|
|
@ -181,18 +178,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.67"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
|
||||
checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
|
@ -253,30 +250,41 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.19"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0"
|
||||
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.188"
|
||||
version = "1.0.203"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
|
||||
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.188"
|
||||
version = "1.0.203"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
|
||||
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.5.2"
|
||||
|
|
@ -291,9 +299,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.37"
|
||||
version = "2.0.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8"
|
||||
checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -308,6 +316,7 @@ dependencies = [
|
|||
"hkdf",
|
||||
"rand",
|
||||
"ring",
|
||||
"sha2",
|
||||
"x25519-dalek",
|
||||
]
|
||||
|
||||
|
|
@ -343,9 +352,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.87"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
|
||||
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
|
|
@ -353,9 +362,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.87"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
|
||||
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
|
|
@ -368,9 +377,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.87"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
|
||||
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
|
|
@ -378,9 +387,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.87"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
|
||||
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -391,15 +400,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.87"
|
||||
version = "0.2.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
|
||||
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.64"
|
||||
version = "0.3.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
|
||||
checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
|
|
@ -429,9 +438,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|||
|
||||
[[package]]
|
||||
name = "x25519-dalek"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96"
|
||||
checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277"
|
||||
dependencies = [
|
||||
"curve25519-dalek",
|
||||
"rand_core",
|
||||
|
|
@ -441,9 +450,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.6.0"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
|
||||
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
|
||||
dependencies = [
|
||||
"zeroize_derive",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -10,4 +10,5 @@ byteorder = "1.4.3"
|
|||
hkdf = "0.12.3"
|
||||
rand = "0.8.5"
|
||||
ring = "0.16.20"
|
||||
sha2 = "0.10.8"
|
||||
x25519-dalek = "2.0.0"
|
||||
|
|
|
|||
61
flake.lock
generated
61
flake.lock
generated
|
|
@ -1,61 +0,0 @@
|
|||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1692799911,
|
||||
"narHash": "sha256-3eihraek4qL744EvQXsK1Ha6C3CR7nnT8X2qWap4RNk=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "f9e7cf818399d17d347f847525c5a5a8032e4e44",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1693985761,
|
||||
"narHash": "sha256-K5b+7j7Tt3+AqbWkcw+wMeqOAWyCD1MH26FPZyWXpdo=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "0bffda19b8af722f8069d09d8b6a24594c80b352",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
42
flake.nix
42
flake.nix
|
|
@ -1,42 +0,0 @@
|
|||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, flake-utils, ... }: flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
in
|
||||
{
|
||||
devShells.default = pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
llvmPackages_16.clang
|
||||
llvmPackages_16.bintools
|
||||
llvmPackages_16.libllvm
|
||||
llvmPackages_16.lldb
|
||||
rustup
|
||||
];
|
||||
# https://github.com/rust-lang/rust-bindgen#environment-variables
|
||||
LIBCLANG_PATH = pkgs.lib.makeLibraryPath [ pkgs.llvmPackages_latest.libclang.lib ];
|
||||
shellHook = ''
|
||||
export PATH=$PATH:''${CARGO_HOME:-~/.cargo}/bin
|
||||
export PATH=$PATH:''${RUSTUP_HOME:-~/.rustup}/toolchains/$RUSTC_VERSION-x86_64-unknown-linux-gnu/bin/
|
||||
'';
|
||||
# Add glibc, clang, glib and other headers to bindgen search path
|
||||
BINDGEN_EXTRA_CLANG_ARGS =
|
||||
(builtins.map (a: ''-I"${a}/include"'') [
|
||||
pkgs.glibc.dev
|
||||
])
|
||||
# Includes with special directory paths
|
||||
++ [
|
||||
''-I"${pkgs.llvmPackages_latest.libclang.lib}/lib/clang/${pkgs.llvmPackages_latest.libclang.version}/include"''
|
||||
''-I"${pkgs.glib.dev}/include/glib-2.0"''
|
||||
''-I${pkgs.glib.out}/lib/glib-2.0/include/''
|
||||
];
|
||||
packages = (with pkgs; [
|
||||
wireshark
|
||||
]);
|
||||
};
|
||||
});
|
||||
}
|
||||
9
shell.nix
Normal file
9
shell.nix
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{ pkgs ? import <nixpkgs> { } }: pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
|
||||
];
|
||||
RUST_BACKTRACE = 1;
|
||||
packages = (with pkgs; [
|
||||
wireshark
|
||||
]);
|
||||
}
|
||||
106
src/crypt.rs
106
src/crypt.rs
|
|
@ -1,11 +1,55 @@
|
|||
//! Module for encrypting `TLSPlaintext` records.
|
||||
|
||||
use crate::proto;
|
||||
use crate::proto::{
|
||||
self,
|
||||
ser_de::{proto_enum, proto_struct, Value},
|
||||
};
|
||||
|
||||
use ring::aead;
|
||||
use ring::aead::{self, Nonce};
|
||||
|
||||
struct TlsCiphertext {
|
||||
encrypted_record: Vec<u8>,
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_keys(shared_secret: SharedSecret) {
|
||||
let hkdf_expand_label = |secret: &[u8], label: &[u8], context: &[u8], length| {
|
||||
proto_struct! {
|
||||
#[derive(Debug)]
|
||||
pub struct HkdfLabel {
|
||||
pub length: u16,
|
||||
pub label: proto::ser_de::List<u8,u8>,
|
||||
pub context: proto::ser_de::List<u8,u8>,
|
||||
}
|
||||
}
|
||||
let mut hkdf_label = Vec::new();
|
||||
HkdfLabel {
|
||||
length,
|
||||
label: {
|
||||
let mut v = b"tls13 ".to_vec();
|
||||
v.extend_from_slice(label);
|
||||
v.into()
|
||||
},
|
||||
context: context.to_vec().into(),
|
||||
}
|
||||
.write(&mut hkdf_label)
|
||||
.unwrap();
|
||||
|
||||
// TODO: use correct algo, the cipher suite hash algorithm!
|
||||
let mut okm = [0u8; 42];
|
||||
hkdf::Hkdf::<sha2::Sha256>::new(None, secret).expand(&hkdf_label, &mut okm)
|
||||
};
|
||||
|
||||
let derive_secret = |secret: &[u8], label: &[u8], messages: ()| {
|
||||
hkdf_expand_label(secret, label, &[], 16) // todo: fix length
|
||||
};
|
||||
}
|
||||
|
||||
pub struct AeadKey {
|
||||
|
|
@ -16,12 +60,46 @@ 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"),
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
pub use seq::{SeqId, SeqIdGen};
|
||||
use x25519_dalek::SharedSecret;
|
||||
|
||||
fn proto_algo_to_ring(algo: proto::CipherSuite) -> &'static aead::Algorithm {
|
||||
match algo {
|
||||
proto::CipherSuite::TLS_AES_128_GCM_SHA256 => &aead::AES_128_GCM,
|
||||
|
|
@ -41,7 +119,23 @@ fn encrypt(key: AeadKey, message: &[u8], seq: u8) -> Vec<u8> {
|
|||
let nonce = aead::Nonce::assume_unique_for_key([0; aead::NONCE_LEN]);
|
||||
// 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();
|
||||
key.key
|
||||
.seal_in_place_append_tag(nonce, aad, &mut ciphertext_payload)
|
||||
.unwrap();
|
||||
|
||||
ciphertext_payload
|
||||
}
|
||||
|
||||
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(&self, key: AeadKey, nonce: Nonce) -> TlsInnerPlaintext {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
208
src/lib.rs
208
src/lib.rs
|
|
@ -2,10 +2,14 @@ mod crypt;
|
|||
pub mod proto;
|
||||
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
fmt::Debug,
|
||||
io::{self, Read, Write},
|
||||
};
|
||||
|
||||
use crypt::{SeqId, SeqIdGen};
|
||||
use proto::CipherSuite;
|
||||
|
||||
use crate::proto::TLSPlaintext;
|
||||
|
||||
type Result<T, E = Error> = std::result::Result<T, E>;
|
||||
|
|
@ -16,24 +20,125 @@ pub struct ClientConnection<W> {
|
|||
|
||||
impl<W: Read + Write> ClientConnection<W> {
|
||||
pub fn establish(w: W, host: &str) -> Result<Self> {
|
||||
let _setup = ClientSetupConnection::establish(w, host)?;
|
||||
let mut setup = ClientSetupConnection {
|
||||
stream: StreamState::new(w),
|
||||
};
|
||||
let _setup = setup.establish(host)?;
|
||||
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
struct ClientSetupConnection<W> {
|
||||
_w: W,
|
||||
stream: StreamState<W>,
|
||||
}
|
||||
|
||||
mod stream_state {
|
||||
use std::io::{Read, Write};
|
||||
|
||||
use crate::crypt::{SeqId, SeqIdGen};
|
||||
use crate::proto::{self, TLSPlaintext};
|
||||
use crate::Result;
|
||||
|
||||
pub struct StreamState<W> {
|
||||
stream: W,
|
||||
read_seq_id: SeqIdGen,
|
||||
write_seq_id: SeqIdGen,
|
||||
}
|
||||
impl<W: Write + Read> StreamState<W> {
|
||||
pub fn new(stream: W) -> Self {
|
||||
Self {
|
||||
stream,
|
||||
read_seq_id: SeqIdGen::new(),
|
||||
write_seq_id: SeqIdGen::new(),
|
||||
}
|
||||
}
|
||||
pub fn write_flush_record(&mut self, plaintext: TLSPlaintext) -> Result<()> {
|
||||
self.write_record(plaintext)?;
|
||||
self.stream.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write_record(&mut self, plaintext: TLSPlaintext) -> Result<SeqId> {
|
||||
plaintext.write(&mut self.stream)?;
|
||||
self.stream.flush()?;
|
||||
Ok(self.write_seq_id.next())
|
||||
}
|
||||
|
||||
pub fn read_record(&mut self) -> Result<(TLSPlaintext, SeqId)> {
|
||||
let seq_id = self.read_seq_id.next();
|
||||
let frame = proto::TLSPlaintext::read(&mut self.stream)?;
|
||||
Ok((frame, seq_id))
|
||||
}
|
||||
}
|
||||
}
|
||||
use stream_state::StreamState;
|
||||
|
||||
macro_rules! unexpected_message {
|
||||
($($tt:tt)*) => {
|
||||
Err(ErrorKind::UnexpectedMessage(format!($($tt)*)).into())
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
https://datatracker.ietf.org/doc/html/rfc8446#appendix-A.1
|
||||
|
||||
```text
|
||||
START <----+
|
||||
Send ClientHello | | Recv HelloRetryRequest
|
||||
[K_send = early data] | |
|
||||
v |
|
||||
/ WAIT_SH ----+
|
||||
| | Recv ServerHello
|
||||
| | K_recv = handshake
|
||||
Can | V
|
||||
send | WAIT_EE
|
||||
early | | Recv EncryptedExtensions
|
||||
data | +--------+--------+
|
||||
| Using | | Using certificate
|
||||
| PSK | v
|
||||
| | WAIT_CERT_CR
|
||||
| | Recv | | Recv CertificateRequest
|
||||
| | Certificate | v
|
||||
| | | WAIT_CERT
|
||||
| | | | Recv Certificate
|
||||
| | v v
|
||||
| | WAIT_CV
|
||||
| | | Recv CertificateVerify
|
||||
| +> WAIT_FINISHED <+
|
||||
| | Recv Finished
|
||||
\ | [Send EndOfEarlyData]
|
||||
| K_send = handshake
|
||||
| [Send Certificate [+ CertificateVerify]]
|
||||
Can send | Send Finished
|
||||
app data --> | K_send = K_recv = application
|
||||
after here v
|
||||
CONNECTED
|
||||
```
|
||||
*/
|
||||
enum ConnectState {
|
||||
Start,
|
||||
WaitServerHello {
|
||||
legacy_session_id: [u8; 32],
|
||||
secret: RefCell<Option<x25519_dalek::EphemeralSecret>>,
|
||||
cipher_suites: Vec<CipherSuite>,
|
||||
},
|
||||
WaitEncryptedExtensions,
|
||||
WaitCertificateRequest,
|
||||
WaitCertificate,
|
||||
WaitCertificateVerify,
|
||||
WaitFinished,
|
||||
Connected,
|
||||
}
|
||||
|
||||
impl<W: Read + Write> ClientSetupConnection<W> {
|
||||
fn establish(mut stream: W, host: &str) -> Result<Self> {
|
||||
fn establish(&mut self, host: &str) -> Result<Self> {
|
||||
let mut state = ConnectState::Start;
|
||||
|
||||
loop {
|
||||
let next_state = match &state {
|
||||
ConnectState::Start => {
|
||||
// https://datatracker.ietf.org/doc/html/rfc8446#section-2
|
||||
let secret = x25519_dalek::EphemeralSecret::random_from_rng(rand::thread_rng());
|
||||
let public = x25519_dalek::PublicKey::from(&secret);
|
||||
|
||||
|
|
@ -89,12 +194,22 @@ impl<W: Read + Write> ClientSetupConnection<W> {
|
|||
.into(),
|
||||
};
|
||||
let plaintext = proto::TLSPlaintext::Handshake { handshake };
|
||||
plaintext.write(&mut stream)?;
|
||||
stream.flush()?;
|
||||
|
||||
let out = proto::TLSPlaintext::read(&mut stream)?;
|
||||
dbg!(&out);
|
||||
|
||||
self.stream.write_flush_record(plaintext)?;
|
||||
ConnectState::WaitServerHello {
|
||||
legacy_session_id,
|
||||
secret: RefCell::new(Some(secret)),
|
||||
cipher_suites,
|
||||
}
|
||||
}
|
||||
ConnectState::WaitServerHello {
|
||||
legacy_session_id,
|
||||
secret,
|
||||
cipher_suites,
|
||||
} => {
|
||||
let (frame, seq_id) = self.stream.read_record()?;
|
||||
if frame.should_drop() {
|
||||
continue;
|
||||
}
|
||||
let proto::TLSPlaintext::Handshake {
|
||||
handshake:
|
||||
proto::Handshake::ServerHello {
|
||||
|
|
@ -105,11 +220,9 @@ impl<W: Read + Write> ClientSetupConnection<W> {
|
|||
legacy_compression_method,
|
||||
extensions,
|
||||
},
|
||||
} = out
|
||||
} = frame
|
||||
else {
|
||||
return Err(
|
||||
ErrorKind::UnexpectedMessage(format!("expected ServerHello, got {out:?}")).into(),
|
||||
);
|
||||
return unexpected_message!("expected ServerHello, got {frame:?}");
|
||||
};
|
||||
|
||||
if random.is_hello_retry_request() {
|
||||
|
|
@ -148,41 +261,84 @@ impl<W: Read + Write> ClientSetupConnection<W> {
|
|||
proto::ExtensionSH::PreSharedKey => todo!(),
|
||||
proto::ExtensionSH::SupportedVersions { selected_version } => {
|
||||
if *selected_version != proto::TLSV13 {
|
||||
return unexpected_message!("server returned non-TLS 1.3 version: {selected_version}");
|
||||
return unexpected_message!(
|
||||
"server returned non-TLS 1.3 version: {selected_version}"
|
||||
);
|
||||
}
|
||||
supported_versions = true;
|
||||
},
|
||||
}
|
||||
proto::ExtensionSH::Cookie { .. } => todo!(),
|
||||
proto::ExtensionSH::KeyShare { key_share } => {
|
||||
let entry = key_share.unwrap_server_hello();
|
||||
match entry {
|
||||
proto::KeyShareEntry::X25519 { len, key_exchange } => {
|
||||
if *len != 32 {
|
||||
return unexpected_message!("key length for X25519 key share must be 32: {len}");
|
||||
return unexpected_message!(
|
||||
"key length for X25519 key share must be 32: {len}"
|
||||
);
|
||||
}
|
||||
server_key = Some(key_exchange);
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !supported_versions {
|
||||
return unexpected_message!("server did not send supported_versions extension");
|
||||
return unexpected_message!(
|
||||
"server did not send supported_versions extension"
|
||||
);
|
||||
}
|
||||
|
||||
let Some(server_key) = server_key else {
|
||||
return unexpected_message!("server did not send its key");
|
||||
};
|
||||
let server_key = x25519_dalek::PublicKey::from(*server_key);
|
||||
let dh_shared_secret = secret.diffie_hellman(&server_key);
|
||||
let dh_shared_secret = secret
|
||||
.borrow_mut()
|
||||
.take()
|
||||
.unwrap()
|
||||
.diffie_hellman(&server_key);
|
||||
|
||||
println!("we have established a shared secret. dont leak it!! anywhere here is it: {:x?}", dh_shared_secret.as_bytes());
|
||||
println!(
|
||||
"we have established a shared secret. dont leak it!! anyways here is it: {:x?}",
|
||||
dh_shared_secret.as_bytes()
|
||||
);
|
||||
|
||||
dbg!(proto::TLSPlaintext::read(&mut stream))?;
|
||||
crypt::compute_keys(dh_shared_secret);
|
||||
|
||||
ConnectState::WaitEncryptedExtensions
|
||||
}
|
||||
ConnectState::WaitEncryptedExtensions => {
|
||||
let (frame, seq_id) = self.stream.read_record()?;
|
||||
if frame.should_drop() {
|
||||
continue;
|
||||
}
|
||||
let proto::TLSPlaintext::ApplicationData { data } = frame else {
|
||||
return unexpected_message!("expected ApplicationData, got {frame:?}");
|
||||
};
|
||||
//crypt::TlsCiphertext::from(data).decrypt(key, seq_id.to_nonce());
|
||||
|
||||
todo!()
|
||||
}
|
||||
ConnectState::WaitCertificateRequest => todo!(),
|
||||
ConnectState::WaitCertificate => todo!(),
|
||||
ConnectState::WaitCertificateVerify => todo!(),
|
||||
ConnectState::WaitFinished => todo!(),
|
||||
ConnectState::Connected => todo!(),
|
||||
};
|
||||
state = next_state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TLSPlaintext {
|
||||
fn should_drop(&self) -> bool {
|
||||
match self {
|
||||
TLSPlaintext::ChangeCipherSpec { data: body } if body.as_ref() == &[0x01] => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -201,16 +357,16 @@ pub enum ErrorKind {
|
|||
impl From<io::Error> for Error {
|
||||
fn from(value: io::Error) -> Self {
|
||||
panic!("error: {value}");
|
||||
Self {
|
||||
kind: ErrorKind::Io(value),
|
||||
}
|
||||
//Self {
|
||||
// kind: ErrorKind::Io(value),
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ErrorKind> for Error {
|
||||
fn from(value: ErrorKind) -> Self {
|
||||
panic!("error:{value:?}");
|
||||
Self { kind: value }
|
||||
//Self { kind: value }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@ use std::net::TcpStream;
|
|||
|
||||
// An example program that makes a shitty HTTP/1.1 request.
|
||||
fn main() {
|
||||
let conn = tls::LoggingWriter(TcpStream::connect(("nilstrieb.dev", 443)).unwrap());
|
||||
tls::ClientConnection::establish(conn, "nilstrieb.dev").unwrap();
|
||||
let conn = tls::LoggingWriter(TcpStream::connect(("vps1.nilstrieb.dev", 443)).unwrap());
|
||||
tls::ClientConnection::establish(conn, "vps1.nilstrieb.dev").unwrap();
|
||||
}
|
||||
|
|
|
|||
79
src/proto.rs
79
src/proto.rs
|
|
@ -17,14 +17,24 @@ pub enum TLSPlaintext {
|
|||
},
|
||||
/// This only exists for compatibility and must be sent immediately before the second flight.
|
||||
/// If this is received with the single byte value `0x01`, then it should just be dropped.
|
||||
ChangeCipherSpec,
|
||||
///
|
||||
/// An implementation may receive an unencrypted record of type
|
||||
/// change_cipher_spec consisting of the single byte value 0x01 at any
|
||||
/// time after the first ClientHello message has been sent or received
|
||||
/// and before the peer's Finished message has been received and MUST
|
||||
/// simply drop it without further processing.
|
||||
ChangeCipherSpec {
|
||||
data: List<u8, u16>,
|
||||
},
|
||||
Alert {
|
||||
alert: Alert,
|
||||
},
|
||||
Handshake {
|
||||
handshake: Handshake,
|
||||
},
|
||||
ApplicationData,
|
||||
ApplicationData {
|
||||
data: Vec<u8>,
|
||||
},
|
||||
}
|
||||
|
||||
impl TLSPlaintext {
|
||||
|
|
@ -36,9 +46,24 @@ impl TLSPlaintext {
|
|||
|
||||
pub fn write(&self, w: &mut impl Write) -> io::Result<()> {
|
||||
match self {
|
||||
TLSPlaintext::Invalid { .. } => todo!(),
|
||||
TLSPlaintext::ChangeCipherSpec => todo!(),
|
||||
TLSPlaintext::Alert { .. } => todo!(),
|
||||
TLSPlaintext::Invalid { .. } => {
|
||||
Self::INVALID.write(w)?;
|
||||
LEGACY_TLSV12.write(w)?;
|
||||
|
||||
todo!()
|
||||
}
|
||||
TLSPlaintext::ChangeCipherSpec { data: body } => {
|
||||
Self::CHANGE_CIPHER_SPEC.write(w)?;
|
||||
LEGACY_TLSV12.write(w)?;
|
||||
body.write(w)?;
|
||||
Ok(())
|
||||
}
|
||||
TLSPlaintext::Alert { .. } => {
|
||||
Self::ALERT.write(w)?;
|
||||
LEGACY_TLSV12.write(w)?;
|
||||
|
||||
todo!()
|
||||
}
|
||||
TLSPlaintext::Handshake { handshake } => {
|
||||
Self::HANDSHAKE.write(w)?;
|
||||
// MUST be set to 0x0303 for all records
|
||||
|
|
@ -55,7 +80,14 @@ impl TLSPlaintext {
|
|||
handshake.write(w)?;
|
||||
Ok(())
|
||||
}
|
||||
TLSPlaintext::ApplicationData => todo!(),
|
||||
TLSPlaintext::ApplicationData { data } => {
|
||||
Self::APPLICATION_DATA.write(w)?;
|
||||
LEGACY_TLSV12.write(w)?;
|
||||
let len: u16 = data.len().try_into().unwrap();
|
||||
len.write(w)?;
|
||||
w.write_all(&data)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -63,10 +95,19 @@ impl TLSPlaintext {
|
|||
let r = &mut FrameReader::new(r);
|
||||
let discr = u8::read(r)?;
|
||||
let _legacy_version = ProtocolVersion::read(r)?;
|
||||
let _len = u16::read(r)?;
|
||||
let len = u16::read(r)?;
|
||||
if len > 2_u16.pow(14) {
|
||||
return Err(crate::ErrorKind::InvalidFrame(Box::new(format!(
|
||||
"TLSPLaintext opaque length exceeds 2^14: {len}"
|
||||
)))
|
||||
.into());
|
||||
}
|
||||
match discr {
|
||||
Self::INVALID => todo!(),
|
||||
Self::CHANGE_CIPHER_SPEC => todo!(),
|
||||
Self::CHANGE_CIPHER_SPEC => {
|
||||
let data = List::read_for_byte_length(len.into(), r)?;
|
||||
Ok(Self::ChangeCipherSpec { data })
|
||||
}
|
||||
Self::ALERT => {
|
||||
let alert = Alert::read(r)?;
|
||||
Ok(Self::Alert { alert })
|
||||
|
|
@ -75,7 +116,12 @@ impl TLSPlaintext {
|
|||
let handshake = Handshake::read(r)?;
|
||||
Ok(TLSPlaintext::Handshake { handshake })
|
||||
}
|
||||
Self::APPLICATION_DATA => todo!(),
|
||||
Self::APPLICATION_DATA => {
|
||||
let data = List::<u8, u16>::read_for_byte_length(len.into(), r)?;
|
||||
Ok(Self::ApplicationData {
|
||||
data: data.into_inner(),
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
return Err(crate::ErrorKind::InvalidFrame(Box::new(format!(
|
||||
"Invalid record discriminant: {discr}"
|
||||
|
|
@ -86,6 +132,16 @@ impl TLSPlaintext {
|
|||
}
|
||||
}
|
||||
|
||||
// https://datatracker.ietf.org/doc/html/rfc8446#section-5.2
|
||||
proto_struct! {
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TlsCiphertext {
|
||||
pub opaque_type: u8,
|
||||
pub legacy_record_version: u8,
|
||||
pub encrypted_record: List<u8, u16>,
|
||||
}
|
||||
}
|
||||
|
||||
pub type ProtocolVersion = u16;
|
||||
pub type Random = [u8; 32];
|
||||
|
||||
|
|
@ -220,7 +276,6 @@ proto_enum! {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
proto_enum! {
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ServerName: u8 {
|
||||
|
|
@ -385,7 +440,9 @@ pub enum ServerHelloKeyshare {
|
|||
impl ServerHelloKeyshare {
|
||||
pub fn unwrap_server_hello(&self) -> &KeyShareEntry {
|
||||
match self {
|
||||
Self::HelloRetryRequest(_) => panic!("unexpected hello retry request, expected server hello"),
|
||||
Self::HelloRetryRequest(_) => {
|
||||
panic!("unexpected hello retry request, expected server hello")
|
||||
}
|
||||
Self::ServerHello(entry) => entry,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,14 +53,14 @@ macro_rules! proto_struct {
|
|||
|
||||
|
||||
impl crate::proto::ser_de::Value for $name {
|
||||
fn write<W: Write>(&self, mut w: &mut W) -> io::Result<()> {
|
||||
fn write<W: std::io::Write>(&self, mut w: &mut W) -> std::io::Result<()> {
|
||||
$(
|
||||
crate::proto::ser_de::Value::write(&self.$field_name, &mut w)?;
|
||||
)*
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read<R: Read>(r: &mut $crate::proto::ser_de::FrameReader<R>) -> crate::Result<Self> {
|
||||
fn read<R: std::io::Read>(r: &mut $crate::proto::ser_de::FrameReader<R>) -> crate::Result<Self> {
|
||||
let ( $( $field_name ),* ) = ($( { crate::proto::ser_de::discard!($field_name); crate::proto::ser_de::Value::read(r)? } ),*);
|
||||
|
||||
Ok(Self {
|
||||
|
|
@ -248,17 +248,8 @@ impl<T: Debug, Len> Debug for List<T, Len> {
|
|||
|
||||
impl<T: Value, Len: Value + Into<usize> + TryFrom<usize> + Default> Value for List<T, Len> {
|
||||
fn read<R: Read>(r: &mut FrameReader<R>) -> crate::Result<Self> {
|
||||
eprintln!("reading a list");
|
||||
let mut remaining_byte_size = Len::read(r)?.into();
|
||||
let mut v = Vec::new();
|
||||
eprintln!("list.. remaining bytes {remaining_byte_size}");
|
||||
while remaining_byte_size > 0 {
|
||||
eprintln!("things {remaining_byte_size} {v:?}");
|
||||
let value = T::read(r)?;
|
||||
remaining_byte_size -= value.byte_size();
|
||||
v.push(value);
|
||||
}
|
||||
Ok(Self(v, PhantomData))
|
||||
let remaining_byte_size = Len::read(r)?.into();
|
||||
Self::read_for_byte_length(remaining_byte_size, r)
|
||||
}
|
||||
fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
||||
let byte_size = self.0.iter().map(Value::byte_size).sum::<usize>();
|
||||
|
|
@ -278,6 +269,22 @@ impl<T: Value, Len: Value + Into<usize> + TryFrom<usize> + Default> Value for Li
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Value, Len: Value + Into<usize> + TryFrom<usize> + Default> List<T, Len> {
|
||||
pub fn read_for_byte_length<R: Read>(mut remaining_byte_size: usize, r: &mut FrameReader<R>) -> crate::Result<Self> {
|
||||
let mut v = Vec::new();
|
||||
while remaining_byte_size > 0 {
|
||||
let value = T::read(r)?;
|
||||
remaining_byte_size -= value.byte_size();
|
||||
v.push(value);
|
||||
}
|
||||
Ok(Self(v, PhantomData))
|
||||
}
|
||||
|
||||
pub fn into_inner(self) -> Vec<T> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Value: Sized + std::fmt::Debug {
|
||||
fn write<W: Write>(&self, w: &mut W) -> io::Result<()>;
|
||||
fn read<R: Read>(r: &mut FrameReader<R>) -> crate::Result<Self>;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue