DragonFly On-Line Manual Pages
ASN1_ITEM_D2I(3) DragonFly Library Functions Manual ASN1_ITEM_D2I(3)
NAME
ASN1_item_d2i, ASN1_item_d2i_bio, ASN1_item_d2i_fp, d2i_ASN1_TYPE,
ASN1_item_i2d, ASN1_item_i2d_bio, ASN1_item_i2d_fp, i2d_ASN1_TYPE,
ASN1_item_dup, ASN1_item_print -- decode and encode ASN.1 objects
SYNOPSIS
#include <openssl/asn1.h>
ASN1_VALUE *
ASN1_item_d2i(ASN1_VALUE **val_out, const unsigned char **der_in,
long length, const ASN1_ITEM *it);
void *
ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in_bio, void *val_out);
void *
ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in_fp, void *val_out);
ASN1_TYPE *
d2i_ASN1_TYPE(ASN1_TYPE **val_out, const unsigned char **der_in,
long length);
int
ASN1_item_i2d(ASN1_VALUE *val_in, unsigned char **der_out,
const ASN1_ITEM *it);
int
ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out_bio, void *val_in);
int
ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out_fp, void *val_in);
int
i2d_ASN1_TYPE(ASN1_TYPE *val_in, unsigned char **der_out);
void *
ASN1_item_dup(const ASN1_ITEM *it, void *val_in);
int
ASN1_item_print(BIO *out_bio, ASN1_VALUE *val_in, int indent,
const ASN1_ITEM *it, const ASN1_PCTX *pctx);
DESCRIPTION
These functions convert ASN.1 values from their BER encoding to internal
C structures (``d2i'') and vice versa (``i2d''). Unlike the C structures
which contain pointers to sub-objects, BER is a serialized encoding,
suitable for transfer over the network and for storage in a file.
ASN1_item_d2i() interpretes *der_in as a DER- or BER-encoded byte array
and decodes one value of type it represented by up to length bytes. If
successful, *der_in is advanced to the byte following the parsed data.
If decoding succeeds and val_out or *val_out is NULL, a new object is
allocated.
If decoding succeeds and *val_out is not NULL, it is assumed to point to
a valid populated object and an attempt is made to reuse it. It must not
be an empty structure such as one returned by ASN1_item_new(3) or by one
of the various type-specific *_new() functions. This ``reuse'' capabil-
ity is present for backward compatibility, but its use is strongly dis-
couraged; see the BUGS section below.
ASN1_item_d2i_bio() and ASN1_item_d2i_fp() are similar to ASN1_item_d2i()
except that they read from a BIO or FILE, respectively.
d2i_ASN1_TYPE() is similar to ASN1_item_d2i() except that it does not
require a desired type to be specified by the user, but instead returns
an ASN1_TYPE wrapper object containing both the type and the value found
in the input.
ASN1_item_i2d() encodes the object pointed to by val_in into DER format.
If *der_out is not NULL, it writes the DER-encoded data to the buffer at
*der_out and increments it to point after the data just written. In this
case, it is the responsibility of the user to make sure that the buffer
pointed to by *der_out is long enough, such that no buffer owerflow can
occur.
If *der_out is NULL, memory is allocated for a buffer, and *der_out is
not incremented, but points to the start of the data just written.
If der_out is NULL, the encoded bytes are not written anywhere but dis-
carded. For val_in objects of variable encoding size, this is sometimes
used to first find the number of bytes that will be written. Then, a
sufficient amount of memory is allocated before calling ASN1_item_i2d()
again. This explicit double-call technique is often not needed because
the auto-allocation technique described in the previous paragraph can be
used.
ASN1_item_i2d_bio() and ASN1_item_i2d_fp() are similar to ASN1_item_i2d()
except that they write to a BIO or FILE, respectively.
i2d_ASN1_TYPE() is similar to ASN1_item_i2d() except that the type and
the value are not provided separately, but in the form of a single
ASN1_TYPE object.
ASN1_item_dup() creates a deep copy of val_in by calling ASN1_item_i2d()
and ASN1_item_d2i().
RETURN VALUES
If successful, ASN1_item_d2i(), ASN1_item_d2i_bio(), ASN1_item_d2i_fp(),
and d2i_ASN1_TYPE() return a pointer to the decoded ASN.1 value. In
addition, if val_out is not NULL, the pointer is also written to
*val_out. If an error occurs, NULL is returned.
ASN1_item_i2d() and i2d_ASN1_TYPE() return the number of bytes written or
a negative value if an error occurs.
ASN1_item_i2d_bio() and ASN1_item_i2d_fp() return 1 for success or 0 for
failure.
ASN1_item_dup() returns the new ASN1_VALUE object or NULL if an error
occurs.
EXAMPLES
Many type-specific wrapper functions exist. Using those wrappers is rec-
ommended in application code because it restores part of the type safety
that the low-level interfaces using ASN1_VALUE lack.
For example, to allocate a buffer and write the DER encoding of an X509
object into it:
X509 *x;
unsigned char *buf;
int len;
buf = NULL;
len = i2d_X509(x, &buf);
if (len < 0)
/* error */
Attempt to decode a buffer:
X509 *x;
unsigned char *buf, *p;
int len;
/* Set up buf and len to point to the input buffer. */
p = buf;
x = d2i_X509(NULL, &p, len);
if (x == NULL)
/* error */
Equivalent technique:
X509 *x;
unsigned char *buf, *p;
int len;
/* Set up buf and len to point to the input buffer. */
p = buf;
x = NULL;
if (d2i_X509(&x, &p, len) == NULL)
/* error */
SEE ALSO
ASN1_item_new(3), ASN1_TYPE_new(3)
HISTORY
d2i_ASN1_TYPE() and i2d_ASN1_TYPE() first appeared in SSLeay 0.5.1 and
have been available since OpenBSD 2.4.
ASN1_item_d2i(), ASN1_item_d2i_bio(), ASN1_item_d2i_fp(),
ASN1_item_i2d(), ASN1_item_i2d_bio(), ASN1_item_i2d_fp(), and
ASN1_item_dup() first appeared in OpenSSL 0.9.7 and have been available
since OpenBSD 3.2.
ASN1_item_print() first appeared in OpenSSL 1.0.0 and has been available
since OpenBSD 4.9.
CAVEATS
If the type described by it fails to match the true type of val_in or
*val_out, buffer overflows and segmentation faults are likely to occur.
For more details about why the type ASN1_VALUE constitutes dangerous user
interface design, see ASN1_item_new(3).
The encoded data is in binary form and may contain embedded NUL bytes.
Functions such as strlen(3) will not return the correct length of the
encoded data.
While the way that *der_in and *der_out are incremented after the opera-
tion supports the typical usage patterns of reading or writing one object
after another, this behaviour can trap the unwary.
Using a temporary pointer into the buffer is mandatory. A common mistake
is to attempt to use a buffer directly as follows:
X509 *x;
unsigned char *buf;
int len;
len = i2d_X509(x, NULL);
buf = malloc(len);
i2d_X509(x, &buf);
/* do something with buf[] */
free(buf);
This code will result in buf apparently containing garbage because it was
incremented during i2d_X509() to point after the data just written. Also
buf will no longer contain the pointer allocated by malloc(3) and the
subsequent call to free(3) is likely to crash.
Another trap to avoid is misuse of the val_out argument:
X509 *x;
if (d2i_X509(&x, &p, len) == NULL)
/* error */
This will probably crash somewhere in d2i_X509() because x is uninitial-
ized and an attempt will be made to interpret its invalid content as an
X509 object, typically causing a segmentation violation. If x is set to
NULL first, then this will not happen.
BUGS
If the ``reuse'' capability is used, a valid object is passed in via
*val_out, and an error occurs, then the object is not freed and may be
left in an invalid or inconsistent state.
In some versions of OpenSSL, the ``reuse'' behaviour is broken such that
some parts of the reused object may persist if they are not present in
the new one.
In many versions of OpenSSL, ASN1_item_i2d() will not return an error if
mandatory fields are not initialized due to a programming error. In that
case, the encoded structure may contain invalid data and some fields may
be missing entirely, such that trying to parse it with ASN1_item_d2i()
may fail.
Any function which encodes an object may return a stale encoding if the
object has been modified after deserialization or previous serialization.
This is because some objects cache the encoding for efficiency reasons.
DragonFly 5.5 March 27, 2018 DragonFly 5.5