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
151 METHOD(ocsp_response_t
, get_status
, cert_validation_t
,
152 private_x509_ocsp_response_t
*this, x509_t
*subject
, x509_t
*issuer
,
153 time_t *revocation_time
, crl_reason_t
*revocation_reason
,
154 time_t *this_update
, time_t *next_update
)
156 enumerator_t
*enumerator
;
157 single_response_t
*response
;
158 cert_validation_t status
= VALIDATION_FAILED
;
159 certificate_t
*issuercert
= &issuer
->interface
;
161 enumerator
= this->responses
->create_enumerator(this->responses
);
162 while (enumerator
->enumerate(enumerator
, &response
))
165 identification_t
*id
;
166 cred_encoding_type_t type
;
167 chunk_t hash
, fingerprint
;
169 /* check serial first, is cheaper */
170 if (!chunk_equals(subject
->get_serial(subject
), response
->serialNumber
))
174 /* check issuerKeyHash if available */
175 if (response
->issuerKeyHash
.ptr
)
177 public_key_t
*public;
179 public = issuercert
->get_public_key(issuercert
);
184 switch (response
->hashAlgorithm
)
187 type
= KEYID_PUBKEY_SHA1
;
190 public->destroy(public);
193 if (!public->get_fingerprint(public, type
, &fingerprint
) ||
194 !chunk_equals(response
->issuerKeyHash
, fingerprint
))
196 public->destroy(public);
199 public->destroy(public);
201 /* check issuerNameHash, if available */
202 else if (response
->issuerNameHash
.ptr
)
204 id
= issuercert
->get_subject(issuercert
);
205 hasher
= lib
->crypto
->create_hasher(lib
->crypto
,
206 hasher_algorithm_from_oid(response
->hashAlgorithm
));
208 !hasher
->allocate_hash(hasher
, id
->get_encoding(id
), &hash
))
213 hasher
->destroy(hasher
);
214 if (!chunk_equals(hash
, response
->issuerNameHash
))
226 status
= response
->status
;
227 *revocation_time
= response
->revocationTime
;
228 *revocation_reason
= response
->revocationReason
;
229 *this_update
= response
->thisUpdate
;
230 *next_update
= response
->nextUpdate
;
234 enumerator
->destroy(enumerator
);
238 METHOD(ocsp_response_t
, create_cert_enumerator
, enumerator_t
*,
239 private_x509_ocsp_response_t
*this)
241 return this->certs
->create_enumerator(this->certs
);
245 * ASN.1 definition of singleResponse
247 static const asn1Object_t singleResponseObjects
[] = {
248 { 0, "singleResponse", ASN1_SEQUENCE
, ASN1_BODY
}, /* 0 */
249 { 1, "certID", ASN1_SEQUENCE
, ASN1_NONE
}, /* 1 */
250 { 2, "algorithm", ASN1_EOC
, ASN1_RAW
}, /* 2 */
251 { 2, "issuerNameHash", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 3 */
252 { 2, "issuerKeyHash", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 4 */
253 { 2, "serialNumber", ASN1_INTEGER
, ASN1_BODY
}, /* 5 */
254 { 1, "certStatusGood", ASN1_CONTEXT_S_0
, ASN1_OPT
}, /* 6 */
255 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 7 */
256 { 1, "certStatusRevoked", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 8 */
257 { 2, "revocationTime", ASN1_GENERALIZEDTIME
, ASN1_BODY
}, /* 9 */
258 { 2, "revocationReason", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 10 */
259 { 3, "crlReason", ASN1_ENUMERATED
, ASN1_BODY
}, /* 11 */
260 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 12 */
261 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 13 */
262 { 1, "certStatusUnknown", ASN1_CONTEXT_S_2
, ASN1_OPT
}, /* 14 */
263 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 15 */
264 { 1, "thisUpdate", ASN1_GENERALIZEDTIME
, ASN1_BODY
}, /* 16 */
265 { 1, "nextUpdateContext", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 17 */
266 { 2, "nextUpdate", ASN1_GENERALIZEDTIME
, ASN1_BODY
}, /* 18 */
267 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 19 */
268 { 1, "singleExtensionsContext", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 20 */
269 { 2, "singleExtensions", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 21 */
270 { 3, "extension", ASN1_SEQUENCE
, ASN1_NONE
}, /* 22 */
271 { 4, "extnID", ASN1_OID
, ASN1_BODY
}, /* 23 */
272 { 4, "critical", ASN1_BOOLEAN
, ASN1_BODY
|
274 { 4, "extnValue", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 25 */
275 { 2, "end loop", ASN1_EOC
, ASN1_END
}, /* 26 */
276 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 27 */
277 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
279 #define SINGLE_RESPONSE_ALGORITHM 2
280 #define SINGLE_RESPONSE_ISSUER_NAME_HASH 3
281 #define SINGLE_RESPONSE_ISSUER_KEY_HASH 4
282 #define SINGLE_RESPONSE_SERIAL_NUMBER 5
283 #define SINGLE_RESPONSE_CERT_STATUS_GOOD 6
284 #define SINGLE_RESPONSE_CERT_STATUS_REVOKED 8
285 #define SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME 9
286 #define SINGLE_RESPONSE_CERT_STATUS_CRL_REASON 11
287 #define SINGLE_RESPONSE_CERT_STATUS_UNKNOWN 14
288 #define SINGLE_RESPONSE_THIS_UPDATE 16
289 #define SINGLE_RESPONSE_NEXT_UPDATE 18
290 #define SINGLE_RESPONSE_EXT_ID 23
291 #define SINGLE_RESPONSE_CRITICAL 24
292 #define SINGLE_RESPONSE_EXT_VALUE 25
295 * Parse a single OCSP response
297 static bool parse_singleResponse(private_x509_ocsp_response_t
*this,
298 chunk_t blob
, int level0
)
300 asn1_parser_t
*parser
;
303 bool success
= FALSE
;
305 single_response_t
*response
;
307 response
= malloc_thing(single_response_t
);
308 response
->hashAlgorithm
= OID_UNKNOWN
;
309 response
->issuerNameHash
= chunk_empty
;
310 response
->issuerKeyHash
= chunk_empty
;
311 response
->serialNumber
= chunk_empty
;
312 response
->status
= VALIDATION_FAILED
;
313 response
->revocationTime
= 0;
314 response
->revocationReason
= CRL_REASON_UNSPECIFIED
;
315 response
->thisUpdate
= UNDEFINED_TIME
;
316 /* if nextUpdate is missing, we give it a short lifetime */
317 response
->nextUpdate
= this->producedAt
+ OCSP_DEFAULT_LIFETIME
;
319 parser
= asn1_parser_create(singleResponseObjects
, blob
);
320 parser
->set_top_level(parser
, level0
);
322 while (parser
->iterate(parser
, &objectID
, &object
))
326 case SINGLE_RESPONSE_ALGORITHM
:
327 response
->hashAlgorithm
= asn1_parse_algorithmIdentifier(object
,
328 parser
->get_level(parser
)+1, NULL
);
330 case SINGLE_RESPONSE_ISSUER_NAME_HASH
:
331 response
->issuerNameHash
= object
;
333 case SINGLE_RESPONSE_ISSUER_KEY_HASH
:
334 response
->issuerKeyHash
= object
;
336 case SINGLE_RESPONSE_SERIAL_NUMBER
:
337 response
->serialNumber
= object
;
339 case SINGLE_RESPONSE_CERT_STATUS_GOOD
:
340 response
->status
= VALIDATION_GOOD
;
342 case SINGLE_RESPONSE_CERT_STATUS_REVOKED
:
343 response
->status
= VALIDATION_REVOKED
;
345 case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME
:
346 response
->revocationTime
= asn1_to_time(&object
, ASN1_GENERALIZEDTIME
);
348 case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON
:
351 response
->revocationReason
= *object
.ptr
;
354 case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN
:
355 response
->status
= VALIDATION_FAILED
;
357 case SINGLE_RESPONSE_THIS_UPDATE
:
358 response
->thisUpdate
= asn1_to_time(&object
, ASN1_GENERALIZEDTIME
);
360 case SINGLE_RESPONSE_NEXT_UPDATE
:
361 response
->nextUpdate
= asn1_to_time(&object
, ASN1_GENERALIZEDTIME
);
362 if (response
->nextUpdate
> this->usableUntil
)
364 this->usableUntil
= response
->nextUpdate
;
369 success
= parser
->success(parser
);
370 parser
->destroy(parser
);
373 if (this->usableUntil
== UNDEFINED_TIME
)
375 this->usableUntil
= this->producedAt
+ OCSP_DEFAULT_LIFETIME
;
377 this->responses
->insert_last(this->responses
, response
);
387 * ASN.1 definition of responses
389 static const asn1Object_t responsesObjects
[] = {
390 { 0, "responses", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 0 */
391 { 1, "singleResponse", ASN1_EOC
, ASN1_RAW
}, /* 1 */
392 { 0, "end loop", ASN1_EOC
, ASN1_END
}, /* 2 */
393 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
395 #define RESPONSES_SINGLE_RESPONSE 1
398 * Parse all responses
400 static bool parse_responses(private_x509_ocsp_response_t
*this,
401 chunk_t blob
, int level0
)
403 asn1_parser_t
*parser
;
406 bool success
= FALSE
;
408 parser
= asn1_parser_create(responsesObjects
, blob
);
409 parser
->set_top_level(parser
, level0
);
411 while (parser
->iterate(parser
, &objectID
, &object
))
415 case RESPONSES_SINGLE_RESPONSE
:
416 if (!parse_singleResponse(this, object
,
417 parser
->get_level(parser
)+1))
426 success
= parser
->success(parser
);
429 parser
->destroy(parser
);
434 * ASN.1 definition of basicResponse
436 static const asn1Object_t basicResponseObjects
[] = {
437 { 0, "BasicOCSPResponse", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
438 { 1, "tbsResponseData", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 1 */
439 { 2, "versionContext", ASN1_CONTEXT_C_0
, ASN1_NONE
|
441 { 3, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 3 */
442 { 2, "responderIdContext", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 4 */
443 { 3, "responderIdByName", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 5 */
444 { 2, "end choice", ASN1_EOC
, ASN1_END
}, /* 6 */
445 { 2, "responderIdContext", ASN1_CONTEXT_C_2
, ASN1_OPT
}, /* 7 */
446 { 3, "responderIdByKey", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 8 */
447 { 2, "end choice", ASN1_EOC
, ASN1_END
}, /* 9 */
448 { 2, "producedAt", ASN1_GENERALIZEDTIME
, ASN1_BODY
}, /* 10 */
449 { 2, "responses", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 11 */
450 { 2, "responseExtensionsContext", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 12 */
451 { 3, "responseExtensions", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 13 */
452 { 4, "extension", ASN1_SEQUENCE
, ASN1_NONE
}, /* 14 */
453 { 5, "extnID", ASN1_OID
, ASN1_BODY
}, /* 15 */
454 { 5, "critical", ASN1_BOOLEAN
, ASN1_BODY
|
456 { 5, "extnValue", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 17 */
457 { 3, "end loop", ASN1_EOC
, ASN1_END
}, /* 18 */
458 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 19 */
459 { 1, "signatureAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 20 */
460 { 1, "signature", ASN1_BIT_STRING
, ASN1_BODY
}, /* 21 */
461 { 1, "certsContext", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 22 */
462 { 2, "certs", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 23 */
463 { 3, "certificate", ASN1_SEQUENCE
, ASN1_RAW
}, /* 24 */
464 { 2, "end loop", ASN1_EOC
, ASN1_END
}, /* 25 */
465 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 26 */
466 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
468 #define BASIC_RESPONSE_TBS_DATA 1
469 #define BASIC_RESPONSE_VERSION 3
470 #define BASIC_RESPONSE_ID_BY_NAME 5
471 #define BASIC_RESPONSE_ID_BY_KEY 8
472 #define BASIC_RESPONSE_PRODUCED_AT 10
473 #define BASIC_RESPONSE_RESPONSES 11
474 #define BASIC_RESPONSE_EXT_ID 15
475 #define BASIC_RESPONSE_CRITICAL 16
476 #define BASIC_RESPONSE_EXT_VALUE 17
477 #define BASIC_RESPONSE_ALGORITHM 20
478 #define BASIC_RESPONSE_SIGNATURE 21
479 #define BASIC_RESPONSE_CERTIFICATE 24
482 * Parse a basicOCSPResponse
484 static bool parse_basicOCSPResponse(private_x509_ocsp_response_t
*this,
485 chunk_t blob
, int level0
)
487 asn1_parser_t
*parser
;
489 chunk_t responses
= chunk_empty
;
491 int extn_oid
= OID_UNKNOWN
;
492 u_int responses_level
= level0
;
494 bool success
= FALSE
;
497 parser
= asn1_parser_create(basicResponseObjects
, blob
);
498 parser
->set_top_level(parser
, level0
);
500 while (parser
->iterate(parser
, &objectID
, &object
))
504 case BASIC_RESPONSE_TBS_DATA
:
505 this->tbsResponseData
= object
;
507 case BASIC_RESPONSE_VERSION
:
509 u_int version
= (object
.len
)? (1 + (u_int
)*object
.ptr
) : 1;
511 if (version
!= OCSP_BASIC_RESPONSE_VERSION
)
513 DBG1(DBG_ASN
, " ocsp ResponseData version %d not "
514 "supported", version
);
519 case BASIC_RESPONSE_ID_BY_NAME
:
520 this->responderId
= identification_create_from_encoding(
521 ID_DER_ASN1_DN
, object
);
522 DBG2(DBG_ASN
, " '%Y'", this->responderId
);
524 case BASIC_RESPONSE_ID_BY_KEY
:
525 this->responderId
= identification_create_from_encoding(
527 DBG2(DBG_ASN
, " '%Y'", this->responderId
);
529 case BASIC_RESPONSE_PRODUCED_AT
:
530 this->producedAt
= asn1_to_time(&object
, ASN1_GENERALIZEDTIME
);
532 case BASIC_RESPONSE_RESPONSES
:
534 responses_level
= parser
->get_level(parser
)+1;
536 case BASIC_RESPONSE_EXT_ID
:
537 extn_oid
= asn1_known_oid(object
);
539 case BASIC_RESPONSE_CRITICAL
:
540 critical
= object
.len
&& *object
.ptr
;
541 DBG2(DBG_ASN
, " %s", critical
? "TRUE" : "FALSE");
543 case BASIC_RESPONSE_EXT_VALUE
:
544 if (extn_oid
== OID_NONCE
)
546 this->nonce
= object
;
549 case BASIC_RESPONSE_ALGORITHM
:
550 this->signatureAlgorithm
= asn1_parse_algorithmIdentifier(object
,
551 parser
->get_level(parser
)+1, NULL
);
553 case BASIC_RESPONSE_SIGNATURE
:
554 this->signature
= object
;
556 case BASIC_RESPONSE_CERTIFICATE
:
558 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
,CERT_X509
,
559 BUILD_BLOB_ASN1_DER
, object
,
563 this->certs
->insert_last(this->certs
, cert
);
569 success
= parser
->success(parser
);
572 parser
->destroy(parser
);
575 if (!this->responderId
)
577 this->responderId
= identification_create_from_encoding(ID_ANY
,
580 success
= parse_responses(this, responses
, responses_level
);
586 * ASN.1 definition of ocspResponse
588 static const asn1Object_t ocspResponseObjects
[] = {
589 { 0, "OCSPResponse", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
590 { 1, "responseStatus", ASN1_ENUMERATED
, ASN1_BODY
}, /* 1 */
591 { 1, "responseBytesContext", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 2 */
592 { 2, "responseBytes", ASN1_SEQUENCE
, ASN1_NONE
}, /* 3 */
593 { 3, "responseType", ASN1_OID
, ASN1_BODY
}, /* 4 */
594 { 3, "response", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 5 */
595 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 6 */
596 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
598 #define OCSP_RESPONSE_STATUS 1
599 #define OCSP_RESPONSE_TYPE 4
600 #define OCSP_RESPONSE 5
603 * Parse OCSPResponse object
605 static bool parse_OCSPResponse(private_x509_ocsp_response_t
*this)
607 asn1_parser_t
*parser
;
610 int responseType
= OID_UNKNOWN
;
611 bool success
= FALSE
;
612 ocsp_status_t status
;
614 parser
= asn1_parser_create(ocspResponseObjects
, this->encoding
);
616 while (parser
->iterate(parser
, &objectID
, &object
))
620 case OCSP_RESPONSE_STATUS
:
621 status
= (ocsp_status_t
)*object
.ptr
;
624 case OCSP_SUCCESSFUL
:
627 DBG1(DBG_LIB
, " ocsp response status: %N",
628 ocsp_status_names
, status
);
632 case OCSP_RESPONSE_TYPE
:
633 responseType
= asn1_known_oid(object
);
636 switch (responseType
)
639 success
= parse_basicOCSPResponse(this, object
,
640 parser
->get_level(parser
)+1);
643 DBG1(DBG_LIB
, " ocsp response type %#B not supported",
650 success
&= parser
->success(parser
);
653 parser
->destroy(parser
);
657 METHOD(certificate_t
, get_type
, certificate_type_t
,
658 private_x509_ocsp_response_t
*this)
660 return CERT_X509_OCSP_RESPONSE
;
663 METHOD(certificate_t
, get_issuer
, identification_t
*,
664 private_x509_ocsp_response_t
*this)
666 return this->responderId
;
669 METHOD(certificate_t
, has_issuer
, id_match_t
,
670 private_x509_ocsp_response_t
*this, identification_t
*issuer
)
672 return this->responderId
->matches(this->responderId
, issuer
);
675 METHOD(certificate_t
, issued_by
, bool,
676 private_x509_ocsp_response_t
*this, certificate_t
*issuer
,
677 signature_scheme_t
*schemep
)
680 signature_scheme_t scheme
;
682 x509_t
*x509
= (x509_t
*)issuer
;
684 if (issuer
->get_type(issuer
) != CERT_X509
)
688 if (this->responderId
->get_type(this->responderId
) == ID_KEY_ID
)
692 key
= issuer
->get_public_key(issuer
);
694 !key
->get_fingerprint(key
, KEYID_PUBKEY_SHA1
, &fingerprint
) ||
695 !chunk_equals(fingerprint
,
696 this->responderId
->get_encoding(this->responderId
)))
705 if (!this->responderId
->equals(this->responderId
,
706 issuer
->get_subject(issuer
)))
711 if (!(x509
->get_flags(x509
) & X509_OCSP_SIGNER
) &&
712 !(x509
->get_flags(x509
) & X509_CA
))
717 /* get the public key of the issuer */
718 key
= issuer
->get_public_key(issuer
);
720 /* determine signature scheme */
721 scheme
= signature_scheme_from_oid(this->signatureAlgorithm
);
723 if (scheme
== SIGN_UNKNOWN
|| key
== NULL
)
727 valid
= key
->verify(key
, scheme
, this->tbsResponseData
, this->signature
);
729 if (valid
&& schemep
)
736 METHOD(certificate_t
, get_public_key
, public_key_t
*,
737 private_x509_ocsp_response_t
*this)
742 METHOD(certificate_t
, get_validity
, bool,
743 private_x509_ocsp_response_t
*this, time_t *when
,
744 time_t *not_before
, time_t *not_after
)
746 time_t t
= when
? *when
: time(NULL
);
750 *not_before
= this->producedAt
;
754 *not_after
= this->usableUntil
;
756 return (t
< this->usableUntil
);
759 METHOD(certificate_t
, get_encoding
, bool,
760 private_x509_ocsp_response_t
*this, cred_encoding_type_t type
,
763 if (type
== CERT_ASN1_DER
)
765 *encoding
= chunk_clone(this->encoding
);
768 return lib
->encoding
->encode(lib
->encoding
, type
, NULL
, encoding
,
769 CRED_PART_X509_OCSP_RES_ASN1_DER
, this->encoding
, CRED_PART_END
);
772 METHOD(certificate_t
, equals
, bool,
773 private_x509_ocsp_response_t
*this, certificate_t
*other
)
778 if (this == (private_x509_ocsp_response_t
*)other
)
782 if (other
->get_type(other
) != CERT_X509_OCSP_RESPONSE
)
786 if (other
->equals
== (void*)equals
)
787 { /* skip allocation if we have the same implementation */
788 return chunk_equals(this->encoding
, ((private_x509_ocsp_response_t
*)other
)->encoding
);
790 if (!other
->get_encoding(other
, CERT_ASN1_DER
, &encoding
))
794 equal
= chunk_equals(this->encoding
, encoding
);
799 METHOD(certificate_t
, get_ref
, certificate_t
*,
800 private_x509_ocsp_response_t
*this)
803 return &this->public.interface
.certificate
;
806 METHOD(certificate_t
, destroy
, void,
807 private_x509_ocsp_response_t
*this)
809 if (ref_put(&this->ref
))
811 this->certs
->destroy_offset(this->certs
, offsetof(certificate_t
, destroy
));
812 this->responses
->destroy_function(this->responses
, free
);
813 DESTROY_IF(this->responderId
);
814 free(this->encoding
.ptr
);
820 * load an OCSP response
822 static x509_ocsp_response_t
*load(chunk_t blob
)
824 private_x509_ocsp_response_t
*this;
830 .get_type
= _get_type
,
831 .get_subject
= _get_issuer
,
832 .get_issuer
= _get_issuer
,
833 .has_subject
= _has_issuer
,
834 .has_issuer
= _has_issuer
,
835 .issued_by
= _issued_by
,
836 .get_public_key
= _get_public_key
,
837 .get_validity
= _get_validity
,
838 .get_encoding
= _get_encoding
,
843 .get_status
= _get_status
,
844 .create_cert_enumerator
= _create_cert_enumerator
,
848 .encoding
= chunk_clone(blob
),
849 .producedAt
= UNDEFINED_TIME
,
850 .usableUntil
= UNDEFINED_TIME
,
851 .responses
= linked_list_create(),
852 .signatureAlgorithm
= OID_UNKNOWN
,
853 .certs
= linked_list_create(),
856 if (!parse_OCSPResponse(this))
861 return &this->public;
867 x509_ocsp_response_t
*x509_ocsp_response_load(certificate_type_t type
,
870 chunk_t blob
= chunk_empty
;
874 switch (va_arg(args
, builder_part_t
))
876 case BUILD_BLOB_ASN1_DER
:
877 blob
= va_arg(args
, chunk_t
);