Added support for delta CRLs to x509 plugin
authorMartin Willi <martin@revosec.ch>
Fri, 17 Dec 2010 15:53:00 +0000 (16:53 +0100)
committerMartin Willi <martin@revosec.ch>
Wed, 5 Jan 2011 15:46:03 +0000 (16:46 +0100)
src/libstrongswan/credentials/builder.c
src/libstrongswan/credentials/builder.h
src/libstrongswan/credentials/certificates/crl.h
src/libstrongswan/plugins/openssl/openssl_crl.c
src/libstrongswan/plugins/x509/x509_crl.c

index 3651e4b..768b9da 100644 (file)
@@ -51,6 +51,7 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END,
        "BUILD_POLICY_CONSTRAINT_INHIBIT",
        "BUILD_X509_FLAG",
        "BUILD_REVOKED_ENUMERATOR",
+       "BUILD_BASE_CRL",
        "BUILD_CHALLENGE_PWD",
        "BUILD_PKCS11_MODULE",
        "BUILD_PKCS11_SLOT",
index 956b1ac..5db3777 100644 (file)
@@ -109,6 +109,8 @@ enum builder_part_t {
        BUILD_X509_FLAG,
        /** enumerator_t over (chunk_t serial, time_t date, crl_reason_t reason) */
        BUILD_REVOKED_ENUMERATOR,
+       /** Base CRL serial for a delta CRL, chunk_t, */
+       BUILD_BASE_CRL,
        /** PKCS#10 challenge password */
        BUILD_CHALLENGE_PWD,
        /** friendly name of a PKCS#11 module, null terminated char* */
index 9425311..2f34974 100644 (file)
@@ -72,6 +72,21 @@ struct crl_t {
        chunk_t (*get_authKeyIdentifier)(crl_t *this);
 
        /**
+        * Is this CRL a delta CRL?
+        *
+        * @param base_crl      gets to baseCrlNumber, if this is a delta CRL
+        * @return                      TRUE if delta CRL
+        */
+       bool (*is_delta_crl)(crl_t *this, chunk_t *base_crl);
+
+       /**
+        * Create an enumerator over Freshest CRL distribution points and issuers.
+        *
+        * @return                      enumerator over x509_cdp_t
+        */
+       enumerator_t* (*create_delta_crl_uri_enumerator)(crl_t *this);
+
+       /**
         * Create an enumerator over all revoked certificates.
         *
         * The enumerator takes 3 pointer arguments:
index 793899d..7786b7f 100644 (file)
@@ -382,6 +382,8 @@ static private_openssl_crl_t *create_empty()
                                },
                                .get_serial = _get_serial,
                                .get_authKeyIdentifier = _get_authKeyIdentifier,
+                               .is_delta_crl = (void*)return_false,
+                               .create_delta_crl_uri_enumerator = (void*)enumerator_create_empty,
                                .create_enumerator = _create_enumerator,
                        },
                },
index 979e0af..06936c8 100644 (file)
@@ -100,6 +100,11 @@ struct private_x509_crl_t {
        linked_list_t *revoked;
 
        /**
+        * List of Freshest CRL distribution points
+        */
+       linked_list_t *crl_uris;
+
+       /**
         * Authority Key Identifier
         */
        chunk_t authKeyIdentifier;
@@ -110,6 +115,11 @@ struct private_x509_crl_t {
        chunk_t authKeySerialNumber;
 
        /**
+        * Number of BaseCRL, if a delta CRL
+        */
+       chunk_t baseCrlNumber;
+
+       /**
         * Signature algorithm
         */
        int algorithm;
@@ -133,9 +143,19 @@ struct private_x509_crl_t {
 /**
  * from x509_cert
  */
-extern chunk_t x509_parse_authorityKeyIdentifier(
-                                                               chunk_t blob, int level0,
-                                                               chunk_t *authKeySerialNumber);
+extern chunk_t x509_parse_authorityKeyIdentifier(chunk_t blob, int level0,
+                                                                                                chunk_t *authKeySerialNumber);
+
+/**
+ * from x509_cert
+ */
+extern void x509_parse_crlDistributionPoints(chunk_t blob, int level0,
+                                                                                        linked_list_t *list);
+
+/**
+ * from x509_cert
+ */
+extern chunk_t x509_build_crlDistributionPoints(linked_list_t *list, int extn);
 
 /**
   * ASN.1 definition of an X.509 certificate revocation list
@@ -288,6 +308,18 @@ static bool parse(private_x509_crl_t *this)
                                                }
                                                this->crlNumber = object;
                                                break;
+                                       case OID_FRESHEST_CRL:
+                                               x509_parse_crlDistributionPoints(object, level,
+                                                                                                                this->crl_uris);
+                                               break;
+                                       case OID_DELTA_CRL_INDICATOR:
+                                               if (!asn1_parse_simple_object(&object, ASN1_INTEGER,
+                                                                                                       level, "deltaCrlIndicator"))
+                                               {
+                                                       goto end;
+                                               }
+                                               this->baseCrlNumber = object;
+                                               break;
                                        default:
                                                if (critical && lib->settings->get_bool(lib->settings,
                                                        "libstrongswan.plugins.x509.enforce_critical", FALSE))
@@ -358,6 +390,26 @@ METHOD(crl_t, get_authKeyIdentifier, chunk_t,
        return this->authKeyIdentifier;
 }
 
+METHOD(crl_t, is_delta_crl, bool,
+       private_x509_crl_t *this, chunk_t *base_crl)
+{
+       if (this->baseCrlNumber.len)
+       {
+               if (base_crl)
+               {
+                       *base_crl = this->baseCrlNumber;
+               }
+               return TRUE;
+       }
+       return FALSE;
+}
+
+METHOD(crl_t, create_delta_crl_uri_enumerator, enumerator_t*,
+       private_x509_crl_t *this)
+{
+       return this->crl_uris->create_enumerator(this->crl_uris);
+}
+
 METHOD(crl_t, create_enumerator, enumerator_t*,
        private_x509_crl_t *this)
 {
@@ -515,18 +567,30 @@ static void revoked_destroy(revoked_t *revoked)
        free(revoked);
 }
 
+/**
+ * Destroy a CDP entry
+ */
+static void cdp_destroy(x509_cdp_t *this)
+{
+       free(this->uri);
+       DESTROY_IF(this->issuer);
+       free(this);
+}
+
 METHOD(certificate_t, destroy, void,
        private_x509_crl_t *this)
 {
        if (ref_put(&this->ref))
        {
                this->revoked->destroy_function(this->revoked, (void*)revoked_destroy);
+               this->crl_uris->destroy_function(this->crl_uris, (void*)cdp_destroy);
                DESTROY_IF(this->issuer);
                free(this->authKeyIdentifier.ptr);
                free(this->encoding.ptr);
                if (this->generated)
                {
                        free(this->crlNumber.ptr);
+                       free(this->baseCrlNumber.ptr);
                        free(this->signature.ptr);
                        free(this->tbsCertList.ptr);
                }
@@ -560,10 +624,13 @@ static private_x509_crl_t* create_empty(void)
                                },
                                .get_serial = _get_serial,
                                .get_authKeyIdentifier = _get_authKeyIdentifier,
+                               .is_delta_crl = _is_delta_crl,
+                               .create_delta_crl_uri_enumerator = _create_delta_crl_uri_enumerator,
                                .create_enumerator = _create_enumerator,
                        },
                },
                .revoked = linked_list_create(),
+               .crl_uris = linked_list_create(),
                .ref = 1,
        );
        return this;
@@ -632,6 +699,7 @@ static bool generate(private_x509_crl_t *this, certificate_t *cert,
                                         private_key_t *key, hash_algorithm_t digest_alg)
 {
        chunk_t extensions = chunk_empty, certList = chunk_empty, serial;
+       chunk_t crlDistributionPoints = chunk_empty, baseCrlNumber = chunk_empty;
        enumerator_t *enumerator;
        crl_reason_t reason;
        time_t date;
@@ -674,8 +742,21 @@ static bool generate(private_x509_crl_t *this, certificate_t *cert,
        }
        enumerator->destroy(enumerator);
 
+       crlDistributionPoints = x509_build_crlDistributionPoints(this->crl_uris,
+                                                                                                                        OID_FRESHEST_CRL);
+
+       if (this->baseCrlNumber.len)
+       {
+               baseCrlNumber =  asn1_wrap(ASN1_SEQUENCE, "mmm",
+                                                       asn1_build_known_oid(OID_DELTA_CRL_INDICATOR),
+                                                       asn1_wrap(ASN1_BOOLEAN, "c",
+                                                               chunk_from_chars(0xFF)),
+                                                       asn1_wrap(ASN1_OCTET_STRING, "m",
+                                                               asn1_integer("c", this->baseCrlNumber)));
+       }
+
        extensions = asn1_wrap(ASN1_CONTEXT_C_0, "m",
-                                       asn1_wrap(ASN1_SEQUENCE, "mm",
+                                       asn1_wrap(ASN1_SEQUENCE, "mmmm",
                                                asn1_wrap(ASN1_SEQUENCE, "mm",
                                                        asn1_build_known_oid(OID_AUTHORITY_KEY_ID),
                                                        asn1_wrap(ASN1_OCTET_STRING, "m",
@@ -685,9 +766,8 @@ static bool generate(private_x509_crl_t *this, certificate_t *cert,
                                                asn1_wrap(ASN1_SEQUENCE, "mm",
                                                        asn1_build_known_oid(OID_CRL_NUMBER),
                                                        asn1_wrap(ASN1_OCTET_STRING, "m",
-                                                               asn1_integer("c", this->crlNumber))
-                                                       )
-                                               ));
+                                                               asn1_integer("c", this->crlNumber))),
+                                               crlDistributionPoints, baseCrlNumber));
 
        this->tbsCertList = asn1_wrap(ASN1_SEQUENCE, "cmcmmmm",
                                                        ASN1_INTEGER_1,
@@ -750,6 +830,29 @@ x509_crl_t *x509_crl_gen(certificate_type_t type, va_list args)
                        case BUILD_REVOKED_ENUMERATOR:
                                read_revoked(crl, va_arg(args, enumerator_t*));
                                continue;
+                       case BUILD_BASE_CRL:
+                               crl->baseCrlNumber = va_arg(args, chunk_t);
+                               crl->baseCrlNumber = chunk_clone(crl->baseCrlNumber);
+                               break;
+                       case BUILD_CRL_DISTRIBUTION_POINTS:
+                       {
+                               enumerator_t *enumerator;
+                               linked_list_t *list;
+                               x509_cdp_t *in, *cdp;
+
+                               list = va_arg(args, linked_list_t*);
+                               enumerator = list->create_enumerator(list);
+                               while (enumerator->enumerate(enumerator, &in))
+                               {
+                                       INIT(cdp,
+                                               .uri = strdup(in->uri),
+                                               .issuer = in->issuer ? in->issuer->clone(in->issuer) : NULL,
+                                       );
+                                       crl->crl_uris->insert_last(crl->crl_uris, cdp);
+                               }
+                               enumerator->destroy(enumerator);
+                               continue;
+                       }
                        case BUILD_END:
                                break;
                        default: