diff options
Diffstat (limited to 'src/libstrongswan/plugins/x509/x509_ocsp_response.c')
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_ocsp_response.c | 212 |
1 files changed, 76 insertions, 136 deletions
diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_response.c b/src/libstrongswan/plugins/x509/x509_ocsp_response.c index 1b3187258..948d7ad85 100644 --- a/src/libstrongswan/plugins/x509/x509_ocsp_response.c +++ b/src/libstrongswan/plugins/x509/x509_ocsp_response.c @@ -1,5 +1,5 @@ /** - * Copyright (C) 2008 Martin Willi + * Copyright (C) 2008-2009 Martin Willi * Copyright (C) 2007 Andreas Steffen * Hochschule fuer Technik Rapperswil * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen @@ -45,42 +45,42 @@ struct private_x509_ocsp_response_t { * Public interface for this ocsp object. */ x509_ocsp_response_t public; - + /** * complete encoded OCSP response */ chunk_t encoding; - + /** * data for signature verficiation */ chunk_t tbsResponseData; - + /** * signature algorithm (OID) */ int signatureAlgorithm; - + /** * signature */ chunk_t signature; - + /** * name or keyid of the responder */ identification_t *responderId; - + /** * time of response production */ time_t producedAt; - + /** * latest nextUpdate in this OCSP response */ time_t usableUntil; - + /** * list of included certificates */ @@ -95,7 +95,7 @@ struct private_x509_ocsp_response_t { * Nonce required for ocsp request and response */ chunk_t nonce; - + /** * reference counter */ @@ -130,29 +130,23 @@ typedef struct { #define OCSP_BASIC_RESPONSE_VERSION 1 /* some OCSP specific prefabricated ASN.1 constants */ -static u_char ASN1_nonce_oid_str[] = { +static const chunk_t ASN1_nonce_oid = chunk_from_chars( 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02 -}; - -static u_char ASN1_response_oid_str[] = { +); +static const chunk_t ASN1_response_oid = chunk_from_chars( 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04 -}; - -static u_char ASN1_response_content_str[] = { +); +static const chunk_t ASN1_response_content = chunk_from_chars( 0x04, 0x0D, 0x30, 0x0B, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01 -}; - -static const chunk_t ASN1_nonce_oid = chunk_from_buf(ASN1_nonce_oid_str); -static const chunk_t ASN1_response_oid = chunk_from_buf(ASN1_response_oid_str); -static const chunk_t ASN1_response_content = chunk_from_buf(ASN1_response_content_str); +); /** * Implementaiton of ocsp_response_t.get_status @@ -167,14 +161,15 @@ static cert_validation_t get_status(private_x509_ocsp_response_t *this, single_response_t *response; cert_validation_t status = VALIDATION_FAILED; certificate_t *issuercert = &issuer->interface; - + enumerator = this->responses->create_enumerator(this->responses); while (enumerator->enumerate(enumerator, &response)) { hasher_t *hasher; identification_t *id; - chunk_t hash; - + key_encoding_type_t type; + chunk_t hash, fingerprint; + /* check serial first, is cheaper */ if (!chunk_equals(subject->get_serial(subject), response->serialNumber)) { @@ -184,22 +179,23 @@ static cert_validation_t get_status(private_x509_ocsp_response_t *this, if (response->issuerKeyHash.ptr) { public_key_t *public; - + public = issuercert->get_public_key(issuercert); if (!public) { continue; } switch (response->hashAlgorithm) - { /* TODO: generic mapper function */ + { case OID_SHA1: - id = public->get_id(public, ID_PUBKEY_SHA1); + type = KEY_ID_PUBKEY_SHA1; break; default: public->destroy(public); continue; } - if (!chunk_equals(response->issuerKeyHash, id->get_encoding(id))) + if (!public->get_fingerprint(public, type, &fingerprint) || + !chunk_equals(response->issuerKeyHash, fingerprint)) { public->destroy(public); continue; @@ -209,7 +205,7 @@ static cert_validation_t get_status(private_x509_ocsp_response_t *this, /* check issuerNameHash, if available */ else if (response->issuerNameHash.ptr) { - hasher = lib->crypto->create_hasher(lib->crypto, + hasher = lib->crypto->create_hasher(lib->crypto, hasher_algorithm_from_oid(response->hashAlgorithm)); if (!hasher) { @@ -233,7 +229,7 @@ static cert_validation_t get_status(private_x509_ocsp_response_t *this, *revocation_reason = response->revocationReason; *this_update = response->thisUpdate; *next_update = response->nextUpdate; - + break; } enumerator->destroy(enumerator); @@ -310,7 +306,7 @@ static bool parse_singleResponse(private_x509_ocsp_response_t *this, bool success = FALSE; single_response_t *response; - + response = malloc_thing(single_response_t); response->hashAlgorithm = OID_UNKNOWN; response->issuerNameHash = chunk_empty; @@ -318,7 +314,7 @@ static bool parse_singleResponse(private_x509_ocsp_response_t *this, response->serialNumber = chunk_empty; response->status = VALIDATION_FAILED; response->revocationTime = 0; - response->revocationReason = CRL_UNSPECIFIED; + response->revocationReason = CRL_REASON_UNSPECIFIED; response->thisUpdate = UNDEFINED_TIME; /* if nextUpdate is missing, we give it a short lifetime */ response->nextUpdate = this->producedAt + OCSP_DEFAULT_LIFETIME; @@ -357,7 +353,7 @@ static bool parse_singleResponse(private_x509_ocsp_response_t *this, { response->revocationReason = *object.ptr; } - break; + break; case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN: response->status = VALIDATION_FAILED; break; @@ -370,7 +366,7 @@ static bool parse_singleResponse(private_x509_ocsp_response_t *this, { this->usableUntil = response->nextUpdate; } - break; + break; } } success = parser->success(parser); @@ -400,14 +396,14 @@ static const asn1Object_t responsesObjects[] = { /** * Parse all responses */ -static bool parse_responses(private_x509_ocsp_response_t *this, +static bool parse_responses(private_x509_ocsp_response_t *this, chunk_t blob, int level0) { asn1_parser_t *parser; chunk_t object; int objectID; bool success = FALSE; - + parser = asn1_parser_create(responsesObjects, blob); parser->set_top_level(parser, level0); @@ -484,7 +480,7 @@ static const asn1Object_t basicResponseObjects[] = { /** * Parse a basicOCSPResponse */ -static bool parse_basicOCSPResponse(private_x509_ocsp_response_t *this, +static bool parse_basicOCSPResponse(private_x509_ocsp_response_t *this, chunk_t blob, int level0) { asn1_parser_t *parser; @@ -496,7 +492,7 @@ static bool parse_basicOCSPResponse(private_x509_ocsp_response_t *this, certificate_t *cert; bool success = FALSE; bool critical; - + parser = asn1_parser_create(basicResponseObjects, blob); parser->set_top_level(parser, level0); @@ -525,7 +521,7 @@ static bool parse_basicOCSPResponse(private_x509_ocsp_response_t *this, break; case BASIC_RESPONSE_ID_BY_KEY: this->responderId = identification_create_from_encoding( - ID_PUBKEY_INFO_SHA1, object); + ID_KEY_ID, object); DBG2(" '%Y'", this->responderId); break; case BASIC_RESPONSE_PRODUCED_AT: @@ -622,15 +618,15 @@ static bool parse_OCSPResponse(private_x509_ocsp_response_t *this) case OCSP_RESPONSE_STATUS: status = (ocsp_status_t)*object.ptr; switch (status) - { - case OCSP_SUCCESSFUL: + { + case OCSP_SUCCESSFUL: break; default: DBG1(" ocsp response status: %N", ocsp_status_names, status); goto end; } - break; + break; case OCSP_RESPONSE_TYPE: responseType = asn1_known_oid(object); break; @@ -689,35 +685,33 @@ static bool issued_by(private_x509_ocsp_response_t *this, certificate_t *issuer) signature_scheme_t scheme; bool valid; x509_t *x509 = (x509_t*)issuer; - + if (issuer->get_type(issuer) != CERT_X509) { return FALSE; } - if (this->responderId->get_type(this->responderId) == ID_DER_ASN1_DN) + if (this->responderId->get_type(this->responderId) == ID_KEY_ID) { - if (!this->responderId->equals(this->responderId, - issuer->get_subject(issuer))) + chunk_t fingerprint; + + key = issuer->get_public_key(issuer); + if (!key || + !key->get_fingerprint(key, KEY_ID_PUBKEY_SHA1, &fingerprint) || + !chunk_equals(fingerprint, + this->responderId->get_encoding(this->responderId))) { + DESTROY_IF(key); return FALSE; } + key->destroy(key); } else { - bool equal; - public_key_t *public = issuer->get_public_key(issuer); - - if (public == NULL) + if (!this->responderId->equals(this->responderId, + issuer->get_subject(issuer))) { return FALSE; } - equal = this->responderId->equals(this->responderId, - public->get_id(public, ID_PUBKEY_SHA1)); - public->destroy(public); - if (!equal) - { - return FALSE; - } } if (!(x509->get_flags(x509) & X509_OCSP_SIGNER) && !(x509->get_flags(x509) & X509_CA)) @@ -754,16 +748,8 @@ static public_key_t* get_public_key(private_x509_ocsp_response_t *this) static bool get_validity(private_x509_ocsp_response_t *this, time_t *when, time_t *not_before, time_t *not_after) { - time_t t; + time_t t = when ? *when : time(NULL); - if (when == NULL) - { - t = time(NULL); - } - else - { - t = *when; - } if (not_before) { *not_before = this->producedAt; @@ -791,7 +777,7 @@ static bool is_newer(certificate_t *this, certificate_t *that) &that_update, FALSE, new ? "replaced":"retained"); return new; } - + /** * Implementation of certificate_t.get_encoding. */ @@ -807,7 +793,7 @@ static bool equals(private_x509_ocsp_response_t *this, certificate_t *other) { chunk_t encoding; bool equal; - + if (this == (private_x509_ocsp_response_t*)other) { return TRUE; @@ -818,7 +804,7 @@ static bool equals(private_x509_ocsp_response_t *this, certificate_t *other) } if (other->equals == (void*)equals) { /* skip allocation if we have the same implementation */ - return chunk_equals(this->encoding, ((private_x509_ocsp_response_t*)other)->encoding); + return chunk_equals(this->encoding, ((private_x509_ocsp_response_t*)other)->encoding); } encoding = other->get_encoding(other); equal = chunk_equals(this->encoding, encoding); @@ -853,12 +839,12 @@ static void destroy(private_x509_ocsp_response_t *this) /** * load an OCSP response */ -static x509_ocsp_response_t *load(chunk_t data) +static x509_ocsp_response_t *load(chunk_t blob) { private_x509_ocsp_response_t *this; - + this = malloc_thing(private_x509_ocsp_response_t); - + this->public.interface.certificate.get_type = (certificate_type_t (*)(certificate_t *this))get_type; this->public.interface.certificate.get_subject = (identification_t* (*)(certificate_t *this))get_issuer; this->public.interface.certificate.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer; @@ -874,9 +860,9 @@ static x509_ocsp_response_t *load(chunk_t data) this->public.interface.certificate.destroy = (void (*)(certificate_t *this))destroy; this->public.interface.get_status = (cert_validation_t(*)(ocsp_response_t*, x509_t *subject, x509_t *issuer, time_t *revocation_time,crl_reason_t *revocation_reason,time_t *this_update, time_t *next_update))get_status; this->public.interface.create_cert_enumerator = (enumerator_t*(*)(ocsp_response_t*))create_cert_enumerator; - + this->ref = 1; - this->encoding = data; + this->encoding = chunk_clone(blob); this->tbsResponseData = chunk_empty; this->responderId = NULL; this->producedAt = UNDEFINED_TIME; @@ -895,78 +881,32 @@ static x509_ocsp_response_t *load(chunk_t data) return &this->public; } - -typedef struct private_builder_t private_builder_t; /** - * Builder implementation for certificate loading + * See header. */ -struct private_builder_t { - /** implements the builder interface */ - builder_t public; - /** loaded response */ - x509_ocsp_response_t *res; -}; - -/** - * Implementation of builder_t.build - */ -static x509_ocsp_response_t *build(private_builder_t *this) +x509_ocsp_response_t *x509_ocsp_response_load(certificate_type_t type, + va_list args) { - x509_ocsp_response_t *res = this->res; - - free(this); - return res; -} + chunk_t blob = chunk_empty; -/** - * Implementation of builder_t.add - */ -static void add(private_builder_t *this, builder_part_t part, ...) -{ - if (!this->res) + while (TRUE) { - va_list args; - chunk_t chunk; - - switch (part) + switch (va_arg(args, builder_part_t)) { case BUILD_BLOB_ASN1_DER: - { - va_start(args, part); - chunk = va_arg(args, chunk_t); - this->res = load(chunk_clone(chunk)); - va_end(args); - return; - } - default: + blob = va_arg(args, chunk_t); + continue; + case BUILD_END: break; + default: + return NULL; } + break; } - if (this->res) + if (blob.ptr) { - destroy((private_x509_ocsp_response_t*)this->res); + return load(blob); } - builder_cancel(&this->public); -} - -/** - * Builder construction function - */ -builder_t *x509_ocsp_response_builder(certificate_type_t type) -{ - private_builder_t *this; - - if (type != CERT_X509_OCSP_RESPONSE) - { - return NULL; - } - - this = malloc_thing(private_builder_t); - - this->res = NULL; - this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add; - this->public.build = (void*(*)(builder_t *this))build; - - return &this->public; + return NULL; } |