bool (*has_rsa_private_key) (credential_store_t *this, rsa_public_key_t *pubkey);
/**
+ * @brief Verify an X.509 certificate up to trust anchor including revocation checks
+ *
+ * @param this calling object
+ * @param cert certificate to be verified
+ * @param until time until which the cert can be trusted
+ * @return TRUE if trusted
+ */
+ bool (*verify) (credential_store_t *this, const x509_t *cert, time_t *until);
+
+ /**
* @brief If an end certificate does not already exists in the credential store then add it.
*
* @param this calling object
* @return pointer to the added or already existing certificate
*/
x509_t* (*add_ca_certificate) (credential_store_t *this, x509_t *cert);
-
+
/**
* @brief Lists all certificates kept in the local credential store.
*
#include <string.h>
#include <pthread.h>
-#include "local_credential_store.h"
-
#include <utils/lexparser.h>
#include <utils/linked_list.h>
#include <utils/logger_manager.h>
+#include <crypto/certinfo.h>
+#include <crypto/rsa/rsa_public_key.h>
#include <crypto/x509.h>
#include <crypto/crl.h>
-#define PATH_BUF 256
+#include "local_credential_store.h"
+
+#define PATH_BUF 256
+#define MAX_CA_PATH_LEN 7
typedef struct private_local_credential_store_t private_local_credential_store_t;
}
/**
+ * Implementation of credential_store_t.get_issuer_certificate.
+ */
+static x509_t* get_issuer_certificate(private_local_credential_store_t *this, const x509_t *cert)
+{
+ x509_t *issuer_cert = NULL;
+
+ iterator_t *iterator = this->ca_certs->create_iterator(this->ca_certs, TRUE);
+
+ while (iterator->has_next(iterator))
+ {
+ x509_t *current_cert;
+
+ iterator->current(iterator, (void**)¤t_cert);
+ if (cert->is_issuer(cert, current_cert))
+ {
+ issuer_cert = current_cert;
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+
+ return issuer_cert;
+}
+
+/**
+ * Implementation of credential_store_t.get_crl.
+ */
+static crl_t* get_crl(private_local_credential_store_t *this, const x509_t *issuer)
+{
+ crl_t *crl = NULL;
+
+ iterator_t *iterator = this->crls->create_iterator(this->crls, TRUE);
+
+ while (iterator->has_next(iterator))
+ {
+ crl_t *current_crl;
+
+ iterator->current(iterator, (void**)¤t_crl);
+ if (current_crl->is_issuer(current_crl, issuer))
+ {
+ crl = current_crl;
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+
+ return crl;
+}
+
+/**
+ * Verify the certificate status using CRLs
+ */
+static cert_status_t verify_by_crl(private_local_credential_store_t* this, const x509_t *cert,
+ const x509_t *issuer_cert, certinfo_t *certinfo)
+{
+ crl_t *crl;
+ bool valid_signature;
+ rsa_public_key_t *issuer_public_key;
+
+
+ pthread_mutex_lock(&(this->crls_mutex));
+
+ crl = get_crl(this, issuer_cert);
+ if (crl == NULL)
+ {
+ this->logger->log(this->logger, ERROR, "crl not found");
+ goto err;
+ }
+ this->logger->log(this->logger, CONTROL|LEVEL1, "crl found");
+
+ issuer_public_key = issuer_cert->get_public_key(issuer_cert);
+ valid_signature = crl->verify(crl, issuer_public_key);
+ issuer_public_key->destroy(issuer_public_key);
+
+ if (!valid_signature)
+ {
+ this->logger->log(this->logger, ERROR, "crl signature is invalid");
+ goto err;
+ }
+ this->logger->log(this->logger, CONTROL|LEVEL1, "crl signature is valid");
+
+ crl->get_status(crl, certinfo);
+
+err:
+ pthread_mutex_unlock(&(this->crls_mutex));
+ return certinfo->get_status(certinfo);
+}
+
+/**
+ * Verify the certificate status using OCSP
+ */
+static cert_status_t verify_by_ocsp(private_local_credential_store_t* this,
+ const x509_t *cert, certinfo_t *certinfo)
+{
+ /* TODO implement function */
+ return CERT_UNDEFINED;
+}
+
+/**
+ * Remove a public key for the linked list
+ */
+static void remove_public_key(private_local_credential_store_t *this, const x509_t *cert)
+{
+ /* TODO implement function */
+}
+
+/**
+ * Implementation of credential_store_t.verify.
+ */
+static bool verify(private_local_credential_store_t *this, const x509_t *cert, time_t *until)
+{
+ int pathlen;
+
+ *until = UNDEFINED_TIME;
+
+ for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
+ {
+ err_t ugh = NULL;
+ x509_t *issuer_cert;
+ rsa_public_key_t *issuer_public_key;
+ bool valid_signature;
+
+ identification_t *subject = cert->get_subject(cert);
+ identification_t *issuer = cert->get_issuer(cert);
+
+ this->logger->log(this->logger, CONTROL|LEVEL1, "subject: '%s'", subject->get_string(subject));
+ this->logger->log(this->logger, CONTROL|LEVEL1, "issuer: '%s'", issuer->get_string(issuer));
+
+ ugh = cert->is_valid(cert, until);
+ if (ugh != NULL)
+ {
+ this->logger->log(this->logger, ERROR, "certificate %s", ugh);
+ return FALSE;
+ }
+ this->logger->log(this->logger, CONTROL|LEVEL1, "certificate is valid");
+
+ issuer_cert = get_issuer_certificate(this, cert);
+ if (issuer_cert == NULL)
+ {
+ this->logger->log(this->logger, ERROR, "issuer certificate not found");
+ return FALSE;
+ }
+ this->logger->log(this->logger, CONTROL|LEVEL1, "issuer certificate found");
+
+ issuer_public_key = issuer_cert->get_public_key(issuer_cert);
+ valid_signature = cert->verify(cert, issuer_public_key);
+ issuer_public_key->destroy(issuer_public_key);
+
+ if (!valid_signature)
+ {
+ this->logger->log(this->logger, ERROR, "certificate signature is invalid");
+ return FALSE;
+ }
+ this->logger->log(this->logger, CONTROL|LEVEL1, "certificate signature is valid");
+
+ /* check if cert is a self-signed root ca */
+ if (pathlen > 0 && cert->is_self_signed(cert))
+ {
+ this->logger->log(this->logger, CONTROL|LEVEL1, "reached self-signed root ca");
+ return TRUE;
+ }
+ else
+ {
+ time_t nextUpdate;
+ cert_status_t status;
+ certinfo_t *certinfo = certinfo_create(cert->get_serialNumber(cert));
+
+ certinfo->set_nextUpdate(certinfo, *until);
+
+ /* first check certificate revocation using ocsp */
+ status = verify_by_ocsp(this, cert, certinfo);
+
+ /* if ocsp service is not available then fall back to crl */
+ if ((status == CERT_UNDEFINED) || (status == CERT_UNKNOWN && this->strict))
+ {
+ status = verify_by_crl(this, cert, issuer_cert, certinfo);
+ }
+
+ nextUpdate = certinfo->get_nextUpdate(certinfo);
+
+ switch (status)
+ {
+ case CERT_GOOD:
+ /* if status information is stale */
+ if (this->strict && nextUpdate < time(NULL))
+ {
+ this->logger->log(this->logger, CONTROL|LEVEL1, "certificate is good but status is stale");
+ remove_public_key(this, cert);
+ return FALSE;
+ }
+ this->logger->log(this->logger, CONTROL|LEVEL1, "certificate is good");
+
+ /* with strict crl policy the public key must have the same
+ * lifetime as the validity of the ocsp status or crl lifetime
+ */
+ if (this->strict && nextUpdate < *until)
+ *until = nextUpdate;
+ break;
+ case CERT_REVOKED:
+ {
+ u_char buf[TIMETOA_BUF];
+ time_t revocationTime = certinfo->get_revocationTime(certinfo);
+
+ timetoa(buf, TIMETOA_BUF, &revocationTime, TRUE);
+ this->logger->log(this->logger, ERROR, "certificate was revoked on %s, reason: %s",
+ buf, certinfo->get_revocationReason(certinfo));
+ remove_public_key(this, cert);
+ return FALSE;
+ }
+ case CERT_UNKNOWN:
+ case CERT_UNDEFINED:
+ default:
+ this->logger->log(this->logger, CONTROL|LEVEL1, "certificate status unknown");
+ if (this->strict)
+ {
+ remove_public_key(this, cert);
+ return FALSE;
+ }
+ break;
+ }
+ certinfo->destroy(certinfo);
+ }
+ /* go up one step in the trust chain */
+ cert = issuer_cert;
+ }
+ this->logger->log(this->logger, ERROR, "maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN);
+ return FALSE;
+}
+
+/**
* Add a unique certificate to a linked list
*/
static x509_t* add_certificate(linked_list_t *certs, x509_t *cert)
this->public.credential_store.get_rsa_private_key = (rsa_private_key_t*(*)(credential_store_t*,rsa_public_key_t*))get_rsa_private_key;
this->public.credential_store.has_rsa_private_key = (bool(*)(credential_store_t*,rsa_public_key_t*))has_rsa_private_key;
this->public.credential_store.get_rsa_public_key = (rsa_public_key_t*(*)(credential_store_t*,identification_t*))get_rsa_public_key;
+ this->public.credential_store.verify = (bool(*)(credential_store_t*,const x509_t*,time_t*))verify;
this->public.credential_store.add_end_certificate = (x509_t*(*)(credential_store_t*,x509_t*))add_end_certificate;
this->public.credential_store.add_ca_certificate = (x509_t*(*)(credential_store_t*,x509_t*))add_ca_certificate;
this->public.credential_store.log_certificates = (void(*)(credential_store_t*,logger_t*,bool))log_certificates;
{
identification_t *id = *idp;
identification_t *subject = cert->get_subject(cert);
+ time_t until;
err_t ugh = cert->is_valid(cert, NULL);
id = subject;
*idp = id->clone(id);
}
+ /* test output */
+ if (charon->credentials->verify(charon->credentials, cert, &until))
+ {
+ char buf[TIMETOA_BUF];
+
+ timetoa(buf, TIMETOA_BUF, &until, TRUE);
+ logger->log(logger, CONTROL, " end entity certificate is trusted until %s", buf);
+ cert->set_until(cert, until);
+ }
+ else
+ {
+ logger->log(logger, ERROR, " end entity certificate is not trusted");
+ }
+ /* end of test output */
return charon->credentials->add_end_certificate(charon->credentials, cert);
}
return NULL;
}
if (msg->add_conn.me.cert)
{
- x509_t *cert = load_end_certificate(msg->add_conn.me.cert, &my_id, this->stroke_logger);
+ x509_t *cert = load_end_certificate(msg->add_conn.me.cert, &my_id, this->logger);
if (my_ca == NULL && !my_ca_same && cert)
{
}
if (msg->add_conn.other.cert)
{
- x509_t *cert = load_end_certificate(msg->add_conn.other.cert, &other_id, this->stroke_logger);
+ x509_t *cert = load_end_certificate(msg->add_conn.other.cert, &other_id, this->logger);
if (other_ca == NULL && !other_ca_same && cert)
{
crypto/hashers/md5_hasher.c crypto/hashers/md5_hasher.h \
crypto/prf_plus.h crypto/prf_plus.c \
crypto/hmac.c crypto/hmac.h \
+crypto/certinfo.c crypto/certinfo.h \
crypto/x509.c crypto/x509.h \
crypto/crl.c crypto/crl.h \
crypto/diffie_hellman.c crypto/diffie_hellman.h \
--- /dev/null
+/**
+ * @file certinfo.c
+ *
+ * @brief Implementation of certinfo_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2006 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <time.h>
+
+#include <types.h>
+#include <definitions.h>
+
+#include "certinfo.h"
+
+typedef struct private_certinfo_t private_certinfo_t;
+
+/**
+ * Private data of a certinfo_t object.
+ */
+struct private_certinfo_t {
+ /**
+ * Public interface for this certificate status information object.
+ */
+ certinfo_t public;
+
+ /**
+ * Serial number of the certificate
+ */
+ chunk_t serialNumber;
+
+ /**
+ * Certificate status
+ */
+ cert_status_t status;
+
+ /**
+ * Time when the certificate status info was generated
+ */
+ time_t thisUpdate;
+
+ /**
+ * Time when an updated certifcate status info will be available
+ */
+ time_t nextUpdate;
+
+ /**
+ * Time of certificate revocation
+ */
+ time_t revocationTime;
+
+ /**
+ * Reason of certificate revocation
+ */
+ crl_reason_t revocationReason;
+};
+
+/**
+ * RFC 2459 CRL reason codes
+ */
+static const char *const crl_reason_name[] = {
+ "unspecified",
+ "key compromise",
+ "ca compromise",
+ "affiliation changed",
+ "superseded",
+ "cessation of operation",
+ "certificate hold",
+ "reason #7",
+ "remove from crl"
+ };
+
+enum_names crl_reason_names =
+ { REASON_UNSPECIFIED, REASON_REMOVE_FROM_CRL, crl_reason_name, NULL};
+
+/**
+ * Implements certinfo_t.get_serialNumber
+ */
+static chunk_t get_serialNumber(const private_certinfo_t *this)
+{
+ return this->serialNumber;
+}
+
+/**
+ * Implements certinfo_t.set_status
+ */
+static void set_status(private_certinfo_t *this, cert_status_t status)
+{
+ this->status = status;
+}
+
+/**
+ * Implements certinfo_t.get_status
+ */
+static cert_status_t get_status(const private_certinfo_t *this)
+{
+ return this->status;
+}
+
+/**
+ * Implements certinfo_t.set_nextUpdate
+ */
+static void set_nextUpdate(private_certinfo_t *this, time_t nextUpdate)
+{
+ this->nextUpdate = nextUpdate;
+}
+
+/**
+ * Implements certinfo_t.get_nextUpdate
+ */
+static time_t get_nextUpdate(const private_certinfo_t *this)
+{
+ return this->nextUpdate;
+}
+
+/**
+ * Implements certinfo_t.set_revocationTime
+ */
+static void set_revocationTime(private_certinfo_t *this, time_t revocationTime)
+{
+ this->revocationTime = revocationTime;
+}
+
+/**
+ * Implements certinfo_t.get_revocationTime
+ */
+static time_t get_revocationTime(const private_certinfo_t *this)
+{
+ return this->revocationTime;
+}
+
+/**
+ * Implements certinfo_t.set_revocationReason
+ */
+static void set_revocationReason(private_certinfo_t *this, crl_reason_t reason)
+{
+ this->revocationReason = reason;
+}
+
+/**
+ * Implements certinfo_t.get_revocationReason
+ */
+static const char *get_revocationReason(const private_certinfo_t *this)
+{
+ return enum_name(&crl_reason_names, this->revocationReason);
+}
+
+/**
+ * Implements certinfo_t.destroy
+ */
+static void destroy(private_certinfo_t *this)
+{
+ free(this->serialNumber.ptr);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+certinfo_t *certinfo_create(chunk_t serial)
+{
+ private_certinfo_t *this = malloc_thing(private_certinfo_t);
+
+ /* initialize */
+ this->serialNumber = chunk_clone(serial);
+ this->status = CERT_UNDEFINED;
+ this->nextUpdate = UNDEFINED_TIME;
+ this->revocationTime = UNDEFINED_TIME;
+ this->revocationReason = REASON_UNSPECIFIED;
+
+ /* public functions */
+ this->public.get_serialNumber = (chunk_t (*) (const certinfo_t*))get_serialNumber;
+ this->public.set_status = (void (*) (certinfo_t*,cert_status_t))set_status;
+ this->public.get_status = (cert_status_t (*) (const certinfo_t*))get_status;
+ this->public.set_nextUpdate = (void (*) (certinfo_t*,time_t))set_nextUpdate;
+ this->public.get_nextUpdate = (time_t (*) (const certinfo_t*))get_nextUpdate;
+ this->public.set_revocationTime = (void (*) (certinfo_t*,time_t))set_revocationTime;
+ this->public.get_revocationTime = (time_t (*) (const certinfo_t*))get_revocationTime;
+ this->public.set_revocationReason = (void (*) (certinfo_t*, crl_reason_t))set_revocationReason;
+ this->public.get_revocationReason = (const char *(*) (const certinfo_t*))get_revocationReason;
+ this->public.destroy = (void (*) (certinfo_t*))destroy;
+
+ return &this->public;
+}
--- /dev/null
+/**
+ * @file certinfo.h
+ *
+ * @brief Interface of certinfo_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2006 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef CERTINFO_H_
+#define CERTINFO_H_
+
+#include <types.h>
+#include <definitions.h>
+
+/**
+ * RFC 2560 OCSP - certificate status
+ */
+typedef enum {
+ CERT_GOOD = 0,
+ CERT_REVOKED = 1,
+ CERT_UNKNOWN = 2,
+ CERT_UNDEFINED = 3
+} cert_status_t;
+
+/**
+ * RFC 2459 CRL reason codes
+ */
+
+extern enum_names crl_reason_names;
+
+typedef enum {
+ REASON_UNSPECIFIED = 0,
+ REASON_KEY_COMPROMISE = 1,
+ REASON_CA_COMPROMISE = 2,
+ REASON_AFFILIATION_CHANGED = 3,
+ REASON_SUPERSEDED = 4,
+ REASON_CESSATION_OF_OPERATON = 5,
+ REASON_CERTIFICATE_HOLD = 6,
+ REASON_REMOVE_FROM_CRL = 8
+} crl_reason_t;
+
+typedef struct certinfo_t certinfo_t;
+
+/**
+ * @brief X.509 certificate status information
+ *
+ *
+ * @ingroup transforms
+ */
+struct certinfo_t {
+
+ /**
+ * @brief Get serial number
+ *
+ *
+ * @param this calling object
+ * @return serialNumber
+ */
+ chunk_t (*get_serialNumber) (const certinfo_t *this);
+
+ /**
+ * @brief Set certificate status
+ *
+ *
+ * @param this calling object
+ * @param status status
+ */
+ void (*set_status) (certinfo_t *this, cert_status_t status);
+
+ /**
+ * @brief Get certificate status
+ *
+ *
+ * @param this calling object
+ * @return status
+ */
+ cert_status_t (*get_status) (const certinfo_t *this);
+
+ /**
+ * @brief Set nextUpdate
+ *
+ *
+ * @param this calling object
+ * @return nextUpdate
+ */
+ void (*set_nextUpdate) (certinfo_t *this, time_t nextUpdate);
+
+ /**
+ * @brief Get nextUpdate
+ *
+ *
+ * @param this calling object
+ * @return nextUpdate
+ */
+ time_t (*get_nextUpdate) (const certinfo_t *this);
+
+ /**
+ * @brief Set revocationTime
+ *
+ *
+ * @param this calling object
+ * @param revocationTime revocationTime
+ */
+ void (*set_revocationTime) (certinfo_t *this, time_t revocationTime);
+
+ /**
+ * @brief Get revocationTime
+ *
+ *
+ * @param this calling object
+ * @return revocationTime
+ */
+ time_t (*get_revocationTime) (const certinfo_t *this);
+
+ /**
+ * @brief Set revocationReason
+ *
+ *
+ * @param this calling object
+ * @param reason revocationReason
+ */
+ void (*set_revocationReason) (certinfo_t *this, crl_reason_t reason);
+
+ /**
+ * @brief Get revocationReason
+ *
+ *
+ * @param this calling object
+ * @return revocationReason
+ */
+ const char *(*get_revocationReason) (const certinfo_t *this);
+
+ /**
+ * @brief Destroys the certinfo_t object.
+ *
+ * @param this crl to destroy
+ */
+ void (*destroy) (certinfo_t *this);
+
+};
+
+/**
+ * @brief Create a certinfo_t object.
+ *
+ * @param serial chunk serial number of the certificate
+ * @return created certinfo_t object
+ *
+ * @ingroup transforms
+ */
+certinfo_t *certinfo_create(chunk_t serial);
+
+#endif /* CERTINFO_H_ */
#include <utils/linked_list.h>
#include <utils/identification.h>
-#include "crl.h"
+#include "certinfo.h"
#include "x509.h"
+#include "crl.h"
#define CRL_WARNING_INTERVAL 7 /* days */
chunk_t signature;
};
-/* ASN.1 definition of an X.509 certificate revocation list */
-
+/**
+ * ASN.1 definition of an X.509 certificate revocation list
+ */
static const asn1Object_t crlObjects[] = {
{ 0, "certificateList", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
{ 1, "tbsCertList", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
{
reason = *object.ptr;
}
- /* TODO logger->log(logger, CONTROL|LEVEL2, " '%s'", enum_name(&crl_reason_names, reason)) */
+ logger->log(logger, CONTROL|LEVEL2, " '%s'", enum_name(&crl_reason_names, reason));
+
return reason;
}
}
/**
- * Implements crl_t.is_newer
- */
-static bool is_newer(const private_crl_t *this, const private_crl_t *other)
-{
- return (this->nextUpdate > other->nextUpdate);
-}
-
-/**
* Implements crl_t.get_issuer
*/
static identification_t *get_issuer(const private_crl_t *this)
}
/**
- * destroy
+ * Implements crl_t.is_issuer
+ */
+static bool is_issuer(const private_crl_t *this, const x509_t *issuer)
+{
+ return (this->authKeyID.ptr)
+ ? chunk_equals(this->authKeyID, issuer->get_subjectKeyID(issuer))
+ : (this->issuer->equals(this->issuer, issuer->get_subject(issuer))
+ && chunk_equals_or_null(this->authKeySerialNumber, issuer->get_serialNumber(issuer)));
+}
+
+/**
+ * Implements crl_t.is_newer
+ */
+static bool is_newer(const private_crl_t *this, const private_crl_t *other)
+{
+ return (this->nextUpdate > other->nextUpdate);
+}
+
+/**
+ * Implements crl_t.verify
+ */
+static bool verify(const private_crl_t *this, const rsa_public_key_t *signer)
+{
+ return signer->verify_emsa_pkcs1_signature(signer, this->tbsCertList, this->signature);
+}
+
+/**
+ * Implements crl_t.get_status
+ */
+static void get_status(const private_crl_t *this, certinfo_t *certinfo)
+{
+ chunk_t serialNumber = certinfo->get_serialNumber(certinfo);
+ iterator_t *iterator = this->revokedCertificates->create_iterator(this->revokedCertificates, TRUE);
+
+ certinfo->set_nextUpdate(certinfo, this->nextUpdate);
+ certinfo->set_status(certinfo, CERT_GOOD);
+
+ while (iterator->has_next(iterator))
+ {
+ revokedCert_t *revokedCert;
+
+ iterator->current(iterator, (void**)&revokedCert);
+ if (chunk_equals(serialNumber, revokedCert->userCertificate))
+ {
+ certinfo->set_status(certinfo, CERT_REVOKED);
+ certinfo->set_revocationTime(certinfo, revokedCert->revocationDate);
+ certinfo->set_revocationReason(certinfo, revokedCert->revocationReason);
+ break;
+ }
+ }
+ iterator->destroy(iterator);
+}
+
+/**
+ * Implements crl_t.destroy
*/
static void destroy(private_crl_t *this)
{
this->authKeySerialNumber = CHUNK_INITIALIZER;
/* public functions */
- this->public.is_valid = (err_t (*) (const crl_t*,time_t*))is_valid;
- this->public.destroy = (void (*) (crl_t*))destroy;
this->public.get_issuer = (identification_t* (*) (const crl_t*))get_issuer;
this->public.equals_issuer = (bool (*) (const crl_t*,const crl_t*))equals_issuer;
+ this->public.is_issuer = (bool (*) (const crl_t*,const x509_t*))is_issuer;
+ this->public.is_valid = (err_t (*) (const crl_t*,time_t*,bool))is_valid;
this->public.is_newer = (bool (*) (const crl_t*,const crl_t*))is_newer;
+ this->public.verify = (bool (*) (const crl_t*,const rsa_public_key_t*))verify;
+ this->public.get_status = (void (*) (const crl_t*,certinfo_t*))get_status;
this->public.log_crl = (void (*) (const crl_t*,logger_t*,bool,bool))log_crl;
+ this->public.destroy = (void (*) (crl_t*))destroy;
/* we do not use a per-instance logger right now, since its not always accessible */
logger = logger_manager->get_logger(logger_manager, ASN1);
#include <types.h>
#include <definitions.h>
#include <crypto/rsa/rsa_public_key.h>
+#include <crypto/certinfo.h>
#include <utils/identification.h>
#include <utils/iterator.h>
#include <utils/logger.h>
-
typedef struct crl_t crl_t;
/**
* @return issuers ID
*/
identification_t *(*get_issuer) (const crl_t *this);
-
+
/**
* @brief Check if both crls have the same issuer.
*
bool (*equals_issuer) (const crl_t *this, const crl_t *other);
/**
- * @brief Check if a crl is trustworthy
- *
- * Use the issuer's public key to verify
- * the trustworthiness of a crl.
+ * @brief Check if ia candidate cert is the issuer of the crl
*
- * @todo implement!
+ * @param this calling object
+ * @param issuer candidate issuer of the crl
+ * @return TRUE if issuer
*/
- bool (*verify) (const crl_t *this, rsa_public_key_t *signer);
-
+ bool (*is_issuer) (const crl_t *this, const x509_t *issuer);
+
/**
* @brief Checks the validity interval of the crl
*
bool (*is_newer) (const crl_t *this, const crl_t *other);
/**
- * @brief Check if a certificate has been revoked.
+ * @brief Check if a crl is trustworthy.
*
- * This function uses the certificate's serialNumber
- * to get the revocation status.
+ * @param this calling object
+ * @param signer signer's RSA public key
+ * @return TRUE if crl is trustworthy
+ */
+ bool (*verify) (const crl_t *this, const rsa_public_key_t *signer);
+
+ /**
+ * @brief Get the certificate status
*
+ * @param this calling object
+ * @param certinfo certinfo is updated
*/
- bool (*get_status) (const crl_t *this, chunk_t serial);
+ void (*get_status) (const crl_t *this, certinfo_t *certinfo);
/**
* @brief Destroys the crl.
* @param data data to process
* @return processed data
*/
- chunk_t (*rsaep) (private_rsa_public_key_t *this, chunk_t data);
+ chunk_t (*rsaep) (const private_rsa_public_key_t *this, chunk_t data);
/**
* @brief Implements the RSASVP1 algorithm specified in PKCS#1.
* @param data data to process
* @return processed data
*/
- chunk_t (*rsavp1) (private_rsa_public_key_t *this, chunk_t data);
+ chunk_t (*rsavp1) (const private_rsa_public_key_t *this, chunk_t data);
};
private_rsa_public_key_t *rsa_public_key_create_empty(void);
/**
* Implementation of private_rsa_public_key_t.rsaep and private_rsa_public_key_t.rsavp1
*/
-static chunk_t rsaep(private_rsa_public_key_t *this, chunk_t data)
+static chunk_t rsaep(const private_rsa_public_key_t *this, chunk_t data)
{
mpz_t m, c;
chunk_t encrypted;
/**
* Implementation of rsa_public_key.verify_emsa_pkcs1_signature.
*/
-static status_t verify_emsa_pkcs1_signature(private_rsa_public_key_t *this, chunk_t data, chunk_t signature)
+static status_t verify_emsa_pkcs1_signature(const private_rsa_public_key_t *this, chunk_t data, chunk_t signature)
{
hasher_t *hasher = NULL;
chunk_t hash;
/**
* Implementation of rsa_public_key.get_key.
*/
-static status_t get_key(private_rsa_public_key_t *this, chunk_t *key)
+static status_t get_key(const private_rsa_public_key_t *this, chunk_t *key)
{
chunk_t n, e;
/**
* Implementation of rsa_public_key.save_key.
*/
-static status_t save_key(private_rsa_public_key_t *this, char *file)
+static status_t save_key(const private_rsa_public_key_t *this, char *file)
{
return NOT_SUPPORTED;
}
/**
* Implementation of rsa_public_key.get_modulus.
*/
-static mpz_t *get_modulus(private_rsa_public_key_t *this)
+static mpz_t *get_modulus(const private_rsa_public_key_t *this)
{
return &this->n;
}
/**
* Implementation of rsa_public_key.get_keysize.
*/
-static size_t get_keysize(private_rsa_public_key_t *this)
+static size_t get_keysize(const private_rsa_public_key_t *this)
{
return this->k;
}
/**
* Implementation of rsa_public_key.get_keyid.
*/
-static chunk_t get_keyid(private_rsa_public_key_t *this)
+static chunk_t get_keyid(const private_rsa_public_key_t *this)
{
return this->keyid;
}
/**
* Implementation of rsa_public_key.clone.
*/
-static rsa_public_key_t* _clone(private_rsa_public_key_t *this)
+static rsa_public_key_t* _clone(const private_rsa_public_key_t *this)
{
private_rsa_public_key_t *clone = rsa_public_key_create_empty();
private_rsa_public_key_t *this = malloc_thing(private_rsa_public_key_t);
/* public functions */
- this->public.verify_emsa_pkcs1_signature = (status_t (*) (rsa_public_key_t*,chunk_t,chunk_t))verify_emsa_pkcs1_signature;
- this->public.get_key = (status_t (*) (rsa_public_key_t*,chunk_t*))get_key;
- this->public.save_key = (status_t (*) (rsa_public_key_t*,char*))save_key;
- this->public.get_modulus = (mpz_t *(*) (rsa_public_key_t*))get_modulus;
- this->public.get_keysize = (size_t (*) (rsa_public_key_t*))get_keysize;
- this->public.get_keyid = (chunk_t (*) (rsa_public_key_t*))get_keyid;
- this->public.clone = (rsa_public_key_t* (*) (rsa_public_key_t*))_clone;
+ this->public.verify_emsa_pkcs1_signature = (status_t (*) (const rsa_public_key_t*,chunk_t,chunk_t))verify_emsa_pkcs1_signature;
+ this->public.get_key = (status_t (*) (const rsa_public_key_t*,chunk_t*))get_key;
+ this->public.save_key = (status_t (*) (const rsa_public_key_t*,char*))save_key;
+ this->public.get_modulus = (mpz_t *(*) (const rsa_public_key_t*))get_modulus;
+ this->public.get_keysize = (size_t (*) (const rsa_public_key_t*))get_keysize;
+ this->public.get_keyid = (chunk_t (*) (const rsa_public_key_t*))get_keyid;
+ this->public.clone = (rsa_public_key_t* (*) (const rsa_public_key_t*))_clone;
this->public.destroy = (void (*) (rsa_public_key_t*))destroy;
/* private functions */
* - INVALID_ARG, if signature is not a signature
* - FAILED if signature invalid or unable to verify
*/
- status_t (*verify_emsa_pkcs1_signature) (rsa_public_key_t *this, chunk_t data, chunk_t signature);
+ status_t (*verify_emsa_pkcs1_signature) (const rsa_public_key_t *this, chunk_t data, chunk_t signature);
/**
* @brief Gets the key.
* - SUCCESS
* - INVALID_STATE, if key not set
*/
- status_t (*get_key) (rsa_public_key_t *this, chunk_t *key);
+ status_t (*get_key) (const rsa_public_key_t *this, chunk_t *key);
/**
* @brief Saves a key to a file.
* @param file file to which the key should be written.
* @return NOT_SUPPORTED
*/
- status_t (*save_key) (rsa_public_key_t *this, char *file);
+ status_t (*save_key) (const rsa_public_key_t *this, char *file);
/**
* @brief Get the modulus of the key.
* @param this calling object
* @return modulus (n) of the key
*/
- mpz_t *(*get_modulus) (rsa_public_key_t *this);
+ mpz_t *(*get_modulus) (const rsa_public_key_t *this);
/**
* @brief Get the size of the modulus in bytes.
* @param this calling object
* @return size of the modulus (n) in bytes
*/
- size_t (*get_keysize) (rsa_public_key_t *this);
+ size_t (*get_keysize) (const rsa_public_key_t *this);
/**
* @brief Get the keyid formed as the SHA-1 hash of a publicKeyInfo object.
* @param this calling object
* @return keyid in the form of a SHA-1 hash
*/
- chunk_t (*get_keyid) (rsa_public_key_t *this);
+ chunk_t (*get_keyid) (const rsa_public_key_t *this);
/**
* @brief Clone the public key.
* @param this public key to clone
* @return clone of this
*/
- rsa_public_key_t *(*clone) (rsa_public_key_t *this);
+ rsa_public_key_t *(*clone) (const rsa_public_key_t *this);
/**
* @brief Destroys the public key.
time_t installed;
/**
+ * Time until certificate can be trusted
+ */
+ time_t until;
+
+ /**
* X.509 Certificate in DER format
*/
chunk_t certificate;
}
/**
+ * Implements x509_t.is_self_signed
+ */
+static bool is_self_signed(const private_x509_t *this)
+{
+ return this->subject->equals(this->subject, this->issuer);
+}
+
+/**
* Implements x509_t.equals_subjectAltName
*/
static bool equals_subjectAltName(const private_x509_t *this, identification_t *id)
}
/**
+ * Implements x509_t.is_issuer
+ */
+static bool is_issuer(const private_x509_t *this, const private_x509_t *issuer)
+{
+ return (this->authKeyID.ptr)
+ ? chunk_equals(this->authKeyID, issuer->subjectKeyID)
+ : (this->issuer->equals(this->issuer, issuer->subject)
+ && chunk_equals_or_null(this->authKeySerialNumber, issuer->serialNumber));
+}
+
+/**
* Implements x509_t.get_public_key
*/
static rsa_public_key_t *get_public_key(const private_x509_t *this)
}
/**
- * Implements x509_t.get_subject
+ * Implements x509_t.get_serialNumber
*/
-static identification_t *get_subject(const private_x509_t *this)
+static chunk_t get_serialNumber(const private_x509_t *this)
{
- return this->subject;
+ return this->serialNumber;
+}
+
+/**
+ * Implements x509_t.get_subjectKeyID
+ */
+static chunk_t get_subjectKeyID(const private_x509_t *this)
+{
+ return this->subjectKeyID;
}
/**
}
/**
+ * Implements x509_t.get_subject
+ */
+static identification_t *get_subject(const private_x509_t *this)
+{
+ return this->subject;
+}
+
+/**
+ * Implements x509_t.set_until
+ */
+static void set_until(private_x509_t *this, time_t until)
+{
+ this->until = until;
+}
+
+/**
+ * Implements x509_t.verify
+ */
+static bool verify(const private_x509_t *this, const rsa_public_key_t *signer)
+{
+ return signer->verify_emsa_pkcs1_signature(signer, this->tbsCertificate, this->signature);
+}
+
+/**
* destroy
*/
static void destroy(private_x509_t *this)
logger->log(logger, CONTROL, " not after %s %s", buf,
check_expiry(this->notAfter, CERT_WARNING_INTERVAL, TRUE));
- logger->log(logger, CONTROL, " pubkey: RSA %d bits%s",
- BITS_PER_BYTE * pubkey->get_keysize(pubkey), has_key? ", has private key":"");
+ timetoa(buf, BUF_LEN, &this->until, utc);
+ logger->log(logger, CONTROL, " pubkey: RSA %d bits%s, until %s",
+ BITS_PER_BYTE * pubkey->get_keysize(pubkey),
+ has_key? ", has private key":"", buf);
+
chunk_to_hex(buf, BUF_LEN, pubkey->get_keyid(pubkey));
logger->log(logger, CONTROL, " keyid: %s", buf);
/* public functions */
this->public.equals = (bool (*) (const x509_t*,const x509_t*))equals;
this->public.equals_subjectAltName = (bool (*) (const x509_t*,identification_t*))equals_subjectAltName;
+ this->public.is_issuer = (bool (*) (const x509_t*,const x509_t*))is_issuer;
this->public.is_valid = (err_t (*) (const x509_t*,time_t*))is_valid;
this->public.is_ca = (bool (*) (const x509_t*))is_ca;
- this->public.destroy = (void (*) (x509_t*))destroy;
+ this->public.is_self_signed = (bool (*) (const x509_t*))is_self_signed;
this->public.get_public_key = (rsa_public_key_t* (*) (const x509_t*))get_public_key;
- this->public.get_subject = (identification_t* (*) (const x509_t*))get_subject;
+ this->public.get_serialNumber = (chunk_t (*) (const x509_t*))get_serialNumber;
+ this->public.get_subjectKeyID = (chunk_t (*) (const x509_t*))get_subjectKeyID;
this->public.get_issuer = (identification_t* (*) (const x509_t*))get_issuer;
+ this->public.get_subject = (identification_t* (*) (const x509_t*))get_subject;
+ this->public.set_until = (void (*) (x509_t*,time_t))set_until;
+ this->public.verify = (bool (*) (const x509_t*,const rsa_public_key_t*))verify;
+ this->public.destroy = (void (*) (x509_t*))destroy;
this->public.log_certificate = (void (*) (const x509_t*,logger_t*,bool,bool))log_certificate;
/* we do not use a per-instance logger right now, since its not always accessible */
destroy(this);
return NULL;
}
-
+ /* set trusted lifetime of public key to notAfter */
+ this->until = this->notAfter;
return &this->public;
}
struct x509_t {
/**
+ * @brief Set trusted public key life.
+ *
+ * @param this calling object
+ * @param until time until public key is trusted
+ */
+ void (*set_until) (x509_t *this, time_t until);
+
+ /**
* @brief Get the RSA public key from the certificate.
*
* @param this calling object
* @return public_key
*/
rsa_public_key_t *(*get_public_key) (const x509_t *this);
+
+ /**
+ * @brief Get serial number from the certificate.
+ *
+ * @param this calling object
+ * @return serialNumber
+ */
+ chunk_t (*get_serialNumber) (const x509_t *this);
+
+ /**
+ * @brief Get serial number from the certificate.
+ *
+ * @param this calling object
+ * @return subjectKeyID
+ */
+ chunk_t (*get_subjectKeyID) (const x509_t *this);
/**
- * @brief Get the certificate issuers ID.
+ * @brief Get the certificate issuer's ID.
*
* The resulting ID is always a identification_t
* of type ID_DER_ASN1_DN.
/**
* @brief Check if a certificate is trustworthy
*
- * Use the issuer's public key to verify
- * the trustworthiness of a certificate.
- *
- * @todo implement!
- */
- bool (*verify) (const x509_t *this, rsa_public_key_t *signer);
-
- /**
- * @brief Get the key identifier of the public key.
- *
- * @todo implement!
+ * @param this calling object
+ * @param signer signer's RSA public key
*/
- chunk_t (*get_subject_key_identifier) (const x509_t *this);
+ bool (*verify) (const x509_t *this, const rsa_public_key_t *signer);
/**
* @brief Compare two certificates.
*
* @param this first cert for compare
* @param other second cert for compare
- * @return TRUE if signature is equal
+ * @return TRUE if signature is equal
*/
bool (*equals) (const x509_t *this, const x509_t *that);
*
* @param this certificate being examined
* @param id id which is being compared to the subjectAltNames
- * @return TRUE if a match is found
+ * @return TRUE if a match is found
*/
bool (*equals_subjectAltName) (const x509_t *this, identification_t *id);
/**
+ * @brief Checks if the subject of the other cert is the issuer of this cert.
+ *
+ * @param this certificate
+ * @param issuer potential issuer certificate
+ * @return TRUE if issuer is found
+ */
+ bool (*is_issuer) (const x509_t *this, const x509_t *issuer);
+
+ /**
* @brief Checks the validity interval of the certificate
*
* @param this certificate being examined
* @param until until = min(until, notAfter)
- * @return NULL if the certificate is valid
+ * @return NULL if the certificate is valid
*/
err_t (*is_valid) (const x509_t *this, time_t *until);
* @brief Returns the CA basic constraints flag
*
* @param this certificate being examined
- * @return TRUE if the CA flag is set
+ * @return TRUE if the CA flag is set
*/
bool (*is_ca) (const x509_t *this);
/**
+ * @brief Checks if the certificate is self-signed (subject equals issuer)
+ *
+ * @param this certificate being examined
+ * @return TRUE if self-signed
+ */
+ bool (*is_self_signed) (const x509_t *this);
+
+ /**
* @brief Destroys the certificate.
*
* @param this certificate to destroy
* @brief Read a x509 certificate from a DER encoded blob.
*
* @param chunk chunk containing DER encoded data
- * @return created x509_t certificate, or NULL if invalid.
+ * @return created x509_t certificate, or NULL if inv\ 1lid.
*
* @ingroup transforms
*/
* for more details.
*/
+#include <stdlib.h>
+
#include "definitions.h"
/*
}
return "INVALID MAPPING";
}
+
+/*
+ * Described in header
+ */
+const char *enum_name(enum_names *ed, unsigned long val)
+{
+ enum_names *p;
+
+ for (p = ed; p != NULL; p = p->en_next_range)
+ {
+ if (p->en_first <= val && val <= p->en_last)
+ return p->en_names[val - p->en_first];
+ }
+ return NULL;
+}
+
*/
char *mapping_find(mapping_t *mappings, int value);
+/**
+ * @brief Describes an enumeration
+ * enum_name() returns the name of an enum value, or NULL if invalid.
+ */
+typedef const struct enum_names enum_names;
+
+struct enum_names {
+ unsigned long en_first; /* first value in range */
+ unsigned long en_last; /* last value in range (inclusive) */
+ const char *const *en_names;
+ enum_names *en_next_range; /* descriptor of next range */
+};
+
+/**
+ * @brief Returns the name of an enum value, or NULL if invalid
+ */
+const char *enum_name(enum_names *ed, unsigned long val);
+
#endif /*DEFINITIONS_H_*/
};
/**
- * RFC 2459 CRL reason codes
- */
-
-/* TODO extern enum_names crl_reason_names; */
-
-typedef enum {
- REASON_UNSPECIFIED = 0,
- REASON_KEY_COMPROMISE = 1,
- REASON_CA_COMPROMISE = 2,
- REASON_AFFILIATION_CHANGED = 3,
- REASON_SUPERSEDED = 4,
- REASON_CESSATION_OF_OPERATON = 5,
- REASON_CERTIFICATE_HOLD = 6,
- REASON_REMOVE_FROM_CRL = 8
-} crl_reason_t;
-
-/**
* String mappings for type status_t.
*/
extern mapping_t status_m[];