| ... | ... | @@ -73,13 +73,13 @@ pub const Tag = struct { |
| 73 | 73 | const tag1: FirstTag = @bitCast(try reader.takeByte()); |
| 74 | 74 | var number: u14 = tag1.number; |
| 75 | 75 | |
| 76 | | if (tag1.number == 15) { |
| 76 | if (tag1.number == 31) { |
| 77 | 77 | const tag2: NextTag = @bitCast(try reader.takeByte()); |
| 78 | 78 | number = tag2.number; |
| 79 | 79 | if (tag2.continues) { |
| 80 | 80 | const tag3: NextTag = @bitCast(try reader.takeByte()); |
| 81 | 81 | number = (number << 7) + tag3.number; |
| 82 | | if (tag3.continues) return error.InvalidLength; |
| 82 | if (tag3.continues) return error.EndOfStream; |
| 83 | 83 | } |
| 84 | 84 | } |
| 85 | 85 | |
| ... | ... | @@ -183,7 +183,7 @@ pub const Element = struct { |
| 183 | 183 | } |
| 184 | 184 | }; |
| 185 | 185 | |
| 186 | | pub const DecodeError = error{ InvalidLength, EndOfStream }; |
| 186 | pub const DecodeError = error{EndOfStream}; |
| 187 | 187 | |
| 188 | 188 | /// Safely decode a DER/BER/CER element at `index`: |
| 189 | 189 | /// - Ensures length uses shortest form |
| ... | ... | @@ -192,26 +192,35 @@ pub const Element = struct { |
| 192 | 192 | pub fn decode(bytes: []const u8, index: Index) DecodeError!Element { |
| 193 | 193 | var reader: std.Io.Reader = .fixed(bytes[index..]); |
| 194 | 194 | |
| 195 | | const tag = try Tag.decode(&reader); |
| 196 | | const size_or_len_size = try reader.takeByte(); |
| 195 | const tag = Tag.decode(&reader) catch |err| switch (err) { |
| 196 | error.ReadFailed => unreachable, // it's all fixed buffers |
| 197 | else => |e| return e, |
| 198 | }; |
| 199 | const size_or_len_size = reader.takeByte() catch |err| switch (err) { |
| 200 | error.ReadFailed => unreachable, // it's all fixed buffers |
| 201 | else => |e| return e, |
| 202 | }; |
| 197 | 203 | |
| 198 | | var start = index + 2; |
| 199 | | var end = start + size_or_len_size; |
| 200 | | // short form between 0-127 |
| 201 | | if (size_or_len_size < 128) { |
| 202 | | if (end > bytes.len) return error.InvalidLength; |
| 203 | | } else { |
| 204 | const len = if (size_or_len_size < 128) |
| 205 | // short form between 0-127 |
| 206 | size_or_len_size |
| 207 | else blk: { |
| 204 | 208 | // long form between 0 and std.math.maxInt(u1024) |
| 205 | 209 | const len_size: u7 = @truncate(size_or_len_size); |
| 206 | | start += len_size; |
| 207 | | if (len_size > @sizeOf(Index)) return error.InvalidLength; |
| 210 | if (len_size > @sizeOf(Index)) return error.EndOfStream; |
| 208 | 211 | |
| 209 | | const len = try reader.takeVarInt(Index, .big, len_size); |
| 210 | | if (len < 128) return error.InvalidLength; // should have used short form |
| 212 | const len = reader.takeVarInt(Index, .big, len_size) catch |err| switch (err) { |
| 213 | error.ReadFailed => unreachable, // it's all fixed buffers |
| 214 | else => |e| return e, |
| 215 | }; |
| 216 | if (len < 128) return error.EndOfStream; // should have used short form |
| 211 | 217 | |
| 212 | | end = std.math.add(Index, start, len) catch return error.InvalidLength; |
| 213 | | if (end > bytes.len) return error.InvalidLength; |
| 214 | | } |
| 218 | break :blk len; |
| 219 | }; |
| 220 | |
| 221 | const start = index + @as(Index, @intCast(reader.seek)); |
| 222 | const end = std.math.add(Index, start, len) catch return error.EndOfStream; |
| 223 | if (end > bytes.len) return error.EndOfStream; |
| 215 | 224 | |
| 216 | 225 | return Element{ .tag = tag, .slice = Slice{ .start = start, .end = end } }; |
| 217 | 226 | } |
| ... | ... | @@ -229,6 +238,12 @@ test Element { |
| 229 | 238 | .tag = Tag.universal(.sequence, true), |
| 230 | 239 | .slice = Element.Slice{ .start = 3, .end = long_form.len }, |
| 231 | 240 | }, Element.decode(&long_form, 0)); |
| 241 | |
| 242 | const multi_byte_tag = [_]u8{ 0x1F, 0x20, 0x08, 0x30, 0x36, 0x3A, 0x32, 0x37, 0x3A, 0x31, 0x35 }; |
| 243 | try std.testing.expectEqual(Element{ |
| 244 | .tag = Tag.universal(.time_of_day, false), |
| 245 | .slice = Element.Slice{ .start = 3, .end = multi_byte_tag.len }, |
| 246 | }, Element.decode(&multi_byte_tag, 0)); |
| 232 | 247 | } |
| 233 | 248 | |
| 234 | 249 | /// For decoding. |