Commit 3cc17b93a9
Changed files (4)
lib
std
crypto
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