diff --git a/lib/std/crypto/Certificate.zig b/lib/std/crypto/Certificate.zig index 6c51ccb133..4f34412b1f 100644 --- a/lib/std/crypto/Certificate.zig +++ b/lib/std/crypto/Certificate.zig @@ -56,6 +56,8 @@ pub const Attribute = enum { organizationName, organizationalUnitName, organizationIdentifier, + subject_alt_name, + pkcs9_emailAddress, pub const map = std.ComptimeStringMap(Attribute, .{ .{ &[_]u8{ 0x55, 0x04, 0x03 }, .commonName }, @@ -66,6 +68,8 @@ pub const Attribute = enum { .{ &[_]u8{ 0x55, 0x04, 0x0A }, .organizationName }, .{ &[_]u8{ 0x55, 0x04, 0x0B }, .organizationalUnitName }, .{ &[_]u8{ 0x55, 0x04, 0x61 }, .organizationIdentifier }, + .{ &[_]u8{ 0x55, 0x1D, 0x11 }, .subject_alt_name }, + .{ &[_]u8{ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01 }, .pkcs9_emailAddress }, }); }; @@ -74,6 +78,7 @@ pub const Parsed = struct { issuer_slice: Slice, subject_slice: Slice, common_name_slice: Slice, + subject_alt_name_slice: Slice, signature_slice: Slice, signature_algorithm: Algorithm, pub_key_algo: AlgorithmCategory, @@ -104,6 +109,10 @@ pub const Parsed = struct { return p.slice(p.common_name_slice); } + pub fn subjectAltName(p: Parsed) []const u8 { + return p.slice(p.subject_alt_name_slice); + } + pub fn signature(p: Parsed) []const u8 { return p.slice(p.signature_slice); } @@ -195,20 +204,33 @@ pub fn parse(cert: Certificate) !Parsed { const pub_key_elem = try der.parseElement(cert_bytes, pub_key_signature_algorithm.slice.end); const pub_key = try parseBitString(cert, pub_key_elem); - const rdn = try der.parseElement(cert_bytes, subject.slice.start); - const atav = try der.parseElement(cert_bytes, rdn.slice.start); - var common_name = der.Element.Slice.empty; - var atav_i = atav.slice.start; - while (atav_i < atav.slice.end) { - const ty_elem = try der.parseElement(cert_bytes, atav_i); - const ty = try parseAttribute(cert_bytes, ty_elem); - const val = try der.parseElement(cert_bytes, ty_elem.slice.end); - switch (ty) { - .commonName => common_name = val.slice, - else => {}, + var subject_alt_name = der.Element.Slice.empty; + var name_i = subject.slice.start; + //std.debug.print("subject name:\n", .{}); + while (name_i < subject.slice.end) { + const rdn = try der.parseElement(cert_bytes, name_i); + var rdn_i = rdn.slice.start; + while (rdn_i < rdn.slice.end) { + const atav = try der.parseElement(cert_bytes, rdn_i); + var atav_i = atav.slice.start; + while (atav_i < atav.slice.end) { + const ty_elem = try der.parseElement(cert_bytes, atav_i); + const ty = try parseAttribute(cert_bytes, ty_elem); + const val = try der.parseElement(cert_bytes, ty_elem.slice.end); + //std.debug.print(" {s}: '{s}'\n", .{ + // @tagName(ty), cert_bytes[val.slice.start..val.slice.end], + //}); + switch (ty) { + .commonName => common_name = val.slice, + .subject_alt_name => subject_alt_name = val.slice, + else => {}, + } + atav_i = val.slice.end; + } + rdn_i = atav.slice.end; } - atav_i = val.slice.end; + name_i = rdn.slice.end; } const sig_algo = try der.parseElement(cert_bytes, tbs_certificate.slice.end); @@ -220,6 +242,7 @@ pub fn parse(cert: Certificate) !Parsed { return .{ .certificate = cert, .common_name_slice = common_name, + .subject_alt_name_slice = subject_alt_name, .issuer_slice = issuer.slice, .subject_slice = subject.slice, .signature_slice = signature, @@ -397,8 +420,11 @@ pub fn parseAlgorithmCategory(bytes: []const u8, element: der.Element) !Algorith pub fn parseAttribute(bytes: []const u8, element: der.Element) !Attribute { if (element.identifier.tag != .object_identifier) return error.CertificateFieldHasWrongDataType; - return Attribute.map.get(bytes[element.slice.start..element.slice.end]) orelse - return error.CertificateHasUnrecognizedAlgorithm; + const oid_bytes = bytes[element.slice.start..element.slice.end]; + return Attribute.map.get(oid_bytes) orelse { + //std.debug.print("attr: {}\n", .{std.fmt.fmtSliceHexLower(oid_bytes)}); + return error.CertificateHasUnrecognizedAttribute; + }; } fn verifyRsa( diff --git a/lib/std/crypto/tls/Client.zig b/lib/std/crypto/tls/Client.zig index 8e46ce5053..aa9df520e6 100644 --- a/lib/std/crypto/tls/Client.zig +++ b/lib/std/crypto/tls/Client.zig @@ -323,8 +323,8 @@ pub fn init(stream: net.Stream, ca_bundle: Certificate.Bundle, host: []const u8) var handshake_state: HandshakeState = .encrypted_extensions; var cleartext_bufs: [2][8000]u8 = undefined; var main_cert_pub_key_algo: Certificate.AlgorithmCategory = undefined; - var main_cert_pub_key_buf: [128]u8 = undefined; - var main_cert_pub_key_len: u8 = undefined; + var main_cert_pub_key_buf: [300]u8 = undefined; + var main_cert_pub_key_len: u16 = undefined; while (true) { const end_hdr = i + 5; @@ -503,7 +503,7 @@ pub fn init(stream: net.Stream, ca_bundle: Certificate.Bundle, host: []const u8) var verify_buffer = ([1]u8{0x20} ** 64) ++ "TLS 1.3, server CertificateVerify\x00".* ++ - ([1]u8{undefined} ** max_digest_len); + @as([max_digest_len]u8, undefined); const verify_bytes = switch (handshake_cipher) { inline else => |*p| v: { @@ -524,7 +524,15 @@ pub fn init(stream: net.Stream, ca_bundle: Certificate.Bundle, host: []const u8) const key = try P256.PublicKey.fromSec1(main_cert_pub_key); try sig.verify(verify_bytes, key); }, - else => return error.TlsBadSignatureAlgorithm, + .rsa_pss_rsae_sha256 => { + @panic("TODO signature algorithm: rsa_pss_rsae_sha256"); + }, + else => { + //std.debug.print("signature algorithm: {any}\n", .{ + // algorithm, + //}); + return error.TlsBadSignatureAlgorithm; + }, } }, @enumToInt(HandshakeType.finished) => { @@ -557,7 +565,7 @@ pub fn init(stream: net.Stream, ca_bundle: Certificate.Bundle, host: []const u8) @enumToInt(ContentType.application_data), 0x03, 0x03, // legacy protocol version 0, wrapped_len, // byte length of encrypted record - } ++ ([1]u8{undefined} ** wrapped_len); + } ++ @as([wrapped_len]u8, undefined); const ad = finished_msg[0..5]; const ciphertext = finished_msg[5..][0..out_cleartext.len];