| author | |
| committer | |
| log | 3cc17b93a9f1b8a7009a58235f77e09de2cd2536 |
| tree | 8bf0dfae080a697bdcfe30c8b1ba2dd3504e6f89 |
| parent | 330d353d6e09ac1d48dedd1bfc127f81021b4b1f |
4 files changed, 51 insertions(+), 8 deletions(-)
lib/std/crypto/asn1/Oid.zig+7-1| ... | ... | @@ -123,7 +123,8 @@ fn encodedLen(dot_notation: []const u8) usize { |
| 123 | 123 | return oid.encoded.len; |
| 124 | 124 | } |
| 125 | 125 | |
| 126 | pub fn encodeComptime(comptime dot_notation: []const u8) [encodedLen(dot_notation)]u8 { | |
| 126 | /// Returns encoded bytes of OID. | |
| 127 | fn encodeComptime(comptime dot_notation: []const u8) [encodedLen(dot_notation)]u8 { | |
| 127 | 128 | @setEvalBranchQuota(4000); |
| 128 | 129 | comptime var buf: [256]u8 = undefined; |
| 129 | 130 | const oid = comptime fromDot(dot_notation, &buf) catch unreachable; |
| ... | ... | @@ -137,6 +138,11 @@ test encodeComptime { |
| 137 | 138 | ); |
| 138 | 139 | } |
| 139 | 140 | |
| 141 | pub fn fromDotComptime(comptime dot_notation: []const u8) Oid { | |
| 142 | const tmp = comptime encodeComptime(dot_notation); | |
| 143 | return Oid{ .encoded = &tmp }; | |
| 144 | } | |
| 145 | ||
| 140 | 146 | /// Maps of: |
| 141 | 147 | /// - Oid -> enum |
| 142 | 148 | /// - Enum -> oid |
lib/std/crypto/asn1/der.zig+26| ... | ... | @@ -23,6 +23,32 @@ pub fn encode(allocator: std.mem.Allocator, value: anytype) ![]u8 { |
| 23 | 23 | return try encoder.buffer.toOwnedSlice(); |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | test encode { | |
| 27 | // https://lapo.it/asn1js/#MAgGAyoDBAIBBA | |
| 28 | const Value = struct { a: asn1.Oid, b: i32 }; | |
| 29 | const test_case = .{ | |
| 30 | .value = Value{ .a = asn1.Oid.fromDotComptime("1.2.3.4"), .b = 4 }, | |
| 31 | .encoded = &[_]u8{ 0x30, 0x08, 0x06, 0x03, 0x2A, 0x03, 0x04, 0x02, 0x01, 0x04 }, | |
| 32 | }; | |
| 33 | const allocator = std.testing.allocator; | |
| 34 | const actual = try encode(allocator, test_case.value); | |
| 35 | defer allocator.free(actual); | |
| 36 | ||
| 37 | try std.testing.expectEqualSlices(u8, test_case.encoded, actual); | |
| 38 | } | |
| 39 | ||
| 40 | test decode { | |
| 41 | // https://lapo.it/asn1js/#MAgGAyoDBAIBBA | |
| 42 | const Value = struct { a: asn1.Oid, b: i32 }; | |
| 43 | const test_case = .{ | |
| 44 | .value = Value{ .a = asn1.Oid.fromDotComptime("1.2.3.4"), .b = 4 }, | |
| 45 | .encoded = &[_]u8{ 0x30, 0x08, 0x06, 0x03, 0x2A, 0x03, 0x04, 0x02, 0x01, 0x04 }, | |
| 46 | }; | |
| 47 | const decoded = try decode(Value, test_case.encoded); | |
| 48 | ||
| 49 | try std.testing.expectEqualDeep(test_case.value, decoded); | |
| 50 | } | |
| 51 | ||
| 26 | 52 | test { |
| 27 | 53 | _ = Decoder; |
| 28 | 54 | _ = Encoder; |
lib/std/crypto/asn1/der/Decoder.zig+8-1| ... | ... | @@ -13,6 +13,7 @@ index: Index = 0, |
| 13 | 13 | /// This is needed because we might visit an implicitly tagged container with a `fn decodeDer`. |
| 14 | 14 | field_tag: ?FieldTag = null, |
| 15 | 15 | |
| 16 | /// Expect a value. | |
| 16 | 17 | pub fn any(self: *Decoder, comptime T: type) !T { |
| 17 | 18 | if (std.meta.hasFn(T, "decodeDer")) return try T.decodeDer(self); |
| 18 | 19 | |
| ... | ... | @@ -80,11 +81,16 @@ pub fn any(self: *Decoder, comptime T: type) !T { |
| 80 | 81 | } |
| 81 | 82 | } |
| 82 | 83 | |
| 84 | //// Expect a sequence. | |
| 83 | 85 | pub fn sequence(self: *Decoder) !Element { |
| 84 | 86 | return try self.element(ExpectedTag.init(.sequence, true, .universal)); |
| 85 | 87 | } |
| 86 | 88 | |
| 87 | pub fn element(self: *Decoder, expected: ExpectedTag) (error{ EndOfStream, UnexpectedElement } || Element.DecodeError)!Element { | |
| 89 | //// Expect an element. | |
| 90 | pub fn element( | |
| 91 | self: *Decoder, | |
| 92 | expected: ExpectedTag, | |
| 93 | ) (error{ EndOfStream, UnexpectedElement } || Element.DecodeError)!Element { | |
| 88 | 94 | if (self.index >= self.bytes.len) return error.EndOfStream; |
| 89 | 95 | |
| 90 | 96 | const res = try Element.decode(self.bytes, self.index); |
| ... | ... | @@ -101,6 +107,7 @@ pub fn element(self: *Decoder, expected: ExpectedTag) (error{ EndOfStream, Unexp |
| 101 | 107 | return res; |
| 102 | 108 | } |
| 103 | 109 | |
| 110 | /// View of element bytes. | |
| 104 | 111 | pub fn view(self: Decoder, elem: Element) []const u8 { |
| 105 | 112 | return elem.slice.view(self.bytes); |
| 106 | 113 | } |
lib/std/crypto/asn1/der/Encoder.zig+10-6| ... | ... | @@ -15,6 +15,7 @@ pub fn deinit(self: *Encoder) void { |
| 15 | 15 | self.buffer.deinit(); |
| 16 | 16 | } |
| 17 | 17 | |
| 18 | /// Encode any value. | |
| 18 | 19 | pub fn any(self: *Encoder, val: anytype) !void { |
| 19 | 20 | const T = @TypeOf(val); |
| 20 | 21 | try self.anyTag(Tag.fromZig(T), val); |
| ... | ... | @@ -74,17 +75,12 @@ fn anyTag(self: *Encoder, tag_: Tag, val: anytype) !void { |
| 74 | 75 | try self.tag(merged_tag); |
| 75 | 76 | } |
| 76 | 77 | |
| 78 | /// Encode a tag. | |
| 77 | 79 | pub fn tag(self: *Encoder, tag_: Tag) !void { |
| 78 | 80 | const t = self.mergedTag(tag_); |
| 79 | 81 | try t.encode(self.writer()); |
| 80 | 82 | } |
| 81 | 83 | |
| 82 | pub fn tagBytes(self: *Encoder, tag_: Tag, bytes: []const u8) !void { | |
| 83 | try self.buffer.prependSlice(bytes); | |
| 84 | try self.length(bytes.len); | |
| 85 | try self.tag(tag_); | |
| 86 | } | |
| 87 | ||
| 88 | 84 | fn mergedTag(self: *Encoder, tag_: Tag) Tag { |
| 89 | 85 | var res = tag_; |
| 90 | 86 | if (self.field_tag) |ft| { |
| ... | ... | @@ -96,6 +92,7 @@ fn mergedTag(self: *Encoder, tag_: Tag) Tag { |
| 96 | 92 | return res; |
| 97 | 93 | } |
| 98 | 94 | |
| 95 | /// Encode a length. | |
| 99 | 96 | pub fn length(self: *Encoder, len: usize) !void { |
| 100 | 97 | const writer_ = self.writer(); |
| 101 | 98 | if (len < 128) { |
| ... | ... | @@ -112,6 +109,13 @@ pub fn length(self: *Encoder, len: usize) !void { |
| 112 | 109 | return error.InvalidLength; |
| 113 | 110 | } |
| 114 | 111 | |
| 112 | /// Encode a tag and length-prefixed bytes. | |
| 113 | pub fn tagBytes(self: *Encoder, tag_: Tag, bytes: []const u8) !void { | |
| 114 | try self.buffer.prependSlice(bytes); | |
| 115 | try self.length(bytes.len); | |
| 116 | try self.tag(tag_); | |
| 117 | } | |
| 118 | ||
| 115 | 119 | /// Warning: This writer writes backwards. `fn print` will NOT work as expected. |
| 116 | 120 | pub fn writer(self: *Encoder) ArrayListReverse.Writer { |
| 117 | 121 | return self.buffer.writer(); |