///|
#cfg(target="native")
priv suberror Tls13HandshakeStateError {
Tls13FinishedVerifyFailed
Tls13UnsupportedSignatureScheme
} derive(Debug, ToJson)
///|
#cfg(target="native")
let tls13_signature_rsa_pss_rsae_sha256 : Int = 0x0804
///|
#cfg(target="native")
let tls13_signature_ecdsa_secp256r1_sha256 : Int = 0x0403
///|
#cfg(target="native")
let tls13_oid_rsa_encryption : String = "1.2.840.113549.1.1.1"
///|
#cfg(target="native")
#warnings("-unused_field")
priv struct Tls13ServerHandshakeResult {
server_hello : Tls13ServerHello
encrypted_extensions : Tls13EncryptedExtensions
certificate : Tls13Certificate?
peer_certificate_info : X509CertificateInfo?
certificate_verify : Tls13CertificateVerify?
handshake_secrets : Tls13HandshakeSecrets
server_handshake_keys : Tls13TrafficKeys
}
///|
#cfg(target="native")
#warnings("-unused_field")
priv struct QuicTlsServerHandshakeResult {
server_connection_id : Bytes
server_hello : Tls13ServerHello
encrypted_extensions : Tls13EncryptedExtensions
certificate : Tls13Certificate?
peer_certificate_info : X509CertificateInfo?
certificate_verify : Tls13CertificateVerify?
handshake_secrets : Tls13HandshakeSecrets
client_handshake_keys : Tls13TrafficKeys
server_handshake_keys : Tls13TrafficKeys
client_quic_handshake_keys : QuicPacketKeys
server_quic_handshake_keys : QuicPacketKeys
server_handshake_largest_ack : Int
client_finished_message : Bytes
client_quic_application_keys : QuicPacketKeys
server_quic_application_keys : QuicPacketKeys
}
///|
#cfg(target="native")
fn tls13_bytes_equal(a : Bytes, b : Bytes) -> Bool {
if a.length() != b.length() {
false
} else {
let mut same = true
for i in 0.. Tls13ServerHandshakeResult raise {
let server_hello = tls13_parse_server_hello(server_hello_message)
let shared_secret = x25519(client_private_key, server_hello.x25519_public_key)
let handshake_transcript = tls13_transcript_hash([
client_hello, server_hello_message,
])
let handshake_secrets = tls13_derive_handshake_secrets(
shared_secret, handshake_transcript,
)
let server_handshake_keys = tls13_derive_traffic_keys(
handshake_secrets.server_handshake_traffic_secret,
)
let encrypted_extensions = tls13_parse_encrypted_extensions(
encrypted_extensions_message,
)
let mut certificate = None
let mut certificate_verify = None
let mut certificate_verify_transcript_hash = None
let before_finished = @buffer.new()
before_finished.write_bytes(client_hello)
before_finished.write_bytes(server_hello_message)
before_finished.write_bytes(encrypted_extensions_message)
for message in extra_messages_before_finished {
if message.length() > 0 &&
message[0].to_int() == tls13_handshake_certificate {
certificate = Some(tls13_parse_certificate(message))
} else if message.length() > 0 &&
message[0].to_int() == tls13_handshake_certificate_verify {
certificate_verify = Some(tls13_parse_certificate_verify(message))
certificate_verify_transcript_hash = Some(
tls13_sha256(before_finished.contents()),
)
}
before_finished.write_bytes(message)
}
let finished_transcript = tls13_sha256(before_finished.contents())
let expected = tls13_finished_verify_data(
server_handshake_keys.finished_key,
finished_transcript,
)
let finished = tls13_parse_finished(finished_message)
guard tls13_bytes_equal(expected, finished.verify_data) else {
raise Tls13FinishedVerifyFailed
}
let peer_certificate_info = if certificate is Some(certificate) &&
certificate.entries.length() > 0 {
Some(x509_parse_certificate(certificate.entries[0].cert_data))
} else {
None
}
if verify_certificate &&
peer_certificate_info is Some(peer_info) &&
certificate_verify is Some(verify) &&
certificate_verify_transcript_hash is Some(transcript_hash) {
tls13_verify_certificate_verify(peer_info, verify, transcript_hash)
}
{
server_hello,
encrypted_extensions,
certificate,
peer_certificate_info,
certificate_verify,
handshake_secrets,
server_handshake_keys,
}
}
///|
#cfg(target="native")
fn tls13_verify_certificate_verify(
peer_info : X509CertificateInfo,
verify : Tls13CertificateVerify,
transcript_hash : Bytes,
) -> Unit raise {
guard verify.signature_scheme == tls13_signature_rsa_pss_rsae_sha256 &&
peer_info.public_key_algorithm == tls13_oid_rsa_encryption else {
raise Tls13UnsupportedSignatureScheme
}
rsa_pss_sha256_verify(
peer_info.public_key,
tls13_certificate_verify_input(
"TLS 1.3, server CertificateVerify", transcript_hash,
),
verify.signature,
)
}
///|
#cfg(target="native")
fn tls13_encode_finished(verify_data : Bytes) -> Bytes raise {
let out = @buffer.new()
out.write_byte(tls13_handshake_finished.to_byte())
tls13_write_u24(out, verify_data.length())
out.write_bytes(verify_data)
out.contents()
}
///|
#cfg(target="native")
fn tls13_build_client_finished(
handshake_secrets : Tls13HandshakeSecrets,
transcript_through_server_finished : Bytes,
) -> (Tls13TrafficKeys, Bytes) raise {
let client_handshake_keys = tls13_derive_traffic_keys(
handshake_secrets.client_handshake_traffic_secret,
)
let verify_data = tls13_finished_verify_data(
client_handshake_keys.finished_key,
transcript_through_server_finished,
)
(client_handshake_keys, tls13_encode_finished(verify_data))
}
///|
#cfg(target="native")
#warnings("-unused_value")
fn quic_process_tls13_server_handshake(
client_private_key : Bytes,
client_hello : Bytes,
original_destination_connection_id : Bytes,
server_initial_packet : Bytes,
server_handshake_packets : Array[Bytes],
verify_certificate? : Bool = true,
) -> QuicTlsServerHandshakeResult raise {
let initial = quic_open_server_initial_packet(
server_initial_packet, original_destination_connection_id,
)
let initial_crypto = quic_collect_crypto_data(initial.payload)
let server_hello_messages = tls13_split_handshake_messages(initial_crypto)
guard server_hello_messages.length() >= 1 else {
raise Tls13HandshakeTruncated
}
let server_hello_message = server_hello_messages[0]
let server_hello = tls13_parse_server_hello(server_hello_message)
let shared_secret = x25519(client_private_key, server_hello.x25519_public_key)
let handshake_secrets = tls13_derive_handshake_secrets(
shared_secret,
tls13_transcript_hash([client_hello, server_hello_message]),
)
let server_quic_handshake_keys = tls13_derive_quic_packet_keys(
handshake_secrets.server_handshake_traffic_secret,
)
let handshake_crypto = @buffer.new()
let mut server_handshake_largest_ack = -1
for packet in server_handshake_packets {
let opened = quic_open_handshake_packet(packet, server_quic_handshake_keys)
if opened.packet_number > server_handshake_largest_ack {
server_handshake_largest_ack = opened.packet_number
}
handshake_crypto.write_bytes(quic_collect_crypto_data(opened.payload))
}
let handshake_messages = tls13_split_handshake_messages(
handshake_crypto.contents(),
)
guard handshake_messages.length() >= 2 else { raise Tls13HandshakeTruncated }
let encrypted_extensions_message = handshake_messages[0]
let finished_message = handshake_messages[handshake_messages.length() - 1]
let extra_messages = []
for i in 1..<(handshake_messages.length() - 1) {
extra_messages.push(handshake_messages[i])
}
let verified = tls13_process_server_handshake(
client_private_key,
client_hello,
server_hello_message,
encrypted_extensions_message,
finished_message,
extra_messages_before_finished=extra_messages,
verify_certificate~,
)
let app_transcript_data = @buffer.new()
app_transcript_data.write_bytes(client_hello)
app_transcript_data.write_bytes(server_hello_message)
app_transcript_data.write_bytes(handshake_crypto.contents())
let app_transcript_hash = tls13_sha256(app_transcript_data.contents())
let (client_handshake_keys, client_finished_message) = tls13_build_client_finished(
handshake_secrets, app_transcript_hash,
)
let app_secrets = tls13_derive_application_secrets(
handshake_secrets.handshake_secret,
app_transcript_hash,
)
let client_quic_handshake_keys = tls13_derive_quic_packet_keys(
handshake_secrets.client_handshake_traffic_secret,
)
{
server_connection_id: initial.source_connection_id,
server_hello: verified.server_hello,
encrypted_extensions: verified.encrypted_extensions,
certificate: verified.certificate,
peer_certificate_info: verified.peer_certificate_info,
certificate_verify: verified.certificate_verify,
handshake_secrets: verified.handshake_secrets,
client_handshake_keys,
server_handshake_keys: verified.server_handshake_keys,
client_quic_handshake_keys,
server_quic_handshake_keys,
server_handshake_largest_ack,
client_finished_message,
client_quic_application_keys: tls13_derive_quic_packet_keys(
app_secrets.client_application_traffic_secret,
),
server_quic_application_keys: tls13_derive_quic_packet_keys(
app_secrets.server_application_traffic_secret,
),
}
}