simplified doc
[gnutls.git] / lib / x509 / ocsp.c
blob37fa4dd298d6c945ab2a5498f19520d55c377d64
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_check_crt:
1279 * @resp: should contain a #gnutls_ocsp_resp_t structure
1280 * @crt: The certificate to check
1282 * This function will check whether the OCSP response
1283 * is about the provided certificate.
1285 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1286 * negative error code is returned.
1289 gnutls_ocsp_resp_check_crt (gnutls_ocsp_resp_t resp,
1290 gnutls_x509_crt_t crt)
1292 int ret;
1293 gnutls_digest_algorithm_t digest;
1294 gnutls_datum_t rdn_hash = {NULL, 0}, rserial = {NULL, 0};
1295 gnutls_datum_t cserial = {NULL, 0};
1296 gnutls_datum_t dn = {NULL, 0};
1297 uint8_t cdn_hash[MAX_HASH_SIZE];
1298 size_t t, hash_len;
1300 ret = gnutls_ocsp_resp_get_single (resp, 0, &digest, &rdn_hash, NULL,
1301 &rserial, NULL, NULL, NULL, NULL, NULL);
1302 if (ret < 0)
1303 return gnutls_assert_val(ret);
1305 if (rserial.size == 0 || digest == GNUTLS_DIG_UNKNOWN)
1307 ret = gnutls_assert_val(GNUTLS_E_OCSP_RESPONSE_ERROR);
1308 goto cleanup;
1311 hash_len = _gnutls_hash_get_algo_len(digest);
1312 if (hash_len != rdn_hash.size)
1314 ret = gnutls_assert_val(GNUTLS_E_OCSP_RESPONSE_ERROR);
1315 goto cleanup;
1318 cserial.size = rserial.size;
1319 cserial.data = gnutls_malloc(cserial.size);
1320 if (cserial.data == NULL)
1322 ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1323 goto cleanup;
1326 t = cserial.size;
1327 ret = gnutls_x509_crt_get_serial(crt, cserial.data, &t);
1328 if (ret < 0)
1330 gnutls_assert();
1331 goto cleanup;
1334 if (rserial.size != cserial.size || memcmp(cserial.data, rserial.data, rserial.size) != 0)
1336 ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
1337 gnutls_assert();
1338 goto cleanup;
1341 ret = gnutls_x509_crt_get_raw_issuer_dn(crt, &dn);
1342 if (ret < 0)
1344 gnutls_assert();
1345 goto cleanup;
1348 ret = _gnutls_hash_fast( digest, dn.data, dn.size, cdn_hash);
1349 if (ret < 0)
1351 gnutls_assert();
1352 goto cleanup;
1355 if (memcmp(cdn_hash, rdn_hash.data, hash_len) != 0)
1357 ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
1358 gnutls_assert();
1359 goto cleanup;
1362 ret = 0;
1364 cleanup:
1365 gnutls_free(rdn_hash.data);
1366 gnutls_free(rserial.data);
1367 gnutls_free(cserial.data);
1368 gnutls_free(dn.data);
1370 return ret;
1374 * gnutls_ocsp_resp_get_single:
1375 * @resp: should contain a #gnutls_ocsp_resp_t structure
1376 * @indx: Specifies which extension OID to get. Use (0) to get the first one.
1377 * @digest: output variable with #gnutls_digest_algorithm_t hash algorithm
1378 * @issuer_name_hash: output buffer with hash of issuer's DN
1379 * @issuer_key_hash: output buffer with hash of issuer's public key
1380 * @serial_number: output buffer with serial number of certificate to check
1381 * @cert_status: a certificate status, a #gnutls_ocsp_cert_status_t enum.
1382 * @this_update: time at which the status is known to be correct.
1383 * @next_update: when newer information will be available, or (time_t)-1 if unspecified
1384 * @revocation_time: when @cert_status is %GNUTLS_OCSP_CERT_REVOKED, holds time of revocation.
1385 * @revocation_reason: revocation reason, a #gnutls_x509_crl_reason_t enum.
1387 * This function will return the certificate information of the
1388 * @indx'ed response in the Basic OCSP Response @resp. The
1389 * information returned corresponds to the OCSP SingleResponse structure
1390 * except the final singleExtensions.
1392 * Each of the pointers to output variables may be NULL to indicate
1393 * that the caller is not interested in that value.
1395 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1396 * negative error code is returned. If you have reached the last
1397 * CertID available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be
1398 * returned.
1401 gnutls_ocsp_resp_get_single (gnutls_ocsp_resp_t resp,
1402 unsigned indx,
1403 gnutls_digest_algorithm_t *digest,
1404 gnutls_datum_t *issuer_name_hash,
1405 gnutls_datum_t *issuer_key_hash,
1406 gnutls_datum_t *serial_number,
1407 unsigned int *cert_status,
1408 time_t *this_update,
1409 time_t *next_update,
1410 time_t *revocation_time,
1411 unsigned int *revocation_reason)
1413 gnutls_datum_t sa;
1414 char name[ASN1_MAX_NAME_SIZE];
1415 int ret;
1417 snprintf (name, sizeof (name),
1418 "tbsResponseData.responses.?%u.certID.hashAlgorithm.algorithm",
1419 indx + 1);
1420 ret = _gnutls_x509_read_value (resp->basicresp, name, &sa, 0);
1421 if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
1422 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1423 else if (ret < 0)
1425 gnutls_assert ();
1426 return ret;
1429 ret = _gnutls_x509_oid_to_digest ((char*)sa.data);
1430 _gnutls_free_datum (&sa);
1431 if (ret < 0)
1433 gnutls_assert ();
1434 return ret;
1437 if (digest)
1438 *digest = ret;
1440 if (issuer_name_hash)
1442 snprintf (name, sizeof (name),
1443 "tbsResponseData.responses.?%u.certID.issuerNameHash",
1444 indx + 1);
1445 ret = _gnutls_x509_read_value (resp->basicresp, name,
1446 issuer_name_hash, 0);
1447 if (ret != GNUTLS_E_SUCCESS)
1449 gnutls_assert ();
1450 return ret;
1454 if (issuer_key_hash)
1456 snprintf (name, sizeof (name),
1457 "tbsResponseData.responses.?%u.certID.issuerKeyHash",
1458 indx + 1);
1459 ret = _gnutls_x509_read_value (resp->basicresp, name,
1460 issuer_key_hash, 0);
1461 if (ret != GNUTLS_E_SUCCESS)
1463 gnutls_assert ();
1464 if (issuer_name_hash)
1465 gnutls_free (issuer_name_hash->data);
1466 return ret;
1470 if (serial_number)
1472 snprintf (name, sizeof (name),
1473 "tbsResponseData.responses.?%u.certID.serialNumber",
1474 indx + 1);
1475 ret = _gnutls_x509_read_value (resp->basicresp, name,
1476 serial_number, 0);
1477 if (ret != GNUTLS_E_SUCCESS)
1479 gnutls_assert ();
1480 if (issuer_name_hash)
1481 gnutls_free (issuer_name_hash->data);
1482 if (issuer_key_hash)
1483 gnutls_free (issuer_key_hash->data);
1484 return ret;
1488 if (cert_status)
1490 snprintf (name, sizeof (name),
1491 "tbsResponseData.responses.?%u.certStatus",
1492 indx + 1);
1493 ret = _gnutls_x509_read_value (resp->basicresp, name, &sa, 0);
1494 if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
1495 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1496 else if (ret < 0)
1498 gnutls_assert ();
1499 return ret;
1501 if (sa.size == 5 && memcmp (sa.data, "good", sa.size) == 0)
1502 *cert_status = GNUTLS_OCSP_CERT_GOOD;
1503 else if (sa.size == 8 && memcmp (sa.data, "revoked", sa.size) == 0)
1504 *cert_status = GNUTLS_OCSP_CERT_REVOKED;
1505 else if (sa.size == 8 && memcmp (sa.data, "unknown", sa.size) == 0)
1506 *cert_status = GNUTLS_OCSP_CERT_UNKNOWN;
1507 else
1509 gnutls_assert ();
1510 gnutls_free (sa.data);
1511 return GNUTLS_E_ASN1_DER_ERROR;
1513 gnutls_free (sa.data);
1516 if (this_update)
1518 char ttime[MAX_TIME];
1519 int len;
1521 snprintf (name, sizeof (name),
1522 "tbsResponseData.responses.?%u.thisUpdate",
1523 indx + 1);
1524 len = sizeof (ttime) - 1;
1525 ret = asn1_read_value (resp->basicresp, name, ttime, &len);
1526 if (ret != ASN1_SUCCESS)
1528 gnutls_assert ();
1529 *this_update = (time_t) (-1);
1531 else
1532 *this_update = _gnutls_x509_generalTime2gtime (ttime);
1535 if (next_update)
1537 char ttime[MAX_TIME];
1538 int len;
1540 snprintf (name, sizeof (name),
1541 "tbsResponseData.responses.?%u.nextUpdate",
1542 indx + 1);
1543 len = sizeof (ttime) - 1;
1544 ret = asn1_read_value (resp->basicresp, name, ttime, &len);
1545 if (ret != ASN1_SUCCESS)
1547 gnutls_assert ();
1548 *next_update = (time_t) (-1);
1550 else
1551 *next_update = _gnutls_x509_generalTime2gtime (ttime);
1554 if (revocation_time)
1556 char ttime[MAX_TIME];
1557 int len;
1559 snprintf (name, sizeof (name),
1560 "tbsResponseData.responses.?%u.certStatus."
1561 "revoked.revocationTime",
1562 indx + 1);
1563 len = sizeof (ttime) - 1;
1564 ret = asn1_read_value (resp->basicresp, name, ttime, &len);
1565 if (ret != ASN1_SUCCESS)
1567 gnutls_assert ();
1568 *revocation_time = (time_t) (-1);
1570 else
1571 *revocation_time = _gnutls_x509_generalTime2gtime (ttime);
1574 /* revocation_reason */
1576 return GNUTLS_E_SUCCESS;
1580 * gnutls_ocsp_resp_get_extension:
1581 * @resp: should contain a #gnutls_ocsp_resp_t structure
1582 * @indx: Specifies which extension OID to get. Use (0) to get the first one.
1583 * @oid: will hold newly allocated buffer with OID of extension, may be NULL
1584 * @critical: output variable with critical flag, may be NULL.
1585 * @data: will hold newly allocated buffer with extension data, may be NULL
1587 * This function will return all information about the requested
1588 * extension in the OCSP response. The information returned is the
1589 * OID, the critical flag, and the data itself. The extension OID
1590 * will be stored as a string. Any of @oid, @critical, and @data may
1591 * be NULL which means that the caller is not interested in getting
1592 * that information back.
1594 * The caller needs to deallocate memory by calling gnutls_free() on
1595 * @oid->data and @data->data.
1597 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1598 * negative error code is returned. If you have reached the last
1599 * extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will
1600 * be returned.
1603 gnutls_ocsp_resp_get_extension (gnutls_ocsp_resp_t resp,
1604 unsigned indx,
1605 gnutls_datum_t *oid,
1606 unsigned int *critical,
1607 gnutls_datum_t *data)
1609 int ret;
1610 char str_critical[10];
1611 char name[ASN1_MAX_NAME_SIZE];
1612 int len;
1614 if (!resp)
1616 gnutls_assert ();
1617 return GNUTLS_E_INVALID_REQUEST;
1620 snprintf (name, sizeof (name),
1621 "tbsResponseData.responseExtensions.?%u.critical",
1622 indx + 1);
1623 len = sizeof (str_critical);
1624 ret = asn1_read_value (resp->basicresp, name, str_critical, &len);
1625 if (ret == ASN1_ELEMENT_NOT_FOUND)
1626 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1627 else if (ret != ASN1_SUCCESS)
1629 gnutls_assert ();
1630 return _gnutls_asn2err (ret);
1633 if (critical)
1635 if (str_critical[0] == 'T')
1636 *critical = 1;
1637 else
1638 *critical = 0;
1641 if (oid)
1643 snprintf (name, sizeof (name),
1644 "tbsResponseData.responseExtensions.?%u.extnID", indx + 1);
1645 ret = _gnutls_x509_read_value (resp->basicresp, name, oid, 0);
1646 if (ret != GNUTLS_E_SUCCESS)
1648 gnutls_assert ();
1649 return ret;
1653 if (data)
1655 snprintf (name, sizeof (name),
1656 "tbsResponseData.responseExtensions.?%u.extnValue", indx + 1);
1657 ret = _gnutls_x509_read_value (resp->basicresp, name, data, 0);
1658 if (ret != GNUTLS_E_SUCCESS)
1660 gnutls_assert ();
1661 if (oid)
1662 gnutls_free (oid->data);
1663 return ret;
1667 return GNUTLS_E_SUCCESS;
1671 * gnutls_ocsp_resp_get_nonce:
1672 * @resp: should contain a #gnutls_ocsp_resp_t structure
1673 * @critical: whether nonce extension is marked critical
1674 * @nonce: will hold newly allocated buffer with nonce data
1676 * This function will return the Basic OCSP Response nonce extension
1677 * data.
1679 * The caller needs to deallocate memory by calling gnutls_free() on
1680 * @nonce->data.
1682 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1683 * negative error code is returned.
1686 gnutls_ocsp_resp_get_nonce (gnutls_ocsp_resp_t resp,
1687 unsigned int *critical,
1688 gnutls_datum_t *nonce)
1690 int ret;
1691 size_t l = 0;
1692 gnutls_datum_t tmp;
1694 ret = get_extension (resp->basicresp, "tbsResponseData.responseExtensions",
1695 GNUTLS_OCSP_NONCE, 0,
1696 &tmp, critical);
1697 if (ret != GNUTLS_E_SUCCESS)
1699 gnutls_assert ();
1700 return ret;
1703 ret = _gnutls_x509_decode_octet_string (NULL, tmp.data, (size_t) tmp.size,
1704 NULL, &l);
1705 if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
1707 gnutls_assert ();
1708 gnutls_free (tmp.data);
1709 return ret;
1712 nonce->data = gnutls_malloc (l);
1713 if (nonce->data == NULL)
1715 gnutls_assert ();
1716 gnutls_free (tmp.data);
1717 return GNUTLS_E_MEMORY_ERROR;
1720 ret = _gnutls_x509_decode_octet_string (NULL, tmp.data, (size_t) tmp.size,
1721 nonce->data, &l);
1722 gnutls_free (tmp.data);
1723 if (ret != GNUTLS_E_SUCCESS)
1725 gnutls_assert ();
1726 return ret;
1728 nonce->size = l;
1730 return GNUTLS_E_SUCCESS;
1734 * gnutls_ocsp_resp_get_signature_algorithm:
1735 * @resp: should contain a #gnutls_ocsp_resp_t structure
1737 * This function will return a value of the #gnutls_sign_algorithm_t
1738 * enumeration that is the signature algorithm that has been used to
1739 * sign the OCSP response.
1741 * Returns: a #gnutls_sign_algorithm_t value, or a negative error code
1742 * on error.
1745 gnutls_ocsp_resp_get_signature_algorithm (gnutls_ocsp_resp_t resp)
1747 int ret;
1748 gnutls_datum_t sa;
1750 ret = _gnutls_x509_read_value (resp->basicresp,
1751 "signatureAlgorithm.algorithm", &sa, 0);
1752 if (ret < 0)
1754 gnutls_assert ();
1755 return ret;
1758 ret = _gnutls_x509_oid2sign_algorithm ((char*)sa.data);
1760 _gnutls_free_datum (&sa);
1762 return ret;
1766 * gnutls_ocsp_resp_get_signature:
1767 * @resp: should contain a #gnutls_ocsp_resp_t structure
1768 * @sig: newly allocated output buffer with signature data
1770 * This function will extract the signature field of a OCSP response.
1772 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1773 * negative error value.
1776 gnutls_ocsp_resp_get_signature (gnutls_ocsp_resp_t resp,
1777 gnutls_datum_t *sig)
1779 int ret;
1781 if (resp == NULL || sig == NULL)
1783 gnutls_assert ();
1784 return GNUTLS_E_INVALID_REQUEST;
1787 ret = _gnutls_x509_read_value (resp->basicresp, "signature", sig, 2);
1788 if (ret != GNUTLS_E_SUCCESS)
1790 gnutls_assert ();
1791 return ret;
1794 return GNUTLS_E_SUCCESS;
1798 * gnutls_ocsp_resp_get_certs:
1799 * @resp: should contain a #gnutls_ocsp_resp_t structure
1800 * @certs: newly allocated array with #gnutls_x509_crt_t certificates
1801 * @ncerts: output variable with number of allocated certs.
1803 * This function will extract the X.509 certificates found in the
1804 * Basic OCSP Response. The @certs output variable will hold a newly
1805 * allocated zero-terminated array with X.509 certificates.
1807 * Every certificate in the array needs to be de-allocated with
1808 * gnutls_x509_crt_deinit() and the array itself must be freed using
1809 * gnutls_free().
1811 * Both the @certs and @ncerts variables may be NULL. Then the
1812 * function will work as normal but will not return the NULL:d
1813 * information. This can be used to get the number of certificates
1814 * only, or to just get the certificate array without its size.
1816 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1817 * negative error value.
1820 gnutls_ocsp_resp_get_certs (gnutls_ocsp_resp_t resp,
1821 gnutls_x509_crt_t ** certs,
1822 size_t *ncerts)
1824 int ret;
1825 size_t ctr = 0, i;
1826 gnutls_x509_crt_t *tmpcerts = NULL, *tmpcerts2;
1827 gnutls_datum_t c = { NULL, 0 };
1829 if (resp == NULL)
1831 gnutls_assert ();
1832 return GNUTLS_E_INVALID_REQUEST;
1835 tmpcerts = gnutls_malloc (sizeof (*tmpcerts));
1836 if (tmpcerts == NULL)
1838 gnutls_assert ();
1839 return GNUTLS_E_MEMORY_ERROR;
1842 for (;;)
1844 char name[ASN1_MAX_NAME_SIZE];
1846 snprintf (name, sizeof (name), "certs.?%u", (unsigned int)(ctr + 1));
1847 ret = _gnutls_x509_der_encode (resp->basicresp, name, &c, 0);
1848 if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
1849 break;
1850 if (ret != GNUTLS_E_SUCCESS)
1852 gnutls_assert ();
1853 goto error;
1856 tmpcerts2 = gnutls_realloc (tmpcerts, (ctr + 2) * sizeof (*tmpcerts));
1857 if (tmpcerts2 == NULL)
1859 gnutls_assert ();
1860 ret = GNUTLS_E_MEMORY_ERROR;
1861 goto error;
1863 tmpcerts = tmpcerts2;
1865 ret = gnutls_x509_crt_init (&tmpcerts[ctr]);
1866 if (ret != GNUTLS_E_SUCCESS)
1868 gnutls_assert ();
1869 goto error;
1871 ctr++;
1873 ret = gnutls_x509_crt_import (tmpcerts[ctr - 1], &c,
1874 GNUTLS_X509_FMT_DER);
1875 if (ret != GNUTLS_E_SUCCESS)
1877 gnutls_assert ();
1878 goto error;
1881 gnutls_free (c.data);
1882 c.data = NULL;
1885 tmpcerts[ctr] = NULL;
1887 if (ncerts)
1888 *ncerts = ctr;
1889 if (certs)
1890 *certs = tmpcerts;
1891 else
1893 /* clean up memory */
1894 ret = GNUTLS_E_SUCCESS;
1895 goto error;
1898 return GNUTLS_E_SUCCESS;
1900 error:
1901 gnutls_free (c.data);
1902 for (i = 0; i < ctr; i++)
1903 gnutls_x509_crt_deinit (tmpcerts[i]);
1904 gnutls_free (tmpcerts);
1905 return ret;
1908 /* Search the OCSP response for a certificate matching the responderId
1909 mentioned in the OCSP response. */
1910 static gnutls_x509_crt_t
1911 find_signercert (gnutls_ocsp_resp_t resp)
1913 int rc;
1914 gnutls_x509_crt_t * certs;
1915 size_t ncerts = 0, i;
1916 gnutls_datum_t riddn;
1917 gnutls_x509_crt_t signercert = NULL;
1919 rc = gnutls_ocsp_resp_get_responder (resp, &riddn);
1920 if (rc != GNUTLS_E_SUCCESS)
1922 gnutls_assert ();
1923 return NULL;
1926 rc = gnutls_ocsp_resp_get_certs (resp, &certs, &ncerts);
1927 if (rc != GNUTLS_E_SUCCESS)
1929 gnutls_assert ();
1930 gnutls_free (riddn.data);
1931 return NULL;
1934 for (i = 0; i < ncerts; i++)
1936 char *crtdn;
1937 size_t crtdnsize = 0;
1938 int cmpok;
1940 rc = gnutls_x509_crt_get_dn (certs[i], NULL, &crtdnsize);
1941 if (rc != GNUTLS_E_SHORT_MEMORY_BUFFER)
1943 gnutls_assert ();
1944 goto quit;
1947 crtdn = gnutls_malloc (crtdnsize);
1948 if (crtdn == NULL)
1950 gnutls_assert ();
1951 goto quit;
1954 rc = gnutls_x509_crt_get_dn (certs[i], crtdn, &crtdnsize);
1955 if (rc != GNUTLS_E_SUCCESS)
1957 gnutls_assert ();
1958 gnutls_free (crtdn);
1959 goto quit;
1962 cmpok = (crtdnsize == riddn.size)
1963 && memcmp (riddn.data, crtdn, crtdnsize);
1965 gnutls_free (crtdn);
1967 if (cmpok == 0)
1969 signercert = certs[i];
1970 goto quit;
1974 gnutls_assert ();
1975 signercert = NULL;
1977 quit:
1978 gnutls_free (riddn.data);
1979 for (i = 0; i < ncerts; i++)
1980 if (certs[i] != signercert)
1981 gnutls_x509_crt_deinit (certs[i]);
1982 gnutls_free (certs);
1983 return signercert;
1986 static int
1987 _ocsp_resp_verify_direct (gnutls_ocsp_resp_t resp,
1988 gnutls_x509_crt_t signercert,
1989 unsigned int *verify,
1990 unsigned int flags)
1992 gnutls_datum_t sig = { NULL };
1993 gnutls_datum_t data = { NULL };
1994 gnutls_pubkey_t pubkey = NULL;
1995 int sigalg;
1996 int rc;
1998 if (resp == NULL || signercert == NULL)
2000 gnutls_assert ();
2001 return GNUTLS_E_INVALID_REQUEST;
2004 rc = gnutls_ocsp_resp_get_signature_algorithm (resp);
2005 if (rc < 0)
2007 gnutls_assert ();
2008 goto done;
2010 sigalg = rc;
2012 rc = export (resp->basicresp, "tbsResponseData", &data);
2013 if (rc != GNUTLS_E_SUCCESS)
2015 gnutls_assert ();
2016 goto done;
2019 rc = gnutls_pubkey_init (&pubkey);
2020 if (rc != GNUTLS_E_SUCCESS)
2022 gnutls_assert ();
2023 goto done;
2026 rc = gnutls_pubkey_import_x509 (pubkey, signercert, 0);
2027 if (rc != GNUTLS_E_SUCCESS)
2029 gnutls_assert ();
2030 goto done;
2033 rc = gnutls_ocsp_resp_get_signature (resp, &sig);
2034 if (rc != GNUTLS_E_SUCCESS)
2036 gnutls_assert ();
2037 goto done;
2040 rc = gnutls_pubkey_verify_data2 (pubkey, sigalg, 0, &data, &sig);
2041 if (rc == GNUTLS_E_PK_SIG_VERIFY_FAILED)
2043 gnutls_assert ();
2044 *verify = GNUTLS_OCSP_VERIFY_SIGNATURE_FAILURE;
2046 else if (rc < 0)
2048 gnutls_assert ();
2049 goto done;
2051 else
2052 *verify = 0;
2054 rc = GNUTLS_E_SUCCESS;
2056 done:
2057 gnutls_free (data.data);
2058 gnutls_free (sig.data);
2059 gnutls_pubkey_deinit (pubkey);
2061 return rc;
2064 static inline unsigned int vstatus_to_ocsp_status(unsigned int status)
2066 unsigned int ostatus;
2068 if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
2069 ostatus = GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM;
2070 else if (status & GNUTLS_CERT_NOT_ACTIVATED)
2071 ostatus = GNUTLS_OCSP_VERIFY_CERT_NOT_ACTIVATED;
2072 else if (status & GNUTLS_CERT_EXPIRED)
2073 ostatus = GNUTLS_OCSP_VERIFY_CERT_EXPIRED;
2074 else
2075 ostatus = GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER;
2077 return ostatus;
2080 static int check_ocsp_purpose(gnutls_x509_crt_t signercert)
2082 char oidtmp[sizeof (GNUTLS_KP_OCSP_SIGNING)];
2083 size_t oidsize;
2084 int indx, rc;
2086 for (indx = 0; ; indx++)
2088 oidsize = sizeof (oidtmp);
2089 rc = gnutls_x509_crt_get_key_purpose_oid (signercert, indx,
2090 oidtmp, &oidsize,
2091 NULL);
2092 if (rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
2094 gnutls_assert();
2095 return rc;
2097 else if (rc == GNUTLS_E_SHORT_MEMORY_BUFFER)
2099 gnutls_assert ();
2100 continue;
2102 else if (rc != GNUTLS_E_SUCCESS)
2104 return gnutls_assert_val(rc);
2107 if (memcmp (oidtmp, GNUTLS_KP_OCSP_SIGNING, oidsize) != 0)
2109 gnutls_assert ();
2110 continue;
2112 break;
2115 return 0;
2119 * gnutls_ocsp_resp_verify_direct:
2120 * @resp: should contain a #gnutls_ocsp_resp_t structure
2121 * @issuer: certificate believed to have signed the response
2122 * @verify: output variable with verification status, an #gnutls_ocsp_cert_status_t
2123 * @flags: verification flags, 0 for now.
2125 * Verify signature of the Basic OCSP Response against the public key
2126 * in the @issuer certificate.
2128 * The output @verify variable will hold verification status codes
2129 * (e.g., %GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND,
2130 * %GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM) which are only valid if the
2131 * function returned %GNUTLS_E_SUCCESS.
2133 * Note that the function returns %GNUTLS_E_SUCCESS even when
2134 * verification failed. The caller must always inspect the @verify
2135 * variable to find out the verification status.
2137 * The @flags variable should be 0 for now.
2139 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2140 * negative error value.
2143 gnutls_ocsp_resp_verify_direct (gnutls_ocsp_resp_t resp,
2144 gnutls_x509_crt_t issuer,
2145 unsigned int *verify,
2146 unsigned int flags)
2148 gnutls_x509_crt_t signercert;
2149 int rc;
2151 if (resp == NULL || issuer == NULL)
2153 gnutls_assert ();
2154 return GNUTLS_E_INVALID_REQUEST;
2157 signercert = find_signercert (resp);
2158 if (!signercert)
2160 signercert = issuer;
2162 else /* response contains a signer. Verify him */
2164 unsigned int vtmp;
2166 rc = gnutls_x509_crt_verify (signercert, &issuer, 1, 0, &vtmp);
2167 if (rc != GNUTLS_E_SUCCESS)
2169 gnutls_assert ();
2170 goto done;
2173 if (vtmp != 0)
2175 *verify = vstatus_to_ocsp_status(vtmp);
2176 gnutls_assert ();
2177 rc = GNUTLS_E_SUCCESS;
2178 goto done;
2181 rc = check_ocsp_purpose(signercert);
2182 if (rc < 0)
2184 gnutls_assert ();
2185 *verify = GNUTLS_OCSP_VERIFY_SIGNER_KEYUSAGE_ERROR;
2186 rc = GNUTLS_E_SUCCESS;
2187 goto done;
2191 rc = _ocsp_resp_verify_direct(resp, signercert, verify, flags);
2193 done:
2194 if (signercert != issuer)
2195 gnutls_x509_crt_deinit(signercert);
2197 return rc;
2201 * gnutls_ocsp_resp_verify:
2202 * @resp: should contain a #gnutls_ocsp_resp_t structure
2203 * @trustlist: trust anchors as a #gnutls_x509_trust_list_t structure
2204 * @verify: output variable with verification status, an #gnutls_ocsp_cert_status_t
2205 * @flags: verification flags, 0 for now.
2207 * Verify signature of the Basic OCSP Response against the public key
2208 * in the certificate of a trusted signer. The @trustlist should be
2209 * populated with trust anchors. The function will extract the signer
2210 * certificate from the Basic OCSP Response and will verify it against
2211 * the @trustlist. A trusted signer is a certificate that is either
2212 * in @trustlist, or it is signed directly by a certificate in
2213 * @trustlist and has the id-ad-ocspSigning Extended Key Usage bit
2214 * set.
2216 * The output @verify variable will hold verification status codes
2217 * (e.g., %GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND,
2218 * %GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM) which are only valid if the
2219 * function returned %GNUTLS_E_SUCCESS.
2221 * Note that the function returns %GNUTLS_E_SUCCESS even when
2222 * verification failed. The caller must always inspect the @verify
2223 * variable to find out the verification status.
2225 * The @flags variable should be 0 for now.
2227 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2228 * negative error value.
2231 gnutls_ocsp_resp_verify (gnutls_ocsp_resp_t resp,
2232 gnutls_x509_trust_list_t trustlist,
2233 unsigned int *verify,
2234 unsigned int flags)
2236 gnutls_x509_crt_t signercert = NULL;
2237 int rc;
2239 /* Algorithm:
2240 1. Find signer cert.
2241 1a. Search in OCSP response Certificate field for responderID.
2242 1b. Verify that signer cert is trusted.
2243 2a. It is in trustlist?
2244 2b. It has OCSP key usage and directly signed by a CA in trustlist?
2245 3. Verify signature of Basic Response using public key from signer cert.
2248 signercert = find_signercert (resp);
2249 if (!signercert)
2251 /* XXX Search in trustlist for certificate matching
2252 responderId as well? */
2253 gnutls_assert ();
2254 *verify = GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND;
2255 rc = GNUTLS_E_SUCCESS;
2256 goto done;
2259 /* Either the signer is directly trusted (i.e., in trustlist) or it
2260 is directly signed by something in trustlist and has proper OCSP
2261 extkeyusage. */
2262 rc = _gnutls_trustlist_inlist (trustlist, signercert);
2263 if (rc < 0)
2265 gnutls_assert ();
2266 goto done;
2268 if (rc == 1)
2270 /* not in trustlist, need to verify signature and bits */
2271 gnutls_x509_crt_t issuer;
2272 unsigned vtmp;
2274 gnutls_assert ();
2276 rc = gnutls_x509_trust_list_get_issuer (trustlist, signercert,
2277 &issuer, 0);
2278 if (rc != GNUTLS_E_SUCCESS)
2280 gnutls_assert ();
2281 *verify = GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER;
2282 rc = GNUTLS_E_SUCCESS;
2283 goto done;
2286 rc = gnutls_x509_crt_verify (signercert, &issuer, 1, 0, &vtmp);
2287 if (rc != GNUTLS_E_SUCCESS)
2289 gnutls_assert ();
2290 goto done;
2293 if (vtmp != 0)
2295 *verify = vstatus_to_ocsp_status(vtmp);
2296 gnutls_assert ();
2297 rc = GNUTLS_E_SUCCESS;
2298 goto done;
2301 rc = check_ocsp_purpose(signercert);
2302 if (rc < 0)
2304 gnutls_assert ();
2305 *verify = GNUTLS_OCSP_VERIFY_SIGNER_KEYUSAGE_ERROR;
2306 rc = GNUTLS_E_SUCCESS;
2307 goto done;
2311 rc = _ocsp_resp_verify_direct (resp, signercert, verify, flags);
2313 done:
2314 gnutls_x509_crt_deinit (signercert);
2316 return rc;