NAME
ober_set_readbuf
,
ober_set_application
,
ober_read_elements
,
ober_get_writebuf
,
ober_write_elements
,
ober_free
—
encode and decode ASN.1 with Basic
Encoding Rules
SYNOPSIS
#include
<sys/types.h>
#include <ber.h>
void
ober_set_readbuf
(struct
ber *ber, void
*buf, size_t
len);
void
ober_set_application
(struct ber
*ber, unsigned int (*cb)(struct ber_element
*));
struct ber_element *
ober_read_elements
(struct
ber *ber, struct
ber_element *root);
ssize_t
ober_get_writebuf
(struct
ber *ber, void
**buf);
ssize_t
ober_write_elements
(struct
ber *ber, struct
ber_element *root);
void
ober_free
(struct
ber *ber);
DESCRIPTION
The BER API provides a mechanism to read and write ASN.1 using the Basic Encoding Rules.
Encoded BER is stored in the following structure:
struct ber { off_t br_offs; u_char *br_wbuf; u_char *br_wptr; u_char *br_wend; u_char *br_rbuf; u_char *br_rptr; u_char *br_rend; unsigned int (*br_application)(struct ber_element *); };
br_rbuf and br_wbuf are the read and write buffers for a BER byte stream. These buffers are used when reading an existing byte stream (e.g. received from a TLS connection), or when writing a new byte stream in preparation for subsequent operations performed by the calling application (e.g. network transmission or export to a file).
Intermediary storage of BER elements during encoding and decoding uses the following structure:
struct ber_element { struct ber_element *be_next; unsigned int be_type; unsigned int be_encoding; size_t be_len; off_t be_offs; int be_free; u_int8_t be_class; void (*be_cb)(void *, size_t); void *be_cbarg; union { struct ber_element *bv_sub; void *bv_val; long long bv_numeric; } be_union; #define be_sub be_union.bv_sub #define be_val be_union.bv_val #define be_numeric be_union.bv_numeric };
ober_set_readbuf
()
sets br_rbuf to point an input buffer of BER encoded
bytes in preparation for decoding. It is assumed that
br_rbuf is already populated and available to the
application, commonly obtained by
read(2),
recv(2), or
tls_read(3).
ober_read_elements
()
may then be called to parse, validate, and store the
ber data stream into its constituent
ber_element parts for subsequent processing. The
calling application must have explicit knowledge of the expected data types
in order for correct decoding.
ober_get_writebuf
()
sets br_wbuf to point to an output buffer for writing
a BER byte stream.
ober_write_elements
()
encodes root into a compliant BER byte stream which is
written to ber for subsequent use by the calling
functions such as send(2), write(2), or tls_write(3).
ober_free
()
frees any dynamically allocated storage associated with
ber.
RETURN VALUES
ober_read_elements
() returns a pointer to
a fully populated list of one or more ber_element
structures. Otherwise -1 is returned and the global variable
errno is set to indicate the error.
ober_get_writebuf
() returns the number of
bytes contained within the buffer buf or -1 on
failure.
ober_write_elements
() returns the number
of bytes written. Otherwise -1 is returned and the global variable
errno is set to ENOMEM
.
ERRORS
ober_read_elements
() will fail if:
- [
ENOMEM
] - No memory was available to create the full ber_element structure list.
- [
ENOBUFS
] ober_read_elements
() was called before callingober_set_readbuf
().- [
ECANCELED
] - buf does not contain enough data to complete the unpacking.
- [
EINVAL
] - buf does not contain a valid BER data structure.
- [
ERANGE
] - One of the values in the structure is larger than the library can unpack.
SEE ALSO
read(2), recv(2), send(2), write(2), ober_add_string(3), ober_get_string(3), ober_oid_cmp(3), ober_set_header(3), tls_read(3)
STANDARDS
ITU-T Recommendation X.690, also known as ISO/IEC 8825-1: Information technology - ASN.1 encoding rules.
HISTORY
These functions first appeared as internal functions in snmpd(8) in OpenBSD 4.2 and were moved to libutil in OpenBSD 6.6.
AUTHORS
The BER library was written by Claudio Jeker <claudio@openbsd.org>, Marc Balmer <marc@openbsd.org> and Reyk Floeter <reyk@openbsd.org>.
CAVEATS
The BER API is subject to the following restrictions which are common to the Distinguished Encoding Rules as defined by X.690:
- Only the definite form of length encoding shall be used, encoded in the minimum number of octets.
- For bitstring, octetstring and restricted character string types, the constructed form of encoding shall not be used.
- If a boolean encoding represents the boolean value TRUE, its single contents octet shall have all eight bits set to one.
- Each unused bit in the final octet of the encoding of a bit string value shall be set to zero.
- If a bitstring value has no 1 bits, then an encoder shall encode the value with a length of 1 and an initial octet set to 0.
In addition, set and sequence values are limited to a maximum of 65535 elements. No alternative encodings are permitted.
“Whereas the basic encoding rules give the sender of an encoding various choices as to how data values may be encoded, the canonical and distinguished encoding rules select just one encoding from those allowed by the basic encoding rules.” [X.690]
The restrictions placed on this API avoid the ambiguity inherent in BER encoded ASN.1 thereby acting as a security mitigation.