2 * Copyright (C) 2008-2009 Martin Willi
3 * Copyright (C) 2007 Andreas Steffen
4 * Hochschule fuer Technik Rapperswil
5 * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #include "x509_ocsp_response.h"
23 #include <asn1/asn1.h>
24 #include <asn1/asn1_parser.h>
25 #include <utils/identification.h>
26 #include <utils/linked_list.h>
30 #include <credentials/certificates/x509.h>
31 #include <credentials/certificates/crl.h>
34 * how long do we use an OCSP response without a nextUpdate
36 #define OCSP_DEFAULT_LIFETIME 30
38 typedef struct private_x509_ocsp_response_t private_x509_ocsp_response_t
;
41 * Private data of a ocsp_t object.
43 struct private_x509_ocsp_response_t
{
45 * Public interface for this ocsp object.
47 x509_ocsp_response_t
public;
50 * complete encoded OCSP response
55 * data for signature verficiation
57 chunk_t tbsResponseData
;
60 * signature algorithm (OID)
62 int signatureAlgorithm
;
70 * name or keyid of the responder
72 identification_t
*responderId
;
75 * time of response production
80 * latest nextUpdate in this OCSP response
85 * list of included certificates
90 * Linked list of OCSP responses, single_response_t
92 linked_list_t
*responses
;
95 * Nonce required for ocsp request and response
106 * single response contained in OCSP response
109 /** hash algorithm OID to for the two hashes */
111 /** hash of issuer DN */
112 chunk_t issuerNameHash
;
114 chunk_t issuerKeyHash
;
115 /** serial number of certificate */
116 chunk_t serialNumber
;
117 /** OCSP certificate status */
118 cert_validation_t status
;
119 /** time of revocation, if revoked */
120 time_t revocationTime
;
121 /** revocation reason, if revoked */
122 crl_reason_t revocationReason
;
123 /** creation of associated CRL */
125 /** creation of next CRL */
129 /* our OCSP response version implementation */
130 #define OCSP_BASIC_RESPONSE_VERSION 1
132 /* some OCSP specific prefabricated ASN.1 constants */
133 static const chunk_t ASN1_nonce_oid
= chunk_from_chars(
136 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02
138 static const chunk_t ASN1_response_oid
= chunk_from_chars(
141 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04
143 static const chunk_t ASN1_response_content
= chunk_from_chars(
148 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
152 * Implementaiton of ocsp_response_t.get_status
154 static cert_validation_t
get_status(private_x509_ocsp_response_t
*this,
155 x509_t
*subject
, x509_t
*issuer
,
156 time_t *revocation_time
,
157 crl_reason_t
*revocation_reason
,
158 time_t *this_update
, time_t *next_update
)
160 enumerator_t
*enumerator
;
161 single_response_t
*response
;
162 cert_validation_t status
= VALIDATION_FAILED
;
163 certificate_t
*issuercert
= &issuer
->interface
;
165 enumerator
= this->responses
->create_enumerator(this->responses
);
166 while (enumerator
->enumerate(enumerator
, &response
))
169 identification_t
*id
;
170 cred_encoding_type_t type
;
171 chunk_t hash
, fingerprint
;
173 /* check serial first, is cheaper */
174 if (!chunk_equals(subject
->get_serial(subject
), response
->serialNumber
))
178 /* check issuerKeyHash if available */
179 if (response
->issuerKeyHash
.ptr
)
181 public_key_t
*public;
183 public = issuercert
->get_public_key(issuercert
);
188 switch (response
->hashAlgorithm
)
191 type
= KEYID_PUBKEY_SHA1
;
194 public->destroy(public);
197 if (!public->get_fingerprint(public, type
, &fingerprint
) ||
198 !chunk_equals(response
->issuerKeyHash
, fingerprint
))
200 public->destroy(public);
203 public->destroy(public);
205 /* check issuerNameHash, if available */
206 else if (response
->issuerNameHash
.ptr
)
208 hasher
= lib
->crypto
->create_hasher(lib
->crypto
,
209 hasher_algorithm_from_oid(response
->hashAlgorithm
));
214 id
= issuercert
->get_subject(issuercert
);
215 hasher
->allocate_hash(hasher
, id
->get_encoding(id
), &hash
);
216 hasher
->destroy(hasher
);
217 if (!chunk_equals(hash
, response
->issuerNameHash
))
227 status
= response
->status
;
228 *revocation_time
= response
->revocationTime
;
229 *revocation_reason
= response
->revocationReason
;
230 *this_update
= response
->thisUpdate
;
231 *next_update
= response
->nextUpdate
;
235 enumerator
->destroy(enumerator
);
240 * Implementation of ocsp_response_t.create_cert_enumerator.
242 static enumerator_t
* create_cert_enumerator(private_x509_ocsp_response_t
*this)
244 return this->certs
->create_enumerator(this->certs
);
248 * ASN.1 definition of singleResponse
250 static const asn1Object_t singleResponseObjects
[] = {
251 { 0, "singleResponse", ASN1_SEQUENCE
, ASN1_BODY
}, /* 0 */
252 { 1, "certID", ASN1_SEQUENCE
, ASN1_NONE
}, /* 1 */
253 { 2, "algorithm", ASN1_EOC
, ASN1_RAW
}, /* 2 */
254 { 2, "issuerNameHash", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 3 */
255 { 2, "issuerKeyHash", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 4 */
256 { 2, "serialNumber", ASN1_INTEGER
, ASN1_BODY
}, /* 5 */
257 { 1, "certStatusGood", ASN1_CONTEXT_S_0
, ASN1_OPT
}, /* 6 */
258 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 7 */
259 { 1, "certStatusRevoked", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 8 */
260 { 2, "revocationTime", ASN1_GENERALIZEDTIME
, ASN1_BODY
}, /* 9 */
261 { 2, "revocationReason", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 10 */
262 { 3, "crlReason", ASN1_ENUMERATED
, ASN1_BODY
}, /* 11 */
263 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 12 */
264 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 13 */
265 { 1, "certStatusUnknown", ASN1_CONTEXT_S_2
, ASN1_OPT
}, /* 14 */
266 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 15 */
267 { 1, "thisUpdate", ASN1_GENERALIZEDTIME
, ASN1_BODY
}, /* 16 */
268 { 1, "nextUpdateContext", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 17 */
269 { 2, "nextUpdate", ASN1_GENERALIZEDTIME
, ASN1_BODY
}, /* 18 */
270 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 19 */
271 { 1, "singleExtensionsContext", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 20 */
272 { 2, "singleExtensions", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 21 */
273 { 3, "extension", ASN1_SEQUENCE
, ASN1_NONE
}, /* 22 */
274 { 4, "extnID", ASN1_OID
, ASN1_BODY
}, /* 23 */
275 { 4, "critical", ASN1_BOOLEAN
, ASN1_BODY
|
277 { 4, "extnValue", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 25 */
278 { 2, "end loop", ASN1_EOC
, ASN1_END
}, /* 26 */
279 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 27 */
280 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
282 #define SINGLE_RESPONSE_ALGORITHM 2
283 #define SINGLE_RESPONSE_ISSUER_NAME_HASH 3
284 #define SINGLE_RESPONSE_ISSUER_KEY_HASH 4
285 #define SINGLE_RESPONSE_SERIAL_NUMBER 5
286 #define SINGLE_RESPONSE_CERT_STATUS_GOOD 6
287 #define SINGLE_RESPONSE_CERT_STATUS_REVOKED 8
288 #define SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME 9
289 #define SINGLE_RESPONSE_CERT_STATUS_CRL_REASON 11
290 #define SINGLE_RESPONSE_CERT_STATUS_UNKNOWN 14
291 #define SINGLE_RESPONSE_THIS_UPDATE 16
292 #define SINGLE_RESPONSE_NEXT_UPDATE 18
293 #define SINGLE_RESPONSE_EXT_ID 23
294 #define SINGLE_RESPONSE_CRITICAL 24
295 #define SINGLE_RESPONSE_EXT_VALUE 25
298 * Parse a single OCSP response
300 static bool parse_singleResponse(private_x509_ocsp_response_t
*this,
301 chunk_t blob
, int level0
)
303 asn1_parser_t
*parser
;
306 bool success
= FALSE
;
308 single_response_t
*response
;
310 response
= malloc_thing(single_response_t
);
311 response
->hashAlgorithm
= OID_UNKNOWN
;
312 response
->issuerNameHash
= chunk_empty
;
313 response
->issuerKeyHash
= chunk_empty
;
314 response
->serialNumber
= chunk_empty
;
315 response
->status
= VALIDATION_FAILED
;
316 response
->revocationTime
= 0;
317 response
->revocationReason
= CRL_REASON_UNSPECIFIED
;
318 response
->thisUpdate
= UNDEFINED_TIME
;
319 /* if nextUpdate is missing, we give it a short lifetime */
320 response
->nextUpdate
= this->producedAt
+ OCSP_DEFAULT_LIFETIME
;
322 parser
= asn1_parser_create(singleResponseObjects
, blob
);
323 parser
->set_top_level(parser
, level0
);
325 while (parser
->iterate(parser
, &objectID
, &object
))
329 case SINGLE_RESPONSE_ALGORITHM
:
330 response
->hashAlgorithm
= asn1_parse_algorithmIdentifier(object
,
331 parser
->get_level(parser
)+1, NULL
);
333 case SINGLE_RESPONSE_ISSUER_NAME_HASH
:
334 response
->issuerNameHash
= object
;
336 case SINGLE_RESPONSE_ISSUER_KEY_HASH
:
337 response
->issuerKeyHash
= object
;
339 case SINGLE_RESPONSE_SERIAL_NUMBER
:
340 response
->serialNumber
= object
;
342 case SINGLE_RESPONSE_CERT_STATUS_GOOD
:
343 response
->status
= VALIDATION_GOOD
;
345 case SINGLE_RESPONSE_CERT_STATUS_REVOKED
:
346 response
->status
= VALIDATION_REVOKED
;
348 case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME
:
349 response
->revocationTime
= asn1_to_time(&object
, ASN1_GENERALIZEDTIME
);
351 case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON
:
354 response
->revocationReason
= *object
.ptr
;
357 case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN
:
358 response
->status
= VALIDATION_FAILED
;
360 case SINGLE_RESPONSE_THIS_UPDATE
:
361 response
->thisUpdate
= asn1_to_time(&object
, ASN1_GENERALIZEDTIME
);
363 case SINGLE_RESPONSE_NEXT_UPDATE
:
364 response
->nextUpdate
= asn1_to_time(&object
, ASN1_GENERALIZEDTIME
);
365 if (response
->nextUpdate
> this->usableUntil
)
367 this->usableUntil
= response
->nextUpdate
;
372 success
= parser
->success(parser
);
373 parser
->destroy(parser
);
376 if (this->usableUntil
== UNDEFINED_TIME
)
378 this->usableUntil
= this->producedAt
+ OCSP_DEFAULT_LIFETIME
;
380 this->responses
->insert_last(this->responses
, response
);
386 * ASN.1 definition of responses
388 static const asn1Object_t responsesObjects
[] = {
389 { 0, "responses", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 0 */
390 { 1, "singleResponse", ASN1_EOC
, ASN1_RAW
}, /* 1 */
391 { 0, "end loop", ASN1_EOC
, ASN1_END
}, /* 2 */
392 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
394 #define RESPONSES_SINGLE_RESPONSE 1
397 * Parse all responses
399 static bool parse_responses(private_x509_ocsp_response_t
*this,
400 chunk_t blob
, int level0
)
402 asn1_parser_t
*parser
;
405 bool success
= FALSE
;
407 parser
= asn1_parser_create(responsesObjects
, blob
);
408 parser
->set_top_level(parser
, level0
);
410 while (parser
->iterate(parser
, &objectID
, &object
))
414 case RESPONSES_SINGLE_RESPONSE
:
415 if (!parse_singleResponse(this, object
,
416 parser
->get_level(parser
)+1))
425 success
= parser
->success(parser
);
428 parser
->destroy(parser
);
433 * ASN.1 definition of basicResponse
435 static const asn1Object_t basicResponseObjects
[] = {
436 { 0, "BasicOCSPResponse", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
437 { 1, "tbsResponseData", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 1 */
438 { 2, "versionContext", ASN1_CONTEXT_C_0
, ASN1_NONE
|
440 { 3, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 3 */
441 { 2, "responderIdContext", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 4 */
442 { 3, "responderIdByName", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 5 */
443 { 2, "end choice", ASN1_EOC
, ASN1_END
}, /* 6 */
444 { 2, "responderIdContext", ASN1_CONTEXT_C_2
, ASN1_OPT
}, /* 7 */
445 { 3, "responderIdByKey", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 8 */
446 { 2, "end choice", ASN1_EOC
, ASN1_END
}, /* 9 */
447 { 2, "producedAt", ASN1_GENERALIZEDTIME
, ASN1_BODY
}, /* 10 */
448 { 2, "responses", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 11 */
449 { 2, "responseExtensionsContext", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 12 */
450 { 3, "responseExtensions", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 13 */
451 { 4, "extension", ASN1_SEQUENCE
, ASN1_NONE
}, /* 14 */
452 { 5, "extnID", ASN1_OID
, ASN1_BODY
}, /* 15 */
453 { 5, "critical", ASN1_BOOLEAN
, ASN1_BODY
|
455 { 5, "extnValue", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 17 */
456 { 4, "end loop", ASN1_EOC
, ASN1_END
}, /* 18 */
457 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 19 */
458 { 1, "signatureAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 20 */
459 { 1, "signature", ASN1_BIT_STRING
, ASN1_BODY
}, /* 21 */
460 { 1, "certsContext", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 22 */
461 { 2, "certs", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 23 */
462 { 3, "certificate", ASN1_SEQUENCE
, ASN1_RAW
}, /* 24 */
463 { 2, "end loop", ASN1_EOC
, ASN1_END
}, /* 25 */
464 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 26 */
465 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
467 #define BASIC_RESPONSE_TBS_DATA 1
468 #define BASIC_RESPONSE_VERSION 3
469 #define BASIC_RESPONSE_ID_BY_NAME 5
470 #define BASIC_RESPONSE_ID_BY_KEY 8
471 #define BASIC_RESPONSE_PRODUCED_AT 10
472 #define BASIC_RESPONSE_RESPONSES 11
473 #define BASIC_RESPONSE_EXT_ID 15
474 #define BASIC_RESPONSE_CRITICAL 16
475 #define BASIC_RESPONSE_EXT_VALUE 17
476 #define BASIC_RESPONSE_ALGORITHM 20
477 #define BASIC_RESPONSE_SIGNATURE 21
478 #define BASIC_RESPONSE_CERTIFICATE 24
481 * Parse a basicOCSPResponse
483 static bool parse_basicOCSPResponse(private_x509_ocsp_response_t
*this,
484 chunk_t blob
, int level0
)
486 asn1_parser_t
*parser
;
488 chunk_t responses
= chunk_empty
;
490 int extn_oid
= OID_UNKNOWN
;
491 u_int responses_level
= level0
;
493 bool success
= FALSE
;
496 parser
= asn1_parser_create(basicResponseObjects
, blob
);
497 parser
->set_top_level(parser
, level0
);
499 while (parser
->iterate(parser
, &objectID
, &object
))
503 case BASIC_RESPONSE_TBS_DATA
:
504 this->tbsResponseData
= object
;
506 case BASIC_RESPONSE_VERSION
:
508 u_int version
= (object
.len
)? (1 + (u_int
)*object
.ptr
) : 1;
510 if (version
!= OCSP_BASIC_RESPONSE_VERSION
)
512 DBG1(DBG_LIB
, " ocsp ResponseData version %d not "
513 "supported", version
);
518 case BASIC_RESPONSE_ID_BY_NAME
:
519 this->responderId
= identification_create_from_encoding(
520 ID_DER_ASN1_DN
, object
);
521 DBG2(DBG_LIB
, " '%Y'", this->responderId
);
523 case BASIC_RESPONSE_ID_BY_KEY
:
524 this->responderId
= identification_create_from_encoding(
526 DBG2(DBG_LIB
, " '%Y'", this->responderId
);
528 case BASIC_RESPONSE_PRODUCED_AT
:
529 this->producedAt
= asn1_to_time(&object
, ASN1_GENERALIZEDTIME
);
531 case BASIC_RESPONSE_RESPONSES
:
533 responses_level
= parser
->get_level(parser
)+1;
535 case BASIC_RESPONSE_EXT_ID
:
536 extn_oid
= asn1_known_oid(object
);
538 case BASIC_RESPONSE_CRITICAL
:
539 critical
= object
.len
&& *object
.ptr
;
540 DBG2(DBG_LIB
, " %s", critical
? "TRUE" : "FALSE");
542 case BASIC_RESPONSE_EXT_VALUE
:
543 if (extn_oid
== OID_NONCE
)
545 this->nonce
= object
;
548 case BASIC_RESPONSE_ALGORITHM
:
549 this->signatureAlgorithm
= asn1_parse_algorithmIdentifier(object
,
550 parser
->get_level(parser
)+1, NULL
);
552 case BASIC_RESPONSE_SIGNATURE
:
553 this->signature
= object
;
555 case BASIC_RESPONSE_CERTIFICATE
:
557 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
,CERT_X509
,
558 BUILD_BLOB_ASN1_DER
, object
,
562 this->certs
->insert_last(this->certs
, cert
);
568 success
= parser
->success(parser
);
571 parser
->destroy(parser
);
574 if (!this->responderId
)
576 this->responderId
= identification_create_from_encoding(ID_ANY
,
579 success
= parse_responses(this, responses
, responses_level
);
585 * ASN.1 definition of ocspResponse
587 static const asn1Object_t ocspResponseObjects
[] = {
588 { 0, "OCSPResponse", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
589 { 1, "responseStatus", ASN1_ENUMERATED
, ASN1_BODY
}, /* 1 */
590 { 1, "responseBytesContext", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 2 */
591 { 2, "responseBytes", ASN1_SEQUENCE
, ASN1_NONE
}, /* 3 */
592 { 3, "responseType", ASN1_OID
, ASN1_BODY
}, /* 4 */
593 { 3, "response", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 5 */
594 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 6 */
595 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
597 #define OCSP_RESPONSE_STATUS 1
598 #define OCSP_RESPONSE_TYPE 4
599 #define OCSP_RESPONSE 5
602 * Parse OCSPResponse object
604 static bool parse_OCSPResponse(private_x509_ocsp_response_t
*this)
606 asn1_parser_t
*parser
;
609 int responseType
= OID_UNKNOWN
;
610 bool success
= FALSE
;
611 ocsp_status_t status
;
613 parser
= asn1_parser_create(ocspResponseObjects
, this->encoding
);
615 while (parser
->iterate(parser
, &objectID
, &object
))
619 case OCSP_RESPONSE_STATUS
:
620 status
= (ocsp_status_t
)*object
.ptr
;
623 case OCSP_SUCCESSFUL
:
626 DBG1(DBG_LIB
, " ocsp response status: %N",
627 ocsp_status_names
, status
);
631 case OCSP_RESPONSE_TYPE
:
632 responseType
= asn1_known_oid(object
);
635 switch (responseType
)
638 success
= parse_basicOCSPResponse(this, object
,
639 parser
->get_level(parser
)+1);
642 DBG1(DBG_LIB
, " ocsp response type %#B not supported",
649 success
&= parser
->success(parser
);
652 parser
->destroy(parser
);
657 * Implementation of certificate_t.get_type
659 static certificate_type_t
get_type(private_x509_ocsp_response_t
*this)
661 return CERT_X509_OCSP_RESPONSE
;
665 * Implementation of certificate_t.get_issuer
667 static identification_t
* get_issuer(private_x509_ocsp_response_t
*this)
669 return this->responderId
;
673 * Implementation of certificate_t.has_subject.
675 static id_match_t
has_issuer(private_x509_ocsp_response_t
*this,
676 identification_t
*issuer
)
678 return this->responderId
->matches(this->responderId
, issuer
);
682 * Implementation of certificate_t.issued_by
684 static bool issued_by(private_x509_ocsp_response_t
*this, certificate_t
*issuer
)
687 signature_scheme_t scheme
;
689 x509_t
*x509
= (x509_t
*)issuer
;
691 if (issuer
->get_type(issuer
) != CERT_X509
)
695 if (this->responderId
->get_type(this->responderId
) == ID_KEY_ID
)
699 key
= issuer
->get_public_key(issuer
);
701 !key
->get_fingerprint(key
, KEYID_PUBKEY_SHA1
, &fingerprint
) ||
702 !chunk_equals(fingerprint
,
703 this->responderId
->get_encoding(this->responderId
)))
712 if (!this->responderId
->equals(this->responderId
,
713 issuer
->get_subject(issuer
)))
718 if (!(x509
->get_flags(x509
) & X509_OCSP_SIGNER
) &&
719 !(x509
->get_flags(x509
) & X509_CA
))
724 /* get the public key of the issuer */
725 key
= issuer
->get_public_key(issuer
);
727 /* determine signature scheme */
728 scheme
= signature_scheme_from_oid(this->signatureAlgorithm
);
730 if (scheme
== SIGN_UNKNOWN
|| key
== NULL
)
734 valid
= key
->verify(key
, scheme
, this->tbsResponseData
, this->signature
);
740 * Implementation of certificate_t.get_public_key
742 static public_key_t
* get_public_key(private_x509_ocsp_response_t
*this)
748 * Implementation of certificate_t.get_validity.
750 static bool get_validity(private_x509_ocsp_response_t
*this, time_t *when
,
751 time_t *not_before
, time_t *not_after
)
753 time_t t
= when
? *when
: time(NULL
);
757 *not_before
= this->producedAt
;
761 *not_after
= this->usableUntil
;
763 return (t
< this->usableUntil
);
767 * Implementation of certificate_t.get_encoding.
769 static bool get_encoding(private_x509_ocsp_response_t
*this,
770 cred_encoding_type_t type
, chunk_t
*encoding
)
772 if (type
== CERT_ASN1_DER
)
774 *encoding
= chunk_clone(this->encoding
);
777 return lib
->encoding
->encode(lib
->encoding
, type
, NULL
, encoding
,
778 CRED_PART_X509_OCSP_RES_ASN1_DER
, this->encoding
, CRED_PART_END
);
782 * Implementation of certificate_t.equals.
784 static bool equals(private_x509_ocsp_response_t
*this, certificate_t
*other
)
789 if (this == (private_x509_ocsp_response_t
*)other
)
793 if (other
->get_type(other
) != CERT_X509_OCSP_RESPONSE
)
797 if (other
->equals
== (void*)equals
)
798 { /* skip allocation if we have the same implementation */
799 return chunk_equals(this->encoding
, ((private_x509_ocsp_response_t
*)other
)->encoding
);
801 if (!other
->get_encoding(other
, CERT_ASN1_DER
, &encoding
))
805 equal
= chunk_equals(this->encoding
, encoding
);
811 * Implementation of certificate_t.get_ref
813 static private_x509_ocsp_response_t
* get_ref(private_x509_ocsp_response_t
*this)
820 * Implements ocsp_t.destroy.
822 static void destroy(private_x509_ocsp_response_t
*this)
824 if (ref_put(&this->ref
))
826 this->certs
->destroy_offset(this->certs
, offsetof(certificate_t
, destroy
));
827 this->responses
->destroy_function(this->responses
, free
);
828 DESTROY_IF(this->responderId
);
829 free(this->encoding
.ptr
);
835 * load an OCSP response
837 static x509_ocsp_response_t
*load(chunk_t blob
)
839 private_x509_ocsp_response_t
*this;
841 this = malloc_thing(private_x509_ocsp_response_t
);
843 this->public.interface
.certificate
.get_type
= (certificate_type_t (*)(certificate_t
*this))get_type
;
844 this->public.interface
.certificate
.get_subject
= (identification_t
* (*)(certificate_t
*this))get_issuer
;
845 this->public.interface
.certificate
.get_issuer
= (identification_t
* (*)(certificate_t
*this))get_issuer
;
846 this->public.interface
.certificate
.has_subject
= (id_match_t(*)(certificate_t
*, identification_t
*subject
))has_issuer
;
847 this->public.interface
.certificate
.has_issuer
= (id_match_t(*)(certificate_t
*, identification_t
*issuer
))has_issuer
;
848 this->public.interface
.certificate
.issued_by
= (bool (*)(certificate_t
*this, certificate_t
*issuer
))issued_by
;
849 this->public.interface
.certificate
.get_public_key
= (public_key_t
* (*)(certificate_t
*this))get_public_key
;
850 this->public.interface
.certificate
.get_validity
= (bool(*)(certificate_t
*, time_t *when
, time_t *, time_t*))get_validity
;
851 this->public.interface
.certificate
.get_encoding
= (bool(*)(certificate_t
*,cred_encoding_type_t
,chunk_t
*))get_encoding
;
852 this->public.interface
.certificate
.equals
= (bool(*)(certificate_t
*, certificate_t
*other
))equals
;
853 this->public.interface
.certificate
.get_ref
= (certificate_t
* (*)(certificate_t
*this))get_ref
;
854 this->public.interface
.certificate
.destroy
= (void (*)(certificate_t
*this))destroy
;
855 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
;
856 this->public.interface
.create_cert_enumerator
= (enumerator_t
*(*)(ocsp_response_t
*))create_cert_enumerator
;
859 this->encoding
= chunk_clone(blob
);
860 this->tbsResponseData
= chunk_empty
;
861 this->responderId
= NULL
;
862 this->producedAt
= UNDEFINED_TIME
;
863 this->usableUntil
= UNDEFINED_TIME
;
864 this->responses
= linked_list_create();
865 this->nonce
= chunk_empty
;
866 this->signatureAlgorithm
= OID_UNKNOWN
;
867 this->signature
= chunk_empty
;
868 this->certs
= linked_list_create();
870 if (!parse_OCSPResponse(this))
875 return &this->public;
881 x509_ocsp_response_t
*x509_ocsp_response_load(certificate_type_t type
,
884 chunk_t blob
= chunk_empty
;
888 switch (va_arg(args
, builder_part_t
))
890 case BUILD_BLOB_ASN1_DER
:
891 blob
= va_arg(args
, chunk_t
);