lib/quic/src/crypto/initial.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 const std = @import("std");
 2 const quic = @import("../root.zig");
 3 
 4 const Hkdf = std.crypto.kdf.hkdf.HkdfSha256;
 5 const Secret = quic.crypto.Secret;
 6 const tls = std.crypto.tls;
 7 
 8 /// The 20-byte Initial salt RFC 9001 section 5.2 fixes for QUIC version 1 serves a caller deriving
 9 /// Initial keys by hand so both endpoints use the same salt. This value acts as the salt of the
10 /// extraction that turns a client's destination connection ID into the Initial secret, from which
11 /// the client and server traffic secrets follow. A version other than 1 uses a different salt, so
12 /// this value belongs to version 1 alone.
13 pub const v1_salt = [_]u8{
14     0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17,
15     0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a,
16 };
17 
18 pub const Secrets = struct {
19     client: Secret,
20     server: Secret,
21 };
22 
23 fn extracted(dcid: []const u8) Secret {
24     return Hkdf.extract(&v1_salt, dcid);
25 }
26 
27 pub fn secrets(dcid: []const u8) Secrets {
28     const initial_secret = extracted(dcid);
29     return .{
30         .client = tls.hkdfExpandLabel(
31             Hkdf,
32             initial_secret,
33             "client in",
34             "",
35             quic.crypto.secret_bytes,
36         ),
37         .server = tls.hkdfExpandLabel(
38             Hkdf,
39             initial_secret,
40             "server in",
41             "",
42             quic.crypto.secret_bytes,
43         ),
44     };
45 }
46 
47 fn hex(comptime text: []const u8) [text.len / 2]u8 {
48     var result: [text.len / 2]u8 = undefined;
49     _ = std.fmt.hexToBytes(&result, text) catch unreachable;
50     return result;
51 }
52 
53 test "RFC 9001 Appendix A.1 version 1 initial secret" {
54     const dcid = hex("8394c8f03e515708");
55     const expected = hex(
56         "7db5df06e7a69e432496adedb0085192" ++
57             "3595221596ae2ae9fb8115c1e9ed0a44",
58     );
59     try std.testing.expectEqual(expected, extracted(&dcid));
60 }