1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
//! ytls Builder traits
//----------------------------------------------------------
// Record Building
//----------------------------------------------------------
/// Non-typed Handshake Builder with raw data inputs.
/// This is implemented by the [`ytls_record::Record`] where as
/// the required inputs are through the client/server contextes.
pub trait HandshakeBuilder {
type Error;
/// Build Client Hello
fn client_hello_untyped<S: ClientHelloBuilder>(_: &S) -> Result<Self, Self::Error>
where
Self: Sized;
/// Build Server Hello
fn server_hello_untyped<S: ServerHelloBuilder>(_: &S) -> Result<Self, Self::Error>
where
Self: Sized;
/// Provide the raw encoded bytes but without header
fn as_hashing_context(&self) -> &[u8];
/// Provide the raw encoded bytes
fn as_encoded_bytes(&self) -> &[u8];
}
/// Wrapped Application data within Application context builder
pub trait WrappedApplicationBuilder {
type Error;
/// Build Application data
fn application_data(_data: &[u8]) -> Result<Self, Self::Error>
where
Self: Sized;
/// Get disjoint mut for AEAD use of 1) additional data 2) cleartext data to encrypt
fn as_disjoint_mut_for_aead(&mut self) -> Result<[&mut [u8]; 2], Self::Error>;
/// Set the AEAD authenticated tag of this wrapped record after encryption
fn set_auth_tag(&mut self, new_tag: &[u8; 16]) -> ();
/// Provide the cleartext as mutable in order for it to be encrypted into ciphertext.
fn as_ciphertext_mut(&mut self) -> &mut [u8];
/// Provides the missing handshake header for hashing purposes
/// which must be included in the transcript hash.
fn wrapped_hash_header_ref(&self) -> [u8; 5];
/// Provide the raw encoded bytes for hashing purposes which
/// includes the cleartext portition that will be encrypted
/// except the wrapped handshake header which must be hashed
/// separately through wrapped_hash_header_ref due to
/// to-be-encrypted records being "wrapped" over TLS 1.2 appdata.
fn as_hashing_context_ref(&self) -> &[u8];
/// Provide the full raw encoded bytes including placeholder
/// tag and record headers
fn as_encoded_bytes(&self) -> &[u8];
}
/// Same except non-wrapped but where we wrap the record into
/// TLS 1.2 Application Data layer, typically encrypted when
/// written to wire.
pub trait WrappedHandshakeBuilder {
type Error;
/// Build Client Handshake Finished
fn client_handshake_finished<S: ClientHandshakeFinishedBuilder>(
_: &S,
) -> Result<Self, Self::Error>
where
Self: Sized;
/// Build Server Handshake Finished
fn server_handshake_finished<S: ServerHandshakeFinishedBuilder>(
_: &S,
) -> Result<Self, Self::Error>
where
Self: Sized;
/// Build Server Certificates
fn server_certificates<S: ServerCertificatesBuilder>(_: &S) -> Result<Self, Self::Error>
where
Self: Sized;
/// Build Server Certificate Verify of which we have the private key of
fn server_certificate_verify<S: ServerCertificateVerifyBuilder>(
_: &S,
) -> Result<Self, Self::Error>
where
Self: Sized;
/// Build Encrypted Extensions
fn encrypted_extensions<S: EncryptedExtensionsBuilder>(s: &S) -> Result<Self, Self::Error>
where
Self: Sized;
/// Get disjoint mut for AEAD use of 1) additional data 2) cleartext data to encrypt
fn as_disjoint_mut_for_aead(&mut self) -> Result<[&mut [u8]; 2], Self::Error>;
/// Set the AEAD authenticated tag of this wrapped record after encryption
fn set_auth_tag(&mut self, new_tag: &[u8; 16]) -> ();
/// Provide the cleartext as mutable in order for it to be encrypted into ciphertext.
fn as_ciphertext_mut(&mut self) -> &mut [u8];
/// Provides the missing handshake header for hashing purposes
/// which must be included in the transcript hash.
fn wrapped_hash_header_ref(&self) -> [u8; 5];
/// Provide the raw encoded bytes for hashing purposes which
/// includes the cleartext portition that will be encrypted
/// except the wrapped handshake header which must be hashed
/// separately through wrapped_hash_header_ref due to
/// to-be-encrypted records being "wrapped" over TLS 1.2 appdata.
fn as_hashing_context_ref(&self) -> &[u8];
/// Provide the full raw encoded bytes including placeholder
/// tag and record headers
fn as_encoded_bytes(&self) -> &[u8];
}
/// Client handshake finished is provided through trait implementation
pub trait ClientHandshakeFinishedBuilder {
/// Provide the hash
fn hash_finished(&self) -> &[u8];
}
/// Server handshake finished is provided through trait implementation
pub trait ServerHandshakeFinishedBuilder {
/// Provide the hash
fn hash_finished(&self) -> &[u8];
}
/// Server certificate verification is provided through trait implementation
pub trait ServerCertificateVerifyBuilder {
/// Provide the signature algorithm used
fn signature_algorithm(&self) -> [u8; 2];
/// Sign the current handshake hash with the used signature
/// algorithm and the server private key used to generate the public key
/// within the server certificate.
fn sign_cert_verify(&self) -> &[u8];
}
/// Server certificates are provided through trait implementation
pub trait ServerCertificatesBuilder {
/// Provide ordered list of certificates and their internal id
fn server_certs_list(&self) -> &[u8];
/// Provide the ASN.1 DER encoded certificate by the given cert id
fn server_cert_data(&self, _id: u8) -> &[u8];
/// Provide any certificate extensions if any by the given cert id.
fn server_cert_extensions(&self, _id: u8) -> &[u8];
}
/// Encrypted Extensions are provided through trait implementation if any
pub trait EncryptedExtensionsBuilder {
// TODO
// Provide the encrypted extensions list if any
//fn encrypted_extension_list(&self) -> &[u16];
}
/// Use to generate ClientHello with the Handshake builder.
/// Provide the optional / required data to construct it.
pub trait ClientHelloBuilder {
/// This should return [3, 1] for TLS 1.0 compat
fn legacy_version(&self) -> &[u8; 2];
/// This should return [3, 3] for TLS 1.2 compat
fn legacy_client_version(&self) -> &[u8; 2];
/// Provide client random
fn client_random(&self) -> &[u8; 32];
/// Middlebox compatibility, provide random data
fn legacy_session_id(&self) -> &[u8];
/// Provide supported cipher suites list
fn cipher_suites(&self) -> &[[u8; 2]];
/// This should return [00] for no compression
fn supported_legacy_insecure_compression_methods(&self) -> &[u8];
/// Extensions used list
fn extensions_list(&self) -> &[u16];
/// Given extension relevant encoded data. See [`ytls_extensions`] to encode.
fn extension_data(&self, _id: u16) -> &[u8];
}
/// Use to generate ServerHello with the HandshakeBuilder.
/// Provide the optional / required data to construct it.
pub trait ServerHelloBuilder {
/// This should return [3, 3] for TLS 1.3
fn legacy_version(&self) -> &[u8; 2];
/// Generate 32 bytes server random for the Hello
fn server_random(&self) -> &[u8; 32];
/// In TLS 1.3 provide the ClientHello session id (if any) back
fn legacy_session_id(&self) -> &[u8];
/// Server selected the cipher suite from client's list.
fn selected_cipher_suite(&self) -> &[u8; 2];
/// Server selected compression list. This must be None for TLS 1.3.
fn selected_legacy_insecure_compression_method(&self) -> Option<u8>;
/// Extensions used list
fn extensions_list(&self) -> &[u16];
/// Given extension relevant encoded data. See [`ytls_extensions`] to encode.
fn extension_data(&self, ext: u16) -> &[u8];
}