Add i2d_re_X509_tbs
authorEmilia Kasper <emilia@openssl.org>
Fri, 5 Sep 2014 13:25:57 +0000 (15:25 +0200)
committerEmilia Kasper <emilia@openssl.org>
Fri, 5 Sep 2014 15:18:06 +0000 (17:18 +0200)
i2d_re_X509_tbs re-encodes the TBS portion of the certificate.

Reviewed-by: Rich Salz <rsalz@openssl.org>
Reviewed-by: Dr Stephen Henson <steve@openssl.org>
crypto/asn1/x_x509.c
crypto/x509/x509.h
doc/crypto/d2i_X509.pod

index fd5e6c6428f29837548d54ad603ec71ff5143dbd..7d33c38a57d329b53f764bdcb5dd6ee8a767d9a4 100644 (file)
@@ -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)
        {
index ee560d19bf587debf1f8643a43b43aa142a0dff5..2fcc107812421f5f8c1c36f76363776720426815 100644 (file)
@@ -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);
index 298ec54a4c3be2242a0a1ef134d461dd144e75a9..fea6e868e5c01316d5d85cca1c77f57697280f00 100644 (file)
@@ -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<x> to BIO B<bp> 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<i> and B<d> in for example B<i2d_X509> stand for
-"internal" (that is an internal C structure) and "DER". So that
-B<i2d_X509> converts from internal to DER.
+"internal" (that is an internal C structure) and "DER". So
+B<i2d_X509> converts from internal to DER. The "re" in
+B<i2d_re_X509_tbs> 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<BER> 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<X509> 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<X509> structure has been modified after deserialization or previous
+serialization.
+
+If, after modification, the B<X509> object is re-signed with X509_sign(),
+the encoding is automatically renewed. Otherwise, the encoding of the
+TBSCertificate portion of the B<X509> 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<X509> structure