Commit 9ca6d67345

Andrew Kelley <andrew@ziglang.org>
2023-01-02 21:18:56
std.crypto.tls.Certificate: make the current time a parameter
1 parent 97acdee
Changed files (3)
lib
std
lib/std/crypto/Certificate/Bundle.zig
@@ -13,7 +13,7 @@ pub const VerifyError = Certificate.Parsed.VerifyError || error{
     CertificateIssuerNotFound,
 };
 
-pub fn verify(cb: Bundle, subject: Certificate.Parsed) VerifyError!void {
+pub fn verify(cb: Bundle, subject: Certificate.Parsed, now_sec: i64) VerifyError!void {
     const bytes_index = cb.find(subject.issuer()) orelse return error.CertificateIssuerNotFound;
     const issuer_cert: Certificate = .{
         .buffer = cb.bytes.items,
@@ -22,7 +22,7 @@ pub fn verify(cb: Bundle, subject: Certificate.Parsed) VerifyError!void {
     // Every certificate in the bundle is pre-parsed before adding it, ensuring
     // that parsing will succeed here.
     const issuer = issuer_cert.parse() catch unreachable;
-    try subject.verify(issuer);
+    try subject.verify(issuer, now_sec);
 }
 
 /// The returned bytes become invalid after calling any of the rescan functions
lib/std/crypto/tls/Client.zig
@@ -351,6 +351,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) !C
     var main_cert_pub_key_algo: Certificate.AlgorithmCategory = undefined;
     var main_cert_pub_key_buf: [300]u8 = undefined;
     var main_cert_pub_key_len: u16 = undefined;
+    const now_sec = std.time.timestamp();
 
     while (true) {
         try d.readAtLeastOurAmt(stream, tls.record_header_len);
@@ -458,10 +459,10 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) !C
                                     @memcpy(&main_cert_pub_key_buf, pub_key.ptr, pub_key.len);
                                     main_cert_pub_key_len = @intCast(@TypeOf(main_cert_pub_key_len), pub_key.len);
                                 } else {
-                                    try prev_cert.verify(subject);
+                                    try prev_cert.verify(subject, now_sec);
                                 }
 
-                                if (ca_bundle.verify(subject)) |_| {
+                                if (ca_bundle.verify(subject, now_sec)) |_| {
                                     handshake_state = .trust_chain_established;
                                     break :cert;
                                 } else |err| switch (err) {
lib/std/crypto/Certificate.zig
@@ -198,14 +198,13 @@ pub const Parsed = struct {
     ///  * That the subject's issuer is indeed the provided issuer.
     ///  * The time validity of the subject.
     ///  * The signature.
-    pub fn verify(parsed_subject: Parsed, parsed_issuer: Parsed) VerifyError!void {
+    pub fn verify(parsed_subject: Parsed, parsed_issuer: Parsed, now_sec: i64) VerifyError!void {
         // Check that the subject's issuer name matches the issuer's
         // subject name.
         if (!mem.eql(u8, parsed_subject.issuer(), parsed_issuer.subject())) {
             return error.CertificateIssuerMismatch;
         }
 
-        const now_sec = std.time.timestamp();
         if (now_sec < parsed_subject.validity.not_before)
             return error.CertificateNotYetValid;
         if (now_sec > parsed_subject.validity.not_after)
@@ -419,10 +418,10 @@ pub fn parse(cert: Certificate) !Parsed {
     };
 }
 
-pub fn verify(subject: Certificate, issuer: Certificate) !void {
+pub fn verify(subject: Certificate, issuer: Certificate, now_sec: i64) !void {
     const parsed_subject = try subject.parse();
     const parsed_issuer = try issuer.parse();
-    return parsed_subject.verify(parsed_issuer);
+    return parsed_subject.verify(parsed_issuer, now_sec);
 }
 
 pub fn contents(cert: Certificate, elem: der.Element) []const u8 {