4 * @brief Implementation of ocsp_t.
8 /* Support of the Online Certificate Status Protocol (OCSP)
9 * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen
10 * Zuercher Hochschule Winterthur
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
29 #include <sys/types.h>
34 #include <asn1/asn1.h>
35 #include <utils/identification.h>
36 #include <utils/randomizer.h>
37 #include <utils/fetcher.h>
40 #include "hashers/hasher.h"
41 #include "rsa/rsa_public_key.h"
46 #define NONCE_LENGTH 16
48 typedef struct private_ocsp_t private_ocsp_t
;
51 * Private data of a ocsp_t object.
53 struct private_ocsp_t
{
55 * Public interface for this ocsp object.
65 * Requestor certificate
67 x509_t
*requestor_cert
;
70 * Linked list of ocsp uris
75 * Linked list of certinfos to be requested
77 linked_list_t
*certinfos
;
80 * Nonce required for ocsp request and response
85 * SHA-1 hash over issuer distinguished name
90 * SHA-1 hash over issuer public key
95 ENUM(response_status_names
, STATUS_SUCCESSFUL
, STATUS_UNAUTHORIZED
,
100 "signature required",
104 /* response container */
105 typedef struct response_t response_t
;
110 identification_t
*responder_id_name
;
111 chunk_t responder_id_key
;
117 x509_t
*responder_cert
;
120 * @brief Destroys the response_t object
122 * @param this response_t to destroy
124 void (*destroy
) (response_t
*this);
128 * Implements response_t.destroy.
130 static void response_destroy(response_t
*this)
132 DESTROY_IF(this->responder_id_name
);
133 DESTROY_IF(this->responder_cert
);
134 free(this->chunk
.ptr
);
139 * Creates a response_t object
141 static response_t
* response_create_from_chunk(chunk_t chunk
)
143 response_t
*this = malloc_thing(response_t
);
146 this->tbs
= chunk_empty
;
147 this->responder_id_name
= NULL
;
148 this->responder_id_key
= chunk_empty
;
149 this->produced_at
= UNDEFINED_TIME
;
150 this->responses
= chunk_empty
;
151 this->nonce
= chunk_empty
;
152 this->algorithm
= OID_UNKNOWN
;
153 this->signature
= chunk_empty
;
154 this->responder_cert
= NULL
;
156 this->destroy
= (void (*) (response_t
*))response_destroy
;
161 /* some OCSP specific prefabricated ASN.1 constants */
163 static u_char ASN1_nonce_oid_str
[] = {
166 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02
169 static u_char ASN1_response_oid_str
[] = {
172 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04
175 static u_char ASN1_response_content_str
[] = {
180 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
183 static const chunk_t ASN1_nonce_oid
= chunk_from_buf(ASN1_nonce_oid_str
);
184 static const chunk_t ASN1_response_oid
= chunk_from_buf(ASN1_response_oid_str
);
185 static const chunk_t ASN1_response_content
= chunk_from_buf(ASN1_response_content_str
);
187 /* asn.1 definitions for parsing */
189 static const asn1Object_t ocspResponseObjects
[] = {
190 { 0, "OCSPResponse", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
191 { 1, "responseStatus", ASN1_ENUMERATED
, ASN1_BODY
}, /* 1 */
192 { 1, "responseBytesContext", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 2 */
193 { 2, "responseBytes", ASN1_SEQUENCE
, ASN1_NONE
}, /* 3 */
194 { 3, "responseType", ASN1_OID
, ASN1_BODY
}, /* 4 */
195 { 3, "response", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 5 */
196 { 1, "end opt", ASN1_EOC
, ASN1_END
} /* 6 */
199 #define OCSP_RESPONSE_STATUS 1
200 #define OCSP_RESPONSE_TYPE 4
201 #define OCSP_RESPONSE 5
202 #define OCSP_RESPONSE_ROOF 7
204 static const asn1Object_t basicResponseObjects
[] = {
205 { 0, "BasicOCSPResponse", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
206 { 1, "tbsResponseData", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 1 */
207 { 2, "versionContext", ASN1_CONTEXT_C_0
, ASN1_NONE
|
209 { 3, "version", ASN1_INTEGER
, ASN1_BODY
}, /* 3 */
210 { 2, "responderIdContext", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 4 */
211 { 3, "responderIdByName", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 5 */
212 { 2, "end choice", ASN1_EOC
, ASN1_END
}, /* 6 */
213 { 2, "responderIdContext", ASN1_CONTEXT_C_2
, ASN1_OPT
}, /* 7 */
214 { 3, "responderIdByKey", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 8 */
215 { 2, "end choice", ASN1_EOC
, ASN1_END
}, /* 9 */
216 { 2, "producedAt", ASN1_GENERALIZEDTIME
, ASN1_BODY
}, /* 10 */
217 { 2, "responses", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 11 */
218 { 2, "responseExtensionsContext", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 12 */
219 { 3, "responseExtensions", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 13 */
220 { 4, "extension", ASN1_SEQUENCE
, ASN1_NONE
}, /* 14 */
221 { 5, "extnID", ASN1_OID
, ASN1_BODY
}, /* 15 */
222 { 5, "critical", ASN1_BOOLEAN
, ASN1_BODY
|
224 { 5, "extnValue", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 17 */
225 { 4, "end loop", ASN1_EOC
, ASN1_END
}, /* 18 */
226 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 19 */
227 { 1, "signatureAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 20 */
228 { 1, "signature", ASN1_BIT_STRING
, ASN1_BODY
}, /* 21 */
229 { 1, "certsContext", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 22 */
230 { 2, "certs", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 23 */
231 { 3, "certificate", ASN1_SEQUENCE
, ASN1_RAW
}, /* 24 */
232 { 2, "end loop", ASN1_EOC
, ASN1_END
}, /* 25 */
233 { 1, "end opt", ASN1_EOC
, ASN1_END
} /* 26 */
236 #define BASIC_RESPONSE_TBS_DATA 1
237 #define BASIC_RESPONSE_VERSION 3
238 #define BASIC_RESPONSE_ID_BY_NAME 5
239 #define BASIC_RESPONSE_ID_BY_KEY 8
240 #define BASIC_RESPONSE_PRODUCED_AT 10
241 #define BASIC_RESPONSE_RESPONSES 11
242 #define BASIC_RESPONSE_EXT_ID 15
243 #define BASIC_RESPONSE_CRITICAL 16
244 #define BASIC_RESPONSE_EXT_VALUE 17
245 #define BASIC_RESPONSE_ALGORITHM 20
246 #define BASIC_RESPONSE_SIGNATURE 21
247 #define BASIC_RESPONSE_CERTIFICATE 24
248 #define BASIC_RESPONSE_ROOF 27
250 static const asn1Object_t responsesObjects
[] = {
251 { 0, "responses", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 0 */
252 { 1, "singleResponse", ASN1_EOC
, ASN1_RAW
}, /* 1 */
253 { 0, "end loop", ASN1_EOC
, ASN1_END
} /* 2 */
256 #define RESPONSES_SINGLE_RESPONSE 1
257 #define RESPONSES_ROOF 3
259 static const asn1Object_t singleResponseObjects
[] = {
260 { 0, "singleResponse", ASN1_SEQUENCE
, ASN1_BODY
}, /* 0 */
261 { 1, "certID", ASN1_SEQUENCE
, ASN1_NONE
}, /* 1 */
262 { 2, "algorithm", ASN1_EOC
, ASN1_RAW
}, /* 2 */
263 { 2, "issuerNameHash", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 3 */
264 { 2, "issuerKeyHash", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 4 */
265 { 2, "serialNumber", ASN1_INTEGER
, ASN1_BODY
}, /* 5 */
266 { 1, "certStatusGood", ASN1_CONTEXT_S_0
, ASN1_OPT
}, /* 6 */
267 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 7 */
268 { 1, "certStatusRevoked", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 8 */
269 { 2, "revocationTime", ASN1_GENERALIZEDTIME
, ASN1_BODY
}, /* 9 */
270 { 2, "revocationReason", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 10 */
271 { 3, "crlReason", ASN1_ENUMERATED
, ASN1_BODY
}, /* 11 */
272 { 2, "end opt", ASN1_EOC
, ASN1_END
}, /* 12 */
273 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 13 */
274 { 1, "certStatusUnknown", ASN1_CONTEXT_S_2
, ASN1_OPT
}, /* 14 */
275 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 15 */
276 { 1, "thisUpdate", ASN1_GENERALIZEDTIME
, ASN1_BODY
}, /* 16 */
277 { 1, "nextUpdateContext", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 17 */
278 { 2, "nextUpdate", ASN1_GENERALIZEDTIME
, ASN1_BODY
}, /* 18 */
279 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 19 */
280 { 1, "singleExtensionsContext", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 20 */
281 { 2, "singleExtensions", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 21 */
282 { 3, "extension", ASN1_SEQUENCE
, ASN1_NONE
}, /* 22 */
283 { 4, "extnID", ASN1_OID
, ASN1_BODY
}, /* 23 */
284 { 4, "critical", ASN1_BOOLEAN
, ASN1_BODY
|
286 { 4, "extnValue", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 25 */
287 { 2, "end loop", ASN1_EOC
, ASN1_END
}, /* 26 */
288 { 1, "end opt", ASN1_EOC
, ASN1_END
} /* 27 */
291 #define SINGLE_RESPONSE_ALGORITHM 2
292 #define SINGLE_RESPONSE_ISSUER_NAME_HASH 3
293 #define SINGLE_RESPONSE_ISSUER_KEY_HASH 4
294 #define SINGLE_RESPONSE_SERIAL_NUMBER 5
295 #define SINGLE_RESPONSE_CERT_STATUS_GOOD 6
296 #define SINGLE_RESPONSE_CERT_STATUS_REVOKED 8
297 #define SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME 9
298 #define SINGLE_RESPONSE_CERT_STATUS_CRL_REASON 11
299 #define SINGLE_RESPONSE_CERT_STATUS_UNKNOWN 14
300 #define SINGLE_RESPONSE_THIS_UPDATE 16
301 #define SINGLE_RESPONSE_NEXT_UPDATE 18
302 #define SINGLE_RESPONSE_EXT_ID 23
303 #define SINGLE_RESPONSE_CRITICAL 24
304 #define SINGLE_RESPONSE_EXT_VALUE 25
305 #define SINGLE_RESPONSE_ROOF 28
308 * build requestorName (into TBSRequest)
310 static chunk_t
build_requestor_name(private_ocsp_t
*this)
312 identification_t
*requestor_name
= this->requestor_cert
->get_subject(this->requestor_cert
);
314 return asn1_wrap(ASN1_CONTEXT_C_1
, "m",
315 asn1_simple_object(ASN1_CONTEXT_C_4
,
316 requestor_name
->get_encoding(requestor_name
)));
320 * build request (into requestList)
321 * no singleRequestExtensions used
323 static chunk_t
build_request(private_ocsp_t
*this, certinfo_t
*certinfo
)
325 chunk_t serialNumber
= certinfo
->get_serialNumber(certinfo
);
327 chunk_t reqCert
= asn1_wrap(ASN1_SEQUENCE
, "cmmm",
329 asn1_simple_object(ASN1_OCTET_STRING
, this->authNameID
),
330 asn1_simple_object(ASN1_OCTET_STRING
, this->authKeyID
),
331 asn1_simple_object(ASN1_INTEGER
, serialNumber
));
333 return asn1_wrap(ASN1_SEQUENCE
, "m", reqCert
);
337 * build requestList (into TBSRequest)
339 static chunk_t
build_request_list(private_ocsp_t
*this)
343 linked_list_t
*request_list
= linked_list_create();
346 iterator_t
*iterator
= this->certinfos
->create_iterator(this->certinfos
, TRUE
);
347 certinfo_t
*certinfo
;
349 while (iterator
->iterate(iterator
, (void**)&certinfo
))
351 chunk_t
*request
= malloc_thing(chunk_t
);
353 *request
= build_request(this, certinfo
);
354 request_list
->insert_last(request_list
, (void*)request
);
355 datalen
+= request
->len
;
357 iterator
->destroy(iterator
);
360 iterator_t
*iterator
= request_list
->create_iterator(request_list
, TRUE
);
363 u_char
*pos
= build_asn1_object(&requestList
, ASN1_SEQUENCE
, datalen
);
365 while (iterator
->iterate(iterator
, (void**)&request
))
367 memcpy(pos
, request
->ptr
, request
->len
);
372 iterator
->destroy(iterator
);
373 request_list
->destroy(request_list
);
379 * build nonce extension (into requestExtensions)
381 static chunk_t
build_nonce_extension(private_ocsp_t
*this)
383 randomizer_t
*randomizer
= randomizer_create();
385 /* generate a random nonce */
386 randomizer
->allocate_pseudo_random_bytes(randomizer
, NONCE_LENGTH
, &this->nonce
);
387 randomizer
->destroy(randomizer
);
389 return asn1_wrap(ASN1_SEQUENCE
, "cm",
391 asn1_simple_object(ASN1_OCTET_STRING
, this->nonce
));
395 * build requestExtensions (into TBSRequest)
397 static chunk_t
build_request_ext(private_ocsp_t
*this)
399 return asn1_wrap(ASN1_CONTEXT_C_2
, "m",
400 asn1_wrap(ASN1_SEQUENCE
, "mm",
401 build_nonce_extension(this),
402 asn1_wrap(ASN1_SEQUENCE
, "cc",
404 ASN1_response_content
411 * build TBSRequest (into OCSPRequest)
413 static chunk_t
build_tbs_request(private_ocsp_t
*this, bool has_requestor_cert
)
415 /* version is skipped since the default is ok */
416 return asn1_wrap(ASN1_SEQUENCE
, "mmm",
417 (has_requestor_cert
)?
build_requestor_name(this): chunk_empty
,
418 build_request_list(this),
419 build_request_ext(this));
423 * build signature into ocsp request
424 * gets built only if a request cert with a corresponding private key is found
426 static chunk_t
build_signature(private_ocsp_t
*this, chunk_t tbsRequest
)
433 * assembles an ocsp request and sets the nonce field in private_ocsp_t to the sent nonce
435 static chunk_t
ocsp_build_request(private_ocsp_t
*this)
437 bool has_requestor_cert
;
438 chunk_t keyid
= this->cacert
->get_keyid(this->cacert
);
439 chunk_t tbsRequest
, signature
;
441 DBG2("assembling ocsp request");
442 DBG2("issuer: '%D'", this->cacert
->get_subject(this->cacert
));
443 DBG2("keyid: %#B", &keyid
);
445 /* looks for requestor cert and matching private key */
446 has_requestor_cert
= FALSE
;
448 /* TODO has_requestor_cert = get_ocsp_requestor_cert(location); */
451 tbsRequest
= build_tbs_request(this, has_requestor_cert
);
453 /* sign tbsReuqest */
454 signature
= (has_requestor_cert
)?
build_signature(this, tbsRequest
): chunk_empty
;
456 return asn1_wrap(ASN1_SEQUENCE
, "mm",
464 * parse a basic OCSP response
466 static bool ocsp_parse_basic_response(chunk_t blob
, int level0
, response_t
*res
)
468 u_int level
, version
;
469 u_int extn_oid
= OID_UNKNOWN
;
475 asn1_init(&ctx
, blob
, level0
, FALSE
, FALSE
);
477 while (objectID
< BASIC_RESPONSE_ROOF
)
479 if (!extract_object(basicResponseObjects
, &objectID
, &object
, &level
, &ctx
))
486 case BASIC_RESPONSE_TBS_DATA
:
489 case BASIC_RESPONSE_VERSION
:
490 version
= (object
.len
)?
(1 + (u_int
)*object
.ptr
) : 1;
491 if (version
!= OCSP_BASIC_RESPONSE_VERSION
)
493 DBG1("wrong ocsp basic response version (version= %i)", version
);
497 case BASIC_RESPONSE_ID_BY_NAME
:
498 res
->responder_id_name
= identification_create_from_encoding(ID_DER_ASN1_DN
, object
);
499 DBG2(" '%D'", res
->responder_id_name
);
501 case BASIC_RESPONSE_ID_BY_KEY
:
502 res
->responder_id_key
= object
;
504 case BASIC_RESPONSE_PRODUCED_AT
:
505 res
->produced_at
= asn1totime(&object
, ASN1_GENERALIZEDTIME
);
507 case BASIC_RESPONSE_RESPONSES
:
508 res
->responses
= object
;
510 case BASIC_RESPONSE_EXT_ID
:
511 extn_oid
= known_oid(object
);
513 case BASIC_RESPONSE_CRITICAL
:
514 critical
= object
.len
&& *object
.ptr
;
515 DBG2(" %s", critical?
"TRUE" : "FALSE");
517 case BASIC_RESPONSE_EXT_VALUE
:
518 if (extn_oid
== OID_NONCE
)
521 case BASIC_RESPONSE_ALGORITHM
:
522 res
->algorithm
= parse_algorithmIdentifier(object
, level
+1, NULL
);
524 case BASIC_RESPONSE_SIGNATURE
:
525 res
->signature
= object
;
527 case BASIC_RESPONSE_CERTIFICATE
:
529 chunk_t blob
= chunk_clone(object
);
531 res
->responder_cert
= x509_create_from_chunk(blob
, level
+1);
541 * parse an ocsp response and return the result as a response_t struct
543 static response_status
ocsp_parse_response(response_t
*res
)
550 response_status rStatus
= STATUS_INTERNALERROR
;
551 u_int ocspResponseType
= OID_UNKNOWN
;
553 asn1_init(&ctx
, res
->chunk
, 0, FALSE
, FALSE
);
555 while (objectID
< OCSP_RESPONSE_ROOF
)
557 if (!extract_object(ocspResponseObjects
, &objectID
, &object
, &level
, &ctx
))
559 return STATUS_INTERNALERROR
;
564 case OCSP_RESPONSE_STATUS
:
565 rStatus
= (response_status
) *object
.ptr
;
566 DBG2(" '%N'", response_status_names
, rStatus
);
570 case STATUS_SUCCESSFUL
:
572 case STATUS_MALFORMEDREQUEST
:
573 case STATUS_INTERNALERROR
:
574 case STATUS_TRYLATER
:
575 case STATUS_SIGREQUIRED
:
576 case STATUS_UNAUTHORIZED
:
577 DBG1("unsuccessful ocsp response: server said '%N'",
578 response_status_names
, rStatus
);
581 return STATUS_INTERNALERROR
;
584 case OCSP_RESPONSE_TYPE
:
585 ocspResponseType
= known_oid(object
);
589 switch (ocspResponseType
)
592 if (!ocsp_parse_basic_response(object
, level
+1, res
))
594 return STATUS_INTERNALERROR
;
598 DBG1("ocsp response is not of type BASIC");
599 DBG1("ocsp response OID: %#B", &object
);
600 return STATUS_INTERNALERROR
;
611 * Check if the OCSP response has a valid signature
613 static bool ocsp_valid_response(response_t
*res
, x509_t
*ocsp_cert
)
615 rsa_public_key_t
*public_key
;
616 time_t until
= UNDEFINED_TIME
;
619 DBG2("verifying ocsp response signature:");
620 DBG2("signer: '%D'", ocsp_cert
->get_subject(ocsp_cert
));
621 DBG2("issuer: '%D'", ocsp_cert
->get_issuer(ocsp_cert
));
623 ugh
= ocsp_cert
->is_valid(ocsp_cert
, &until
);
626 DBG1("ocsp signer certificate %s", ugh
);
629 public_key
= ocsp_cert
->get_public_key(ocsp_cert
);
631 return public_key
->verify_emsa_pkcs1_signature(public_key
, res
->tbs
, res
->signature
) == SUCCESS
;
635 * parse a single OCSP response
637 static bool ocsp_parse_single_response(private_ocsp_t
*this, chunk_t blob
, int level0
)
639 u_int level
, extn_oid
;
645 certinfo_t
*certinfo
= NULL
;
647 asn1_init(&ctx
, blob
, level0
, FALSE
, FALSE
);
649 while (objectID
< SINGLE_RESPONSE_ROOF
)
651 if (!extract_object(singleResponseObjects
, &objectID
, &object
, &level
, &ctx
))
658 case SINGLE_RESPONSE_ALGORITHM
:
659 if (parse_algorithmIdentifier(object
, level
+1, NULL
) != OID_SHA1
)
661 DBG1("only sha-1 hash supported in ocsp single response");
665 case SINGLE_RESPONSE_ISSUER_NAME_HASH
:
666 if (!chunk_equals(object
, this->authNameID
))
668 DBG1("ocsp single response has wrong issuer name hash");
672 case SINGLE_RESPONSE_ISSUER_KEY_HASH
:
673 if (!chunk_equals(object
, this->authKeyID
))
675 DBG1("ocsp single response has wrong issuer key hash");
679 case SINGLE_RESPONSE_SERIAL_NUMBER
:
681 iterator_t
*iterator
= this->certinfos
->create_iterator(this->certinfos
, TRUE
);
682 certinfo_t
*current_certinfo
;
684 while (iterator
->iterate(iterator
, (void**)¤t_certinfo
))
686 if (chunk_equals(object
, current_certinfo
->get_serialNumber(current_certinfo
)))
688 certinfo
= current_certinfo
;
691 iterator
->destroy(iterator
);
692 if (certinfo
== NULL
)
694 DBG1("unrequested serial number in ocsp single response");
699 case SINGLE_RESPONSE_CERT_STATUS_GOOD
:
700 certinfo
->set_status(certinfo
, CERT_GOOD
);
702 case SINGLE_RESPONSE_CERT_STATUS_REVOKED
:
703 certinfo
->set_status(certinfo
, CERT_REVOKED
);
705 case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME
:
706 certinfo
->set_revocationTime(certinfo
,
707 asn1totime(&object
, ASN1_GENERALIZEDTIME
));
709 case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON
:
710 certinfo
->set_revocationReason(certinfo
,
711 (object
.len
== 1) ?
*object
.ptr
: REASON_UNSPECIFIED
);
713 case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN
:
714 certinfo
->set_status(certinfo
, CERT_UNKNOWN
);
716 case SINGLE_RESPONSE_THIS_UPDATE
:
717 certinfo
->set_thisUpdate(certinfo
,
718 asn1totime(&object
, ASN1_GENERALIZEDTIME
));
720 case SINGLE_RESPONSE_NEXT_UPDATE
:
721 certinfo
->set_nextUpdate(certinfo
,
722 asn1totime(&object
, ASN1_GENERALIZEDTIME
));
724 case SINGLE_RESPONSE_EXT_ID
:
725 extn_oid
= known_oid(object
);
727 case SINGLE_RESPONSE_CRITICAL
:
728 critical
= object
.len
&& *object
.ptr
;
729 DBG2(" %s", critical ?
"TRUE" : "FALSE");
730 case SINGLE_RESPONSE_EXT_VALUE
:
739 * verify and process ocsp response and update the ocsp cache
741 static void ocsp_process_response(private_ocsp_t
*this, response_t
*res
, credential_store_t
*credentials
)
743 x509_t
*ocsp_cert
= NULL
;
745 /* parse the ocsp response without looking at the single responses yet */
746 response_status status
= ocsp_parse_response(res
);
748 if (status
!= STATUS_SUCCESSFUL
)
750 DBG1("error in ocsp response");
754 /* check if there was a nonce in the request */
755 if (this->nonce
.ptr
!= NULL
&& res
->nonce
.ptr
== NULL
)
757 DBG1("ocsp response contains no nonce, replay attack possible");
760 /* check if the nonces are identical */
761 if (res
->nonce
.ptr
!= NULL
&& !chunk_equals(res
->nonce
, this->nonce
))
763 DBG1("invalid nonce in ocsp response");
767 /* check if we received a trusted responder certificate */
768 if (res
->responder_cert
)
770 if (res
->responder_cert
->is_ocsp_signer(res
->responder_cert
))
772 DBG2("received certificate is ocsp signer");
773 if (credentials
->is_trusted(credentials
, res
->responder_cert
))
775 DBG1("received ocsp signer certificate is trusted");
776 ocsp_cert
= credentials
->add_auth_certificate(credentials
,
777 res
->responder_cert
, AUTH_OCSP
);
778 res
->responder_cert
= NULL
;
782 DBG1("received ocsp signer certificate is not trusted - rejected");
787 DBG1("received certificate is no ocsp signer - rejected");
791 /* if we didn't receive a trusted responder cert, search the credential store */
792 if (ocsp_cert
== NULL
)
794 ocsp_cert
= credentials
->get_auth_certificate(credentials
,
795 AUTH_OCSP
|AUTH_CA
, res
->responder_id_name
);
796 if (ocsp_cert
== NULL
)
798 DBG1("no ocsp signer certificate found");
803 /* check the response signature */
804 if (!ocsp_valid_response(res
, ocsp_cert
))
806 DBG1("ocsp response signature is invalid");
809 DBG2("ocsp response signature is valid");
811 /* now parse the single responses one at a time */
818 asn1_init(&ctx
, res
->responses
, 0, FALSE
, FALSE
);
820 while (objectID
< RESPONSES_ROOF
)
822 if (!extract_object(responsesObjects
, &objectID
, &object
, &level
, &ctx
))
826 if (objectID
== RESPONSES_SINGLE_RESPONSE
)
828 ocsp_parse_single_response(this, object
, level
+1);
836 * Implements ocsp_t.fetch.
838 static void fetch(private_ocsp_t
*this, certinfo_t
*certinfo
, credential_store_t
*credentials
)
841 response_t
*response
= NULL
;
843 if (this->uris
->get_count(this->uris
) == 0)
847 this->certinfos
->insert_last(this->certinfos
, (void*)certinfo
);
849 request
= ocsp_build_request(this);
850 DBG3("ocsp request: %B", &request
);
852 iterator_t
*iterator
= this->uris
->create_iterator(this->uris
, TRUE
);
853 identification_t
*uri
;
855 while (iterator
->iterate(iterator
, (void**)&uri
))
858 char uri_string
[BUF_LEN
];
859 chunk_t uri_chunk
= uri
->get_encoding(uri
);
860 chunk_t response_chunk
;
862 snprintf(uri_string
, BUF_LEN
, "%.*s", uri_chunk
.len
, uri_chunk
.ptr
);
863 fetcher
= fetcher_create(uri_string
);
865 response_chunk
= fetcher
->post(fetcher
, "application/ocsp-request", request
);
866 fetcher
->destroy(fetcher
);
867 if (response_chunk
.ptr
!= NULL
)
869 response
= response_create_from_chunk(response_chunk
);
873 iterator
->destroy(iterator
);
877 if (response
== NULL
)
881 DBG3("ocsp response: %B", &response
->chunk
);
882 ocsp_process_response(this, response
, credentials
);
883 response
->destroy(response
);
887 * Implements ocsp_t.destroy.
889 static void destroy(private_ocsp_t
*this)
891 this->certinfos
->destroy(this->certinfos
);
892 free(this->authNameID
.ptr
);
893 free(this->nonce
.ptr
);
898 * Described in header.
900 ocsp_t
*ocsp_create(x509_t
*cacert
, linked_list_t
*uris
)
902 private_ocsp_t
*this = malloc_thing(private_ocsp_t
);
905 this->cacert
= cacert
;
907 this->certinfos
= linked_list_create();
908 this->nonce
= chunk_empty
;
909 this->authKeyID
= cacert
->get_subjectKeyID(cacert
);
911 hasher_t
*hasher
= hasher_create(HASH_SHA1
);
912 identification_t
*issuer
= cacert
->get_subject(cacert
);
914 hasher
->allocate_hash(hasher
, issuer
->get_encoding(issuer
),
916 hasher
->destroy(hasher
);
919 /* public functions */
920 this->public.fetch
= (void (*) (ocsp_t
*,certinfo_t
*,credential_store_t
*))fetch
;
921 this->public.destroy
= (void (*) (ocsp_t
*))destroy
;
923 return &this->public;