OBER_READ_ELEMENTS(3)

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
libutil
#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 calling ober_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
-nosplit 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:

1.  Only the definite form of length encoding shall be used, encoded in the minimum number of octets.
2.  For bitstring, octetstring and restricted character string types, the constructed form of encoding shall not be used.
3.  If a boolean encoding represents the boolean value TRUE, its single contents octet shall have all eight bits set to one.
4.  Each unused bit in the final octet of the encoding of a bit string value shall be set to zero.
5.  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.