summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrob <rob@cvs.openbsd.org>2019-05-15 03:11:53 +0000
committerrob <rob@cvs.openbsd.org>2019-05-15 03:11:53 +0000
commitfe363846e01a212234cfb461bca7b86843898477 (patch)
treed7ecad90374dd33ae39a58ec9318c937215b2621
parent38f09fdd5eb8706715549291980c3b0f7b3dece7 (diff)
Split ber.3 into logical parts. Further tweaking will be done in tree.
Discussed with and ok jmc@, schwarze@, claudio@
-rw-r--r--lib/libutil/Makefile6
-rw-r--r--lib/libutil/ber.3454
-rw-r--r--lib/libutil/ber_add_string.3167
-rw-r--r--lib/libutil/ber_get_string.3120
-rw-r--r--lib/libutil/ber_oid_cmp.3109
-rw-r--r--lib/libutil/ber_read_elements.3225
-rw-r--r--lib/libutil/ber_set_header.3144
7 files changed, 769 insertions, 456 deletions
diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile
index e643be436a5..7517436497a 100644
--- a/lib/libutil/Makefile
+++ b/lib/libutil/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.41 2019/05/11 17:46:02 rob Exp $
+# $OpenBSD: Makefile,v 1.42 2019/05/15 03:11:52 rob Exp $
# $NetBSD: Makefile,v 1.8 1996/05/16 07:03:28 thorpej Exp $
LIB= util
@@ -12,7 +12,9 @@ SRCS= bcrypt_pbkdf.c ber.c check_expire.c duid.c getmaxpartitions.c \
login_fbtab.c uucplock.c fparseln.c opendisk.c pidfile.c \
fmt_scaled.c imsg.c imsg-buffer.c pkcs5_pbkdf2.c
-MAN= bcrypt_pbkdf.3 ber.3 check_expire.3 getmaxpartitions.3 \
+MAN= bcrypt_pbkdf.3 ber_add_string.3 ber_get_string.3 ber_oid_cmp.3 \
+ ber_read_elements.3 ber_set_header.3 \
+ check_expire.3 getmaxpartitions.3 \
getrawpartition.3 \
isduid.3 login.3 \
opendev.3 openpty.3 pw_init.3 pw_lock.3 readlabelfs.3 uucplock.3 \
diff --git a/lib/libutil/ber.3 b/lib/libutil/ber.3
deleted file mode 100644
index ad6978ec929..00000000000
--- a/lib/libutil/ber.3
+++ /dev/null
@@ -1,454 +0,0 @@
-.\" $OpenBSD: ber.3,v 1.2 2019/05/12 19:29:41 rob Exp $
-.\"
-.\" Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org>
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd $Mdocdate: May 12 2019 $
-.Dt BER 3
-.Os
-.Sh NAME
-.Nm ber_get_element ,
-.Nm ber_set_header ,
-.Nm ber_link_elements ,
-.Nm ber_unlink_elements ,
-.Nm ber_replace_elements ,
-.Nm ber_add_sequence ,
-.Nm ber_add_set ,
-.Nm ber_add_enumerated ,
-.Nm ber_add_integer ,
-.Nm ber_get_integer ,
-.Nm ber_get_enumerated ,
-.Nm ber_add_boolean ,
-.Nm ber_get_boolean ,
-.Nm ber_add_string ,
-.Nm ber_add_nstring ,
-.Nm ber_add_ostring ,
-.Nm ber_add_bitstring ,
-.Nm ber_get_string ,
-.Nm ber_get_nstring ,
-.Nm ber_get_ostring ,
-.Nm ber_get_bitstring ,
-.Nm ber_add_null ,
-.Nm ber_get_null ,
-.Nm ber_add_eoc ,
-.Nm ber_get_eoc ,
-.Nm ber_add_oid ,
-.Nm ber_add_noid ,
-.Nm ber_add_oidstring ,
-.Nm ber_get_oid ,
-.Nm ber_oid2ber ,
-.Nm ber_string2oid ,
-.Nm ber_oid_cmp ,
-.Nm ber_printf_elements ,
-.Nm ber_scanf_elements ,
-.Nm ber_get_writebuf ,
-.Nm ber_write_elements ,
-.Nm ber_set_readbuf ,
-.Nm ber_read_elements ,
-.Nm ber_getpos ,
-.Nm ber_free_element ,
-.Nm ber_free_elements ,
-.Nm ber_calc_len ,
-.Nm ber_set_application ,
-.Nm ber_set_writecallback ,
-.Nm ber_free
-.Nd encode and decode ASN.1 with Basic Encoding Rules
-.Sh SYNOPSIS
-.In sys/types.h
-.In ber.h
-.Ft "struct ber_element *"
-.Fn "ber_get_element" "unsigned int encoding"
-.Ft "void"
-.Fn "ber_set_header" "struct ber_element *elm" "int class" "unsigned int type"
-.Ft "void"
-.Fn "ber_link_elements" "struct ber_element *prev" "struct ber_element *elm"
-.Ft "struct ber_element *"
-.Fn "ber_unlink_elements" "struct ber_element *prev"
-.Ft "void"
-.Fn "ber_replace_elements" "struct ber_element *prev" "struct ber_element *elm"
-.Ft "struct ber_element *"
-.Fn "ber_add_sequence" "struct ber_element *prev"
-.Ft "struct ber_element *"
-.Fn "ber_add_set" "struct ber_element *prev"
-.Ft "struct ber_element *"
-.Fn "ber_add_integer" "struct ber_element *prev" "long long val"
-.Ft "int"
-.Fn "ber_get_integer" "struct ber_element *root" "long long *val"
-.Ft "struct ber_element *"
-.Fn "ber_add_enumerated" "struct ber_element *prev" "long long val"
-.Ft "int"
-.Fn "ber_get_enumerated" "struct ber_element *root" "long long *val"
-.Ft "struct ber_element *"
-.Fn "ber_add_boolean" "struct ber_element *prev" "int bool"
-.Ft "int"
-.Fn "ber_get_boolean" "struct ber_element *root" "int *bool"
-.Ft "struct ber_element *"
-.Fn "ber_add_string" "struct ber_element *prev" "const char *string"
-.Ft "struct ber_element *"
-.Fn "ber_add_nstring" "struct ber_element *prev" "const char *string" "size_t size"
-.Ft "struct ber_element *"
-.Fo "ber_add_ostring"
-.Fa "struct ber_element *prev"
-.Fa "struct ber_octetstring *ostring"
-.Fc
-.Ft "int"
-.Fn "ber_get_string" "struct ber_element *root" "char **charbuf"
-.Ft "int"
-.Fn "ber_get_nstring" "struct ber_element *root" "void **buf" "size_t *size"
-.Ft "int"
-.Fn "ber_get_ostring" "struct ber_element *root" "struct ber_octetstring *ostring"
-.Ft "struct ber_element *"
-.Fo "ber_add_bitstring"
-.Fa "struct ber_element *prev"
-.Fa "const void *buf"
-.Fa "size_t size"
-.Fc
-.Ft "int"
-.Fn "ber_get_bitstring" "struct ber_element *root" "void **buf" "size_t *size"
-.Ft "struct ber_element *"
-.Fn "ber_add_null" "struct ber_element *prev"
-.Ft "int"
-.Fn "ber_get_null" "struct ber_element *root"
-.Ft "struct ber_element *"
-.Fn "ber_add_eoc" "struct ber_element *prev"
-.Ft "int"
-.Fn "ber_get_eoc" "struct ber_element *root"
-.Ft "struct ber_element *"
-.Fn "ber_add_oid" "struct ber_element *prev" "struct ber_oid *oid"
-.Ft "struct ber_element *"
-.Fn "ber_add_noid" "struct ber_element *prev" "struct ber_oid *oid" "int n"
-.Ft "struct ber_element *"
-.Fn "ber_add_oidstring" "struct ber_element *prev" "const char *string"
-.Ft "int"
-.Fn "ber_get_oid" "struct ber_element *root" "struct ber_oid *oid"
-.Ft "size_t"
-.Fn "ber_oid2ber" "struct ber_oid *oid" "u_int8_t *buf" "size_t size"
-.Ft "int"
-.Fn "ber_string2oid" "const char *string" "struct ber_oid *oid"
-.Ft "int"
-.Fn "ber_oid_cmp" "struct ber_oid *oid" "struct ber_oid *oid"
-.Ft "struct ber_element *"
-.Fn "ber_printf_elements" "struct ber_element *prev" "char *format" "..."
-.Ft "int"
-.Fn "ber_scanf_elements" "struct ber_element *root" "char *format" "..."
-.Ft "ssize_t"
-.Fn "ber_get_writebuf" "struct ber *ber" "void **buf"
-.Ft "ssize_t"
-.Fn "ber_write_elements" "struct ber *ber" "struct ber_element *root"
-.Ft "void"
-.Fn "ber_set_readbuf" "struct ber *ber" "void *buf" "size_t len"
-.Ft "struct ber_element *"
-.Fn "ber_read_elements" "struct ber *ber" "struct ber_element *root"
-.Ft off_t
-.Fn "ber_getpos" "struct ber_element *elm"
-.Ft "void"
-.Fn "ber_free_element" "struct ber_element *root"
-.Ft "void"
-.Fn "ber_free_elements" "struct ber_element *root"
-.Ft "size_t"
-.Fn "ber_calc_len" "struct ber_element *root"
-.Ft "void"
-.Fo "ber_set_application"
-.Fa "struct ber *ber"
-.Fa "unsigned int (*cb)(struct ber_element *)"
-.Fc
-.Ft "void"
-.Fo "ber_set_writecallback"
-.Fa "struct ber_element *elm"
-.Fa "void (*cb)(void *arg, size_t offs)"
-.Fa "void *arg"
-.Fc
-.Ft "void"
-.Fn "ber_free" "struct ber *ber"
-.Sh DESCRIPTION
-The
-.Nm ber
-API provides a mechanism to read and write ASN.1 streams and buffers using the
-Basic Encoding Rules.
-.Pp
-Encoded
-.Nm ber
-is stored in the following structure:
-.Bd -literal
-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 *);
-};
-.Ed
-.Pp
-.Fa br_rbuf
-and
-.Fa br_wbuf
-are the read and write buffers for a
-.Nm ber
-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).
-.Pp
-Intermediary storage of ber elements during decoding and encoding uses the
-following structure:
-.Bd -literal
-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
-};
-.Ed
-.Pp
-A linked list containing one or more
-.Vt ber_element
-is created during the decoding and encoding of
-.Vt ber .
-.Pp
-Once the
-.Vt ber
-and
-.Vt ber_element
-data structures have been declared,
-.Fn ber_set_readbuf
-may be called to initialize
-.Fa br_rbuf
-in preparation for decoding.
-It is assumed that a pointer to a ber byte stream is already available to the
-application, commonly obtained by
-.Xr read 2 ,
-.Xr recv 2 ,
-or
-.Xr tls_read 3 .
-.Fn ber_read_elements
-may then be called to parse, validate, and store the data stream into its
-consituent parts for subsequent processing.
-.Fn ber_read_elements
-returns a pointer to a fully populated list of one or more
-.Vt ber_element ,
-or
-.Dv NULL
-on a type mismatch or read error.
-.Pp
-The calling application must have explicit knowledge of the expected data
-types in order for correct decoding.
-.Fn ber_scanf_elements
-may be called to extract
-.Vt ber_element
-content into local variables.
-The
-.Fn ber_get_*
-functions extract the value of a single
-.Vt ber_element
-instance.
-.Fn ber_scanf_elements
-and the
-.Fn ber_get_*
-functions return 0 on success and -1 on failure.
-.Pp
-The first step when creating new ber is to populate
-.Vt ber_element
-with the desired content.
-This may be achieved using the
-.Fn ber_add_*
-and
-.Fn ber_printf_elements
-functions, each of which return a pointer to
-.Vt ber_element
-on success or
-.Dv NULL
-on failure.
-.Pp
-Once
-.Vt ber_element
-has been fully populated,
-.Fn ber_get_writebuf
-may be used to initialize
-.Fa br_wbuf
-for writing.
-.Fn ber_write_elements
-encodes
-.Vt ber_element
-into a compliant
-.Nm ber
-byte stream for subsequent use by the calling application, most commonly using
-.Xr send 2 ,
-.Xr write 2 ,
-or
-.Xr tls_write 3 .
-.Sh I/O OPERATIONS
-.Fn ber_get_writebuf ,
-.Fn ber_write_elements ,
-.Fn ber_set_readbuf ,
-.Fn ber_read_elements ,
-.Fn ber_getpos ,
-.Fn ber_free_element ,
-.Fn ber_free_elements ,
-.Fn ber_set_application ,
-.Fn ber_set_writecallback ,
-.Fn ber_free
-.Sh BER ELEMENTS
-.Fn ber_get_element ,
-.Fn ber_set_header ,
-.Fn ber_link_elements ,
-.Fn ber_unlink_elements ,
-.Fn ber_replace_elements ,
-.Fn ber_calc_len
-.Sh BER TYPES
-.Fn ber_add_sequence ,
-.Fn ber_add_set ,
-.Fn ber_add_integer ,
-.Fn ber_get_integer ,
-.Fn ber_add_enumerated ,
-.Fn ber_get_enumerated ,
-.Fn ber_add_boolean ,
-.Fn ber_get_boolean ,
-.Fn ber_add_string ,
-.Fn ber_add_nstring ,
-.Fn ber_add_ostring ,
-.Fn ber_add_bitstring ,
-.Fn ber_get_string ,
-.Fn ber_get_nstring ,
-.Fn ber_get_ostring ,
-.Fn ber_get_bitstring ,
-.Fn ber_add_null ,
-.Fn ber_get_null ,
-.Fn ber_add_eoc ,
-.Fn ber_get_eoc
-.Sh FORMAT STRINGS
-.Fn ber_printf_elements ,
-.Fn ber_scanf_elements
-.Sh OBJECT IDS
-Object Identifiers are commonly used in ASN.1-based protocols.
-These functions provide an interface to parse OIDs.
-For internal representation of OIDs, the following structure
-.Vt struct ber_oid
-is being used:
-.Bd -literal
-#define BER_MIN_OID_LEN 2
-#define BER_MAX_OID_LEN 32
-
-struct ber_oid {
- u_int32_t bo_id[BER_MAX_OID_LEN + 1];
- size_t bo_n;
-};
-.Ed
-.Pp
-.Fn ber_add_oid ,
-.Fn ber_add_noid ,
-.Fn ber_add_oidstring ,
-.Fn ber_get_oid ,
-.Fn ber_oid2ber ,
-.Fn ber_string2oid
-.Fn ber_oid_cmp ,
-.Sh RETURN VALUES
-Upon successful completion
-.Fn ber_get_integer ,
-.Fn ber_get_enumerated ,
-.Fn ber_get_boolean ,
-.Fn ber_get_string ,
-.Fn ber_get_nstring ,
-.Fn ber_get_ostring ,
-.Fn ber_get_bitstring ,
-.Fn ber_get_null ,
-.Fn ber_get_eoc ,
-.Fn ber_get_oid ,
-.Fn ber_string2oid
-and
-.Fn ber_scanf_elements
-return 0, while
-.Fn ber_write_elements
-returns the number of bytes written.
-Otherwise, \-1 is returned and the global variable errno is
-set to indicate the error.
-.Sh SEE ALSO
-.Xr read 2 ,
-.Xr recv 2 ,
-.Xr send 2 ,
-.Xr write 2 ,
-.Xr tls_read 3
-.Sh STANDARDS
-ITU-T Recommendation X.690, also known as ISO/IEC 8825-1:
-Information technology - ASN.1 encoding rules.
-.Sh HISTORY
-The
-.Nm ber
-manpage first appeared in
-.Ox 4.3 .
-.Sh AUTHORS
-.An -nosplit
-The
-.Nm ber
-library was written by
-.An Claudio Jeker Aq Mt claudio@openbsd.org ,
-.An Marc Balmer Aq Mt marc@openbsd.org
-and
-.An Reyk Floeter Aq Mt reyk@openbsd.org .
-.Sh CAVEATS
-The
-.Nm ber
-API is subject to the following restrictions which are common to the
-Distinguished Encoding Rules as defined by X.690:
-.Pp
-.Bl -enum -compact
-.It
-Only the definite form of length encoding shall be used, encoded in the
-minimum number of octets.
-.It
-For bitstring, octetstring and restricted character string types, the
-constructed form of encoding shall not be used.
-.It
-If a boolean encoding represents the boolean value TRUE, its single contents
-octet shall have all eight bits set to one.
-.It
-Each unused bit in the final octet of the encoding of a bit string value shall
-be set to zero.
-.It
-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.
-.El
-.Pp
-In addition, set and sequence values are limited to a maximum of 65535 elements.
-No alternative encodings are permitted.
-.Pp
-.Do
-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.
-.Dc
-.Bq X.690
-.Pp
-The restrictions placed on this API avoid the ambiguity inherent in
-.Nm ber
-encoded ASN.1 thereby acting as a security mitigation.
-.Sh BUGS
-This manpage is a stub.
diff --git a/lib/libutil/ber_add_string.3 b/lib/libutil/ber_add_string.3
new file mode 100644
index 00000000000..a90c58bac5f
--- /dev/null
+++ b/lib/libutil/ber_add_string.3
@@ -0,0 +1,167 @@
+.\" $OpenBSD: ber_add_string.3,v 1.1 2019/05/15 03:11:52 rob Exp $
+.\"
+.\" Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate: May 15 2019 $
+.Dt BER_ADD_STRING 3
+.Os
+.Sh NAME
+.Nm ber_get_element ,
+.Nm ber_add_sequence ,
+.Nm ber_add_set ,
+.Nm ber_add_null ,
+.Nm ber_add_eoc ,
+.Nm ber_add_integer ,
+.Nm ber_add_enumerated ,
+.Nm ber_add_boolean ,
+.Nm ber_add_string ,
+.Nm ber_add_nstring ,
+.Nm ber_add_ostring ,
+.Nm ber_add_bitstring ,
+.Nm ber_add_oid ,
+.Nm ber_add_noid ,
+.Nm ber_add_oidstring ,
+.Nm ber_printf_elements
+.Nd create ASN.1 objects for BER encoding
+.Sh SYNOPSIS
+.In sys/types.h
+.In ber.h
+.Ft "struct ber_element *"
+.Fn "ber_get_element" "unsigned int encoding"
+.Ft "struct ber_element *"
+.Fn "ber_add_sequence" "struct ber_element *prev"
+.Ft "struct ber_element *"
+.Fn "ber_add_set" "struct ber_element *prev"
+.Ft "struct ber_element *"
+.Fn "ber_add_null" "struct ber_element *prev"
+.Ft "struct ber_element *"
+.Fn "ber_add_eoc" "struct ber_element *prev"
+.Ft "struct ber_element *"
+.Fn "ber_add_integer" "struct ber_element *prev" "long long val"
+.Ft "struct ber_element *"
+.Fn "ber_add_enumerated" "struct ber_element *prev" "long long val"
+.Ft "struct ber_element *"
+.Fn "ber_add_boolean" "struct ber_element *prev" "int bool"
+.Ft "struct ber_element *"
+.Fn "ber_add_string" "struct ber_element *prev" "const char *string"
+.Ft "struct ber_element *"
+.Fn "ber_add_nstring" "struct ber_element *prev" "const char *string" "size_t size"
+.Ft "struct ber_element *"
+.Fo "ber_add_ostring"
+.Fa "struct ber_element *prev"
+.Fa "struct ber_octetstring *ostring"
+.Fc
+.Ft "struct ber_element *"
+.Fo "ber_add_bitstring"
+.Fa "struct ber_element *prev"
+.Fa "const void *buf"
+.Fa "size_t size"
+.Fc
+.Ft "struct ber_element *"
+.Fn "ber_add_oid" "struct ber_element *prev" "struct ber_oid *oid"
+.Ft "struct ber_element *"
+.Fn "ber_add_noid" "struct ber_element *prev" "struct ber_oid *oid" "int n"
+.Ft "struct ber_element *"
+.Fn "ber_add_oidstring" "struct ber_element *prev" "const char *string"
+.Ft "struct ber_element *"
+.Fn "ber_printf_elements" "struct ber_element *prev" "char *format" "..."
+.Sh DESCRIPTION
+Intermediary storage of BER elements during encoding and decoding uses the
+following structure:
+.Bd -literal
+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
+};
+.Ed
+.Pp
+.Fn ber_get_element
+creates a new
+.Vt ber_element
+with default values, dynamically allocates required storage, and sets
+.Fa be_encoding
+to
+.Fa encoding .
+.Pp
+The
+.Fn ber_add_*
+and
+.Fn ber_printf_elements
+functions may be used to populate
+.Vt ber_element .
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn ber_get_element ,
+.Fn ber_add_sequence ,
+.Fn ber_add_set ,
+.Fn ber_add_null ,
+.Fn ber_add_eoc ,
+.Fn ber_add_integer ,
+.Fn ber_add_enumerated ,
+.Fn ber_add_boolean ,
+.Fn ber_add_string ,
+.Fn ber_add_nstring ,
+.Fn ber_add_ostring ,
+.Fn ber_add_bitstring ,
+.Fn ber_add_oid ,
+.Fn ber_add_noid ,
+.Fn ber_add_oidstring ,
+and
+.Fn ber_printf_elements
+return a pointer to a populated
+.Vt ber_element .
+Otherwise
+.Dv NULL
+is returned and the global variable errno is
+set to indicate the error.
+.Sh SEE ALSO
+.Xr ber_get_string 3 ,
+.Xr ber_oid_cmp 3 ,
+.Xr ber_read_elements 3 ,
+.Xr ber_set_header 3
+.Sh STANDARDS
+ITU-T Recommendation X.690, also known as ISO/IEC 8825-1:
+Information technology - ASN.1 encoding rules.
+.Sh HISTORY
+These functions first appeared as internal functions in
+.Xr snmpd 8
+in
+.Ox 4.2
+and were moved to libutil in
+.Ox 6.6 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm ber
+library was written by
+.An Claudio Jeker Aq Mt claudio@openbsd.org ,
+.An Marc Balmer Aq Mt marc@openbsd.org
+and
+.An Reyk Floeter Aq Mt reyk@openbsd.org .
diff --git a/lib/libutil/ber_get_string.3 b/lib/libutil/ber_get_string.3
new file mode 100644
index 00000000000..e48ac4a0847
--- /dev/null
+++ b/lib/libutil/ber_get_string.3
@@ -0,0 +1,120 @@
+.\" $OpenBSD: ber_get_string.3,v 1.1 2019/05/15 03:11:52 rob Exp $
+.\"
+.\" Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate: May 15 2019 $
+.Dt BER_GET_STRING 3
+.Os
+.Sh NAME
+.Nm ber_get_null ,
+.Nm ber_get_eoc ,
+.Nm ber_get_integer ,
+.Nm ber_get_enumerated ,
+.Nm ber_get_boolean ,
+.Nm ber_get_string ,
+.Nm ber_get_nstring ,
+.Nm ber_get_ostring ,
+.Nm ber_get_bitstring ,
+.Nm ber_get_oid ,
+.Nm ber_getpos ,
+.Nm ber_scanf_elements
+.Nd access properties of ASN.1 objects decoded from BER
+.Sh SYNOPSIS
+.In sys/types.h
+.In ber.h
+.Ft "int"
+.Fn "ber_get_null" "struct ber_element *root"
+.Ft "int"
+.Fn "ber_get_eoc" "struct ber_element *root"
+.Ft "int"
+.Fn "ber_get_integer" "struct ber_element *root" "long long *val"
+.Ft "int"
+.Fn "ber_get_enumerated" "struct ber_element *root" "long long *val"
+.Ft "int"
+.Fn "ber_get_boolean" "struct ber_element *root" "int *bool"
+.Ft "int"
+.Fn "ber_get_string" "struct ber_element *root" "char **charbuf"
+.Ft "int"
+.Fn "ber_get_nstring" "struct ber_element *root" "void **buf" "size_t *size"
+.Ft "int"
+.Fn "ber_get_ostring" "struct ber_element *root" "struct ber_octetstring *ostring"
+.Ft "int"
+.Fn "ber_get_bitstring" "struct ber_element *root" "void **buf" "size_t *size"
+.Ft "int"
+.Fn "ber_get_oid" "struct ber_element *root" "struct ber_oid *oid"
+.Ft off_t
+.Fn "ber_getpos" "struct ber_element *elm"
+.Ft "int"
+.Fn "ber_scanf_elements" "struct ber_element *root" "char *format" "..."
+.Sh DESCRIPTION
+The
+.Fn ber_get_*
+and
+.Fn ber_scanf_elements
+functions may be used to save
+.Vt ber_element
+values into local variables.
+.Pp
+.Fn ber_getpos
+may be used to obtain the
+.Vt ber_element
+offset
+.Fa be_offs .
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn ber_get_null ,
+.Fn ber_get_eoc ,
+.Fn ber_get_integer ,
+.Fn ber_get_enumerated ,
+.Fn ber_get_boolean ,
+.Fn ber_get_string ,
+.Fn ber_get_nstring ,
+.Fn ber_get_ostring ,
+.Fn ber_get_bitstring ,
+.Fn ber_get_oid ,
+.Fn ber_string2oid
+and
+.Fn ber_scanf_elements
+return 0.
+Otherwise \-1 is returned and the global variable errno is
+set to indicate the error.
+.Pp
+.Fn ber_getpos
+returns the value of
+.Vt be_offs .
+.Sh SEE ALSO
+.Xr ber_add_string 3 ,
+.Xr ber_oid_cmp 3 ,
+.Xr ber_read_elements 3 ,
+.Xr ber_set_header 3
+.Sh STANDARDS
+ITU-T Recommendation X.690, also known as ISO/IEC 8825-1:
+Information technology - ASN.1 encoding rules.
+.Sh HISTORY
+These functions first appeared as internal functions in
+.Xr snmpd 8
+in
+.Ox 4.2
+and were moved to libutil in
+.Ox 6.6 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm ber
+library was written by
+.An Claudio Jeker Aq Mt claudio@openbsd.org ,
+.An Marc Balmer Aq Mt marc@openbsd.org
+and
+.An Reyk Floeter Aq Mt reyk@openbsd.org .
diff --git a/lib/libutil/ber_oid_cmp.3 b/lib/libutil/ber_oid_cmp.3
new file mode 100644
index 00000000000..6c15da45d95
--- /dev/null
+++ b/lib/libutil/ber_oid_cmp.3
@@ -0,0 +1,109 @@
+.\" $OpenBSD: ber_oid_cmp.3,v 1.1 2019/05/15 03:11:52 rob Exp $
+.\"
+.\" Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate: May 15 2019 $
+.Dt BER_OID_CMP 3
+.Os
+.Sh NAME
+.Nm ber_oid_cmp ,
+.Nm ber_oid2ber ,
+.Nm ber_string2oid
+.Nd OID helper functions for the BER library
+.Sh SYNOPSIS
+.In sys/types.h
+.In ber.h
+.Ft "int"
+.Fn "ber_oid_cmp" "struct ber_oid *a" "struct ber_oid *b"
+.Ft "size_t"
+.Fn "ber_oid2ber" "struct ber_oid *oid" "u_int8_t *buf" "size_t size"
+.Ft "int"
+.Fn "ber_string2oid" "const char *string" "struct ber_oid *oid"
+.Sh DESCRIPTION
+Object Identifiers are commonly used in ASN.1-based protocols.
+These functions provide an interface to parse OIDs.
+For internal representation of OIDs, the following structure
+.Vt struct ber_oid
+is being used:
+.Bd -literal
+#define BER_MIN_OID_LEN 2
+#define BER_MAX_OID_LEN 32
+
+struct ber_oid {
+ u_int32_t bo_id[BER_MAX_OID_LEN + 1];
+ size_t bo_n;
+};
+.Ed
+.Pp
+The
+.Fn ber_oid2ber
+and
+.Fn ber_string2oid
+functions may be used to convert from and to
+.Vt struct ber_oid .
+.Pp
+.Fn ber_oid_cmp
+may be used to compare two
+.Vt ber_oid
+structures.
+.Sh RETURN VALUES
+.Fn ber_oid2ber
+returns the number of bytes written or 0 on faliure.
+.Pp
+.Fn ber_string2oid
+returns 0 on success or -1 on failure.
+.Pp
+.Fn ber_oid_cmp
+returns 0 when oids
+.Fa a
+and
+.Fa b
+are identical.
+If
+.Fa b
+is a successor of
+.Fa a ,
+1 is returned.
+If
+.Fa b
+is a predecessor of
+.Fa a ,
+-1 is returned.
+If
+.Fa b
+is larger, but a child of
+.Fa a ,
+2 is returned.
+.Sh SEE ALSO
+.Xr ber_add_string 3 ,
+.Xr ber_get_string 3 ,
+.Xr ber_read_elements 3 ,
+.Xr ber_set_header 3
+.Sh HISTORY
+These functions first appeared as internal functions in
+.Xr snmpd 8
+in
+.Ox 4.2
+and were moved to libutil in
+.Ox 6.6 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm ber
+library was written by
+.An Claudio Jeker Aq Mt claudio@openbsd.org ,
+.An Marc Balmer Aq Mt marc@openbsd.org
+and
+.An Reyk Floeter Aq Mt reyk@openbsd.org .
diff --git a/lib/libutil/ber_read_elements.3 b/lib/libutil/ber_read_elements.3
new file mode 100644
index 00000000000..d2e0533aafb
--- /dev/null
+++ b/lib/libutil/ber_read_elements.3
@@ -0,0 +1,225 @@
+.\" $OpenBSD: ber_read_elements.3,v 1.1 2019/05/15 03:11:52 rob Exp $
+.\"
+.\" Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate: May 15 2019 $
+.Dt BER_READ_ELEMENTS 3
+.Os
+.Sh NAME
+.Nm ber_set_readbuf ,
+.Nm ber_set_application ,
+.Nm ber_read_elements ,
+.Nm ber_get_writebuf ,
+.Nm ber_write_elements ,
+.Nm ber_free
+.Nd encode and decode ASN.1 with Basic Encoding Rules
+.Sh SYNOPSIS
+.In sys/types.h
+.In ber.h
+.Ft "void"
+.Fn "ber_set_readbuf" "struct ber *ber" "void *buf" "size_t len"
+.Ft "void"
+.Fo "ber_set_application"
+.Fa "struct ber *ber"
+.Fa "unsigned int (*cb)(struct ber_element *)"
+.Fc
+.Ft "struct ber_element *"
+.Fn "ber_read_elements" "struct ber *ber" "struct ber_element *root"
+.Ft "ssize_t"
+.Fn "ber_get_writebuf" "struct ber *ber" "void **buf"
+.Ft "ssize_t"
+.Fn "ber_write_elements" "struct ber *ber" "struct ber_element *root"
+.Ft "void"
+.Fn "ber_free" "struct ber *ber"
+.Sh DESCRIPTION
+The BER API provides a mechanism to read and write ASN.1 using the
+Basic Encoding Rules.
+.Pp
+Encoded BER is stored in the following structure:
+.Bd -literal
+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 *);
+};
+.Ed
+.Pp
+.Fa br_rbuf
+and
+.Fa 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).
+.Pp
+Intermediary storage of BER elements during encoding and decoding uses the
+following structure:
+.Bd -literal
+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
+};
+.Ed
+.Pp
+.Fn ber_set_readbuf
+sets
+.Fa br_rbuf
+to point an input buffer of BER encoded bytes in preparation for decoding.
+It is assumed that
+.Fa br_rbuf
+is already populated and available to the
+application, commonly obtained by
+.Xr read 2 ,
+.Xr recv 2 ,
+or
+.Xr tls_read 3 .
+.Pp
+.Fn ber_read_elements
+may then be called to parse, validate, and store the
+.Fa ber
+data stream into its
+consituent
+.Vt ber_element
+parts for subsequent processing.
+The calling application must have explicit knowledge of the expected data
+types in order for correct decoding.
+.Pp
+.Fn ber_get_writebuf
+sets
+.Fa br_wbuf
+to point to an output buffer for writing a BER byte stream.
+.Pp
+.Fn ber_write_elements
+encodes
+.Fa root
+into a compliant BER byte stream which is written to
+.Fa ber
+for subsequent use by the calling
+functions such as
+.Xr send 2 ,
+.Xr write 2 ,
+or
+.Xr tls_write 3 .
+.Pp
+.Fn ber_free
+frees any dynamically allocated storage associated with
+.Fa ber .
+.Sh RETURN VALUES
+.Fn ber_read_elements
+returns a pointer to a fully populated list of one or more
+.Vt ber_element
+structures or
+.Dv NULL
+on a type mismatch or read error.
+.Pp
+.Fn ber_get_writebuf
+returns the number of bytes contained within buffer
+.Vt b
+within the buffer
+.Fa buf
+or \-1 on failure.
+.Pp
+.Fn ber_write_elements
+returns the number of bytes written.
+Otherwise \-1 is returned and the global variable errno is
+set to indicate the error.
+.Sh SEE ALSO
+.Xr read 2 ,
+.Xr recv 2 ,
+.Xr send 2 ,
+.Xr write 2 ,
+.Xr ber_add_string 3 ,
+.Xr ber_get_string 3 ,
+.Xr ber_oid_cmp 3 ,
+.Xr ber_set_header 3 ,
+.Xr tls_read 3
+.Sh STANDARDS
+ITU-T Recommendation X.690, also known as ISO/IEC 8825-1:
+Information technology - ASN.1 encoding rules.
+.Sh HISTORY
+These functions first appeared as internal functions in
+.Xr snmpd 8
+in
+.Ox 4.2
+and were moved to libutil in
+.Ox 6.6 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm ber
+library was written by
+.An Claudio Jeker Aq Mt claudio@openbsd.org ,
+.An Marc Balmer Aq Mt marc@openbsd.org
+and
+.An Reyk Floeter Aq Mt reyk@openbsd.org .
+.Sh CAVEATS
+The
+.Nm ber
+API is subject to the following restrictions which are common to the
+Distinguished Encoding Rules as defined by X.690:
+.Pp
+.Bl -enum -compact
+.It
+Only the definite form of length encoding shall be used, encoded in the
+minimum number of octets.
+.It
+For bitstring, octetstring and restricted character string types, the
+constructed form of encoding shall not be used.
+.It
+If a boolean encoding represents the boolean value TRUE, its single contents
+octet shall have all eight bits set to one.
+.It
+Each unused bit in the final octet of the encoding of a bit string value shall
+be set to zero.
+.It
+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.
+.El
+.Pp
+In addition, set and sequence values are limited to a maximum of 65535 elements.
+No alternative encodings are permitted.
+.Pp
+.Do
+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.
+.Dc
+.Bq X.690
+.Pp
+The restrictions placed on this API avoid the ambiguity inherent in
+.Nm ber
+encoded ASN.1 thereby acting as a security mitigation.
diff --git a/lib/libutil/ber_set_header.3 b/lib/libutil/ber_set_header.3
new file mode 100644
index 00000000000..dea1bfcb562
--- /dev/null
+++ b/lib/libutil/ber_set_header.3
@@ -0,0 +1,144 @@
+.\" $OpenBSD: ber_set_header.3,v 1.1 2019/05/15 03:11:52 rob Exp $
+.\"
+.\" Copyright (c) 2007, 2012 Reyk Floeter <reyk@openbsd.org>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate: May 15 2019 $
+.Dt BER_SET_HEADER 3
+.Os
+.Sh NAME
+.Nm ber_set_header ,
+.Nm ber_calc_len ,
+.Nm ber_set_writecallback ,
+.Nm ber_link_elements ,
+.Nm ber_replace_elements ,
+.Nm ber_unlink_elements ,
+.Nm ber_free_element ,
+.Nm ber_free_elements
+.Nd change and destroy ASN.1 objects for BER encoding
+.Sh SYNOPSIS
+.In sys/types.h
+.In ber.h
+.Ft "void"
+.Fn "ber_set_header" "struct ber_element *elm" "int class" "unsigned int type"
+.Ft "size_t"
+.Fn "ber_calc_len" "struct ber_element *root"
+.Ft "void"
+.Fo "ber_set_writecallback"
+.Fa "void (*cb)(void *arg, sizeof_t offs)"
+.Fc
+.Ft "void"
+.Fn "ber_link_elements" "struct ber_element *prev" "struct ber_element *elm"
+.Ft "void"
+.Fn "ber_replace_elements" "struct ber_element *prev" "struct ber_element *elm"
+.Ft "struct ber_element *"
+.Fn "ber_unlink_elements" "struct ber_element *prev"
+.Ft "void"
+.Fn "ber_free_element" "struct ber_element *root"
+.Ft "void"
+.Fn "ber_free_elements" "struct ber_element *root"
+.Pp
+.Fd #define BER_TYPE_BOOLEAN 1
+.Fd #define BER_TYPE_INTEGER 2
+.Fd #define BER_TYPE_BITSTRING 3
+.Fd #define BER_TYPE_OCTETSTRING 4
+.Fd #define BER_TYPE_NULL 5
+.Fd #define BER_TYPE_OBJECT 6
+.Fd #define BER_TYPE_ENUMERATED 10
+.Fd #define BER_TYPE_SEQUENCE 16
+.Fd #define BER_TYPE_SET 17
+.Pp
+.Fd #define BER_TYPE_CONSTRUCTED 0x20
+.Pp
+.Fd #define BER_CLASS_UNIVERSAL 0x0
+.Fd #define BER_CLASS_UNIV BER_CLASS_UNIVERSAL
+.Fd #define BER_CLASS_APPLICATION 0x1
+.Fd #define BER_CLASS_APP BER_CLASS_APPLICATION
+.Fd #define BER_CLASS_CONTEXT 0x2
+.Fd #define BER_CLASS_PRIVATE 0x3
+.Sh DESCRIPTION
+.Fn ber_set_header
+sets the
+.Fa class
+and
+.Fa type
+of
+.Fa elm .
+.Pp
+.Fn ber_calc_len
+determines the total length of
+.Fa root .
+.Pp
+.Fn ber_set_writecallback
+registers the
+.Vt br_cb
+callback function.
+.Pp
+.Fn ber_link_elements
+links
+.Fa prev
+and
+.Fa elm .
+.Pp
+.Fn ber_replace_elements
+replaces
+.Fa prev
+with
+.Fa new
+and frees any dynamically allocated storage assocated with
+.Fa prev .
+.Pp
+.Fn ber_unlink_elements
+unlinks
+.Fa prev .
+.Pp
+.Fn ber_free_element
+and
+.Fn ber_free_elements
+free any dynamically allocated storage associated with
+.Fa root .
+.Sh RETURN VALUES
+.Fn ber_calc_len
+returns the total length of a fully populated
+.Fa root
+containing one or more
+.Vt ber_element .
+.Pp
+.Fn ber_unlink_elements
+returns a pointer to
+.Vt ber_element .
+.Sh SEE ALSO
+.Xr ber_add_string 3 ,
+.Xr ber_get_string 3 ,
+.Xr ber_oid_cmp 3 ,
+.Xr ber_read_elements 3
+.Sh STANDARDS
+ITU-T Recommendation X.690, also known as ISO/IEC 8825-1:
+Information technology - ASN.1 encoding rules.
+.Sh HISTORY
+These functions first appeared as internal functions in
+.Xr snmpd 8
+in
+.Ox 4.2
+and were moved to libutil in
+.Ox 6.6 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm ber
+library was written by
+.An Claudio Jeker Aq Mt claudio@openbsd.org ,
+.An Marc Balmer Aq Mt marc@openbsd.org
+and
+.An Reyk Floeter Aq Mt reyk@openbsd.org .