| 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,7 +123,8 @@ fn encodedLen(dot_notation: []const u8) usize { |
| 123 | return oid.encoded.len; | 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 | @setEvalBranchQuota(4000); | 128 | @setEvalBranchQuota(4000); |
| 128 | comptime var buf: [256]u8 = undefined; | 129 | comptime var buf: [256]u8 = undefined; |
| 129 | const oid = comptime fromDot(dot_notation, &buf) catch unreachable; | 130 | const oid = comptime fromDot(dot_notation, &buf) catch unreachable; |
| ... | @@ -137,6 +138,11 @@ test encodeComptime { | ... | @@ -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 | /// Maps of: | 146 | /// Maps of: |
| 141 | /// - Oid -> enum | 147 | /// - Oid -> enum |
| 142 | /// - Enum -> oid | 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,6 +23,32 @@ pub fn encode(allocator: std.mem.Allocator, value: anytype) ![]u8 { |
| 23 | return try encoder.buffer.toOwnedSlice(); | 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 | test { | 52 | test { |
| 27 | _ = Decoder; | 53 | _ = Decoder; |
| 28 | _ = Encoder; | 54 | _ = Encoder; |
lib/std/crypto/asn1/der/Decoder.zig+8-1| ... | @@ -13,6 +13,7 @@ index: Index = 0, | ... | @@ -13,6 +13,7 @@ index: Index = 0, |
| 13 | /// This is needed because we might visit an implicitly tagged container with a `fn decodeDer`. | 13 | /// This is needed because we might visit an implicitly tagged container with a `fn decodeDer`. |
| 14 | field_tag: ?FieldTag = null, | 14 | field_tag: ?FieldTag = null, |
| 15 | 15 | ||
| 16 | /// Expect a value. | ||
| 16 | pub fn any(self: *Decoder, comptime T: type) !T { | 17 | pub fn any(self: *Decoder, comptime T: type) !T { |
| 17 | if (std.meta.hasFn(T, "decodeDer")) return try T.decodeDer(self); | 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,11 +81,16 @@ pub fn any(self: *Decoder, comptime T: type) !T { |
| 80 | } | 81 | } |
| 81 | } | 82 | } |
| 82 | 83 | ||
| 84 | //// Expect a sequence. | ||
| 83 | pub fn sequence(self: *Decoder) !Element { | 85 | pub fn sequence(self: *Decoder) !Element { |
| 84 | return try self.element(ExpectedTag.init(.sequence, true, .universal)); | 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 | if (self.index >= self.bytes.len) return error.EndOfStream; | 94 | if (self.index >= self.bytes.len) return error.EndOfStream; |
| 89 | 95 | ||
| 90 | const res = try Element.decode(self.bytes, self.index); | 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,6 +107,7 @@ pub fn element(self: *Decoder, expected: ExpectedTag) (error{ EndOfStream, Unexp |
| 101 | return res; | 107 | return res; |
| 102 | } | 108 | } |
| 103 | 109 | ||
| 110 | /// View of element bytes. | ||
| 104 | pub fn view(self: Decoder, elem: Element) []const u8 { | 111 | pub fn view(self: Decoder, elem: Element) []const u8 { |
| 105 | return elem.slice.view(self.bytes); | 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,6 +15,7 @@ pub fn deinit(self: *Encoder) void { |
| 15 | self.buffer.deinit(); | 15 | self.buffer.deinit(); |
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | /// Encode any value. | ||
| 18 | pub fn any(self: *Encoder, val: anytype) !void { | 19 | pub fn any(self: *Encoder, val: anytype) !void { |
| 19 | const T = @TypeOf(val); | 20 | const T = @TypeOf(val); |
| 20 | try self.anyTag(Tag.fromZig(T), val); | 21 | try self.anyTag(Tag.fromZig(T), val); |
| ... | @@ -74,17 +75,12 @@ fn anyTag(self: *Encoder, tag_: Tag, val: anytype) !void { | ... | @@ -74,17 +75,12 @@ fn anyTag(self: *Encoder, tag_: Tag, val: anytype) !void { |
| 74 | try self.tag(merged_tag); | 75 | try self.tag(merged_tag); |
| 75 | } | 76 | } |
| 76 | 77 | ||
| 78 | /// Encode a tag. | ||
| 77 | pub fn tag(self: *Encoder, tag_: Tag) !void { | 79 | pub fn tag(self: *Encoder, tag_: Tag) !void { |
| 78 | const t = self.mergedTag(tag_); | 80 | const t = self.mergedTag(tag_); |
| 79 | try t.encode(self.writer()); | 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 | fn mergedTag(self: *Encoder, tag_: Tag) Tag { | 84 | fn mergedTag(self: *Encoder, tag_: Tag) Tag { |
| 89 | var res = tag_; | 85 | var res = tag_; |
| 90 | if (self.field_tag) |ft| { | 86 | if (self.field_tag) |ft| { |
| ... | @@ -96,6 +92,7 @@ fn mergedTag(self: *Encoder, tag_: Tag) Tag { | ... | @@ -96,6 +92,7 @@ fn mergedTag(self: *Encoder, tag_: Tag) Tag { |
| 96 | return res; | 92 | return res; |
| 97 | } | 93 | } |
| 98 | 94 | ||
| 95 | /// Encode a length. | ||
| 99 | pub fn length(self: *Encoder, len: usize) !void { | 96 | pub fn length(self: *Encoder, len: usize) !void { |
| 100 | const writer_ = self.writer(); | 97 | const writer_ = self.writer(); |
| 101 | if (len < 128) { | 98 | if (len < 128) { |
| ... | @@ -112,6 +109,13 @@ pub fn length(self: *Encoder, len: usize) !void { | ... | @@ -112,6 +109,13 @@ pub fn length(self: *Encoder, len: usize) !void { |
| 112 | return error.InvalidLength; | 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 | /// Warning: This writer writes backwards. `fn print` will NOT work as expected. | 119 | /// Warning: This writer writes backwards. `fn print` will NOT work as expected. |
| 116 | pub fn writer(self: *Encoder) ArrayListReverse.Writer { | 120 | pub fn writer(self: *Encoder) ArrayListReverse.Writer { |
| 117 | return self.buffer.writer(); | 121 | return self.buffer.writer(); |