Cache some CRL related extensions.
[openssl.git] / crypto / asn1 / x_crl.c
index 8843f3413852d3582289c5af26dc1e3379ab2976..8943b84373137f51bad64ef291f69eb0572e1596 100644 (file)
 #include "cryptlib.h"
 #include <openssl/asn1t.h>
 #include <openssl/x509.h>
+#include <openssl/x509v3.h>
 
 static int X509_REVOKED_cmp(const X509_REVOKED * const *a,
                                const X509_REVOKED * const *b);
-static int X509_REVOKED_seq_cmp(const X509_REVOKED * const *a,
-                               const X509_REVOKED * const *b);
 
 ASN1_SEQUENCE(X509_REVOKED) = {
        ASN1_SIMPLE(X509_REVOKED,serialNumber, ASN1_INTEGER),
@@ -72,43 +71,29 @@ ASN1_SEQUENCE(X509_REVOKED) = {
        ASN1_SEQUENCE_OF_OPT(X509_REVOKED,extensions, X509_EXTENSION)
 } ASN1_SEQUENCE_END(X509_REVOKED)
 
-/* The X509_CRL_INFO structure needs a bit of customisation. This is actually
- * mirroring the old behaviour: its purpose is to allow the use of
- * sk_X509_REVOKED_find to lookup revoked certificates. Unfortunately
- * this will zap the original order and the signature so we keep a copy
- * of the original positions and reorder appropriately before encoding.
- *
- * Might want to see if there's a better way of doing this later...
+/* The X509_CRL_INFO structure needs a bit of customisation.
+ * Since we cache the original encoding the signature wont be affected by
+ * reordering of the revoked field.
  */
-static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it)
+static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+                                                               void *exarg)
 {
        X509_CRL_INFO *a = (X509_CRL_INFO *)*pval;
-       int i;
-       int (*old_cmp)(const X509_REVOKED * const *,
-                       const X509_REVOKED * const *);
 
        if(!a || !a->revoked) return 1;
        switch(operation) {
-
-               /* Save original order */
+               /* Just set cmp function here. We don't sort because that
+                * would affect the output of X509_CRL_print().
+                */
                case ASN1_OP_D2I_POST:
-               for (i=0; i<sk_X509_REVOKED_num(a->revoked); i++)
-                       sk_X509_REVOKED_value(a->revoked,i)->sequence=i;
                sk_X509_REVOKED_set_cmp_func(a->revoked,X509_REVOKED_cmp);
                break;
-
-               /* Restore original order */
-               case ASN1_OP_I2D_PRE:
-               old_cmp=sk_X509_REVOKED_set_cmp_func(a->revoked,X509_REVOKED_seq_cmp);
-               sk_X509_REVOKED_sort(a->revoked);
-               sk_X509_REVOKED_set_cmp_func(a->revoked,old_cmp);
-               break;
        }
        return 1;
 }
 
 
-ASN1_SEQUENCE_cb(X509_CRL_INFO, crl_inf_cb) = {
+ASN1_SEQUENCE_enc(X509_CRL_INFO, enc, crl_inf_cb) = {
        ASN1_OPT(X509_CRL_INFO, version, ASN1_INTEGER),
        ASN1_SIMPLE(X509_CRL_INFO, sig_alg, X509_ALGOR),
        ASN1_SIMPLE(X509_CRL_INFO, issuer, X509_NAME),
@@ -116,9 +101,44 @@ ASN1_SEQUENCE_cb(X509_CRL_INFO, crl_inf_cb) = {
        ASN1_OPT(X509_CRL_INFO, nextUpdate, ASN1_TIME),
        ASN1_SEQUENCE_OF_OPT(X509_CRL_INFO, revoked, X509_REVOKED),
        ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0)
-} ASN1_SEQUENCE_END_cb(X509_CRL_INFO, X509_CRL_INFO)
+} ASN1_SEQUENCE_END_enc(X509_CRL_INFO, X509_CRL_INFO)
+
+/* The X509_CRL structure needs a bit of customisation. Cache some extensions
+ * and hash of the whole CRL.
+ */
+static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+                                                               void *exarg)
+       {
+       X509_CRL *crl = (X509_CRL *)*pval;
+
+       switch(operation)
+               {
+               case ASN1_OP_NEW_POST:
+               crl->idp = NULL;
+               crl->akid = NULL;
+               break;
 
-ASN1_SEQUENCE_ref(X509_CRL, 0, CRYPTO_LOCK_X509_CRL) = {
+               case ASN1_OP_D2I_POST:
+#ifndef OPENSSL_NO_SHA
+               X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL);
+#endif
+               crl->idp = X509_CRL_get_ext_d2i(crl,
+                               NID_issuing_distribution_point, NULL, NULL);
+               crl->akid = X509_CRL_get_ext_d2i(crl,
+                               NID_authority_key_identifier, NULL, NULL);      
+               break;
+
+               case ASN1_OP_FREE_POST:
+               if (crl->akid)
+                       AUTHORITY_KEYID_free(crl->akid);
+               if (crl->idp)
+                       ISSUING_DIST_POINT_free(crl->idp);
+               break;
+               }
+       return 1;
+       }
+
+ASN1_SEQUENCE_ref(X509_CRL, crl_cb, CRYPTO_LOCK_X509_CRL) = {
        ASN1_SIMPLE(X509_CRL, crl, X509_CRL_INFO),
        ASN1_SIMPLE(X509_CRL, sig_alg, X509_ALGOR),
        ASN1_SIMPLE(X509_CRL, signature, ASN1_BIT_STRING)
@@ -127,6 +147,7 @@ ASN1_SEQUENCE_ref(X509_CRL, 0, CRYPTO_LOCK_X509_CRL) = {
 IMPLEMENT_ASN1_FUNCTIONS(X509_REVOKED)
 IMPLEMENT_ASN1_FUNCTIONS(X509_CRL_INFO)
 IMPLEMENT_ASN1_FUNCTIONS(X509_CRL)
+IMPLEMENT_ASN1_DUP_FUNCTION(X509_CRL)
 
 static int X509_REVOKED_cmp(const X509_REVOKED * const *a,
                        const X509_REVOKED * const *b)
@@ -136,12 +157,6 @@ static int X509_REVOKED_cmp(const X509_REVOKED * const *a,
                (ASN1_STRING *)(*b)->serialNumber));
        }
 
-static int X509_REVOKED_seq_cmp(const X509_REVOKED * const *a,
-                               const X509_REVOKED * const *b)
-       {
-       return((*a)->sequence-(*b)->sequence);
-       }
-
 int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
 {
        X509_CRL_INFO *inf;
@@ -152,6 +167,7 @@ int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
                ASN1err(ASN1_F_X509_CRL_ADD0_REVOKED, ERR_R_MALLOC_FAILURE);
                return 0;
        }
+       inf->enc.modified = 1;
        return 1;
 }