diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/std/crypto/asn1/Oid.zig | 8 | ||||
| -rw-r--r-- | lib/std/crypto/asn1/der.zig | 26 | ||||
| -rw-r--r-- | lib/std/crypto/asn1/der/Decoder.zig | 9 | ||||
| -rw-r--r-- | lib/std/crypto/asn1/der/Encoder.zig | 16 |
4 files changed, 51 insertions, 8 deletions
diff --git a/lib/std/crypto/asn1/Oid.zig b/lib/std/crypto/asn1/Oid.zig index 18d10cfda1..897b4050bf 100644 --- a/lib/std/crypto/asn1/Oid.zig +++ b/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 diff --git a/lib/std/crypto/asn1/der.zig b/lib/std/crypto/asn1/der.zig index 28e5f77988..4395f9f3b6 100644 --- a/lib/std/crypto/asn1/der.zig +++ b/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; diff --git a/lib/std/crypto/asn1/der/Decoder.zig b/lib/std/crypto/asn1/der/Decoder.zig index dc8894c94f..2eedbee957 100644 --- a/lib/std/crypto/asn1/der/Decoder.zig +++ b/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); } diff --git a/lib/std/crypto/asn1/der/Encoder.zig b/lib/std/crypto/asn1/der/Encoder.zig index 709fbe75c6..939a1a5aa7 100644 --- a/lib/std/crypto/asn1/der/Encoder.zig +++ b/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(); |
