Use the new asn1_read_node_value()
[gnutls.git] / lib / x509 / ocsp.c
blob0857e33acf2175ed77d5b123918118c86eb0599b
1 /*
2 * Copyright (C) 2011-2012 Free Software Foundation, Inc.
3 * Author: Simon Josefsson
5 * This file is part of GnuTLS.
7 * The GnuTLS is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 3 of
10 * the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>
22 /* Online Certificate Status Protocol - RFC 2560
25 #include <gnutls_int.h>
26 #include <gnutls_global.h>
27 #include <gnutls_errors.h>
28 #include <libtasn1.h>
29 #include <gnutls_pk.h>
30 #include "common.h"
31 #include "hash.h"
32 #include "verify-high.h"
34 #include <gnutls/ocsp.h>
35 #include <auth/cert.h>
37 typedef struct gnutls_ocsp_req_int
39 ASN1_TYPE req;
40 } gnutls_ocsp_req_int;
42 typedef struct gnutls_ocsp_resp_int
44 ASN1_TYPE resp;
45 gnutls_datum_t response_type_oid;
46 ASN1_TYPE basicresp;
47 } gnutls_ocsp_resp_int;
49 #define MAX_TIME 64
51 /**
52 * gnutls_ocsp_req_init:
53 * @req: The structure to be initialized
55 * This function will initialize an OCSP request structure.
57 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
58 * negative error value.
59 **/
60 int
61 gnutls_ocsp_req_init (gnutls_ocsp_req_t * req)
63 gnutls_ocsp_req_t tmp = gnutls_calloc (1, sizeof (gnutls_ocsp_req_int));
64 int ret;
66 if (!tmp)
67 return GNUTLS_E_MEMORY_ERROR;
69 ret = asn1_create_element (_gnutls_get_pkix (), "PKIX1.OCSPRequest",
70 &tmp->req);
71 if (ret != ASN1_SUCCESS)
73 gnutls_assert ();
74 gnutls_free (tmp);
75 return _gnutls_asn2err (ret);
78 *req = tmp;
80 return GNUTLS_E_SUCCESS;
83 /**
84 * gnutls_ocsp_req_deinit:
85 * @req: The structure to be deinitialized
87 * This function will deinitialize a OCSP request structure.
88 **/
89 void
90 gnutls_ocsp_req_deinit (gnutls_ocsp_req_t req)
92 if (!req)
93 return;
95 if (req->req)
96 asn1_delete_structure (&req->req);
98 req->req = NULL;
100 gnutls_free (req);
104 * gnutls_ocsp_resp_init:
105 * @resp: The structure to be initialized
107 * This function will initialize an OCSP response structure.
109 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
110 * negative error value.
113 gnutls_ocsp_resp_init (gnutls_ocsp_resp_t * resp)
115 gnutls_ocsp_resp_t tmp = gnutls_calloc (1, sizeof (gnutls_ocsp_resp_int));
116 int ret;
118 if (!tmp)
119 return GNUTLS_E_MEMORY_ERROR;
121 ret = asn1_create_element (_gnutls_get_pkix (),
122 "PKIX1.OCSPResponse", &tmp->resp);
123 if (ret != ASN1_SUCCESS)
125 gnutls_assert ();
126 gnutls_free (tmp);
127 return _gnutls_asn2err (ret);
130 ret = asn1_create_element (_gnutls_get_pkix (),
131 "PKIX1.BasicOCSPResponse", &tmp->basicresp);
132 if (ret != ASN1_SUCCESS)
134 gnutls_assert ();
135 asn1_delete_structure (&tmp->resp);
136 gnutls_free (tmp);
137 return _gnutls_asn2err (ret);
140 *resp = tmp;
142 return GNUTLS_E_SUCCESS;
146 * gnutls_ocsp_resp_deinit:
147 * @resp: The structure to be deinitialized
149 * This function will deinitialize a OCSP response structure.
151 void
152 gnutls_ocsp_resp_deinit (gnutls_ocsp_resp_t resp)
154 if (!resp)
155 return;
157 if (resp->resp)
158 asn1_delete_structure (&resp->resp);
159 gnutls_free (resp->response_type_oid.data);
160 if (resp->basicresp)
161 asn1_delete_structure (&resp->basicresp);
163 resp->resp = NULL;
164 resp->response_type_oid.data = NULL;
165 resp->basicresp = NULL;
167 gnutls_free (resp);
171 * gnutls_ocsp_req_import:
172 * @req: The structure to store the parsed request.
173 * @data: DER encoded OCSP request.
175 * This function will convert the given DER encoded OCSP request to
176 * the native #gnutls_ocsp_req_t format. The output will be stored in
177 * @req.
179 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
180 * negative error value.
183 gnutls_ocsp_req_import (gnutls_ocsp_req_t req,
184 const gnutls_datum_t * data)
186 int ret = 0;
188 if (req == NULL || data == NULL)
190 gnutls_assert ();
191 return GNUTLS_E_INVALID_REQUEST;
194 if (req->req)
196 /* Any earlier asn1_der_decoding will modify the ASN.1
197 structure, so we need to replace it with a fresh
198 structure. */
199 asn1_delete_structure (&req->req);
201 ret = asn1_create_element (_gnutls_get_pkix (),
202 "PKIX1.OCSPRequest", &req->req);
203 if (ret != ASN1_SUCCESS)
205 gnutls_assert ();
206 return _gnutls_asn2err (ret);
210 ret = asn1_der_decoding (&req->req, data->data, data->size, NULL);
211 if (ret != ASN1_SUCCESS)
213 gnutls_assert ();
214 return _gnutls_asn2err (ret);
217 return GNUTLS_E_SUCCESS;
221 * gnutls_ocsp_resp_import:
222 * @resp: The structure to store the parsed response.
223 * @data: DER encoded OCSP response.
225 * This function will convert the given DER encoded OCSP response to
226 * the native #gnutls_ocsp_resp_t format. It also decodes the Basic
227 * OCSP Response part, if any. The output will be stored in @resp.
229 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
230 * negative error value.
233 gnutls_ocsp_resp_import (gnutls_ocsp_resp_t resp,
234 const gnutls_datum_t * data)
236 int ret = 0;
238 if (resp == NULL || data == NULL)
240 gnutls_assert ();
241 return GNUTLS_E_INVALID_REQUEST;
244 if (resp->resp)
246 /* Any earlier asn1_der_decoding will modify the ASN.1
247 structure, so we need to replace it with a fresh
248 structure. */
249 asn1_delete_structure (&resp->resp);
251 ret = asn1_create_element (_gnutls_get_pkix (),
252 "PKIX1.OCSPResponse", &resp->resp);
253 if (ret != ASN1_SUCCESS)
255 gnutls_assert ();
256 return _gnutls_asn2err (ret);
260 ret = asn1_der_decoding (&resp->resp, data->data, data->size, NULL);
261 if (ret != ASN1_SUCCESS)
263 gnutls_assert ();
264 return _gnutls_asn2err (ret);
267 if (gnutls_ocsp_resp_get_status (resp) != GNUTLS_OCSP_RESP_SUCCESSFUL)
268 return GNUTLS_E_SUCCESS;
270 ret = _gnutls_x509_read_value (resp->resp, "responseBytes.responseType",
271 &resp->response_type_oid, 0);
272 if (ret < 0)
274 gnutls_assert ();
275 return ret;
278 #define OCSP_BASIC "1.3.6.1.5.5.7.48.1.1"
280 if (resp->response_type_oid.size == sizeof (OCSP_BASIC)
281 && memcmp (resp->response_type_oid.data, OCSP_BASIC,
282 resp->response_type_oid.size) == 0)
284 gnutls_datum_t d;
286 if (resp->basicresp)
288 asn1_delete_structure (&resp->basicresp);
290 ret = asn1_create_element (_gnutls_get_pkix (),
291 "PKIX1.BasicOCSPResponse", &resp->basicresp);
292 if (ret != ASN1_SUCCESS)
294 gnutls_assert ();
295 return _gnutls_asn2err (ret);
299 ret = _gnutls_x509_read_value (resp->resp, "responseBytes.response",
300 &d, 0);
301 if (ret < 0)
303 gnutls_assert ();
304 return ret;
307 ret = asn1_der_decoding (&resp->basicresp, d.data, d.size, NULL);
308 gnutls_free (d.data);
309 if (ret != ASN1_SUCCESS)
311 gnutls_assert ();
312 return _gnutls_asn2err (ret);
315 else
316 resp->basicresp = NULL;
318 return GNUTLS_E_SUCCESS;
321 static int
322 export (ASN1_TYPE node, const char *name, gnutls_datum_t * data)
324 int ret;
325 int len = 0;
327 ret = asn1_der_coding (node, name, NULL, &len, NULL);
328 if (ret != ASN1_MEM_ERROR)
330 gnutls_assert ();
331 return _gnutls_asn2err (ret);
333 data->size = len;
334 data->data = gnutls_malloc (len);
335 if (data->data == NULL)
336 return GNUTLS_E_MEMORY_ERROR;
337 ret = asn1_der_coding (node, name, data->data, &len, NULL);
338 if (ret != ASN1_SUCCESS)
340 gnutls_assert ();
341 return _gnutls_asn2err (ret);
344 return GNUTLS_E_SUCCESS;
348 * gnutls_ocsp_req_export:
349 * @req: Holds the OCSP request
350 * @data: newly allocate buffer holding DER encoded OCSP request
352 * This function will export the OCSP request to DER format.
354 * Returns: In case of failure a negative error code will be
355 * returned, and 0 on success.
358 gnutls_ocsp_req_export (gnutls_ocsp_req_t req, gnutls_datum_t * data)
360 int ret;
362 if (req == NULL || data == NULL)
364 gnutls_assert ();
365 return GNUTLS_E_INVALID_REQUEST;
368 /* XXX remove when we support these fields */
369 asn1_write_value (req->req, "tbsRequest.requestorName", NULL, 0);
370 asn1_write_value (req->req, "optionalSignature", NULL, 0);
372 /* prune extension field if we don't have any extension */
373 ret = gnutls_ocsp_req_get_extension (req, 0, NULL, NULL, NULL);
374 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
375 asn1_write_value (req->req, "tbsRequest.requestExtensions", NULL, 0);
377 return export (req->req, "", data);
381 * gnutls_ocsp_resp_export:
382 * @resp: Holds the OCSP response
383 * @data: newly allocate buffer holding DER encoded OCSP response
385 * This function will export the OCSP response to DER format.
387 * Returns: In case of failure a negative error code will be
388 * returned, and 0 on success.
391 gnutls_ocsp_resp_export (gnutls_ocsp_resp_t resp, gnutls_datum_t * data)
393 if (resp == NULL || data == NULL)
395 gnutls_assert ();
396 return GNUTLS_E_INVALID_REQUEST;
399 return export (resp->resp, "", data);
403 * gnutls_ocsp_req_get_version:
404 * @req: should contain a #gnutls_ocsp_req_t structure
406 * This function will return the version of the OCSP request.
407 * Typically this is always 1 indicating version 1.
409 * Returns: version of OCSP request, or a negative error code on error.
412 gnutls_ocsp_req_get_version (gnutls_ocsp_req_t req)
414 uint8_t version[8];
415 int len, ret;
417 if (req == NULL)
419 gnutls_assert ();
420 return GNUTLS_E_INVALID_REQUEST;
423 len = sizeof (version);
424 ret = asn1_read_value (req->req, "tbsRequest.version", version, &len);
425 if (ret != ASN1_SUCCESS)
427 if (ret == ASN1_ELEMENT_NOT_FOUND)
428 return 1; /* the DEFAULT version */
429 gnutls_assert ();
430 return _gnutls_asn2err (ret);
433 return (int) version[0] + 1;
437 * gnutls_ocsp_req_get_cert_id:
438 * @req: should contain a #gnutls_ocsp_req_t structure
439 * @indx: Specifies which extension OID to get. Use (0) to get the first one.
440 * @digest: output variable with #gnutls_digest_algorithm_t hash algorithm
441 * @issuer_name_hash: output buffer with hash of issuer's DN
442 * @issuer_key_hash: output buffer with hash of issuer's public key
443 * @serial_number: output buffer with serial number of certificate to check
445 * This function will return the certificate information of the
446 * @indx'ed request in the OCSP request. The information returned
447 * corresponds to the CertID structure:
449 * <informalexample><programlisting>
450 * CertID ::= SEQUENCE {
451 * hashAlgorithm AlgorithmIdentifier,
452 * issuerNameHash OCTET STRING, -- Hash of Issuer's DN
453 * issuerKeyHash OCTET STRING, -- Hash of Issuers public key
454 * serialNumber CertificateSerialNumber }
455 * </programlisting></informalexample>
457 * Each of the pointers to output variables may be NULL to indicate
458 * that the caller is not interested in that value.
460 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
461 * negative error code is returned. If you have reached the last
462 * CertID available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be
463 * returned.
466 gnutls_ocsp_req_get_cert_id (gnutls_ocsp_req_t req,
467 unsigned indx,
468 gnutls_digest_algorithm_t *digest,
469 gnutls_datum_t *issuer_name_hash,
470 gnutls_datum_t *issuer_key_hash,
471 gnutls_datum_t *serial_number)
473 gnutls_datum_t sa;
474 char name[ASN1_MAX_NAME_SIZE];
475 int ret;
477 if (req == NULL)
479 gnutls_assert ();
480 return GNUTLS_E_INVALID_REQUEST;
483 snprintf (name, sizeof (name),
484 "tbsRequest.requestList.?%u.reqCert.hashAlgorithm.algorithm",
485 indx + 1);
486 ret = _gnutls_x509_read_value (req->req, name, &sa, 0);
487 if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
488 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
489 else if (ret < 0)
491 gnutls_assert ();
492 return ret;
495 ret = _gnutls_x509_oid_to_digest ((char*)sa.data);
496 _gnutls_free_datum (&sa);
497 if (ret < 0)
499 gnutls_assert ();
500 return ret;
503 if (digest)
504 *digest = ret;
506 if (issuer_name_hash)
508 snprintf (name, sizeof (name),
509 "tbsRequest.requestList.?%u.reqCert.issuerNameHash", indx + 1);
510 ret = _gnutls_x509_read_value (req->req, name, issuer_name_hash, 0);
511 if (ret != GNUTLS_E_SUCCESS)
513 gnutls_assert ();
514 return ret;
518 if (issuer_key_hash)
520 snprintf (name, sizeof (name),
521 "tbsRequest.requestList.?%u.reqCert.issuerKeyHash", indx + 1);
522 ret = _gnutls_x509_read_value (req->req, name, issuer_key_hash, 0);
523 if (ret != GNUTLS_E_SUCCESS)
525 gnutls_assert ();
526 if (issuer_name_hash)
527 gnutls_free (issuer_name_hash->data);
528 return ret;
532 if (serial_number)
534 snprintf (name, sizeof (name),
535 "tbsRequest.requestList.?%u.reqCert.serialNumber", indx + 1);
536 ret = _gnutls_x509_read_value (req->req, name, serial_number, 0);
537 if (ret != GNUTLS_E_SUCCESS)
539 gnutls_assert ();
540 if (issuer_name_hash)
541 gnutls_free (issuer_name_hash->data);
542 if (issuer_key_hash)
543 gnutls_free (issuer_key_hash->data);
544 return ret;
548 return GNUTLS_E_SUCCESS;
552 * gnutls_ocsp_req_add_cert_id:
553 * @req: should contain a #gnutls_ocsp_req_t structure
554 * @digest: hash algorithm, a #gnutls_digest_algorithm_t value
555 * @issuer_name_hash: hash of issuer's DN
556 * @issuer_key_hash: hash of issuer's public key
557 * @serial_number: serial number of certificate to check
559 * This function will add another request to the OCSP request for a
560 * particular certificate having the issuer name hash of
561 * @issuer_name_hash and issuer key hash of @issuer_key_hash (both
562 * hashed using @digest) and serial number @serial_number.
564 * The information needed corresponds to the CertID structure:
566 * <informalexample><programlisting>
567 * CertID ::= SEQUENCE {
568 * hashAlgorithm AlgorithmIdentifier,
569 * issuerNameHash OCTET STRING, -- Hash of Issuer's DN
570 * issuerKeyHash OCTET STRING, -- Hash of Issuers public key
571 * serialNumber CertificateSerialNumber }
572 * </programlisting></informalexample>
574 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
575 * negative error code is returned.
578 gnutls_ocsp_req_add_cert_id (gnutls_ocsp_req_t req,
579 gnutls_digest_algorithm_t digest,
580 const gnutls_datum_t *issuer_name_hash,
581 const gnutls_datum_t *issuer_key_hash,
582 const gnutls_datum_t *serial_number)
584 int result;
585 const char *oid;
587 if (req == NULL || issuer_name_hash == NULL
588 || issuer_key_hash == NULL || serial_number == NULL)
590 gnutls_assert ();
591 return GNUTLS_E_INVALID_REQUEST;
594 oid = _gnutls_x509_digest_to_oid (digest);
595 if (oid == NULL)
597 gnutls_assert ();
598 return GNUTLS_E_INVALID_REQUEST;
601 result = asn1_write_value (req->req, "tbsRequest.requestList", "NEW", 1);
602 if (result != ASN1_SUCCESS)
604 gnutls_assert ();
605 return _gnutls_asn2err (result);
608 result = asn1_write_value
609 (req->req, "tbsRequest.requestList.?LAST.reqCert.hashAlgorithm.algorithm",
610 oid, 1);
611 if (result != ASN1_SUCCESS)
613 gnutls_assert ();
614 return _gnutls_asn2err (result);
617 /* XXX we don't support any algorithm with parameters */
618 result = asn1_write_value
619 (req->req, "tbsRequest.requestList.?LAST.reqCert.hashAlgorithm.parameters",
620 ASN1_NULL, ASN1_NULL_SIZE);
621 if (result != ASN1_SUCCESS)
623 gnutls_assert ();
624 return _gnutls_asn2err (result);
627 result = asn1_write_value
628 (req->req, "tbsRequest.requestList.?LAST.reqCert.issuerNameHash",
629 issuer_name_hash->data, issuer_name_hash->size);
630 if (result != ASN1_SUCCESS)
632 gnutls_assert ();
633 return _gnutls_asn2err (result);
636 result = asn1_write_value
637 (req->req, "tbsRequest.requestList.?LAST.reqCert.issuerKeyHash",
638 issuer_key_hash->data, issuer_key_hash->size);
639 if (result != ASN1_SUCCESS)
641 gnutls_assert ();
642 return _gnutls_asn2err (result);
645 result = asn1_write_value
646 (req->req, "tbsRequest.requestList.?LAST.reqCert.serialNumber",
647 serial_number->data, serial_number->size);
648 if (result != ASN1_SUCCESS)
650 gnutls_assert ();
651 return _gnutls_asn2err (result);
654 /* XXX add separate function that can add extensions too */
655 result = asn1_write_value
656 (req->req, "tbsRequest.requestList.?LAST.singleRequestExtensions",
657 NULL, 0);
658 if (result != ASN1_SUCCESS)
660 gnutls_assert ();
661 return _gnutls_asn2err (result);
664 return GNUTLS_E_SUCCESS;
668 * gnutls_ocsp_req_add_cert:
669 * @req: should contain a #gnutls_ocsp_req_t structure
670 * @digest: hash algorithm, a #gnutls_digest_algorithm_t value
671 * @issuer: issuer of @subject certificate
672 * @cert: certificate to request status for
674 * This function will add another request to the OCSP request for a
675 * particular certificate. The issuer name hash, issuer key hash, and
676 * serial number fields is populated as follows. The issuer name and
677 * the serial number is taken from @cert. The issuer key is taken
678 * from @issuer. The hashed values will be hashed using the @digest
679 * algorithm, normally %GNUTLS_DIG_SHA1.
681 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
682 * negative error code is returned.
685 gnutls_ocsp_req_add_cert (gnutls_ocsp_req_t req,
686 gnutls_digest_algorithm_t digest,
687 gnutls_x509_crt_t issuer,
688 gnutls_x509_crt_t cert)
690 int ret;
691 gnutls_datum_t sn, tmp, inh, ikh;
692 uint8_t inh_buf[MAX_HASH_SIZE];
693 uint8_t ikh_buf[MAX_HASH_SIZE];
694 size_t inhlen = MAX_HASH_SIZE;
695 size_t ikhlen = MAX_HASH_SIZE;
697 if (req == NULL || issuer == NULL || cert == NULL)
699 gnutls_assert ();
700 return GNUTLS_E_INVALID_REQUEST;
703 ret = _gnutls_x509_der_encode (cert->cert,
704 "tbsCertificate.issuer.rdnSequence",
705 &tmp, 0);
706 if (ret != GNUTLS_E_SUCCESS)
708 gnutls_assert ();
709 return ret;
712 ret = gnutls_fingerprint (digest, &tmp, inh_buf, &inhlen);
713 gnutls_free (tmp.data);
714 if (ret != GNUTLS_E_SUCCESS)
716 gnutls_assert ();
717 return ret;
719 inh.size = inhlen;
720 inh.data = inh_buf;
722 ret = _gnutls_x509_read_value
723 (issuer->cert, "tbsCertificate.subjectPublicKeyInfo.subjectPublicKey",
724 &tmp, 2);
725 if (ret != GNUTLS_E_SUCCESS)
727 gnutls_assert ();
728 return ret;
731 ret = gnutls_fingerprint (digest, &tmp, ikh_buf, &ikhlen);
732 gnutls_free (tmp.data);
733 if (ret != GNUTLS_E_SUCCESS)
735 gnutls_assert ();
736 return ret;
738 ikh.size = ikhlen;
739 ikh.data = ikh_buf;
741 ret = _gnutls_x509_read_value (cert->cert, "tbsCertificate.serialNumber",
742 &sn, 0);
743 if (ret != GNUTLS_E_SUCCESS)
745 gnutls_assert ();
746 return ret;
749 ret = gnutls_ocsp_req_add_cert_id (req, digest, &inh, &ikh, &sn);
750 gnutls_free (sn.data);
751 if (ret != GNUTLS_E_SUCCESS)
753 gnutls_assert ();
754 return ret;
757 return GNUTLS_E_SUCCESS;
761 * gnutls_ocsp_req_get_extension:
762 * @req: should contain a #gnutls_ocsp_req_t structure
763 * @indx: Specifies which extension OID to get. Use (0) to get the first one.
764 * @oid: will hold newly allocated buffer with OID of extension, may be NULL
765 * @critical: output variable with critical flag, may be NULL.
766 * @data: will hold newly allocated buffer with extension data, may be NULL
768 * This function will return all information about the requested
769 * extension in the OCSP request. The information returned is the
770 * OID, the critical flag, and the data itself. The extension OID
771 * will be stored as a string. Any of @oid, @critical, and @data may
772 * be NULL which means that the caller is not interested in getting
773 * that information back.
775 * The caller needs to deallocate memory by calling gnutls_free() on
776 * @oid->data and @data->data.
778 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
779 * negative error code is returned. If you have reached the last
780 * extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will
781 * be returned.
784 gnutls_ocsp_req_get_extension (gnutls_ocsp_req_t req,
785 unsigned indx,
786 gnutls_datum_t *oid,
787 unsigned int *critical,
788 gnutls_datum_t *data)
790 int ret;
791 char str_critical[10];
792 char name[ASN1_MAX_NAME_SIZE];
793 int len;
795 if (!req)
797 gnutls_assert ();
798 return GNUTLS_E_INVALID_REQUEST;
801 snprintf (name, sizeof (name), "tbsRequest.requestExtensions.?%u.critical",
802 indx + 1);
803 len = sizeof (str_critical);
804 ret = asn1_read_value (req->req, name, str_critical, &len);
805 if (ret == ASN1_ELEMENT_NOT_FOUND)
806 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
807 else if (ret != ASN1_SUCCESS)
809 gnutls_assert ();
810 return _gnutls_asn2err (ret);
813 if (critical)
815 if (str_critical[0] == 'T')
816 *critical = 1;
817 else
818 *critical = 0;
821 if (oid)
823 snprintf (name, sizeof (name),
824 "tbsRequest.requestExtensions.?%u.extnID", indx + 1);
825 ret = _gnutls_x509_read_value (req->req, name, oid, 0);
826 if (ret != GNUTLS_E_SUCCESS)
828 gnutls_assert ();
829 return ret;
833 if (data)
835 snprintf (name, sizeof (name),
836 "tbsRequest.requestExtensions.?%u.extnValue", indx + 1);
837 ret = _gnutls_x509_read_value (req->req, name, data, 0);
838 if (ret != GNUTLS_E_SUCCESS)
840 gnutls_assert ();
841 if (oid)
842 gnutls_free (oid->data);
843 return ret;
847 return GNUTLS_E_SUCCESS;
851 * gnutls_ocsp_req_set_extension:
852 * @req: should contain a #gnutls_ocsp_req_t structure
853 * @oid: buffer with OID of extension as a string.
854 * @critical: critical flag, normally false.
855 * @data: the extension data
857 * This function will add an extension to the OCSP request. Calling
858 * this function multiple times for the same OID will overwrite values
859 * from earlier calls.
861 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
862 * negative error code is returned.
865 gnutls_ocsp_req_set_extension (gnutls_ocsp_req_t req,
866 const char *oid,
867 unsigned int critical,
868 const gnutls_datum_t *data)
870 if (req == NULL || oid == NULL || data == NULL)
872 gnutls_assert ();
873 return GNUTLS_E_INVALID_REQUEST;
876 return set_extension (req->req, "tbsRequest.requestExtensions", oid,
877 data, critical);
881 * gnutls_ocsp_req_get_nonce:
882 * @req: should contain a #gnutls_ocsp_req_t structure
883 * @critical: whether nonce extension is marked critical, or NULL
884 * @nonce: will hold newly allocated buffer with nonce data
886 * This function will return the OCSP request nonce extension data.
888 * The caller needs to deallocate memory by calling gnutls_free() on
889 * @nonce->data.
891 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
892 * negative error code is returned.
895 gnutls_ocsp_req_get_nonce (gnutls_ocsp_req_t req,
896 unsigned int *critical,
897 gnutls_datum_t *nonce)
899 int ret;
900 size_t l = 0;
901 gnutls_datum_t tmp;
903 if (req == NULL || nonce == NULL)
905 gnutls_assert ();
906 return GNUTLS_E_INVALID_REQUEST;
909 ret = get_extension (req->req, "tbsRequest.requestExtensions",
910 GNUTLS_OCSP_NONCE, 0,
911 &tmp, critical);
912 if (ret != GNUTLS_E_SUCCESS)
914 gnutls_assert ();
915 return ret;
918 ret = _gnutls_x509_decode_octet_string (NULL, tmp.data, (size_t) tmp.size,
919 NULL, &l);
920 if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
922 gnutls_assert ();
923 gnutls_free (tmp.data);
924 return ret;
927 nonce->data = gnutls_malloc (l);
928 if (nonce->data == NULL)
930 gnutls_assert ();
931 gnutls_free (tmp.data);
932 return GNUTLS_E_MEMORY_ERROR;
935 ret = _gnutls_x509_decode_octet_string (NULL, tmp.data, (size_t) tmp.size,
936 nonce->data, &l);
937 gnutls_free (tmp.data);
938 if (ret != GNUTLS_E_SUCCESS)
940 gnutls_assert ();
941 return ret;
943 nonce->size = l;
945 return GNUTLS_E_SUCCESS;
949 * gnutls_ocsp_req_set_nonce:
950 * @req: should contain a #gnutls_ocsp_req_t structure
951 * @critical: critical flag, normally false.
952 * @nonce: the nonce data
954 * This function will add an nonce extension to the OCSP request.
955 * Calling this function multiple times will overwrite values from
956 * earlier calls.
958 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
959 * negative error code is returned.
962 gnutls_ocsp_req_set_nonce (gnutls_ocsp_req_t req,
963 unsigned int critical,
964 const gnutls_datum_t *nonce)
966 int ret;
967 gnutls_datum_t dernonce;
968 unsigned char temp[SIZEOF_UNSIGNED_LONG_INT + 1];
969 int len;
971 if (req == NULL || nonce == NULL)
973 gnutls_assert ();
974 return GNUTLS_E_INVALID_REQUEST;
977 asn1_length_der (nonce->size, temp, &len);
979 dernonce.size = 1 + len + nonce->size;
980 dernonce.data = gnutls_malloc (dernonce.size);
981 if (dernonce.data == NULL)
983 gnutls_assert ();
984 return GNUTLS_E_MEMORY_ERROR;
987 dernonce.data[0] = '\x04';
988 memcpy (dernonce.data + 1, temp, len);
989 memcpy (dernonce.data + 1 + len, nonce->data, nonce->size);
991 ret = set_extension (req->req, "tbsRequest.requestExtensions",
992 GNUTLS_OCSP_NONCE, &dernonce, critical);
993 gnutls_free (dernonce.data);
994 if (ret != GNUTLS_E_SUCCESS)
996 gnutls_assert ();
997 return ret;
1000 return ret;
1004 * gnutls_ocsp_req_randomize_nonce:
1005 * @req: should contain a #gnutls_ocsp_req_t structure
1007 * This function will add or update an nonce extension to the OCSP
1008 * request with a newly generated random value.
1010 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1011 * negative error code is returned.
1014 gnutls_ocsp_req_randomize_nonce (gnutls_ocsp_req_t req)
1016 int ret;
1017 uint8_t rndbuf[23];
1018 gnutls_datum_t nonce = { rndbuf, sizeof (rndbuf) };
1020 if (req == NULL)
1022 gnutls_assert ();
1023 return GNUTLS_E_INVALID_REQUEST;
1026 ret = gnutls_rnd (GNUTLS_RND_NONCE, rndbuf, sizeof (rndbuf));
1027 if (ret != GNUTLS_E_SUCCESS)
1029 gnutls_assert ();
1030 return ret;
1033 ret = gnutls_ocsp_req_set_nonce (req, 0, &nonce);
1034 if (ret != GNUTLS_E_SUCCESS)
1036 gnutls_assert ();
1037 return ret;
1040 return GNUTLS_E_SUCCESS;
1044 * gnutls_ocsp_resp_get_status:
1045 * @resp: should contain a #gnutls_ocsp_resp_t structure
1047 * This function will return the status of a OCSP response, an
1048 * #gnutls_ocsp_resp_status_t enumeration.
1050 * Returns: status of OCSP request as a #gnutls_ocsp_resp_status_t, or
1051 * a negative error code on error.
1054 gnutls_ocsp_resp_get_status (gnutls_ocsp_resp_t resp)
1056 uint8_t str[1];
1057 int len, ret;
1059 if (resp == NULL)
1061 gnutls_assert ();
1062 return GNUTLS_E_INVALID_REQUEST;
1065 len = sizeof (str);
1066 ret = asn1_read_value (resp->resp, "responseStatus", str, &len);
1067 if (ret != ASN1_SUCCESS)
1069 gnutls_assert ();
1070 return _gnutls_asn2err (ret);
1073 switch (str[0])
1075 case GNUTLS_OCSP_RESP_SUCCESSFUL:
1076 case GNUTLS_OCSP_RESP_MALFORMEDREQUEST:
1077 case GNUTLS_OCSP_RESP_INTERNALERROR:
1078 case GNUTLS_OCSP_RESP_TRYLATER:
1079 case GNUTLS_OCSP_RESP_SIGREQUIRED:
1080 case GNUTLS_OCSP_RESP_UNAUTHORIZED:
1081 break;
1082 default:
1083 return GNUTLS_E_UNEXPECTED_PACKET;
1086 return (int) str[0];
1090 * gnutls_ocsp_resp_get_response:
1091 * @resp: should contain a #gnutls_ocsp_resp_t structure
1092 * @response_type_oid: newly allocated output buffer with response type OID
1093 * @response: newly allocated output buffer with DER encoded response
1095 * This function will extract the response type OID in and the
1096 * response data from an OCSP response. Normally the
1097 * @response_type_oid is always "1.3.6.1.5.5.7.48.1.1" which means the
1098 * @response should be decoded as a Basic OCSP Response, but
1099 * technically other response types could be used.
1101 * This function is typically only useful when you want to extract the
1102 * response type OID of an response for diagnostic purposes.
1103 * Otherwise gnutls_ocsp_resp_import() will decode the basic OCSP
1104 * response part and the caller need not worry about that aspect.
1106 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1107 * negative error value.
1110 gnutls_ocsp_resp_get_response (gnutls_ocsp_resp_t resp,
1111 gnutls_datum_t *response_type_oid,
1112 gnutls_datum_t *response)
1114 int ret;
1116 if (resp == NULL)
1118 gnutls_assert ();
1119 return GNUTLS_E_INVALID_REQUEST;
1122 if (response_type_oid != NULL)
1124 ret = _gnutls_x509_read_value (resp->resp, "responseBytes.responseType",
1125 response_type_oid, 0);
1126 if (ret < 0)
1128 gnutls_assert ();
1129 return ret;
1133 if (response != NULL)
1135 ret = _gnutls_x509_read_value (resp->resp, "responseBytes.response",
1136 response, 0);
1137 if (ret < 0)
1139 gnutls_assert ();
1140 return ret;
1144 return GNUTLS_E_SUCCESS;
1148 * gnutls_ocsp_resp_get_version:
1149 * @resp: should contain a #gnutls_ocsp_resp_t structure
1151 * This function will return the version of the Basic OCSP Response.
1152 * Typically this is always 1 indicating version 1.
1154 * Returns: version of Basic OCSP response, or a negative error code
1155 * on error.
1158 gnutls_ocsp_resp_get_version (gnutls_ocsp_resp_t resp)
1160 uint8_t version[8];
1161 int len, ret;
1163 if (resp == NULL)
1165 gnutls_assert ();
1166 return GNUTLS_E_INVALID_REQUEST;
1169 len = sizeof (version);
1170 ret = asn1_read_value (resp->resp, "tbsResponseData.version", version, &len);
1171 if (ret != ASN1_SUCCESS)
1173 if (ret == ASN1_ELEMENT_NOT_FOUND)
1174 return 1; /* the DEFAULT version */
1175 gnutls_assert ();
1176 return _gnutls_asn2err (ret);
1179 return (int) version[0] + 1;
1183 * gnutls_ocsp_resp_get_responder:
1184 * @resp: should contain a #gnutls_ocsp_resp_t structure
1185 * @dn: newly allocated buffer with name
1187 * This function will extract the name of the Basic OCSP Response in
1188 * the provided buffer. The name will be in the form
1189 * "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output string
1190 * will be ASCII or UTF-8 encoded, depending on the certificate data.
1192 * The caller needs to deallocate memory by calling gnutls_free() on
1193 * @dn->data.
1195 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1196 * negative error code is returned.
1199 gnutls_ocsp_resp_get_responder (gnutls_ocsp_resp_t resp,
1200 gnutls_datum_t *dn)
1202 int ret;
1203 size_t l = 0;
1205 if (resp == NULL || dn == NULL)
1207 gnutls_assert ();
1208 return GNUTLS_E_INVALID_REQUEST;
1211 ret = _gnutls_x509_parse_dn
1212 (resp->basicresp, "tbsResponseData.responderID.byName",
1213 NULL, &l);
1214 if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
1216 gnutls_assert ();
1217 return ret;
1220 dn->data = gnutls_malloc (l);
1221 if (dn->data == NULL)
1223 gnutls_assert ();
1224 return GNUTLS_E_MEMORY_ERROR;
1227 ret = _gnutls_x509_parse_dn
1228 (resp->basicresp, "tbsResponseData.responderID.byName",
1229 (char*)dn->data, &l);
1230 if (ret != GNUTLS_E_SUCCESS)
1232 gnutls_assert ();
1233 return ret;
1236 dn->size = l;
1238 return GNUTLS_E_SUCCESS;
1242 * gnutls_ocsp_resp_get_produced:
1243 * @resp: should contain a #gnutls_ocsp_resp_t structure
1245 * This function will return the time when the OCSP response was
1246 * signed.
1248 * Returns: signing time, or (time_t)-1 on error.
1250 time_t
1251 gnutls_ocsp_resp_get_produced (gnutls_ocsp_resp_t resp)
1253 char ttime[MAX_TIME];
1254 int len, ret;
1255 time_t c_time;
1257 if (resp == NULL || resp->basicresp == NULL)
1259 gnutls_assert ();
1260 return (time_t) (-1);
1263 len = sizeof (ttime) - 1;
1264 ret = asn1_read_value (resp->basicresp, "tbsResponseData.producedAt",
1265 ttime, &len);
1266 if (ret != ASN1_SUCCESS)
1268 gnutls_assert ();
1269 return (time_t) (-1);
1272 c_time = _gnutls_x509_generalTime2gtime (ttime);
1274 return c_time;
1278 * gnutls_ocsp_resp_get_single:
1279 * @resp: should contain a #gnutls_ocsp_resp_t structure
1280 * @indx: Specifies which extension OID to get. Use (0) to get the first one.
1281 * @digest: output variable with #gnutls_digest_algorithm_t hash algorithm
1282 * @issuer_name_hash: output buffer with hash of issuer's DN
1283 * @issuer_key_hash: output buffer with hash of issuer's public key
1284 * @serial_number: output buffer with serial number of certificate to check
1285 * @cert_status: a certificate status, a #gnutls_ocsp_cert_status_t enum.
1286 * @this_update: time at which the status is known to be correct.
1287 * @next_update: when newer information will be available, or (time_t)-1 if unspecified
1288 * @revocation_time: when @cert_status is %GNUTLS_OCSP_CERT_REVOKED, holds time of revocation.
1289 * @revocation_reason: revocation reason, a #gnutls_x509_crl_reason_t enum.
1291 * This function will return the certificate information of the
1292 * @indx'ed response in the Basic OCSP Response @resp. The
1293 * information returned corresponds to the SingleResponse structure
1294 * except the final singleExtensions, reproduced here for illustration:
1296 * <informalexample><programlisting>
1297 * SingleResponse ::= SEQUENCE {
1298 * certID CertID,
1299 * certStatus CertStatus,
1300 * thisUpdate GeneralizedTime,
1301 * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
1302 * singleExtensions [1] EXPLICIT Extensions OPTIONAL }
1304 * CertID ::= SEQUENCE {
1305 * hashAlgorithm AlgorithmIdentifier,
1306 * issuerNameHash OCTET STRING, -- Hash of Issuer's DN
1307 * issuerKeyHash OCTET STRING, -- Hash of Issuers public key
1308 * serialNumber CertificateSerialNumber }
1310 * CertStatus ::= CHOICE {
1311 * good [0] IMPLICIT NULL,
1312 * revoked [1] IMPLICIT RevokedInfo,
1313 * unknown [2] IMPLICIT UnknownInfo }
1315 * RevokedInfo ::= SEQUENCE {
1316 * revocationTime GeneralizedTime,
1317 * revocationReason [0] EXPLICIT CRLReason OPTIONAL }
1318 * </programlisting></informalexample>
1320 * Each of the pointers to output variables may be NULL to indicate
1321 * that the caller is not interested in that value.
1323 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1324 * negative error code is returned. If you have reached the last
1325 * CertID available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be
1326 * returned.
1329 gnutls_ocsp_resp_get_single (gnutls_ocsp_resp_t resp,
1330 unsigned indx,
1331 gnutls_digest_algorithm_t *digest,
1332 gnutls_datum_t *issuer_name_hash,
1333 gnutls_datum_t *issuer_key_hash,
1334 gnutls_datum_t *serial_number,
1335 unsigned int *cert_status,
1336 time_t *this_update,
1337 time_t *next_update,
1338 time_t *revocation_time,
1339 unsigned int *revocation_reason)
1341 gnutls_datum_t sa;
1342 char name[ASN1_MAX_NAME_SIZE];
1343 int ret;
1345 snprintf (name, sizeof (name),
1346 "tbsResponseData.responses.?%u.certID.hashAlgorithm.algorithm",
1347 indx + 1);
1348 ret = _gnutls_x509_read_value (resp->basicresp, name, &sa, 0);
1349 if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
1350 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1351 else if (ret < 0)
1353 gnutls_assert ();
1354 return ret;
1357 ret = _gnutls_x509_oid_to_digest ((char*)sa.data);
1358 _gnutls_free_datum (&sa);
1359 if (ret < 0)
1361 gnutls_assert ();
1362 return ret;
1365 if (digest)
1366 *digest = ret;
1368 if (issuer_name_hash)
1370 snprintf (name, sizeof (name),
1371 "tbsResponseData.responses.?%u.certID.issuerNameHash",
1372 indx + 1);
1373 ret = _gnutls_x509_read_value (resp->basicresp, name,
1374 issuer_name_hash, 0);
1375 if (ret != GNUTLS_E_SUCCESS)
1377 gnutls_assert ();
1378 return ret;
1382 if (issuer_key_hash)
1384 snprintf (name, sizeof (name),
1385 "tbsResponseData.responses.?%u.certID.issuerKeyHash",
1386 indx + 1);
1387 ret = _gnutls_x509_read_value (resp->basicresp, name,
1388 issuer_key_hash, 0);
1389 if (ret != GNUTLS_E_SUCCESS)
1391 gnutls_assert ();
1392 if (issuer_name_hash)
1393 gnutls_free (issuer_name_hash->data);
1394 return ret;
1398 if (serial_number)
1400 snprintf (name, sizeof (name),
1401 "tbsResponseData.responses.?%u.certID.serialNumber",
1402 indx + 1);
1403 ret = _gnutls_x509_read_value (resp->basicresp, name,
1404 serial_number, 0);
1405 if (ret != GNUTLS_E_SUCCESS)
1407 gnutls_assert ();
1408 if (issuer_name_hash)
1409 gnutls_free (issuer_name_hash->data);
1410 if (issuer_key_hash)
1411 gnutls_free (issuer_key_hash->data);
1412 return ret;
1416 if (cert_status)
1418 snprintf (name, sizeof (name),
1419 "tbsResponseData.responses.?%u.certStatus",
1420 indx + 1);
1421 ret = _gnutls_x509_read_value (resp->basicresp, name, &sa, 0);
1422 if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
1423 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1424 else if (ret < 0)
1426 gnutls_assert ();
1427 return ret;
1429 if (sa.size == 5 && memcmp (sa.data, "good", sa.size) == 0)
1430 *cert_status = GNUTLS_OCSP_CERT_GOOD;
1431 else if (sa.size == 8 && memcmp (sa.data, "revoked", sa.size) == 0)
1432 *cert_status = GNUTLS_OCSP_CERT_REVOKED;
1433 else if (sa.size == 8 && memcmp (sa.data, "unknown", sa.size) == 0)
1434 *cert_status = GNUTLS_OCSP_CERT_UNKNOWN;
1435 else
1437 gnutls_assert ();
1438 gnutls_free (sa.data);
1439 return GNUTLS_E_ASN1_DER_ERROR;
1441 gnutls_free (sa.data);
1444 if (this_update)
1446 char ttime[MAX_TIME];
1447 int len;
1449 snprintf (name, sizeof (name),
1450 "tbsResponseData.responses.?%u.thisUpdate",
1451 indx + 1);
1452 len = sizeof (ttime) - 1;
1453 ret = asn1_read_value (resp->basicresp, name, ttime, &len);
1454 if (ret != ASN1_SUCCESS)
1456 gnutls_assert ();
1457 *this_update = (time_t) (-1);
1459 else
1460 *this_update = _gnutls_x509_generalTime2gtime (ttime);
1463 if (next_update)
1465 char ttime[MAX_TIME];
1466 int len;
1468 snprintf (name, sizeof (name),
1469 "tbsResponseData.responses.?%u.nextUpdate",
1470 indx + 1);
1471 len = sizeof (ttime) - 1;
1472 ret = asn1_read_value (resp->basicresp, name, ttime, &len);
1473 if (ret != ASN1_SUCCESS)
1475 gnutls_assert ();
1476 *next_update = (time_t) (-1);
1478 else
1479 *next_update = _gnutls_x509_generalTime2gtime (ttime);
1482 if (revocation_time)
1484 char ttime[MAX_TIME];
1485 int len;
1487 snprintf (name, sizeof (name),
1488 "tbsResponseData.responses.?%u.certStatus."
1489 "revoked.revocationTime",
1490 indx + 1);
1491 len = sizeof (ttime) - 1;
1492 ret = asn1_read_value (resp->basicresp, name, ttime, &len);
1493 if (ret != ASN1_SUCCESS)
1495 gnutls_assert ();
1496 *revocation_time = (time_t) (-1);
1498 else
1499 *revocation_time = _gnutls_x509_generalTime2gtime (ttime);
1502 /* revocation_reason */
1504 return GNUTLS_E_SUCCESS;
1508 * gnutls_ocsp_resp_get_extension:
1509 * @resp: should contain a #gnutls_ocsp_resp_t structure
1510 * @indx: Specifies which extension OID to get. Use (0) to get the first one.
1511 * @oid: will hold newly allocated buffer with OID of extension, may be NULL
1512 * @critical: output variable with critical flag, may be NULL.
1513 * @data: will hold newly allocated buffer with extension data, may be NULL
1515 * This function will return all information about the requested
1516 * extension in the OCSP response. The information returned is the
1517 * OID, the critical flag, and the data itself. The extension OID
1518 * will be stored as a string. Any of @oid, @critical, and @data may
1519 * be NULL which means that the caller is not interested in getting
1520 * that information back.
1522 * The caller needs to deallocate memory by calling gnutls_free() on
1523 * @oid->data and @data->data.
1525 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1526 * negative error code is returned. If you have reached the last
1527 * extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will
1528 * be returned.
1531 gnutls_ocsp_resp_get_extension (gnutls_ocsp_resp_t resp,
1532 unsigned indx,
1533 gnutls_datum_t *oid,
1534 unsigned int *critical,
1535 gnutls_datum_t *data)
1537 int ret;
1538 char str_critical[10];
1539 char name[ASN1_MAX_NAME_SIZE];
1540 int len;
1542 if (!resp)
1544 gnutls_assert ();
1545 return GNUTLS_E_INVALID_REQUEST;
1548 snprintf (name, sizeof (name),
1549 "tbsResponseData.responseExtensions.?%u.critical",
1550 indx + 1);
1551 len = sizeof (str_critical);
1552 ret = asn1_read_value (resp->basicresp, name, str_critical, &len);
1553 if (ret == ASN1_ELEMENT_NOT_FOUND)
1554 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1555 else if (ret != ASN1_SUCCESS)
1557 gnutls_assert ();
1558 return _gnutls_asn2err (ret);
1561 if (critical)
1563 if (str_critical[0] == 'T')
1564 *critical = 1;
1565 else
1566 *critical = 0;
1569 if (oid)
1571 snprintf (name, sizeof (name),
1572 "tbsResponseData.responseExtensions.?%u.extnID", indx + 1);
1573 ret = _gnutls_x509_read_value (resp->basicresp, name, oid, 0);
1574 if (ret != GNUTLS_E_SUCCESS)
1576 gnutls_assert ();
1577 return ret;
1581 if (data)
1583 snprintf (name, sizeof (name),
1584 "tbsResponseData.responseExtensions.?%u.extnValue", indx + 1);
1585 ret = _gnutls_x509_read_value (resp->basicresp, name, data, 0);
1586 if (ret != GNUTLS_E_SUCCESS)
1588 gnutls_assert ();
1589 if (oid)
1590 gnutls_free (oid->data);
1591 return ret;
1595 return GNUTLS_E_SUCCESS;
1599 * gnutls_ocsp_resp_get_nonce:
1600 * @resp: should contain a #gnutls_ocsp_resp_t structure
1601 * @critical: whether nonce extension is marked critical
1602 * @nonce: will hold newly allocated buffer with nonce data
1604 * This function will return the Basic OCSP Response nonce extension
1605 * data.
1607 * The caller needs to deallocate memory by calling gnutls_free() on
1608 * @nonce->data.
1610 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1611 * negative error code is returned.
1614 gnutls_ocsp_resp_get_nonce (gnutls_ocsp_resp_t resp,
1615 unsigned int *critical,
1616 gnutls_datum_t *nonce)
1618 int ret;
1619 size_t l = 0;
1620 gnutls_datum_t tmp;
1622 ret = get_extension (resp->basicresp, "tbsResponseData.responseExtensions",
1623 GNUTLS_OCSP_NONCE, 0,
1624 &tmp, critical);
1625 if (ret != GNUTLS_E_SUCCESS)
1627 gnutls_assert ();
1628 return ret;
1631 ret = _gnutls_x509_decode_octet_string (NULL, tmp.data, (size_t) tmp.size,
1632 NULL, &l);
1633 if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
1635 gnutls_assert ();
1636 gnutls_free (tmp.data);
1637 return ret;
1640 nonce->data = gnutls_malloc (l);
1641 if (nonce->data == NULL)
1643 gnutls_assert ();
1644 gnutls_free (tmp.data);
1645 return GNUTLS_E_MEMORY_ERROR;
1648 ret = _gnutls_x509_decode_octet_string (NULL, tmp.data, (size_t) tmp.size,
1649 nonce->data, &l);
1650 gnutls_free (tmp.data);
1651 if (ret != GNUTLS_E_SUCCESS)
1653 gnutls_assert ();
1654 return ret;
1656 nonce->size = l;
1658 return GNUTLS_E_SUCCESS;
1662 * gnutls_ocsp_resp_get_signature_algorithm:
1663 * @resp: should contain a #gnutls_ocsp_resp_t structure
1665 * This function will return a value of the #gnutls_sign_algorithm_t
1666 * enumeration that is the signature algorithm that has been used to
1667 * sign the OCSP response.
1669 * Returns: a #gnutls_sign_algorithm_t value, or a negative error code
1670 * on error.
1673 gnutls_ocsp_resp_get_signature_algorithm (gnutls_ocsp_resp_t resp)
1675 int ret;
1676 gnutls_datum_t sa;
1678 ret = _gnutls_x509_read_value (resp->basicresp,
1679 "signatureAlgorithm.algorithm", &sa, 0);
1680 if (ret < 0)
1682 gnutls_assert ();
1683 return ret;
1686 ret = _gnutls_x509_oid2sign_algorithm ((char*)sa.data);
1688 _gnutls_free_datum (&sa);
1690 return ret;
1694 * gnutls_ocsp_resp_get_signature:
1695 * @resp: should contain a #gnutls_ocsp_resp_t structure
1696 * @sig: newly allocated output buffer with signature data
1698 * This function will extract the signature field of a OCSP response.
1700 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1701 * negative error value.
1704 gnutls_ocsp_resp_get_signature (gnutls_ocsp_resp_t resp,
1705 gnutls_datum_t *sig)
1707 int ret;
1709 if (resp == NULL || sig == NULL)
1711 gnutls_assert ();
1712 return GNUTLS_E_INVALID_REQUEST;
1715 ret = _gnutls_x509_read_value (resp->basicresp, "signature", sig, 2);
1716 if (ret != GNUTLS_E_SUCCESS)
1718 gnutls_assert ();
1719 return ret;
1722 return GNUTLS_E_SUCCESS;
1726 * gnutls_ocsp_resp_get_certs:
1727 * @resp: should contain a #gnutls_ocsp_resp_t structure
1728 * @certs: newly allocated array with #gnutls_x509_crt_t certificates
1729 * @ncerts: output variable with number of allocated certs.
1731 * This function will extract the X.509 certificates found in the
1732 * Basic OCSP Response. The @certs output variable will hold a newly
1733 * allocated zero-terminated array with X.509 certificates.
1735 * Every certificate in the array needs to be de-allocated with
1736 * gnutls_x509_crt_deinit() and the array itself must be freed using
1737 * gnutls_free().
1739 * Both the @certs and @ncerts variables may be NULL. Then the
1740 * function will work as normal but will not return the NULL:d
1741 * information. This can be used to get the number of certificates
1742 * only, or to just get the certificate array without its size.
1744 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1745 * negative error value.
1748 gnutls_ocsp_resp_get_certs (gnutls_ocsp_resp_t resp,
1749 gnutls_x509_crt_t ** certs,
1750 size_t *ncerts)
1752 int ret;
1753 size_t ctr = 0, i;
1754 gnutls_x509_crt_t *tmpcerts = NULL, *tmpcerts2;
1755 gnutls_datum_t c = { NULL, 0 };
1757 if (resp == NULL)
1759 gnutls_assert ();
1760 return GNUTLS_E_INVALID_REQUEST;
1763 tmpcerts = gnutls_malloc (sizeof (*tmpcerts));
1764 if (tmpcerts == NULL)
1766 gnutls_assert ();
1767 return GNUTLS_E_MEMORY_ERROR;
1770 for (;;)
1772 char name[ASN1_MAX_NAME_SIZE];
1774 snprintf (name, sizeof (name), "certs.?%u", (unsigned int)(ctr + 1));
1775 ret = _gnutls_x509_der_encode (resp->basicresp, name, &c, 0);
1776 if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
1777 break;
1778 if (ret != GNUTLS_E_SUCCESS)
1780 gnutls_assert ();
1781 goto error;
1784 tmpcerts2 = gnutls_realloc (tmpcerts, (ctr + 2) * sizeof (*tmpcerts));
1785 if (tmpcerts2 == NULL)
1787 gnutls_assert ();
1788 ret = GNUTLS_E_MEMORY_ERROR;
1789 goto error;
1791 tmpcerts = tmpcerts2;
1793 ret = gnutls_x509_crt_init (&tmpcerts[ctr]);
1794 if (ret != GNUTLS_E_SUCCESS)
1796 gnutls_assert ();
1797 goto error;
1799 ctr++;
1801 ret = gnutls_x509_crt_import (tmpcerts[ctr - 1], &c,
1802 GNUTLS_X509_FMT_DER);
1803 if (ret != GNUTLS_E_SUCCESS)
1805 gnutls_assert ();
1806 goto error;
1809 gnutls_free (c.data);
1810 c.data = NULL;
1813 tmpcerts[ctr] = NULL;
1815 if (ncerts)
1816 *ncerts = ctr;
1817 if (certs)
1818 *certs = tmpcerts;
1819 else
1821 /* clean up memory */
1822 ret = GNUTLS_E_SUCCESS;
1823 goto error;
1826 return GNUTLS_E_SUCCESS;
1828 error:
1829 gnutls_free (c.data);
1830 for (i = 0; i < ctr; i++)
1831 gnutls_x509_crt_deinit (tmpcerts[i]);
1832 gnutls_free (tmpcerts);
1833 return ret;
1836 /* Search the OCSP response for a certificate matching the responderId
1837 mentioned in the OCSP response. */
1838 static gnutls_x509_crt_t
1839 find_signercert (gnutls_ocsp_resp_t resp)
1841 int rc;
1842 gnutls_x509_crt_t * certs;
1843 size_t ncerts = 0, i;
1844 gnutls_datum_t riddn;
1845 gnutls_x509_crt_t signercert = NULL;
1847 rc = gnutls_ocsp_resp_get_responder (resp, &riddn);
1848 if (rc != GNUTLS_E_SUCCESS)
1850 gnutls_assert ();
1851 return NULL;
1854 rc = gnutls_ocsp_resp_get_certs (resp, &certs, &ncerts);
1855 if (rc != GNUTLS_E_SUCCESS)
1857 gnutls_assert ();
1858 gnutls_free (riddn.data);
1859 return NULL;
1862 for (i = 0; i < ncerts; i++)
1864 char *crtdn;
1865 size_t crtdnsize = 0;
1866 int cmpok;
1868 rc = gnutls_x509_crt_get_dn (certs[i], NULL, &crtdnsize);
1869 if (rc != GNUTLS_E_SHORT_MEMORY_BUFFER)
1871 gnutls_assert ();
1872 goto quit;
1875 crtdn = gnutls_malloc (crtdnsize);
1876 if (crtdn == NULL)
1878 gnutls_assert ();
1879 goto quit;
1882 rc = gnutls_x509_crt_get_dn (certs[i], crtdn, &crtdnsize);
1883 if (rc != GNUTLS_E_SUCCESS)
1885 gnutls_assert ();
1886 gnutls_free (crtdn);
1887 goto quit;
1890 cmpok = (crtdnsize == riddn.size)
1891 && memcmp (riddn.data, crtdn, crtdnsize);
1893 gnutls_free (crtdn);
1895 if (cmpok == 0)
1897 signercert = certs[i];
1898 goto quit;
1902 gnutls_assert ();
1903 signercert = NULL;
1905 quit:
1906 gnutls_free (riddn.data);
1907 for (i = 0; i < ncerts; i++)
1908 if (certs[i] != signercert)
1909 gnutls_x509_crt_deinit (certs[i]);
1910 gnutls_free (certs);
1911 return signercert;
1914 static int
1915 _ocsp_resp_verify_direct (gnutls_ocsp_resp_t resp,
1916 gnutls_x509_crt_t signercert,
1917 unsigned int *verify,
1918 unsigned int flags)
1920 gnutls_datum_t sig = { NULL };
1921 gnutls_datum_t data = { NULL };
1922 gnutls_pubkey_t pubkey = NULL;
1923 int sigalg;
1924 int rc;
1926 if (resp == NULL || signercert == NULL)
1928 gnutls_assert ();
1929 return GNUTLS_E_INVALID_REQUEST;
1932 rc = gnutls_ocsp_resp_get_signature_algorithm (resp);
1933 if (rc < 0)
1935 gnutls_assert ();
1936 goto done;
1938 sigalg = rc;
1940 rc = export (resp->basicresp, "tbsResponseData", &data);
1941 if (rc != GNUTLS_E_SUCCESS)
1943 gnutls_assert ();
1944 goto done;
1947 rc = gnutls_pubkey_init (&pubkey);
1948 if (rc != GNUTLS_E_SUCCESS)
1950 gnutls_assert ();
1951 goto done;
1954 rc = gnutls_pubkey_import_x509 (pubkey, signercert, 0);
1955 if (rc != GNUTLS_E_SUCCESS)
1957 gnutls_assert ();
1958 goto done;
1961 rc = gnutls_ocsp_resp_get_signature (resp, &sig);
1962 if (rc != GNUTLS_E_SUCCESS)
1964 gnutls_assert ();
1965 goto done;
1968 rc = gnutls_pubkey_verify_data2 (pubkey, sigalg, 0, &data, &sig);
1969 if (rc == GNUTLS_E_PK_SIG_VERIFY_FAILED)
1971 gnutls_assert ();
1972 *verify = GNUTLS_OCSP_VERIFY_SIGNATURE_FAILURE;
1974 else if (rc < 0)
1976 gnutls_assert ();
1977 goto done;
1979 else
1980 *verify = 0;
1982 rc = GNUTLS_E_SUCCESS;
1984 done:
1985 gnutls_free (data.data);
1986 gnutls_free (sig.data);
1987 gnutls_pubkey_deinit (pubkey);
1989 return rc;
1992 static inline unsigned int vstatus_to_ocsp_status(unsigned int status)
1994 unsigned int ostatus;
1996 if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
1997 ostatus = GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM;
1998 else if (status & GNUTLS_CERT_NOT_ACTIVATED)
1999 ostatus = GNUTLS_OCSP_VERIFY_CERT_NOT_ACTIVATED;
2000 else if (status & GNUTLS_CERT_EXPIRED)
2001 ostatus = GNUTLS_OCSP_VERIFY_CERT_EXPIRED;
2002 else
2003 ostatus = GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER;
2005 return ostatus;
2008 static int check_ocsp_purpose(gnutls_x509_crt_t signercert)
2010 char oidtmp[sizeof (GNUTLS_KP_OCSP_SIGNING)];
2011 size_t oidsize;
2012 int indx, rc;
2014 for (indx = 0; ; indx++)
2016 oidsize = sizeof (oidtmp);
2017 rc = gnutls_x509_crt_get_key_purpose_oid (signercert, indx,
2018 oidtmp, &oidsize,
2019 NULL);
2020 if (rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
2022 gnutls_assert();
2023 return rc;
2025 else if (rc == GNUTLS_E_SHORT_MEMORY_BUFFER)
2027 gnutls_assert ();
2028 continue;
2030 else if (rc != GNUTLS_E_SUCCESS)
2032 return gnutls_assert_val(rc);
2035 if (memcmp (oidtmp, GNUTLS_KP_OCSP_SIGNING, oidsize) != 0)
2037 gnutls_assert ();
2038 continue;
2040 break;
2043 return 0;
2047 * gnutls_ocsp_resp_verify_direct:
2048 * @resp: should contain a #gnutls_ocsp_resp_t structure
2049 * @issuer: certificate believed to have signed the response
2050 * @verify: output variable with verification status, an #gnutls_ocsp_cert_status_t
2051 * @flags: verification flags, 0 for now.
2053 * Verify signature of the Basic OCSP Response against the public key
2054 * in the @issuer certificate.
2056 * The output @verify variable will hold verification status codes
2057 * (e.g., %GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND,
2058 * %GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM) which are only valid if the
2059 * function returned %GNUTLS_E_SUCCESS.
2061 * Note that the function returns %GNUTLS_E_SUCCESS even when
2062 * verification failed. The caller must always inspect the @verify
2063 * variable to find out the verification status.
2065 * The @flags variable should be 0 for now.
2067 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2068 * negative error value.
2071 gnutls_ocsp_resp_verify_direct (gnutls_ocsp_resp_t resp,
2072 gnutls_x509_crt_t issuer,
2073 unsigned int *verify,
2074 unsigned int flags)
2076 gnutls_x509_crt_t signercert;
2077 int rc;
2079 if (resp == NULL || issuer == NULL)
2081 gnutls_assert ();
2082 return GNUTLS_E_INVALID_REQUEST;
2085 signercert = find_signercert (resp);
2086 if (!signercert)
2088 signercert = issuer;
2090 else /* response contains a signer. Verify him */
2092 unsigned int vtmp;
2094 rc = gnutls_x509_crt_verify (signercert, &issuer, 1, 0, &vtmp);
2095 if (rc != GNUTLS_E_SUCCESS)
2097 gnutls_assert ();
2098 goto done;
2101 if (vtmp != 0)
2103 *verify = vstatus_to_ocsp_status(vtmp);
2104 gnutls_assert ();
2105 rc = GNUTLS_E_SUCCESS;
2106 goto done;
2109 rc = check_ocsp_purpose(signercert);
2110 if (rc < 0)
2112 gnutls_assert ();
2113 *verify = GNUTLS_OCSP_VERIFY_SIGNER_KEYUSAGE_ERROR;
2114 rc = GNUTLS_E_SUCCESS;
2115 goto done;
2119 rc = _ocsp_resp_verify_direct(resp, signercert, verify, flags);
2121 done:
2122 if (signercert != issuer)
2123 gnutls_x509_crt_deinit(signercert);
2125 return rc;
2129 * gnutls_ocsp_resp_verify:
2130 * @resp: should contain a #gnutls_ocsp_resp_t structure
2131 * @trustlist: trust anchors as a #gnutls_x509_trust_list_t structure
2132 * @verify: output variable with verification status, an #gnutls_ocsp_cert_status_t
2133 * @flags: verification flags, 0 for now.
2135 * Verify signature of the Basic OCSP Response against the public key
2136 * in the certificate of a trusted signer. The @trustlist should be
2137 * populated with trust anchors. The function will extract the signer
2138 * certificate from the Basic OCSP Response and will verify it against
2139 * the @trustlist. A trusted signer is a certificate that is either
2140 * in @trustlist, or it is signed directly by a certificate in
2141 * @trustlist and has the id-ad-ocspSigning Extended Key Usage bit
2142 * set.
2144 * The output @verify variable will hold verification status codes
2145 * (e.g., %GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND,
2146 * %GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM) which are only valid if the
2147 * function returned %GNUTLS_E_SUCCESS.
2149 * Note that the function returns %GNUTLS_E_SUCCESS even when
2150 * verification failed. The caller must always inspect the @verify
2151 * variable to find out the verification status.
2153 * The @flags variable should be 0 for now.
2155 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2156 * negative error value.
2159 gnutls_ocsp_resp_verify (gnutls_ocsp_resp_t resp,
2160 gnutls_x509_trust_list_t trustlist,
2161 unsigned int *verify,
2162 unsigned int flags)
2164 gnutls_x509_crt_t signercert = NULL;
2165 int rc;
2167 /* Algorithm:
2168 1. Find signer cert.
2169 1a. Search in OCSP response Certificate field for responderID.
2170 1b. Verify that signer cert is trusted.
2171 2a. It is in trustlist?
2172 2b. It has OCSP key usage and directly signed by a CA in trustlist?
2173 3. Verify signature of Basic Response using public key from signer cert.
2176 signercert = find_signercert (resp);
2177 if (!signercert)
2179 /* XXX Search in trustlist for certificate matching
2180 responderId as well? */
2181 gnutls_assert ();
2182 *verify = GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND;
2183 rc = GNUTLS_E_SUCCESS;
2184 goto done;
2187 /* Either the signer is directly trusted (i.e., in trustlist) or it
2188 is directly signed by something in trustlist and has proper OCSP
2189 extkeyusage. */
2190 rc = _gnutls_trustlist_inlist (trustlist, signercert);
2191 if (rc < 0)
2193 gnutls_assert ();
2194 goto done;
2196 if (rc == 1)
2198 /* not in trustlist, need to verify signature and bits */
2199 gnutls_x509_crt_t issuer;
2200 unsigned vtmp;
2202 gnutls_assert ();
2204 rc = gnutls_x509_trust_list_get_issuer (trustlist, signercert,
2205 &issuer, 0);
2206 if (rc != GNUTLS_E_SUCCESS)
2208 gnutls_assert ();
2209 *verify = GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER;
2210 rc = GNUTLS_E_SUCCESS;
2211 goto done;
2214 rc = gnutls_x509_crt_verify (signercert, &issuer, 1, 0, &vtmp);
2215 if (rc != GNUTLS_E_SUCCESS)
2217 gnutls_assert ();
2218 goto done;
2221 if (vtmp != 0)
2223 *verify = vstatus_to_ocsp_status(vtmp);
2224 gnutls_assert ();
2225 rc = GNUTLS_E_SUCCESS;
2226 goto done;
2229 rc = check_ocsp_purpose(signercert);
2230 if (rc < 0)
2232 gnutls_assert ();
2233 *verify = GNUTLS_OCSP_VERIFY_SIGNER_KEYUSAGE_ERROR;
2234 rc = GNUTLS_E_SUCCESS;
2235 goto done;
2239 rc = _ocsp_resp_verify_direct (resp, signercert, verify, flags);
2241 done:
2242 gnutls_x509_crt_deinit (signercert);
2244 return rc;