Line data Source code
1 : /* ocsp.c - OCSP (rfc2560)
2 : * Copyright (C) 2003, 2004, 2005, 2006, 2012 g10 Code GmbH
3 : *
4 : * This file is part of KSBA.
5 : *
6 : * KSBA is free software; you can redistribute it and/or modify
7 : * it under the terms of either
8 : *
9 : * - the GNU Lesser General Public License as published by the Free
10 : * Software Foundation; either version 3 of the License, or (at
11 : * your option) any later version.
12 : *
13 : * or
14 : *
15 : * - the GNU General Public License as published by the Free
16 : * Software Foundation; either version 2 of the License, or (at
17 : * your option) any later version.
18 : *
19 : * or both in parallel, as here.
20 : *
21 : * KSBA is distributed in the hope that it will be useful, but WITHOUT
22 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23 : * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
24 : * License for more details.
25 : *
26 : * You should have received a copies of the GNU General Public License
27 : * and the GNU Lesser General Public License along with this program;
28 : * if not, see <http://www.gnu.org/licenses/>.
29 : */
30 :
31 : #include <config.h>
32 : #include <stdio.h>
33 : #include <stdlib.h>
34 : #include <string.h>
35 : #include <assert.h>
36 :
37 : #include "util.h"
38 :
39 : #include "cert.h"
40 : #include "convert.h"
41 : #include "keyinfo.h"
42 : #include "der-encoder.h"
43 : #include "ber-help.h"
44 : #include "ocsp.h"
45 :
46 :
47 : static const char oidstr_sha1[] = "1.3.14.3.2.26";
48 : static const char oidstr_ocsp_basic[] = "1.3.6.1.5.5.7.48.1.1";
49 : static const char oidstr_ocsp_nonce[] = "1.3.6.1.5.5.7.48.1.2";
50 :
51 :
52 : #if 0
53 : static void
54 : dump_hex (const unsigned char *p, size_t n)
55 : {
56 : if (!p)
57 : fputs ("none", stderr);
58 : else
59 : {
60 : for (; n; n--, p++)
61 : fprintf (stderr, " %02X", *p);
62 : }
63 : }
64 : #endif
65 :
66 :
67 : static void
68 0 : parse_skip (unsigned char const **buf, size_t *len, struct tag_info *ti)
69 : {
70 0 : if (ti->length)
71 : {
72 0 : assert (ti->length <= *len);
73 0 : *len -= ti->length;
74 0 : *buf += ti->length;
75 : }
76 0 : }
77 :
78 : static gpg_error_t
79 0 : parse_sequence (unsigned char const **buf, size_t *len, struct tag_info *ti)
80 : {
81 : gpg_error_t err;
82 :
83 0 : err = _ksba_ber_parse_tl (buf, len, ti);
84 0 : if (err)
85 : ;
86 0 : else if (!(ti->class == CLASS_UNIVERSAL && ti->tag == TYPE_SEQUENCE
87 0 : && ti->is_constructed) )
88 0 : err = gpg_error (GPG_ERR_INV_OBJ);
89 0 : else if (ti->length > *len)
90 0 : err = gpg_error (GPG_ERR_BAD_BER);
91 0 : return err;
92 : }
93 :
94 : static gpg_error_t
95 0 : parse_enumerated (unsigned char const **buf, size_t *len, struct tag_info *ti,
96 : size_t maxlen)
97 : {
98 : gpg_error_t err;
99 :
100 0 : err = _ksba_ber_parse_tl (buf, len, ti);
101 0 : if (err)
102 : ;
103 0 : else if (!(ti->class == CLASS_UNIVERSAL && ti->tag == TYPE_ENUMERATED
104 0 : && !ti->is_constructed) )
105 0 : err = gpg_error (GPG_ERR_INV_OBJ);
106 0 : else if (!ti->length)
107 0 : err = gpg_error (GPG_ERR_TOO_SHORT);
108 0 : else if (maxlen && ti->length > maxlen)
109 0 : err = gpg_error (GPG_ERR_TOO_LARGE);
110 0 : else if (ti->length > *len)
111 0 : err = gpg_error (GPG_ERR_BAD_BER);
112 :
113 0 : return err;
114 : }
115 :
116 : static gpg_error_t
117 0 : parse_integer (unsigned char const **buf, size_t *len, struct tag_info *ti)
118 : {
119 : gpg_error_t err;
120 :
121 0 : err = _ksba_ber_parse_tl (buf, len, ti);
122 0 : if (err)
123 : ;
124 0 : else if (!(ti->class == CLASS_UNIVERSAL && ti->tag == TYPE_INTEGER
125 0 : && !ti->is_constructed) )
126 0 : err = gpg_error (GPG_ERR_INV_OBJ);
127 0 : else if (!ti->length)
128 0 : err = gpg_error (GPG_ERR_TOO_SHORT);
129 0 : else if (ti->length > *len)
130 0 : err = gpg_error (GPG_ERR_BAD_BER);
131 :
132 0 : return err;
133 : }
134 :
135 : static gpg_error_t
136 0 : parse_octet_string (unsigned char const **buf, size_t *len, struct tag_info *ti)
137 : {
138 : gpg_error_t err;
139 :
140 0 : err= _ksba_ber_parse_tl (buf, len, ti);
141 0 : if (err)
142 : ;
143 0 : else if (!(ti->class == CLASS_UNIVERSAL && ti->tag == TYPE_OCTET_STRING
144 0 : && !ti->is_constructed) )
145 0 : err = gpg_error (GPG_ERR_INV_OBJ);
146 0 : else if (!ti->length)
147 0 : err = gpg_error (GPG_ERR_TOO_SHORT);
148 0 : else if (ti->length > *len)
149 0 : err = gpg_error (GPG_ERR_BAD_BER);
150 :
151 0 : return err;
152 : }
153 :
154 :
155 : /* Note that R_BOOL will only be set if a value has been given. Thus
156 : the caller should set it to the default value prior to calling this
157 : function. Obviously no call to parse_skip is required after
158 : calling this function. */
159 : static gpg_error_t
160 0 : parse_optional_boolean (unsigned char const **buf, size_t *len, int *r_bool)
161 : {
162 : gpg_error_t err;
163 : struct tag_info ti;
164 :
165 0 : err = _ksba_ber_parse_tl (buf, len, &ti);
166 0 : if (err)
167 : ;
168 0 : else if (!ti.length)
169 0 : err = gpg_error (GPG_ERR_TOO_SHORT);
170 0 : else if (ti.length > *len)
171 0 : err = gpg_error (GPG_ERR_BAD_BER);
172 0 : else if (ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_BOOLEAN
173 0 : && !ti.is_constructed)
174 : {
175 0 : if (ti.length != 1)
176 0 : err = gpg_error (GPG_ERR_BAD_BER);
177 0 : *r_bool = !!**buf;
178 0 : parse_skip (buf, len, &ti);
179 : }
180 : else
181 : { /* Undo the read. */
182 0 : *buf -= ti.nhdr;
183 0 : *len += ti.nhdr;
184 : }
185 :
186 0 : return err;
187 : }
188 :
189 :
190 :
191 : static gpg_error_t
192 0 : parse_object_id_into_str (unsigned char const **buf, size_t *len, char **oid)
193 : {
194 : struct tag_info ti;
195 : gpg_error_t err;
196 :
197 0 : *oid = NULL;
198 0 : err = _ksba_ber_parse_tl (buf, len, &ti);
199 0 : if (err)
200 : ;
201 0 : else if (!(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_OBJECT_ID
202 0 : && !ti.is_constructed) )
203 0 : err = gpg_error (GPG_ERR_INV_OBJ);
204 0 : else if (!ti.length)
205 0 : err = gpg_error (GPG_ERR_TOO_SHORT);
206 0 : else if (ti.length > *len)
207 0 : err = gpg_error (GPG_ERR_BAD_BER);
208 0 : else if (!(*oid = ksba_oid_to_str (*buf, ti.length)))
209 0 : err = gpg_error_from_syserror ();
210 : else
211 : {
212 0 : *buf += ti.length;
213 0 : *len -= ti.length;
214 : }
215 0 : return err;
216 : }
217 :
218 :
219 : static gpg_error_t
220 0 : parse_asntime_into_isotime (unsigned char const **buf, size_t *len,
221 : ksba_isotime_t isotime)
222 : {
223 : struct tag_info ti;
224 : gpg_error_t err;
225 :
226 0 : err = _ksba_ber_parse_tl (buf, len, &ti);
227 0 : if (err)
228 : ;
229 0 : else if ( !(ti.class == CLASS_UNIVERSAL
230 0 : && (ti.tag == TYPE_UTC_TIME || ti.tag == TYPE_GENERALIZED_TIME)
231 0 : && !ti.is_constructed) )
232 0 : err = gpg_error (GPG_ERR_INV_OBJ);
233 0 : else if (ti.length > *len)
234 0 : err = gpg_error (GPG_ERR_INV_BER);
235 0 : else if (!(err = _ksba_asntime_to_iso (*buf, ti.length,
236 0 : ti.tag == TYPE_UTC_TIME, isotime)))
237 0 : parse_skip (buf, len, &ti);
238 :
239 0 : return err;
240 : }
241 :
242 :
243 : static gpg_error_t
244 0 : parse_context_tag (unsigned char const **buf, size_t *len, struct tag_info *ti,
245 : int tag)
246 : {
247 : gpg_error_t err;
248 :
249 0 : err = _ksba_ber_parse_tl (buf, len, ti);
250 0 : if (err)
251 : ;
252 0 : else if (!(ti->class == CLASS_CONTEXT && ti->tag == tag
253 0 : && ti->is_constructed) )
254 0 : err = gpg_error (GPG_ERR_INV_OBJ);
255 0 : else if (ti->length > *len)
256 0 : err = gpg_error (GPG_ERR_BAD_BER);
257 :
258 0 : return err;
259 : }
260 :
261 :
262 :
263 : /* Create a new OCSP object and retrun it in R_OCSP. Return 0 on
264 : success or an error code.
265 : */
266 : gpg_error_t
267 0 : ksba_ocsp_new (ksba_ocsp_t *r_ocsp)
268 : {
269 0 : *r_ocsp = xtrycalloc (1, sizeof **r_ocsp);
270 0 : if (!*r_ocsp)
271 0 : return gpg_error_from_syserror ();
272 0 : return 0;
273 : }
274 :
275 :
276 : static void
277 0 : release_ocsp_certlist (struct ocsp_certlist_s *cl)
278 : {
279 0 : while (cl)
280 : {
281 0 : struct ocsp_certlist_s *tmp = cl->next;
282 0 : ksba_cert_release (cl->cert);
283 0 : xfree (cl);
284 0 : cl = tmp;
285 : }
286 0 : }
287 :
288 :
289 : static void
290 0 : release_ocsp_extensions (struct ocsp_extension_s *ex)
291 : {
292 0 : while (ex)
293 : {
294 0 : struct ocsp_extension_s *tmp = ex->next;
295 0 : xfree (ex);
296 0 : ex = tmp;
297 : }
298 0 : }
299 :
300 :
301 : /* Release the OCSP object and all its resources. Passing NULL for
302 : OCSP is a valid nop. */
303 : void
304 0 : ksba_ocsp_release (ksba_ocsp_t ocsp)
305 : {
306 : struct ocsp_reqitem_s *ri;
307 :
308 0 : if (!ocsp)
309 0 : return;
310 0 : xfree (ocsp->digest_oid);
311 0 : xfree (ocsp->request_buffer);
312 0 : for (; (ri=ocsp->requestlist); ri = ocsp->requestlist )
313 : {
314 0 : ocsp->requestlist = ri->next;
315 0 : ksba_cert_release (ri->cert);
316 0 : ksba_cert_release (ri->issuer_cert);
317 0 : release_ocsp_extensions (ri->single_extensions);
318 0 : xfree (ri->serialno);
319 : }
320 0 : xfree (ocsp->sigval);
321 0 : xfree (ocsp->responder_id.name);
322 0 : xfree (ocsp->responder_id.keyid);
323 0 : release_ocsp_certlist (ocsp->received_certs);
324 0 : release_ocsp_extensions (ocsp->response_extensions);
325 0 : xfree (ocsp);
326 : }
327 :
328 :
329 :
330 : /* Set the hash algorithm to be used for signing the request to OID.
331 : Using this function will force the creation of a signed
332 : request. */
333 : gpg_error_t
334 0 : ksba_ocsp_set_digest_algo (ksba_ocsp_t ocsp, const char *oid)
335 : {
336 0 : if (!ocsp || !oid || !*oid)
337 0 : return gpg_error (GPG_ERR_INV_VALUE);
338 0 : if (ocsp->digest_oid)
339 0 : xfree (ocsp->digest_oid);
340 0 : ocsp->digest_oid = xtrystrdup (oid);
341 0 : if (!ocsp->digest_oid)
342 0 : return gpg_error_from_syserror ();
343 0 : return 0;
344 : }
345 :
346 :
347 : gpg_error_t
348 0 : ksba_ocsp_set_requestor (ksba_ocsp_t ocsp, ksba_cert_t cert)
349 : {
350 : (void)ocsp;
351 : (void)cert;
352 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
353 : }
354 :
355 :
356 : /* Add the certificate CERT for which the status is to be requested
357 : and it's issuer certificate ISSUER_CERT to the context. This
358 : function may be called multiple time to create a list of targets to
359 : get combined into one actual request. */
360 : gpg_error_t
361 0 : ksba_ocsp_add_target (ksba_ocsp_t ocsp,
362 : ksba_cert_t cert, ksba_cert_t issuer_cert)
363 : {
364 : struct ocsp_reqitem_s *ri;
365 :
366 0 : if (!ocsp || !cert || !issuer_cert)
367 0 : return gpg_error (GPG_ERR_INV_VALUE);
368 :
369 0 : ri = xtrycalloc (1, sizeof *ri);
370 0 : if (!ri)
371 0 : return gpg_error_from_syserror ();
372 0 : ksba_cert_ref (cert);
373 0 : ri->cert = cert;
374 0 : ksba_cert_ref (issuer_cert);
375 0 : ri->issuer_cert = issuer_cert;
376 :
377 0 : ri->next = ocsp->requestlist;
378 0 : ocsp->requestlist = ri;
379 :
380 0 : return 0;
381 : }
382 :
383 :
384 : /* Set the nonce to be used for the request to the content of the
385 : buffer NONCE of size NONCELEN. Libksba may have an upper limit of
386 : the allowed size of the nonce; if the supplied nonce is larger it
387 : will be truncated and the actual used length of the nonce returned.
388 : To detect the implementation limit (which should be considered as a
389 : good suggestion), the function may be called with NULL for NONCE,
390 : in which case the maximal usable noncelength is returned. The
391 : function returns the length of the nonce which will be used. */
392 : size_t
393 0 : ksba_ocsp_set_nonce (ksba_ocsp_t ocsp, unsigned char *nonce, size_t noncelen)
394 : {
395 0 : if (!ocsp)
396 0 : return 0;
397 0 : if (!nonce)
398 0 : return sizeof ocsp->nonce;
399 0 : if (noncelen > sizeof ocsp->nonce)
400 0 : noncelen = sizeof ocsp->nonce;
401 0 : if (noncelen)
402 : {
403 0 : memcpy (ocsp->nonce, nonce, noncelen);
404 : }
405 0 : ocsp->noncelen = noncelen;
406 0 : return noncelen;
407 : }
408 :
409 :
410 : /* Compute the SHA-1 nameHash for the certificate CERT and put it in
411 : the buffer SHA1_BUFFER which must have been allocated to at least
412 : 20 bytes. */
413 : static gpg_error_t
414 0 : issuer_name_hash (ksba_cert_t cert, unsigned char *sha1_buffer)
415 : {
416 : gpg_error_t err;
417 : const unsigned char *ptr;
418 : size_t length, dummy;
419 :
420 0 : err = _ksba_cert_get_subject_dn_ptr (cert, &ptr, &length);
421 0 : if (!err)
422 : {
423 0 : err = _ksba_hash_buffer (NULL, ptr, length, 20, sha1_buffer, &dummy);
424 0 : if (!err && dummy != 20)
425 0 : err = gpg_error (GPG_ERR_BUG);
426 : }
427 0 : return err;
428 : }
429 :
430 : /* Compute the SHA-1 hash of the public key of CERT and put it in teh
431 : buffer SHA1_BUFFER which must have been allocated with at least 20
432 : bytes. */
433 : static gpg_error_t
434 0 : issuer_key_hash (ksba_cert_t cert, unsigned char *sha1_buffer)
435 : {
436 : gpg_error_t err;
437 : const unsigned char *ptr;
438 : size_t length, dummy;
439 :
440 0 : err = _ksba_cert_get_public_key_ptr (cert, &ptr, &length);
441 0 : if (!err)
442 : {
443 0 : err = _ksba_hash_buffer (NULL, ptr, length, 20, sha1_buffer, &dummy);
444 0 : if (!err && dummy != 20)
445 0 : err = gpg_error (GPG_ERR_BUG);
446 : }
447 0 : return err;
448 : }
449 :
450 :
451 : /* Write the extensions for a request to WOUT. */
452 : static gpg_error_t
453 0 : write_request_extensions (ksba_ocsp_t ocsp, ksba_writer_t wout)
454 : {
455 : gpg_error_t err;
456 : unsigned char *buf;
457 : size_t buflen;
458 : unsigned char *p;
459 : size_t derlen;
460 0 : ksba_writer_t w1 = NULL;
461 0 : ksba_writer_t w2 = NULL;
462 :
463 0 : if (!ocsp->noncelen)
464 0 : return 0; /* We do only support the nonce extension. */
465 :
466 : /* Create writer objects for construction of the extension. */
467 0 : err = ksba_writer_new (&w2);
468 0 : if (!err)
469 0 : err = ksba_writer_set_mem (w2, 256);
470 0 : if (!err)
471 0 : err = ksba_writer_new (&w1);
472 0 : if (!err)
473 0 : err = ksba_writer_set_mem (w1, 256);
474 0 : if (err)
475 0 : goto leave;
476 :
477 : /* Write OID and and nonce. */
478 0 : err = ksba_oid_from_str (oidstr_ocsp_nonce, &buf, &buflen);
479 0 : if (err)
480 0 : goto leave;
481 0 : err = _ksba_ber_write_tl (w1, TYPE_OBJECT_ID, CLASS_UNIVERSAL, 0, buflen);
482 0 : if (!err)
483 0 : err = ksba_writer_write (w1, buf, buflen);
484 0 : xfree (buf); buf = NULL;
485 : /* We known that the nonce is short enough to put the tag into 2 bytes, thus
486 : we write the encapsulating octet string directly with a fixed length. */
487 0 : if (!err)
488 0 : err = _ksba_ber_write_tl (w1, TYPE_OCTET_STRING, CLASS_UNIVERSAL, 0,
489 0 : 2+ocsp->noncelen);
490 0 : if (!err)
491 0 : err = _ksba_ber_write_tl (w1, TYPE_OCTET_STRING, CLASS_UNIVERSAL, 0,
492 : ocsp->noncelen);
493 0 : if (!err)
494 0 : err = ksba_writer_write (w1, ocsp->nonce, ocsp->noncelen);
495 :
496 : /* Put a sequence around. */
497 0 : p = ksba_writer_snatch_mem (w1, &derlen);
498 0 : if (!p)
499 : {
500 0 : err = ksba_writer_error (w1);
501 0 : goto leave;
502 : }
503 0 : err = _ksba_ber_write_tl (w2, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, derlen);
504 0 : if (!err)
505 0 : err = ksba_writer_write (w2, p, derlen);
506 0 : xfree (p); p = NULL;
507 :
508 : /* Put the sequence around all extensions. */
509 0 : err = ksba_writer_set_mem (w1, 256);
510 0 : if (err)
511 0 : goto leave;
512 0 : p = ksba_writer_snatch_mem (w2, &derlen);
513 0 : if (!p)
514 : {
515 0 : err = ksba_writer_error (w2);
516 0 : goto leave;
517 : }
518 0 : err = _ksba_ber_write_tl (w1, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, derlen);
519 0 : if (!err)
520 0 : err = ksba_writer_write (w1, p, derlen);
521 0 : xfree (p); p = NULL;
522 :
523 : /* And put a context tag around everything. */
524 0 : p = ksba_writer_snatch_mem (w1, &derlen);
525 0 : if (!p)
526 : {
527 0 : err = ksba_writer_error (w1);
528 0 : goto leave;
529 : }
530 0 : err = _ksba_ber_write_tl (wout, 2, CLASS_CONTEXT, 1, derlen);
531 0 : if (!err)
532 0 : err = ksba_writer_write (wout, p, derlen);
533 0 : xfree (p); p = NULL;
534 :
535 :
536 : leave:
537 0 : ksba_writer_release (w2);
538 0 : ksba_writer_release (w1);
539 0 : return err;
540 : }
541 :
542 :
543 : /* Build a request from the current context. The function checks that
544 : all necessary information have been set and stores the prepared
545 : request in the context. A subsequent ksba_ocsp_build_request may
546 : then be used to retrieve this request. Optional the requestmay be
547 : signed beofre calling ksba_ocsp_build_request.
548 : */
549 : gpg_error_t
550 0 : ksba_ocsp_prepare_request (ksba_ocsp_t ocsp)
551 : {
552 : gpg_error_t err;
553 : struct ocsp_reqitem_s *ri;
554 : unsigned char *p;
555 : const unsigned char *der;
556 : size_t derlen;
557 0 : ksba_writer_t w1 = NULL;
558 0 : ksba_writer_t w2 = NULL;
559 0 : ksba_writer_t w3 = NULL;
560 : ksba_writer_t w4, w5, w6, w7; /* Used as aliases. */
561 :
562 0 : if (!ocsp)
563 0 : return gpg_error (GPG_ERR_INV_VALUE);
564 :
565 0 : xfree (ocsp->request_buffer);
566 0 : ocsp->request_buffer = NULL;
567 0 : ocsp->request_buflen = 0;
568 :
569 0 : if (!ocsp->requestlist)
570 0 : return gpg_error (GPG_ERR_MISSING_ACTION);
571 :
572 : /* Create three writer objects for construction of the request. */
573 0 : err = ksba_writer_new (&w3);
574 0 : if (!err)
575 0 : err = ksba_writer_set_mem (w3, 2048);
576 0 : if (!err)
577 0 : err = ksba_writer_new (&w2);
578 0 : if (!err)
579 0 : err = ksba_writer_new (&w1);
580 0 : if (err)
581 0 : goto leave;
582 :
583 :
584 : /* Loop over all single requests. */
585 0 : for (ri=ocsp->requestlist; ri; ri = ri->next)
586 : {
587 0 : err = ksba_writer_set_mem (w2, 256);
588 0 : if (!err)
589 0 : err = ksba_writer_set_mem (w1, 256);
590 0 : if (err)
591 0 : goto leave;
592 :
593 : /* Write the AlgorithmIdentifier. */
594 0 : err = _ksba_der_write_algorithm_identifier (w1, oidstr_sha1, NULL, 0);
595 0 : if (err)
596 0 : goto leave;
597 :
598 : /* Compute the issuerNameHash and write it into the CertID object. */
599 0 : err = issuer_name_hash (ri->issuer_cert, ri->issuer_name_hash);
600 0 : if (!err)
601 0 : err = _ksba_ber_write_tl (w1, TYPE_OCTET_STRING, CLASS_UNIVERSAL, 0,20);
602 0 : if (!err)
603 0 : err = ksba_writer_write (w1, ri->issuer_name_hash, 20);
604 0 : if(err)
605 0 : goto leave;
606 :
607 : /* Compute the issuerKeyHash and write it. */
608 0 : err = issuer_key_hash (ri->issuer_cert, ri->issuer_key_hash);
609 0 : if (!err)
610 0 : err = _ksba_ber_write_tl (w1, TYPE_OCTET_STRING, CLASS_UNIVERSAL, 0,20);
611 0 : if (!err)
612 0 : err = ksba_writer_write (w1, ri->issuer_key_hash, 20);
613 0 : if (err)
614 0 : goto leave;
615 :
616 : /* Write the serialNumber of the certificate to be checked. */
617 0 : err = _ksba_cert_get_serial_ptr (ri->cert, &der, &derlen);
618 0 : if (!err)
619 0 : err = _ksba_ber_write_tl (w1, TYPE_INTEGER, CLASS_UNIVERSAL, 0, derlen);
620 0 : if (!err)
621 0 : err = ksba_writer_write (w1, der, derlen);
622 0 : if (err)
623 0 : goto leave;
624 0 : xfree (ri->serialno);
625 0 : ri->serialno = xtrymalloc (derlen);
626 0 : if (!ri->serialno)
627 : {
628 0 : err = gpg_error_from_syserror ();
629 0 : goto leave;
630 : }
631 0 : memcpy (ri->serialno, der, derlen);
632 0 : ri->serialnolen = derlen;
633 :
634 :
635 : /* Now write it out as a sequence to the outer certID object. */
636 0 : p = ksba_writer_snatch_mem (w1, &derlen);
637 0 : if (!p)
638 : {
639 0 : err = ksba_writer_error (w1);
640 0 : goto leave;
641 : }
642 0 : err = _ksba_ber_write_tl (w2, TYPE_SEQUENCE, CLASS_UNIVERSAL,
643 : 1, derlen);
644 0 : if (!err)
645 0 : err = ksba_writer_write (w2, p, derlen);
646 0 : xfree (p); p = NULL;
647 0 : if (err)
648 0 : goto leave;
649 :
650 : /* Here we would write singleRequestExtensions. */
651 :
652 : /* Now write it out as a sequence to the outer Request object. */
653 0 : p = ksba_writer_snatch_mem (w2, &derlen);
654 0 : if (!p)
655 : {
656 0 : err = ksba_writer_error (w2);
657 0 : goto leave;
658 : }
659 0 : err = _ksba_ber_write_tl (w3, TYPE_SEQUENCE, CLASS_UNIVERSAL,
660 : 1, derlen);
661 0 : if (!err)
662 0 : err = ksba_writer_write (w3, p, derlen);
663 0 : xfree (p); p = NULL;
664 0 : if (err)
665 0 : goto leave;
666 :
667 : } /* End of looping over single requests. */
668 :
669 : /* Reuse writers; for clarity, use new names. */
670 0 : w4 = w1;
671 0 : w5 = w2;
672 0 : err = ksba_writer_set_mem (w4, 2048);
673 0 : if (!err)
674 0 : err = ksba_writer_set_mem (w5, 2048);
675 0 : if (err)
676 0 : goto leave;
677 :
678 : /* Put a sequence tag before the requestList. */
679 0 : p = ksba_writer_snatch_mem (w3, &derlen);
680 0 : if (!p)
681 : {
682 0 : err = ksba_writer_error (w3);
683 0 : goto leave;
684 : }
685 0 : err = _ksba_ber_write_tl (w4, TYPE_SEQUENCE, CLASS_UNIVERSAL,
686 : 1, derlen);
687 0 : if (!err)
688 0 : err = ksba_writer_write (w4, p, derlen);
689 0 : xfree (p); p = NULL;
690 0 : if (err)
691 0 : goto leave;
692 :
693 : /* The requestExtensions go here. */
694 0 : err = write_request_extensions (ocsp, w4);
695 :
696 : /* Write the tbsRequest. */
697 :
698 : /* The version is default, thus we don't write it. */
699 :
700 : /* The requesterName would go here. */
701 :
702 : /* Write the requestList. */
703 0 : p = ksba_writer_snatch_mem (w4, &derlen);
704 0 : if (!p)
705 : {
706 0 : err = ksba_writer_error (w4);
707 0 : goto leave;
708 : }
709 0 : err = _ksba_ber_write_tl (w5, TYPE_SEQUENCE, CLASS_UNIVERSAL,
710 : 1, derlen);
711 0 : if (!err)
712 0 : err = ksba_writer_write (w5, p, derlen);
713 0 : xfree (p); p = NULL;
714 0 : if (err)
715 0 : goto leave;
716 :
717 : /* Reuse writers; for clarity, use new names. */
718 0 : w6 = w3;
719 0 : w7 = w4;
720 0 : err = ksba_writer_set_mem (w6, 2048);
721 0 : if (!err)
722 0 : err = ksba_writer_set_mem (w7, 2048);
723 0 : if (err)
724 0 : goto leave;
725 :
726 : /* Prepend a sequence tag. */
727 0 : p = ksba_writer_snatch_mem (w5, &derlen);
728 0 : if (!p)
729 : {
730 0 : err = ksba_writer_error (w5);
731 0 : goto leave;
732 : }
733 0 : err = _ksba_ber_write_tl (w6, TYPE_SEQUENCE, CLASS_UNIVERSAL,
734 : 1, derlen);
735 0 : if (!err)
736 0 : err = ksba_writer_write (w6, p, derlen);
737 0 : xfree (p); p = NULL;
738 0 : if (err)
739 0 : goto leave;
740 :
741 : /* Write the ocspRequest. */
742 :
743 : /* Note that we do not support the optional signature, because this
744 : saves us one writer object. */
745 :
746 : /* Prepend a sequence tag. */
747 : /* p = ksba_writer_snatch_mem (w6, &derlen); */
748 : /* if (!p) */
749 : /* { */
750 : /* err = ksba_writer_error (w6); */
751 : /* goto leave; */
752 : /* } */
753 : /* err = _ksba_ber_write_tl (w7, TYPE_SEQUENCE, CLASS_UNIVERSAL, */
754 : /* 1, derlen); */
755 : /* if (!err) */
756 : /* err = ksba_writer_write (w7, p, derlen); */
757 : /* xfree (p); p = NULL; */
758 : /* if (err) */
759 : /* goto leave; */
760 :
761 :
762 : /* Read out the entire request. */
763 0 : p = ksba_writer_snatch_mem (w6, &derlen);
764 0 : if (!p)
765 : {
766 0 : err = ksba_writer_error (w6);
767 0 : goto leave;
768 : }
769 0 : ocsp->request_buffer = p;
770 0 : ocsp->request_buflen = derlen;
771 : /* Ready. */
772 :
773 : leave:
774 0 : ksba_writer_release (w3);
775 0 : ksba_writer_release (w2);
776 0 : ksba_writer_release (w1);
777 0 : return err;
778 : }
779 :
780 :
781 : gpg_error_t
782 0 : ksba_ocsp_hash_request (ksba_ocsp_t ocsp,
783 : void (*hasher)(void *, const void *,
784 : size_t length),
785 : void *hasher_arg)
786 : {
787 : (void)ocsp;
788 : (void)hasher;
789 : (void)hasher_arg;
790 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
791 : }
792 :
793 :
794 : gpg_error_t
795 0 : ksba_ocsp_set_sig_val (ksba_ocsp_t ocsp,
796 : ksba_const_sexp_t sigval)
797 : {
798 : (void)ocsp;
799 : (void)sigval;
800 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
801 : }
802 :
803 :
804 : gpg_error_t
805 0 : ksba_ocsp_add_cert (ksba_ocsp_t ocsp, ksba_cert_t cert)
806 : {
807 : (void)ocsp;
808 : (void)cert;
809 0 : return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
810 : }
811 :
812 :
813 :
814 : /* Build a request from the current context. The function checks that
815 : all necessary information have been set and then returns an
816 : allocated buffer with the resulting request.
817 : */
818 : gpg_error_t
819 0 : ksba_ocsp_build_request (ksba_ocsp_t ocsp,
820 : unsigned char **r_buffer, size_t *r_buflen)
821 : {
822 : gpg_error_t err;
823 :
824 0 : if (!ocsp || !r_buffer || !r_buflen)
825 0 : return gpg_error (GPG_ERR_INV_VALUE);
826 0 : *r_buffer = NULL;
827 0 : *r_buflen = 0;
828 :
829 0 : if (!ocsp->requestlist)
830 0 : return gpg_error (GPG_ERR_MISSING_ACTION);
831 0 : if (!ocsp->request_buffer)
832 : {
833 : /* No prepare done, do it now. */
834 0 : err = ksba_ocsp_prepare_request (ocsp);
835 0 : if (err)
836 0 : return err;
837 0 : assert (ocsp->request_buffer);
838 : }
839 0 : *r_buffer = ocsp->request_buffer;
840 0 : *r_buflen = ocsp->request_buflen;
841 0 : ocsp->request_buffer = NULL;
842 0 : ocsp->request_buflen = 0;
843 0 : return 0;
844 : }
845 :
846 :
847 :
848 : /*
849 : Parse the response extensions and store them aways. While doing
850 : this we also check the nonce extension. A typical data ASN.1 blob
851 : with only the nonce extension as passed to this function is:
852 :
853 : SEQUENCE {
854 : SEQUENCE {
855 : OBJECT IDENTIFIER ocspNonce (1 3 6 1 5 5 7 48 1 2)
856 : OCTET STRING, encapsulates {
857 : INTEGER
858 : 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50
859 : }
860 : }
861 : }
862 : */
863 :
864 : static int
865 0 : parse_response_extensions (ksba_ocsp_t ocsp,
866 : const unsigned char *data, size_t datalen)
867 : {
868 : gpg_error_t err;
869 : struct tag_info ti;
870 : size_t length;
871 0 : char *oid = NULL;
872 :
873 0 : assert (!ocsp->response_extensions);
874 0 : err = parse_sequence (&data, &datalen, &ti);
875 0 : if (err)
876 0 : goto leave;
877 0 : length = ti.length;
878 0 : while (length)
879 : {
880 : struct ocsp_extension_s *ex;
881 : int is_crit;
882 :
883 0 : err = parse_sequence (&data, &datalen, &ti);
884 0 : if (err)
885 0 : goto leave;
886 0 : if (length < ti.nhdr + ti.length)
887 : {
888 0 : err = gpg_error (GPG_ERR_BAD_BER);
889 0 : goto leave;
890 : }
891 0 : length -= ti.nhdr + ti.length;
892 :
893 0 : xfree (oid);
894 0 : err = parse_object_id_into_str (&data, &datalen, &oid);
895 0 : if (err)
896 0 : goto leave;
897 0 : is_crit = 0;
898 0 : err = parse_optional_boolean (&data, &datalen, &is_crit);
899 0 : if (err)
900 0 : goto leave;
901 0 : err = parse_octet_string (&data, &datalen, &ti);
902 0 : if (err)
903 0 : goto leave;
904 0 : if (!strcmp (oid, oidstr_ocsp_nonce))
905 : {
906 0 : err = parse_octet_string (&data, &datalen, &ti);
907 0 : if (err)
908 0 : goto leave;
909 0 : if (ocsp->noncelen != ti.length
910 0 : || memcmp (ocsp->nonce, data, ti.length))
911 0 : ocsp->bad_nonce = 1;
912 : else
913 0 : ocsp->good_nonce = 1;
914 : }
915 0 : ex = xtrymalloc (sizeof *ex + strlen (oid) + ti.length);
916 0 : if (!ex)
917 : {
918 0 : err = gpg_error_from_syserror ();
919 0 : goto leave;
920 : }
921 0 : ex->crit = is_crit;
922 0 : strcpy (ex->data, oid);
923 0 : ex->data[strlen (oid)] = 0;
924 0 : ex->off = strlen (oid) + 1;
925 0 : ex->len = ti.length;
926 0 : memcpy (ex->data + ex->off, data, ti.length);
927 0 : ex->next = ocsp->response_extensions;
928 0 : ocsp->response_extensions = ex;
929 :
930 0 : parse_skip (&data, &datalen, &ti); /* Skip the octet string / integer. */
931 : }
932 :
933 : leave:
934 0 : xfree (oid);
935 0 : return err;
936 : }
937 :
938 :
939 : /*
940 : Parse single extensions and store them away.
941 : */
942 : static int
943 0 : parse_single_extensions (struct ocsp_reqitem_s *ri,
944 : const unsigned char *data, size_t datalen)
945 : {
946 : gpg_error_t err;
947 : struct tag_info ti;
948 : size_t length;
949 0 : char *oid = NULL;
950 :
951 0 : assert (ri && !ri->single_extensions);
952 0 : err = parse_sequence (&data, &datalen, &ti);
953 0 : if (err)
954 0 : goto leave;
955 0 : length = ti.length;
956 0 : while (length)
957 : {
958 : struct ocsp_extension_s *ex;
959 : int is_crit;
960 :
961 0 : err = parse_sequence (&data, &datalen, &ti);
962 0 : if (err)
963 0 : goto leave;
964 0 : if (length < ti.nhdr + ti.length)
965 : {
966 0 : err = gpg_error (GPG_ERR_BAD_BER);
967 0 : goto leave;
968 : }
969 0 : length -= ti.nhdr + ti.length;
970 :
971 0 : xfree (oid);
972 0 : err = parse_object_id_into_str (&data, &datalen, &oid);
973 0 : if (err)
974 0 : goto leave;
975 0 : is_crit = 0;
976 0 : err = parse_optional_boolean (&data, &datalen, &is_crit);
977 0 : if (err)
978 0 : goto leave;
979 0 : err = parse_octet_string (&data, &datalen, &ti);
980 0 : if (err)
981 0 : goto leave;
982 0 : ex = xtrymalloc (sizeof *ex + strlen (oid) + ti.length);
983 0 : if (!ex)
984 : {
985 0 : err = gpg_error_from_syserror ();
986 0 : goto leave;
987 : }
988 0 : ex->crit = is_crit;
989 0 : strcpy (ex->data, oid);
990 0 : ex->data[strlen (oid)] = 0;
991 0 : ex->off = strlen (oid) + 1;
992 0 : ex->len = ti.length;
993 0 : memcpy (ex->data + ex->off, data, ti.length);
994 0 : ex->next = ri->single_extensions;
995 0 : ri->single_extensions = ex;
996 :
997 0 : parse_skip (&data, &datalen, &ti); /* Skip the octet string / integer. */
998 : }
999 :
1000 : leave:
1001 0 : xfree (oid);
1002 0 : return err;
1003 : }
1004 :
1005 :
1006 : /* Parse the first part of a response:
1007 :
1008 : OCSPResponse ::= SEQUENCE {
1009 : responseStatus OCSPResponseStatus,
1010 : responseBytes [0] EXPLICIT ResponseBytes OPTIONAL }
1011 :
1012 : OCSPResponseStatus ::= ENUMERATED {
1013 : successful (0), --Response has valid confirmations
1014 : malformedRequest (1), --Illegal confirmation request
1015 : internalError (2), --Internal error in issuer
1016 : tryLater (3), --Try again later
1017 : --(4) is not used
1018 : sigRequired (5), --Must sign the request
1019 : unauthorized (6) --Request unauthorized
1020 : }
1021 :
1022 : ResponseBytes ::= SEQUENCE {
1023 : responseType OBJECT IDENTIFIER,
1024 : response OCTET STRING }
1025 :
1026 : On success the RESPONSE_STATUS field of OCSP will be set to the
1027 : response status and DATA will now point to the first byte in the
1028 : octet string of the response; RLEN will be set to the length of
1029 : this octet string. Note thate DATALEN is also updated but might
1030 : point to a value larger than RLEN points to, if the provided data
1031 : is a part of a larger image. */
1032 : static gpg_error_t
1033 0 : parse_response_status (ksba_ocsp_t ocsp,
1034 : unsigned char const **data, size_t *datalen,
1035 : size_t *rlength)
1036 : {
1037 : gpg_error_t err;
1038 : struct tag_info ti;
1039 : char *oid;
1040 :
1041 0 : *rlength = 0;
1042 : /* Parse the OCSPResponse sequence. */
1043 0 : err = parse_sequence (data, datalen, &ti);
1044 0 : if (err)
1045 0 : return err;
1046 : /* Parse the OCSPResponseStatus. */
1047 0 : err = parse_enumerated (data, datalen, &ti, 1);
1048 0 : if (err)
1049 0 : return err;
1050 0 : switch (**data)
1051 : {
1052 0 : case 0: ocsp->response_status = KSBA_OCSP_RSPSTATUS_SUCCESS; break;
1053 0 : case 1: ocsp->response_status = KSBA_OCSP_RSPSTATUS_MALFORMED; break;
1054 0 : case 2: ocsp->response_status = KSBA_OCSP_RSPSTATUS_INTERNAL; break;
1055 0 : case 3: ocsp->response_status = KSBA_OCSP_RSPSTATUS_TRYLATER; break;
1056 0 : case 5: ocsp->response_status = KSBA_OCSP_RSPSTATUS_SIGREQUIRED; break;
1057 0 : case 6: ocsp->response_status = KSBA_OCSP_RSPSTATUS_UNAUTHORIZED; break;
1058 0 : default: ocsp->response_status = KSBA_OCSP_RSPSTATUS_OTHER; break;
1059 : }
1060 0 : parse_skip (data, datalen, &ti);
1061 :
1062 0 : if (ocsp->response_status)
1063 0 : return 0; /* This is an error reponse; we have to stop here. */
1064 :
1065 : /* We have a successful reponse status, thus we check that
1066 : ResponseBytes are actually available. */
1067 0 : err = parse_context_tag (data, datalen, &ti, 0);
1068 0 : if (err)
1069 0 : return err;
1070 0 : err = parse_sequence (data, datalen, &ti);
1071 0 : if (err)
1072 0 : return err;
1073 0 : err = parse_object_id_into_str (data, datalen, &oid);
1074 0 : if (err)
1075 0 : return err;
1076 0 : if (strcmp (oid, oidstr_ocsp_basic))
1077 : {
1078 0 : xfree (oid);
1079 0 : return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
1080 : }
1081 0 : xfree (oid);
1082 :
1083 : /* Check that the next field is an octet string. */
1084 0 : err = parse_octet_string (data, datalen, &ti);
1085 0 : if (err)
1086 0 : return err;
1087 0 : *rlength = ti.length;
1088 0 : return 0;
1089 : }
1090 :
1091 : /* Parse the object:
1092 :
1093 : SingleResponse ::= SEQUENCE {
1094 : certID CertID,
1095 : certStatus CertStatus,
1096 : thisUpdate GeneralizedTime,
1097 : nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
1098 : singleExtensions [1] EXPLICIT Extensions OPTIONAL }
1099 :
1100 : CertStatus ::= CHOICE {
1101 : good [0] IMPLICIT NULL,
1102 : revoked [1] IMPLICIT RevokedInfo,
1103 : unknown [2] IMPLICIT UnknownInfo }
1104 :
1105 : RevokedInfo ::= SEQUENCE {
1106 : revocationTime GeneralizedTime,
1107 : revocationReason [0] EXPLICIT CRLReason OPTIONAL }
1108 :
1109 : UnknownInfo ::= NULL -- this can be replaced with an enumeration
1110 :
1111 : */
1112 :
1113 : static gpg_error_t
1114 0 : parse_single_response (ksba_ocsp_t ocsp,
1115 : unsigned char const **data, size_t *datalen)
1116 : {
1117 : gpg_error_t err;
1118 : struct tag_info ti;
1119 : const unsigned char *savedata;
1120 : const unsigned char *endptr;
1121 : size_t savedatalen;
1122 : size_t n;
1123 : char *oid;
1124 : ksba_isotime_t this_update, next_update, revocation_time;
1125 : int look_for_request;
1126 : const unsigned char *name_hash;
1127 : const unsigned char *key_hash;
1128 : const unsigned char *serialno;
1129 : size_t serialnolen;
1130 0 : struct ocsp_reqitem_s *request_item = NULL;
1131 :
1132 : /* The SingeResponse sequence. */
1133 0 : err = parse_sequence (data, datalen, &ti);
1134 0 : if (err)
1135 0 : return err;
1136 0 : endptr = *data + ti.length;
1137 :
1138 : /* The CertID is
1139 : SEQUENCE {
1140 : hashAlgorithm AlgorithmIdentifier,
1141 : issuerNameHash OCTET STRING, -- Hash of Issuer's DN
1142 : issuerKeyHash OCTET STRING, -- Hash of Issuers public key
1143 : serialNumber CertificateSerialNumber }
1144 : */
1145 0 : err = parse_sequence (data, datalen, &ti);
1146 0 : if (err)
1147 0 : return err;
1148 0 : err = _ksba_parse_algorithm_identifier (*data, *datalen, &n, &oid);
1149 0 : if (err)
1150 0 : return err;
1151 0 : assert (n <= *datalen);
1152 0 : *data += n;
1153 0 : *datalen -= n;
1154 : /* fprintf (stderr, "algorithmIdentifier is `%s'\n", oid); */
1155 0 : look_for_request = !strcmp (oid, oidstr_sha1);
1156 0 : xfree (oid);
1157 :
1158 0 : err = parse_octet_string (data, datalen, &ti);
1159 0 : if (err)
1160 0 : return err;
1161 0 : name_hash = *data;
1162 : /* fprintf (stderr, "issuerNameHash="); */
1163 : /* dump_hex (*data, ti.length); */
1164 : /* putc ('\n', stderr); */
1165 0 : if (ti.length != 20)
1166 0 : look_for_request = 0; /* Can't be a SHA-1 digest. */
1167 0 : parse_skip (data, datalen, &ti);
1168 :
1169 0 : err = parse_octet_string (data, datalen, &ti);
1170 0 : if (err)
1171 0 : return err;
1172 0 : key_hash = *data;
1173 : /* fprintf (stderr, "issuerKeyHash="); */
1174 : /* dump_hex (*data, ti.length); */
1175 : /* putc ('\n', stderr); */
1176 0 : if (ti.length != 20)
1177 0 : look_for_request = 0; /* Can't be a SHA-1 digest. */
1178 0 : parse_skip (data, datalen, &ti);
1179 :
1180 0 : err= parse_integer (data, datalen, &ti);
1181 0 : if (err)
1182 0 : return err;
1183 0 : serialno = *data;
1184 0 : serialnolen = ti.length;
1185 : /* fprintf (stderr, "serialNumber="); */
1186 : /* dump_hex (*data, ti.length); */
1187 : /* putc ('\n', stderr); */
1188 0 : parse_skip (data, datalen, &ti);
1189 :
1190 0 : if (look_for_request)
1191 : {
1192 0 : for (request_item = ocsp->requestlist;
1193 0 : request_item; request_item = request_item->next)
1194 0 : if (!memcmp (request_item->issuer_name_hash, name_hash, 20)
1195 0 : && !memcmp (request_item->issuer_key_hash, key_hash, 20)
1196 0 : && request_item->serialnolen == serialnolen
1197 0 : && !memcmp (request_item->serialno, serialno, serialnolen))
1198 0 : break; /* Got it. */
1199 : }
1200 :
1201 :
1202 : /*
1203 : CertStatus ::= CHOICE {
1204 : good [0] IMPLICIT NULL,
1205 : revoked [1] IMPLICIT RevokedInfo,
1206 : unknown [2] IMPLICIT UnknownInfo }
1207 : */
1208 0 : *revocation_time = 0;
1209 0 : err = _ksba_ber_parse_tl (data, datalen, &ti);
1210 0 : if (err)
1211 0 : return err;
1212 0 : if (ti.length > *datalen)
1213 0 : return gpg_error (GPG_ERR_BAD_BER);
1214 0 : else if (ti.class == CLASS_CONTEXT && ti.tag == 0 && !ti.is_constructed)
1215 : { /* good */
1216 0 : if (!ti.length)
1217 : ; /* Cope with zero length objects. */
1218 0 : else if (*datalen && !**data)
1219 : { /* Skip the NULL. */
1220 0 : (*datalen)--;
1221 0 : (*data)++;
1222 : }
1223 : else
1224 0 : return gpg_error (GPG_ERR_INV_OBJ);
1225 :
1226 0 : if (request_item)
1227 0 : request_item->status = KSBA_STATUS_GOOD;
1228 : }
1229 0 : else if (ti.class == CLASS_CONTEXT && ti.tag == 1 && ti.is_constructed)
1230 0 : { /* revoked */
1231 0 : ksba_crl_reason_t reason = KSBA_CRLREASON_UNSPECIFIED;
1232 :
1233 0 : err = parse_asntime_into_isotime (data, datalen, revocation_time);
1234 0 : if (err)
1235 0 : return err;
1236 : /* fprintf (stderr, "revocationTime=%s\n", revocation_time); */
1237 0 : savedata = *data;
1238 0 : savedatalen = *datalen;
1239 0 : err = parse_context_tag (data, datalen, &ti, 0);
1240 0 : if (err)
1241 : {
1242 0 : *data = savedata;
1243 0 : *datalen = savedatalen;
1244 : }
1245 : else
1246 : { /* Got a revocationReason. */
1247 0 : err = parse_enumerated (data, datalen, &ti, 1);
1248 0 : if (err)
1249 0 : return err;
1250 0 : switch (**data)
1251 : {
1252 0 : case 0: reason = KSBA_CRLREASON_UNSPECIFIED; break;
1253 0 : case 1: reason = KSBA_CRLREASON_KEY_COMPROMISE; break;
1254 0 : case 2: reason = KSBA_CRLREASON_CA_COMPROMISE; break;
1255 0 : case 3: reason = KSBA_CRLREASON_AFFILIATION_CHANGED; break;
1256 0 : case 4: reason = KSBA_CRLREASON_SUPERSEDED; break;
1257 0 : case 5: reason = KSBA_CRLREASON_CESSATION_OF_OPERATION; break;
1258 0 : case 6: reason = KSBA_CRLREASON_CERTIFICATE_HOLD; break;
1259 0 : case 8: reason = KSBA_CRLREASON_REMOVE_FROM_CRL; break;
1260 0 : case 9: reason = KSBA_CRLREASON_PRIVILEGE_WITHDRAWN; break;
1261 0 : case 10: reason = KSBA_CRLREASON_AA_COMPROMISE; break;
1262 0 : default: reason = KSBA_CRLREASON_OTHER; break;
1263 : }
1264 0 : parse_skip (data, datalen, &ti);
1265 : }
1266 : /* fprintf (stderr, "revocationReason=%04x\n", reason); */
1267 0 : if (request_item)
1268 : {
1269 0 : request_item->status = KSBA_STATUS_REVOKED;
1270 0 : _ksba_copy_time (request_item->revocation_time, revocation_time);
1271 0 : request_item->revocation_reason = reason;
1272 : }
1273 : }
1274 0 : else if (ti.class == CLASS_CONTEXT && ti.tag == 2 && !ti.is_constructed
1275 0 : && *datalen)
1276 : { /* unknown */
1277 0 : if (!ti.length)
1278 : ; /* Cope with zero length objects. */
1279 0 : else if (!**data)
1280 : { /* Skip the NULL. */
1281 0 : (*datalen)--;
1282 0 : (*data)++;
1283 : }
1284 : else /* The comment indicates that an enumeration may come here. */
1285 : {
1286 0 : err = parse_enumerated (data, datalen, &ti, 0);
1287 0 : if (err)
1288 0 : return err;
1289 0 : fprintf (stderr, "libksba: unknownReason with an enum of "
1290 : "length %u detected\n",
1291 0 : (unsigned int)ti.length);
1292 0 : parse_skip (data, datalen, &ti);
1293 : }
1294 0 : if (request_item)
1295 0 : request_item->status = KSBA_STATUS_UNKNOWN;
1296 : }
1297 : else
1298 0 : err = gpg_error (GPG_ERR_INV_OBJ);
1299 :
1300 : /* thisUpdate. */
1301 0 : err = parse_asntime_into_isotime (data, datalen, this_update);
1302 0 : if (err)
1303 0 : return err;
1304 : /* fprintf (stderr, "thisUpdate=%s\n", this_update); */
1305 0 : if (request_item)
1306 0 : _ksba_copy_time (request_item->this_update, this_update);
1307 :
1308 : /* nextUpdate is optional. */
1309 0 : if (*data >= endptr)
1310 0 : return 0;
1311 0 : *next_update = 0;
1312 0 : err = _ksba_ber_parse_tl (data, datalen, &ti);
1313 0 : if (err)
1314 0 : return err;
1315 0 : if (ti.length > *datalen)
1316 0 : return gpg_error (GPG_ERR_BAD_BER);
1317 0 : else if (ti.class == CLASS_CONTEXT && ti.tag == 0 && ti.is_constructed)
1318 : { /* have nextUpdate */
1319 0 : err = parse_asntime_into_isotime (data, datalen, next_update);
1320 0 : if (err)
1321 0 : return err;
1322 : /* fprintf (stderr, "nextUpdate=%s\n", next_update); */
1323 0 : if (request_item)
1324 0 : _ksba_copy_time (request_item->next_update, next_update);
1325 : }
1326 0 : else if (ti.class == CLASS_CONTEXT && ti.tag == 1 && ti.is_constructed)
1327 : { /* Undo that read. */
1328 0 : *data -= ti.nhdr;
1329 0 : *datalen += ti.nhdr;
1330 : }
1331 : else
1332 0 : err = gpg_error (GPG_ERR_INV_OBJ);
1333 :
1334 : /* singleExtensions is optional */
1335 0 : if (*data >= endptr)
1336 0 : return 0;
1337 0 : err = _ksba_ber_parse_tl (data, datalen, &ti);
1338 0 : if (err)
1339 0 : return err;
1340 0 : if (ti.length > *datalen)
1341 0 : return gpg_error (GPG_ERR_BAD_BER);
1342 0 : if (ti.class == CLASS_CONTEXT && ti.tag == 1 && ti.is_constructed)
1343 : {
1344 0 : if (request_item)
1345 : {
1346 0 : err = parse_single_extensions (request_item, *data, ti.length);
1347 0 : if (err)
1348 0 : return err;
1349 : }
1350 0 : parse_skip (data, datalen, &ti);
1351 : }
1352 : else
1353 0 : err = gpg_error (GPG_ERR_INV_OBJ);
1354 :
1355 0 : return 0;
1356 : }
1357 :
1358 : /* Parse the object:
1359 :
1360 : ResponseData ::= SEQUENCE {
1361 : version [0] EXPLICIT Version DEFAULT v1,
1362 : responderID ResponderID,
1363 : producedAt GeneralizedTime,
1364 : responses SEQUENCE OF SingleResponse,
1365 : responseExtensions [1] EXPLICIT Extensions OPTIONAL }
1366 :
1367 : ResponderID ::= CHOICE {
1368 : byName [1] Name,
1369 : byKey [2] KeyHash }
1370 :
1371 :
1372 : */
1373 : static gpg_error_t
1374 0 : parse_response_data (ksba_ocsp_t ocsp,
1375 : unsigned char const **data, size_t *datalen)
1376 : {
1377 : gpg_error_t err;
1378 : struct tag_info ti;
1379 : const unsigned char *savedata;
1380 : size_t savedatalen;
1381 : size_t responses_length;
1382 :
1383 : /* The out er sequence. */
1384 0 : err = parse_sequence (data, datalen, &ti);
1385 0 : if (err)
1386 0 : return err;
1387 :
1388 : /* The optional version field. */
1389 0 : savedata = *data;
1390 0 : savedatalen = *datalen;
1391 0 : err = parse_context_tag (data, datalen, &ti, 0);
1392 0 : if (err)
1393 : {
1394 0 : *data = savedata;
1395 0 : *datalen = savedatalen;
1396 : }
1397 : else
1398 : {
1399 : /* FIXME: check that the version matches. */
1400 0 : parse_skip (data, datalen, &ti);
1401 : }
1402 :
1403 : /* The responderID field. */
1404 0 : assert (!ocsp->responder_id.name);
1405 0 : assert (!ocsp->responder_id.keyid);
1406 0 : err = _ksba_ber_parse_tl (data, datalen, &ti);
1407 0 : if (err)
1408 0 : return err;
1409 0 : if (ti.length > *datalen)
1410 0 : return gpg_error (GPG_ERR_BAD_BER);
1411 0 : else if (ti.class == CLASS_CONTEXT && ti.tag == 1 && ti.is_constructed)
1412 : { /* byName. */
1413 0 : err = _ksba_derdn_to_str (*data, ti.length, &ocsp->responder_id.name);
1414 0 : if (err)
1415 0 : return err;
1416 0 : parse_skip (data, datalen, &ti);
1417 : }
1418 0 : else if (ti.class == CLASS_CONTEXT && ti.tag == 2 && ti.is_constructed)
1419 : { /* byKey. */
1420 0 : err = parse_octet_string (data, datalen, &ti);
1421 0 : if (err)
1422 0 : return err;
1423 0 : if (!ti.length)
1424 0 : return gpg_error (GPG_ERR_INV_OBJ); /* Zero length key id. */
1425 0 : ocsp->responder_id.keyid = xtrymalloc (ti.length);
1426 0 : if (!ocsp->responder_id.keyid)
1427 0 : return gpg_error_from_syserror ();
1428 0 : memcpy (ocsp->responder_id.keyid, *data, ti.length);
1429 0 : ocsp->responder_id.keyidlen = ti.length;
1430 0 : parse_skip (data, datalen, &ti);
1431 : }
1432 : else
1433 0 : err = gpg_error (GPG_ERR_INV_OBJ);
1434 :
1435 : /* The producedAt field. */
1436 0 : err = parse_asntime_into_isotime (data, datalen, ocsp->produced_at);
1437 0 : if (err)
1438 0 : return err;
1439 :
1440 : /* The responses field set. */
1441 0 : err = parse_sequence (data, datalen, &ti);
1442 0 : if (err )
1443 0 : return err;
1444 0 : responses_length = ti.length;
1445 0 : while (responses_length)
1446 : {
1447 0 : savedatalen = *datalen;
1448 0 : err = parse_single_response (ocsp, data, datalen);
1449 0 : if (err)
1450 0 : return err;
1451 0 : assert (responses_length >= savedatalen - *datalen);
1452 0 : responses_length -= savedatalen - *datalen;
1453 : }
1454 :
1455 : /* The optional responseExtensions set. */
1456 0 : savedata = *data;
1457 0 : savedatalen = *datalen;
1458 0 : err = parse_context_tag (data, datalen, &ti, 1);
1459 0 : if (!err)
1460 : {
1461 0 : err = parse_response_extensions (ocsp, *data, ti.length);
1462 0 : if (err)
1463 0 : return err;
1464 0 : parse_skip (data, datalen, &ti);
1465 : }
1466 0 : else if (gpg_err_code (err) == GPG_ERR_INV_OBJ)
1467 : {
1468 0 : *data = savedata;
1469 0 : *datalen = savedatalen;
1470 : }
1471 : else
1472 0 : return err;
1473 :
1474 0 : return 0;
1475 : }
1476 :
1477 :
1478 : /* Parse the entire response message pointed to by MSG of length
1479 : MSGLEN. */
1480 : static gpg_error_t
1481 0 : parse_response (ksba_ocsp_t ocsp, const unsigned char *msg, size_t msglen)
1482 : {
1483 : gpg_error_t err;
1484 : struct tag_info ti;
1485 : const unsigned char *msgstart;
1486 : const unsigned char *endptr;
1487 : const char *s;
1488 : size_t len;
1489 :
1490 :
1491 0 : msgstart = msg;
1492 0 : err = parse_response_status (ocsp, &msg, &msglen, &len);
1493 0 : if (err)
1494 0 : return err;
1495 0 : msglen = len; /* We don't care about any extra bytes provided to us. */
1496 0 : if (ocsp->response_status)
1497 : {
1498 : /* fprintf (stderr,"response status found to be %d - stop\n", */
1499 : /* ocsp->response_status); */
1500 0 : return 0;
1501 : }
1502 :
1503 : /* Now that we are sure that it is a BasicOCSPResponse, we can parse
1504 : the really important things:
1505 :
1506 : BasicOCSPResponse ::= SEQUENCE {
1507 : tbsResponseData ResponseData,
1508 : signatureAlgorithm AlgorithmIdentifier,
1509 : signature BIT STRING,
1510 : certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
1511 : */
1512 0 : err = parse_sequence (&msg, &msglen, &ti);
1513 0 : if (err)
1514 0 : return err;
1515 0 : endptr = msg + ti.length;
1516 :
1517 0 : ocsp->hash_offset = msg - msgstart;
1518 0 : err = parse_response_data (ocsp, &msg, &msglen);
1519 0 : if (err)
1520 0 : return err;
1521 0 : ocsp->hash_length = msg - msgstart - ocsp->hash_offset;
1522 :
1523 : /* The signatureAlgorithm and the signature. We only need to get the
1524 : length of both objects and let a specialized function do the
1525 : actual parsing. */
1526 0 : s = msg;
1527 0 : len = msglen;
1528 0 : err = parse_sequence (&msg, &msglen, &ti);
1529 0 : if (err)
1530 0 : return err;
1531 0 : parse_skip (&msg, &msglen, &ti);
1532 0 : err= _ksba_ber_parse_tl (&msg, &msglen, &ti);
1533 0 : if (err)
1534 0 : return err;
1535 0 : if (!(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_BIT_STRING
1536 0 : && !ti.is_constructed) )
1537 0 : err = gpg_error (GPG_ERR_INV_OBJ);
1538 0 : else if (!ti.length)
1539 0 : err = gpg_error (GPG_ERR_TOO_SHORT);
1540 0 : else if (ti.length > msglen)
1541 0 : err = gpg_error (GPG_ERR_BAD_BER);
1542 0 : parse_skip (&msg, &msglen, &ti);
1543 0 : len = len - msglen;
1544 0 : xfree (ocsp->sigval); ocsp->sigval = NULL;
1545 0 : err = _ksba_sigval_to_sexp (s, len, &ocsp->sigval);
1546 0 : if (err)
1547 0 : return err;
1548 :
1549 : /* Parse the optional sequence of certificates. */
1550 0 : if (msg >= endptr)
1551 0 : return 0; /* It's optional, so stop now. */
1552 0 : err = parse_context_tag (&msg, &msglen, &ti, 0);
1553 0 : if (gpg_err_code (err) == GPG_ERR_INV_OBJ)
1554 0 : return 0; /* Not the right tag. Stop here. */
1555 0 : if (err)
1556 0 : return err;
1557 0 : err = parse_sequence (&msg, &msglen, &ti);
1558 0 : if (err)
1559 0 : return err;
1560 0 : if (ti.ndef)
1561 0 : return gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
1562 :
1563 : {
1564 : ksba_cert_t cert;
1565 : struct ocsp_certlist_s *cl, **cl_tail;
1566 :
1567 0 : assert (!ocsp->received_certs);
1568 0 : cl_tail = &ocsp->received_certs;
1569 0 : endptr = msg + ti.length;
1570 0 : while (msg < endptr)
1571 : {
1572 : /* Find the length of the certificate. */
1573 0 : s = msg;
1574 0 : err = parse_sequence (&msg, &msglen, &ti);
1575 0 : if (err)
1576 0 : return err;
1577 0 : err = ksba_cert_new (&cert);
1578 0 : if (err)
1579 0 : return err;
1580 0 : err = ksba_cert_init_from_mem (cert, msg - ti.nhdr,
1581 0 : ti.nhdr + ti.length);
1582 0 : if (err)
1583 : {
1584 0 : ksba_cert_release (cert);
1585 0 : return err;
1586 : }
1587 0 : parse_skip (&msg, &msglen, &ti);
1588 0 : cl = xtrycalloc (1, sizeof *cl);
1589 0 : if (!cl)
1590 : {
1591 0 : err = gpg_error_from_syserror ();
1592 0 : ksba_cert_release (cert);
1593 0 : return err;
1594 : }
1595 :
1596 0 : cl->cert = cert;
1597 :
1598 0 : *cl_tail = cl;
1599 0 : cl_tail = &cl->next;
1600 : }
1601 : }
1602 :
1603 0 : return 0;
1604 : }
1605 :
1606 :
1607 : /* Given the OCSP context and a binary reponse message of MSGLEN bytes
1608 : in MSG, this fucntion parses the response and prepares it for
1609 : signature verification. The status from the server is returned in
1610 : RESPONSE_STATUS and must be checked even if the function returns
1611 : without an error. */
1612 : gpg_error_t
1613 0 : ksba_ocsp_parse_response (ksba_ocsp_t ocsp,
1614 : const unsigned char *msg, size_t msglen,
1615 : ksba_ocsp_response_status_t *response_status)
1616 : {
1617 : gpg_error_t err;
1618 : struct ocsp_reqitem_s *ri;
1619 :
1620 0 : if (!ocsp || !msg || !msglen || !response_status)
1621 0 : return gpg_error (GPG_ERR_INV_VALUE);
1622 :
1623 0 : if (!ocsp->requestlist)
1624 0 : return gpg_error (GPG_ERR_MISSING_ACTION);
1625 :
1626 : /* Reset the fields used to track the response. This is so that we
1627 : can use the parse function a second time for the same
1628 : request. This is useful in case of a TryLater response status. */
1629 0 : ocsp->response_status = KSBA_OCSP_RSPSTATUS_NONE;
1630 0 : release_ocsp_certlist (ocsp->received_certs);
1631 0 : release_ocsp_extensions (ocsp->response_extensions);
1632 0 : ocsp->received_certs = NULL;
1633 0 : ocsp->hash_length = 0;
1634 0 : ocsp->bad_nonce = 0;
1635 0 : ocsp->good_nonce = 0;
1636 0 : xfree (ocsp->responder_id.name);
1637 0 : ocsp->responder_id.name = NULL;
1638 0 : xfree (ocsp->responder_id.keyid);
1639 0 : ocsp->responder_id.keyid = NULL;
1640 0 : for (ri=ocsp->requestlist; ri; ri = ri->next)
1641 : {
1642 0 : ri->status = KSBA_STATUS_NONE;
1643 0 : *ri->this_update = 0;
1644 0 : *ri->next_update = 0;
1645 0 : *ri->revocation_time = 0;
1646 0 : ri->revocation_reason = 0;
1647 0 : release_ocsp_extensions (ri->single_extensions);
1648 : }
1649 :
1650 : /* Run the actual parser. */
1651 0 : err = parse_response (ocsp, msg, msglen);
1652 0 : *response_status = ocsp->response_status;
1653 :
1654 : /* FIXME: find duplicates in the request list and set them to the
1655 : same status. */
1656 :
1657 0 : if (*response_status == KSBA_OCSP_RSPSTATUS_SUCCESS)
1658 0 : if (ocsp->bad_nonce || (ocsp->noncelen && !ocsp->good_nonce))
1659 0 : *response_status = KSBA_OCSP_RSPSTATUS_REPLAYED;
1660 :
1661 0 : return err;
1662 : }
1663 :
1664 :
1665 : /* Return the digest algorithm to be used for the signature or NULL in
1666 : case of an error. The returned pointer is valid as long as the
1667 : context is valid and no other ksba_ocsp_parse_response or
1668 : ksba_ocsp_build_request has been used. */
1669 : const char *
1670 0 : ksba_ocsp_get_digest_algo (ksba_ocsp_t ocsp)
1671 : {
1672 0 : return ocsp? ocsp->digest_oid : NULL;
1673 : }
1674 :
1675 :
1676 : /* Hash the data of the response using the hash function HASHER which
1677 : will be passed HASHER_ARG as its first argument and a pointer and a
1678 : length of the data to be hashed. This hash function might be called
1679 : several times and should update the hash context. The algorithm to
1680 : be used for the hashing can be retrieved using
1681 : ksba_ocsp_get_digest_algo. Note that MSG and MSGLEN should be
1682 : indentical to the values passed to ksba_ocsp_parse_response. */
1683 : gpg_error_t
1684 0 : ksba_ocsp_hash_response (ksba_ocsp_t ocsp,
1685 : const unsigned char *msg, size_t msglen,
1686 : void (*hasher)(void *, const void *, size_t length),
1687 : void *hasher_arg)
1688 :
1689 : {
1690 0 : if (!ocsp || !msg || !hasher)
1691 0 : return gpg_error (GPG_ERR_INV_VALUE);
1692 0 : if (!ocsp->hash_length)
1693 0 : return gpg_error (GPG_ERR_MISSING_ACTION);
1694 0 : if (ocsp->hash_offset + ocsp->hash_length >= msglen)
1695 0 : return gpg_error (GPG_ERR_CONFLICT);
1696 :
1697 0 : hasher (hasher_arg, msg + ocsp->hash_offset, ocsp->hash_length);
1698 0 : return 0;
1699 : }
1700 :
1701 :
1702 : /* Return the actual signature in a format suitable to be used as
1703 : input to Libgcrypt's verification function. The caller must free
1704 : the returned string and that function may be called only once after
1705 : a successful ksba_ocsp_parse_response. Returns NULL for an invalid
1706 : handle or if no signature is available. If PRODUCED_AT is not NULL,
1707 : it will receive the time the response was signed. */
1708 : ksba_sexp_t
1709 0 : ksba_ocsp_get_sig_val (ksba_ocsp_t ocsp, ksba_isotime_t produced_at)
1710 : {
1711 : ksba_sexp_t p;
1712 :
1713 0 : if (produced_at)
1714 0 : *produced_at = 0;
1715 0 : if (!ocsp || !ocsp->sigval )
1716 0 : return NULL;
1717 :
1718 0 : if (produced_at)
1719 0 : _ksba_copy_time (produced_at, ocsp->produced_at);
1720 :
1721 0 : p = ocsp->sigval;
1722 0 : ocsp->sigval = NULL;
1723 0 : return p;
1724 : }
1725 :
1726 :
1727 : /* Return the responder ID for the current response into R_NAME or
1728 : into R_KEYID. On sucess either R_NAME or R_KEYID will receive an
1729 : allocated object. If R_NAME or R_KEYID has been passed as NULL but
1730 : a value is available the errorcode GPG_ERR_NO_DATA is returned.
1731 : Caller must release the values stored at R_NAME or R_KEYID; the
1732 : function stores NULL tehre in case of an error. */
1733 : gpg_error_t
1734 0 : ksba_ocsp_get_responder_id (ksba_ocsp_t ocsp,
1735 : char **r_name, ksba_sexp_t *r_keyid)
1736 : {
1737 0 : if (r_name)
1738 0 : *r_name = NULL;
1739 0 : if (r_keyid)
1740 0 : *r_keyid = NULL;
1741 :
1742 0 : if (!ocsp)
1743 0 : return gpg_error (GPG_ERR_INV_VALUE);
1744 :
1745 0 : if (ocsp->responder_id.name && r_name)
1746 : {
1747 0 : *r_name = xtrystrdup (ocsp->responder_id.name);
1748 0 : if (!*r_name)
1749 0 : return gpg_error_from_syserror ();
1750 : }
1751 0 : else if (ocsp->responder_id.keyid && r_keyid)
1752 0 : {
1753 : char numbuf[50];
1754 : size_t numbuflen;
1755 :
1756 0 : sprintf (numbuf,"(%lu:", (unsigned long)ocsp->responder_id.keyidlen);
1757 0 : numbuflen = strlen (numbuf);
1758 0 : *r_keyid = xtrymalloc (numbuflen + ocsp->responder_id.keyidlen + 2);
1759 0 : if (!*r_keyid)
1760 0 : return gpg_error_from_syserror ();
1761 0 : strcpy (*r_keyid, numbuf);
1762 0 : memcpy (*r_keyid+numbuflen,
1763 0 : ocsp->responder_id.keyid, ocsp->responder_id.keyidlen);
1764 0 : (*r_keyid)[numbuflen + ocsp->responder_id.keyidlen] = ')';
1765 0 : (*r_keyid)[numbuflen + ocsp->responder_id.keyidlen + 1] = 0;
1766 : }
1767 : else
1768 0 : return gpg_error (GPG_ERR_NO_DATA);
1769 :
1770 0 : return 0;
1771 : }
1772 :
1773 :
1774 : /* Get optional certificates out of a response. The caller may use
1775 : * this in a loop to get all certificates. The returned certificate
1776 : * is a shallow copy of the original one; the caller must still use
1777 : * ksba_cert_release() to free it. Returns: A certificate object or
1778 : * NULL for end of list or error. */
1779 : ksba_cert_t
1780 0 : ksba_ocsp_get_cert (ksba_ocsp_t ocsp, int idx)
1781 : {
1782 : struct ocsp_certlist_s *cl;
1783 :
1784 0 : if (!ocsp || idx < 0)
1785 0 : return NULL;
1786 :
1787 0 : for (cl=ocsp->received_certs; cl && idx; cl = cl->next, idx--)
1788 : ;
1789 0 : if (!cl)
1790 0 : return NULL;
1791 0 : ksba_cert_ref (cl->cert);
1792 0 : return cl->cert;
1793 : }
1794 :
1795 :
1796 :
1797 :
1798 : /* Return the status of the certificate CERT for the last response
1799 : done on the context OCSP. CERT must be the same certificate as
1800 : used for the request; only a shallow compare is done (i.e. the
1801 : pointers are compared). R_STATUS returns the status value,
1802 : R_THIS_UPDATE and R_NEXT_UPDATE are the corresponding OCSP response
1803 : values, R_REVOCATION_TIME is only set to the revocation time if the
1804 : indicated status is revoked, R_REASON will be set to the reason
1805 : given for a revocation. All the R_* arguments may be given as NULL
1806 : if the value is not required. The function return 0 on success,
1807 : GPG_ERR_NOT_FOUND if CERT was not used in the request or any other
1808 : error code. Note that the caller should have checked the signature
1809 : of the entire reponse to be good before using the stati retruned by
1810 : this function. */
1811 : gpg_error_t
1812 0 : ksba_ocsp_get_status (ksba_ocsp_t ocsp, ksba_cert_t cert,
1813 : ksba_status_t *r_status,
1814 : ksba_isotime_t r_this_update,
1815 : ksba_isotime_t r_next_update,
1816 : ksba_isotime_t r_revocation_time,
1817 : ksba_crl_reason_t *r_reason)
1818 : {
1819 : struct ocsp_reqitem_s *ri;
1820 :
1821 0 : if (!ocsp || !cert || !r_status)
1822 0 : return gpg_error (GPG_ERR_INV_VALUE);
1823 0 : if (!ocsp->requestlist)
1824 0 : return gpg_error (GPG_ERR_MISSING_ACTION);
1825 :
1826 : /* Find the certificate. We don't care about the issuer certificate
1827 : and stop at the first match. The implementation may be optimized
1828 : by keeping track of the last certificate found to start with the
1829 : next one then. Given that a usual request consists only of a few
1830 : certificates, this does not make much sense in reality. */
1831 0 : for (ri=ocsp->requestlist; ri; ri = ri->next)
1832 0 : if (ri->cert == cert)
1833 0 : break;
1834 0 : if (!ri)
1835 0 : return gpg_error (GPG_ERR_NOT_FOUND);
1836 0 : if (r_status)
1837 0 : *r_status = ri->status;
1838 0 : if (r_this_update)
1839 0 : _ksba_copy_time (r_this_update, ri->this_update);
1840 0 : if (r_next_update)
1841 0 : _ksba_copy_time (r_next_update, ri->next_update);
1842 0 : if (r_revocation_time)
1843 0 : _ksba_copy_time (r_revocation_time, ri->revocation_time);
1844 0 : if (r_reason)
1845 0 : *r_reason = ri->revocation_reason;
1846 0 : return 0;
1847 : }
1848 :
1849 :
1850 : /* WARNING: The returned values ares only valid as long as no other
1851 : ocsp function is called on the same context. */
1852 : gpg_error_t
1853 0 : ksba_ocsp_get_extension (ksba_ocsp_t ocsp, ksba_cert_t cert, int idx,
1854 : char const **r_oid, int *r_crit,
1855 : unsigned char const **r_der, size_t *r_derlen)
1856 : {
1857 : struct ocsp_extension_s *ex;
1858 :
1859 0 : if (!ocsp)
1860 0 : return gpg_error (GPG_ERR_INV_VALUE);
1861 0 : if (!ocsp->requestlist)
1862 0 : return gpg_error (GPG_ERR_MISSING_ACTION);
1863 0 : if (idx < 0)
1864 0 : return gpg_error (GPG_ERR_INV_INDEX);
1865 :
1866 0 : if (cert)
1867 : {
1868 : /* Return extensions for the certificate (singleExtensions). */
1869 : struct ocsp_reqitem_s *ri;
1870 :
1871 0 : for (ri=ocsp->requestlist; ri; ri = ri->next)
1872 0 : if (ri->cert == cert)
1873 0 : break;
1874 0 : if (!ri)
1875 0 : return gpg_error (GPG_ERR_NOT_FOUND);
1876 :
1877 0 : for (ex=ri->single_extensions; ex && idx; ex = ex->next, idx--)
1878 : ;
1879 0 : if (!ex)
1880 0 : return gpg_error (GPG_ERR_EOF); /* No more extensions. */
1881 : }
1882 : else
1883 : {
1884 : /* Return extensions for the response (responseExtensions). */
1885 0 : for (ex=ocsp->response_extensions; ex && idx; ex = ex->next, idx--)
1886 : ;
1887 0 : if (!ex)
1888 0 : return gpg_error (GPG_ERR_EOF); /* No more extensions. */
1889 : }
1890 :
1891 0 : if (r_oid)
1892 0 : *r_oid = ex->data;
1893 0 : if (r_crit)
1894 0 : *r_crit = ex->crit;
1895 0 : if (r_der)
1896 0 : *r_der = ex->data + ex->off;
1897 0 : if (r_derlen)
1898 0 : *r_derlen = ex->len;
1899 :
1900 0 : return 0;
1901 : }
|