ocsp request is now fully built but without requestor signature
[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 <string.h>
27 #include <time.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31
32 #include <asn1/oid.h>
33 #include <asn1/asn1.h>
34 #include <utils/identification.h>
35 #include <utils/randomizer.h>
36 #include <debug.h>
37
38 #include "hashers/hasher.h"
39 #include "certinfo.h"
40 #include "x509.h"
41 #include "ocsp.h"
42
43 #define NONCE_LENGTH 16
44
45 typedef struct private_ocsp_t private_ocsp_t;
46
47 /**
48 * Private data of a ocsp_t object.
49 */
50 struct private_ocsp_t {
51 /**
52 * Public interface for this ocsp object.
53 */
54 ocsp_t public;
55
56 /**
57 * CA certificate.
58 */
59 x509_t *cacert;
60
61 /**
62 * Requestor certificate
63 */
64 x509_t *requestor_cert;
65
66 /**
67 * Linked list of ocsp uris
68 */
69 linked_list_t *uris;
70
71 /**
72 * Linked list of certinfos to be requested
73 */
74 linked_list_t *certinfos;
75
76 /**
77 * Nonce required for ocsp request and response
78 */
79 chunk_t nonce;
80
81 /**
82 * SHA-1 hash over issuer distinguished name
83 */
84 chunk_t authNameID;
85 };
86
87 static const char *const response_status_names[] = {
88 "successful",
89 "malformed request",
90 "internal error",
91 "try later",
92 "signature required",
93 "unauthorized"
94 };
95
96 /* response container */
97 typedef struct response_t response_t;
98
99 struct response_t {
100 chunk_t tbs;
101 chunk_t responder_id_name;
102 chunk_t responder_id_key;
103 time_t produced_at;
104 chunk_t responses;
105 chunk_t nonce;
106 int algorithm;
107 chunk_t signature;
108 };
109
110 const response_t empty_response = {
111 { NULL, 0 } , /* tbs */
112 { NULL, 0 } , /* responder_id_name */
113 { NULL, 0 } , /* responder_id_key */
114 UNDEFINED_TIME, /* produced_at */
115 { NULL, 0 } , /* single_response */
116 { NULL, 0 } , /* nonce */
117 OID_UNKNOWN , /* signature_algorithm */
118 { NULL, 0 } /* signature */
119 };
120
121 /* single response container */
122 typedef struct single_response single_response_t;
123
124 struct single_response {
125 single_response_t *next;
126 int hash_algorithm;
127 chunk_t issuer_name_hash;
128 chunk_t issuer_key_hash;
129 chunk_t serialNumber;
130 cert_status_t status;
131 time_t revocationTime;
132 crl_reason_t revocationReason;
133 time_t thisUpdate;
134 time_t nextUpdate;
135 };
136
137 const single_response_t empty_single_response = {
138 NULL , /* *next */
139 OID_UNKNOWN , /* hash_algorithm */
140 { NULL, 0 } , /* issuer_name_hash */
141 { NULL, 0 } , /* issuer_key_hash */
142 { NULL, 0 } , /* serial_number */
143 CERT_UNDEFINED , /* status */
144 UNDEFINED_TIME , /* revocationTime */
145 REASON_UNSPECIFIED, /* revocationReason */
146 UNDEFINED_TIME , /* this_update */
147 UNDEFINED_TIME /* next_update */
148 };
149
150 /* some OCSP specific prefabricated ASN.1 constants */
151
152 static u_char ASN1_nonce_oid_str[] = {
153 0x06, 0x09,
154 0x2B, 0x06,
155 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02
156 };
157
158 static u_char ASN1_response_oid_str[] = {
159 0x06, 0x09,
160 0x2B, 0x06,
161 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04
162 };
163
164 static u_char ASN1_response_content_str[] = {
165 0x04, 0x0D,
166 0x30, 0x0B,
167 0x06, 0x09,
168 0x2B, 0x06,
169 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
170 };
171
172 static const chunk_t ASN1_nonce_oid = chunk_from_buf(ASN1_nonce_oid_str);
173 static const chunk_t ASN1_response_oid = chunk_from_buf(ASN1_response_oid_str);
174 static const chunk_t ASN1_response_content = chunk_from_buf(ASN1_response_content_str);
175
176 /* asn.1 definitions for parsing */
177
178 static const asn1Object_t ocspResponseObjects[] = {
179 { 0, "OCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
180 { 1, "responseStatus", ASN1_ENUMERATED, ASN1_BODY }, /* 1 */
181 { 1, "responseBytesContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 2 */
182 { 2, "responseBytes", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */
183 { 3, "responseType", ASN1_OID, ASN1_BODY }, /* 4 */
184 { 3, "response", ASN1_OCTET_STRING, ASN1_BODY }, /* 5 */
185 { 1, "end opt", ASN1_EOC, ASN1_END } /* 6 */
186 };
187
188 #define OCSP_RESPONSE_STATUS 1
189 #define OCSP_RESPONSE_TYPE 4
190 #define OCSP_RESPONSE 5
191 #define OCSP_RESPONSE_ROOF 7
192
193 static const asn1Object_t basicResponseObjects[] = {
194 { 0, "BasicOCSPResponse", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
195 { 1, "tbsResponseData", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
196 { 2, "versionContext", ASN1_CONTEXT_C_0, ASN1_NONE |
197 ASN1_DEF }, /* 2 */
198 { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */
199 { 2, "responderIdContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 4 */
200 { 3, "responderIdByName", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
201 { 2, "end choice", ASN1_EOC, ASN1_END }, /* 6 */
202 { 2, "responderIdContext", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 7 */
203 { 3, "responderIdByKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 8 */
204 { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */
205 { 2, "producedAt", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 10 */
206 { 2, "responses", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */
207 { 2, "responseExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 12 */
208 { 3, "responseExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 13 */
209 { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 14 */
210 { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 15 */
211 { 5, "critical", ASN1_BOOLEAN, ASN1_BODY |
212 ASN1_DEF }, /* 16 */
213 { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 17 */
214 { 4, "end loop", ASN1_EOC, ASN1_END }, /* 18 */
215 { 2, "end opt", ASN1_EOC, ASN1_END }, /* 19 */
216 { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 20 */
217 { 1, "signature", ASN1_BIT_STRING, ASN1_BODY }, /* 21 */
218 { 1, "certsContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 22 */
219 { 2, "certs", ASN1_SEQUENCE, ASN1_LOOP }, /* 23 */
220 { 3, "certificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 24 */
221 { 2, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
222 { 1, "end opt", ASN1_EOC, ASN1_END } /* 26 */
223 };
224
225 #define BASIC_RESPONSE_TBS_DATA 1
226 #define BASIC_RESPONSE_VERSION 3
227 #define BASIC_RESPONSE_ID_BY_NAME 5
228 #define BASIC_RESPONSE_ID_BY_KEY 8
229 #define BASIC_RESPONSE_PRODUCED_AT 10
230 #define BASIC_RESPONSE_RESPONSES 11
231 #define BASIC_RESPONSE_EXT_ID 15
232 #define BASIC_RESPONSE_CRITICAL 16
233 #define BASIC_RESPONSE_EXT_VALUE 17
234 #define BASIC_RESPONSE_ALGORITHM 20
235 #define BASIC_RESPONSE_SIGNATURE 21
236 #define BASIC_RESPONSE_CERTIFICATE 24
237 #define BASIC_RESPONSE_ROOF 27
238
239 static const asn1Object_t responsesObjects[] = {
240 { 0, "responses", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
241 { 1, "singleResponse", ASN1_EOC, ASN1_RAW }, /* 1 */
242 { 0, "end loop", ASN1_EOC, ASN1_END } /* 2 */
243 };
244
245 #define RESPONSES_SINGLE_RESPONSE 1
246 #define RESPONSES_ROOF 3
247
248 static const asn1Object_t singleResponseObjects[] = {
249 { 0, "singleResponse", ASN1_SEQUENCE, ASN1_BODY }, /* 0 */
250 { 1, "certID", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
251 { 2, "algorithm", ASN1_EOC, ASN1_RAW }, /* 2 */
252 { 2, "issuerNameHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 3 */
253 { 2, "issuerKeyHash", ASN1_OCTET_STRING, ASN1_BODY }, /* 4 */
254 { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 5 */
255 { 1, "certStatusGood", ASN1_CONTEXT_S_0, ASN1_OPT }, /* 6 */
256 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 7 */
257 { 1, "certStatusRevoked", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 8 */
258 { 2, "revocationTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 9 */
259 { 2, "revocationReason", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 10 */
260 { 3, "crlReason", ASN1_ENUMERATED, ASN1_BODY }, /* 11 */
261 { 2, "end opt", ASN1_EOC, ASN1_END }, /* 12 */
262 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 13 */
263 { 1, "certStatusUnknown", ASN1_CONTEXT_S_2, ASN1_OPT }, /* 14 */
264 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 15 */
265 { 1, "thisUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 16 */
266 { 1, "nextUpdateContext", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 17 */
267 { 2, "nextUpdate", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 18 */
268 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 19 */
269 { 1, "singleExtensionsContext", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 20 */
270 { 2, "singleExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 21 */
271 { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */
272 { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 23 */
273 { 4, "critical", ASN1_BOOLEAN, ASN1_BODY |
274 ASN1_DEF }, /* 24 */
275 { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 25 */
276 { 2, "end loop", ASN1_EOC, ASN1_END }, /* 26 */
277 { 1, "end opt", ASN1_EOC, ASN1_END } /* 27 */
278 };
279
280 #define SINGLE_RESPONSE_ALGORITHM 2
281 #define SINGLE_RESPONSE_ISSUER_NAME_HASH 3
282 #define SINGLE_RESPONSE_ISSUER_KEY_HASH 4
283 #define SINGLE_RESPONSE_SERIAL_NUMBER 5
284 #define SINGLE_RESPONSE_CERT_STATUS_GOOD 6
285 #define SINGLE_RESPONSE_CERT_STATUS_REVOKED 8
286 #define SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME 9
287 #define SINGLE_RESPONSE_CERT_STATUS_CRL_REASON 11
288 #define SINGLE_RESPONSE_CERT_STATUS_UNKNOWN 14
289 #define SINGLE_RESPONSE_THIS_UPDATE 16
290 #define SINGLE_RESPONSE_NEXT_UPDATE 18
291 #define SINGLE_RESPONSE_EXT_ID 23
292 #define SINGLE_RESPONSE_CRITICAL 24
293 #define SINGLE_RESPONSE_EXT_VALUE 25
294 #define SINGLE_RESPONSE_ROOF 28
295
296 /**
297 * build requestorName (into TBSRequest)
298 */
299 static chunk_t build_requestor_name(private_ocsp_t *this)
300 {
301 identification_t *requestor_name = this->requestor_cert->get_subject(this->requestor_cert);
302
303 return asn1_wrap(ASN1_CONTEXT_C_1, "m",
304 asn1_simple_object(ASN1_CONTEXT_C_4,
305 requestor_name->get_encoding(requestor_name)));
306 }
307
308 /**
309 * build request (into requestList)
310 * no singleRequestExtensions used
311 */
312 static chunk_t build_request(private_ocsp_t *this, certinfo_t *certinfo)
313 {
314 chunk_t authKeyID = this->cacert->get_subjectKeyID(this->cacert);
315 chunk_t serialNumber = certinfo->get_serialNumber(certinfo);
316
317 chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "cmmm",
318 ASN1_sha1_id,
319 asn1_simple_object(ASN1_OCTET_STRING, this->authNameID),
320 asn1_simple_object(ASN1_OCTET_STRING, authKeyID),
321 asn1_simple_object(ASN1_INTEGER, serialNumber));
322
323 return asn1_wrap(ASN1_SEQUENCE, "m", reqCert);
324 }
325
326 /**
327 * build requestList (into TBSRequest)
328 */
329 static chunk_t build_request_list(private_ocsp_t *this)
330 {
331 chunk_t requestList;
332 size_t datalen = 0;
333 linked_list_t *request_list = linked_list_create();
334
335 {
336 iterator_t *iterator = this->certinfos->create_iterator(this->certinfos, TRUE);
337 certinfo_t *certinfo;
338
339 while (iterator->iterate(iterator, (void**)&certinfo))
340 {
341 chunk_t *request = malloc_thing(chunk_t);
342
343 *request = build_request(this, certinfo);
344 request_list->insert_last(request_list, (void*)request);
345 datalen += request->len;
346 }
347 iterator->destroy(iterator);
348 }
349 {
350 iterator_t *iterator = request_list->create_iterator(request_list, TRUE);
351 chunk_t *request;
352
353 u_char *pos = build_asn1_object(&requestList, ASN1_SEQUENCE, datalen);
354
355 while (iterator->iterate(iterator, (void**)&request))
356 {
357 memcpy(pos, request->ptr, request->len);
358 pos += request->len;
359 free(request->ptr);
360 free(request);
361 }
362 iterator->destroy(iterator);
363 request_list->destroy(request_list);
364 }
365 return requestList;
366 }
367
368 /**
369 * build nonce extension (into requestExtensions)
370 */
371 static chunk_t build_nonce_extension(private_ocsp_t *this)
372 {
373 randomizer_t *randomizer = randomizer_create();
374
375 /* generate a random nonce */
376 randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_LENGTH, &this->nonce);
377 randomizer->destroy(randomizer);
378
379 return asn1_wrap(ASN1_SEQUENCE, "cm",
380 ASN1_nonce_oid,
381 asn1_simple_object(ASN1_OCTET_STRING, this->nonce));
382 }
383
384 /**
385 * build requestExtensions (into TBSRequest)
386 */
387 static chunk_t build_request_ext(private_ocsp_t *this)
388 {
389 return asn1_wrap(ASN1_CONTEXT_C_2, "m",
390 asn1_wrap(ASN1_SEQUENCE, "mm",
391 build_nonce_extension(this),
392 asn1_wrap(ASN1_SEQUENCE, "cc",
393 ASN1_response_oid,
394 ASN1_response_content
395 )
396 )
397 );
398 }
399
400 /**
401 * build TBSRequest (into OCSPRequest)
402 */
403 static chunk_t build_tbs_request(private_ocsp_t *this, bool has_requestor_cert)
404 {
405 /* version is skipped since the default is ok */
406 return asn1_wrap(ASN1_SEQUENCE, "mmm",
407 (has_requestor_cert)? build_requestor_name(this): chunk_empty,
408 build_request_list(this),
409 build_request_ext(this));
410 }
411
412 /**
413 * build signature into ocsp request
414 * gets built only if a request cert with a corresponding private key is found
415 */
416 static chunk_t build_signature(private_ocsp_t *this, chunk_t tbsRequest)
417 {
418 return chunk_empty;
419 }
420
421 /**
422 * assembles an ocsp request and sets the nonce field in private_ocsp_t to the sent nonce
423 */
424 static chunk_t ocsp_build_request(private_ocsp_t *this)
425 {
426 bool has_requestor_cert;
427 chunk_t keyid = this->cacert->get_keyid(this->cacert);
428 chunk_t tbsRequest, signature;
429
430 DBG2("assembling ocsp request");
431 DBG2("issuer: '%D'", this->cacert->get_subject(this->cacert));
432 DBG2("keyid: %#B", &keyid);
433
434 /* looks for requestor cert and matching private key */
435 has_requestor_cert = FALSE;
436
437 /* has_requestor_cert = get_ocsp_requestor_cert(location); */
438
439 /* build content */
440 tbsRequest = build_tbs_request(this, has_requestor_cert);
441
442 /* sign tbsReuqest */
443 signature = (has_requestor_cert)? build_signature(this, tbsRequest): chunk_empty;
444
445 return asn1_wrap(ASN1_SEQUENCE, "mm",
446 tbsRequest,
447 signature);
448
449 return signature;
450 }
451
452 /**
453 * Implements ocsp_t.fetch.
454 */
455 static void fetch(private_ocsp_t *this, certinfo_t *certinfo)
456 {
457 chunk_t request;
458
459 if (this->uris->get_count(this->uris) == 0)
460 {
461 return;
462 }
463 this->certinfos->insert_last(this->certinfos, (void*)certinfo);
464
465 request = ocsp_build_request(this);
466 DBG3("ocsp request: %B", &request);
467 {
468 iterator_t *iterator = this->uris->create_iterator(this->uris, TRUE);
469 identification_t *uri;
470
471 while (iterator->iterate(iterator, (void**)&uri))
472 {
473 DBG1("sending ocsp request to location '%D'", uri);
474 }
475 iterator->destroy(iterator);
476 }
477 free(request.ptr);
478 }
479
480 /**
481 * Implements ocsp_t.destroy.
482 */
483 static void destroy(private_ocsp_t *this)
484 {
485 this->certinfos->destroy(this->certinfos);
486 free(this->authNameID.ptr);
487 free(this->nonce.ptr);
488 free(this);
489 }
490
491 /*
492 * Described in header.
493 */
494 ocsp_t *ocsp_create(x509_t *cacert, linked_list_t *uris)
495 {
496 private_ocsp_t *this = malloc_thing(private_ocsp_t);
497
498 /* initialize */
499 this->cacert = cacert;
500 this->uris = uris;
501 this->certinfos = linked_list_create();
502 {
503 hasher_t *hasher = hasher_create(HASH_SHA1);
504 identification_t *issuer = cacert->get_subject(cacert);
505
506 hasher->allocate_hash(hasher, issuer->get_encoding(issuer),
507 &this->authNameID);
508 hasher->destroy(hasher);
509 }
510
511 /* public functions */
512 this->public.fetch = (void (*) (ocsp_t*,certinfo_t*))fetch;
513 this->public.destroy = (void (*) (ocsp_t*))destroy;
514
515 return &this->public;
516 }