diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libstrongswan/crypto/ca.c | 204 | ||||
-rw-r--r-- | src/libstrongswan/crypto/ca.h | 81 |
2 files changed, 259 insertions, 26 deletions
diff --git a/src/libstrongswan/crypto/ca.c b/src/libstrongswan/crypto/ca.c index f7ffa3841..1a53021b6 100644 --- a/src/libstrongswan/crypto/ca.c +++ b/src/libstrongswan/crypto/ca.c @@ -24,7 +24,10 @@ #include <unistd.h> #include <string.h> #include <stdio.h> +#include <pthread.h> +#include "x509.h" +#include "crl.h" #include "ca.h" #include "certinfo.h" @@ -57,7 +60,7 @@ struct private_ca_info_t { /** * Distinguished Name of the CA */ - const x509_t *cacert; + x509_t *cacert; /** * List of crl URIs @@ -70,9 +73,20 @@ struct private_ca_info_t { linked_list_t *ocspuris; /** + * CRL issued by this ca + */ + crl_t *crl; + + /** * List of certificate info records */ linked_list_t *certinfos; + + /** + * mutex controls access to the elements: + * name, crluris, ocspuris, crl, and certinfos + */ + pthread_mutex_t mutex; }; /** @@ -85,11 +99,103 @@ static bool equals(const private_ca_info_t *this, const private_ca_info_t *that) } /** - * Implements ca_info_t.equals_name + * Implements ca_info_t.equals_name_release_info + */ +static bool equals_name_release_info(private_ca_info_t *this, const char *name) +{ + bool found; + + pthread_mutex_lock(&(this->mutex)); + found = this->name != NULL && streq(this->name, name); + + if (found) + { + this->crluris->destroy_offset(this->crluris, + offsetof(identification_t, destroy)); + this->crluris = linked_list_create(); + + this->ocspuris->destroy_offset(this->ocspuris, + offsetof(identification_t, destroy)); + this->ocspuris = linked_list_create(); + + free(this->name); + this->name = NULL; + } + + pthread_mutex_unlock(&(this->mutex)); + return found; +} + +/** + * Implements ca_info_t.is_crl_issuer */ -static bool equals_name(const private_ca_info_t *this, const char *name) +static bool is_cert_issuer(private_ca_info_t *this, const x509_t *cert) { - return this->name != NULL && streq(this->name, name); + return cert->is_issuer(cert, this->cacert); +} + +/** + * Implements ca_info_t.is_crl_issuer + */ +static bool is_crl_issuer(private_ca_info_t *this, const crl_t *crl) +{ + return crl->is_issuer(crl, this->cacert); +} + +/** + * Implements ca_info_t.has_crl + */ +static bool has_crl(private_ca_info_t *this) +{ + bool found; + + pthread_mutex_lock(&(this->mutex)); + found = this->crl != NULL; + pthread_mutex_unlock(&(this->mutex)); + + return found; +} + +/** + * Implements ca_info_t.add_crl + */ +static void add_crl(private_ca_info_t *this, crl_t *crl) +{ + pthread_mutex_lock(&(this->mutex)); + + if (this->crl) + { + if (crl->is_newer(crl, this->crl)) + { + this->crl->destroy(this->crl); + this->crl = crl; + DBG1(" thisUpdate is newer - existing crl replaced"); + } + else + { + crl->destroy(crl); + DBG1(" thisUpdate is not newer - existing crl retained"); + } + } + else + { + this->crl = crl; + DBG2(" crl added"); + } + + pthread_mutex_unlock(&(this->mutex)); +} + +/** + * Implements ca_info_t.list_crl + */ +static void list_crl(private_ca_info_t *this, FILE *out, bool utc) +{ + pthread_mutex_lock(&(this->mutex)); + + fprintf(out, "%#U\n", this->crl, utc); + + pthread_mutex_unlock(&(this->mutex)); } /** @@ -151,7 +257,9 @@ static void add_crluri(private_ca_info_t *this, chunk_t uri) { identification_t *crluri = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri); + pthread_mutex_lock(&(this->mutex)); add_identification(this->crluris, crluri); + pthread_mutex_unlock(&(this->mutex)); } } @@ -169,19 +277,26 @@ static void add_ocspuri(private_ca_info_t *this, chunk_t uri) { identification_t *ocspuri = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri); + pthread_mutex_lock(&(this->mutex)); add_identification(this->ocspuris, ocspuri); + pthread_mutex_unlock(&(this->mutex)); } } /** - * Implements ca_info_t.add_info + * Implements ca_info_t.add_info. */ void add_info (private_ca_info_t *this, const private_ca_info_t *that) { + pthread_mutex_lock(&(this->mutex)); + if (this->name == NULL && that->name != NULL) { this->name = strdup(that->name); } + + pthread_mutex_unlock(&(this->mutex)); + { identification_t *uri; @@ -193,6 +308,7 @@ void add_info (private_ca_info_t *this, const private_ca_info_t *that) } iterator->destroy(iterator); } + { identification_t *uri; @@ -207,20 +323,57 @@ void add_info (private_ca_info_t *this, const private_ca_info_t *that) } /** - * Implements ca_info_t.release_info + * Implements ca_info_t.get_certificate. */ -static void release_info(private_ca_info_t *this) +static x509_t* get_certificate(private_ca_info_t* this) { - this->crluris->destroy_offset(this->crluris, - offsetof(identification_t, destroy)); - this->crluris = linked_list_create(); + return this->cacert; +} - this->ocspuris->destroy_offset(this->ocspuris, - offsetof(identification_t, destroy)); - this->ocspuris = linked_list_create(); +/** + * Implements ca_info_t.verify_by_crl. + */ +static cert_status_t verify_by_crl(private_ca_info_t* this, const x509_t *cert, + certinfo_t *certinfo) +{ + bool valid_signature; + rsa_public_key_t *issuer_public_key; - free(this->name); - this->name = NULL; + + pthread_mutex_lock(&(this->mutex)); + + if (this->crl == NULL) + { + DBG1("crl not found"); + goto err; + } + DBG2("crl found"); + + issuer_public_key = this->cacert->get_public_key(this->cacert); + valid_signature = this->crl->verify(this->crl, issuer_public_key); + + if (!valid_signature) + { + DBG1("crl signature is invalid"); + goto err; + } + DBG2("crl signature is valid"); + + this->crl->get_status(this->crl, certinfo); + +err: + pthread_mutex_unlock(&(this->mutex)); + return certinfo->get_status(certinfo); +} + +/** + * Implements ca_info_t.verify_by_ocsp. + */ +static cert_status_t verify_by_ocsp(private_ca_info_t* this, const x509_t *cert, + certinfo_t *certinfo) +{ + /* TODO implement function */ + return CERT_UNDEFINED; } /** @@ -234,6 +387,7 @@ static void destroy(private_ca_info_t *this) offsetof(identification_t, destroy)); this->certinfos->destroy_offset(this->certinfos, offsetof(certinfo_t, destroy)); + DESTROY_IF(this->crl); free(this->name); free(this); } @@ -258,6 +412,8 @@ static int print(FILE *stream, const struct printf_info *info, { return fprintf(stream, "(null)"); } + + pthread_mutex_lock(&(this->mutex)); written += fprintf(stream, "%#T", &this->installed, utc); if (this->name) @@ -303,6 +459,7 @@ static int print(FILE *stream, const struct printf_info *info, } iterator->destroy(iterator); } + pthread_mutex_unlock(&(this->mutex)); return written; } @@ -317,7 +474,7 @@ static void __attribute__ ((constructor))print_register() /* * Described in header. */ -ca_info_t *ca_info_create(const char *name, const x509_t *cacert) +ca_info_t *ca_info_create(const char *name, x509_t *cacert) { private_ca_info_t *this = malloc_thing(private_ca_info_t); @@ -328,14 +485,25 @@ ca_info_t *ca_info_create(const char *name, const x509_t *cacert) this->crluris = linked_list_create(); this->ocspuris = linked_list_create(); this->certinfos = linked_list_create(); + this->crl = NULL; + /* initialize the mutex */ + pthread_mutex_init(&(this->mutex), NULL); + /* public functions */ this->public.equals = (bool (*) (const ca_info_t*,const ca_info_t*))equals; - this->public.equals_name = (bool (*) (const ca_info_t*,const char*))equals_name; + this->public.equals_name_release_info = (bool (*) (ca_info_t*,const char*))equals_name_release_info; + this->public.is_cert_issuer = (bool (*) (ca_info_t*,const x509_t*))is_cert_issuer; + this->public.is_crl_issuer = (bool (*) (ca_info_t*,const crl_t*))is_crl_issuer; this->public.add_info = (void (*) (ca_info_t*,const ca_info_t*))add_info; + this->public.add_crl = (void (*) (ca_info_t*,crl_t*))add_crl; + this->public.has_crl = (bool (*) (ca_info_t*))has_crl; + this->public.list_crl = (void (*) (ca_info_t*,FILE*,bool))list_crl; this->public.add_crluri = (void (*) (ca_info_t*,chunk_t))add_crluri; this->public.add_ocspuri = (void (*) (ca_info_t*,chunk_t))add_ocspuri; - this->public.release_info = (void (*) (ca_info_t*))release_info; + this->public.get_certificate = (x509_t* (*) (ca_info_t*))get_certificate; + this->public.verify_by_crl = (cert_status_t (*) (ca_info_t*,const x509_t*,certinfo_t*))verify_by_crl; + this->public.verify_by_ocsp = (cert_status_t (*) (ca_info_t*,const x509_t*,certinfo_t*))verify_by_ocsp; this->public.destroy = (void (*) (ca_info_t*))destroy; return &this->public; diff --git a/src/libstrongswan/crypto/ca.h b/src/libstrongswan/crypto/ca.h index 8b1bd3d71..1b2e33ed9 100644 --- a/src/libstrongswan/crypto/ca.h +++ b/src/libstrongswan/crypto/ca.h @@ -29,6 +29,7 @@ typedef struct ca_info_t ca_info_t; #include <chunk.h> #include "x509.h" +#include "crl.h" /** * @brief X.509 certification authority information record @@ -43,7 +44,7 @@ struct ca_info_t { /** * @brief Compare two ca info records * - * Comparison is doen via the keyid of the ca certificate + * Comparison is done via the keyid of the ca certificate * * @param this first ca info object * @param that second ca info objct @@ -52,12 +53,30 @@ struct ca_info_t { bool (*equals) (const ca_info_t *this, const ca_info_t* that); /** - * @brief Checks if the ca info record has the same name + * @brief If the ca info record has the same name then release the name and URIs * * @param this ca info object * @return TRUE if a match is found */ - bool (*equals_name) (const ca_info_t *this, const char *name); + bool (*equals_name_release_info) (ca_info_t *this, const char *name); + + /** + * @brief Checks if a certificate was issued by this ca + * + * @param this ca info object + * @param cert certificate to be checked + * @return TRUE if the issuing ca has been found + */ + bool (*is_cert_issuer) (ca_info_t *this, const x509_t *cert); + + /** + * @brief Checks if a crl was issued by this ca + * + * @param this ca info object + * @param crl crl to be checked + * @return TRUE if the issuing ca has been found + */ + bool (*is_crl_issuer) (ca_info_t *this, const crl_t *crl); /** * @brief Merges info from a secondary ca info object @@ -68,6 +87,31 @@ struct ca_info_t { void (*add_info) (ca_info_t *this, const ca_info_t *that); /** + * @brief Adds a new or replaces an obsoleted CRL + * + * @param this ca info object + * @param crl crl to be added + */ + void (*add_crl) (ca_info_t *this, crl_t *crl); + + /** + * @brief Does the CA have a CRL? + * + * @param this ca info object + * @return TRUE if crl is available + */ + bool (*has_crl) (ca_info_t *this); + + /** + * @brief List the CRL onto the console + * + * @param this ca info object + * @param utc TRUE - utc + FALSE - local time + */ + void (*list_crl) (ca_info_t *this, FILE *out, bool utc); + + /** * @brief Adds a CRL URI to a list * * @param this ca info object @@ -76,7 +120,7 @@ struct ca_info_t { void (*add_crluri) (ca_info_t *this, chunk_t uri); /** - * @brief Adds a CRL URI to a list + * @brief Adds a OCSP URI to a list * * @param this ca info object * @param uri ocsp uri to be added @@ -84,11 +128,32 @@ struct ca_info_t { void (*add_ocspuri) (ca_info_t *this, chunk_t uri); /** - * @brief Releases the name and URIs of ca info record + * @brief Get the ca certificate + * + * @param this ca info object + * @return ca certificate + */ + x509_t* (*get_certificate) (ca_info_t *this); + + /** + * @brief Verify the status of a certificate by CRL * - * @param this ca info to release + * @param this ca info object + * @param cert certificate to be verified + * @param certinfo detailed certificate status information + * @return certificate status + */ + cert_status_t (*verify_by_crl) (ca_info_t* this, const x509_t* cert, certinfo_t* certinfo); + + /** + * @brief Verify the status of a certificate by OCSP + * + * @param this ca info object + * @param cert certificate to be verified + * @param certinfo detailed certificate status information + * @return certificate status */ - void (*release_info) (ca_info_t *this); + cert_status_t (*verify_by_ocsp) (ca_info_t* this, const x509_t* cert, certinfo_t* certinfo); /** * @brief Destroys a ca info record @@ -107,6 +172,6 @@ struct ca_info_t { * * @ingroup transforms */ -ca_info_t *ca_info_create(const char *name, const x509_t *cacert); +ca_info_t *ca_info_create(const char *name, x509_t *cacert); #endif /* CA_H_ */ |