added ocsp_parse_single_response
[strongswan.git] / src / libstrongswan / crypto / ocsp.c
1 /**
2 * @file ocsp.c
3 *
4 * @brief Implementation of ocsp_t.
5 *
6 */
7
8 /* Support of the Online Certificate Status Protocol (OCSP)
9 * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen
10 * Zuercher Hochschule Winterthur
11 *
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>.
16 *
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
20 * for more details.
21 *
22 */
23
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <time.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32
33 #include <asn1/oid.h>
34 #include <asn1/asn1.h>
35 #include <utils/identification.h>
36 #include <utils/randomizer.h>
37 #include <utils/fetcher.h>
38 #include <debug.h>
39
40 #include "hashers/hasher.h"
41 #include "certinfo.h"
42 #include "x509.h"
43 #include "ocsp.h"
44
45 #define NONCE_LENGTH 16
46
47 typedef struct private_ocsp_t private_ocsp_t;
48
49 /**
50 * Private data of a ocsp_t object.
51 */
52 struct private_ocsp_t {
53 /**
54 * Public interface for this ocsp object.
55 */
56 ocsp_t public;
57
58 /**
59 * CA certificate.
60 */
61 x509_t *cacert;
62
63 /**
64 * Requestor certificate
65 */
66 x509_t *requestor_cert;
67
68 /**
69 * Linked list of ocsp uris
70 */
71 linked_list_t *uris;
72
73 /**
74 * Linked list of certinfos to be requested
75 */
76 linked_list_t *certinfos;
77
78 /**
79 * Nonce required for ocsp request and response
80 */
81 chunk_t nonce;
82
83 /**
84 * SHA-1 hash over issuer distinguished name
85 */
86 chunk_t authNameID;
87 };
88
89 ENUM(response_status_names, STATUS_SUCCESSFUL, STATUS_UNAUTHORIZED,
90 "successful",
91 "malformed request",
92 "internal error",
93 "try later",
94 "signature required",
95 "unauthorized"
96 );
97
98 /* response container */
99 typedef struct response_t response_t;
100
101 struct response_t {
102 chunk_t tbs;
103 identification_t *responder_id_name;
104 chunk_t responder_id_key;
105 time_t produced_at;
106 chunk_t responses;
107 chunk_t nonce;
108 int algorithm;
109 chunk_t signature;
110 };
111
112 const response_t empty_response = {
113 { NULL, 0 } , /* tbs */
114 NULL , /* responder_id_name */
115 { NULL, 0 } , /* responder_id_key */
116 UNDEFINED_TIME, /* produced_at */
117 { NULL, 0 } , /* single_response */
118 { NULL, 0 } , /* nonce */
119 OID_UNKNOWN , /* signature_algorithm */
120 { NULL, 0 } /* signature */
121 };
122
123 /* single response container */
124 typedef struct single_response single_response_t;
125
126 struct single_response {
127 single_response_t *next;
128 int hash_algorithm;
129 chunk_t issuer_name_hash;
130 chunk_t issuer_key_hash;
131 chunk_t serialNumber;
132 cert_status_t status;
133 time_t revocationTime;
134 crl_reason_t revocationReason;
135 time_t thisUpdate;
136 time_t nextUpdate;
137 };
138
139 const single_response_t empty_single_response = {
140 NULL , /* *next */
141 OID_UNKNOWN , /* hash_algorithm */
142 { NULL, 0 } , /* issuer_name_hash */
143 { NULL, 0 } , /* issuer_key_hash */
144 { NULL, 0 } , /* serial_number */
145 CERT_UNDEFINED , /* status */
146 UNDEFINED_TIME , /* revocationTime */
147 REASON_UNSPECIFIED, /* revocationReason */
148 UNDEFINED_TIME , /* this_update */
149 UNDEFINED_TIME /* next_update */
150 };
151
152 /* some OCSP specific prefabricated ASN.1 constants */
153
154 static u_char ASN1_nonce_oid_str[] = {
155 0x06, 0x09,
156 0x2B, 0x06,
157 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02
158 };
159
160 static u_char ASN1_response_oid_str[] = {
161 0x06, 0x09,
162 0x2B, 0x06,
163 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04
164 };
165
166 static u_char ASN1_response_content_str[] = {
167 0x04, 0x0D,
168 0x30, 0x0B,
169 0x06, 0x09,
170 0x2B, 0x06,
171 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
172 };
173
174 static const chunk_t ASN1_nonce_oid = chunk_from_buf(ASN1_nonce_oid_str);
175 static const chunk_t ASN1_response_oid = chunk_from_buf(ASN1_response_oid_str);
176 static const chunk_t ASN1_response_content = chunk_from_buf(ASN1_response_content_str);
177
178 /* asn.1 definitions for parsing */
179
180 static const asn1Object_t ocspResponseObjects[] = {
181 { 0, "OCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
182 { 1, "responseStatus", ASN1_ENUMERATED, ASN1_BODY }, /* 1 */
183 { 1, "responseBytesContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 2 */
184 { 2, "responseBytes", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */
185 { 3, "responseType", ASN1_OID, ASN1_BODY }, /* 4 */
186 { 3, "response", ASN1_OCTET_STRING, ASN1_BODY }, /* 5 */
187 { 1, "end opt", ASN1_EOC, ASN1_END } /* 6 */
188 };
189
190 #define OCSP_RESPONSE_STATUS 1
191 #define OCSP_RESPONSE_TYPE 4
192 #define OCSP_RESPONSE 5
193 #define OCSP_RESPONSE_ROOF 7
194
195 static const asn1Object_t basicResponseObjects[] = {
196 { 0, "BasicOCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
197 { 1, "tbsResponseData", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
198 { 2, "versionContext", ASN1_CONTEXT_C_0, ASN1_NONE |
199 ASN1_DEF }, /* 2 */
200 { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */
201 { 2, "responderIdContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 4 */
202 { 3, "responderIdByName", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
203 { 2, "end choice", ASN1_EOC, ASN1_END }, /* 6 */
204 { 2, "responderIdContext", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 7 */
205 { 3, "responderIdByKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 8 */
206 { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */
207 { 2, "producedAt", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 10 */
208 { 2, "responses", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */
209 { 2, "responseExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 12 */
210 { 3, "responseExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 13 */
211 { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 14 */
212 { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 15 */
213 { 5, "critical", ASN1_BOOLEAN, ASN1_BODY |
214 ASN1_DEF }, /* 16 */
215 { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 17 */
216 { 4, "end loop", ASN1_EOC, ASN1_END }, /* 18 */
217 { 2, "end opt", ASN1_EOC, ASN1_END }, /* 19 */
218 { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 20 */
219 { 1, "signature", ASN1_BIT_STRING, ASN1_BODY }, /* 21 */
220 { 1, "certsContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 22 */
221 { 2, "certs", ASN1_SEQUENCE, ASN1_LOOP }, /* 23 */
222 { 3, "certificate", ASN1_SEQUENCE, ASN1_RAW }, /* 24 */
223 { 2, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
224 { 1, "end opt", ASN1_EOC, ASN1_END } /* 26 */
225 };
226
227 #define BASIC_RESPONSE_TBS_DATA 1
228 #define BASIC_RESPONSE_VERSION 3
229 #define BASIC_RESPONSE_ID_BY_NAME 5
230 #define BASIC_RESPONSE_ID_BY_KEY 8
231 #define BASIC_RESPONSE_PRODUCED_AT 10
232 #define BASIC_RESPONSE_RESPONSES 11
233 #define BASIC_RESPONSE_EXT_ID 15
234 #define BASIC_RESPONSE_CRITICAL 16
235 #define BASIC_RESPONSE_EXT_VALUE 17
236 #define BASIC_RESPONSE_ALGORITHM 20
237 #define BASIC_RESPONSE_SIGNATURE 21
238 #define BASIC_RESPONSE_CERTIFICATE 24
239 #define BASIC_RESPONSE_ROOF 27
240
241 static const asn1Object_t responsesObjects[] = {
242 { 0, "responses", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
243 { 1, "singleResponse", ASN1_EOC, ASN1_RAW }, /* 1 */
244 { 0, "end loop", ASN1_EOC, ASN1_END } /* 2 */
245 };
246
247 #define RESPONSES_SINGLE_RESPONSE 1
248 #define RESPONSES_ROOF 3
249
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 |
276 ASN1_DEF }, /* 24 */
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 };
281
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
296 #define SINGLE_RESPONSE_ROOF 28
297
298 /**
299 * build requestorName (into TBSRequest)
300 */
301 static chunk_t build_requestor_name(private_ocsp_t *this)
302 {
303 identification_t *requestor_name = this->requestor_cert->get_subject(this->requestor_cert);
304
305 return asn1_wrap(ASN1_CONTEXT_C_1, "m",
306 asn1_simple_object(ASN1_CONTEXT_C_4,
307 requestor_name->get_encoding(requestor_name)));
308 }
309
310 /**
311 * build request (into requestList)
312 * no singleRequestExtensions used
313 */
314 static chunk_t build_request(private_ocsp_t *this, certinfo_t *certinfo)
315 {
316 chunk_t authKeyID = this->cacert->get_subjectKeyID(this->cacert);
317 chunk_t serialNumber = certinfo->get_serialNumber(certinfo);
318
319 chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "cmmm",
320 ASN1_sha1_id,
321 asn1_simple_object(ASN1_OCTET_STRING, this->authNameID),
322 asn1_simple_object(ASN1_OCTET_STRING, authKeyID),
323 asn1_simple_object(ASN1_INTEGER, serialNumber));
324
325 return asn1_wrap(ASN1_SEQUENCE, "m", reqCert);
326 }
327
328 /**
329 * build requestList (into TBSRequest)
330 */
331 static chunk_t build_request_list(private_ocsp_t *this)
332 {
333 chunk_t requestList;
334 size_t datalen = 0;
335 linked_list_t *request_list = linked_list_create();
336
337 {
338 iterator_t *iterator = this->certinfos->create_iterator(this->certinfos, TRUE);
339 certinfo_t *certinfo;
340
341 while (iterator->iterate(iterator, (void**)&certinfo))
342 {
343 chunk_t *request = malloc_thing(chunk_t);
344
345 *request = build_request(this, certinfo);
346 request_list->insert_last(request_list, (void*)request);
347 datalen += request->len;
348 }
349 iterator->destroy(iterator);
350 }
351 {
352 iterator_t *iterator = request_list->create_iterator(request_list, TRUE);
353 chunk_t *request;
354
355 u_char *pos = build_asn1_object(&requestList, ASN1_SEQUENCE, datalen);
356
357 while (iterator->iterate(iterator, (void**)&request))
358 {
359 memcpy(pos, request->ptr, request->len);
360 pos += request->len;
361 free(request->ptr);
362 free(request);
363 }
364 iterator->destroy(iterator);
365 request_list->destroy(request_list);
366 }
367 return requestList;
368 }
369
370 /**
371 * build nonce extension (into requestExtensions)
372 */
373 static chunk_t build_nonce_extension(private_ocsp_t *this)
374 {
375 randomizer_t *randomizer = randomizer_create();
376
377 /* generate a random nonce */
378 randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_LENGTH, &this->nonce);
379 randomizer->destroy(randomizer);
380
381 return asn1_wrap(ASN1_SEQUENCE, "cm",
382 ASN1_nonce_oid,
383 asn1_simple_object(ASN1_OCTET_STRING, this->nonce));
384 }
385
386 /**
387 * build requestExtensions (into TBSRequest)
388 */
389 static chunk_t build_request_ext(private_ocsp_t *this)
390 {
391 return asn1_wrap(ASN1_CONTEXT_C_2, "m",
392 asn1_wrap(ASN1_SEQUENCE, "mm",
393 build_nonce_extension(this),
394 asn1_wrap(ASN1_SEQUENCE, "cc",
395 ASN1_response_oid,
396 ASN1_response_content
397 )
398 )
399 );
400 }
401
402 /**
403 * build TBSRequest (into OCSPRequest)
404 */
405 static chunk_t build_tbs_request(private_ocsp_t *this, bool has_requestor_cert)
406 {
407 /* version is skipped since the default is ok */
408 return asn1_wrap(ASN1_SEQUENCE, "mmm",
409 (has_requestor_cert)? build_requestor_name(this): chunk_empty,
410 build_request_list(this),
411 build_request_ext(this));
412 }
413
414 /**
415 * build signature into ocsp request
416 * gets built only if a request cert with a corresponding private key is found
417 */
418 static chunk_t build_signature(private_ocsp_t *this, chunk_t tbsRequest)
419 {
420 /* TODO */
421 return chunk_empty;
422 }
423
424 /**
425 * assembles an ocsp request and sets the nonce field in private_ocsp_t to the sent nonce
426 */
427 static chunk_t ocsp_build_request(private_ocsp_t *this)
428 {
429 bool has_requestor_cert;
430 chunk_t keyid = this->cacert->get_keyid(this->cacert);
431 chunk_t tbsRequest, signature;
432
433 DBG2("assembling ocsp request");
434 DBG2("issuer: '%D'", this->cacert->get_subject(this->cacert));
435 DBG2("keyid: %#B", &keyid);
436
437 /* looks for requestor cert and matching private key */
438 has_requestor_cert = FALSE;
439
440 /* TODO has_requestor_cert = get_ocsp_requestor_cert(location); */
441
442 /* build content */
443 tbsRequest = build_tbs_request(this, has_requestor_cert);
444
445 /* sign tbsReuqest */
446 signature = (has_requestor_cert)? build_signature(this, tbsRequest): chunk_empty;
447
448 return asn1_wrap(ASN1_SEQUENCE, "mm",
449 tbsRequest,
450 signature);
451
452 return signature;
453 }
454
455 /**
456 * Check if the OCSP response has a valid signature
457 */
458 static bool ocsp_valid_response(response_t *res)
459 {
460 /* TODO */
461 return FALSE;
462 }
463
464 /**
465 * parse a basic OCSP response
466 */
467 static bool ocsp_parse_basic_response(chunk_t blob, int level0, response_t *res)
468 {
469 u_int level, version;
470 u_int extn_oid = OID_UNKNOWN;
471 u_char buf[BUF_LEN];
472 asn1_ctx_t ctx;
473 bool critical;
474 chunk_t object;
475 int objectID = 0;
476
477 asn1_init(&ctx, blob, level0, FALSE, FALSE);
478
479 while (objectID < BASIC_RESPONSE_ROOF)
480 {
481 if (!extract_object(basicResponseObjects, &objectID, &object, &level, &ctx))
482 {
483 return FALSE;
484 }
485
486 switch (objectID)
487 {
488 case BASIC_RESPONSE_TBS_DATA:
489 res->tbs = object;
490 break;
491 case BASIC_RESPONSE_VERSION:
492 version = (object.len)? (1 + (u_int)*object.ptr) : 1;
493 if (version != OCSP_BASIC_RESPONSE_VERSION)
494 {
495 DBG1("wrong ocsp basic response version (version= %i)", version);
496 return FALSE;
497 }
498 break;
499 case BASIC_RESPONSE_ID_BY_NAME:
500 res->responder_id_name = identification_create_from_encoding(ID_DER_ASN1_DN, object);
501 DBG2(" '%D'", res->responder_id_name);
502 break;
503 case BASIC_RESPONSE_ID_BY_KEY:
504 res->responder_id_key = object;
505 break;
506 case BASIC_RESPONSE_PRODUCED_AT:
507 res->produced_at = asn1totime(&object, ASN1_GENERALIZEDTIME);
508 break;
509 case BASIC_RESPONSE_RESPONSES:
510 res->responses = object;
511 break;
512 case BASIC_RESPONSE_EXT_ID:
513 extn_oid = known_oid(object);
514 break;
515 case BASIC_RESPONSE_CRITICAL:
516 critical = object.len && *object.ptr;
517 DBG2(" %s", critical? "TRUE" : "FALSE");
518 break;
519 case BASIC_RESPONSE_EXT_VALUE:
520 if (extn_oid == OID_NONCE)
521 res->nonce = object;
522 break;
523 case BASIC_RESPONSE_ALGORITHM:
524 res->algorithm = parse_algorithmIdentifier(object, level+1, NULL);
525 break;
526 case BASIC_RESPONSE_SIGNATURE:
527 res->signature = object;
528 break;
529 case BASIC_RESPONSE_CERTIFICATE:
530 {
531 chunk_t blob = chunk_clone(object);
532 x509_t *cert = x509_create_from_chunk(blob, level+1);
533
534 if (cert == NULL)
535 {
536 break;
537 }
538 if (cert->is_ocsp_signer(cert))
539 {
540 DBG2("received OCSP signer certificate");
541 cert->destroy(cert);
542 /* TODO trust_authcert_candidate(cert, NULL))
543 add_authcert(cert, AUTH_OCSP); */
544 }
545 else
546 {
547 DBG1("embedded ocsp certificate rejected");
548 cert->destroy(cert);
549 }
550 }
551 break;
552 }
553 objectID++;
554 }
555 return TRUE;
556 }
557
558 /**
559 * parse an ocsp response and return the result as a response_t struct
560 */
561 static response_status ocsp_parse_response(chunk_t blob, response_t * res)
562 {
563 asn1_ctx_t ctx;
564 chunk_t object;
565 u_int level;
566 int objectID = 0;
567
568 response_status rStatus = STATUS_INTERNALERROR;
569 u_int ocspResponseType = OID_UNKNOWN;
570
571 asn1_init(&ctx, blob, 0, FALSE, FALSE);
572
573 while (objectID < OCSP_RESPONSE_ROOF)
574 {
575 if (!extract_object(ocspResponseObjects, &objectID, &object, &level, &ctx))
576 {
577 return STATUS_INTERNALERROR;
578 }
579
580 switch (objectID)
581 {
582 case OCSP_RESPONSE_STATUS:
583 rStatus = (response_status) *object.ptr;
584 DBG2(" '%N'", response_status_names, rStatus);
585
586 switch (rStatus)
587 {
588 case STATUS_SUCCESSFUL:
589 break;
590 case STATUS_MALFORMEDREQUEST:
591 case STATUS_INTERNALERROR:
592 case STATUS_TRYLATER:
593 case STATUS_SIGREQUIRED:
594 case STATUS_UNAUTHORIZED:
595 DBG1("unsuccessful ocsp response: server said '%N'",
596 response_status_names, rStatus);
597 return rStatus;
598 default:
599 return STATUS_INTERNALERROR;
600 }
601 break;
602 case OCSP_RESPONSE_TYPE:
603 ocspResponseType = known_oid(object);
604 break;
605 case OCSP_RESPONSE:
606 {
607 switch (ocspResponseType)
608 {
609 case OID_BASIC:
610 if (!ocsp_parse_basic_response(object, level+1, res))
611 {
612 return STATUS_INTERNALERROR;
613 }
614 break;
615 default:
616 DBG1("ocsp response is not of type BASIC");
617 DBG1("ocsp response OID: %#B", &object);
618 return STATUS_INTERNALERROR;
619 }
620 }
621 break;
622 }
623 objectID++;
624 }
625 return rStatus;
626 }
627
628 /**
629 * parse a single OCSP response
630 */
631 static bool ocsp_parse_single_response(chunk_t blob, int level0, single_response_t *sres)
632 {
633 u_int level, extn_oid;
634 asn1_ctx_t ctx;
635 bool critical;
636 chunk_t object;
637 int objectID = 0;
638
639 asn1_init(&ctx, blob, level0, FALSE, FALSE);
640
641 while (objectID < SINGLE_RESPONSE_ROOF)
642 {
643 if (!extract_object(singleResponseObjects, &objectID, &object, &level, &ctx))
644 {
645 return FALSE;
646 }
647
648 switch (objectID)
649 {
650 case SINGLE_RESPONSE_ALGORITHM:
651 sres->hash_algorithm = parse_algorithmIdentifier(object, level+1, NULL);
652 break;
653 case SINGLE_RESPONSE_ISSUER_NAME_HASH:
654 sres->issuer_name_hash = object;
655 break;
656 case SINGLE_RESPONSE_ISSUER_KEY_HASH:
657 sres->issuer_key_hash = object;
658 break;
659 case SINGLE_RESPONSE_SERIAL_NUMBER:
660 sres->serialNumber = object;
661 break;
662 case SINGLE_RESPONSE_CERT_STATUS_GOOD:
663 sres->status = CERT_GOOD;
664 break;
665 case SINGLE_RESPONSE_CERT_STATUS_REVOKED:
666 sres->status = CERT_REVOKED;
667 break;
668 case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME:
669 sres->revocationTime = asn1totime(&object, ASN1_GENERALIZEDTIME);
670 break;
671 case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON:
672 sres->revocationReason = (object.len == 1)
673 ? *object.ptr : REASON_UNSPECIFIED;
674 break;
675 case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN:
676 sres->status = CERT_UNKNOWN;
677 break;
678 case SINGLE_RESPONSE_THIS_UPDATE:
679 sres->thisUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME);
680 break;
681 case SINGLE_RESPONSE_NEXT_UPDATE:
682 sres->nextUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME);
683 break;
684 case SINGLE_RESPONSE_EXT_ID:
685 extn_oid = known_oid(object);
686 break;
687 case SINGLE_RESPONSE_CRITICAL:
688 critical = object.len && *object.ptr;
689 DBG2(" %s", critical ? "TRUE" : "FALSE");
690 case SINGLE_RESPONSE_EXT_VALUE:
691 break;
692 }
693 objectID++;
694 }
695 return TRUE;
696 }
697
698 /**
699 * process received ocsp single response and add it to ocsp cache
700 */
701 static void process_single_response(private_ocsp_t *this, single_response_t *sres)
702 {
703 /* TODO */
704 }
705
706 /**
707 * verify and process ocsp response and update the ocsp cache
708 */
709 void ocsp_process_response(private_ocsp_t *this, chunk_t reply)
710 {
711 response_t res = empty_response;
712
713 /* parse the ocsp response without looking at the single responses yet */
714 response_status status = ocsp_parse_response(reply, &res);
715
716 if (status != STATUS_SUCCESSFUL)
717 {
718 DBG1("error in ocsp response");
719 return;
720 }
721
722 /* check if there was a nonce in the request */
723 if (this->nonce.ptr != NULL && res.nonce.ptr == NULL)
724 {
725 DBG1("ocsp response contains no nonce, replay attack possible");
726 }
727
728 /* check if the nonces are identical */
729 if (res.nonce.ptr != NULL && !chunk_equals(res.nonce, this->nonce))
730 {
731 DBG1("invalid nonce in ocsp response");
732 return;
733 }
734
735 /* check if the response is signed by a trusted key */
736 if (!ocsp_valid_response(&res))
737 {
738 DBG1("invalid ocsp response");
739 return;
740 }
741 DBG2("valid ocsp response");
742
743 /* now parse the single responses one at a time */
744 {
745 u_int level;
746 asn1_ctx_t ctx;
747 chunk_t object;
748 int objectID = 0;
749
750 asn1_init(&ctx, res.responses, 0, FALSE, FALSE);
751
752 while (objectID < RESPONSES_ROOF)
753 {
754 if (!extract_object(responsesObjects, &objectID, &object, &level, &ctx))
755 {
756 return;
757 }
758 if (objectID == RESPONSES_SINGLE_RESPONSE)
759 {
760 single_response_t sres = empty_single_response;
761
762 if (ocsp_parse_single_response(object, level+1, &sres))
763 {
764 process_single_response(this, &sres);
765 }
766 }
767 objectID++;
768 }
769 }
770 }
771
772 /**
773 * Implements ocsp_t.fetch.
774 */
775 static void fetch(private_ocsp_t *this, certinfo_t *certinfo)
776 {
777 chunk_t request;
778 chunk_t response;
779 bool fetched = FALSE;
780
781 if (this->uris->get_count(this->uris) == 0)
782 {
783 return;
784 }
785 this->certinfos->insert_last(this->certinfos, (void*)certinfo);
786
787 request = ocsp_build_request(this);
788 DBG3("ocsp request: %B", &request);
789 {
790 iterator_t *iterator = this->uris->create_iterator(this->uris, TRUE);
791 identification_t *uri;
792
793 while (iterator->iterate(iterator, (void**)&uri))
794 {
795 fetcher_t *fetcher;
796 char uri_string[BUF_LEN];
797 chunk_t uri_chunk = uri->get_encoding(uri);
798
799 snprintf(uri_string, BUF_LEN, "%.*s", uri_chunk.len, uri_chunk.ptr);
800 fetcher = fetcher_create(uri_string);
801
802 response = fetcher->post(fetcher, "application/ocsp-request", request);
803 fetcher->destroy(fetcher);
804 if (response.ptr != NULL)
805 {
806 fetched = TRUE;
807 break;
808 }
809 }
810 iterator->destroy(iterator);
811 }
812 free(request.ptr);
813
814 if (!fetched)
815 {
816 return;
817 }
818 DBG3("ocsp response: %B", &response);
819 ocsp_process_response(this, response);
820 free(response.ptr);
821 }
822
823 /**
824 * Implements ocsp_t.destroy.
825 */
826 static void destroy(private_ocsp_t *this)
827 {
828 this->certinfos->destroy(this->certinfos);
829 free(this->authNameID.ptr);
830 free(this->nonce.ptr);
831 free(this);
832 }
833
834 /*
835 * Described in header.
836 */
837 ocsp_t *ocsp_create(x509_t *cacert, linked_list_t *uris)
838 {
839 private_ocsp_t *this = malloc_thing(private_ocsp_t);
840
841 /* initialize */
842 this->cacert = cacert;
843 this->uris = uris;
844 this->certinfos = linked_list_create();
845 this->nonce = chunk_empty;
846 {
847 hasher_t *hasher = hasher_create(HASH_SHA1);
848 identification_t *issuer = cacert->get_subject(cacert);
849
850 hasher->allocate_hash(hasher, issuer->get_encoding(issuer),
851 &this->authNameID);
852 hasher->destroy(hasher);
853 }
854
855 /* public functions */
856 this->public.fetch = (void (*) (ocsp_t*,certinfo_t*))fetch;
857 this->public.destroy = (void (*) (ocsp_t*))destroy;
858
859 return &this->public;
860 }