@@ -349,3 +349,112 @@ pub inline fn int3(x: u24) [3]u8 {
349349 @truncate (u8 , x ),
350350 };
351351}
352+
353+ pub const Der = struct {
354+ pub const Class = enum (u2 ) {
355+ universal ,
356+ application ,
357+ context_specific ,
358+ private ,
359+ };
360+
361+ pub const PC = enum (u1 ) {
362+ primitive ,
363+ constructed ,
364+ };
365+
366+ pub const Identifier = packed struct (u8 ) {
367+ tag : Tag ,
368+ pc : PC ,
369+ class : Class ,
370+ };
371+
372+ pub const Tag = enum (u5 ) {
373+ boolean = 1 ,
374+ integer = 2 ,
375+ bitstring = 3 ,
376+ null = 5 ,
377+ object_identifier = 6 ,
378+ sequence = 16 ,
379+ _ ,
380+ };
381+
382+ pub const Oid = enum {
383+ commonName ,
384+ countryName ,
385+ localityName ,
386+ stateOrProvinceName ,
387+ organizationName ,
388+ organizationalUnitName ,
389+ sha256WithRSAEncryption ,
390+ sha384WithRSAEncryption ,
391+ sha512WithRSAEncryption ,
392+ sha224WithRSAEncryption ,
393+
394+ pub const map = std .ComptimeStringMap (Oid , .{
395+ .{ &[_ ]u8 { 0x55 , 0x04 , 0x03 }, .commonName },
396+ .{ &[_ ]u8 { 0x55 , 0x04 , 0x06 }, .countryName },
397+ .{ &[_ ]u8 { 0x55 , 0x04 , 0x07 }, .localityName },
398+ .{ &[_ ]u8 { 0x55 , 0x04 , 0x08 }, .stateOrProvinceName },
399+ .{ &[_ ]u8 { 0x55 , 0x04 , 0x0A }, .organizationName },
400+ .{ &[_ ]u8 { 0x55 , 0x04 , 0x0B }, .organizationalUnitName },
401+ .{ &[_ ]u8 { 0x2A , 0x86 , 0x48 , 0x86 , 0xF7 , 0x0D , 0x01 , 0x01 , 0x0B }, .sha256WithRSAEncryption },
402+ .{ &[_ ]u8 { 0x2A , 0x86 , 0x48 , 0x86 , 0xF7 , 0x0D , 0x01 , 0x01 , 0x0C }, .sha384WithRSAEncryption },
403+ .{ &[_ ]u8 { 0x2A , 0x86 , 0x48 , 0x86 , 0xF7 , 0x0D , 0x01 , 0x01 , 0x0D }, .sha512WithRSAEncryption },
404+ .{ &[_ ]u8 { 0x2A , 0x86 , 0x48 , 0x86 , 0xF7 , 0x0D , 0x01 , 0x01 , 0x0E }, .sha224WithRSAEncryption },
405+ });
406+ };
407+
408+ pub const Element = struct {
409+ identifier : Identifier ,
410+ contents : []const u8 ,
411+ };
412+
413+ pub const ParseElementError = error {CertificateHasFieldWithInvalidLength };
414+
415+ pub fn parseElement (bytes : []const u8 , index : * usize ) ParseElementError ! Der.Element {
416+ var i = index .* ;
417+ const identifier = @bitCast (Identifier , bytes [i ]);
418+ i += 1 ;
419+ const size_byte = bytes [i ];
420+ i += 1 ;
421+ if ((size_byte >> 7 ) == 0 ) {
422+ const contents = bytes [i .. ][0.. size_byte ];
423+ index .* = i + contents .len ;
424+ return .{
425+ .identifier = identifier ,
426+ .contents = contents ,
427+ };
428+ }
429+
430+ const len_size = @truncate (u7 , size_byte );
431+ if (len_size > @sizeOf (usize )) {
432+ return error .CertificateHasFieldWithInvalidLength ;
433+ }
434+
435+ const end = i + len_size ;
436+ var long_form_size : usize = 0 ;
437+ while (i < end ) : (i += 1 ) {
438+ long_form_size = (long_form_size << 8 ) | bytes [i ];
439+ }
440+
441+ const contents = bytes [i .. ][0.. long_form_size ];
442+ index .* = i + contents .len ;
443+
444+ return .{
445+ .identifier = identifier ,
446+ .contents = contents ,
447+ };
448+ }
449+
450+ pub const ParseObjectIdError = error {
451+ CertificateHasUnrecognizedObjectId ,
452+ CertificateFieldHasWrongDataType ,
453+ } || ParseElementError ;
454+
455+ pub fn parseObjectId (bytes : []const u8 , index : * usize ) ParseObjectIdError ! Oid {
456+ const oid_element = try parseElement (bytes , index );
457+ if (oid_element .identifier .tag != .object_identifier ) return error .CertificateFieldHasWrongDataType ;
458+ return Oid .map .get (oid_element .contents ) orelse return error .CertificateHasUnrecognizedObjectId ;
459+ }
460+ };
0 commit comments