added X.509 trust chain verification
authorAndreas Steffen <andreas.steffen@strongswan.org>
Tue, 27 Jun 2006 08:48:28 +0000 (08:48 -0000)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Tue, 27 Jun 2006 08:48:28 +0000 (08:48 -0000)
15 files changed:
src/charon/config/credentials/credential_store.h
src/charon/config/credentials/local_credential_store.c
src/charon/threads/stroke_interface.c
src/libstrongswan/Makefile.am
src/libstrongswan/crypto/certinfo.c [new file with mode: 0644]
src/libstrongswan/crypto/certinfo.h [new file with mode: 0644]
src/libstrongswan/crypto/crl.c
src/libstrongswan/crypto/crl.h
src/libstrongswan/crypto/rsa/rsa_public_key.c
src/libstrongswan/crypto/rsa/rsa_public_key.h
src/libstrongswan/crypto/x509.c
src/libstrongswan/crypto/x509.h
src/libstrongswan/definitions.c
src/libstrongswan/definitions.h
src/libstrongswan/types.h

index 302eefe..b1dd877 100755 (executable)
@@ -92,6 +92,16 @@ struct credential_store_t {
        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
@@ -108,7 +118,7 @@ struct credential_store_t {
         * @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.
         *
index ef12884..53e9cb6 100644 (file)
 #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;
 
@@ -166,6 +169,236 @@ static bool has_rsa_private_key(private_local_credential_store_t *this, rsa_publ
 }
 
 /**
+ * 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**)&current_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**)&current_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)
@@ -600,6 +833,7 @@ local_credential_store_t * local_credential_store_create(bool strict)
        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;
index 0bb97ca..912213b 100755 (executable)
@@ -136,6 +136,7 @@ static x509_t* load_end_certificate(const char *filename, identification_t **idp
        {
                identification_t *id = *idp;
                identification_t *subject = cert->get_subject(cert);
+               time_t until;
 
                err_t ugh = cert->is_valid(cert, NULL);
 
@@ -149,6 +150,20 @@ static x509_t* load_end_certificate(const char *filename, identification_t **idp
                        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;
@@ -305,7 +320,7 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
        }
        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)
                {
@@ -316,7 +331,7 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
        }
        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)
                {
index 968342d..23ade32 100644 (file)
@@ -21,6 +21,7 @@ crypto/hashers/sha1_hasher.c crypto/hashers/sha1_hasher.h \
 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 \
diff --git a/src/libstrongswan/crypto/certinfo.c b/src/libstrongswan/crypto/certinfo.c
new file mode 100644 (file)
index 0000000..7fef2fa
--- /dev/null
@@ -0,0 +1,198 @@
+/**
+ * @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;
+}
diff --git a/src/libstrongswan/crypto/certinfo.h b/src/libstrongswan/crypto/certinfo.h
new file mode 100644 (file)
index 0000000..81707fa
--- /dev/null
@@ -0,0 +1,166 @@
+/**
+ * @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_ */
index 6033340..f7e172c 100755 (executable)
@@ -33,8 +33,9 @@
 #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 */
 
@@ -132,8 +133,9 @@ struct private_crl_t {
        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 */
@@ -201,7 +203,8 @@ static crl_reason_t parse_crl_reasonCode(chunk_t object)
        {
                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;
 }
 
@@ -332,14 +335,6 @@ static err_t is_valid(const private_crl_t *this, time_t *until, bool strict)
 }
 
 /**
- * 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)
@@ -359,7 +354,61 @@ static bool equals_issuer(const private_crl_t *this, const private_crl_t *other)
 }
 
 /**
- * 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)
 {
@@ -440,12 +489,15 @@ crl_t *crl_create_from_chunk(chunk_t chunk)
        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);
index 4cecee7..e4739fc 100755 (executable)
 #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;
 
 /**
@@ -54,7 +54,7 @@ struct crl_t {
         * @return                                      issuers ID
         */
        identification_t *(*get_issuer) (const crl_t *this);
-               
+
        /**
         * @brief Check if both crls have the same issuer.
         * 
@@ -65,15 +65,14 @@ struct crl_t {
        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
         * 
@@ -94,13 +93,21 @@ struct crl_t {
        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.
index 87c0bd0..cc714b0 100644 (file)
@@ -141,7 +141,7 @@ struct private_rsa_public_key_t {
         * @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.
@@ -150,7 +150,7 @@ struct private_rsa_public_key_t {
         * @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);
@@ -158,7 +158,7 @@ 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;
@@ -182,7 +182,7 @@ static chunk_t rsaep(private_rsa_public_key_t *this, chunk_t data)
 /**
  * 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;
@@ -291,7 +291,7 @@ end:
 /**
  * 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;
 
@@ -313,7 +313,7 @@ static status_t get_key(private_rsa_public_key_t *this, chunk_t *key)
 /**
  * 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;
 }
@@ -321,7 +321,7 @@ static status_t save_key(private_rsa_public_key_t *this, char *file)
 /**
  * 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;
 }
@@ -329,7 +329,7 @@ static mpz_t *get_modulus(private_rsa_public_key_t *this)
 /**
  * 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;
 }
@@ -337,7 +337,7 @@ static size_t get_keysize(private_rsa_public_key_t *this)
 /**
  * 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;
 }
@@ -345,7 +345,7 @@ static chunk_t get_keyid(private_rsa_public_key_t *this)
 /**
  * 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();
        
@@ -376,13 +376,13 @@ private_rsa_public_key_t *rsa_public_key_create_empty(void)
        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 */
index 61796ae..62bdd7d 100644 (file)
@@ -67,7 +67,7 @@ struct rsa_public_key_t {
         *                                                      - 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.
@@ -83,7 +83,7 @@ struct rsa_public_key_t {
         *                                                      - 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.
@@ -94,7 +94,7 @@ struct rsa_public_key_t {
         * @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.
@@ -102,7 +102,7 @@ struct rsa_public_key_t {
         * @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.
@@ -110,7 +110,7 @@ struct rsa_public_key_t {
         * @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.
@@ -118,7 +118,7 @@ struct rsa_public_key_t {
         * @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.
@@ -126,7 +126,7 @@ struct rsa_public_key_t {
         * @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.
index 905fc4c..c65071c 100755 (executable)
@@ -74,6 +74,11 @@ struct private_x509_t {
        time_t installed;
 
        /**
+        * Time until certificate can be trusted
+        */
+       time_t until;
+
+       /**
         * X.509 Certificate in DER format
         */
        chunk_t certificate;
@@ -910,6 +915,14 @@ static bool is_ca(const private_x509_t *this)
 }
 
 /**
+ * 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)
@@ -933,6 +946,17 @@ static bool equals_subjectAltName(const private_x509_t *this, identification_t *
 }
 
 /**
+ * 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)
@@ -941,11 +965,19 @@ 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;
 }
 
 /**
@@ -957,6 +989,30 @@ static identification_t *get_issuer(const private_x509_t *this)
 }
 
 /**
+ * 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)
@@ -1060,8 +1116,11 @@ static void log_certificate(const private_x509_t *this, logger_t *logger, bool u
        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);
 
@@ -1103,12 +1162,18 @@ x509_t *x509_create_from_chunk(chunk_t chunk)
        /* 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 */
@@ -1127,7 +1192,8 @@ x509_t *x509_create_from_chunk(chunk_t chunk)
                destroy(this);
                return NULL;
        }
-
+       /* set trusted lifetime of public key to notAfter */
+       this->until = this->notAfter;
        return &this->public;
 }
 
index 9f0bbf4..a4451eb 100755 (executable)
@@ -49,15 +49,39 @@ typedef struct x509_t x509_t;
 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.
@@ -81,19 +105,10 @@ struct x509_t {
        /**
         * @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.
@@ -102,7 +117,7 @@ struct x509_t {
         * 
         * @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);
        
@@ -111,16 +126,25 @@ struct x509_t {
         * 
         * @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);
        
@@ -128,11 +152,19 @@ struct x509_t {
         * @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
@@ -154,7 +186,7 @@ struct x509_t {
  * @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
  */
index 59c97a2..c6cabe5 100644 (file)
@@ -20,6 +20,8 @@
  * for more details.
  */
 
+#include <stdlib.h>
+
 #include "definitions.h"
 
 /*
@@ -38,3 +40,19 @@ char *mapping_find(mapping_t * maps, int value)
        }
        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;
+}
+
index b8e6ba9..001f5f3 100644 (file)
@@ -135,4 +135,22 @@ struct mapping_t
  */
 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_*/
index 0a1ea08..e180105 100644 (file)
@@ -110,23 +110,6 @@ enum status_t {
 };
 
 /**
- * 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[];