Commit 3cc17b93a9

clickingbuttons <clickingbuttons@pm.me>
2024-05-16 19:11:58
std.crypto.asn1: add short comments and der tests
1 parent 330d353
Changed files (4)
lib
lib/std/crypto/asn1/der/Decoder.zig
@@ -13,6 +13,7 @@ index: Index = 0,
 /// This is needed because we might visit an implicitly tagged container with a `fn decodeDer`.
 field_tag: ?FieldTag = null,
 
+/// Expect a value.
 pub fn any(self: *Decoder, comptime T: type) !T {
     if (std.meta.hasFn(T, "decodeDer")) return try T.decodeDer(self);
 
@@ -80,11 +81,16 @@ pub fn any(self: *Decoder, comptime T: type) !T {
     }
 }
 
+//// Expect a sequence.
 pub fn sequence(self: *Decoder) !Element {
     return try self.element(ExpectedTag.init(.sequence, true, .universal));
 }
 
-pub fn element(self: *Decoder, expected: ExpectedTag) (error{ EndOfStream, UnexpectedElement } || Element.DecodeError)!Element {
+//// Expect an element.
+pub fn element(
+    self: *Decoder,
+    expected: ExpectedTag,
+) (error{ EndOfStream, UnexpectedElement } || Element.DecodeError)!Element {
     if (self.index >= self.bytes.len) return error.EndOfStream;
 
     const res = try Element.decode(self.bytes, self.index);
@@ -101,6 +107,7 @@ pub fn element(self: *Decoder, expected: ExpectedTag) (error{ EndOfStream, Unexp
     return res;
 }
 
+/// View of element bytes.
 pub fn view(self: Decoder, elem: Element) []const u8 {
     return elem.slice.view(self.bytes);
 }
lib/std/crypto/asn1/der/Encoder.zig
@@ -15,6 +15,7 @@ pub fn deinit(self: *Encoder) void {
     self.buffer.deinit();
 }
 
+/// Encode any value.
 pub fn any(self: *Encoder, val: anytype) !void {
     const T = @TypeOf(val);
     try self.anyTag(Tag.fromZig(T), val);
@@ -74,17 +75,12 @@ fn anyTag(self: *Encoder, tag_: Tag, val: anytype) !void {
     try self.tag(merged_tag);
 }
 
+/// Encode a tag.
 pub fn tag(self: *Encoder, tag_: Tag) !void {
     const t = self.mergedTag(tag_);
     try t.encode(self.writer());
 }
 
-pub fn tagBytes(self: *Encoder, tag_: Tag, bytes: []const u8) !void {
-    try self.buffer.prependSlice(bytes);
-    try self.length(bytes.len);
-    try self.tag(tag_);
-}
-
 fn mergedTag(self: *Encoder, tag_: Tag) Tag {
     var res = tag_;
     if (self.field_tag) |ft| {
@@ -96,6 +92,7 @@ fn mergedTag(self: *Encoder, tag_: Tag) Tag {
     return res;
 }
 
+/// Encode a length.
 pub fn length(self: *Encoder, len: usize) !void {
     const writer_ = self.writer();
     if (len < 128) {
@@ -112,6 +109,13 @@ pub fn length(self: *Encoder, len: usize) !void {
     return error.InvalidLength;
 }
 
+/// Encode a tag and length-prefixed bytes.
+pub fn tagBytes(self: *Encoder, tag_: Tag, bytes: []const u8) !void {
+    try self.buffer.prependSlice(bytes);
+    try self.length(bytes.len);
+    try self.tag(tag_);
+}
+
 /// Warning: This writer writes backwards. `fn print` will NOT work as expected.
 pub fn writer(self: *Encoder) ArrayListReverse.Writer {
     return self.buffer.writer();
lib/std/crypto/asn1/der.zig
@@ -23,6 +23,32 @@ pub fn encode(allocator: std.mem.Allocator, value: anytype) ![]u8 {
     return try encoder.buffer.toOwnedSlice();
 }
 
+test encode {
+    // https://lapo.it/asn1js/#MAgGAyoDBAIBBA
+    const Value = struct { a: asn1.Oid, b: i32 };
+    const test_case = .{
+        .value = Value{ .a = asn1.Oid.fromDotComptime("1.2.3.4"), .b = 4 },
+        .encoded = &[_]u8{ 0x30, 0x08, 0x06, 0x03, 0x2A, 0x03, 0x04, 0x02, 0x01, 0x04 },
+    };
+    const allocator = std.testing.allocator;
+    const actual = try encode(allocator, test_case.value);
+    defer allocator.free(actual);
+
+    try std.testing.expectEqualSlices(u8, test_case.encoded, actual);
+}
+
+test decode {
+    // https://lapo.it/asn1js/#MAgGAyoDBAIBBA
+    const Value = struct { a: asn1.Oid, b: i32 };
+    const test_case = .{
+        .value = Value{ .a = asn1.Oid.fromDotComptime("1.2.3.4"), .b = 4 },
+        .encoded = &[_]u8{ 0x30, 0x08, 0x06, 0x03, 0x2A, 0x03, 0x04, 0x02, 0x01, 0x04 },
+    };
+    const decoded = try decode(Value, test_case.encoded);
+
+    try std.testing.expectEqualDeep(test_case.value, decoded);
+}
+
 test {
     _ = Decoder;
     _ = Encoder;
lib/std/crypto/asn1/Oid.zig
@@ -123,7 +123,8 @@ fn encodedLen(dot_notation: []const u8) usize {
     return oid.encoded.len;
 }
 
-pub fn encodeComptime(comptime dot_notation: []const u8) [encodedLen(dot_notation)]u8 {
+/// Returns encoded bytes of OID.
+fn encodeComptime(comptime dot_notation: []const u8) [encodedLen(dot_notation)]u8 {
     @setEvalBranchQuota(4000);
     comptime var buf: [256]u8 = undefined;
     const oid = comptime fromDot(dot_notation, &buf) catch unreachable;
@@ -137,6 +138,11 @@ test encodeComptime {
     );
 }
 
+pub fn fromDotComptime(comptime dot_notation: []const u8) Oid {
+    const tmp = comptime encodeComptime(dot_notation);
+    return Oid{ .encoded = &tmp };
+}
+
 /// Maps of:
 /// - Oid -> enum
 /// - Enum -> oid