Skip to content

Commit d17314c

Browse files
committed
extract std.crypto.tls.Client into separate namespace
1 parent 68e289f commit d17314c

File tree

4 files changed

+385
-368
lines changed

4 files changed

+385
-368
lines changed

lib/std/crypto.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ const std = @import("std.zig");
176176

177177
pub const errors = @import("crypto/errors.zig");
178178

179-
pub const Tls = @import("crypto/Tls.zig");
179+
pub const tls = @import("crypto/tls.zig");
180180

181181
test {
182182
_ = aead.aegis.Aegis128L;

lib/std/crypto/tls.zig

Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
//! Plaintext:
2+
//! * type: ContentType
3+
//! * legacy_record_version: u16 = 0x0303,
4+
//! * length: u16,
5+
//! - The length (in bytes) of the following TLSPlaintext.fragment. The
6+
//! length MUST NOT exceed 2^14 bytes.
7+
//! * fragment: opaque
8+
//! - the data being transmitted
9+
//!
10+
//! Ciphertext
11+
//! * ContentType opaque_type = application_data; /* 23 */
12+
//! * ProtocolVersion legacy_record_version = 0x0303; /* TLS v1.2 */
13+
//! * uint16 length;
14+
//! * opaque encrypted_record[TLSCiphertext.length];
15+
//!
16+
//! Handshake:
17+
//! * type: HandshakeType
18+
//! * length: u24
19+
//! * data: opaque
20+
//!
21+
//! ServerHello:
22+
//! * ProtocolVersion legacy_version = 0x0303;
23+
//! * Random random;
24+
//! * opaque legacy_session_id_echo<0..32>;
25+
//! * CipherSuite cipher_suite;
26+
//! * uint8 legacy_compression_method = 0;
27+
//! * Extension extensions<6..2^16-1>;
28+
//!
29+
//! Extension:
30+
//! * ExtensionType extension_type;
31+
//! * opaque extension_data<0..2^16-1>;
32+
33+
const std = @import("../std.zig");
34+
const Tls = @This();
35+
const net = std.net;
36+
const mem = std.mem;
37+
const crypto = std.crypto;
38+
const assert = std.debug.assert;
39+
40+
pub const Client = @import("tls/Client.zig");
41+
42+
pub const ciphertext_record_header_len = 5;
43+
pub const max_ciphertext_len = (1 << 14) + 256;
44+
pub const max_ciphertext_record_len = max_ciphertext_len + ciphertext_record_header_len;
45+
pub const hello_retry_request_sequence = [32]u8{
46+
0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
47+
0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C,
48+
};
49+
50+
pub const ProtocolVersion = enum(u16) {
51+
tls_1_2 = 0x0303,
52+
tls_1_3 = 0x0304,
53+
_,
54+
};
55+
56+
pub const ContentType = enum(u8) {
57+
invalid = 0,
58+
change_cipher_spec = 20,
59+
alert = 21,
60+
handshake = 22,
61+
application_data = 23,
62+
_,
63+
};
64+
65+
pub const HandshakeType = enum(u8) {
66+
client_hello = 1,
67+
server_hello = 2,
68+
new_session_ticket = 4,
69+
end_of_early_data = 5,
70+
encrypted_extensions = 8,
71+
certificate = 11,
72+
certificate_request = 13,
73+
certificate_verify = 15,
74+
finished = 20,
75+
key_update = 24,
76+
message_hash = 254,
77+
};
78+
79+
pub const ExtensionType = enum(u16) {
80+
/// RFC 6066
81+
server_name = 0,
82+
/// RFC 6066
83+
max_fragment_length = 1,
84+
/// RFC 6066
85+
status_request = 5,
86+
/// RFC 8422, 7919
87+
supported_groups = 10,
88+
/// RFC 8446
89+
signature_algorithms = 13,
90+
/// RFC 5764
91+
use_srtp = 14,
92+
/// RFC 6520
93+
heartbeat = 15,
94+
/// RFC 7301
95+
application_layer_protocol_negotiation = 16,
96+
/// RFC 6962
97+
signed_certificate_timestamp = 18,
98+
/// RFC 7250
99+
client_certificate_type = 19,
100+
/// RFC 7250
101+
server_certificate_type = 20,
102+
/// RFC 7685
103+
padding = 21,
104+
/// RFC 8446
105+
pre_shared_key = 41,
106+
/// RFC 8446
107+
early_data = 42,
108+
/// RFC 8446
109+
supported_versions = 43,
110+
/// RFC 8446
111+
cookie = 44,
112+
/// RFC 8446
113+
psk_key_exchange_modes = 45,
114+
/// RFC 8446
115+
certificate_authorities = 47,
116+
/// RFC 8446
117+
oid_filters = 48,
118+
/// RFC 8446
119+
post_handshake_auth = 49,
120+
/// RFC 8446
121+
signature_algorithms_cert = 50,
122+
/// RFC 8446
123+
key_share = 51,
124+
};
125+
126+
pub const AlertLevel = enum(u8) {
127+
warning = 1,
128+
fatal = 2,
129+
_,
130+
};
131+
132+
pub const AlertDescription = enum(u8) {
133+
close_notify = 0,
134+
unexpected_message = 10,
135+
bad_record_mac = 20,
136+
record_overflow = 22,
137+
handshake_failure = 40,
138+
bad_certificate = 42,
139+
unsupported_certificate = 43,
140+
certificate_revoked = 44,
141+
certificate_expired = 45,
142+
certificate_unknown = 46,
143+
illegal_parameter = 47,
144+
unknown_ca = 48,
145+
access_denied = 49,
146+
decode_error = 50,
147+
decrypt_error = 51,
148+
protocol_version = 70,
149+
insufficient_security = 71,
150+
internal_error = 80,
151+
inappropriate_fallback = 86,
152+
user_canceled = 90,
153+
missing_extension = 109,
154+
unsupported_extension = 110,
155+
unrecognized_name = 112,
156+
bad_certificate_status_response = 113,
157+
unknown_psk_identity = 115,
158+
certificate_required = 116,
159+
no_application_protocol = 120,
160+
_,
161+
};
162+
163+
pub const SignatureScheme = enum(u16) {
164+
// RSASSA-PKCS1-v1_5 algorithms
165+
rsa_pkcs1_sha256 = 0x0401,
166+
rsa_pkcs1_sha384 = 0x0501,
167+
rsa_pkcs1_sha512 = 0x0601,
168+
169+
// ECDSA algorithms
170+
ecdsa_secp256r1_sha256 = 0x0403,
171+
ecdsa_secp384r1_sha384 = 0x0503,
172+
ecdsa_secp521r1_sha512 = 0x0603,
173+
174+
// RSASSA-PSS algorithms with public key OID rsaEncryption
175+
rsa_pss_rsae_sha256 = 0x0804,
176+
rsa_pss_rsae_sha384 = 0x0805,
177+
rsa_pss_rsae_sha512 = 0x0806,
178+
179+
// EdDSA algorithms
180+
ed25519 = 0x0807,
181+
ed448 = 0x0808,
182+
183+
// RSASSA-PSS algorithms with public key OID RSASSA-PSS
184+
rsa_pss_pss_sha256 = 0x0809,
185+
rsa_pss_pss_sha384 = 0x080a,
186+
rsa_pss_pss_sha512 = 0x080b,
187+
188+
// Legacy algorithms
189+
rsa_pkcs1_sha1 = 0x0201,
190+
ecdsa_sha1 = 0x0203,
191+
192+
_,
193+
};
194+
195+
pub const NamedGroup = enum(u16) {
196+
// Elliptic Curve Groups (ECDHE)
197+
secp256r1 = 0x0017,
198+
secp384r1 = 0x0018,
199+
secp521r1 = 0x0019,
200+
x25519 = 0x001D,
201+
x448 = 0x001E,
202+
203+
// Finite Field Groups (DHE)
204+
ffdhe2048 = 0x0100,
205+
ffdhe3072 = 0x0101,
206+
ffdhe4096 = 0x0102,
207+
ffdhe6144 = 0x0103,
208+
ffdhe8192 = 0x0104,
209+
210+
_,
211+
};
212+
213+
pub const CipherSuite = enum(u16) {
214+
TLS_AES_128_GCM_SHA256 = 0x1301,
215+
TLS_AES_256_GCM_SHA384 = 0x1302,
216+
TLS_CHACHA20_POLY1305_SHA256 = 0x1303,
217+
TLS_AES_128_CCM_SHA256 = 0x1304,
218+
TLS_AES_128_CCM_8_SHA256 = 0x1305,
219+
};
220+
221+
pub const CipherParams = union(CipherSuite) {
222+
TLS_AES_128_GCM_SHA256: struct {
223+
pub const AEAD = crypto.aead.aes_gcm.Aes128Gcm;
224+
pub const Hash = crypto.hash.sha2.Sha256;
225+
pub const Hmac = crypto.auth.hmac.Hmac(Hash);
226+
pub const Hkdf = crypto.kdf.hkdf.Hkdf(Hmac);
227+
228+
handshake_secret: [Hkdf.key_len]u8,
229+
master_secret: [Hkdf.key_len]u8,
230+
client_handshake_key: [AEAD.key_length]u8,
231+
server_handshake_key: [AEAD.key_length]u8,
232+
client_finished_key: [Hmac.key_length]u8,
233+
server_finished_key: [Hmac.key_length]u8,
234+
client_handshake_iv: [AEAD.nonce_length]u8,
235+
server_handshake_iv: [AEAD.nonce_length]u8,
236+
transcript_hash: Hash,
237+
},
238+
TLS_AES_256_GCM_SHA384: struct {
239+
pub const AEAD = crypto.aead.aes_gcm.Aes256Gcm;
240+
pub const Hash = crypto.hash.sha2.Sha384;
241+
pub const Hmac = crypto.auth.hmac.Hmac(Hash);
242+
pub const Hkdf = crypto.kdf.hkdf.Hkdf(Hmac);
243+
244+
handshake_secret: [Hkdf.key_len]u8,
245+
master_secret: [Hkdf.key_len]u8,
246+
client_handshake_key: [AEAD.key_length]u8,
247+
server_handshake_key: [AEAD.key_length]u8,
248+
client_finished_key: [Hmac.key_length]u8,
249+
server_finished_key: [Hmac.key_length]u8,
250+
client_handshake_iv: [AEAD.nonce_length]u8,
251+
server_handshake_iv: [AEAD.nonce_length]u8,
252+
transcript_hash: Hash,
253+
},
254+
TLS_CHACHA20_POLY1305_SHA256: void,
255+
TLS_AES_128_CCM_SHA256: void,
256+
TLS_AES_128_CCM_8_SHA256: void,
257+
};
258+
259+
/// Encryption parameters for application traffic.
260+
pub const ApplicationCipher = union(CipherSuite) {
261+
TLS_AES_128_GCM_SHA256: struct {
262+
pub const AEAD = crypto.aead.aes_gcm.Aes128Gcm;
263+
pub const Hash = crypto.hash.sha2.Sha256;
264+
pub const Hmac = crypto.auth.hmac.Hmac(Hash);
265+
pub const Hkdf = crypto.kdf.hkdf.Hkdf(Hmac);
266+
267+
client_key: [AEAD.key_length]u8,
268+
server_key: [AEAD.key_length]u8,
269+
client_iv: [AEAD.nonce_length]u8,
270+
server_iv: [AEAD.nonce_length]u8,
271+
},
272+
TLS_AES_256_GCM_SHA384: struct {
273+
pub const AEAD = crypto.aead.aes_gcm.Aes256Gcm;
274+
pub const Hash = crypto.hash.sha2.Sha384;
275+
pub const Hmac = crypto.auth.hmac.Hmac(Hash);
276+
pub const Hkdf = crypto.kdf.hkdf.Hkdf(Hmac);
277+
278+
client_key: [AEAD.key_length]u8,
279+
server_key: [AEAD.key_length]u8,
280+
client_iv: [AEAD.nonce_length]u8,
281+
server_iv: [AEAD.nonce_length]u8,
282+
},
283+
TLS_CHACHA20_POLY1305_SHA256: void,
284+
TLS_AES_128_CCM_SHA256: void,
285+
TLS_AES_128_CCM_8_SHA256: void,
286+
};
287+
288+
pub fn hkdfExpandLabel(
289+
comptime Hkdf: type,
290+
key: [Hkdf.key_len]u8,
291+
label: []const u8,
292+
context: []const u8,
293+
comptime len: usize,
294+
) [len]u8 {
295+
const max_label_len = 255;
296+
const max_context_len = 255;
297+
const tls13 = "tls13 ";
298+
var buf: [2 + 1 + tls13.len + max_label_len + 1 + max_context_len]u8 = undefined;
299+
mem.writeIntBig(u16, buf[0..2], len);
300+
buf[2] = @intCast(u8, tls13.len + label.len);
301+
buf[3..][0..tls13.len].* = tls13.*;
302+
var i: usize = 3 + tls13.len;
303+
mem.copy(u8, buf[i..], label);
304+
i += label.len;
305+
buf[i] = @intCast(u8, context.len);
306+
i += 1;
307+
mem.copy(u8, buf[i..], context);
308+
i += context.len;
309+
310+
var result: [len]u8 = undefined;
311+
Hkdf.expand(&result, buf[0..i], key);
312+
return result;
313+
}
314+
315+
pub fn emptyHash(comptime Hash: type) [Hash.digest_length]u8 {
316+
var result: [Hash.digest_length]u8 = undefined;
317+
Hash.hash(&.{}, &result, .{});
318+
return result;
319+
}
320+
321+
pub fn hmac(comptime Hmac: type, message: []const u8, key: [Hmac.key_length]u8) [Hmac.mac_length]u8 {
322+
var result: [Hmac.mac_length]u8 = undefined;
323+
Hmac.create(&result, message, &key);
324+
return result;
325+
}

0 commit comments

Comments
 (0)