OpenSSL d2i_X509(3openssl)
NNNNAAAAMMMMEEEEd2i_X509, i2d_X509, d2i_X509_bio, d2i_X509_fp, i2d_X509_bio,
i2d_X509_fp - X509 encode and decode functions
SSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS#include
X509 *d2i_X509(X509 **px, const unsigned char **in, int len);
int i2d_X509(X509 *x, unsigned char **out);
X509 *d2i_X509_bio(BIO *bp, X509 **x);
X509 *d2i_X509_fp(FILE *fp, X509 **x);
int i2d_X509_bio(BIO *bp, X509 *x);
int i2d_X509_fp(FILE *fp, X509 *x);
DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN The X509 encode and decode routines encode and parse an XXXX555500009999 structure, which represents an X509 certificate.d2i_X509() attempts to decode lllleeeennnn bytes at ****iiiinnnn. If
successful a pointer to the XXXX555500009999 structure is returned. If an error occurred then NNNNUUUULLLLLLLL is returned. If ppppxxxx is not NNNNUUUULLLLLLLL then the returned structure is written to ****ppppxxxx. If ****ppppxxxx is not NNNNUUUULLLLLLLL then it is assumed that ****ppppxxxx contains a valid XXXX555500009999 structure and an attempt is made to reuse it. If the call is successful ****iiiinnnn is incremented to the byte following the parsed data.i2d_X509() encodes the structure pointed to by xxxx into DER
format. If oooouuuutttt is not NNNNUUUULLLLLLLL is writes the DER encoded data to the buffer at ****oooouuuutttt, and increments it to point after the data just written. If the return value is negative an error occurred, otherwise it returns the length of the encoded data. For OpenSSL 0.9.7 and later if ****oooouuuutttt is NNNNUUUULLLLLLLL memory will be allocated for a buffer and the encoded data written to it. In this case ****oooouuuutttt is not incremented and it points to the start of the data just written.d2i_X509_bio() is similar to d2i_X509() except it attempts
to parse data from BIO bbbbpppp.d2i_X509_fp() is similar to d2i_X509() except it attempts to
parse data from FILE pointer ffffpppp.i2d_X509_bio() is similar to i2d_X509() except it writes the
encoding of the structure xxxx to BIO bbbbpppp and it returns 1 for success and 0 for failure.12/Sep/2009 Last change: 0.9.8o 1
OpenSSL d2i_X509(3openssl)
i2d_X509_fp() is similar to i2d_X509() except it writes the
encoding of the structure xxxx to BIO bbbbpppp and it returns 1 for success and 0 for failure. NNNNOOOOTTTTEEEESSSSThe letters iiii and dddd in for example iiii2222dddd_XXXX555500009999 stand for
"internal" (that is an internal C structure) and "DER". Sothat iiii2222dddd_XXXX555500009999 converts from internal to DER.
The functions can also understand BBBBEEEERRRR forms.The actual X509 structure passed to i2d_X509() must be a
valid populated XXXX555500009999 structure it can nnnnooootttt simply be fed withan empty structure such as that returned by X509_new().
The encoded data is in binary form and may contain embedded zeroes. Therefore any FILE pointers or BIOs should be opened in binary mode. Functions such as ssssttttrrrrlllleeeennnn(((()))) will nnnnooootttt return the correct length of the encoded structure. The ways that ****iiiinnnn and ****oooouuuutttt are incremented after the operation can trap the unwary. See the WWWWAAAARRRRNNNNIIIINNNNGGGGSSSS section for some common errors. The reason for the auto increment behaviour is to reflect a typical usage of ASN1 functions: after one structure is encoded or decoded another will processed after it. EEEEXXXXAAAAMMMMPPPPLLLLEEEESSSS Allocate and encode the DER encoding of an X509 structure: int len; unsigned char *buf, *p;len = i2d_X509(x, NULL);
buf = OPENSSL_malloc(len);
if (buf == NULL) /* error */ p = buf;i2d_X509(x, &p);
If you are using OpenSSL 0.9.7 or later then this can be simplified to: int len; unsigned char *buf; buf = NULL;12/Sep/2009 Last change: 0.9.8o 2
OpenSSL d2i_X509(3openssl)
len = i2d_X509(x, &buf);
if (len < 0) /* error */ Attempt to decode a buffer: X509 *x; unsigned char *buf, *p; int len; /* Something to setup buf and len */ p = buf;x = d2i_X509(NULL, &p, len);
if (x == NULL) /* Some error */ Alternative technique: X509 *x; unsigned char *buf, *p; int len; /* Something to setup buf and len */ p = buf; x = NULL;if(!d2i_X509(&x, &p, len))
/* Some error */ WWWWAAAARRRRNNNNIIIINNNNGGGGSSSS The use of temporary variable is mandatory. A common mistake is to attempt to use a buffer directly as follows: int len; unsigned char *buf;len = i2d_X509(x, NULL);
buf = OPENSSL_malloc(len);
12/Sep/2009 Last change: 0.9.8o 3
OpenSSL d2i_X509(3openssl)
if (buf == NULL) /* error */i2d_X509(x, &buf);
/* Other stuff ... */OPENSSL_free(buf);
This code will result in bbbbuuuuffff apparently containing garbage because it was incremented after the call to point after the data just written. Also bbbbuuuuffff will no longer contain thepointer allocated by OOOOPPPPEEEENNNNSSSSSSSSLLLL_mmmmaaaalllllllloooocccc(((()))) and the subsequent
call to OOOOPPPPEEEENNNNSSSSSSSSLLLL_ffffrrrreeeeeeee(((()))) may well crash.
The auto allocation feature (setting buf to NULL) only works on OpenSSL 0.9.7 and later. Attempts to use it on earlier versions will typically cause a segmentation violation. Another trap to avoid is misuse of the xxxxpppp argument todddd2222iiii_XXXX555500009999(((()))):
X509 *x;if (!d2i_X509(&x, &p, len))
/* Some error */This will probably crash somewhere in dddd2222iiii_XXXX555500009999(((()))). The reason
for this is that the variable xxxx is uninitialized and an attempt will be made to interpret its (invalid) value as an XXXX555500009999 structure, typically causing a segmentation violation. If xxxx is set to NULL first then this will not happen. BBBBUUUUGGGGSSSS In some versions of OpenSSL the "reuse" behaviour ofd2i_X509() when ****ppppxxxx is valid is broken and some parts of the
reused structure may persist if they are not present in the new one. As a result the use of this "reuse" behaviour is strongly discouraged.i2d_X509() will not return an error in many versions of
OpenSSL, if mandatory fields are not initialized due to a programming error then the encoded structure may contain invalid data or omit the fields entirely and will not beparsed by d2i_X509(). This may be fixed in future so code
should not assume that i2d_X509() will always succeed.
RRRREEEETTTTUUUURRRRNNNN VVVVAAAALLLLUUUUEEEESSSSd2i_X509(), d2i_X509_bio() and d2i_X509_fp() return a valid
XXXX555500009999 structure or NNNNUUUULLLLLLLL if an error occurs. The error codethat can be obtained by ERR_get_error(3).
12/Sep/2009 Last change: 0.9.8o 4
OpenSSL d2i_X509(3openssl)
i2d_X509() returns the number of bytes successfully encoded
or a negative value if an error occurs. The error code canbe obtained by ERR_get_error(3).
i2d_X509_bio() and i2d_X509_fp() return 1 for success and 0
if an error occurs The error code can be obtained byERR_get_error(3).
SSSSEEEEEEEE AAAALLLLSSSSOOOOERR_get_error(3)
HHHHIIIISSSSTTTTOOOORRRRYYYYd2i_X509, i2d_X509, d2i_X509_bio, d2i_X509_fp, i2d_X509_bio
and i2d_X509_fp are available in all versions of SSLeay and
OpenSSL.12/Sep/2009 Last change: 0.9.8o 5