From 1a1705a0fd50729ecc0a870925ff40e08ed3109e Mon Sep 17 00:00:00 2001 From: Lasse Letager Hansen Date: Tue, 5 Nov 2024 15:02:02 +0100 Subject: [PATCH 01/33] move key scheduling to seperate file --- src/lib.rs | 1 + src/tls13handshake.rs | 164 +------------------------------- src/tls13keyscheduler.rs | 198 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+), 163 deletions(-) create mode 100644 src/tls13keyscheduler.rs diff --git a/src/lib.rs b/src/lib.rs index 100ae668..c2fcaed0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,6 +30,7 @@ mod tls13formats; mod tls13handshake; mod tls13record; +mod tls13keyscheduler; pub mod server; pub mod tls13api; diff --git a/src/tls13handshake.rs b/src/tls13handshake.rs index 63067db1..cd1c9d18 100644 --- a/src/tls13handshake.rs +++ b/src/tls13handshake.rs @@ -11,15 +11,11 @@ use crate::{ tls13formats::{handshake_data::HandshakeData, *}, tls13record::*, tls13utils::*, + tls13keyscheduler::*, }; /* TLS 1.3 Key Schedule: See RFC 8446 Section 7 */ -/// Get the hash of an empty byte slice. -fn hash_empty(algorithm: &HashAlgorithm) -> Result { - algorithm.hash(&Bytes::new()) -} - /// HKDF expand with a `label`. fn hkdf_expand_label( hash_algorithm: &HashAlgorithm, @@ -40,164 +36,6 @@ fn hkdf_expand_label( } } -pub fn derive_secret( - hash_algorithm: &HashAlgorithm, - key: &Key, - label: Bytes, - transcript_hash: &Digest, -) -> Result { - hkdf_expand_label( - hash_algorithm, - key, - label, - transcript_hash, - hash_algorithm.hash_len(), - ) -} - -pub fn derive_binder_key(ha: &HashAlgorithm, k: &Key) -> Result { - let early_secret = hkdf_extract(ha, k, &zero_key(ha))?; - derive_secret( - ha, - &early_secret, - bytes(&LABEL_RES_BINDER), - &hash_empty(ha)?, - ) -} - -/// Derive an AEAD key and iv. -pub(crate) fn derive_aead_key_iv( - hash_algorithm: &HashAlgorithm, - aead_algorithm: &AeadAlgorithm, - key: &Key, -) -> Result { - let sender_write_key = hkdf_expand_label( - hash_algorithm, - key, - bytes(&LABEL_KEY), - &Bytes::new(), - aead_algorithm.key_len(), - )?; - let sender_write_iv = hkdf_expand_label( - hash_algorithm, - key, - bytes(&LABEL_IV), - &Bytes::new(), - aead_algorithm.iv_len(), - )?; - Ok(AeadKeyIV::new( - AeadKey::new(sender_write_key, *aead_algorithm), - sender_write_iv, - )) -} - -/// Derive 0-RTT AEAD keys. -pub(crate) fn derive_0rtt_keys( - hash_algorithm: &HashAlgorithm, - aead_algoorithm: &AeadAlgorithm, - key: &Key, - tx: &Digest, -) -> Result<(AeadKeyIV, Key), TLSError> { - let early_secret = hkdf_extract(hash_algorithm, key, &zero_key(hash_algorithm))?; - let client_early_traffic_secret = - derive_secret(hash_algorithm, &early_secret, bytes(&LABEL_C_E_TRAFFIC), tx)?; - let early_exporter_master_secret = derive_secret( - hash_algorithm, - &early_secret, - bytes(&LABEL_E_EXP_MASTER), - tx, - )?; - let sender_write_key_iv = derive_aead_key_iv( - hash_algorithm, - aead_algoorithm, - &client_early_traffic_secret, - )?; - Ok((sender_write_key_iv, early_exporter_master_secret)) -} - -pub fn derive_finished_key(ha: &HashAlgorithm, k: &Key) -> Result { - hkdf_expand_label( - ha, - k, - bytes(&LABEL_FINISHED), - &Bytes::new(), - ha.hmac_tag_len(), - ) -} - -/// Derive the handshake keys and master secret. -pub(crate) fn derive_hk_ms( - ha: &HashAlgorithm, - ae: &AeadAlgorithm, - shared_secret: &Key, - psko: &Option, - transcript_hash: &Digest, -) -> Result<(AeadKeyIV, AeadKeyIV, MacKey, MacKey, Key), TLSError> { - let psk = if let Some(k) = psko { - k.clone() - } else { - zero_key(ha) - }; - let early_secret = hkdf_extract(ha, &psk, &zero_key(ha))?; - let digest_emp = hash_empty(ha)?; - let derived_secret = derive_secret(ha, &early_secret, bytes(&LABEL_DERIVED), &digest_emp)?; - let handshake_secret = hkdf_extract(ha, shared_secret, &derived_secret)?; - let client_handshake_traffic_secret = derive_secret( - ha, - &handshake_secret, - bytes(&LABEL_C_HS_TRAFFIC), - transcript_hash, - )?; - let server_handshake_traffic_secret = derive_secret( - ha, - &handshake_secret, - bytes(&LABEL_S_HS_TRAFFIC), - transcript_hash, - )?; - let client_finished_key = derive_finished_key(ha, &client_handshake_traffic_secret)?; - let server_finished_key = derive_finished_key(ha, &server_handshake_traffic_secret)?; - let client_write_key_iv = derive_aead_key_iv(ha, ae, &client_handshake_traffic_secret)?; - let server_write_key_iv = derive_aead_key_iv(ha, ae, &server_handshake_traffic_secret)?; - let master_secret_ = derive_secret(ha, &handshake_secret, bytes(&LABEL_DERIVED), &digest_emp)?; - let master_secret = hkdf_extract(ha, &zero_key(ha), &master_secret_)?; - Ok(( - client_write_key_iv, - server_write_key_iv, - client_finished_key, - server_finished_key, - master_secret, - )) -} - -/// Derive the application keys and master secret. -pub(crate) fn derive_app_keys( - ha: &HashAlgorithm, - ae: &AeadAlgorithm, - master_secret: &Key, - tx: &Digest, -) -> Result<(AeadKeyIV, AeadKeyIV, Key), TLSError> { - let client_application_traffic_secret_0 = - derive_secret(ha, master_secret, bytes(&LABEL_C_AP_TRAFFIC), tx)?; - let server_application_traffic_secret_0 = - derive_secret(ha, master_secret, bytes(&LABEL_S_AP_TRAFFIC), tx)?; - let client_write_key_iv = derive_aead_key_iv(ha, ae, &client_application_traffic_secret_0)?; - let server_write_key_iv = derive_aead_key_iv(ha, ae, &server_application_traffic_secret_0)?; - let exporter_master_secret = derive_secret(ha, master_secret, bytes(&LABEL_EXP_MASTER), tx)?; - Ok(( - client_write_key_iv, - server_write_key_iv, - exporter_master_secret, - )) -} - -pub(crate) fn derive_rms( - ha: &HashAlgorithm, - master_secret: &Key, - tx: &Digest, -) -> Result { - derive_secret(ha, master_secret, bytes(&LABEL_RES_MASTER), tx) -} - /* Handshake State Machine */ /* We implement a simple linear state machine: PostClientHello -> PostServerHello -> PostCertificateVerify -> diff --git a/src/tls13keyscheduler.rs b/src/tls13keyscheduler.rs new file mode 100644 index 00000000..95702b12 --- /dev/null +++ b/src/tls13keyscheduler.rs @@ -0,0 +1,198 @@ +use rand::{CryptoRng, RngCore}; + +use crate::{ + tls13cert::{cert_public_key, rsa_public_key, verification_key_from_cert}, + tls13crypto::{ + hkdf_expand, hkdf_extract, hmac_tag, hmac_verify, kem_decap, kem_encap, kem_keygen, sign, + sign_rsa, verify, zero_key, AeadAlgorithm, AeadKey, AeadKeyIV, Algorithms, Digest, + HashAlgorithm, KemSk, Key, MacKey, Psk, Random, SignatureScheme, + }, + tls13formats::{handshake_data::HandshakeData, *}, + tls13record::*, + tls13utils::*, +}; + +/// Get the hash of an empty byte slice. +fn hash_empty(algorithm: &HashAlgorithm) -> Result { + algorithm.hash(&Bytes::new()) +} + +/* TLS 1.3 Key Schedule: See RFC 8446 Section 7 */ + +/// HKDF expand with a `label`. +fn hkdf_expand_label( + hash_algorithm: &HashAlgorithm, + key: &Key, + label: Bytes, + context: &Bytes, + len: usize, +) -> Result { + if len >= 65536 { + Err(PAYLOAD_TOO_LONG) + } else { + let lenb = u16_as_be_bytes(U16(len as u16)); + let tls13_label = Bytes::from_slice(&LABEL_TLS13).concat(label); + let info = encode_length_u8(tls13_label.as_raw())? + .concat(encode_length_u8(context.as_raw())?) + .prefix(&lenb); + hkdf_expand(hash_algorithm, key, &info, len) + } +} + +pub fn derive_secret( + hash_algorithm: &HashAlgorithm, + key: &Key, + label: Bytes, + transcript_hash: &Digest, +) -> Result { + hkdf_expand_label( + hash_algorithm, + key, + label, + transcript_hash, + hash_algorithm.hash_len(), + ) +} + +pub fn derive_binder_key(ha: &HashAlgorithm, k: &Key) -> Result { + let early_secret = hkdf_extract(ha, k, &zero_key(ha))?; + derive_secret( + ha, + &early_secret, + bytes(&LABEL_RES_BINDER), + &hash_empty(ha)?, + ) +} + +/// Derive an AEAD key and iv. +pub(crate) fn derive_aead_key_iv( + hash_algorithm: &HashAlgorithm, + aead_algorithm: &AeadAlgorithm, + key: &Key, +) -> Result { + let sender_write_key = hkdf_expand_label( + hash_algorithm, + key, + bytes(&LABEL_KEY), + &Bytes::new(), + aead_algorithm.key_len(), + )?; + let sender_write_iv = hkdf_expand_label( + hash_algorithm, + key, + bytes(&LABEL_IV), + &Bytes::new(), + aead_algorithm.iv_len(), + )?; + Ok(AeadKeyIV::new( + AeadKey::new(sender_write_key, *aead_algorithm), + sender_write_iv, + )) +} + +/// Derive 0-RTT AEAD keys. +pub(crate) fn derive_0rtt_keys( + hash_algorithm: &HashAlgorithm, + aead_algoorithm: &AeadAlgorithm, + key: &Key, + tx: &Digest, +) -> Result<(AeadKeyIV, Key), TLSError> { + let early_secret = hkdf_extract(hash_algorithm, key, &zero_key(hash_algorithm))?; + let client_early_traffic_secret = + derive_secret(hash_algorithm, &early_secret, bytes(&LABEL_C_E_TRAFFIC), tx)?; + let early_exporter_master_secret = derive_secret( + hash_algorithm, + &early_secret, + bytes(&LABEL_E_EXP_MASTER), + tx, + )?; + let sender_write_key_iv = derive_aead_key_iv( + hash_algorithm, + aead_algoorithm, + &client_early_traffic_secret, + )?; + Ok((sender_write_key_iv, early_exporter_master_secret)) +} + +pub fn derive_finished_key(ha: &HashAlgorithm, k: &Key) -> Result { + hkdf_expand_label( + ha, + k, + bytes(&LABEL_FINISHED), + &Bytes::new(), + ha.hmac_tag_len(), + ) +} + +/// Derive the handshake keys and master secret. +pub(crate) fn derive_hk_ms( + ha: &HashAlgorithm, + ae: &AeadAlgorithm, + shared_secret: &Key, + psko: &Option, + transcript_hash: &Digest, +) -> Result<(AeadKeyIV, AeadKeyIV, MacKey, MacKey, Key), TLSError> { + let psk = if let Some(k) = psko { + k.clone() + } else { + zero_key(ha) + }; + let early_secret = hkdf_extract(ha, &psk, &zero_key(ha))?; + let digest_emp = hash_empty(ha)?; + let derived_secret = derive_secret(ha, &early_secret, bytes(&LABEL_DERIVED), &digest_emp)?; + let handshake_secret = hkdf_extract(ha, shared_secret, &derived_secret)?; + let client_handshake_traffic_secret = derive_secret( + ha, + &handshake_secret, + bytes(&LABEL_C_HS_TRAFFIC), + transcript_hash, + )?; + let server_handshake_traffic_secret = derive_secret( + ha, + &handshake_secret, + bytes(&LABEL_S_HS_TRAFFIC), + transcript_hash, + )?; + let client_finished_key = derive_finished_key(ha, &client_handshake_traffic_secret)?; + let server_finished_key = derive_finished_key(ha, &server_handshake_traffic_secret)?; + let client_write_key_iv = derive_aead_key_iv(ha, ae, &client_handshake_traffic_secret)?; + let server_write_key_iv = derive_aead_key_iv(ha, ae, &server_handshake_traffic_secret)?; + let master_secret_ = derive_secret(ha, &handshake_secret, bytes(&LABEL_DERIVED), &digest_emp)?; + let master_secret = hkdf_extract(ha, &zero_key(ha), &master_secret_)?; + Ok(( + client_write_key_iv, + server_write_key_iv, + client_finished_key, + server_finished_key, + master_secret, + )) +} + +/// Derive the application keys and master secret. +pub(crate) fn derive_app_keys( + ha: &HashAlgorithm, + ae: &AeadAlgorithm, + master_secret: &Key, + tx: &Digest, +) -> Result<(AeadKeyIV, AeadKeyIV, Key), TLSError> { + let client_application_traffic_secret_0 = + derive_secret(ha, master_secret, bytes(&LABEL_C_AP_TRAFFIC), tx)?; + let server_application_traffic_secret_0 = + derive_secret(ha, master_secret, bytes(&LABEL_S_AP_TRAFFIC), tx)?; + let client_write_key_iv = derive_aead_key_iv(ha, ae, &client_application_traffic_secret_0)?; + let server_write_key_iv = derive_aead_key_iv(ha, ae, &server_application_traffic_secret_0)?; + let exporter_master_secret = derive_secret(ha, master_secret, bytes(&LABEL_EXP_MASTER), tx)?; + Ok(( + client_write_key_iv, + server_write_key_iv, + exporter_master_secret, + )) +} + +pub(crate) fn derive_rms( + ha: &HashAlgorithm, + master_secret: &Key, + tx: &Digest, +) -> Result { + derive_secret(ha, master_secret, bytes(&LABEL_RES_MASTER), tx) +} From e296d9a289c868b39aaac4a24d1feba41b7737b6 Mon Sep 17 00:00:00 2001 From: Lasse Letager Hansen Date: Wed, 6 Nov 2024 18:42:09 +0100 Subject: [PATCH 02/33] Use xpd instead of derive_server --- src/test_tls13traces_internal.rs | 1 + src/tls13handshake.rs | 29 +-- src/tls13keyscheduler.rs | 328 +++++++++++++++++++++++++++---- 3 files changed, 294 insertions(+), 64 deletions(-) diff --git a/src/test_tls13traces_internal.rs b/src/test_tls13traces_internal.rs index 7056f8d1..bfb9fa65 100644 --- a/src/test_tls13traces_internal.rs +++ b/src/test_tls13traces_internal.rs @@ -1,5 +1,6 @@ #![allow(dead_code)] +use crate::tls13keyscheduler::*; use crate::tls13handshake::*; use crate::tls13utils::*; use crate::{ diff --git a/src/tls13handshake.rs b/src/tls13handshake.rs index cd1c9d18..3157f3c8 100644 --- a/src/tls13handshake.rs +++ b/src/tls13handshake.rs @@ -4,38 +4,15 @@ use crate::{ server::{lookup_db, ServerDB, ServerInfo}, tls13cert::{cert_public_key, rsa_public_key, verification_key_from_cert}, tls13crypto::{ - hkdf_expand, hkdf_extract, hmac_tag, hmac_verify, kem_decap, kem_encap, kem_keygen, sign, - sign_rsa, verify, zero_key, AeadAlgorithm, AeadKey, AeadKeyIV, Algorithms, Digest, - HashAlgorithm, KemSk, Key, MacKey, Psk, Random, SignatureScheme, + hmac_tag, hmac_verify, kem_decap, kem_encap, kem_keygen, sign, sign_rsa, verify, + Algorithms, Digest, KemSk, Key, MacKey, Psk, Random, SignatureScheme, }, tls13formats::{handshake_data::HandshakeData, *}, + tls13keyscheduler::*, tls13record::*, tls13utils::*, - tls13keyscheduler::*, }; -/* TLS 1.3 Key Schedule: See RFC 8446 Section 7 */ - -/// HKDF expand with a `label`. -fn hkdf_expand_label( - hash_algorithm: &HashAlgorithm, - key: &Key, - label: Bytes, - context: &Bytes, - len: usize, -) -> Result { - if len >= 65536 { - Err(PAYLOAD_TOO_LONG) - } else { - let lenb = u16_as_be_bytes(U16(len as u16)); - let tls13_label = Bytes::from_slice(&LABEL_TLS13).concat(label); - let info = encode_length_u8(tls13_label.as_raw())? - .concat(encode_length_u8(context.as_raw())?) - .prefix(&lenb); - hkdf_expand(hash_algorithm, key, &info, len) - } -} - /* Handshake State Machine */ /* We implement a simple linear state machine: PostClientHello -> PostServerHello -> PostCertificateVerify -> diff --git a/src/tls13keyscheduler.rs b/src/tls13keyscheduler.rs index 95702b12..e694b8b6 100644 --- a/src/tls13keyscheduler.rs +++ b/src/tls13keyscheduler.rs @@ -1,14 +1,9 @@ -use rand::{CryptoRng, RngCore}; - use crate::{ - tls13cert::{cert_public_key, rsa_public_key, verification_key_from_cert}, tls13crypto::{ - hkdf_expand, hkdf_extract, hmac_tag, hmac_verify, kem_decap, kem_encap, kem_keygen, sign, - sign_rsa, verify, zero_key, AeadAlgorithm, AeadKey, AeadKeyIV, Algorithms, Digest, - HashAlgorithm, KemSk, Key, MacKey, Psk, Random, SignatureScheme, + hkdf_expand, hkdf_extract, hmac_tag, zero_key, AeadAlgorithm, AeadKey, AeadKeyIV, + Algorithms, Digest, HashAlgorithm, Key, MacKey, Psk, }, - tls13formats::{handshake_data::HandshakeData, *}, - tls13record::*, + tls13formats::*, tls13utils::*, }; @@ -39,29 +34,15 @@ fn hkdf_expand_label( } } -pub fn derive_secret( - hash_algorithm: &HashAlgorithm, - key: &Key, - label: Bytes, - transcript_hash: &Digest, -) -> Result { - hkdf_expand_label( - hash_algorithm, - key, - label, - transcript_hash, - hash_algorithm.hash_len(), - ) -} - pub fn derive_binder_key(ha: &HashAlgorithm, k: &Key) -> Result { let early_secret = hkdf_extract(ha, k, &zero_key(ha))?; - derive_secret( + Ok(xpd( + ES, ha, &early_secret, bytes(&LABEL_RES_BINDER), &hash_empty(ha)?, - ) + )?.1) } /// Derive an AEAD key and iv. @@ -98,9 +79,10 @@ pub(crate) fn derive_0rtt_keys( tx: &Digest, ) -> Result<(AeadKeyIV, Key), TLSError> { let early_secret = hkdf_extract(hash_algorithm, key, &zero_key(hash_algorithm))?; - let client_early_traffic_secret = - derive_secret(hash_algorithm, &early_secret, bytes(&LABEL_C_E_TRAFFIC), tx)?; - let early_exporter_master_secret = derive_secret( + let (_, client_early_traffic_secret) = + xpd(ES, hash_algorithm, &early_secret, bytes(&LABEL_C_E_TRAFFIC), tx)?; + let (_, early_exporter_master_secret) = xpd( + ES, hash_algorithm, &early_secret, bytes(&LABEL_E_EXP_MASTER), @@ -139,15 +121,17 @@ pub(crate) fn derive_hk_ms( }; let early_secret = hkdf_extract(ha, &psk, &zero_key(ha))?; let digest_emp = hash_empty(ha)?; - let derived_secret = derive_secret(ha, &early_secret, bytes(&LABEL_DERIVED), &digest_emp)?; + let (_, derived_secret) = xpd(ES, ha, &early_secret, bytes(&LABEL_DERIVED), &digest_emp)?; let handshake_secret = hkdf_extract(ha, shared_secret, &derived_secret)?; - let client_handshake_traffic_secret = derive_secret( + let (_, client_handshake_traffic_secret) = xpd( + HS, ha, &handshake_secret, bytes(&LABEL_C_HS_TRAFFIC), transcript_hash, )?; - let server_handshake_traffic_secret = derive_secret( + let (_, server_handshake_traffic_secret) = xpd( + HS, ha, &handshake_secret, bytes(&LABEL_S_HS_TRAFFIC), @@ -157,7 +141,13 @@ pub(crate) fn derive_hk_ms( let server_finished_key = derive_finished_key(ha, &server_handshake_traffic_secret)?; let client_write_key_iv = derive_aead_key_iv(ha, ae, &client_handshake_traffic_secret)?; let server_write_key_iv = derive_aead_key_iv(ha, ae, &server_handshake_traffic_secret)?; - let master_secret_ = derive_secret(ha, &handshake_secret, bytes(&LABEL_DERIVED), &digest_emp)?; + let (_, master_secret_) = xpd( + HS, + ha, + &handshake_secret, + bytes(&LABEL_DERIVED), + &digest_emp, + )?; let master_secret = hkdf_extract(ha, &zero_key(ha), &master_secret_)?; Ok(( client_write_key_iv, @@ -175,13 +165,13 @@ pub(crate) fn derive_app_keys( master_secret: &Key, tx: &Digest, ) -> Result<(AeadKeyIV, AeadKeyIV, Key), TLSError> { - let client_application_traffic_secret_0 = - derive_secret(ha, master_secret, bytes(&LABEL_C_AP_TRAFFIC), tx)?; - let server_application_traffic_secret_0 = - derive_secret(ha, master_secret, bytes(&LABEL_S_AP_TRAFFIC), tx)?; + let (_, client_application_traffic_secret_0) = + xpd(AS, ha, master_secret, bytes(&LABEL_C_AP_TRAFFIC), tx)?; + let (_, server_application_traffic_secret_0) = + xpd(AS, ha, master_secret, bytes(&LABEL_S_AP_TRAFFIC), tx)?; let client_write_key_iv = derive_aead_key_iv(ha, ae, &client_application_traffic_secret_0)?; let server_write_key_iv = derive_aead_key_iv(ha, ae, &server_application_traffic_secret_0)?; - let exporter_master_secret = derive_secret(ha, master_secret, bytes(&LABEL_EXP_MASTER), tx)?; + let (_, exporter_master_secret) = xpd(AS, ha, master_secret, bytes(&LABEL_EXP_MASTER), tx)?; Ok(( client_write_key_iv, server_write_key_iv, @@ -194,5 +184,267 @@ pub(crate) fn derive_rms( master_secret: &Key, tx: &Digest, ) -> Result { - derive_secret(ha, master_secret, bytes(&LABEL_RES_MASTER), tx) + let (_, key) = xpd(AS, ha, master_secret, bytes(&LABEL_RES_MASTER), tx)?; + Ok(key) +} + +///////////////////////////////////////////////// + +trait KeySchedule { + fn labels(a: N, b: bool) -> [u8; 12]; // Bit string of size 96 (8*12) + fn prnt_n(a: N) -> (Option, Option); } + +struct TLSkeyscheduler {} + +#[derive(Copy, Clone)] +enum TLSnames { + ES, + EEM, + CET, + Bind, + Binder, + HS, + SHT, + CHT, + HSalt, + AS, + RM, + CAT, + SAT, + EAM, + PSK, + + ZeroSalt, // 0 + ESalt, + DH, + ZeroIKM, // 0^len(alg) +} +use TLSnames::*; + +impl KeySchedule for TLSkeyscheduler { + fn prnt_n(a: TLSnames) -> (Option, Option) { + match a { + ES => (Some(ZeroSalt), Some(PSK)), + EEM | CET | Bind => (Some(ES), None), + Binder => (Some(Bind), None), + HS => (Some(ESalt), Some(DH)), + SHT | CHT | HSalt => (Some(HS), None), + AS => (Some(HSalt), Some(ZeroIKM)), + RM | CAT | SAT | EAM => (Some(AS), None), + PSK => (Some(RM), None), + ZeroSalt | DH | ZeroIKM => (None, None), + ESalt => (todo!(), None), + } + } + + fn labels(a: TLSnames, b: bool) -> [u8; 12] { + match a { + // EEM => LABEL_E_EXP_MASTER, + // CET => LABEL_C_E_TRAFFIC, + // Binder => LABEL_RES_BINDER, + SHT => LABEL_S_HS_TRAFFIC, + CHT => LABEL_C_HS_TRAFFIC, + CAT => LABEL_C_AP_TRAFFIC, + SAT => LABEL_S_AP_TRAFFIC, + _ => [0; 96 / 8], + } + } +} + +enum Label { + RES_BINDER__, + EXT_BINDER__, + C_E_TRAFFIC_, + E_EXP_MASTER, + EXP_MASTER__, + RES_MASTER__, + C_HS_TRAFFIC, + S_HS_TRAFFIC, + DERIVED_____, + C_AP_TRAFFIC, + S_AP_TRAFFIC, + RESUMPTION__, +} +use Label::*; + +fn convert_label(label: Bytes) -> Option