support of multiple certificates with same peer id
authorAndreas Steffen <andreas.steffen@strongswan.org>
Tue, 15 May 2007 12:46:05 +0000 (12:46 -0000)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Tue, 15 May 2007 12:46:05 +0000 (12:46 -0000)
src/charon/config/credentials/local_credential_store.c
src/charon/sa/authenticators/rsa_authenticator.c
src/libstrongswan/credential_store.h

index a920150..e21c28a 100644 (file)
@@ -323,51 +323,89 @@ static ca_info_t* get_issuer(private_local_credential_store_t *this, const x509_
 }
 
 /**
 }
 
 /**
- * Implementation of local_credential_store_t.get_trusted_public_key.
+ * Implementation of local_credential_store_t.verify.
  */
  */
-static rsa_public_key_t *get_trusted_public_key(private_local_credential_store_t *this,
-                                                                                               identification_t *id)
+static status_t verify_signature(private_local_credential_store_t *this,
+                                                                chunk_t hash, chunk_t sig,
+                                                                identification_t *id, ca_info_t **issuer_p)
 {
 {
-       cert_status_t status;
-       err_t ugh;
-
-       x509_t *cert = get_certificate(this, id);
+       iterator_t *iterator = this->certs->create_iterator(this->certs, TRUE);
+       status_t sig_status;
+       x509_t *cert;
 
 
-       if (cert == NULL)
-               return NULL;
+       /* default return values in case of failure */
+       sig_status = NOT_FOUND;
+       *issuer_p = NULL;
 
 
-       ugh = cert->is_valid(cert, NULL);
-       if (ugh != NULL)
+       while (iterator->iterate(iterator, (void**)&cert))
        {
        {
-               DBG1(DBG_CFG, "certificate %s", ugh);
-               return NULL;
-       }
+               if (id->equals(id, cert->get_subject(cert))
+               ||      cert->equals_subjectAltName(cert, id))
+               {
+                       err_t ugh;
+                       rsa_public_key_t *public_key = cert->get_public_key(cert);
+                       chunk_t keyid = public_key->get_keyid(public_key);
 
 
-       if (!cert->is_self_signed(cert))
-       {
-               ca_info_t *issuer = get_issuer(this, cert);
+                       DBG2(DBG_CFG, "found candidate peer certificate");
+                       DBG2(DBG_CFG, "subject: '%D'", cert->get_subject(cert));
+                       DBG2(DBG_CFG, "issuer:  '%D'", cert->get_issuer(cert));
+                       DBG2(DBG_CFG, "keyid:    %#B", &keyid);
 
 
-               if (issuer == NULL)
-               {
-                       DBG1(DBG_CFG, "issuer of public key not found");
-                       return NULL;
-               }
-               status = cert->get_status(cert);
+                       ugh = cert->is_valid(cert, NULL);
+                       if (ugh != NULL)
+                       {
+                               DBG1(DBG_CFG, "candidate peer certificate %s", ugh);
+                               sig_status = INVALID_STATE;
+                               continue;
+                       }
+                       if (!cert->is_self_signed(cert))
+                       {
+                               cert_status_t cert_status;
+                               ca_info_t *issuer = get_issuer(this, cert);
 
 
-               if (status == CERT_REVOKED
-               ||  status == CERT_UNTRUSTED
-               || (issuer->is_strict(issuer) && status != CERT_GOOD))
-               {
-                       DBG1(DBG_CFG, "certificate status: %N", cert_status_names, status);
-                       return NULL;
-               }
-               if (status == CERT_GOOD && cert->get_until(cert) < time(NULL))
-               {
-                       DBG1(DBG_CFG, "certificate is good but crl is stale");
-                       return NULL;
+                               if (issuer == NULL)
+                               {
+                                       DBG1(DBG_CFG, "issuer of candidate peer certificate not found");
+                                       sig_status = NOT_FOUND;
+                                       continue;
+                               }
+                               cert_status = cert->get_status(cert);
+
+                               if (cert_status == CERT_REVOKED
+                               ||  cert_status == CERT_UNTRUSTED
+                               || ((issuer)->is_strict(issuer) && cert_status != CERT_GOOD))
+                               {
+                                       DBG1(DBG_CFG, "candidate peer certificate has a non-acceptable status: %N", cert_status_names, cert_status);
+                                       sig_status = INVALID_STATE;
+                                       continue;
+                               }
+                               if (cert_status == CERT_GOOD && cert->get_until(cert) < time(NULL))
+                               {
+                                       DBG1(DBG_CFG, "candidate peer certificate is good but crl is stale");
+                                       sig_status = INVALID_STATE;
+                                       continue;
+                               }
+                               *issuer_p = issuer;
+                       }
+                       sig_status = public_key->verify_emsa_pkcs1_signature(public_key, hash, sig);
+                       if (sig_status == SUCCESS)
+                       {
+                               DBG2(DBG_CFG, "candidate peer certificate has a matching RSA public key");
+                               break;
+                       }
+                       else
+                       {
+                               DBG1(DBG_CFG, "candidate peer certificate has a non-matching RSA public key");
+                               *issuer_p = NULL;
+                       }
                }
        }
                }
        }
-       return cert->get_public_key(cert);
+       iterator->destroy(iterator);
+       if (sig_status == NOT_FOUND)
+       {
+               DBG1(DBG_CFG, "no candidate peer certificate found");
+       }
+       return sig_status;
 }
 
 /**
 }
 
 /**
@@ -1414,12 +1452,12 @@ local_credential_store_t * local_credential_store_create(void)
        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.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.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_trusted_public_key = (rsa_public_key_t*(*)(credential_store_t*,identification_t*))get_trusted_public_key;
        this->public.credential_store.get_certificate = (x509_t* (*) (credential_store_t*,identification_t*))get_certificate;
        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.get_certificate = (x509_t* (*) (credential_store_t*,identification_t*))get_certificate;
        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_signature = (status_t (*) (credential_store_t*,chunk_t,chunk_t,identification_t*,ca_info_t**))verify_signature;
        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;
        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 19aad06..beb9463 100644 (file)
@@ -60,8 +60,8 @@ static status_t verify(private_rsa_authenticator_t *this, chunk_t ike_sa_init,
 {
        status_t status;
        chunk_t auth_data, octets;
 {
        status_t status;
        chunk_t auth_data, octets;
-       rsa_public_key_t *public_key;
        identification_t *other_id;
        identification_t *other_id;
+       ca_info_t *issuer;
        prf_t *prf;
        
        other_id = this->ike_sa->get_other_id(this->ike_sa);
        prf_t *prf;
        
        other_id = this->ike_sa->get_other_id(this->ike_sa);
@@ -71,28 +71,17 @@ static status_t verify(private_rsa_authenticator_t *this, chunk_t ike_sa_init,
                return INVALID_ARG;
        }
        auth_data = auth_payload->get_data(auth_payload);
                return INVALID_ARG;
        }
        auth_data = auth_payload->get_data(auth_payload);
-       public_key = charon->credentials->get_trusted_public_key(charon->credentials,
-                                                                                                                        other_id);
-       if (public_key == NULL)
-       {
-               DBG1(DBG_IKE, "no RSA public key found for '%D'", other_id);
-               return NOT_FOUND;
-       }
        prf = this->ike_sa->get_prf(this->ike_sa);
        prf->set_key(prf, this->ike_sa->get_skp_verify(this->ike_sa));
        octets = build_tbs_octets(ike_sa_init, my_nonce, other_id, prf);
        prf = this->ike_sa->get_prf(this->ike_sa);
        prf->set_key(prf, this->ike_sa->get_skp_verify(this->ike_sa));
        octets = build_tbs_octets(ike_sa_init, my_nonce, other_id, prf);
-       status = public_key->verify_emsa_pkcs1_signature(public_key, octets, auth_data);
+       status = charon->credentials->verify_signature(charon->credentials,
+                                                                 octets, auth_data, other_id, &issuer);
        chunk_free(&octets);
        
        chunk_free(&octets);
        
-       if (status != SUCCESS)
-       {
-               DBG1(DBG_IKE, "RSA signature verification failed");
-               return status;
-       }
-       
-       DBG1(DBG_IKE, "authentication of '%D' with %N successful",
-                other_id, auth_method_names, AUTH_RSA);
-       return SUCCESS;
+       DBG1(DBG_IKE, "authentication of '%D' with %N %s",
+                                 other_id, auth_method_names, AUTH_RSA,
+                                 (status == SUCCESS)? "successful":"failed");
+       return status;
 }
 
 /**
 }
 
 /**
index 65e692d..dce8d60 100755 (executable)
@@ -88,15 +88,6 @@ struct credential_store_t {
        rsa_public_key_t* (*get_rsa_public_key) (credential_store_t *this, identification_t *id);
        
        /**
        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.
         * @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.
@@ -154,6 +145,18 @@ struct credential_store_t {
        ca_info_t* (*get_issuer) (credential_store_t *this, const x509_t* cert);
 
        /**
        ca_info_t* (*get_issuer) (credential_store_t *this, const x509_t* cert);
 
        /**
+        * @brief Verify an RSA signature given the ID of the signer
+        * 
+        * @param this                                  calling object
+        * @param hash                                  hash value to be verified.
+        * @param sig                                   signature to be verified.
+        * @param id                                    identification_t object identifiying the signer.
+        * @param issuer_p                              issuer of the signer's certificate (if not self-signed).
+        * @return                                              status of the verification - SUCCESS if successful
+        */
+       status_t (*verify_signature) (credential_store_t *this, chunk_t hash, chunk_t sig, identification_t *id, ca_info_t **issuer_p);
+       
+       /**
         * @brief Verify an X.509 certificate up to trust anchor without any status checks
         *
         * @param this          calling object
         * @brief Verify an X.509 certificate up to trust anchor without any status checks
         *
         * @param this          calling object