tlv v0.1.0 TLV
Provides functions to decode, encode and work with ASN.1 BER-TLV structures. It supports tags encoded on multiple bytes, length encoded on multiple bytes, indefinite length and both primitive and constructed TLVs.
Summary
Types
Represents a BER-TLV structure. The tag
is represented as an integer and header bits are not separated from the tag.
This is to accomodate common usages of the encoding. Primitive TLVs have a binary value
, while constructed have
a list of TLVs. The indefinite_length
field is set by the decoder to reflect the original byte representation and
also serves as instruction to the encoder on how to encode the length
Functions
Decodes (recursively) the first binary encoded TLV in the given binary and returns a tuple with the parsed TLV
structure and the remaining data as a binary in the form {parsed_tlv, remaining_data}
. On error it returns the atom
:no_tlv
Encodes (recursively) the given TLV structure and returns its binary representation according to the BER-TLV specifications
Types
t :: %TLV{indefinite_length: boolean, tag: integer, value: binary | [TLV.t]}
Represents a BER-TLV structure. The tag
is represented as an integer and header bits are not separated from the tag.
This is to accomodate common usages of the encoding. Primitive TLVs have a binary value
, while constructed have
a list of TLVs. The indefinite_length
field is set by the decoder to reflect the original byte representation and
also serves as instruction to the encoder on how to encode the length.
Functions
Specs
decode(binary) :: {TLV.t, binary} | :no_tlv
Decodes (recursively) the first binary encoded TLV in the given binary and returns a tuple with the parsed TLV
structure and the remaining data as a binary in the form {parsed_tlv, remaining_data}
. On error it returns the atom
:no_tlv
.
The decoder tolerates lengths encoded on more bytes than strictly needed, although the ASN.1 specification require encoders to always generate the shortest possible encoding.
Examples
# Primitive TLV + data after its end
iex> TLV.decode(<<0x80, 0x02, 0xCA, 0xFE, 0xAA, 0xBB>>)
{%TLV{indefinite_length: false, tag: 0x80, value: <<0xCA, 0xFE>>}, <<0xAA, 0xBB>>}
# Constructed TLV
iex> TLV.decode(<<0xE0, 0x03, 0x80, 0x01, 0xAA>>)
{%TLV{indefinite_length: false, tag: 0xE0, value:
[%TLV{indefinite_length: false, tag: 0x80, value: <<0xAA>>}]
}, ""}
# Malformed TLV
iex> TLV.decode(<<0x80, 0x02, 0x00>>)
:no_tlv
Specs
encode(TLV.t) :: binary
Encodes (recursively) the given TLV structure and returns its binary representation according to the BER-TLV specifications.
If indefinite_length
is set to true
and the TLV is a constructed one, indefinite length encoding will be use. For
primitive TLVs this field will be ignored, since for primitive TLVs only definite length is allowed.
The primitive/constructed bit of the tag
field will not be checked for consistency with the value
field.
Examples
# Primitive TLV
iex> TLV.encode(%TLV{tag: 0x80, value: <<0xAA, 0xBB>>})
<<0x80, 0x02, 0xAA, 0xBB>>
# Constructed TLV
iex> TLV.encode(%TLV{tag: 0xE0, value: [%TLV{tag: 0x80, value: <<0xAA>>}]})
<<0xE0, 0x03, 0x80, 0x01, 0xAA>>