2 * Copyright (C) 2008 Martin Willi
3 * Copyright (C) 2007 Andreas Steffen
4 * Hochschule für 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
20 #include "x509_ocsp_response.h"
25 #include <asn1/asn1.h>
26 #include <asn1/asn1_parser.h>
27 #include <utils/identification.h>
28 #include <utils/linked_list.h>
32 #include <credentials/certificates/x509.h>
33 #include <credentials/certificates/crl.h>
36 * how long do we use an OCSP response without a nextUpdate
38 #define OCSP_DEFAULT_LIFETIME 30
40 typedef struct private_x509_ocsp_response_t private_x509_ocsp_response_t
;
43 * Private data of a ocsp_t object.
45 struct private_x509_ocsp_response_t
{
47 * Public interface for this ocsp object.
49 x509_ocsp_response_t
public;
52 * complete encoded OCSP response
57 * data for signature verficiation
59 chunk_t tbsResponseData
;
62 * signature algorithm (OID)
64 int signatureAlgorithm
;
72 * name or keyid of the responder
74 identification_t
*responderId
;
77 * time of response production
82 * latest nextUpdate in this OCSP response
87 * list of included certificates
92 * Linked list of OCSP responses, single_response_t
94 linked_list_t
*responses
;
97 * Nonce required for ocsp request and response
108 * single response contained in OCSP response
111 /** hash algorithm OID to for the two hashes */
113 /** hash of issuer DN */
114 chunk_t issuerNameHash
;
116 chunk_t issuerKeyHash
;
117 /** serial number of certificate */
118 chunk_t serialNumber
;
119 /** OCSP certificate status */
120 cert_validation_t status
;
121 /** time of revocation, if revoked */
122 time_t revocationTime
;
123 /** revocation reason, if revoked */
124 crl_reason_t revocationReason
;
125 /** creation of associated CRL */
127 /** creation of next CRL */
131 /* our OCSP response version implementation */
132 #define OCSP_BASIC_RESPONSE_VERSION 1
134 /* some OCSP specific prefabricated ASN.1 constants */
135 static u_char ASN1_nonce_oid_str
[] = {
138 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02
141 static u_char ASN1_response_oid_str
[] = {
144 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04
147 static u_char ASN1_response_content_str
[] = {
152 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
155 static const chunk_t ASN1_nonce_oid
= chunk_from_buf(ASN1_nonce_oid_str
);
156 static const chunk_t ASN1_response_oid
= chunk_from_buf(ASN1_response_oid_str
);
157 static const chunk_t ASN1_response_content
= chunk_from_buf(ASN1_response_content_str
);
160 * Implementaiton of ocsp_response_t.get_status
162 static cert_validation_t
get_status(private_x509_ocsp_response_t
*this,
163 x509_t
*subject
, x509_t
*issuer
,
164 time_t *revocation_time
,
165 crl_reason_t
*revocation_reason
,
166 time_t *this_update
, time_t *next_update
)
168 enumerator_t
*enumerator
;
169 single_response_t
*response
;
170 cert_validation_t status
= VALIDATION_FAILED
;
171 certificate_t
*issuercert
= &issuer
->interface
;
173 enumerator
= this->responses
->create_enumerator(this->responses
);
174 while (enumerator
->enumerate(enumerator
, &response
))
177 identification_t
*id
;
180 /* check serial first, is cheaper */
181 if (!chunk_equals(subject
->get_serial(subject
), response
->serialNumber
))
185 /* check issuerKeyHash if available */
186 if (response
->issuerKeyHash
.ptr
)
188 public_key_t
*public;
190 public = issuercert
->get_public_key(issuercert
);
195 switch (response
->hashAlgorithm
)
196 { /* TODO: generic mapper function */
198 id
= public->get_id(public, ID_PUBKEY_SHA1
);
201 public->destroy(public);
204 if (!chunk_equals(response
->issuerKeyHash
, id
->get_encoding(id
)))
206 public->destroy(public);
209 public->destroy(public);
211 /* check issuerNameHash, if available */
212 else if (response
->issuerNameHash
.ptr
)
214 hasher
= lib
->crypto
->create_hasher(lib
->crypto
,
215 hasher_algorithm_from_oid(response
->hashAlgorithm
));
220 id
= issuercert
->get_subject(issuercert
);
221 hasher
->allocate_hash(hasher
, id
->get_encoding(id
), &hash
);
222 hasher
->destroy(hasher
);
223 if (!chunk_equals(hash
, response
->issuerNameHash
))
233 status
= response
->status
;
234 *revocation_time
= response
->revocationTime
;
235 *revocation_reason
= response
->revocationReason
;
236 *this_update
= response
->thisUpdate
;
237 *next_update
= response
->nextUpdate
;
241 enumerator
->destroy(enumerator
);
246 * Implementation of ocsp_response_t.create_cert_enumerator.
248 static enumerator_t
* create_cert_enumerator(private_x509_ocsp_response_t
*this)
250 return this->certs
->create_enumerator(this->certs
);
254 * ASN.1 definition of singleResponse
256 static const asn1Object_t singleResponseObjects
[] = {
257 { 0, "singleResponse", ASN1_SEQUENCE
, ASN1_BODY
}, /* 0 */
258 { 1, "certID", ASN1_SEQUENCE
, ASN1_NONE
}, /* 1 */
259 { 2, "algorithm", ASN1_EOC
, ASN1_RAW
}, /* 2 */
260 { 2, "issuerNameHash", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 3 */
261 { 2, "issuerKeyHash", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 4 */
262 { 2, "serialNumber", ASN1_INTEGER
, ASN1_BODY
}, /* 5 */
263 { 1, "certStatusGood", ASN1_CONTEXT_S_0
, ASN1_OPT
}, /* 6 */
264 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 7 */
265 { 1, "certStatusRevoked", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 8 */
266 { 2, "revocationTime", ASN1_GENERALIZEDTIME
, ASN1_BODY
}, /* 9 */
267 { 2, "revocationReason", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 10 */
268 { 3, "crlReason", ASN1_ENUMERATED
, ASN1_BODY
}, /* 11 */
269 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 12 */
270 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 13 */
271 { 1, "certStatusUnknown", ASN1_CONTEXT_S_2
, ASN1_OPT
}, /* 14 */
272 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 15 */
273 { 1, "thisUpdate", ASN1_GENERALIZEDTIME
, ASN1_BODY
}, /* 16 */
274 { 1, "nextUpdateContext", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 17 */
275 { 2, "nextUpdate", ASN1_GENERALIZEDTIME
, ASN1_BODY
}, /* 18 */
276 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 19 */
277 { 1, "singleExtensionsContext", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 20 */
278 { 2, "singleExtensions", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 21 */
279 { 3, "extension", ASN1_SEQUENCE
, ASN1_NONE
}, /* 22 */
280 { 4, "extnID", ASN1_OID
, ASN1_BODY
}, /* 23 */
281 { 4, "critical", ASN1_BOOLEAN
, ASN1_BODY
|
283 { 4, "extnValue", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 25 */
284 { 2, "end loop", ASN1_EOC
, ASN1_END
}, /* 26 */
285 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 27 */
286 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
288 #define SINGLE_RESPONSE_ALGORITHM 2
289 #define SINGLE_RESPONSE_ISSUER_NAME_HASH 3
290 #define SINGLE_RESPONSE_ISSUER_KEY_HASH 4
291 #define SINGLE_RESPONSE_SERIAL_NUMBER 5
292 #define SINGLE_RESPONSE_CERT_STATUS_GOOD 6
293 #define SINGLE_RESPONSE_CERT_STATUS_REVOKED 8
294 #define SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME 9
295 #define SINGLE_RESPONSE_CERT_STATUS_CRL_REASON 11
296 #define SINGLE_RESPONSE_CERT_STATUS_UNKNOWN 14
297 #define SINGLE_RESPONSE_THIS_UPDATE 16
298 #define SINGLE_RESPONSE_NEXT_UPDATE 18
299 #define SINGLE_RESPONSE_EXT_ID 23
300 #define SINGLE_RESPONSE_CRITICAL 24
301 #define SINGLE_RESPONSE_EXT_VALUE 25
304 * Parse a single OCSP response
306 static bool parse_singleResponse(private_x509_ocsp_response_t
*this,
307 chunk_t blob
, int level0
)
309 asn1_parser_t
*parser
;
312 bool success
= FALSE
;
314 single_response_t
*response
;
316 response
= malloc_thing(single_response_t
);
317 response
->hashAlgorithm
= OID_UNKNOWN
;
318 response
->issuerNameHash
= chunk_empty
;
319 response
->issuerKeyHash
= chunk_empty
;
320 response
->serialNumber
= chunk_empty
;
321 response
->status
= VALIDATION_FAILED
;
322 response
->revocationTime
= 0;
323 response
->revocationReason
= CRL_UNSPECIFIED
;
324 response
->thisUpdate
= UNDEFINED_TIME
;
325 /* if nextUpdate is missing, we give it a short lifetime */
326 response
->nextUpdate
= this->producedAt
+ OCSP_DEFAULT_LIFETIME
;
328 parser
= asn1_parser_create(singleResponseObjects
, blob
);
329 parser
->set_top_level(parser
, level0
);
331 while (parser
->iterate(parser
, &objectID
, &object
))
335 case SINGLE_RESPONSE_ALGORITHM
:
336 response
->hashAlgorithm
= asn1_parse_algorithmIdentifier(object
,
337 parser
->get_level(parser
)+1, NULL
);
339 case SINGLE_RESPONSE_ISSUER_NAME_HASH
:
340 response
->issuerNameHash
= object
;
342 case SINGLE_RESPONSE_ISSUER_KEY_HASH
:
343 response
->issuerKeyHash
= object
;
345 case SINGLE_RESPONSE_SERIAL_NUMBER
:
346 response
->serialNumber
= object
;
348 case SINGLE_RESPONSE_CERT_STATUS_GOOD
:
349 response
->status
= VALIDATION_GOOD
;
351 case SINGLE_RESPONSE_CERT_STATUS_REVOKED
:
352 response
->status
= VALIDATION_REVOKED
;
354 case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME
:
355 response
->revocationTime
= asn1_to_time(&object
, ASN1_GENERALIZEDTIME
);
357 case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON
:
360 response
->revocationReason
= *object
.ptr
;
363 case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN
:
364 response
->status
= VALIDATION_FAILED
;
366 case SINGLE_RESPONSE_THIS_UPDATE
:
367 response
->thisUpdate
= asn1_to_time(&object
, ASN1_GENERALIZEDTIME
);
369 case SINGLE_RESPONSE_NEXT_UPDATE
:
370 response
->nextUpdate
= asn1_to_time(&object
, ASN1_GENERALIZEDTIME
);
371 if (response
->nextUpdate
> this->usableUntil
)
373 this->usableUntil
= response
->nextUpdate
;
378 success
= parser
->success(parser
);
379 parser
->destroy(parser
);
382 if (this->usableUntil
== UNDEFINED_TIME
)
384 this->usableUntil
= this->producedAt
+ OCSP_DEFAULT_LIFETIME
;
386 this->responses
->insert_last(this->responses
, response
);
392 * ASN.1 definition of responses
394 static const asn1Object_t responsesObjects
[] = {
395 { 0, "responses", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 0 */
396 { 1, "singleResponse", ASN1_EOC
, ASN1_RAW
}, /* 1 */
397 { 0, "end loop", ASN1_EOC
, ASN1_END
}, /* 2 */
398 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
400 #define RESPONSES_SINGLE_RESPONSE 1
403 * Parse all responses
405 static bool parse_responses(private_x509_ocsp_response_t
*this,
406 chunk_t blob
, int level0
)
408 asn1_parser_t
*parser
;
411 bool success
= FALSE
;
413 parser
= asn1_parser_create(responsesObjects
, blob
);
414 parser
->set_top_level(parser
, level0
);
416 while (parser
->iterate(parser
, &objectID
, &object
))
420 case RESPONSES_SINGLE_RESPONSE
:
421 if (!parse_singleResponse(this, object
,
422 parser
->get_level(parser
)+1))
431 success
= parser
->success(parser
);
434 parser
->destroy(parser
);
439 * ASN.1 definition of basicResponse
441 static const asn1Object_t basicResponseObjects
[] = {
442 { 0, "BasicOCSPResponse", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
443 { 1, "tbsResponseData", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 1 */
444 { 2, "versionContext", ASN1_CONTEXT_C_0
, ASN1_NONE
|
446 { 3, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 3 */
447 { 2, "responderIdContext", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 4 */
448 { 3, "responderIdByName", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 5 */
449 { 2, "end choice", ASN1_EOC
, ASN1_END
}, /* 6 */
450 { 2, "responderIdContext", ASN1_CONTEXT_C_2
, ASN1_OPT
}, /* 7 */
451 { 3, "responderIdByKey", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 8 */
452 { 2, "end choice", ASN1_EOC
, ASN1_END
}, /* 9 */
453 { 2, "producedAt", ASN1_GENERALIZEDTIME
, ASN1_BODY
}, /* 10 */
454 { 2, "responses", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 11 */
455 { 2, "responseExtensionsContext", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 12 */
456 { 3, "responseExtensions", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 13 */
457 { 4, "extension", ASN1_SEQUENCE
, ASN1_NONE
}, /* 14 */
458 { 5, "extnID", ASN1_OID
, ASN1_BODY
}, /* 15 */
459 { 5, "critical", ASN1_BOOLEAN
, ASN1_BODY
|
461 { 5, "extnValue", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 17 */
462 { 4, "end loop", ASN1_EOC
, ASN1_END
}, /* 18 */
463 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 19 */
464 { 1, "signatureAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 20 */
465 { 1, "signature", ASN1_BIT_STRING
, ASN1_BODY
}, /* 21 */
466 { 1, "certsContext", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 22 */
467 { 2, "certs", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 23 */
468 { 3, "certificate", ASN1_SEQUENCE
, ASN1_RAW
}, /* 24 */
469 { 2, "end loop", ASN1_EOC
, ASN1_END
}, /* 25 */
470 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 26 */
471 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
473 #define BASIC_RESPONSE_TBS_DATA 1
474 #define BASIC_RESPONSE_VERSION 3
475 #define BASIC_RESPONSE_ID_BY_NAME 5
476 #define BASIC_RESPONSE_ID_BY_KEY 8
477 #define BASIC_RESPONSE_PRODUCED_AT 10
478 #define BASIC_RESPONSE_RESPONSES 11
479 #define BASIC_RESPONSE_EXT_ID 15
480 #define BASIC_RESPONSE_CRITICAL 16
481 #define BASIC_RESPONSE_EXT_VALUE 17
482 #define BASIC_RESPONSE_ALGORITHM 20
483 #define BASIC_RESPONSE_SIGNATURE 21
484 #define BASIC_RESPONSE_CERTIFICATE 24
487 * Parse a basicOCSPResponse
489 static bool parse_basicOCSPResponse(private_x509_ocsp_response_t
*this,
490 chunk_t blob
, int level0
)
492 asn1_parser_t
*parser
;
494 chunk_t responses
= chunk_empty
;
496 int extn_oid
= OID_UNKNOWN
;
497 u_int responses_level
= level0
;
499 bool success
= FALSE
;
502 parser
= asn1_parser_create(basicResponseObjects
, blob
);
503 parser
->set_top_level(parser
, level0
);
505 while (parser
->iterate(parser
, &objectID
, &object
))
509 case BASIC_RESPONSE_TBS_DATA
:
510 this->tbsResponseData
= object
;
512 case BASIC_RESPONSE_VERSION
:
514 u_int version
= (object
.len
)?
(1 + (u_int
)*object
.ptr
) : 1;
516 if (version
!= OCSP_BASIC_RESPONSE_VERSION
)
518 DBG1(" ocsp ResponseData version %d not supported", version
);
523 case BASIC_RESPONSE_ID_BY_NAME
:
524 this->responderId
= identification_create_from_encoding(
525 ID_DER_ASN1_DN
, object
);
526 DBG2(" '%D'", this->responderId
);
528 case BASIC_RESPONSE_ID_BY_KEY
:
529 this->responderId
= identification_create_from_encoding(
530 ID_PUBKEY_INFO_SHA1
, object
);
531 DBG2(" '%D'", this->responderId
);
533 case BASIC_RESPONSE_PRODUCED_AT
:
534 this->producedAt
= asn1_to_time(&object
, ASN1_GENERALIZEDTIME
);
536 case BASIC_RESPONSE_RESPONSES
:
538 responses_level
= parser
->get_level(parser
)+1;
540 case BASIC_RESPONSE_EXT_ID
:
541 extn_oid
= asn1_known_oid(object
);
543 case BASIC_RESPONSE_CRITICAL
:
544 critical
= object
.len
&& *object
.ptr
;
545 DBG2(" %s", critical ?
"TRUE" : "FALSE");
547 case BASIC_RESPONSE_EXT_VALUE
:
548 if (extn_oid
== OID_NONCE
)
550 this->nonce
= object
;
553 case BASIC_RESPONSE_ALGORITHM
:
554 this->signatureAlgorithm
= asn1_parse_algorithmIdentifier(object
,
555 parser
->get_level(parser
)+1, NULL
);
557 case BASIC_RESPONSE_SIGNATURE
:
558 this->signature
= object
;
560 case BASIC_RESPONSE_CERTIFICATE
:
562 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
,CERT_X509
,
568 this->certs
->insert_last(this->certs
, cert
);
574 success
= parser
->success(parser
);
577 parser
->destroy(parser
);
580 if (!this->responderId
)
582 this->responderId
= identification_create_from_encoding(ID_ANY
,
585 success
= parse_responses(this, responses
, responses_level
);
591 * ASN.1 definition of ocspResponse
593 static const asn1Object_t ocspResponseObjects
[] = {
594 { 0, "OCSPResponse", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
595 { 1, "responseStatus", ASN1_ENUMERATED
, ASN1_BODY
}, /* 1 */
596 { 1, "responseBytesContext", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 2 */
597 { 2, "responseBytes", ASN1_SEQUENCE
, ASN1_NONE
}, /* 3 */
598 { 3, "responseType", ASN1_OID
, ASN1_BODY
}, /* 4 */
599 { 3, "response", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 5 */
600 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 6 */
601 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
603 #define OCSP_RESPONSE_STATUS 1
604 #define OCSP_RESPONSE_TYPE 4
605 #define OCSP_RESPONSE 5
608 * Parse OCSPResponse object
610 static bool parse_OCSPResponse(private_x509_ocsp_response_t
*this)
612 asn1_parser_t
*parser
;
615 int responseType
= OID_UNKNOWN
;
616 bool success
= FALSE
;
617 ocsp_status_t status
;
619 parser
= asn1_parser_create(ocspResponseObjects
, this->encoding
);
621 while (parser
->iterate(parser
, &objectID
, &object
))
625 case OCSP_RESPONSE_STATUS
:
626 status
= (ocsp_status_t
)*object
.ptr
;
629 case OCSP_SUCCESSFUL
:
632 DBG1(" ocsp response status: %N",
633 ocsp_status_names
, status
);
637 case OCSP_RESPONSE_TYPE
:
638 responseType
= asn1_known_oid(object
);
641 switch (responseType
)
644 success
= parse_basicOCSPResponse(this, object
,
645 parser
->get_level(parser
)+1);
648 DBG1(" ocsp response type %#B not supported", &object
);
654 success
&= parser
->success(parser
);
657 parser
->destroy(parser
);
662 * Implementation of certificate_t.get_type
664 static certificate_type_t
get_type(private_x509_ocsp_response_t
*this)
666 return CERT_X509_OCSP_RESPONSE
;
670 * Implementation of certificate_t.get_issuer
672 static identification_t
* get_issuer(private_x509_ocsp_response_t
*this)
674 return this->responderId
;
678 * Implementation of certificate_t.has_subject.
680 static id_match_t
has_issuer(private_x509_ocsp_response_t
*this,
681 identification_t
*issuer
)
683 return this->responderId
->matches(this->responderId
, issuer
);
687 * Implementation of certificate_t.issued_by
689 static bool issued_by(private_x509_ocsp_response_t
*this, certificate_t
*issuer
)
692 signature_scheme_t scheme
;
694 x509_t
*x509
= (x509_t
*)issuer
;
696 if (issuer
->get_type(issuer
) != CERT_X509
)
700 if (this->responderId
->get_type(this->responderId
) == ID_DER_ASN1_DN
)
702 if (!this->responderId
->equals(this->responderId
,
703 issuer
->get_subject(issuer
)))
711 public_key_t
*public = issuer
->get_public_key(issuer
);
717 equal
= this->responderId
->equals(this->responderId
,
718 public->get_id(public, ID_PUBKEY_SHA1
));
719 public->destroy(public);
725 if (!(x509
->get_flags(x509
) & X509_OCSP_SIGNER
) &&
726 !(x509
->get_flags(x509
) & X509_CA
))
730 /* TODO: generic OID to scheme mapper? */
731 switch (this->signatureAlgorithm
)
733 case OID_MD5_WITH_RSA
:
734 scheme
= SIGN_RSA_EMSA_PKCS1_MD5
;
736 case OID_SHA1_WITH_RSA
:
737 scheme
= SIGN_RSA_EMSA_PKCS1_SHA1
;
739 case OID_SHA256_WITH_RSA
:
740 scheme
= SIGN_RSA_EMSA_PKCS1_SHA256
;
742 case OID_SHA384_WITH_RSA
:
743 scheme
= SIGN_RSA_EMSA_PKCS1_SHA384
;
745 case OID_SHA512_WITH_RSA
:
746 scheme
= SIGN_RSA_EMSA_PKCS1_SHA512
;
751 key
= issuer
->get_public_key(issuer
);
756 valid
= key
->verify(key
, scheme
, this->tbsResponseData
, this->signature
);
762 * Implementation of certificate_t.get_public_key
764 static public_key_t
* get_public_key(private_x509_ocsp_response_t
*this)
770 * Implementation of certificate_t.get_validity.
772 static bool get_validity(private_x509_ocsp_response_t
*this, time_t *when
,
773 time_t *not_before
, time_t *not_after
)
787 *not_before
= this->producedAt
;
791 *not_after
= this->usableUntil
;
793 return (t
< this->usableUntil
);
797 * Implementation of certificate_t.is_newer.
799 static bool is_newer(certificate_t
*this, certificate_t
*that
)
801 time_t this_update
, that_update
, now
= time(NULL
);
804 this->get_validity(this, &now
, &this_update
, NULL
);
805 that
->get_validity(that
, &now
, &that_update
, NULL
);
806 new = this_update
> that_update
;
807 DBG1(" ocsp response from %#T is %s - existing ocsp response from %#T %s",
808 &this_update
, FALSE
, new ?
"newer":"not newer",
809 &that_update
, FALSE
, new ?
"replaced":"retained");
814 * Implementation of certificate_t.get_encoding.
816 static chunk_t
get_encoding(private_x509_ocsp_response_t
*this)
818 return chunk_clone(this->encoding
);
822 * Implementation of certificate_t.equals.
824 static bool equals(private_x509_ocsp_response_t
*this, certificate_t
*other
)
829 if (this == (private_x509_ocsp_response_t
*)other
)
833 if (other
->get_type(other
) != CERT_X509_OCSP_RESPONSE
)
837 if (other
->equals
== (void*)equals
)
838 { /* skip allocation if we have the same implementation */
839 return chunk_equals(this->encoding
, ((private_x509_ocsp_response_t
*)other
)->encoding
);
841 encoding
= other
->get_encoding(other
);
842 equal
= chunk_equals(this->encoding
, encoding
);
848 * Implementation of certificate_t.get_ref
850 static private_x509_ocsp_response_t
* get_ref(private_x509_ocsp_response_t
*this)
857 * Implements ocsp_t.destroy.
859 static void destroy(private_x509_ocsp_response_t
*this)
861 if (ref_put(&this->ref
))
863 this->certs
->destroy_offset(this->certs
, offsetof(certificate_t
, destroy
));
864 this->responses
->destroy_function(this->responses
, free
);
865 DESTROY_IF(this->responderId
);
866 free(this->encoding
.ptr
);
872 * load an OCSP response
874 static x509_ocsp_response_t
*load(chunk_t data
)
876 private_x509_ocsp_response_t
*this;
878 this = malloc_thing(private_x509_ocsp_response_t
);
880 this->public.interface
.certificate
.get_type
= (certificate_type_t (*)(certificate_t
*this))get_type
;
881 this->public.interface
.certificate
.get_subject
= (identification_t
* (*)(certificate_t
*this))get_issuer
;
882 this->public.interface
.certificate
.get_issuer
= (identification_t
* (*)(certificate_t
*this))get_issuer
;
883 this->public.interface
.certificate
.has_subject
= (id_match_t(*)(certificate_t
*, identification_t
*subject
))has_issuer
;
884 this->public.interface
.certificate
.has_issuer
= (id_match_t(*)(certificate_t
*, identification_t
*issuer
))has_issuer
;
885 this->public.interface
.certificate
.issued_by
= (bool (*)(certificate_t
*this, certificate_t
*issuer
))issued_by
;
886 this->public.interface
.certificate
.get_public_key
= (public_key_t
* (*)(certificate_t
*this))get_public_key
;
887 this->public.interface
.certificate
.get_validity
= (bool(*)(certificate_t
*, time_t *when
, time_t *, time_t*))get_validity
;
888 this->public.interface
.certificate
.is_newer
= (bool (*)(certificate_t
*,certificate_t
*))is_newer
;
889 this->public.interface
.certificate
.get_encoding
= (chunk_t(*)(certificate_t
*))get_encoding
;
890 this->public.interface
.certificate
.equals
= (bool(*)(certificate_t
*, certificate_t
*other
))equals
;
891 this->public.interface
.certificate
.get_ref
= (certificate_t
* (*)(certificate_t
*this))get_ref
;
892 this->public.interface
.certificate
.destroy
= (void (*)(certificate_t
*this))destroy
;
893 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
;
894 this->public.interface
.create_cert_enumerator
= (enumerator_t
*(*)(ocsp_response_t
*))create_cert_enumerator
;
897 this->encoding
= data
;
898 this->tbsResponseData
= chunk_empty
;
899 this->responderId
= NULL
;
900 this->producedAt
= UNDEFINED_TIME
;
901 this->usableUntil
= UNDEFINED_TIME
;
902 this->responses
= linked_list_create();
903 this->nonce
= chunk_empty
;
904 this->signatureAlgorithm
= OID_UNKNOWN
;
905 this->signature
= chunk_empty
;
906 this->certs
= linked_list_create();
908 if (!parse_OCSPResponse(this))
913 return &this->public;
917 typedef struct private_builder_t private_builder_t
;
919 * Builder implementation for certificate loading
921 struct private_builder_t
{
922 /** implements the builder interface */
924 /** loaded response */
925 x509_ocsp_response_t
*res
;
929 * Implementation of builder_t.build
931 static x509_ocsp_response_t
*build(private_builder_t
*this)
933 x509_ocsp_response_t
*res
= this->res
;
940 * Implementation of builder_t.add
942 static void add(private_builder_t
*this, builder_part_t part
, ...)
948 DBG1("ignoring surplus build part %N", builder_part_names
, part
);
954 case BUILD_BLOB_ASN1_DER
:
956 va_start(args
, part
);
957 this->res
= load(va_arg(args
, chunk_t
));
962 DBG1("ignoring unsupported build part %N", builder_part_names
, part
);
968 * Builder construction function
970 builder_t
*x509_ocsp_response_builder(certificate_type_t type
)
972 private_builder_t
*this;
974 if (type
!= CERT_X509_OCSP_RESPONSE
)
979 this = malloc_thing(private_builder_t
);
982 this->public.add
= (void(*)(builder_t
*this, builder_part_t part
, ...))add
;
983 this->public.build
= (void*(*)(builder_t
*this))build
;
985 return &this->public;