diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-01-15 14:59:49 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-01-15 14:59:49 -0700 |
| commit | 9a0e1704aee1db4a7ca29706e11dd5ec6739c094 (patch) | |
| tree | ea342add4bca3d29583f960970fb162791992882 /lib | |
| parent | bb15e4057c9c8bb22084990de475ab10a44592c0 (diff) | |
| download | zig-9a0e1704aee1db4a7ca29706e11dd5ec6739c094.tar.gz zig-9a0e1704aee1db4a7ca29706e11dd5ec6739c094.zip | |
std.crypto.Certificate: support v1
closes #14304
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/std/crypto/Certificate.zig | 38 |
1 files changed, 30 insertions, 8 deletions
diff --git a/lib/std/crypto/Certificate.zig b/lib/std/crypto/Certificate.zig index fe211c6146..db984385bf 100644 --- a/lib/std/crypto/Certificate.zig +++ b/lib/std/crypto/Certificate.zig @@ -3,6 +3,8 @@ index: u32, pub const Bundle = @import("Certificate/Bundle.zig"); +pub const Version = enum { v1, v2, v3 }; + pub const Algorithm = enum { sha1WithRSAEncryption, sha224WithRSAEncryption, @@ -130,6 +132,7 @@ pub const Parsed = struct { message_slice: Slice, subject_alt_name_slice: Slice, validity: Validity, + version: Version, pub const PubKeyAlgo = union(AlgorithmCategory) { rsaEncryption: void, @@ -299,9 +302,12 @@ pub fn parse(cert: Certificate) !Parsed { const cert_bytes = cert.buffer; const certificate = try der.Element.parse(cert_bytes, cert.index); const tbs_certificate = try der.Element.parse(cert_bytes, certificate.slice.start); - const version = try der.Element.parse(cert_bytes, tbs_certificate.slice.start); - try checkVersion(cert_bytes, version); - const serial_number = try der.Element.parse(cert_bytes, version.slice.end); + const version_elem = try der.Element.parse(cert_bytes, tbs_certificate.slice.start); + const version = try parseVersion(cert_bytes, version_elem); + const serial_number = if (@bitCast(u8, version_elem.identifier) == 0xa0) + try der.Element.parse(cert_bytes, version_elem.slice.end) + else + version_elem; // RFC 5280, section 4.1.2.3: // "This field MUST contain the same algorithm identifier as // the signatureAlgorithm field in the sequence Certificate." @@ -370,6 +376,9 @@ pub fn parse(cert: Certificate) !Parsed { // Extensions var subject_alt_name_slice = der.Element.Slice.empty; ext: { + if (version == .v1) + break :ext; + if (pub_key_info.slice.end >= tbs_certificate.slice.end) break :ext; @@ -415,6 +424,7 @@ pub fn parse(cert: Certificate) !Parsed { .not_after = not_after_utc, }, .subject_alt_name_slice = subject_alt_name_slice, + .version = version, }; } @@ -588,12 +598,24 @@ fn parseEnum(comptime E: type, bytes: []const u8, element: der.Element) !E { return E.map.get(oid_bytes) orelse return error.CertificateHasUnrecognizedObjectId; } -pub fn checkVersion(bytes: []const u8, version: der.Element) !void { - if (@bitCast(u8, version.identifier) != 0xa0 or - !mem.eql(u8, bytes[version.slice.start..version.slice.end], "\x02\x01\x02")) - { - return error.UnsupportedCertificateVersion; +pub fn parseVersion(bytes: []const u8, version_elem: der.Element) !Version { + if (@bitCast(u8, version_elem.identifier) != 0xa0) + return .v1; + + if (version_elem.slice.end - version_elem.slice.start != 3) + return error.CertificateFieldHasInvalidLength; + + const encoded_version = bytes[version_elem.slice.start..version_elem.slice.end]; + + if (mem.eql(u8, encoded_version, "\x02\x01\x02")) { + return .v3; + } else if (mem.eql(u8, encoded_version, "\x02\x01\x01")) { + return .v2; + } else if (mem.eql(u8, encoded_version, "\x02\x01\x00")) { + return .v1; } + + return error.UnsupportedCertificateVersion; } fn verifyRsa( |
