Skip to documentation
SLOP

tiny.quic.tls.schedule

Reference tiny.quic tls schedule

Defined in tls.

API (10)

Actions

Public operations.

Types and contracts

Public types and contracts.

No direct callersNo direct callstlsschedule
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Called byCallsNo direct callersprivate sourcelib.quic.src.tls.schedulederivetls.schedule.Scheduleapplication
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsprivate sourcelib.quic.src.tls.engine.machine.EngineinstallScheduletls.schedule.ScheduleeraseDerivationSecrets
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.accy.src.choir.record.programrestoreIntiny.accychoir.record.programvalidatetest sourcelib.accy.src.preparation.testtest: Accy stage records preserve ful...private sourcelib.quic.src.tls.engine.machine.EngineinstallScheduletest sourcelib.quic.src.tls.schedule.test_RFC_8448_secti...3 handshake scheduleprivate sourcelib.quic.src.tls.schedulederivetls.schedule.Scheduleinit
Static calls · unresolved targets: 1 · external targets: 2.
Called byCallsNo direct callstls.schedulefinishedVerifyDatatls.schedulefinishedKey
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsprivate sourcelib.quic.src.tls.engine.machine.EnginequeueSignedAndFinishedprivate sourcelib.quic.src.tls.engine.machine.EngineverifyFinishedtest sourcelib.quic.src.tls.scheduletest: RFC 8448 section 3 application ...tls.schedulefinishedKeytls.schedulefinishedVerifyData
Static calls · unresolved targets: 0 · external targets: 1.

Source: lib/quic/src/tls/root.zig:38

zig
pub const schedule = @import("schedule.zig");

Source: lib/quic/src/tls/schedule.zig

zig
const std = @import("std");const Hkdf = std.crypto.kdf.hkdf.HkdfSha256;const Hmac = std.crypto.auth.hmac.sha2.HmacSha256;const Sha256 = std.crypto.hash.sha2.Sha256;const tls = std.crypto.tls;pub const Secret = [Sha256.digest_length]u8;pub const Application = struct {    client: Secret,    server: Secret,    exporter: Secret,};pub const Schedule = struct {    early: Secret,    handshake: Secret,    client_handshake: Secret,    server_handshake: Secret,    master: Secret,    pub fn init(shared_secret: Secret, hello_hash: Secret) Schedule {        const zero: Secret = @splat(0);        var early = Hkdf.extract(&zero, &zero);        defer std.crypto.secureZero(u8, &early);        const empty_hash = tls.emptyHash(Sha256);        var early_derived = tls.hkdfExpandLabel(            Hkdf,            early,            "derived",            &empty_hash,            @sizeOf(Secret),        );        defer std.crypto.secureZero(u8, &early_derived);        var handshake = Hkdf.extract(&early_derived, &shared_secret);        defer std.crypto.secureZero(u8, &handshake);        var client = derive(handshake, "c hs traffic", hello_hash);        defer std.crypto.secureZero(u8, &client);        var server = derive(handshake, "s hs traffic", hello_hash);        defer std.crypto.secureZero(u8, &server);        var handshake_derived = tls.hkdfExpandLabel(            Hkdf,            handshake,            "derived",            &empty_hash,            @sizeOf(Secret),        );        defer std.crypto.secureZero(u8, &handshake_derived);        var master = Hkdf.extract(&handshake_derived, &zero);        defer std.crypto.secureZero(u8, &master);        return .{            .early = early,            .handshake = handshake,            .client_handshake = client,            .server_handshake = server,            .master = master,        };    }    pub fn application(self: *const Schedule, transcript_hash: Secret) Application {        return .{            .client = derive(self.master, "c ap traffic", transcript_hash),            .server = derive(self.master, "s ap traffic", transcript_hash),            .exporter = derive(self.master, "exp master", transcript_hash),        };    }    pub fn eraseDerivationSecrets(self: *Schedule) void {        std.crypto.secureZero(u8, &self.early);        std.crypto.secureZero(u8, &self.handshake);    }    pub fn eraseHandshakeTrafficSecrets(self: *Schedule) void {        std.crypto.secureZero(u8, &self.client_handshake);        std.crypto.secureZero(u8, &self.server_handshake);    }    pub fn eraseMasterSecret(self: *Schedule) void {        std.crypto.secureZero(u8, &self.master);    }};pub fn finishedKey(traffic_secret: Secret) Secret {    return tls.hkdfExpandLabel(Hkdf, traffic_secret, "finished", &.{}, @sizeOf(Secret));}pub fn finishedVerifyData(traffic_secret: Secret, transcript_hash: Secret) Secret {    return tls.hmac(Hmac, &transcript_hash, finishedKey(traffic_secret));}fn derive(secret: Secret, label: []const u8, transcript_hash: Secret) Secret {    return tls.hkdfExpandLabel(Hkdf, secret, label, &transcript_hash, @sizeOf(Secret));}fn hexBytes(comptime length: usize, comptime value: []const u8) [length]u8 {    var result: [length]u8 = undefined;    _ = std.fmt.hexToBytes(&result, value) catch unreachable;    return result;}fn rfc8448ClientHello() [196]u8 {    return hexBytes(196, "010000c00303cb34ecb1e78163ba1c38c6dacb196a6dffa21a8d9912ec18a2" ++        "ef6283024dece7000006130113031302010000910000000b0009000006736572" ++        "766572ff01000100000a00140012001d00170018001901000101010201030104" ++        "00230000003300260024001d002099381de560e4bd43d23d8e435a7dbafeb3c0" ++        "6e51c13cae4d5413691e529aaf2c002b0003020304000d0020001e0403050306" ++        "03020308040805080604010501060102010402050206020202002d0002010100" ++        "1c00024001");}fn rfc8448ServerHello() [90]u8 {    return hexBytes(90, "020000560303a6af06a4121860dc5e6e60249cd34c95930c8ac5cb1434dac155" ++        "772ed3e2692800130100002e00330024001d0020c9828876112095fe66762bdb" ++        "f7c672e156d6cc253b833df1dd69b1b04e751f0f002b00020304");}fn rfc8448HelloHash() Secret {    var transcript = Sha256.init(.{});    transcript.update(&rfc8448ClientHello());    transcript.update(&rfc8448ServerHello());    var digest: Secret = undefined;    transcript.final(&digest);    return digest;}test "RFC 8448 section 3 X25519 and TLS 1.3 handshake schedule" {    const client_private = hexBytes(        32,        "49af42ba7f7994852d713ef2784bcbcaa7911de26adc5642cb634540e7ea5005",    );    const server_private = hexBytes(        32,        "b1580eeadf6dd589b8ef4f2d5652578cc810e9980191ec8d058308cea216a21e",    );    const client_public = try std.crypto.dh.X25519.recoverPublicKey(client_private);    const server_public = try std.crypto.dh.X25519.recoverPublicKey(server_private);    const shared = try std.crypto.dh.X25519.scalarmult(server_private, client_public);    const client_shared = try std.crypto.dh.X25519.scalarmult(client_private, server_public);    try std.testing.expectEqual(shared, client_shared);    try std.testing.expectEqual(        hexBytes(32, "8bd4054fb55b9d63fdfbacf9f04b9f0d35e6d63f537563efd46272900f89492d"),        shared,    );    const hello_hash = rfc8448HelloHash();    try expectSecret(        "860c06edc07858ee8e78f0e7428c58edd6b43f2ca3e6e95f02ed063cf0e1cad8",        hello_hash,    );    const schedule = Schedule.init(shared, hello_hash);    try expectSecret(        "33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a",        schedule.early,    );    try expectSecret(        "1dc826e93606aa6fdc0aadc12f741b01046aa6b99f691ed221a9f0ca043fbeac",        schedule.handshake,    );    try expectSecret(        "b3eddb126e067f35a780b3abf45e2d8f3b1a950738f52e9600746a0e27a55a21",        schedule.client_handshake,    );    try expectSecret(        "b67b7d690cc16c4e75e54213cb2d37b4e9c912bcded9105d42befd59d391ad38",        schedule.server_handshake,    );    try expectSecret(        "18df06843d13a08bf2a449844c5f8a478001bc4d4c627984d5a41da8d0402919",        schedule.master,    );}test "RFC 8448 section 3 application schedule and server Finished" {    const master = hexBytes(        32,        "18df06843d13a08bf2a449844c5f8a478001bc4d4c627984d5a41da8d0402919",    );    const base = Schedule{        .early = undefined,        .handshake = undefined,        .client_handshake = undefined,        .server_handshake = hexBytes(            32,            "b67b7d690cc16c4e75e54213cb2d37b4e9c912bcded9105d42befd59d391ad38",        ),        .master = master,    };    const application = base.application(hexBytes(        32,        "9608102a0f1ccc6db6250b7b7e417b1a000eaada3daae4777a7686c9ff83df13",    ));    try expectSecret(        "9e40646ce79a7f9dc05af8889bce6552875afa0b06df0087f792ebb7c17504a5",        application.client,    );    try expectSecret(        "a11af9f05531f856ad47116b45a950328204b4f44bfb6b3a4b4f1f3fcb631643",        application.server,    );    try expectSecret(        "fe22f881176eda18eb8f44529e6792c50c9a3f89452f68d8ae311b4309d3cf50",        application.exporter,    );    const verify_data = finishedVerifyData(base.server_handshake, hexBytes(        32,        "edb7725fa7a3473b031ec8ef65a2485493900138a2b91291407d7951a06110ed",    ));    try expectSecret(        "9b9b141d906337fbd2cbdce71df4deda4ab42c309572cb7fffee5454b78f0718",        verify_data,    );}fn expectSecret(comptime expected: []const u8, actual: Secret) !void {    try std.testing.expectEqual(hexBytes(32, expected), actual);}

Audit

Definitions11
Public names11
Members8
Version26.7.0
Revisiondaab053ee433