From db0f828413a9a277a8da7075cebd988718a19ad6 Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Mon, 12 Mar 2007 13:42:31 +0000 Subject: [PATCH] results from the single responses is stored in the corresponding certinfo_t structs --- .../credentials/local_credential_store.c | 4 +- src/libstrongswan/crypto/certinfo.c | 19 +++ src/libstrongswan/crypto/certinfo.h | 18 ++- src/libstrongswan/crypto/ocsp.c | 114 +++++++++--------- 4 files changed, 94 insertions(+), 61 deletions(-) diff --git a/src/charon/config/credentials/local_credential_store.c b/src/charon/config/credentials/local_credential_store.c index 9dcd28be3..50fc53b32 100644 --- a/src/charon/config/credentials/local_credential_store.c +++ b/src/charon/config/credentials/local_credential_store.c @@ -645,7 +645,7 @@ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *f certinfo->destroy(certinfo); return FALSE; } - DBG2(DBG_CFG, "certificate is good"); + DBG1(DBG_CFG, "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 @@ -684,7 +684,7 @@ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *f case CERT_UNKNOWN: case CERT_UNDEFINED: default: - DBG2(DBG_CFG, "certificate status unknown"); + DBG1(DBG_CFG, "certificate status unknown"); if (this->strict) { /* update status of end certificate in the credential store */ diff --git a/src/libstrongswan/crypto/certinfo.c b/src/libstrongswan/crypto/certinfo.c index 1ba5bf2f6..8c899e678 100644 --- a/src/libstrongswan/crypto/certinfo.c +++ b/src/libstrongswan/crypto/certinfo.c @@ -125,6 +125,22 @@ static cert_status_t get_status(const private_certinfo_t *this) return this->status; } +/** + * Implements certinfo_t.set_thisUpdate + */ +static void set_thisUpdate(private_certinfo_t *this, time_t thisUpdate) +{ + this->thisUpdate = thisUpdate; +} + +/** + * Implements certinfo_t.get_thisUpdate + */ +static time_t get_thisUpdate(const private_certinfo_t *this) +{ + return this->thisUpdate; +} + /** * Implements certinfo_t.set_nextUpdate */ @@ -192,6 +208,7 @@ certinfo_t *certinfo_create(chunk_t serial) /* initialize */ this->serialNumber = chunk_clone(serial); this->status = CERT_UNDEFINED; + this->thisUpdate = UNDEFINED_TIME; this->nextUpdate = UNDEFINED_TIME; this->revocationTime = UNDEFINED_TIME; this->revocationReason = REASON_UNSPECIFIED; @@ -201,6 +218,8 @@ certinfo_t *certinfo_create(chunk_t serial) 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_thisUpdate = (void (*) (certinfo_t*,time_t))set_thisUpdate; + this->public.get_thisUpdate = (time_t (*) (const certinfo_t*))get_thisUpdate; 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; diff --git a/src/libstrongswan/crypto/certinfo.h b/src/libstrongswan/crypto/certinfo.h index acea85698..b8be002a9 100644 --- a/src/libstrongswan/crypto/certinfo.h +++ b/src/libstrongswan/crypto/certinfo.h @@ -99,11 +99,27 @@ struct certinfo_t { */ cert_status_t (*get_status) (const certinfo_t *this); + /** + * @brief Set thisUpdate. + * + * @param this calling object + * @param thisUpdate thisUpdate + */ + void (*set_thisUpdate) (certinfo_t *this, time_t thisUpdate); + + /** + * @brief Get thisUpdate. + * + * @param this calling object + * @return thisUpdate + */ + time_t (*get_thisUpdate) (const certinfo_t *this); + /** * @brief Set nextUpdate. * * @param this calling object - * @return nextUpdate + * @param nextUpdate */ void (*set_nextUpdate) (certinfo_t *this, time_t nextUpdate); diff --git a/src/libstrongswan/crypto/ocsp.c b/src/libstrongswan/crypto/ocsp.c index c22d26e8e..6f21aa8dc 100644 --- a/src/libstrongswan/crypto/ocsp.c +++ b/src/libstrongswan/crypto/ocsp.c @@ -85,6 +85,11 @@ struct private_ocsp_t { * SHA-1 hash over issuer distinguished name */ chunk_t authNameID; + + /** + * SHA-1 hash over issuer public key + */ + chunk_t authKeyID; }; ENUM(response_status_names, STATUS_SUCCESSFUL, STATUS_UNAUTHORIZED, @@ -153,35 +158,6 @@ static response_t* response_create_from_chunk(chunk_t chunk) return this; } -/* single response container */ -typedef struct single_response single_response_t; - -struct single_response { - single_response_t *next; - int hash_algorithm; - chunk_t issuer_name_hash; - chunk_t issuer_key_hash; - chunk_t serialNumber; - cert_status_t status; - time_t revocationTime; - crl_reason_t revocationReason; - time_t thisUpdate; - time_t nextUpdate; -}; - -const single_response_t empty_single_response = { - NULL , /* *next */ - OID_UNKNOWN , /* hash_algorithm */ - { NULL, 0 } , /* issuer_name_hash */ - { NULL, 0 } , /* issuer_key_hash */ - { NULL, 0 } , /* serial_number */ - CERT_UNDEFINED , /* status */ - UNDEFINED_TIME , /* revocationTime */ - REASON_UNSPECIFIED, /* revocationReason */ - UNDEFINED_TIME , /* this_update */ - UNDEFINED_TIME /* next_update */ -}; - /* some OCSP specific prefabricated ASN.1 constants */ static u_char ASN1_nonce_oid_str[] = { @@ -346,13 +322,12 @@ static chunk_t build_requestor_name(private_ocsp_t *this) */ static chunk_t build_request(private_ocsp_t *this, certinfo_t *certinfo) { - chunk_t authKeyID = this->cacert->get_subjectKeyID(this->cacert); chunk_t serialNumber = certinfo->get_serialNumber(certinfo); chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "cmmm", ASN1_sha1_id, asn1_simple_object(ASN1_OCTET_STRING, this->authNameID), - asn1_simple_object(ASN1_OCTET_STRING, authKeyID), + asn1_simple_object(ASN1_OCTET_STRING, this->authKeyID), asn1_simple_object(ASN1_INTEGER, serialNumber)); return asn1_wrap(ASN1_SEQUENCE, "m", reqCert); @@ -660,7 +635,7 @@ static bool ocsp_valid_response(response_t *res, x509_t *ocsp_cert) /** * parse a single OCSP response */ -static bool ocsp_parse_single_response(chunk_t blob, int level0, single_response_t *sres) +static bool ocsp_parse_single_response(private_ocsp_t *this, chunk_t blob, int level0) { u_int level, extn_oid; asn1_ctx_t ctx; @@ -668,6 +643,8 @@ static bool ocsp_parse_single_response(chunk_t blob, int level0, single_response chunk_t object; int objectID = 0; + certinfo_t *certinfo = NULL; + asn1_init(&ctx, blob, level0, FALSE, FALSE); while (objectID < SINGLE_RESPONSE_ROOF) @@ -680,38 +657,70 @@ static bool ocsp_parse_single_response(chunk_t blob, int level0, single_response switch (objectID) { case SINGLE_RESPONSE_ALGORITHM: - sres->hash_algorithm = parse_algorithmIdentifier(object, level+1, NULL); + if (parse_algorithmIdentifier(object, level+1, NULL) != OID_SHA1) + { + DBG1("only sha-1 hash supported in ocsp single response"); + return FALSE; + } break; case SINGLE_RESPONSE_ISSUER_NAME_HASH: - sres->issuer_name_hash = object; + if (!chunk_equals(object, this->authNameID)) + { + DBG1("ocsp single response has wrong issuer name hash"); + return FALSE; + } break; case SINGLE_RESPONSE_ISSUER_KEY_HASH: - sres->issuer_key_hash = object; + if (!chunk_equals(object, this->authKeyID)) + { + DBG1("ocsp single response has wrong issuer key hash"); + return FALSE; + } break; case SINGLE_RESPONSE_SERIAL_NUMBER: - sres->serialNumber = object; + { + iterator_t *iterator = this->certinfos->create_iterator(this->certinfos, TRUE); + certinfo_t *current_certinfo; + + while (iterator->iterate(iterator, (void**)¤t_certinfo)) + { + if (chunk_equals(object, current_certinfo->get_serialNumber(current_certinfo))) + { + certinfo = current_certinfo; + } + } + iterator->destroy(iterator); + if (certinfo == NULL) + { + DBG1("unrequested serial number in ocsp single response"); + return FALSE; + } + } break; case SINGLE_RESPONSE_CERT_STATUS_GOOD: - sres->status = CERT_GOOD; + certinfo->set_status(certinfo, CERT_GOOD); break; case SINGLE_RESPONSE_CERT_STATUS_REVOKED: - sres->status = CERT_REVOKED; + certinfo->set_status(certinfo, CERT_REVOKED); break; case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME: - sres->revocationTime = asn1totime(&object, ASN1_GENERALIZEDTIME); + certinfo->set_revocationTime(certinfo, + asn1totime(&object, ASN1_GENERALIZEDTIME)); break; case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON: - sres->revocationReason = (object.len == 1) - ? *object.ptr : REASON_UNSPECIFIED; + certinfo->set_revocationReason(certinfo, + (object.len == 1) ? *object.ptr : REASON_UNSPECIFIED); break; case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN: - sres->status = CERT_UNKNOWN; + certinfo->set_status(certinfo, CERT_UNKNOWN); break; case SINGLE_RESPONSE_THIS_UPDATE: - sres->thisUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME); + certinfo->set_thisUpdate(certinfo, + asn1totime(&object, ASN1_GENERALIZEDTIME)); break; case SINGLE_RESPONSE_NEXT_UPDATE: - sres->nextUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME); + certinfo->set_nextUpdate(certinfo, + asn1totime(&object, ASN1_GENERALIZEDTIME)); break; case SINGLE_RESPONSE_EXT_ID: extn_oid = known_oid(object); @@ -727,14 +736,6 @@ static bool ocsp_parse_single_response(chunk_t blob, int level0, single_response return TRUE; } -/** - * process received ocsp single response and add it to ocsp cache - */ -static void process_single_response(private_ocsp_t *this, single_response_t *sres) -{ - /* TODO */ -} - /** * verify and process ocsp response and update the ocsp cache */ @@ -825,12 +826,7 @@ static void ocsp_process_response(private_ocsp_t *this, response_t *res, credent } if (objectID == RESPONSES_SINGLE_RESPONSE) { - single_response_t sres = empty_single_response; - - if (ocsp_parse_single_response(object, level+1, &sres)) - { - process_single_response(this, &sres); - } + ocsp_parse_single_response(this, object, level+1); } objectID++; } @@ -911,6 +907,8 @@ ocsp_t *ocsp_create(x509_t *cacert, linked_list_t *uris) this->uris = uris; this->certinfos = linked_list_create(); this->nonce = chunk_empty; + this->authKeyID = cacert->get_subjectKeyID(cacert); + /* TODO compute authKeyID in case subjectKeyID does not exist */ { hasher_t *hasher = hasher_create(HASH_SHA1); identification_t *issuer = cacert->get_subject(cacert);