support of multiple certificates with same peer id
This commit is contained in:
@@ -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,
|
static status_t verify_signature(private_local_credential_store_t *this,
|
||||||
identification_t *id)
|
chunk_t hash, chunk_t sig,
|
||||||
|
identification_t *id, ca_info_t **issuer_p)
|
||||||
{
|
{
|
||||||
cert_status_t status;
|
iterator_t *iterator = this->certs->create_iterator(this->certs, TRUE);
|
||||||
err_t ugh;
|
status_t sig_status;
|
||||||
|
x509_t *cert;
|
||||||
|
|
||||||
x509_t *cert = get_certificate(this, id);
|
/* default return values in case of failure */
|
||||||
|
sig_status = NOT_FOUND;
|
||||||
|
*issuer_p = NULL;
|
||||||
|
|
||||||
if (cert == NULL)
|
while (iterator->iterate(iterator, (void**)&cert))
|
||||||
return NULL;
|
|
||||||
|
|
||||||
ugh = cert->is_valid(cert, NULL);
|
|
||||||
if (ugh != NULL)
|
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "certificate %s", ugh);
|
if (id->equals(id, cert->get_subject(cert))
|
||||||
return NULL;
|
|| cert->equals_subjectAltName(cert, id))
|
||||||
}
|
|
||||||
|
|
||||||
if (!cert->is_self_signed(cert))
|
|
||||||
{
|
|
||||||
ca_info_t *issuer = get_issuer(this, cert);
|
|
||||||
|
|
||||||
if (issuer == NULL)
|
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "issuer of public key not found");
|
err_t ugh;
|
||||||
return NULL;
|
rsa_public_key_t *public_key = cert->get_public_key(cert);
|
||||||
}
|
chunk_t keyid = public_key->get_keyid(public_key);
|
||||||
status = cert->get_status(cert);
|
|
||||||
|
|
||||||
if (status == CERT_REVOKED
|
DBG2(DBG_CFG, "found candidate peer certificate");
|
||||||
|| status == CERT_UNTRUSTED
|
DBG2(DBG_CFG, "subject: '%D'", cert->get_subject(cert));
|
||||||
|| (issuer->is_strict(issuer) && status != CERT_GOOD))
|
DBG2(DBG_CFG, "issuer: '%D'", cert->get_issuer(cert));
|
||||||
{
|
DBG2(DBG_CFG, "keyid: %#B", &keyid);
|
||||||
DBG1(DBG_CFG, "certificate status: %N", cert_status_names, status);
|
|
||||||
return NULL;
|
ugh = cert->is_valid(cert, NULL);
|
||||||
}
|
if (ugh != NULL)
|
||||||
if (status == CERT_GOOD && cert->get_until(cert) < time(NULL))
|
{
|
||||||
{
|
DBG1(DBG_CFG, "candidate peer certificate %s", ugh);
|
||||||
DBG1(DBG_CFG, "certificate is good but crl is stale");
|
sig_status = INVALID_STATE;
|
||||||
return NULL;
|
continue;
|
||||||
|
}
|
||||||
|
if (!cert->is_self_signed(cert))
|
||||||
|
{
|
||||||
|
cert_status_t cert_status;
|
||||||
|
ca_info_t *issuer = get_issuer(this, cert);
|
||||||
|
|
||||||
|
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_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.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.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_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_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_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.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.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.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_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.add_auth_certificate = (x509_t* (*) (credential_store_t*,x509_t*,u_int))add_auth_certificate;
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ static status_t verify(private_rsa_authenticator_t *this, chunk_t ike_sa_init,
|
|||||||
{
|
{
|
||||||
status_t status;
|
status_t status;
|
||||||
chunk_t auth_data, octets;
|
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;
|
prf_t *prf;
|
||||||
|
|
||||||
other_id = this->ike_sa->get_other_id(this->ike_sa);
|
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;
|
return INVALID_ARG;
|
||||||
}
|
}
|
||||||
auth_data = auth_payload->get_data(auth_payload);
|
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 = this->ike_sa->get_prf(this->ike_sa);
|
||||||
prf->set_key(prf, this->ike_sa->get_skp_verify(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);
|
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, "authentication of '%D' with %N %s",
|
||||||
{
|
other_id, auth_method_names, AUTH_RSA,
|
||||||
DBG1(DBG_IKE, "RSA signature verification failed");
|
(status == SUCCESS)? "successful":"failed");
|
||||||
return status;
|
return status;
|
||||||
}
|
|
||||||
|
|
||||||
DBG1(DBG_IKE, "authentication of '%D' with %N successful",
|
|
||||||
other_id, auth_method_names, AUTH_RSA);
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -87,15 +87,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
|
* @brief Returns the RSA private key belonging to an RSA public key
|
||||||
*
|
*
|
||||||
@@ -153,6 +144,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
|
* @brief Verify an X.509 certificate up to trust anchor without any status checks
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user