=pod =head1 NAME d2i_X509, i2d_X509, d2i_X509_bio, d2i_X509_fp, i2d_X509_bio, i2d_X509_fp - X509 encode and decode functions =head1 SYNOPSIS #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); int i2d_re_X509_tbs(X509 *x, unsigned char **out); =head1 DESCRIPTION The X509 encode and decode routines encode and parse an B structure, which represents an X509 certificate. d2i_X509() attempts to decode B bytes at B<*in>. If successful a pointer to the B structure is returned. If an error occurred then B is returned. If B is not B then the returned structure is written to B<*px>. If B<*px> is not B then it is assumed that B<*px> contains a valid B structure and an attempt is made to reuse it. This "reuse" capability is present for historical compatibility but its use is B (see BUGS below, and the discussion in the RETURN VALUES section). If the call is successful B<*in> is incremented to the byte following the parsed data. i2d_X509() encodes the structure pointed to by B into DER format. If B is not B is writes the DER encoded data to the buffer at B<*out>, 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. If B<*out> is B memory will be allocated for a buffer and the encoded data written to it. In this case B<*out> 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 B. d2i_X509_fp() is similar to d2i_X509() except it attempts to parse data from FILE pointer B. i2d_X509_bio() is similar to i2d_X509() except it writes the encoding of the structure B to BIO B and it returns 1 for success and 0 for failure. i2d_X509_fp() is similar to i2d_X509() except it writes the encoding of the structure B to BIO B and it returns 1 for success and 0 for failure. i2d_re_X509_tbs() is similar to i2d_X509() except it encodes only the TBSCertificate portion of the certificate. =head1 NOTES The letters B and B in for example B stand for "internal" (that is an internal C structure) and "DER". So B converts from internal to DER. The "re" in B stands for "re-encode", and ensures that a fresh encoding is generated in case the object has been modified after creation (see the BUGS section). The functions can also understand B forms. The actual X509 structure passed to i2d_X509() must be a valid populated B structure it can B simply be fed with an 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 strlen() will B return the correct length of the encoded structure. The ways that B<*in> and B<*out> are incremented after the operation can trap the unwary. See the B 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. =head1 EXAMPLES Allocate and encode the DER encoding of an X509 structure: int len; unsigned char *buf; buf = NULL; 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 */ =head1 WARNINGS 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); if (buf == NULL) /* error */ i2d_X509(x, &buf); /* Other stuff ... */ OPENSSL_free(buf); This code will result in B apparently containing garbage because it was incremented after the call to point after the data just written. Also B will no longer contain the pointer allocated by OPENSSL_malloc() and the subsequent call to OPENSSL_free() may well crash. Another trap to avoid is misuse of the B argument to d2i_X509(): X509 *x; if (!d2i_X509(&x, &p, len)) /* Some error */ This will probably crash somewhere in d2i_X509(). The reason for this is that the variable B is uninitialized and an attempt will be made to interpret its (invalid) value as an B structure, typically causing a segmentation violation. If B is set to NULL first then this will not happen. =head1 BUGS In some versions of OpenSSL the "reuse" behaviour of d2i_X509() when B<*px> 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 be parsed by d2i_X509(). This may be fixed in future so code should not assume that i2d_X509() will always succeed. The encoding of the TBSCertificate portion of a certificate is cached in the B structure internally to improve encoding performance and to ensure certificate signatures are verified correctly in some certificates with broken (non-DER) encodings. Any function which encodes an X509 structure such as i2d_X509(), i2d_X509_fp() or i2d_X509_bio() may return a stale encoding if the B structure has been modified after deserialization or previous serialization. If, after modification, the B object is re-signed with X509_sign(), the encoding is automatically renewed. Otherwise, the encoding of the TBSCertificate portion of the B can be manually renewed by calling i2d_re_X509_tbs(). =head1 RETURN VALUES d2i_X509(), d2i_X509_bio() and d2i_X509_fp() return a valid B structure or B if an error occurs. The error code that can be obtained by L. If the "reuse" capability has been used with a valid X509 structure being passed in via B then the object is not freed in the event of error but may be in a potentially invalid or inconsistent state. i2d_X509() returns the number of bytes successfully encoded or a negative value if an error occurs. The error code can be obtained by L. i2d_X509_bio() and i2d_X509_fp() return 1 for success and 0 if an error occurs The error code can be obtained by L. =head1 SEE ALSO L L, L, L, L, L, L, L, L, L, L, L, L, L, L, L =cut