| ... | ... | @@ -56,6 +56,8 @@ pub const Attribute = enum { |
| 56 | 56 | organizationName, |
| 57 | 57 | organizationalUnitName, |
| 58 | 58 | organizationIdentifier, |
| 59 | subject_alt_name, |
| 60 | pkcs9_emailAddress, |
| 59 | 61 | |
| 60 | 62 | pub const map = std.ComptimeStringMap(Attribute, .{ |
| 61 | 63 | .{ &[_]u8{ 0x55, 0x04, 0x03 }, .commonName }, |
| ... | ... | @@ -66,6 +68,8 @@ pub const Attribute = enum { |
| 66 | 68 | .{ &[_]u8{ 0x55, 0x04, 0x0A }, .organizationName }, |
| 67 | 69 | .{ &[_]u8{ 0x55, 0x04, 0x0B }, .organizationalUnitName }, |
| 68 | 70 | .{ &[_]u8{ 0x55, 0x04, 0x61 }, .organizationIdentifier }, |
| 71 | .{ &[_]u8{ 0x55, 0x1D, 0x11 }, .subject_alt_name }, |
| 72 | .{ &[_]u8{ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01 }, .pkcs9_emailAddress }, |
| 69 | 73 | }); |
| 70 | 74 | }; |
| 71 | 75 | |
| ... | ... | @@ -74,6 +78,7 @@ pub const Parsed = struct { |
| 74 | 78 | issuer_slice: Slice, |
| 75 | 79 | subject_slice: Slice, |
| 76 | 80 | common_name_slice: Slice, |
| 81 | subject_alt_name_slice: Slice, |
| 77 | 82 | signature_slice: Slice, |
| 78 | 83 | signature_algorithm: Algorithm, |
| 79 | 84 | pub_key_algo: AlgorithmCategory, |
| ... | ... | @@ -104,6 +109,10 @@ pub const Parsed = struct { |
| 104 | 109 | return p.slice(p.common_name_slice); |
| 105 | 110 | } |
| 106 | 111 | |
| 112 | pub fn subjectAltName(p: Parsed) []const u8 { |
| 113 | return p.slice(p.subject_alt_name_slice); |
| 114 | } |
| 115 | |
| 107 | 116 | pub fn signature(p: Parsed) []const u8 { |
| 108 | 117 | return p.slice(p.signature_slice); |
| 109 | 118 | } |
| ... | ... | @@ -195,20 +204,33 @@ pub fn parse(cert: Certificate) !Parsed { |
| 195 | 204 | const pub_key_elem = try der.parseElement(cert_bytes, pub_key_signature_algorithm.slice.end); |
| 196 | 205 | const pub_key = try parseBitString(cert, pub_key_elem); |
| 197 | 206 | |
| 198 | | const rdn = try der.parseElement(cert_bytes, subject.slice.start); |
| 199 | | const atav = try der.parseElement(cert_bytes, rdn.slice.start); |
| 200 | | |
| 201 | 207 | var common_name = der.Element.Slice.empty; |
| 202 | | var atav_i = atav.slice.start; |
| 203 | | while (atav_i < atav.slice.end) { |
| 204 | | const ty_elem = try der.parseElement(cert_bytes, atav_i); |
| 205 | | const ty = try parseAttribute(cert_bytes, ty_elem); |
| 206 | | const val = try der.parseElement(cert_bytes, ty_elem.slice.end); |
| 207 | | switch (ty) { |
| 208 | | .commonName => common_name = val.slice, |
| 209 | | else => {}, |
| 208 | var subject_alt_name = der.Element.Slice.empty; |
| 209 | var name_i = subject.slice.start; |
| 210 | //std.debug.print("subject name:\n", .{}); |
| 211 | while (name_i < subject.slice.end) { |
| 212 | const rdn = try der.parseElement(cert_bytes, name_i); |
| 213 | var rdn_i = rdn.slice.start; |
| 214 | while (rdn_i < rdn.slice.end) { |
| 215 | const atav = try der.parseElement(cert_bytes, rdn_i); |
| 216 | var atav_i = atav.slice.start; |
| 217 | while (atav_i < atav.slice.end) { |
| 218 | const ty_elem = try der.parseElement(cert_bytes, atav_i); |
| 219 | const ty = try parseAttribute(cert_bytes, ty_elem); |
| 220 | const val = try der.parseElement(cert_bytes, ty_elem.slice.end); |
| 221 | //std.debug.print(" {s}: '{s}'\n", .{ |
| 222 | // @tagName(ty), cert_bytes[val.slice.start..val.slice.end], |
| 223 | //}); |
| 224 | switch (ty) { |
| 225 | .commonName => common_name = val.slice, |
| 226 | .subject_alt_name => subject_alt_name = val.slice, |
| 227 | else => {}, |
| 228 | } |
| 229 | atav_i = val.slice.end; |
| 230 | } |
| 231 | rdn_i = atav.slice.end; |
| 210 | 232 | } |
| 211 | | atav_i = val.slice.end; |
| 233 | name_i = rdn.slice.end; |
| 212 | 234 | } |
| 213 | 235 | |
| 214 | 236 | const sig_algo = try der.parseElement(cert_bytes, tbs_certificate.slice.end); |
| ... | ... | @@ -220,6 +242,7 @@ pub fn parse(cert: Certificate) !Parsed { |
| 220 | 242 | return .{ |
| 221 | 243 | .certificate = cert, |
| 222 | 244 | .common_name_slice = common_name, |
| 245 | .subject_alt_name_slice = subject_alt_name, |
| 223 | 246 | .issuer_slice = issuer.slice, |
| 224 | 247 | .subject_slice = subject.slice, |
| 225 | 248 | .signature_slice = signature, |
| ... | ... | @@ -397,8 +420,11 @@ pub fn parseAlgorithmCategory(bytes: []const u8, element: der.Element) !Algorith |
| 397 | 420 | pub fn parseAttribute(bytes: []const u8, element: der.Element) !Attribute { |
| 398 | 421 | if (element.identifier.tag != .object_identifier) |
| 399 | 422 | return error.CertificateFieldHasWrongDataType; |
| 400 | | return Attribute.map.get(bytes[element.slice.start..element.slice.end]) orelse |
| 401 | | return error.CertificateHasUnrecognizedAlgorithm; |
| 423 | const oid_bytes = bytes[element.slice.start..element.slice.end]; |
| 424 | return Attribute.map.get(oid_bytes) orelse { |
| 425 | //std.debug.print("attr: {}\n", .{std.fmt.fmtSliceHexLower(oid_bytes)}); |
| 426 | return error.CertificateHasUnrecognizedAttribute; |
| 427 | }; |
| 402 | 428 | } |
| 403 | 429 | |
| 404 | 430 | fn verifyRsa( |