|
|
@ -0,0 +1,453 @@ |
|
|
|
.\" $OpenBSD: ber.3,v 1.1 2019/05/11 17:46:02 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 11 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 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. |