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