authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-22 20:19:25-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-01-02 16:57:15-07:00
log642a8b05c3687d5c084ed164c773bd4d0a4faaef
tree53fd0a8880b54b0e2dd51d0bb93fb188014a4a38
parent7cb535d4b54a4e5627edc6b558d1f31b41651328

std.crypto.tls.Certificate: explicit error set for verify


4 files changed, 38 insertions(+), 10 deletions(-)

lib/std/crypto/Certificate.zig+26-4
......@@ -116,9 +116,23 @@ pub const Parsed = struct {
116116 return p.slice(p.message_slice);
117117 }
118118
119 pub const VerifyError = error{
120 CertificateIssuerMismatch,
121 CertificateNotYetValid,
122 CertificateExpired,
123 CertificateSignatureAlgorithmUnsupported,
124 CertificateSignatureAlgorithmMismatch,
125 CertificateFieldHasInvalidLength,
126 CertificateFieldHasWrongDataType,
127 CertificatePublicKeyInvalid,
128 CertificateSignatureInvalidLength,
129 CertificateSignatureInvalid,
130 CertificateSignatureUnsupportedBitCount,
131 };
132
119133 /// This function checks the time validity for the subject only. Checking
120134 /// the issuer's time validity is out of scope.
121 pub fn verify(parsed_subject: Parsed, parsed_issuer: Parsed) !void {
135 pub fn verify(parsed_subject: Parsed, parsed_issuer: Parsed) VerifyError!void {
122136 // Check that the subject's issuer name matches the issuer's
123137 // subject name.
124138 if (!mem.eql(u8, parsed_subject.issuer(), parsed_issuer.subject())) {
......@@ -452,11 +466,19 @@ fn verifyRsa(
452466 hash_der ++
453467 msg_hashed;
454468
455 const public_key = try rsa.PublicKey.fromBytes(exponent, modulus, rsa.poop);
456 const em_dec = try rsa.encrypt(modulus_len, sig[0..modulus_len].*, public_key, rsa.poop);
469 const public_key = rsa.PublicKey.fromBytes(exponent, modulus, rsa.poop) catch |err| switch (err) {
470 error.OutOfMemory => @panic("TODO don't heap allocate"),
471 };
472 const em_dec = rsa.encrypt(modulus_len, sig[0..modulus_len].*, public_key, rsa.poop) catch |err| switch (err) {
473 error.OutOfMemory => @panic("TODO don't heap allocate"),
474
475 error.MessageTooLong => unreachable,
476 error.NegativeIntoUnsigned => @panic("TODO make RSA not emit this error"),
477 error.TargetTooSmall => @panic("TODO make RSA not emit this error"),
478 error.BufferTooSmall => @panic("TODO make RSA not emit this error"),
479 };
457480
458481 if (!mem.eql(u8, &em, &em_dec)) {
459 try std.testing.expectEqualSlices(u8, &em, &em_dec);
460482 return error.CertificateSignatureInvalid;
461483 }
462484 },
lib/std/crypto/Certificate/Bundle.zig+9-3
......@@ -9,13 +9,19 @@
99map: std.HashMapUnmanaged(der.Element.Slice, u32, MapContext, std.hash_map.default_max_load_percentage) = .{},
1010bytes: std.ArrayListUnmanaged(u8) = .{},
1111
12pub fn verify(cb: Bundle, subject: Certificate.Parsed) !void {
13 const bytes_index = cb.find(subject.issuer()) orelse return error.IssuerNotFound;
12pub const VerifyError = Certificate.Parsed.VerifyError || error{
13 CertificateIssuerNotFound,
14};
15
16pub fn verify(cb: Bundle, subject: Certificate.Parsed) VerifyError!void {
17 const bytes_index = cb.find(subject.issuer()) orelse return error.CertificateIssuerNotFound;
1418 const issuer_cert: Certificate = .{
1519 .buffer = cb.bytes.items,
1620 .index = bytes_index,
1721 };
18 const issuer = try issuer_cert.parse();
22 // Every certificate in the bundle is pre-parsed before adding it, ensuring
23 // that parsing will succeed here.
24 const issuer = issuer_cert.parse() catch unreachable;
1925 try subject.verify(issuer);
2026}
2127
lib/std/crypto/der.zig+2-2
......@@ -111,7 +111,7 @@ pub const Element = struct {
111111 };
112112};
113113
114pub const ParseElementError = error{CertificateHasFieldWithInvalidLength};
114pub const ParseElementError = error{CertificateFieldHasInvalidLength};
115115
116116pub fn parseElement(bytes: []const u8, index: u32) ParseElementError!Element {
117117 var i = index;
......@@ -131,7 +131,7 @@ pub fn parseElement(bytes: []const u8, index: u32) ParseElementError!Element {
131131
132132 const len_size = @truncate(u7, size_byte);
133133 if (len_size > @sizeOf(u32)) {
134 return error.CertificateHasFieldWithInvalidLength;
134 return error.CertificateFieldHasInvalidLength;
135135 }
136136
137137 const end_i = i + len_size;
lib/std/crypto/tls/Client.zig+1-1
......@@ -470,7 +470,7 @@ pub fn init(stream: net.Stream, ca_bundle: Certificate.Bundle, host: []const u8)
470470 handshake_state = .trust_chain_established;
471471 break :cert;
472472 } else |err| switch (err) {
473 error.IssuerNotFound => {},
473 error.CertificateIssuerNotFound => {},
474474 else => |e| {
475475 std.debug.print("unable to validate cert against system root CAs: {s}\n", .{
476476 @errorName(e),