From ca78602304cae9e820833ecb6fbeef9f3111ec41 Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Tue, 15 May 2007 14:51:04 +0000 Subject: [PATCH] verification of locally loaded peer certificates --- .../credentials/local_credential_store.c | 179 +++++++++--------- 1 file changed, 92 insertions(+), 87 deletions(-) diff --git a/src/charon/config/credentials/local_credential_store.c b/src/charon/config/credentials/local_credential_store.c index e21c28af9..ca39a58c1 100644 --- a/src/charon/config/credentials/local_credential_store.c +++ b/src/charon/config/credentials/local_credential_store.c @@ -322,92 +322,6 @@ static ca_info_t* get_issuer(private_local_credential_store_t *this, const x509_ return found; } -/** - * Implementation of local_credential_store_t.verify. - */ -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) -{ - iterator_t *iterator = this->certs->create_iterator(this->certs, TRUE); - status_t sig_status; - x509_t *cert; - - /* default return values in case of failure */ - sig_status = NOT_FOUND; - *issuer_p = NULL; - - while (iterator->iterate(iterator, (void**)&cert)) - { - 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); - - 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); - - 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 (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; - } - } - } - iterator->destroy(iterator); - if (sig_status == NOT_FOUND) - { - DBG1(DBG_CFG, "no candidate peer certificate found"); - } - return sig_status; -} - /** * Implementation of local_credential_store_t.get_rsa_private_key. */ @@ -643,14 +557,16 @@ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *f for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++) { + bool valid_signature; err_t ugh = NULL; ca_info_t *issuer; x509_t *issuer_cert; rsa_public_key_t *issuer_public_key; - bool valid_signature; + chunk_t keyid = cert->get_keyid(cert); DBG1(DBG_CFG, "subject: '%D'", cert->get_subject(cert)); DBG1(DBG_CFG, "issuer: '%D'", cert->get_issuer(cert)); + DBG1(DBG_CFG, "keyid: %#B", &keyid); ugh = cert->is_valid(cert, &until); if (ugh != NULL) @@ -798,6 +714,95 @@ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *f return FALSE; } +/** + * Implementation of local_credential_store_t.verify_signature. + */ +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) +{ + iterator_t *iterator = this->certs->create_iterator(this->certs, TRUE); + status_t sig_status; + x509_t *cert; + + /* default return values in case of failure */ + sig_status = NOT_FOUND; + *issuer_p = NULL; + + while (iterator->iterate(iterator, (void**)&cert)) + { + if (id->equals(id, cert->get_subject(cert)) + || cert->equals_subjectAltName(cert, id)) + { + rsa_public_key_t *public_key = cert->get_public_key(cert); + cert_status_t cert_status = cert->get_status(cert); + + DBG2(DBG_CFG, "found candidate peer certificate"); + + if (cert_status == CERT_UNDEFINED || cert->get_until(cert) < time(NULL)) + { + bool found; + + if (!verify(this, cert, &found)) + { + sig_status = VERIFY_ERROR; + DBG1(DBG_CFG, "candidate peer certificate was not successfully verified"); + continue; + } + if (!cert->is_self_signed(cert)) + { + *issuer_p = get_issuer(this, cert); + } + } + else + { + chunk_t keyid = public_key->get_keyid(public_key); + + 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 (!cert->is_self_signed(cert)) + { + ca_info_t *issuer = get_issuer(this, cert); + + if (issuer == NULL) + { + DBG1(DBG_CFG, "candidate peer certificate has no retrievable issuer"); + sig_status = NOT_FOUND; + continue; + } + if (cert_status == CERT_REVOKED || cert_status == CERT_UNTRUSTED + || ((issuer)->is_strict(issuer) && cert_status != CERT_GOOD)) + { + DBG1(DBG_CFG, "candidate peer certificate has an inacceptable status: %N", cert_status_names, cert_status); + sig_status = VERIFY_ERROR; + 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; + } + } + } + iterator->destroy(iterator); + if (sig_status == NOT_FOUND) + { + DBG1(DBG_CFG, "no candidate peer certificate found"); + } + return sig_status; +} + /** * Add a unique certificate to a linked list */