-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
extract std.crypto.tls.Client into separate namespace
- Loading branch information
Showing
4 changed files
with
385 additions
and
368 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,325 @@ | ||
//! Plaintext: | ||
//! * type: ContentType | ||
//! * legacy_record_version: u16 = 0x0303, | ||
//! * length: u16, | ||
//! - The length (in bytes) of the following TLSPlaintext.fragment. The | ||
//! length MUST NOT exceed 2^14 bytes. | ||
//! * fragment: opaque | ||
//! - the data being transmitted | ||
//! | ||
//! Ciphertext | ||
//! * ContentType opaque_type = application_data; /* 23 */ | ||
//! * ProtocolVersion legacy_record_version = 0x0303; /* TLS v1.2 */ | ||
//! * uint16 length; | ||
//! * opaque encrypted_record[TLSCiphertext.length]; | ||
//! | ||
//! Handshake: | ||
//! * type: HandshakeType | ||
//! * length: u24 | ||
//! * data: opaque | ||
//! | ||
//! ServerHello: | ||
//! * ProtocolVersion legacy_version = 0x0303; | ||
//! * Random random; | ||
//! * opaque legacy_session_id_echo<0..32>; | ||
//! * CipherSuite cipher_suite; | ||
//! * uint8 legacy_compression_method = 0; | ||
//! * Extension extensions<6..2^16-1>; | ||
//! | ||
//! Extension: | ||
//! * ExtensionType extension_type; | ||
//! * opaque extension_data<0..2^16-1>; | ||
|
||
const std = @import("../std.zig"); | ||
const Tls = @This(); | ||
const net = std.net; | ||
const mem = std.mem; | ||
const crypto = std.crypto; | ||
const assert = std.debug.assert; | ||
|
||
pub const Client = @import("tls/Client.zig"); | ||
|
||
pub const ciphertext_record_header_len = 5; | ||
pub const max_ciphertext_len = (1 << 14) + 256; | ||
pub const max_ciphertext_record_len = max_ciphertext_len + ciphertext_record_header_len; | ||
pub const hello_retry_request_sequence = [32]u8{ | ||
0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, | ||
0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C, | ||
}; | ||
|
||
pub const ProtocolVersion = enum(u16) { | ||
tls_1_2 = 0x0303, | ||
tls_1_3 = 0x0304, | ||
_, | ||
}; | ||
|
||
pub const ContentType = enum(u8) { | ||
invalid = 0, | ||
change_cipher_spec = 20, | ||
alert = 21, | ||
handshake = 22, | ||
application_data = 23, | ||
_, | ||
}; | ||
|
||
pub const HandshakeType = enum(u8) { | ||
client_hello = 1, | ||
server_hello = 2, | ||
new_session_ticket = 4, | ||
end_of_early_data = 5, | ||
encrypted_extensions = 8, | ||
certificate = 11, | ||
certificate_request = 13, | ||
certificate_verify = 15, | ||
finished = 20, | ||
key_update = 24, | ||
message_hash = 254, | ||
}; | ||
|
||
pub const ExtensionType = enum(u16) { | ||
/// RFC 6066 | ||
server_name = 0, | ||
/// RFC 6066 | ||
max_fragment_length = 1, | ||
/// RFC 6066 | ||
status_request = 5, | ||
/// RFC 8422, 7919 | ||
supported_groups = 10, | ||
/// RFC 8446 | ||
signature_algorithms = 13, | ||
/// RFC 5764 | ||
use_srtp = 14, | ||
/// RFC 6520 | ||
heartbeat = 15, | ||
/// RFC 7301 | ||
application_layer_protocol_negotiation = 16, | ||
/// RFC 6962 | ||
signed_certificate_timestamp = 18, | ||
/// RFC 7250 | ||
client_certificate_type = 19, | ||
/// RFC 7250 | ||
server_certificate_type = 20, | ||
/// RFC 7685 | ||
padding = 21, | ||
/// RFC 8446 | ||
pre_shared_key = 41, | ||
/// RFC 8446 | ||
early_data = 42, | ||
/// RFC 8446 | ||
supported_versions = 43, | ||
/// RFC 8446 | ||
cookie = 44, | ||
/// RFC 8446 | ||
psk_key_exchange_modes = 45, | ||
/// RFC 8446 | ||
certificate_authorities = 47, | ||
/// RFC 8446 | ||
oid_filters = 48, | ||
/// RFC 8446 | ||
post_handshake_auth = 49, | ||
/// RFC 8446 | ||
signature_algorithms_cert = 50, | ||
/// RFC 8446 | ||
key_share = 51, | ||
}; | ||
|
||
pub const AlertLevel = enum(u8) { | ||
warning = 1, | ||
fatal = 2, | ||
_, | ||
}; | ||
|
||
pub const AlertDescription = enum(u8) { | ||
close_notify = 0, | ||
unexpected_message = 10, | ||
bad_record_mac = 20, | ||
record_overflow = 22, | ||
handshake_failure = 40, | ||
bad_certificate = 42, | ||
unsupported_certificate = 43, | ||
certificate_revoked = 44, | ||
certificate_expired = 45, | ||
certificate_unknown = 46, | ||
illegal_parameter = 47, | ||
unknown_ca = 48, | ||
access_denied = 49, | ||
decode_error = 50, | ||
decrypt_error = 51, | ||
protocol_version = 70, | ||
insufficient_security = 71, | ||
internal_error = 80, | ||
inappropriate_fallback = 86, | ||
user_canceled = 90, | ||
missing_extension = 109, | ||
unsupported_extension = 110, | ||
unrecognized_name = 112, | ||
bad_certificate_status_response = 113, | ||
unknown_psk_identity = 115, | ||
certificate_required = 116, | ||
no_application_protocol = 120, | ||
_, | ||
}; | ||
|
||
pub const SignatureScheme = enum(u16) { | ||
// RSASSA-PKCS1-v1_5 algorithms | ||
rsa_pkcs1_sha256 = 0x0401, | ||
rsa_pkcs1_sha384 = 0x0501, | ||
rsa_pkcs1_sha512 = 0x0601, | ||
|
||
// ECDSA algorithms | ||
ecdsa_secp256r1_sha256 = 0x0403, | ||
ecdsa_secp384r1_sha384 = 0x0503, | ||
ecdsa_secp521r1_sha512 = 0x0603, | ||
|
||
// RSASSA-PSS algorithms with public key OID rsaEncryption | ||
rsa_pss_rsae_sha256 = 0x0804, | ||
rsa_pss_rsae_sha384 = 0x0805, | ||
rsa_pss_rsae_sha512 = 0x0806, | ||
|
||
// EdDSA algorithms | ||
ed25519 = 0x0807, | ||
ed448 = 0x0808, | ||
|
||
// RSASSA-PSS algorithms with public key OID RSASSA-PSS | ||
rsa_pss_pss_sha256 = 0x0809, | ||
rsa_pss_pss_sha384 = 0x080a, | ||
rsa_pss_pss_sha512 = 0x080b, | ||
|
||
// Legacy algorithms | ||
rsa_pkcs1_sha1 = 0x0201, | ||
ecdsa_sha1 = 0x0203, | ||
|
||
_, | ||
}; | ||
|
||
pub const NamedGroup = enum(u16) { | ||
// Elliptic Curve Groups (ECDHE) | ||
secp256r1 = 0x0017, | ||
secp384r1 = 0x0018, | ||
secp521r1 = 0x0019, | ||
x25519 = 0x001D, | ||
x448 = 0x001E, | ||
|
||
// Finite Field Groups (DHE) | ||
ffdhe2048 = 0x0100, | ||
ffdhe3072 = 0x0101, | ||
ffdhe4096 = 0x0102, | ||
ffdhe6144 = 0x0103, | ||
ffdhe8192 = 0x0104, | ||
|
||
_, | ||
}; | ||
|
||
pub const CipherSuite = enum(u16) { | ||
TLS_AES_128_GCM_SHA256 = 0x1301, | ||
TLS_AES_256_GCM_SHA384 = 0x1302, | ||
TLS_CHACHA20_POLY1305_SHA256 = 0x1303, | ||
TLS_AES_128_CCM_SHA256 = 0x1304, | ||
TLS_AES_128_CCM_8_SHA256 = 0x1305, | ||
}; | ||
|
||
pub const CipherParams = union(CipherSuite) { | ||
TLS_AES_128_GCM_SHA256: struct { | ||
pub const AEAD = crypto.aead.aes_gcm.Aes128Gcm; | ||
pub const Hash = crypto.hash.sha2.Sha256; | ||
pub const Hmac = crypto.auth.hmac.Hmac(Hash); | ||
pub const Hkdf = crypto.kdf.hkdf.Hkdf(Hmac); | ||
|
||
handshake_secret: [Hkdf.key_len]u8, | ||
master_secret: [Hkdf.key_len]u8, | ||
client_handshake_key: [AEAD.key_length]u8, | ||
server_handshake_key: [AEAD.key_length]u8, | ||
client_finished_key: [Hmac.key_length]u8, | ||
server_finished_key: [Hmac.key_length]u8, | ||
client_handshake_iv: [AEAD.nonce_length]u8, | ||
server_handshake_iv: [AEAD.nonce_length]u8, | ||
transcript_hash: Hash, | ||
}, | ||
TLS_AES_256_GCM_SHA384: struct { | ||
pub const AEAD = crypto.aead.aes_gcm.Aes256Gcm; | ||
pub const Hash = crypto.hash.sha2.Sha384; | ||
pub const Hmac = crypto.auth.hmac.Hmac(Hash); | ||
pub const Hkdf = crypto.kdf.hkdf.Hkdf(Hmac); | ||
|
||
handshake_secret: [Hkdf.key_len]u8, | ||
master_secret: [Hkdf.key_len]u8, | ||
client_handshake_key: [AEAD.key_length]u8, | ||
server_handshake_key: [AEAD.key_length]u8, | ||
client_finished_key: [Hmac.key_length]u8, | ||
server_finished_key: [Hmac.key_length]u8, | ||
client_handshake_iv: [AEAD.nonce_length]u8, | ||
server_handshake_iv: [AEAD.nonce_length]u8, | ||
transcript_hash: Hash, | ||
}, | ||
TLS_CHACHA20_POLY1305_SHA256: void, | ||
TLS_AES_128_CCM_SHA256: void, | ||
TLS_AES_128_CCM_8_SHA256: void, | ||
}; | ||
|
||
/// Encryption parameters for application traffic. | ||
pub const ApplicationCipher = union(CipherSuite) { | ||
TLS_AES_128_GCM_SHA256: struct { | ||
pub const AEAD = crypto.aead.aes_gcm.Aes128Gcm; | ||
pub const Hash = crypto.hash.sha2.Sha256; | ||
pub const Hmac = crypto.auth.hmac.Hmac(Hash); | ||
pub const Hkdf = crypto.kdf.hkdf.Hkdf(Hmac); | ||
|
||
client_key: [AEAD.key_length]u8, | ||
server_key: [AEAD.key_length]u8, | ||
client_iv: [AEAD.nonce_length]u8, | ||
server_iv: [AEAD.nonce_length]u8, | ||
}, | ||
TLS_AES_256_GCM_SHA384: struct { | ||
pub const AEAD = crypto.aead.aes_gcm.Aes256Gcm; | ||
pub const Hash = crypto.hash.sha2.Sha384; | ||
pub const Hmac = crypto.auth.hmac.Hmac(Hash); | ||
pub const Hkdf = crypto.kdf.hkdf.Hkdf(Hmac); | ||
|
||
client_key: [AEAD.key_length]u8, | ||
server_key: [AEAD.key_length]u8, | ||
client_iv: [AEAD.nonce_length]u8, | ||
server_iv: [AEAD.nonce_length]u8, | ||
}, | ||
TLS_CHACHA20_POLY1305_SHA256: void, | ||
TLS_AES_128_CCM_SHA256: void, | ||
TLS_AES_128_CCM_8_SHA256: void, | ||
}; | ||
|
||
pub fn hkdfExpandLabel( | ||
comptime Hkdf: type, | ||
key: [Hkdf.key_len]u8, | ||
label: []const u8, | ||
context: []const u8, | ||
comptime len: usize, | ||
) [len]u8 { | ||
const max_label_len = 255; | ||
const max_context_len = 255; | ||
const tls13 = "tls13 "; | ||
var buf: [2 + 1 + tls13.len + max_label_len + 1 + max_context_len]u8 = undefined; | ||
mem.writeIntBig(u16, buf[0..2], len); | ||
buf[2] = @intCast(u8, tls13.len + label.len); | ||
buf[3..][0..tls13.len].* = tls13.*; | ||
var i: usize = 3 + tls13.len; | ||
mem.copy(u8, buf[i..], label); | ||
i += label.len; | ||
buf[i] = @intCast(u8, context.len); | ||
i += 1; | ||
mem.copy(u8, buf[i..], context); | ||
i += context.len; | ||
|
||
var result: [len]u8 = undefined; | ||
Hkdf.expand(&result, buf[0..i], key); | ||
return result; | ||
} | ||
|
||
pub fn emptyHash(comptime Hash: type) [Hash.digest_length]u8 { | ||
var result: [Hash.digest_length]u8 = undefined; | ||
Hash.hash(&.{}, &result, .{}); | ||
return result; | ||
} | ||
|
||
pub fn hmac(comptime Hmac: type, message: []const u8, key: [Hmac.key_length]u8) [Hmac.mac_length]u8 { | ||
var result: [Hmac.mac_length]u8 = undefined; | ||
Hmac.create(&result, message, &key); | ||
return result; | ||
} |
Oops, something went wrong.