]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/pluto/ocsp.c
Support different encoding types in certificate.get_encoding()
[thirdparty/strongswan.git] / src / pluto / ocsp.c
CommitLineData
997358a6
MW
1/* Support of the Online Certificate Status Protocol (OCSP)
2 * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen
7be566dc 3 * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
997358a6
MW
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
997358a6
MW
14 */
15
16#include <unistd.h>
17#include <stdlib.h>
18#include <string.h>
19#include <time.h>
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23
24#include <freeswan.h>
997358a6 25
bc2e33ca 26#include <library.h>
08b2d288
AS
27#include <asn1/asn1.h>
28#include <asn1/asn1_parser.h>
29#include <asn1/oid.h>
bc2e33ca 30#include <crypto/rngs/rng.h>
c08ae816 31#include <crypto/hashers/hasher.h>
08b2d288 32
997358a6
MW
33#include "constants.h"
34#include "defs.h"
35#include "log.h"
36#include "x509.h"
37#include "crl.h"
38#include "ca.h"
997358a6
MW
39#include "certs.h"
40#include "smartcard.h"
997358a6 41#include "whack.h"
997358a6
MW
42#include "keys.h"
43#include "fetch.h"
44#include "ocsp.h"
45
3d7a244b 46#define NONCE_LENGTH 16
997358a6
MW
47
48static const char *const cert_status_names[] = {
3d7a244b
AS
49 "good",
50 "revoked",
51 "unknown",
52 "undefined"
997358a6
MW
53};
54
55
56static const char *const response_status_names[] = {
3d7a244b
AS
57 "successful",
58 "malformed request",
59 "internal error",
60 "try later",
61 "status #4",
62 "signature required",
63 "unauthorized"
997358a6
MW
64};
65
66/* response container */
67typedef struct response response_t;
68
69struct response {
0354d570
AS
70 chunk_t tbs;
71 identification_t *responder_id_name;
72 chunk_t responder_id_key;
73 time_t produced_at;
74 chunk_t responses;
75 chunk_t nonce;
76 int algorithm;
77 chunk_t signature;
997358a6
MW
78};
79
80const response_t empty_response = {
3d7a244b 81 { NULL, 0 } , /* tbs */
0354d570 82 NULL , /* responder_id_name */
3d7a244b
AS
83 { NULL, 0 } , /* responder_id_key */
84 UNDEFINED_TIME, /* produced_at */
85 { NULL, 0 } , /* single_response */
86 { NULL, 0 } , /* nonce */
87 OID_UNKNOWN , /* signature_algorithm */
88 { NULL, 0 } /* signature */
997358a6
MW
89};
90
91/* single response container */
92typedef struct single_response single_response_t;
93
94struct single_response {
3d7a244b
AS
95 single_response_t *next;
96 int hash_algorithm;
97 chunk_t issuer_name_hash;
98 chunk_t issuer_key_hash;
99 chunk_t serialNumber;
100 cert_status_t status;
101 time_t revocationTime;
102 crl_reason_t revocationReason;
103 time_t thisUpdate;
104 time_t nextUpdate;
997358a6
MW
105};
106
107const single_response_t empty_single_response = {
f561d6f2
AS
108 NULL , /* *next */
109 OID_UNKNOWN , /* hash_algorithm */
110 { NULL, 0 } , /* issuer_name_hash */
111 { NULL, 0 } , /* issuer_key_hash */
112 { NULL, 0 } , /* serial_number */
113 CERT_UNDEFINED , /* status */
114 UNDEFINED_TIME , /* revocationTime */
115 CRL_REASON_UNSPECIFIED, /* revocationReason */
116 UNDEFINED_TIME , /* this_update */
117 UNDEFINED_TIME /* next_update */
997358a6
MW
118};
119
120
121/* list of single requests */
122typedef struct request_list request_list_t;
123struct request_list {
3d7a244b
AS
124 chunk_t request;
125 request_list_t *next;
997358a6
MW
126};
127
128/* some OCSP specific prefabricated ASN.1 constants */
3b878dae 129static const chunk_t ASN1_nonce_oid = chunk_from_chars(
3d7a244b 130 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02
3b878dae
MW
131);
132static const chunk_t ASN1_response_oid = chunk_from_chars(
3d7a244b 133 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04
3b878dae
MW
134);
135static const chunk_t ASN1_response_content = chunk_from_chars(
3d7a244b
AS
136 0x04, 0x0D,
137 0x30, 0x0B,
138 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
3b878dae 139);
997358a6
MW
140
141/* default OCSP uri */
142static chunk_t ocsp_default_uri;
143
144/* ocsp cache: pointer to first element */
145static ocsp_location_t *ocsp_cache = NULL;
146
147/* static temporary storage for ocsp requestor information */
f565d0c5 148static cert_t *ocsp_requestor_cert = NULL;
997358a6
MW
149
150static smartcard_t *ocsp_requestor_sc = NULL;
151
8b799d55 152static private_key_t *ocsp_requestor_key = NULL;
997358a6 153
08b2d288
AS
154/**
155 * ASN.1 definition of ocspResponse
156 */
997358a6 157static const asn1Object_t ocspResponseObjects[] = {
08b2d288
AS
158 { 0, "OCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
159 { 1, "responseStatus", ASN1_ENUMERATED, ASN1_BODY }, /* 1 */
160 { 1, "responseBytesContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 2 */
161 { 2, "responseBytes", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */
162 { 3, "responseType", ASN1_OID, ASN1_BODY }, /* 4 */
163 { 3, "response", ASN1_OCTET_STRING, ASN1_BODY }, /* 5 */
164 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 6 */
165 { 0, "exit", ASN1_EOC, ASN1_EXIT }
997358a6 166};
08b2d288
AS
167#define OCSP_RESPONSE_STATUS 1
168#define OCSP_RESPONSE_TYPE 4
169#define OCSP_RESPONSE 5
997358a6 170
08b2d288
AS
171/**
172 * ASN.1 definition of basicResponse
173 */
997358a6 174static const asn1Object_t basicResponseObjects[] = {
08b2d288
AS
175 { 0, "BasicOCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
176 { 1, "tbsResponseData", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
177 { 2, "versionContext", ASN1_CONTEXT_C_0, ASN1_NONE |
178 ASN1_DEF }, /* 2 */
179 { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */
180 { 2, "responderIdContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 4 */
181 { 3, "responderIdByName", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
182 { 2, "end choice", ASN1_EOC, ASN1_END }, /* 6 */
183 { 2, "responderIdContext", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 7 */
184 { 3, "responderIdByKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 8 */
185 { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */
186 { 2, "producedAt", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 10 */
187 { 2, "responses", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */
188 { 2, "responseExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 12 */
189 { 3, "responseExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 13 */
190 { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 14 */
191 { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 15 */
192 { 5, "critical", ASN1_BOOLEAN, ASN1_BODY |
193 ASN1_DEF }, /* 16 */
194 { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 17 */
195 { 4, "end loop", ASN1_EOC, ASN1_END }, /* 18 */
196 { 2, "end opt", ASN1_EOC, ASN1_END }, /* 19 */
197 { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 20 */
198 { 1, "signature", ASN1_BIT_STRING, ASN1_BODY }, /* 21 */
199 { 1, "certsContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 22 */
200 { 2, "certs", ASN1_SEQUENCE, ASN1_LOOP }, /* 23 */
201 { 3, "certificate", ASN1_SEQUENCE, ASN1_RAW }, /* 24 */
202 { 2, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
203 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 26 */
204 { 0, "exit", ASN1_EOC, ASN1_EXIT }
997358a6 205};
08b2d288
AS
206#define BASIC_RESPONSE_TBS_DATA 1
207#define BASIC_RESPONSE_VERSION 3
208#define BASIC_RESPONSE_ID_BY_NAME 5
209#define BASIC_RESPONSE_ID_BY_KEY 8
210#define BASIC_RESPONSE_PRODUCED_AT 10
211#define BASIC_RESPONSE_RESPONSES 11
212#define BASIC_RESPONSE_EXT_ID 15
213#define BASIC_RESPONSE_CRITICAL 16
214#define BASIC_RESPONSE_EXT_VALUE 17
215#define BASIC_RESPONSE_ALGORITHM 20
216#define BASIC_RESPONSE_SIGNATURE 21
217#define BASIC_RESPONSE_CERTIFICATE 24
218
219/**
220 * ASN.1 definition of responses
221 */
997358a6 222static const asn1Object_t responsesObjects[] = {
08b2d288
AS
223 { 0, "responses", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
224 { 1, "singleResponse", ASN1_EOC, ASN1_RAW }, /* 1 */
225 { 0, "end loop", ASN1_EOC, ASN1_END }, /* 2 */
226 { 0, "exit", ASN1_EOC, ASN1_EXIT }
997358a6 227};
08b2d288 228#define RESPONSES_SINGLE_RESPONSE 1
997358a6 229
08b2d288
AS
230/**
231 * ASN.1 definition of singleResponse
232 */
997358a6 233static const asn1Object_t singleResponseObjects[] = {
08b2d288
AS
234 { 0, "singleResponse", ASN1_SEQUENCE, ASN1_BODY }, /* 0 */
235 { 1, "certID", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
236 { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 2 */
237 { 2, "issuerNameHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 3 */
238 { 2, "issuerKeyHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 4 */
239 { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 5 */
240 { 1, "certStatusGood", ASN1_CONTEXT_S_0, ASN1_OPT }, /* 6 */
241 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 7 */
242 { 1, "certStatusRevoked", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 8 */
243 { 2, "revocationTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 9 */
244 { 2, "revocationReason", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 10 */
245 { 3, "crlReason", ASN1_ENUMERATED, ASN1_BODY }, /* 11 */
246 { 2, "end opt", ASN1_EOC, ASN1_END }, /* 12 */
247 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 13 */
248 { 1, "certStatusUnknown", ASN1_CONTEXT_S_2, ASN1_OPT }, /* 14 */
249 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 15 */
250 { 1, "thisUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 16 */
251 { 1, "nextUpdateContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 17 */
252 { 2, "nextUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 18 */
253 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 19 */
254 { 1, "singleExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 20 */
255 { 2, "singleExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 21 */
256 { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */
257 { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 23 */
258 { 4, "critical", ASN1_BOOLEAN, ASN1_BODY |
259 ASN1_DEF }, /* 24 */
260 { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 25 */
261 { 2, "end loop", ASN1_EOC, ASN1_END }, /* 26 */
262 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 27 */
263 { 0, "exit", ASN1_EOC, ASN1_EXIT }
997358a6 264};
08b2d288
AS
265#define SINGLE_RESPONSE_ALGORITHM 2
266#define SINGLE_RESPONSE_ISSUER_NAME_HASH 3
267#define SINGLE_RESPONSE_ISSUER_KEY_HASH 4
268#define SINGLE_RESPONSE_SERIAL_NUMBER 5
269#define SINGLE_RESPONSE_CERT_STATUS_GOOD 6
270#define SINGLE_RESPONSE_CERT_STATUS_REVOKED 8
271#define SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME 9
272#define SINGLE_RESPONSE_CERT_STATUS_CRL_REASON 11
273#define SINGLE_RESPONSE_CERT_STATUS_UNKNOWN 14
274#define SINGLE_RESPONSE_THIS_UPDATE 16
275#define SINGLE_RESPONSE_NEXT_UPDATE 18
276#define SINGLE_RESPONSE_EXT_ID 23
277#define SINGLE_RESPONSE_CRITICAL 24
278#define SINGLE_RESPONSE_EXT_VALUE 25
997358a6 279
08b2d288
AS
280/*
281 * Build an ocsp location from certificate information
997358a6
MW
282 * without unsharing its contents
283 */
f565d0c5 284static bool build_ocsp_location(const cert_t *cert, ocsp_location_t *location)
997358a6 285{
0eff9f65
AS
286 certificate_t *certificate = cert->cert;
287 identification_t *issuer = certificate->get_issuer(certificate);
288 x509_t *x509 = (x509_t*)certificate;
289 chunk_t issuer_dn = issuer->get_encoding(issuer);
290 chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
8b799d55 291 hasher_t *hasher;
c08ae816 292 static u_char digest[HASH_SIZE_SHA1]; /* temporary storage */
7daf5226 293
0eff9f65 294 enumerator_t *enumerator = x509->create_ocsp_uri_enumerator(x509);
997358a6 295
0eff9f65
AS
296 location->uri = NULL;
297 while (enumerator->enumerate(enumerator, &location->uri))
9b91b818 298 {
0eff9f65
AS
299 break;
300 }
301 enumerator->destroy(enumerator);
302
303 if (location->uri == NULL)
304 {
0354d570
AS
305 ca_info_t *ca = get_ca_info(issuer, authKeyID);
306 if (ca && ca->ocspuri)
3d7a244b 307 {
0eff9f65 308 location->uri = ca->ocspuri;
3d7a244b
AS
309 }
310 else
311 { /* abort if no ocsp location uri is defined */
312 return FALSE;
313 }
9b91b818 314 }
7daf5226 315
8b799d55 316 /* compute authNameID from as SHA-1 hash of issuer DN */
c08ae816 317 location->authNameID = chunk_create(digest, HASH_SIZE_SHA1);
8b799d55
AS
318 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
319 if (hasher == NULL)
320 {
321 return FALSE;
322 }
0eff9f65 323 hasher->get_hash(hasher, issuer_dn, digest);
8b799d55 324 hasher->destroy(hasher);
3d7a244b
AS
325
326 location->next = NULL;
0354d570 327 location->issuer = issuer;
0eff9f65 328 location->authKeyID = authKeyID;
7daf5226 329
0eff9f65 330 if (authKeyID.ptr == NULL)
997358a6 331 {
f565d0c5 332 cert_t *authcert = get_authcert(issuer, authKeyID, X509_CA);
3d7a244b 333
0354d570 334 if (authcert)
3d7a244b 335 {
0eff9f65
AS
336 x509_t *x509 = (x509_t*)authcert->cert;
337
338 location->authKeyID = x509->get_subjectKeyIdentifier(x509);
3d7a244b 339 }
997358a6 340 }
997358a6 341
3d7a244b
AS
342 location->nonce = chunk_empty;
343 location->certinfo = NULL;
997358a6 344
3d7a244b 345 return TRUE;
997358a6
MW
346}
347
08b2d288
AS
348/**
349 * Compare two ocsp locations for equality
997358a6 350 */
08b2d288 351static bool same_ocsp_location(const ocsp_location_t *a, const ocsp_location_t *b)
997358a6 352{
0354d570 353 return ((a->authKeyID.ptr)
3d7a244b 354 ? same_keyid(a->authKeyID, b->authKeyID)
0354d570 355 : a->issuer->equals(a->issuer, b->issuer))
0eff9f65 356 && streq(a->uri, b->uri);
997358a6
MW
357}
358
08b2d288
AS
359/**
360 * Find an existing ocsp location in a chained list
997358a6 361 */
08b2d288 362ocsp_location_t* get_ocsp_location(const ocsp_location_t * loc, ocsp_location_t *chain)
997358a6
MW
363{
364
0354d570 365 while (chain)
3d7a244b
AS
366 {
367 if (same_ocsp_location(loc, chain))
368 return chain;
369 chain = chain->next;
370 }
371 return NULL;
997358a6 372}
3d7a244b 373
08b2d288
AS
374/**
375 * Retrieves the status of a cert from the ocsp cache
997358a6
MW
376 * returns CERT_UNDEFINED if no status is found
377 */
08b2d288
AS
378static cert_status_t get_ocsp_status(const ocsp_location_t *loc,
379 chunk_t serialNumber,
380 time_t *nextUpdate, time_t *revocationTime,
381 crl_reason_t *revocationReason)
997358a6 382{
3d7a244b
AS
383 ocsp_certinfo_t *certinfo, **certinfop;
384 int cmp = -1;
997358a6 385
3d7a244b
AS
386 /* find location */
387 ocsp_location_t *location = get_ocsp_location(loc, ocsp_cache);
997358a6 388
3d7a244b
AS
389 if (location == NULL)
390 return CERT_UNDEFINED;
997358a6 391
3d7a244b
AS
392 /* traverse list of certinfos in increasing order */
393 certinfop = &location->certinfo;
997358a6 394 certinfo = *certinfop;
997358a6 395
0354d570 396 while (certinfo)
3d7a244b
AS
397 {
398 cmp = chunk_compare(serialNumber, certinfo->serialNumber);
399 if (cmp <= 0)
400 break;
401 certinfop = &certinfo->next;
402 certinfo = *certinfop;
403 }
404
405 if (cmp == 0)
406 {
407 *nextUpdate = certinfo->nextUpdate;
408 *revocationTime = certinfo->revocationTime;
409 *revocationReason = certinfo->revocationReason;
410 return certinfo->status;
411 }
997358a6 412
3d7a244b 413 return CERT_UNDEFINED;
997358a6
MW
414}
415
08b2d288
AS
416/**
417 * Verify the ocsp status of a certificate
997358a6 418 */
f565d0c5 419cert_status_t verify_by_ocsp(const cert_t *cert, time_t *until,
08b2d288
AS
420 time_t *revocationDate,
421 crl_reason_t *revocationReason)
997358a6 422{
0eff9f65
AS
423 x509_t *x509 = (x509_t*)cert->cert;
424 chunk_t serialNumber = x509->get_serial(x509);
3d7a244b
AS
425 cert_status_t status;
426 ocsp_location_t location;
ce2f2461 427 time_t nextUpdate = UNDEFINED_TIME;
3d7a244b
AS
428
429 *revocationDate = UNDEFINED_TIME;
f561d6f2 430 *revocationReason = CRL_REASON_UNSPECIFIED;
7daf5226 431
3d7a244b
AS
432 /* is an ocsp location defined? */
433 if (!build_ocsp_location(cert, &location))
0eff9f65 434 {
3d7a244b 435 return CERT_UNDEFINED;
0eff9f65 436 }
997358a6 437
3d7a244b 438 lock_ocsp_cache("verify_by_ocsp");
0eff9f65 439 status = get_ocsp_status(&location, serialNumber, &nextUpdate
3d7a244b
AS
440 , revocationDate, revocationReason);
441 unlock_ocsp_cache("verify_by_ocsp");
442
443 if (status == CERT_UNDEFINED || nextUpdate < time(NULL))
444 {
445 plog("ocsp status is stale or not in cache");
0eff9f65 446 add_ocsp_fetch_request(&location, serialNumber);
3d7a244b
AS
447
448 /* inititate fetching of ocsp status */
449 wake_fetch_thread("verify_by_ocsp");
450 }
451 *until = nextUpdate;
452 return status;
997358a6
MW
453}
454
08b2d288
AS
455/**
456 * Check if an ocsp status is about to expire
997358a6 457 */
08b2d288 458void check_ocsp(void)
997358a6 459{
3d7a244b 460 ocsp_location_t *location;
997358a6 461
3d7a244b
AS
462 lock_ocsp_cache("check_ocsp");
463 location = ocsp_cache;
7daf5226 464
0354d570 465 while (location)
997358a6 466 {
3d7a244b
AS
467 char buf[BUF_LEN];
468 bool first = TRUE;
469 ocsp_certinfo_t *certinfo = location->certinfo;
997358a6 470
0354d570 471 while (certinfo)
3d7a244b
AS
472 {
473 if (!certinfo->once)
997358a6 474 {
3d7a244b
AS
475 time_t time_left = certinfo->nextUpdate - time(NULL);
476
477 DBG(DBG_CONTROL,
478 if (first)
479 {
0354d570
AS
480 DBG_log("issuer: \"%Y\"", location->issuer);
481 if (location->authKeyID.ptr)
3d7a244b
AS
482 {
483 datatot(location->authKeyID.ptr, location->authKeyID.len
484 , ':', buf, BUF_LEN);
485 DBG_log("authkey: %s", buf);
486 }
487 first = FALSE;
488 }
489 datatot(certinfo->serialNumber.ptr, certinfo->serialNumber.len
490 , ':', buf, BUF_LEN);
491 DBG_log("serial: %s, %ld seconds left", buf, time_left)
492 )
493
494 if (time_left < 2*crl_check_interval)
495 add_ocsp_fetch_request(location, certinfo->serialNumber);
997358a6 496 }
3d7a244b
AS
497 certinfo = certinfo->next;
498 }
499 location = location->next;
997358a6 500 }
3d7a244b 501 unlock_ocsp_cache("check_ocsp");
997358a6
MW
502}
503
08b2d288 504/**
997358a6
MW
505 * frees the allocated memory of a certinfo struct
506 */
08b2d288 507static void free_certinfo(ocsp_certinfo_t *certinfo)
997358a6 508{
3d7a244b
AS
509 free(certinfo->serialNumber.ptr);
510 free(certinfo);
997358a6
MW
511}
512
08b2d288 513/**
997358a6
MW
514 * frees all certinfos in a chained list
515 */
08b2d288 516static void free_certinfos(ocsp_certinfo_t *chain)
997358a6 517{
3d7a244b 518 ocsp_certinfo_t *certinfo;
997358a6 519
0354d570 520 while (chain)
3d7a244b
AS
521 {
522 certinfo = chain;
523 chain = chain->next;
524 free_certinfo(certinfo);
525 }
997358a6
MW
526}
527
08b2d288
AS
528/**
529 * Frees the memory allocated to an ocsp location including all certinfos
997358a6 530 */
08b2d288 531static void free_ocsp_location(ocsp_location_t* location)
997358a6 532{
0354d570 533 DESTROY_IF(location->issuer);
3d7a244b
AS
534 free(location->authNameID.ptr);
535 free(location->authKeyID.ptr);
0eff9f65 536 free(location->uri);
3d7a244b
AS
537 free_certinfos(location->certinfo);
538 free(location);
997358a6
MW
539}
540
541/*
08b2d288 542 * Free a chained list of ocsp locations
997358a6 543 */
08b2d288 544void free_ocsp_locations(ocsp_location_t **chain)
997358a6 545{
0354d570 546 while (*chain)
3d7a244b
AS
547 {
548 ocsp_location_t *location = *chain;
549 *chain = location->next;
550 free_ocsp_location(location);
551 }
997358a6
MW
552}
553
08b2d288
AS
554/**
555 * Free the ocsp cache
997358a6 556 */
08b2d288 557void free_ocsp_cache(void)
997358a6 558{
3d7a244b
AS
559 lock_ocsp_cache("free_ocsp_cache");
560 free_ocsp_locations(&ocsp_cache);
561 unlock_ocsp_cache("free_ocsp_cache");
997358a6
MW
562}
563
08b2d288
AS
564/**
565 * Frees the ocsp cache and global variables
997358a6 566 */
08b2d288 567void free_ocsp(void)
997358a6 568{
3d7a244b
AS
569 free(ocsp_default_uri.ptr);
570 free_ocsp_cache();
997358a6
MW
571}
572
08b2d288
AS
573/**
574 * List a chained list of ocsp_locations
997358a6 575 */
08b2d288
AS
576void list_ocsp_locations(ocsp_location_t *location, bool requests,
577 bool utc, bool strict)
997358a6 578{
3d7a244b 579 bool first = TRUE;
997358a6 580
0354d570 581 while (location)
997358a6 582 {
3d7a244b
AS
583 ocsp_certinfo_t *certinfo = location->certinfo;
584
0354d570 585 if (certinfo)
997358a6 586 {
3d7a244b
AS
587 if (first)
588 {
589 whack_log(RC_COMMENT, " ");
0354d570
AS
590 whack_log(RC_COMMENT, "List of OCSP %s:", requests ?
591 "Fetch Requests" : "Responses");
3d7a244b
AS
592 first = FALSE;
593 }
594 whack_log(RC_COMMENT, " ");
0354d570 595 if (location->issuer)
3d7a244b 596 {
0354d570 597 whack_log(RC_COMMENT, " issuer: \"%Y\"", location->issuer);
3d7a244b 598 }
0354d570 599 whack_log(RC_COMMENT, " uri: '%s'", location->uri);
ce2f2461 600 if (location->authNameID.ptr)
3d7a244b 601 {
0354d570 602 whack_log(RC_COMMENT, " authname: %#B", &location->authNameID);
3d7a244b 603 }
ce2f2461 604 if (location->authKeyID.ptr)
3d7a244b 605 {
0354d570 606 whack_log(RC_COMMENT, " authkey: %#B", &location->authKeyID);
3d7a244b 607 }
ce2f2461 608 while (certinfo)
3d7a244b 609 {
3d7a244b
AS
610 if (requests)
611 {
0354d570 612 whack_log(RC_COMMENT, " serial: %#B, %d trials",
ce2f2461 613 &certinfo->serialNumber, certinfo->trials);
3d7a244b
AS
614 }
615 else if (certinfo->once)
616 {
0354d570 617 whack_log(RC_COMMENT, " serial: %#B, %s, once%s",
ce2f2461
AS
618 &certinfo->serialNumber,
619 cert_status_names[certinfo->status],
620 (certinfo->nextUpdate < time(NULL))? " (expired)": "");
3d7a244b
AS
621 }
622 else
623 {
0406eeaa 624 whack_log(RC_COMMENT, " serial: %#B, %s, until %T %s",
ce2f2461
AS
625 &certinfo->serialNumber,
626 cert_status_names[certinfo->status],
627 &certinfo->nextUpdate, utc,
628 check_expiry(certinfo->nextUpdate, OCSP_WARNING_INTERVAL, strict));
3d7a244b 629 }
3d7a244b
AS
630 certinfo = certinfo->next;
631 }
997358a6 632 }
3d7a244b 633 location = location->next;
997358a6 634 }
997358a6
MW
635}
636
08b2d288
AS
637/**
638 * List the ocsp cache
997358a6 639 */
08b2d288 640void list_ocsp_cache(bool utc, bool strict)
997358a6 641{
3d7a244b
AS
642 lock_ocsp_cache("list_ocsp_cache");
643 list_ocsp_locations(ocsp_cache, FALSE, utc, strict);
644 unlock_ocsp_cache("list_ocsp_cache");
997358a6
MW
645}
646
08b2d288 647static bool get_ocsp_requestor_cert(ocsp_location_t *location)
997358a6 648{
f565d0c5 649 cert_t *cert = NULL;
997358a6 650
3d7a244b
AS
651 /* initialize temporary static storage */
652 ocsp_requestor_cert = NULL;
653 ocsp_requestor_sc = NULL;
8b799d55 654 ocsp_requestor_key = NULL;
997358a6 655
3d7a244b 656 for (;;)
997358a6 657 {
0eff9f65 658 certificate_t *certificate;
3d7a244b
AS
659
660 /* looking for a certificate from the same issuer */
0eff9f65 661 cert = get_x509cert(location->issuer, location->authKeyID, cert);
3d7a244b 662 if (cert == NULL)
0eff9f65 663 {
3d7a244b 664 break;
0eff9f65
AS
665 }
666 certificate = cert->cert;
997358a6 667 DBG(DBG_CONTROL,
0eff9f65 668 DBG_log("candidate: '%Y'", certificate->get_subject(certificate));
997358a6 669 )
3d7a244b
AS
670
671 if (cert->smartcard)
997358a6 672 {
3d7a244b
AS
673 /* look for a matching private key on a smartcard */
674 smartcard_t *sc = scx_get(cert);
675
0354d570 676 if (sc)
3d7a244b
AS
677 {
678 DBG(DBG_CONTROL,
679 DBG_log("matching smartcard found")
680 )
681 if (sc->valid)
682 {
683 ocsp_requestor_cert = cert;
684 ocsp_requestor_sc = sc;
685 return TRUE;
686 }
687 plog("unable to sign ocsp request without PIN");
688 }
997358a6 689 }
3d7a244b
AS
690 else
691 {
692 /* look for a matching private key in the chained list */
8b799d55 693 private_key_t *private = get_x509_private_key(cert);
997358a6 694
0354d570 695 if (private)
3d7a244b
AS
696 {
697 DBG(DBG_CONTROL,
698 DBG_log("matching private key found")
699 )
700 ocsp_requestor_cert = cert;
8b799d55 701 ocsp_requestor_key = private;
3d7a244b
AS
702 return TRUE;
703 }
704 }
997358a6 705 }
3d7a244b 706 return FALSE;
997358a6
MW
707}
708
8b799d55 709static chunk_t sc_build_sha1_signature(chunk_t tbs, smartcard_t *sc)
997358a6 710{
8b799d55 711 hasher_t *hasher;
3d7a244b 712 u_char *pos;
3b878dae 713 chunk_t digest;
8b799d55 714 chunk_t digest_info, sigdata;
3d7a244b 715 size_t siglen = 0;
997358a6 716
8b799d55 717 if (!scx_establish_context(sc) || !scx_login(sc))
997358a6 718 {
8b799d55
AS
719 scx_release_context(sc);
720 return chunk_empty;
721 }
997358a6 722
8b799d55 723 siglen = scx_get_keylength(sc);
997358a6 724
8b799d55
AS
725 if (siglen == 0)
726 {
727 plog("failed to get keylength from smartcard");
728 scx_release_context(sc);
729 return chunk_empty;
730 }
997358a6 731
8b799d55
AS
732 DBG(DBG_CONTROL | DBG_CRYPT,
733 DBG_log("signing hash with RSA key from smartcard (slot: %d, id: %s)"
734 , (int)sc->slot, sc->id)
735 )
997358a6 736
8b799d55
AS
737 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
738 if (hasher == NULL)
739 {
740 return chunk_empty;
3d7a244b 741 }
3b878dae 742 hasher->allocate_hash(hasher, tbs, &digest);
8b799d55
AS
743 hasher->destroy(hasher);
744
745 /* according to PKCS#1 v2.1 digest must be packaged into
746 * an ASN.1 structure for encryption
747 */
eb73685d 748 digest_info = asn1_wrap(ASN1_SEQUENCE, "mm"
8b799d55 749 , asn1_algorithmIdentifier(OID_SHA1)
3b878dae 750 , asn1_wrap(ASN1_OCTET_STRING, "m", digest));
8b799d55
AS
751
752 pos = asn1_build_object(&sigdata, ASN1_BIT_STRING, 1 + siglen);
753 *pos++ = 0x00;
754 scx_sign_hash(sc, digest_info.ptr, digest_info.len, pos, siglen);
755 free(digest_info.ptr);
756
757 if (!pkcs11_keep_state)
3d7a244b 758 {
8b799d55 759 scx_release_context(sc);
3d7a244b
AS
760 }
761 return sigdata;
997358a6
MW
762}
763
08b2d288
AS
764/**
765 * build signature into ocsp request gets built only if a request cert
766 * with a corresponding private key is found
997358a6 767 */
08b2d288 768static chunk_t build_signature(chunk_t tbsRequest)
997358a6 769{
0406eeaa 770 chunk_t sigdata, cert, certs = chunk_empty;
3d7a244b 771
0354d570 772 if (ocsp_requestor_sc)
8b799d55
AS
773 {
774 /* RSA signature is done on smartcard */
775 sigdata = sc_build_sha1_signature(tbsRequest, ocsp_requestor_sc);
776 }
777 else
778 {
779 /* RSA signature is done in software */
780 sigdata = x509_build_signature(tbsRequest, OID_SHA1, ocsp_requestor_key,
781 TRUE);
782 }
3d7a244b 783 if (sigdata.ptr == NULL)
8b799d55 784 {
3d7a244b 785 return chunk_empty;
8b799d55 786 }
3d7a244b
AS
787
788 /* include our certificate */
0406eeaa
MW
789 if (ocsp_requestor_cert->cert->get_encoding(ocsp_requestor_cert->cert,
790 CERT_ASN1_DER, &cert))
791 {
792 certs = asn1_wrap(ASN1_CONTEXT_C_0, "m",
793 asn1_wrap(ASN1_SEQUENCE, "m", cert));
794 }
3d7a244b
AS
795 /* build signature comprising algorithm, signature and cert */
796 return asn1_wrap(ASN1_CONTEXT_C_0, "m"
eb73685d 797 , asn1_wrap(ASN1_SEQUENCE, "mmm"
08b2d288 798 , asn1_algorithmIdentifier(OID_SHA1_WITH_RSA)
3d7a244b
AS
799 , sigdata
800 , certs
801 )
802 );
997358a6
MW
803}
804
08b2d288
AS
805/**
806 * Build request (into requestList)
997358a6
MW
807 * no singleRequestExtensions used
808 */
08b2d288 809static chunk_t build_request(ocsp_location_t *location, ocsp_certinfo_t *certinfo)
997358a6 810{
eb73685d 811 chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "mmmm"
08b2d288 812 , asn1_algorithmIdentifier(OID_SHA1)
3d7a244b
AS
813 , asn1_simple_object(ASN1_OCTET_STRING, location->authNameID)
814 , asn1_simple_object(ASN1_OCTET_STRING, location->authKeyID)
815 , asn1_simple_object(ASN1_INTEGER, certinfo->serialNumber));
997358a6 816
3d7a244b 817 return asn1_wrap(ASN1_SEQUENCE, "m", reqCert);
997358a6
MW
818}
819
08b2d288 820/**
997358a6
MW
821 * build requestList (into TBSRequest)
822 */
08b2d288 823static chunk_t build_request_list(ocsp_location_t *location)
997358a6 824{
3d7a244b
AS
825 chunk_t requestList;
826 request_list_t *reqs = NULL;
827 ocsp_certinfo_t *certinfo = location->certinfo;
828 u_char *pos;
997358a6 829
3d7a244b 830 size_t datalen = 0;
997358a6 831
3d7a244b 832 /* build content */
0354d570 833 while (certinfo)
3d7a244b
AS
834 {
835 /* build request for every certificate in list
836 * and store them in a chained list
837 */
838 request_list_t *req = malloc_thing(request_list_t);
997358a6 839
3d7a244b
AS
840 req->request = build_request(location, certinfo);
841 req->next = reqs;
842 reqs = req;
997358a6 843
3d7a244b
AS
844 datalen += req->request.len;
845 certinfo = certinfo->next;
846 }
997358a6 847
08b2d288 848 pos = asn1_build_object(&requestList, ASN1_SEQUENCE, datalen);
3d7a244b
AS
849
850 /* copy all in chained list, free list afterwards */
0354d570 851 while (reqs)
3d7a244b
AS
852 {
853 request_list_t *req = reqs;
854
855 mv_chunk(&pos, req->request);
856 reqs = reqs->next;
857 free(req);
858 }
997358a6 859
3d7a244b 860 return requestList;
997358a6
MW
861}
862
08b2d288
AS
863/**
864 * Build requestorName (into TBSRequest)
997358a6 865 */
08b2d288 866static chunk_t build_requestor_name(void)
997358a6 867{
0eff9f65
AS
868 certificate_t *certificate = ocsp_requestor_cert->cert;
869 identification_t *subject = certificate->get_subject(certificate);
870
3d7a244b
AS
871 return asn1_wrap(ASN1_CONTEXT_C_1, "m"
872 , asn1_simple_object(ASN1_CONTEXT_C_4
0eff9f65 873 , subject->get_encoding(subject)));
997358a6
MW
874}
875
08b2d288 876/**
997358a6
MW
877 * build nonce extension (into requestExtensions)
878 */
08b2d288 879static chunk_t build_nonce_extension(ocsp_location_t *location)
997358a6 880{
bc2e33ca
AS
881 rng_t *rng;
882
3d7a244b
AS
883 /* generate a random nonce */
884 location->nonce.ptr = malloc(NONCE_LENGTH),
885 location->nonce.len = NONCE_LENGTH;
bc2e33ca
AS
886 rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
887 rng->get_bytes(rng, location->nonce.len, location->nonce.ptr);
888 rng->destroy(rng);
3d7a244b
AS
889
890 return asn1_wrap(ASN1_SEQUENCE, "cm"
891 , ASN1_nonce_oid
892 , asn1_simple_object(ASN1_OCTET_STRING, location->nonce));
997358a6
MW
893}
894
08b2d288
AS
895/**
896 * Build requestExtensions (into TBSRequest)
997358a6 897 */
08b2d288 898static chunk_t build_request_ext(ocsp_location_t *location)
997358a6 899{
3d7a244b
AS
900 return asn1_wrap(ASN1_CONTEXT_C_2, "m"
901 , asn1_wrap(ASN1_SEQUENCE, "mm"
902 , build_nonce_extension(location)
903 , asn1_wrap(ASN1_SEQUENCE, "cc"
904 , ASN1_response_oid
905 , ASN1_response_content
906 )
907 )
908 );
997358a6
MW
909}
910
08b2d288
AS
911/**
912 * Build TBSRequest (into OCSPRequest)
997358a6 913 */
08b2d288 914static chunk_t build_tbs_request(ocsp_location_t *location, bool has_requestor_cert)
997358a6 915{
3d7a244b
AS
916 /* version is skipped since the default is ok */
917 return asn1_wrap(ASN1_SEQUENCE, "mmm"
918 , (has_requestor_cert)
919 ? build_requestor_name()
920 : chunk_empty
921 , build_request_list(location)
922 , build_request_ext(location));
997358a6
MW
923}
924
08b2d288
AS
925/**
926 * Assembles an ocsp request to given location
997358a6
MW
927 * and sets nonce field in location to the sent nonce
928 */
08b2d288 929chunk_t build_ocsp_request(ocsp_location_t *location)
997358a6 930{
3d7a244b
AS
931 bool has_requestor_cert;
932 chunk_t tbsRequest, signature;
3d7a244b
AS
933
934 DBG(DBG_CONTROL,
935 DBG_log("assembling ocsp request");
0354d570
AS
936 DBG_log("issuer: \"%Y\"", location->issuer);
937 if (location->authKeyID.ptr)
3d7a244b 938 {
0354d570 939 DBG_log("authkey: %#B", &location->authKeyID);
3d7a244b
AS
940 }
941 )
942 lock_certs_and_keys("build_ocsp_request");
997358a6 943
3d7a244b
AS
944 /* looks for requestor cert and matching private key */
945 has_requestor_cert = get_ocsp_requestor_cert(location);
997358a6 946
3d7a244b
AS
947 /* build content */
948 tbsRequest = build_tbs_request(location, has_requestor_cert);
997358a6 949
3d7a244b
AS
950 /* sign tbsReuqest */
951 signature = (has_requestor_cert)? build_signature(tbsRequest)
952 : chunk_empty;
997358a6 953
3d7a244b 954 unlock_certs_and_keys("build_ocsp_request");
997358a6 955
3d7a244b
AS
956 return asn1_wrap(ASN1_SEQUENCE, "mm"
957 , tbsRequest
958 , signature);
997358a6
MW
959}
960
08b2d288
AS
961/**
962 * Check if the OCSP response has a valid signature
997358a6 963 */
08b2d288 964static bool valid_ocsp_response(response_t *res)
997358a6 965{
4c68a85a 966 int pathlen, pathlen_constraint;
f565d0c5 967 cert_t *authcert;
997358a6 968
3d7a244b 969 lock_authcert_list("valid_ocsp_response");
997358a6 970
0eff9f65 971 authcert = get_authcert(res->responder_id_name, res->responder_id_key,
fc12e3cd 972 X509_OCSP_SIGNER | X509_CA);
997358a6
MW
973 if (authcert == NULL)
974 {
3d7a244b
AS
975 plog("no matching ocsp signer cert found");
976 unlock_authcert_list("valid_ocsp_response");
977 return FALSE;
997358a6
MW
978 }
979 DBG(DBG_CONTROL,
3d7a244b 980 DBG_log("ocsp signer cert found")
997358a6
MW
981 )
982
0eff9f65
AS
983 if (!x509_check_signature(res->tbs, res->signature, res->algorithm,
984 authcert->cert))
997358a6 985 {
3d7a244b
AS
986 plog("signature of ocsp response is invalid");
987 unlock_authcert_list("valid_ocsp_response");
988 return FALSE;
997358a6
MW
989 }
990 DBG(DBG_CONTROL,
3d7a244b 991 DBG_log("signature of ocsp response is valid")
997358a6
MW
992 )
993
3d7a244b 994
4c68a85a 995 for (pathlen = -1; pathlen <= X509_MAX_PATH_LEN; pathlen++)
997358a6 996 {
f565d0c5 997 cert_t *cert = authcert;
0eff9f65
AS
998 certificate_t *certificate = cert->cert;
999 x509_t *x509 = (x509_t*)certificate;
1000 identification_t *subject = certificate->get_subject(certificate);
1001 identification_t *issuer = certificate->get_issuer(certificate);
1002 chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
c4570d18 1003 time_t not_before, not_after;
3d7a244b
AS
1004
1005 DBG(DBG_CONTROL,
0eff9f65
AS
1006 DBG_log("subject: '%Y'", subject);
1007 DBG_log("issuer: '%Y'", issuer);
cf85e131 1008 if (authKeyID.ptr)
3d7a244b 1009 {
0eff9f65 1010 DBG_log("authkey: %#B", &authKeyID);
3d7a244b
AS
1011 }
1012 )
1013
c4570d18 1014 if (!certificate->get_validity(certificate, NULL, &not_before, &not_after))
3d7a244b 1015 {
c4570d18
AS
1016 plog("certificate is invalid (valid from %T to %T)",
1017 &not_before, FALSE, &not_after, FALSE);
0406eeaa 1018
3d7a244b
AS
1019 unlock_authcert_list("valid_ocsp_response");
1020 return FALSE;
1021 }
3d7a244b
AS
1022 DBG(DBG_CONTROL,
1023 DBG_log("certificate is valid")
1024 )
7daf5226 1025
0354d570 1026 authcert = get_authcert(issuer, authKeyID, X509_CA);
3d7a244b
AS
1027 if (authcert == NULL)
1028 {
1029 plog("issuer cacert not found");
1030 unlock_authcert_list("valid_ocsp_response");
1031 return FALSE;
1032 }
1033 DBG(DBG_CONTROL,
1034 DBG_log("issuer cacert found")
1035 )
1036
0eff9f65 1037 if (!certificate->issued_by(certificate, authcert->cert))
3d7a244b
AS
1038 {
1039 plog("certificate signature is invalid");
1040 unlock_authcert_list("valid_ocsp_response");
1041 return FALSE;
1042 }
1043 DBG(DBG_CONTROL,
1044 DBG_log("certificate signature is valid")
1045 )
1046
4c68a85a
AS
1047 /* check path length constraint */
1048 pathlen_constraint = x509->get_pathLenConstraint(x509);
1049 if (pathlen_constraint != X509_NO_PATH_LEN_CONSTRAINT &&
1050 pathlen > pathlen_constraint)
1051 {
1052 plog("path length of %d violates constraint of %d",
1053 pathlen, pathlen_constraint);
1054 return FALSE;
1055 }
1056
3d7a244b 1057 /* check if cert is self-signed */
0eff9f65 1058 if (x509->get_flags(x509) & X509_SELF_SIGNED)
3d7a244b
AS
1059 {
1060 DBG(DBG_CONTROL,
4c68a85a
AS
1061 DBG_log("reached self-signed root ca with a path length of %d",
1062 pathlen)
3d7a244b
AS
1063 )
1064 unlock_authcert_list("valid_ocsp_response");
1065 return TRUE;
1066 }
997358a6 1067 }
4c68a85a 1068 plog("maximum path length of %d exceeded", X509_MAX_PATH_LEN);
3d7a244b
AS
1069 unlock_authcert_list("valid_ocsp_response");
1070 return FALSE;
997358a6
MW
1071}
1072
08b2d288
AS
1073/**
1074 * Parse a basic OCSP response
997358a6 1075 */
08b2d288 1076static bool parse_basic_ocsp_response(chunk_t blob, int level0, response_t *res)
997358a6 1077{
08b2d288 1078 asn1_parser_t *parser;
3d7a244b 1079 chunk_t object;
08b2d288 1080 u_int version;
08b2d288 1081 int objectID;
3d7a244b 1082 int extn_oid = OID_UNKNOWN;
08b2d288
AS
1083 bool success = FALSE;
1084 bool critical;
3d7a244b 1085
08b2d288
AS
1086 parser = asn1_parser_create(basicResponseObjects, blob);
1087 parser->set_top_level(parser, level0);
3d7a244b 1088
08b2d288 1089 while (parser->iterate(parser, &objectID, &object))
997358a6 1090 {
3d7a244b 1091 switch (objectID)
997358a6 1092 {
3d7a244b
AS
1093 case BASIC_RESPONSE_TBS_DATA:
1094 res->tbs = object;
1095 break;
1096 case BASIC_RESPONSE_VERSION:
1097 version = (object.len)? (1 + (u_int)*object.ptr) : 1;
1098 if (version != OCSP_BASIC_RESPONSE_VERSION)
1099 {
1100 plog("wrong ocsp basic response version (version= %i)", version);
08b2d288 1101 goto end;
3d7a244b
AS
1102 }
1103 break;
1104 case BASIC_RESPONSE_ID_BY_NAME:
0354d570
AS
1105 res->responder_id_name = identification_create_from_encoding(
1106 ID_DER_ASN1_DN, object);
3d7a244b 1107 DBG(DBG_PARSING,
0354d570 1108 DBG_log(" '%Y'", res->responder_id_name)
3d7a244b
AS
1109 )
1110 break;
1111 case BASIC_RESPONSE_ID_BY_KEY:
1112 res->responder_id_key = object;
1113 break;
1114 case BASIC_RESPONSE_PRODUCED_AT:
08b2d288 1115 res->produced_at = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
3d7a244b
AS
1116 break;
1117 case BASIC_RESPONSE_RESPONSES:
1118 res->responses = object;
1119 break;
1120 case BASIC_RESPONSE_EXT_ID:
1121 extn_oid = asn1_known_oid(object);
1122 break;
1123 case BASIC_RESPONSE_CRITICAL:
1124 critical = object.len && *object.ptr;
1125 DBG(DBG_PARSING,
1126 DBG_log(" %s",(critical)?"TRUE":"FALSE");
1127 )
1128 break;
1129 case BASIC_RESPONSE_EXT_VALUE:
1130 if (extn_oid == OID_NONCE)
1131 res->nonce = object;
1132 break;
1133 case BASIC_RESPONSE_ALGORITHM:
08b2d288
AS
1134 res->algorithm = asn1_parse_algorithmIdentifier(object,
1135 parser->get_level(parser)+1, NULL);
3d7a244b
AS
1136 break;
1137 case BASIC_RESPONSE_SIGNATURE:
1138 res->signature = object;
1139 break;
1140 case BASIC_RESPONSE_CERTIFICATE:
1141 {
f565d0c5 1142 cert_t *cert = malloc_thing(cert_t);
0eff9f65 1143 x509_t *x509;
3d7a244b 1144
f565d0c5 1145 *cert = cert_empty;
0eff9f65
AS
1146 cert->cert = lib->creds->create(lib->creds,
1147 CRED_CERTIFICATE, CERT_X509,
1148 BUILD_BLOB_ASN1_DER, object,
1149 BUILD_END);
1150 if (cert->cert == NULL)
1151 {
1152 DBG(DBG_CONTROL | DBG_PARSING,
1153 DBG_log("parsing of embedded ocsp certificate failed")
1154 )
f565d0c5 1155 cert_free(cert);
0eff9f65
AS
1156 break;
1157 }
0eff9f65 1158 x509 = (x509_t*)cert->cert;
0406eeaa 1159
0eff9f65
AS
1160 if ((x509->get_flags(x509) & X509_OCSP_SIGNER) &&
1161 trust_authcert_candidate(cert, NULL))
3d7a244b 1162 {
fc12e3cd 1163 add_authcert(cert, X509_OCSP_SIGNER);
3d7a244b
AS
1164 }
1165 else
1166 {
1167 DBG(DBG_CONTROL | DBG_PARSING,
1168 DBG_log("embedded ocsp certificate rejected")
1169 )
f565d0c5 1170 cert_free(cert);
3d7a244b
AS
1171 }
1172 }
1173 break;
997358a6 1174 }
997358a6 1175 }
08b2d288
AS
1176 success = parser->success(parser);
1177
1178end:
1179 parser->destroy(parser);
1180 return success;
1181
997358a6
MW
1182}
1183
1184
08b2d288
AS
1185/**
1186 * Parse an ocsp response and return the result as a response_t struct
997358a6 1187 */
08b2d288 1188static response_status parse_ocsp_response(chunk_t blob, response_t * res)
997358a6 1189{
08b2d288 1190 asn1_parser_t *parser;
3d7a244b 1191 chunk_t object;
08b2d288 1192 int objectID;
3d7a244b 1193 int ocspResponseType = OID_UNKNOWN;
08b2d288 1194 bool success = FALSE;
3d7a244b
AS
1195 response_status rStatus = STATUS_INTERNALERROR;
1196
08b2d288 1197 parser = asn1_parser_create(ocspResponseObjects, blob);
3d7a244b 1198
08b2d288 1199 while (parser->iterate(parser, &objectID, &object))
3d7a244b 1200 {
3d7a244b
AS
1201 switch (objectID) {
1202 case OCSP_RESPONSE_STATUS:
1203 rStatus = (response_status) *object.ptr;
1204
1205 switch (rStatus)
1206 {
1207 case STATUS_SUCCESSFUL:
1208 break;
1209 case STATUS_MALFORMEDREQUEST:
1210 case STATUS_INTERNALERROR:
1211 case STATUS_TRYLATER:
1212 case STATUS_SIGREQUIRED:
1213 case STATUS_UNAUTHORIZED:
1214 plog("ocsp response: server said '%s'"
1215 , response_status_names[rStatus]);
08b2d288 1216 goto end;
3d7a244b 1217 default:
08b2d288 1218 goto end;
3d7a244b
AS
1219 }
1220 break;
1221 case OCSP_RESPONSE_TYPE:
1222 ocspResponseType = asn1_known_oid(object);
1223 break;
1224 case OCSP_RESPONSE:
1225 {
1226 switch (ocspResponseType) {
1227 case OID_BASIC:
08b2d288
AS
1228 success = parse_basic_ocsp_response(object,
1229 parser->get_level(parser)+1, res);
3d7a244b
AS
1230 break;
1231 default:
1232 DBG(DBG_CONTROL,
1233 DBG_log("ocsp response is not of type BASIC");
1234 DBG_dump_chunk("ocsp response OID: ", object);
1235 )
08b2d288 1236 goto end;
3d7a244b
AS
1237 }
1238 }
1239 break;
997358a6 1240 }
997358a6 1241 }
08b2d288
AS
1242 success &= parser->success(parser);
1243
1244end:
1245 parser->destroy(parser);
3d7a244b 1246 return rStatus;
997358a6
MW
1247}
1248
08b2d288
AS
1249/**
1250 * Parse a basic OCSP response
997358a6 1251 */
08b2d288
AS
1252static bool parse_ocsp_single_response(chunk_t blob, int level0,
1253 single_response_t *sres)
997358a6 1254{
08b2d288 1255 asn1_parser_t *parser;
3d7a244b 1256 chunk_t object;
08b2d288
AS
1257 u_int extn_oid;
1258 int objectID;
1259 bool critical;
1260 bool success = FALSE;
997358a6 1261
08b2d288
AS
1262 parser = asn1_parser_create(singleResponseObjects, blob);
1263 parser->set_top_level(parser, level0);
997358a6 1264
08b2d288 1265 while (parser->iterate(parser, &objectID, &object))
997358a6 1266 {
3d7a244b
AS
1267 switch (objectID)
1268 {
1269 case SINGLE_RESPONSE_ALGORITHM:
08b2d288
AS
1270 sres->hash_algorithm = asn1_parse_algorithmIdentifier(object,
1271 parser->get_level(parser)+1, NULL);
3d7a244b
AS
1272 break;
1273 case SINGLE_RESPONSE_ISSUER_NAME_HASH:
1274 sres->issuer_name_hash = object;
1275 break;
1276 case SINGLE_RESPONSE_ISSUER_KEY_HASH:
1277 sres->issuer_key_hash = object;
1278 break;
1279 case SINGLE_RESPONSE_SERIAL_NUMBER:
1280 sres->serialNumber = object;
1281 break;
1282 case SINGLE_RESPONSE_CERT_STATUS_GOOD:
1283 sres->status = CERT_GOOD;
1284 break;
1285 case SINGLE_RESPONSE_CERT_STATUS_REVOKED:
1286 sres->status = CERT_REVOKED;
1287 break;
1288 case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME:
08b2d288 1289 sres->revocationTime = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
3d7a244b
AS
1290 break;
1291 case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON:
1292 sres->revocationReason = (object.len == 1)
f561d6f2 1293 ? *object.ptr : CRL_REASON_UNSPECIFIED;
3d7a244b
AS
1294 break;
1295 case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN:
1296 sres->status = CERT_UNKNOWN;
1297 break;
1298 case SINGLE_RESPONSE_THIS_UPDATE:
08b2d288 1299 sres->thisUpdate = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
3d7a244b
AS
1300 break;
1301 case SINGLE_RESPONSE_NEXT_UPDATE:
08b2d288 1302 sres->nextUpdate = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
3d7a244b
AS
1303 break;
1304 case SINGLE_RESPONSE_EXT_ID:
1305 extn_oid = asn1_known_oid(object);
1306 break;
1307 case SINGLE_RESPONSE_CRITICAL:
1308 critical = object.len && *object.ptr;
1309 DBG(DBG_PARSING,
1310 DBG_log(" %s",(critical)?"TRUE":"FALSE");
1311 )
1312 case SINGLE_RESPONSE_EXT_VALUE:
1313 break;
1314 }
997358a6 1315 }
08b2d288
AS
1316 success = parser->success(parser);
1317 parser->destroy(parser);
1318 return success;
997358a6
MW
1319}
1320
08b2d288
AS
1321/**
1322 * Add an ocsp location to a chained list
997358a6 1323 */
08b2d288
AS
1324ocsp_location_t* add_ocsp_location(const ocsp_location_t *loc,
1325 ocsp_location_t **chain)
997358a6 1326{
3d7a244b 1327 ocsp_location_t *location = malloc_thing(ocsp_location_t);
997358a6 1328
3d7a244b 1329 /* unshare location fields */
0354d570 1330 location->issuer = loc->issuer->clone(loc->issuer);
3d7a244b
AS
1331 location->authNameID = chunk_clone(loc->authNameID);
1332 location->authKeyID = chunk_clone(loc->authKeyID);
0eff9f65 1333 location->uri = strdup(loc->uri);
3d7a244b 1334 location->certinfo = NULL;
997358a6 1335
3d7a244b
AS
1336 /* insert new ocsp location in front of chain */
1337 location->next = *chain;
1338 *chain = location;
997358a6 1339
3d7a244b
AS
1340 DBG(DBG_CONTROL,
1341 DBG_log("new ocsp location added")
1342 )
997358a6 1343
3d7a244b 1344 return location;
997358a6
MW
1345}
1346
08b2d288 1347/**
997358a6
MW
1348 * add a certinfo struct to a chained list
1349 */
08b2d288
AS
1350void add_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info,
1351 ocsp_location_t **chain, bool request)
997358a6 1352{
3d7a244b
AS
1353 ocsp_location_t *location;
1354 ocsp_certinfo_t *certinfo, **certinfop;
1355 char buf[BUF_LEN];
1356 time_t now;
1357 int cmp = -1;
1358
1359 location = get_ocsp_location(loc, *chain);
1360 if (location == NULL)
08b2d288 1361 {
3d7a244b 1362 location = add_ocsp_location(loc, chain);
08b2d288 1363 }
3d7a244b
AS
1364
1365 /* traverse list of certinfos in increasing order */
1366 certinfop = &location->certinfo;
997358a6 1367 certinfo = *certinfop;
3d7a244b 1368
0354d570 1369 while (certinfo)
3d7a244b
AS
1370 {
1371 cmp = chunk_compare(info->serialNumber, certinfo->serialNumber);
1372 if (cmp <= 0)
1373 break;
1374 certinfop = &certinfo->next;
1375 certinfo = *certinfop;
1376 }
1377
997358a6 1378 if (cmp != 0)
3d7a244b
AS
1379 {
1380 /* add a new certinfo entry */
1381 ocsp_certinfo_t *cnew = malloc_thing(ocsp_certinfo_t);
1382
1383 cnew->serialNumber = chunk_clone(info->serialNumber);
1384 cnew->next = certinfo;
20afe5e9 1385 cnew->trials = 0;
3d7a244b
AS
1386 *certinfop = cnew;
1387 certinfo = cnew;
1388 }
7daf5226 1389
3d7a244b
AS
1390 DBG(DBG_CONTROL,
1391 datatot(info->serialNumber.ptr, info->serialNumber.len, ':'
1392 , buf, BUF_LEN);
1393 DBG_log("ocsp %s for serial %s %s"
1394 , request?"fetch request":"certinfo"
1395 , buf
1396 , (cmp == 0)? (request?"already exists":"updated"):"added")
1397 )
1398
1399 time(&now);
1400
1401 if (request)
1402 {
1403 certinfo->status = CERT_UNDEFINED;
7daf5226 1404
3d7a244b 1405 if (cmp != 0)
08b2d288 1406 {
3d7a244b 1407 certinfo->thisUpdate = now;
08b2d288 1408 }
3d7a244b
AS
1409 certinfo->nextUpdate = UNDEFINED_TIME;
1410 }
1411 else
1412 {
1413 certinfo->status = info->status;
1414 certinfo->revocationTime = info->revocationTime;
1415 certinfo->revocationReason = info->revocationReason;
7daf5226 1416
3d7a244b
AS
1417 certinfo->thisUpdate = (info->thisUpdate != UNDEFINED_TIME)?
1418 info->thisUpdate : now;
997358a6 1419
3d7a244b 1420 certinfo->once = (info->nextUpdate == UNDEFINED_TIME);
997358a6 1421
3d7a244b
AS
1422 certinfo->nextUpdate = (certinfo->once)?
1423 (now + OCSP_DEFAULT_VALID_TIME) : info->nextUpdate;
1424 }
997358a6
MW
1425}
1426
08b2d288
AS
1427/**
1428 * Process received ocsp single response and add it to ocsp cache
997358a6 1429 */
08b2d288
AS
1430static void process_single_response(ocsp_location_t *location,
1431 single_response_t *sres)
997358a6 1432{
3d7a244b
AS
1433 ocsp_certinfo_t *certinfo, **certinfop;
1434 int cmp = -1;
1435
1436 if (sres->hash_algorithm != OID_SHA1)
1437 {
1438 plog("only SHA-1 hash supported in OCSP single response");
1439 return;
1440 }
1441 if (!(chunk_equals(sres->issuer_name_hash, location->authNameID)
1442 && chunk_equals(sres->issuer_key_hash, location->authKeyID)))
1443 {
1444 plog("ocsp single response has wrong issuer");
1445 return;
1446 }
7daf5226 1447
3d7a244b
AS
1448 /* traverse list of certinfos in increasing order */
1449 certinfop = &location->certinfo;
997358a6 1450 certinfo = *certinfop;
3d7a244b 1451
0354d570 1452 while (certinfo)
3d7a244b
AS
1453 {
1454 cmp = chunk_compare(sres->serialNumber, certinfo->serialNumber);
1455 if (cmp <= 0)
1456 break;
1457 certinfop = &certinfo->next;
1458 certinfo = *certinfop;
1459 }
1460
1461 if (cmp != 0)
1462 {
1463 plog("received unrequested cert status from ocsp server");
1464 return;
1465 }
1466
1467 /* unlink cert from ocsp fetch request list */
1468 *certinfop = certinfo->next;
7daf5226 1469
3d7a244b
AS
1470 /* update certinfo using the single response information */
1471 certinfo->thisUpdate = sres->thisUpdate;
1472 certinfo->nextUpdate = sres->nextUpdate;
1473 certinfo->status = sres->status;
1474 certinfo->revocationTime = sres->revocationTime;
1475 certinfo->revocationReason = sres->revocationReason;
7daf5226 1476
3d7a244b
AS
1477 /* add or update certinfo in ocsp cache */
1478 lock_ocsp_cache("process_single_response");
1479 add_certinfo(location, certinfo, &ocsp_cache, FALSE);
1480 unlock_ocsp_cache("process_single_response");
1481
1482 /* free certinfo unlinked from ocsp fetch request list */
1483 free_certinfo(certinfo);
997358a6
MW
1484}
1485
f893bce3
AS
1486/**
1487 * Destroy a response_t object
1488 */
1489static void free_response(response_t *res)
1490{
1491 DESTROY_IF(res->responder_id_name);
1492}
1493
08b2d288
AS
1494/**
1495 * Parse and verify ocsp response and update the ocsp cache
997358a6 1496 */
08b2d288 1497void parse_ocsp(ocsp_location_t *location, chunk_t blob)
997358a6 1498{
3d7a244b 1499 response_t res = empty_response;
997358a6 1500
3d7a244b
AS
1501 /* parse the ocsp response without looking at the single responses yet */
1502 response_status status = parse_ocsp_response(blob, &res);
997358a6 1503
3d7a244b
AS
1504 if (status != STATUS_SUCCESSFUL)
1505 {
1506 plog("error in ocsp response");
f893bce3 1507 goto free;
3d7a244b
AS
1508 }
1509 /* check if there was a nonce in the request */
0354d570 1510 if (location->nonce.ptr && res.nonce.ptr == NULL)
3d7a244b
AS
1511 {
1512 plog("ocsp response contains no nonce, replay attack possible");
1513 }
1514 /* check if the nonce is identical */
0354d570 1515 if (res.nonce.ptr && !chunk_equals(res.nonce, location->nonce))
3d7a244b
AS
1516 {
1517 plog("invalid nonce in ocsp response");
f893bce3 1518 goto free;
3d7a244b
AS
1519 }
1520 /* check if the response is signed by a trusted key */
1521 if (!valid_ocsp_response(&res))
997358a6 1522 {
3d7a244b 1523 plog("invalid ocsp response");
f893bce3 1524 goto free;
3d7a244b
AS
1525 }
1526 DBG(DBG_CONTROL,
1527 DBG_log("valid ocsp response")
1528 )
1529
1530 /* now parse the single responses one at a time */
1531 {
08b2d288 1532 asn1_parser_t *parser;
3d7a244b 1533 chunk_t object;
08b2d288 1534 int objectID;
997358a6 1535
08b2d288 1536 parser = asn1_parser_create(responsesObjects, res.responses);
3d7a244b 1537
08b2d288 1538 while (parser->iterate(parser, &objectID, &object))
997358a6 1539 {
3d7a244b
AS
1540 if (objectID == RESPONSES_SINGLE_RESPONSE)
1541 {
1542 single_response_t sres = empty_single_response;
1543
08b2d288 1544 if (!parse_ocsp_single_response(object,
b9b8a98f 1545 parser->get_level(parser)+1, &sres))
3d7a244b 1546 {
08b2d288 1547 goto end;
3d7a244b 1548 }
08b2d288 1549 process_single_response(location, &sres);
3d7a244b 1550 }
997358a6 1551 }
08b2d288
AS
1552end:
1553 parser->destroy(parser);
997358a6 1554 }
f893bce3
AS
1555
1556free:
1557 free_response(&res);
997358a6 1558}