ocsp signer certificate and ocsp response signature can be verified
authorAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 8 Mar 2007 23:29:04 +0000 (23:29 -0000)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 8 Mar 2007 23:29:04 +0000 (23:29 -0000)
src/charon/config/credentials/credential_store.h
src/charon/config/credentials/local_credential_store.c
src/libstrongswan/Makefile.am
src/libstrongswan/credential_store.h [new file with mode: 0755]
src/libstrongswan/crypto/ca.c
src/libstrongswan/crypto/ca.h
src/libstrongswan/crypto/ocsp.c
src/libstrongswan/crypto/ocsp.h

index 3786196..e19f147 100755 (executable)
@@ -136,13 +136,22 @@ struct credential_store_t {
        ca_info_t* (*get_issuer) (credential_store_t *this, const x509_t* cert);
 
        /**
-        * @brief Verify an X.509 certificate up to trust anchor including revocation checks
+        * @brief Verify an X.509 certificate up to trust anchor without any status checks
         *
         * @param this          calling object
         * @param cert          certificate to be verified
-        * @param found         found a certificate copy in the credential store
         * @return                      TRUE if trusted
         */
+       bool (*is_trusted) (credential_store_t *this, x509_t *cert);
+
+       /**
+        * @brief Verify an X.509 certificate up to trust anchor including status checks
+        *
+        * @param this          calling object
+        * @param cert          certificate to be verified
+        * @param found         found a certificate copy in the credential store
+        * @return                      TRUE if valid, trusted, and current status is good
+        */
        bool (*verify) (credential_store_t *this, x509_t *cert, bool *found);
 
        /**
index 1caa33b..25ba970 100644 (file)
@@ -481,6 +481,60 @@ static void add_uris(ca_info_t *issuer, x509_t *cert)
 }
 
 /**
+ * Implementation of credential_store_t.is_trusted
+ */
+static bool is_trusted(private_local_credential_store_t *this, x509_t *cert)
+{
+       int pathlen;
+
+       DBG2(DBG_CFG, "establishing trust in certificate:");
+
+       for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
+       {
+               ca_info_t *issuer;
+               x509_t *issuer_cert;
+               rsa_public_key_t *issuer_public_key;
+               bool valid_signature;
+
+               DBG2(DBG_CFG, "subject: '%D'", cert->get_subject(cert));
+               DBG2(DBG_CFG, "issuer:  '%D'", cert->get_issuer(cert));
+       
+               issuer = get_issuer(this, cert);
+               if (issuer == NULL)
+               {
+                       DBG1(DBG_CFG, "issuer info not found");
+                       return FALSE;
+               }
+               DBG2(DBG_CFG, "issuer info found");
+
+               issuer_cert = issuer->get_certificate(issuer);
+               issuer_public_key = issuer_cert->get_public_key(issuer_cert);
+               valid_signature = cert->verify(cert, issuer_public_key);
+
+               if (!valid_signature)
+               {
+                       DBG1(DBG_CFG, "certificate signature is invalid");
+                       return FALSE;
+               }
+               DBG2(DBG_CFG, "certificate signature is valid");
+
+               /* check if cert is a self-signed root ca */
+               if (pathlen > 0 && cert->is_self_signed(cert))
+               {
+                       DBG2(DBG_CFG, "reached self-signed root ca");
+                       return TRUE;
+               }
+               else
+               {
+                       /* go up one step in the trust chain */
+                       cert = issuer_cert;
+               }
+       }
+       DBG1(DBG_CFG, "maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN);
+       return FALSE;
+}
+
+/**
  * Implementation of credential_store_t.verify.
  */
 static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *found)
@@ -491,6 +545,8 @@ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *f
        x509_t *end_cert = cert;
        x509_t *cert_copy = find_certificate(this->certs, end_cert);
        
+       DBG2(DBG_CFG, "verifying end entity certificate:");
+
        *found = (cert_copy != NULL);
        if (*found)
        {
@@ -565,7 +621,7 @@ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *f
                        }
 
                        /* first check certificate revocation using ocsp */
-                       status = issuer->verify_by_ocsp(issuer, cert, certinfo);
+                       status = issuer->verify_by_ocsp(issuer, cert, certinfo, &this->public);
 
                        /* if ocsp service is not available then fall back to crl */
                        if ((status == CERT_UNDEFINED) || (status == CERT_UNKNOWN && this->strict))
@@ -1234,6 +1290,7 @@ local_credential_store_t * local_credential_store_create(bool strict)
        this->public.credential_store.get_auth_certificate = (x509_t* (*) (credential_store_t*,u_int,identification_t*))get_auth_certificate;
        this->public.credential_store.get_ca_certificate_by_keyid = (x509_t* (*) (credential_store_t*,chunk_t))get_ca_certificate_by_keyid;
        this->public.credential_store.get_issuer = (ca_info_t* (*) (credential_store_t*,const x509_t*))get_issuer;
+       this->public.credential_store.is_trusted = (bool (*) (credential_store_t*,x509_t*))is_trusted;
        this->public.credential_store.verify = (bool (*) (credential_store_t*,x509_t*,bool*))verify;
        this->public.credential_store.add_end_certificate = (x509_t* (*) (credential_store_t*,x509_t*))add_end_certificate;
        this->public.credential_store.add_auth_certificate = (x509_t* (*) (credential_store_t*,x509_t*,u_int))add_auth_certificate;
index d076824..3c1a913 100644 (file)
@@ -1,6 +1,7 @@
 lib_LTLIBRARIES = libstrongswan.la
 
 libstrongswan_la_SOURCES = \
+credential_store.h \
 library.c library.h \
 chunk.c chunk.h \
 debug.c debug.h \
diff --git a/src/libstrongswan/credential_store.h b/src/libstrongswan/credential_store.h
new file mode 100755 (executable)
index 0000000..e19f147
--- /dev/null
@@ -0,0 +1,285 @@
+/**
+ * @file credential_store.h
+ * 
+ * @brief Interface credential_store_t.
+ *  
+ */
+
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 CREDENTIAL_STORE_H_
+#define CREDENTIAL_STORE_H_
+
+typedef struct credential_store_t credential_store_t;
+
+#include <library.h>
+#include <crypto/x509.h>
+#include <crypto/ca.h>
+#include <crypto/rsa/rsa_private_key.h>
+#include <crypto/rsa/rsa_public_key.h>
+#include <utils/identification.h>
+
+
+/**
+ * @brief The interface for a credential_store backend.
+ *
+ * @b Constructors:
+ *  - stroke_create()
+ *
+ * @ingroup config
+ */
+struct credential_store_t { 
+
+       /**
+        * @brief Returns the secret shared by two specific IDs.
+        * 
+        * The returned chunk must be destroyed by the caller after usage.
+        * 
+        * @param this                                  calling object
+        * @param my_id                                 my ID identifiying the secret.
+        * @param other_id                              peer ID identifying the secret.
+        * @param[out] secret                   the pre-shared secret will be written there.
+        * @return
+        *                                                              - NOT_FOUND     if no preshared secrets for specific ID could be found
+        *                                                              - SUCCESS
+        *
+        */     
+       status_t (*get_shared_key) (credential_store_t *this, identification_t *my_id, identification_t *other_id, chunk_t *shared_key);
+       
+       /**
+        * @brief Returns the RSA public key of a specific ID.
+        * 
+        * @param this                                  calling object
+        * @param id                                    identification_t object identifiying the key.
+        * @return                                              public key, or NULL if not found
+        */
+       rsa_public_key_t* (*get_rsa_public_key) (credential_store_t *this, identification_t *id);
+       
+       /**
+        * @brief Returns the RSA public key of a specific ID if is trusted
+        * 
+        * @param this                                  calling object
+        * @param id                                    identification_t object identifiying the key.
+        * @return                                              public key, or NULL if not found or not trusted
+        */
+       rsa_public_key_t* (*get_trusted_public_key) (credential_store_t *this, identification_t *id);
+       
+       /**
+        * @brief Returns the RSA private key belonging to an RSA public key
+        * 
+        * The returned rsa_private_key_t must be destroyed by the caller after usage.
+        * 
+        * @param this                                  calling object
+        * @param pubkey                                public key 
+        * @return                                              private key, or NULL if not found
+        */     
+       rsa_private_key_t* (*get_rsa_private_key) (credential_store_t *this, rsa_public_key_t *pubkey);
+
+       /**
+        * @brief Is there a matching RSA private key belonging to an RSA public key?
+        * 
+        * @param this                                  calling object
+        * @param pubkey                                public key 
+        * @return                                              TRUE if matching private key was found 
+        */     
+       bool (*has_rsa_private_key) (credential_store_t *this, rsa_public_key_t *pubkey);
+
+       /**
+        * @brief Returns the certificate of a specific ID.
+        * 
+        * @param this                                  calling object
+        * @param id                                    identification_t object identifiying the cert.
+        * @return                                              certificate, or NULL if not found
+        */
+       x509_t* (*get_certificate) (credential_store_t *this, identification_t *id);
+       
+       /**
+        * @brief Returns the auth certificate of a specific subject distinguished name.
+        * 
+        * @param this                                  calling object
+        * @param auth_flags                    set of allowed authority types
+        * @param id                                    identification_t object identifiying the cacert.
+        * @return                                              certificate, or NULL if not found
+        */
+       x509_t* (*get_auth_certificate) (credential_store_t *this, u_int auth_flags, identification_t *id);
+       
+       /**
+        * @brief Returns the ca certificate of a specific keyID.
+        * 
+        * @param this                                  calling object
+        * @param keyid                                 identification_t object identifiying the cacert.
+        * @return                                              certificate, or NULL if not found
+        */
+       x509_t* (*get_ca_certificate_by_keyid) (credential_store_t *this, chunk_t keyid);
+       
+       /**
+        * @brief Returns the issuing ca of a given certificate.
+        * 
+        * @param this                                  calling object
+        * @param cert                                  certificate for which issuer ca info is required
+        * @return                                              ca info, or NULL if not found
+        */
+       ca_info_t* (*get_issuer) (credential_store_t *this, const x509_t* cert);
+
+       /**
+        * @brief Verify an X.509 certificate up to trust anchor without any status checks
+        *
+        * @param this          calling object
+        * @param cert          certificate to be verified
+        * @return                      TRUE if trusted
+        */
+       bool (*is_trusted) (credential_store_t *this, x509_t *cert);
+
+       /**
+        * @brief Verify an X.509 certificate up to trust anchor including status checks
+        *
+        * @param this          calling object
+        * @param cert          certificate to be verified
+        * @param found         found a certificate copy in the credential store
+        * @return                      TRUE if valid, trusted, and current status is good
+        */
+       bool (*verify) (credential_store_t *this, x509_t *cert, bool *found);
+
+       /**
+        * @brief If an end certificate does not already exists in the credential store then add it.
+        *
+        * @param this          calling object
+        * @param cert          certificate to be added
+        * @return                      pointer to the added or already existing certificate
+        */
+       x509_t* (*add_end_certificate) (credential_store_t *this, x509_t *cert);
+
+       /**
+        * @brief If an authority certificate does not already exists in the credential store then add it.
+        *
+        * @param this                  calling object
+        * @param cert                  authority certificate to be added
+        * @param auth_flag             authority flags to add to the certificate
+        * @return                              pointer to the added or already existing certificate
+        */
+       x509_t* (*add_auth_certificate) (credential_store_t *this, x509_t *cert, u_int auth_flag);
+
+       /**
+        * @brief If a ca info record does not already exists in the credential store then add it.
+        *
+        * @param this          calling object
+        * @param ca_info       ca info record to be added
+        */
+       void (*add_ca_info) (credential_store_t *this, ca_info_t *ca_info);
+
+       /**
+        * @brief Release a ca info record with a given name.
+        *
+        * @param this          calling object
+        * @param name          name of the ca info record to be released
+        * @return
+        *                                                      - SUCCESS, or
+        *                                                      - NOT_FOUND
+        */
+       status_t (*release_ca_info) (credential_store_t *this, const char *name);
+
+       /**
+        * @brief Create an iterator over all end certificates.
+        *
+        * @param this          calling object
+        * @return                      iterator
+        */
+       iterator_t* (*create_cert_iterator) (credential_store_t *this);
+
+       /**
+        * @brief Create an iterator over all authority certificates.
+        *
+        * @param this          calling object
+        * @return                      iterator
+        */
+       iterator_t* (*create_auth_cert_iterator) (credential_store_t *this);
+
+       /**
+        * @brief Create an iterator over all CA info records
+        *
+        * @param this          calling object
+        * @return                      iterator
+        */
+       iterator_t* (*create_cainfo_iterator) (credential_store_t *this);
+
+       /**
+        * @brief Check if there are any CRLs.
+        *
+        * @param this          calling object
+        * @param out           output stream
+        * @param utc           either utc or local time
+        */
+       void (*list_crls) (credential_store_t *this, FILE *out, bool utc);
+
+       /**
+        * @brief Loads ca certificates from a default directory.
+        *
+        * Certificates in both DER and PEM format are accepted
+        *
+        * @param this          calling object
+        */
+       void (*load_ca_certificates) (credential_store_t *this);
+       
+       /**
+        * @brief Loads ocsp certificates from a default directory.
+        *
+        * Certificates in both DER and PEM format are accepted
+        *
+        * @param this          calling object
+        */
+       void (*load_ocsp_certificates) (credential_store_t *this);
+       
+       /**
+        * @brief Loads CRLs from a default directory.
+        *
+        * Certificates in both DER and PEM format are accepted
+        *
+        * @param this          calling object
+        * @param path          directory to load crls from 
+        */
+       void (*load_crls) (credential_store_t *this);
+       
+       /**
+        * @brief Loads secrets in ipsec.secrets
+        * 
+        * Currently, all RSA private key files must be in unencrypted form
+     * either in DER or PEM format.
+        * 
+        * @param this                  calling object
+        */
+       void (*load_secrets) (credential_store_t *this);
+
+       /**
+        * @brief Destroys a credential_store_t object.
+        * 
+        * @param this                                  calling object
+        */
+       void (*destroy) (credential_store_t *this);
+};
+
+/**
+ * @brief Creates a credential_store_t instance.
+ *
+ * @param  strict              enforce a strict crl policy
+ * @return                             credential store instance.
+ * 
+ * @ingroup config
+ */
+credential_store_t *credential_store_create(bool strict);
+
+
+#endif /*CREDENTIAL_STORE_H_*/
index 79e4697..e9ccbfd 100644 (file)
@@ -382,8 +382,10 @@ err:
 /**
   * 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)
+static cert_status_t verify_by_ocsp(private_ca_info_t* this,
+                                                                       const x509_t *cert,
+                                                                       certinfo_t *certinfo,
+                                                                       credential_store_t *credentials)
 {
        bool found = FALSE;
 
@@ -419,7 +421,7 @@ static cert_status_t verify_by_ocsp(private_ca_info_t* this, const x509_t *cert,
                DBG2("ocsp status is not in cache");
 
                ocsp = ocsp_create(this->cacert, this->ocspuris);
-               ocsp->fetch(ocsp, certinfo);
+               ocsp->fetch(ocsp, certinfo, credentials);
                ocsp->destroy(ocsp);
        }
 
@@ -555,7 +557,7 @@ ca_info_t *ca_info_create(const char *name, x509_t *cacert)
        this->public.add_ocspuri = (void (*) (ca_info_t*,chunk_t))add_ocspuri;
        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.verify_by_ocsp = (cert_status_t (*) (ca_info_t*,const x509_t*,certinfo_t*,credential_store_t*))verify_by_ocsp;
        this->public.destroy = (void (*) (ca_info_t*))destroy;
 
        return &this->public;
index 1b2e33e..0aa3e20 100644 (file)
@@ -28,6 +28,8 @@ typedef struct ca_info_t ca_info_t;
 #include <library.h>
 #include <chunk.h>
 
+#include <credential_store.h>
+
 #include "x509.h"
 #include "crl.h"
 
@@ -151,9 +153,10 @@ struct ca_info_t {
         * @param this                  ca info object
         * @param cert                  certificate to be verified
         * @param certinfo              detailed certificate status information
+        * @param credentials   credential store needed for trust path verification
         * @return                              certificate status
         */
-       cert_status_t (*verify_by_ocsp) (ca_info_t* this, const x509_t* cert, certinfo_t* certinfo);
+       cert_status_t (*verify_by_ocsp) (ca_info_t* this, const x509_t* cert, certinfo_t* certinfo, credential_store_t* credentials);
 
        /**
         * @brief Destroys a ca info record
index 707b038..3a4ea3b 100644 (file)
@@ -38,6 +38,7 @@
 #include <debug.h>
 
 #include "hashers/hasher.h"
+#include "rsa/rsa_public_key.h"
 #include "certinfo.h"
 #include "x509.h"
 #include "ocsp.h"
@@ -107,19 +108,49 @@ struct response_t {
        chunk_t           nonce;
        int               algorithm;
        chunk_t           signature;
-};
+       x509_t           *responder_cert;
 
-const response_t empty_response = {
-       { NULL, 0 }   , /* tbs */
-         NULL        , /* responder_id_name */
-       { NULL, 0 }   , /* responder_id_key */
-       UNDEFINED_TIME, /* produced_at */
-       { NULL, 0 }   , /* single_response */
-       { NULL, 0 }   , /* nonce */
-       OID_UNKNOWN   , /* signature_algorithm */
-       { NULL, 0 }             /* signature */
+       /**
+        * @brief Destroys the response_t object
+        * 
+        * @param this          response_t to destroy
+        */
+       void (*destroy) (response_t *this);
 };
 
+/**
+ * Implements response_t.destroy.
+ */
+static void response_destroy(response_t *this)
+{
+       DESTROY_IF(this->responder_id_name);
+       DESTROY_IF(this->responder_cert);
+}
+
+/**
+ * Creates a response_t object
+ */
+static response_t* response_create(void)
+{
+       response_t *this = malloc_thing(response_t);
+
+       this->tbs               = chunk_empty;
+       this->responder_id_name = NULL;
+       this->responder_id_key  = chunk_empty;
+       this->produced_at       = UNDEFINED_TIME;
+       this->responses         = chunk_empty;
+       this->nonce             = chunk_empty;
+       this->algorithm         = OID_UNKNOWN;
+       this->signature         = chunk_empty;
+       this->responder_cert    = NULL;
+
+       this->destroy = (void (*) (response_t*))response_destroy;
+
+       return this;
+}
+
+
+
 /* single response container */
 typedef struct single_response single_response_t;
 
@@ -453,15 +484,6 @@ static chunk_t ocsp_build_request(private_ocsp_t *this)
 }
 
 /**
- * Check if the OCSP response has a valid signature
- */
-static bool ocsp_valid_response(response_t *res)
-{
-       /* TODO */
-       return FALSE;
-}
-
-/**
  * parse a basic OCSP response
  */
 static bool ocsp_parse_basic_response(chunk_t blob, int level0, response_t *res)
@@ -529,24 +551,8 @@ static bool ocsp_parse_basic_response(chunk_t blob, int level0, response_t *res)
                        case BASIC_RESPONSE_CERTIFICATE:
                                {
                                        chunk_t blob = chunk_clone(object);
-                                       x509_t *cert = x509_create_from_chunk(blob, level+1);
 
-                                       if (cert == NULL)
-                                       {
-                                               break;
-                                       }
-                                       if (cert->is_ocsp_signer(cert))
-                                       {
-                                               DBG2("received OCSP signer certificate");
-                                               cert->destroy(cert);
-                                               /* TODO trust_authcert_candidate(cert, NULL))
-                                                add_authcert(cert, AUTH_OCSP); */
-                                       }
-                                       else
-                                       {
-                                               DBG1("embedded ocsp certificate rejected");
-                                               cert->destroy(cert);
-                                       }
+                                       res->responder_cert = x509_create_from_chunk(blob, level+1);
                                }
                                break;
                }
@@ -558,7 +564,7 @@ static bool ocsp_parse_basic_response(chunk_t blob, int level0, response_t *res)
 /**
  * parse an ocsp response and return the result as a response_t struct
  */
-static response_status ocsp_parse_response(chunk_t blob, response_t * res)
+static response_status ocsp_parse_response(chunk_t blob, response_t *res)
 {
        asn1_ctx_t ctx;
        chunk_t object;
@@ -626,6 +632,32 @@ static response_status ocsp_parse_response(chunk_t blob, response_t * res)
 }
 
 /**
+ * Check if the OCSP response has a valid signature
+ */
+static bool ocsp_valid_response(response_t *res, x509_t *ocsp_cert)
+{
+       rsa_public_key_t *public_key;
+       time_t until = UNDEFINED_TIME;
+       err_t ugh;
+
+       DBG2("verifying ocsp response signature:");
+       DBG2("signer:  '%D'", ocsp_cert->get_subject(ocsp_cert));
+       DBG2("issuer:  '%D'", ocsp_cert->get_issuer(ocsp_cert));
+
+       ugh = ocsp_cert->is_valid(ocsp_cert, &until);
+       if (ugh != NULL)
+       {
+               DBG1("ocsp signer certificate %s", ugh);
+               return FALSE;
+       }
+       DBG2("ocsp signer certificate is valid");
+
+       public_key = ocsp_cert->get_public_key(ocsp_cert);
+
+       return public_key->verify_emsa_pkcs1_signature(public_key, res->tbs, res->signature) == SUCCESS;
+}
+
+/**
  * parse a single OCSP response
  */
 static bool ocsp_parse_single_response(chunk_t blob, int level0, single_response_t *sres)
@@ -706,39 +738,76 @@ static void process_single_response(private_ocsp_t *this, single_response_t *sre
 /**
  *  verify and process ocsp response and update the ocsp cache
  */
-void ocsp_process_response(private_ocsp_t *this, chunk_t reply)
+void ocsp_process_response(private_ocsp_t *this, chunk_t blob, credential_store_t *credentials)
 {
-       response_t res = empty_response;
+       x509_t *ocsp_cert = NULL;
+       response_t *res = response_create();
 
        /* parse the ocsp response without looking at the single responses yet */
-       response_status status = ocsp_parse_response(reply, &res);
+       response_status status = ocsp_parse_response(blob, res);
 
        if (status != STATUS_SUCCESSFUL)
        {
                DBG1("error in ocsp response");
-               return;
+               goto err;
        }
 
        /* check if there was a nonce in the request */
-       if (this->nonce.ptr != NULL && res.nonce.ptr == NULL)
+       if (this->nonce.ptr != NULL && res->nonce.ptr == NULL)
        {
                DBG1("ocsp response contains no nonce, replay attack possible");
        }
 
        /* check if the nonces are identical */
-       if (res.nonce.ptr != NULL && !chunk_equals(res.nonce, this->nonce))
+       if (res->nonce.ptr != NULL && !chunk_equals(res->nonce, this->nonce))
     {
                DBG1("invalid nonce in ocsp response");
-               return;
+               goto err;
        }
 
-       /* check if the response is signed by a trusted key */
-       if (!ocsp_valid_response(&res))
+       /* check if we received a trusted responder certificate */
+       if (res->responder_cert)
        {
-               DBG1("invalid ocsp response");
-               return;
+               if (res->responder_cert->is_ocsp_signer(res->responder_cert))
+               {
+                       DBG2("received certificate is ocsp signer");
+                       if (credentials->is_trusted(credentials, res->responder_cert))
+                       {
+                               DBG2("received ocsp signer certificate is trusted");
+                               ocsp_cert = credentials->add_auth_certificate(credentials,
+                                                                       res->responder_cert, AUTH_OCSP);
+                               res->responder_cert = NULL;
+                       }
+                       else
+                       {
+                               DBG1("received ocsp signer certificate is not trusted - rejected");
+                       }
+               }
+               else
+               {
+                       DBG1("received certificate is no ocsp signer - rejected");
+               }
+       }
+
+       /* if we didn't receive a trusted responder cert, search the credential store */
+       if (ocsp_cert == NULL)
+       {
+               ocsp_cert = credentials->get_auth_certificate(credentials,
+                                                       AUTH_OCSP|AUTH_CA, res->responder_id_name);
+               if (ocsp_cert == NULL)
+               {
+                       DBG1("no ocsp signer certificate found");
+                       goto err;
+               }
+       }
+
+       /* check the response signature */
+       if (!ocsp_valid_response(res, ocsp_cert))
+       {
+               DBG1("ocsp response signature is invalid");
+               goto err;
        }
-       DBG2("valid ocsp response");
+       DBG2("ocsp response signature is valid");
 
     /* now parse the single responses one at a time */
     {
@@ -747,13 +816,13 @@ void ocsp_process_response(private_ocsp_t *this, chunk_t reply)
                chunk_t object;
                int objectID = 0;
 
-               asn1_init(&ctx, res.responses, 0, FALSE, FALSE);
+               asn1_init(&ctx, res->responses, 0, FALSE, FALSE);
 
                while (objectID < RESPONSES_ROOF)
                {
                        if (!extract_object(responsesObjects, &objectID, &object, &level, &ctx))
                        {
-                               return;
+                               goto err;
                        }
                        if (objectID == RESPONSES_SINGLE_RESPONSE)
                        {
@@ -767,12 +836,14 @@ void ocsp_process_response(private_ocsp_t *this, chunk_t reply)
                        objectID++;
                }
        }
+err:
+       res->destroy(res);
 }
 
 /**
  * Implements ocsp_t.fetch.
  */
-static void fetch(private_ocsp_t *this, certinfo_t *certinfo)
+static void fetch(private_ocsp_t *this, certinfo_t *certinfo, credential_store_t *credentials)
 {
        chunk_t request;
        chunk_t response;
@@ -816,7 +887,7 @@ static void fetch(private_ocsp_t *this, certinfo_t *certinfo)
                return;
        }
        DBG3("ocsp response: %B", &response);
-       ocsp_process_response(this, response);
+       ocsp_process_response(this, response, credentials);
        free(response.ptr);
 }
 
@@ -853,7 +924,7 @@ ocsp_t *ocsp_create(x509_t *cacert, linked_list_t *uris)
        }
 
        /* public functions */
-       this->public.fetch = (void (*) (ocsp_t*,certinfo_t*))fetch;
+       this->public.fetch = (void (*) (ocsp_t*,certinfo_t*,credential_store_t*))fetch;
        this->public.destroy = (void (*) (ocsp_t*))destroy;
 
        return &this->public;
index 687eae4..42059e1 100644 (file)
@@ -27,7 +27,9 @@
 
 typedef struct ocsp_t ocsp_t;
 
-#include "utils/linked_list.h"
+#include <credential_store.h>
+#include <utils/linked_list.h>
+
 #include "certinfo.h"
 
 /* constants */
@@ -57,8 +59,9 @@ struct ocsp_t {
         * 
         * @param uris                          linked list of ocsp uris
         * @param certinfo                      certificate status info to be updated
+        * @param credentials           credential store needed for trust path verification
         */
-       void (*fetch) (ocsp_t *this, certinfo_t *certinfo);
+       void (*fetch) (ocsp_t *this, certinfo_t *certinfo, credential_store_t *credentials);
 
        /**
         * @brief Destroys the ocsp_t object.