From 95b1752cc7531e4b609aea166f2db1c155ab5bdd Mon Sep 17 00:00:00 2001 From: Emilia Kasper Date: Fri, 5 Sep 2014 15:25:57 +0200 Subject: [PATCH] Add i2d_re_X509_tbs i2d_re_X509_tbs re-encodes the TBS portion of the certificate. Reviewed-by: Rich Salz Reviewed-by: Dr Stephen Henson --- crypto/asn1/x_x509.c | 6 ++++++ crypto/x509/x509.h | 2 ++ doc/crypto/d2i_X509.pod | 27 +++++++++++++++++++++++++-- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/crypto/asn1/x_x509.c b/crypto/asn1/x_x509.c index fd5e6c6428..7d33c38a57 100644 --- a/crypto/asn1/x_x509.c +++ b/crypto/asn1/x_x509.c @@ -193,6 +193,12 @@ int i2d_X509_AUX(X509 *a, unsigned char **pp) return length; } +int i2d_re_X509_tbs(X509 *x, unsigned char **pp) + { + x->cert_info->enc.modified = 1; + return i2d_X509_CINF(x->cert_info, pp); + } + void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, const X509 *x) { diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h index ee560d19bf..2fcc107812 100644 --- a/crypto/x509/x509.h +++ b/crypto/x509/x509.h @@ -852,6 +852,8 @@ void *X509_get_ex_data(X509 *r, int idx); int i2d_X509_AUX(X509 *a,unsigned char **pp); X509 * d2i_X509_AUX(X509 **a,const unsigned char **pp,long length); +int i2d_re_X509_tbs(X509 *x, unsigned char **pp); + void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, const X509 *x); int X509_get_signature_nid(const X509 *x); diff --git a/doc/crypto/d2i_X509.pod b/doc/crypto/d2i_X509.pod index 298ec54a4c..fea6e868e5 100644 --- a/doc/crypto/d2i_X509.pod +++ b/doc/crypto/d2i_X509.pod @@ -18,6 +18,8 @@ i2d_X509_fp - X509 encode and decode functions 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 @@ -57,11 +59,17 @@ 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 that -B converts from internal to DER. +"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. @@ -206,6 +214,21 @@ 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 -- 2.34.1