structstd.crypto.asn1.Element[src]

A decoded view.

Fields

tag: Tag
slice: Slice

Error Sets

Error SetDecodeError[src]

Errors

anyerror means the error set is known only at runtime.

EndOfStream
InvalidLength

Source Code

Source code
pub const DecodeError = error{ InvalidLength, EndOfStream }

Functions

Functiondecode[src]

pub fn decode(bytes: []const u8, index: Index) DecodeError!Element

Safely decode a DER/BER/CER element at index:

  • Ensures length uses shortest form
  • Ensures length is within bytes
  • Ensures length is less than std.math.maxInt(Index)

Parameters

bytes: []const u8
index: Index

Source Code

Source code
pub fn decode(bytes: []const u8, index: Index) DecodeError!Element {
    var stream = std.io.fixedBufferStream(bytes[index..]);
    var reader = stream.reader();

    const tag = try Tag.decode(reader);
    const size_or_len_size = try reader.readByte();

    var start = index + 2;
    var end = start + size_or_len_size;
    // short form between 0-127
    if (size_or_len_size < 128) {
        if (end > bytes.len) return error.InvalidLength;
    } else {
        // long form between 0 and std.math.maxInt(u1024)
        const len_size: u7 = @truncate(size_or_len_size);
        start += len_size;
        if (len_size > @sizeOf(Index)) return error.InvalidLength;

        const len = try reader.readVarInt(Index, .big, len_size);
        if (len < 128) return error.InvalidLength; // should have used short form

        end = std.math.add(Index, start, len) catch return error.InvalidLength;
        if (end > bytes.len) return error.InvalidLength;
    }

    return Element{ .tag = tag, .slice = Slice{ .start = start, .end = end } };
}

Source Code

Source code
pub const Element = struct {
    tag: Tag,
    slice: Slice,

    pub const Slice = struct {
        start: Index,
        end: Index,

        pub fn len(self: Slice) Index {
            return self.end - self.start;
        }

        pub fn view(self: Slice, bytes: []const u8) []const u8 {
            return bytes[self.start..self.end];
        }
    };

    pub const DecodeError = error{ InvalidLength, EndOfStream };

    /// Safely decode a DER/BER/CER element at `index`:
    /// - Ensures length uses shortest form
    /// - Ensures length is within `bytes`
    /// - Ensures length is less than `std.math.maxInt(Index)`
    pub fn decode(bytes: []const u8, index: Index) DecodeError!Element {
        var stream = std.io.fixedBufferStream(bytes[index..]);
        var reader = stream.reader();

        const tag = try Tag.decode(reader);
        const size_or_len_size = try reader.readByte();

        var start = index + 2;
        var end = start + size_or_len_size;
        // short form between 0-127
        if (size_or_len_size < 128) {
            if (end > bytes.len) return error.InvalidLength;
        } else {
            // long form between 0 and std.math.maxInt(u1024)
            const len_size: u7 = @truncate(size_or_len_size);
            start += len_size;
            if (len_size > @sizeOf(Index)) return error.InvalidLength;

            const len = try reader.readVarInt(Index, .big, len_size);
            if (len < 128) return error.InvalidLength; // should have used short form

            end = std.math.add(Index, start, len) catch return error.InvalidLength;
            if (end > bytes.len) return error.InvalidLength;
        }

        return Element{ .tag = tag, .slice = Slice{ .start = start, .end = end } };
    }
}