summaryrefslogtreecommitdiff
path: root/src/libstrongswan/plugins/x509/x509_ocsp_response.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/plugins/x509/x509_ocsp_response.c')
-rw-r--r--src/libstrongswan/plugins/x509/x509_ocsp_response.c212
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;
}