aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2010-05-21 15:52:20 +0200
committerMartin Willi <martin@revosec.ch>2010-05-21 16:25:51 +0200
commit13c593f126eea2b64cedd8764652d23b77c97f62 (patch)
tree826a5ef5ec3301d27eea7f082b55463d1a84e342
parentaab861608a06353fe297da66f49957ce12529bc1 (diff)
downloadstrongswan-13c593f126eea2b64cedd8764652d23b77c97f62.tar.bz2
strongswan-13c593f126eea2b64cedd8764652d23b77c97f62.tar.xz
Added support for CRL generation to x509 plugin
-rw-r--r--src/libstrongswan/credentials/builder.c1
-rw-r--r--src/libstrongswan/credentials/builder.h2
-rw-r--r--src/libstrongswan/plugins/x509/x509_crl.c189
-rw-r--r--src/libstrongswan/plugins/x509/x509_crl.h9
-rw-r--r--src/libstrongswan/plugins/x509/x509_plugin.c4
5 files changed, 202 insertions, 3 deletions
diff --git a/src/libstrongswan/credentials/builder.c b/src/libstrongswan/credentials/builder.c
index 8be1c1576..cfb708e33 100644
--- a/src/libstrongswan/credentials/builder.c
+++ b/src/libstrongswan/credentials/builder.c
@@ -44,6 +44,7 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END,
"BUILD_OCSP_ACCESS_LOCATIONS",
"BUILD_PATHLEN",
"BUILD_X509_FLAG",
+ "BUILD_REVOKED_ENUMERATOR",
"BUILD_SMARTCARD_KEYID",
"BUILD_SMARTCARD_PIN",
"BUILD_RSA_MODULUS",
diff --git a/src/libstrongswan/credentials/builder.h b/src/libstrongswan/credentials/builder.h
index 62a6ffaaf..ffb09f72a 100644
--- a/src/libstrongswan/credentials/builder.h
+++ b/src/libstrongswan/credentials/builder.h
@@ -101,6 +101,8 @@ enum builder_part_t {
BUILD_PATHLEN,
/** enforce an additional X509 flag, x509_flag_t */
BUILD_X509_FLAG,
+ /** enumerator_t over (chunk_t serial, time_t date, crl_reason_t reason) */
+ BUILD_REVOKED_ENUMERATOR,
/** key ID of a key on a smartcard, null terminated char* ([slot:]keyid) */
BUILD_SMARTCARD_KEYID,
/** pin to access a key on a smartcard, null terminated char* */
diff --git a/src/libstrongswan/plugins/x509/x509_crl.c b/src/libstrongswan/plugins/x509/x509_crl.c
index e171e4c2d..f3d5c6d73 100644
--- a/src/libstrongswan/plugins/x509/x509_crl.c
+++ b/src/libstrongswan/plugins/x509/x509_crl.c
@@ -26,6 +26,7 @@ typedef struct revoked_t revoked_t;
#include <asn1/asn1.h>
#include <asn1/asn1_parser.h>
#include <credentials/certificates/x509.h>
+#include <credentials/keys/private_key.h>
#include <utils/linked_list.h>
/**
@@ -119,6 +120,11 @@ struct private_x509_crl_t {
chunk_t signature;
/**
+ * has this CRL been generated
+ */
+ bool generated;
+
+ /**
* reference counter
*/
refcount_t ref;
@@ -236,7 +242,7 @@ static bool parse(private_x509_crl_t *this)
break;
case CRL_OBJ_REVOCATION_DATE:
revoked = malloc_thing(revoked_t);
- revoked->serial = userCertificate;
+ revoked->serial = chunk_clone(userCertificate);
revoked->date = asn1_parse_time(object, level);
revoked->reason = CRL_REASON_UNSPECIFIED;
this->revoked->insert_last(this->revoked, (void *)revoked);
@@ -267,7 +273,6 @@ static bool parse(private_x509_crl_t *this)
}
else if (extn_oid == OID_AUTHORITY_KEY_ID)
{
-
this->authKeyIdentifier = x509_parse_authorityKeyIdentifier(object,
level, &this->authKeySerialNumber);
}
@@ -478,15 +483,30 @@ METHOD(certificate_t, equals, bool,
return equal;
}
+/**
+ * Destroy a revoked_t entry
+ */
+static void revoked_destroy(revoked_t *revoked)
+{
+ free(revoked->serial.ptr);
+ free(revoked);
+}
+
METHOD(certificate_t, destroy, void,
private_x509_crl_t *this)
{
if (ref_put(&this->ref))
{
- this->revoked->destroy_function(this->revoked, free);
+ this->revoked->destroy_function(this->revoked, (void*)revoked_destroy);
DESTROY_IF(this->issuer);
free(this->authKeyIdentifier.ptr);
free(this->encoding.ptr);
+ if (this->generated)
+ {
+ free(this->crlNumber.ptr);
+ free(this->signature.ptr);
+ free(this->tbsCertList.ptr);
+ }
free(this);
}
}
@@ -561,3 +581,166 @@ x509_crl_t *x509_crl_load(certificate_type_t type, va_list args)
return NULL;
};
+/**
+ * Read certificate status from enumerator, copy to crl
+ */
+static void read_revoked(private_x509_crl_t *crl, enumerator_t *enumerator)
+{
+ revoked_t *revoked;
+ chunk_t serial;
+ time_t date;
+ crl_reason_t reason;
+
+ while (enumerator->enumerate(enumerator, &serial, &date, &reason))
+ {
+ INIT(revoked,
+ .serial = chunk_clone(serial),
+ .date = date,
+ .reason = reason,
+ );
+ crl->revoked->insert_last(crl->revoked, revoked);
+ }
+}
+
+/**
+ * Generate CRL encoding, sign CRL
+ */
+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;
+ enumerator_t *enumerator;
+ crl_reason_t reason;
+ time_t date;
+ x509_t *x509;
+
+ x509 = (x509_t*)cert;
+
+ this->issuer = cert->get_issuer(cert);
+ this->issuer = this->issuer->clone(this->issuer);
+
+ this->authKeyIdentifier = chunk_clone(x509->get_authKeyIdentifier(x509));
+
+ /* select signature scheme */
+ this->algorithm = hasher_signature_algorithm_to_oid(digest_alg,
+ key->get_type(key));
+ if (this->algorithm == OID_UNKNOWN)
+ {
+ return FALSE;
+ }
+
+ enumerator = create_enumerator(this);
+ while (enumerator->enumerate(enumerator, &serial, &date, &reason))
+ {
+ chunk_t revoked, entry_ext = chunk_empty;
+
+ if (reason != CRL_REASON_UNSPECIFIED)
+ {
+ entry_ext = asn1_wrap(ASN1_SEQUENCE, "m",
+ asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_build_known_oid(OID_CRL_REASON_CODE),
+ asn1_wrap(ASN1_OCTET_STRING, "m",
+ asn1_wrap(ASN1_ENUMERATED, "c",
+ chunk_from_chars(reason)))));
+ }
+ revoked = asn1_wrap(ASN1_SEQUENCE, "mmm",
+ asn1_integer("c", serial),
+ asn1_from_time(&date, ASN1_UTCTIME),
+ entry_ext);
+ certList = chunk_cat("mm", certList, revoked);
+ }
+ enumerator->destroy(enumerator);
+
+ extensions = asn1_wrap(ASN1_CONTEXT_C_0, "m",
+ asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_build_known_oid(OID_AUTHORITY_KEY_ID),
+ asn1_wrap(ASN1_OCTET_STRING, "m",
+ asn1_wrap(ASN1_SEQUENCE, "m",
+ asn1_wrap(ASN1_CONTEXT_S_0, "c",
+ this->authKeyIdentifier)))),
+ asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_build_known_oid(OID_CRL_NUMBER),
+ asn1_wrap(ASN1_OCTET_STRING, "m",
+ asn1_integer("c", this->crlNumber))
+ )
+ ));
+
+ this->tbsCertList = asn1_wrap(ASN1_SEQUENCE, "cmcmmmm",
+ ASN1_INTEGER_1,
+ asn1_algorithmIdentifier(this->algorithm),
+ this->issuer->get_encoding(this->issuer),
+ asn1_from_time(&this->thisUpdate, ASN1_UTCTIME),
+ asn1_from_time(&this->nextUpdate, ASN1_UTCTIME),
+ asn1_wrap(ASN1_SEQUENCE, "m", certList),
+ extensions);
+
+ if (!key->sign(key, signature_scheme_from_oid(this->algorithm),
+ this->tbsCertList, &this->signature))
+ {
+ return FALSE;
+ }
+ this->encoding = asn1_wrap(ASN1_SEQUENCE, "cmm",
+ this->tbsCertList,
+ asn1_algorithmIdentifier(this->algorithm),
+ asn1_bitstring("c", this->signature));
+ return TRUE;
+}
+
+/**
+ * See header.
+ */
+x509_crl_t *x509_crl_gen(certificate_type_t type, va_list args)
+{
+ hash_algorithm_t digest_alg = HASH_SHA1;
+ private_x509_crl_t *crl;
+ certificate_t *cert = NULL;
+ private_key_t *key = NULL;
+
+ crl = create_empty();
+ crl->generated = TRUE;
+ while (TRUE)
+ {
+ builder_part_t part = va_arg(args, builder_part_t);
+
+ switch (part)
+ {
+ case BUILD_SIGNING_KEY:
+ key = va_arg(args, private_key_t*);
+ continue;
+ case BUILD_SIGNING_CERT:
+ cert = va_arg(args, certificate_t*);
+ continue;
+ case BUILD_NOT_BEFORE_TIME:
+ crl->thisUpdate = va_arg(args, time_t);
+ continue;
+ case BUILD_NOT_AFTER_TIME:
+ crl->nextUpdate = va_arg(args, time_t);
+ continue;
+ case BUILD_SERIAL:
+ crl->crlNumber = va_arg(args, chunk_t);
+ crl->crlNumber = chunk_clone(crl->crlNumber);
+ continue;
+ case BUILD_DIGEST_ALG:
+ digest_alg = va_arg(args, int);
+ continue;
+ case BUILD_REVOKED_ENUMERATOR:
+ read_revoked(crl, va_arg(args, enumerator_t*));
+ continue;
+ case BUILD_END:
+ break;
+ default:
+ destroy(crl);
+ return NULL;
+ }
+ break;
+ }
+
+ if (key && cert && cert->get_type(cert) == CERT_X509 &&
+ generate(crl, cert, key, digest_alg))
+ {
+ return &crl->public;
+ }
+ destroy(crl);
+ return NULL;
+}
diff --git a/src/libstrongswan/plugins/x509/x509_crl.h b/src/libstrongswan/plugins/x509/x509_crl.h
index 890650162..e8fe74e81 100644
--- a/src/libstrongswan/plugins/x509/x509_crl.h
+++ b/src/libstrongswan/plugins/x509/x509_crl.h
@@ -46,4 +46,13 @@ struct x509_crl_t {
*/
x509_crl_t *x509_crl_load(certificate_type_t type, va_list args);
+/**
+ * Generate a X.509 CRL.
+ *
+ * @param type certificate type, CERT_X509_CRL only
+ * @param args builder_part_t argument list
+ * @return X.509 CRL, NULL on failure
+ */
+x509_crl_t *x509_crl_gen(certificate_type_t type, va_list args);
+
#endif /** X509_CRL_H_ @}*/
diff --git a/src/libstrongswan/plugins/x509/x509_plugin.c b/src/libstrongswan/plugins/x509/x509_plugin.c
index e71c55efc..8391781e2 100644
--- a/src/libstrongswan/plugins/x509/x509_plugin.c
+++ b/src/libstrongswan/plugins/x509/x509_plugin.c
@@ -52,6 +52,8 @@ static void destroy(private_x509_plugin_t *this)
lib->creds->remove_builder(lib->creds,
(builder_function_t)x509_crl_load);
lib->creds->remove_builder(lib->creds,
+ (builder_function_t)x509_crl_gen);
+ lib->creds->remove_builder(lib->creds,
(builder_function_t)x509_ocsp_request_gen);
lib->creds->remove_builder(lib->creds,
(builder_function_t)x509_ocsp_response_load);
@@ -81,6 +83,8 @@ plugin_t *x509_plugin_create()
(builder_function_t)x509_ac_load);
lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
(builder_function_t)x509_crl_load);
+ lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
+ (builder_function_t)x509_crl_gen);
lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST,
(builder_function_t)x509_ocsp_request_gen);
lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_OCSP_RESPONSE,