std.crypto.asn1: add short comments and der tests

This commit is contained in:
clickingbuttons 2024-05-16 13:11:58 -04:00
parent 330d353d6e
commit 3cc17b93a9
4 changed files with 51 additions and 8 deletions

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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();