check for either iconv or libiconv.
[gnutls.git] / lib / x509 / ocsp.c
blob87a250317c061c486b80eecea902a56647d153ba
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 "verify-high.h"
33 #include <gnutls/ocsp.h>
34 #include <auth/cert.h>
36 typedef struct gnutls_ocsp_req_int
38 ASN1_TYPE req;
39 } gnutls_ocsp_req_int;
41 typedef struct gnutls_ocsp_resp_int
43 ASN1_TYPE resp;
44 gnutls_datum_t response_type_oid;
45 ASN1_TYPE basicresp;
46 } gnutls_ocsp_resp_int;
48 #define MAX_TIME 64
50 /**
51 * gnutls_ocsp_req_init:
52 * @req: The structure to be initialized
54 * This function will initialize an OCSP request structure.
56 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
57 * negative error value.
58 **/
59 int
60 gnutls_ocsp_req_init (gnutls_ocsp_req_t * req)
62 gnutls_ocsp_req_t tmp = gnutls_calloc (1, sizeof (gnutls_ocsp_req_int));
63 int ret;
65 if (!tmp)
66 return GNUTLS_E_MEMORY_ERROR;
68 ret = asn1_create_element (_gnutls_get_pkix (), "PKIX1.OCSPRequest",
69 &tmp->req);
70 if (ret != ASN1_SUCCESS)
72 gnutls_assert ();
73 gnutls_free (tmp);
74 return _gnutls_asn2err (ret);
77 *req = tmp;
79 return GNUTLS_E_SUCCESS;
82 /**
83 * gnutls_ocsp_req_deinit:
84 * @req: The structure to be deinitialized
86 * This function will deinitialize a OCSP request structure.
87 **/
88 void
89 gnutls_ocsp_req_deinit (gnutls_ocsp_req_t req)
91 if (!req)
92 return;
94 if (req->req)
95 asn1_delete_structure (&req->req);
97 req->req = NULL;
99 gnutls_free (req);
103 * gnutls_ocsp_resp_init:
104 * @resp: The structure to be initialized
106 * This function will initialize an OCSP response structure.
108 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
109 * negative error value.
112 gnutls_ocsp_resp_init (gnutls_ocsp_resp_t * resp)
114 gnutls_ocsp_resp_t tmp = gnutls_calloc (1, sizeof (gnutls_ocsp_resp_int));
115 int ret;
117 if (!tmp)
118 return GNUTLS_E_MEMORY_ERROR;
120 ret = asn1_create_element (_gnutls_get_pkix (),
121 "PKIX1.OCSPResponse", &tmp->resp);
122 if (ret != ASN1_SUCCESS)
124 gnutls_assert ();
125 gnutls_free (tmp);
126 return _gnutls_asn2err (ret);
129 ret = asn1_create_element (_gnutls_get_pkix (),
130 "PKIX1.BasicOCSPResponse", &tmp->basicresp);
131 if (ret != ASN1_SUCCESS)
133 gnutls_assert ();
134 asn1_delete_structure (&tmp->resp);
135 gnutls_free (tmp);
136 return _gnutls_asn2err (ret);
139 *resp = tmp;
141 return GNUTLS_E_SUCCESS;
145 * gnutls_ocsp_resp_deinit:
146 * @resp: The structure to be deinitialized
148 * This function will deinitialize a OCSP response structure.
150 void
151 gnutls_ocsp_resp_deinit (gnutls_ocsp_resp_t resp)
153 if (!resp)
154 return;
156 if (resp->resp)
157 asn1_delete_structure (&resp->resp);
158 gnutls_free (resp->response_type_oid.data);
159 if (resp->basicresp)
160 asn1_delete_structure (&resp->basicresp);
162 resp->resp = NULL;
163 resp->response_type_oid.data = NULL;
164 resp->basicresp = NULL;
166 gnutls_free (resp);
170 * gnutls_ocsp_req_import:
171 * @req: The structure to store the parsed request.
172 * @data: DER encoded OCSP request.
174 * This function will convert the given DER encoded OCSP request to
175 * the native #gnutls_ocsp_req_t format. The output will be stored in
176 * @req.
178 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
179 * negative error value.
182 gnutls_ocsp_req_import (gnutls_ocsp_req_t req,
183 const gnutls_datum_t * data)
185 int ret = 0;
187 if (req == NULL || data == NULL)
189 gnutls_assert ();
190 return GNUTLS_E_INVALID_REQUEST;
193 if (req->req)
195 /* Any earlier asn1_der_decoding will modify the ASN.1
196 structure, so we need to replace it with a fresh
197 structure. */
198 asn1_delete_structure (&req->req);
200 ret = asn1_create_element (_gnutls_get_pkix (),
201 "PKIX1.OCSPRequest", &req->req);
202 if (ret != ASN1_SUCCESS)
204 gnutls_assert ();
205 return _gnutls_asn2err (ret);
209 ret = asn1_der_decoding (&req->req, data->data, data->size, NULL);
210 if (ret != ASN1_SUCCESS)
212 gnutls_assert ();
213 return _gnutls_asn2err (ret);
216 return GNUTLS_E_SUCCESS;
220 * gnutls_ocsp_resp_import:
221 * @resp: The structure to store the parsed response.
222 * @data: DER encoded OCSP response.
224 * This function will convert the given DER encoded OCSP response to
225 * the native #gnutls_ocsp_resp_t format. It also decodes the Basic
226 * OCSP Response part, if any. The output will be stored in @resp.
228 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
229 * negative error value.
232 gnutls_ocsp_resp_import (gnutls_ocsp_resp_t resp,
233 const gnutls_datum_t * data)
235 int ret = 0;
237 if (resp == NULL || data == NULL)
239 gnutls_assert ();
240 return GNUTLS_E_INVALID_REQUEST;
243 if (resp->resp)
245 /* Any earlier asn1_der_decoding will modify the ASN.1
246 structure, so we need to replace it with a fresh
247 structure. */
248 asn1_delete_structure (&resp->resp);
250 ret = asn1_create_element (_gnutls_get_pkix (),
251 "PKIX1.OCSPResponse", &resp->resp);
252 if (ret != ASN1_SUCCESS)
254 gnutls_assert ();
255 return _gnutls_asn2err (ret);
259 ret = asn1_der_decoding (&resp->resp, data->data, data->size, NULL);
260 if (ret != ASN1_SUCCESS)
262 gnutls_assert ();
263 return _gnutls_asn2err (ret);
266 if (gnutls_ocsp_resp_get_status (resp) != GNUTLS_OCSP_RESP_SUCCESSFUL)
267 return GNUTLS_E_SUCCESS;
269 ret = _gnutls_x509_read_value (resp->resp, "responseBytes.responseType",
270 &resp->response_type_oid);
271 if (ret < 0)
273 gnutls_assert ();
274 return ret;
277 #define OCSP_BASIC "1.3.6.1.5.5.7.48.1.1"
279 if (resp->response_type_oid.size == sizeof (OCSP_BASIC)
280 && memcmp (resp->response_type_oid.data, OCSP_BASIC,
281 resp->response_type_oid.size) == 0)
283 gnutls_datum_t d;
285 if (resp->basicresp)
287 asn1_delete_structure (&resp->basicresp);
289 ret = asn1_create_element (_gnutls_get_pkix (),
290 "PKIX1.BasicOCSPResponse", &resp->basicresp);
291 if (ret != ASN1_SUCCESS)
293 gnutls_assert ();
294 return _gnutls_asn2err (ret);
298 ret = _gnutls_x509_read_value (resp->resp, "responseBytes.response",
299 &d);
300 if (ret < 0)
302 gnutls_assert ();
303 return ret;
306 ret = asn1_der_decoding (&resp->basicresp, d.data, d.size, NULL);
307 gnutls_free (d.data);
308 if (ret != ASN1_SUCCESS)
310 gnutls_assert ();
311 return _gnutls_asn2err (ret);
314 else
315 resp->basicresp = NULL;
317 return GNUTLS_E_SUCCESS;
320 static int
321 export (ASN1_TYPE node, const char *name, gnutls_datum_t * data)
323 int ret;
324 int len = 0;
326 ret = asn1_der_coding (node, name, NULL, &len, NULL);
327 if (ret != ASN1_MEM_ERROR)
329 gnutls_assert ();
330 return _gnutls_asn2err (ret);
332 data->size = len;
333 data->data = gnutls_malloc (len);
334 if (data->data == NULL)
335 return GNUTLS_E_MEMORY_ERROR;
336 ret = asn1_der_coding (node, name, data->data, &len, NULL);
337 if (ret != ASN1_SUCCESS)
339 gnutls_assert ();
340 return _gnutls_asn2err (ret);
343 return GNUTLS_E_SUCCESS;
347 * gnutls_ocsp_req_export:
348 * @req: Holds the OCSP request
349 * @data: newly allocate buffer holding DER encoded OCSP request
351 * This function will export the OCSP request to DER format.
353 * Returns: In case of failure a negative error code will be
354 * returned, and 0 on success.
357 gnutls_ocsp_req_export (gnutls_ocsp_req_t req, gnutls_datum_t * data)
359 int ret;
361 if (req == NULL || data == NULL)
363 gnutls_assert ();
364 return GNUTLS_E_INVALID_REQUEST;
367 /* XXX remove when we support these fields */
368 asn1_write_value (req->req, "tbsRequest.requestorName", NULL, 0);
369 asn1_write_value (req->req, "optionalSignature", NULL, 0);
371 /* prune extension field if we don't have any extension */
372 ret = gnutls_ocsp_req_get_extension (req, 0, NULL, NULL, NULL);
373 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
374 asn1_write_value (req->req, "tbsRequest.requestExtensions", NULL, 0);
376 return export (req->req, "", data);
380 * gnutls_ocsp_resp_export:
381 * @resp: Holds the OCSP response
382 * @data: newly allocate buffer holding DER encoded OCSP response
384 * This function will export the OCSP response to DER format.
386 * Returns: In case of failure a negative error code will be
387 * returned, and 0 on success.
390 gnutls_ocsp_resp_export (gnutls_ocsp_resp_t resp, gnutls_datum_t * data)
392 if (resp == NULL || data == NULL)
394 gnutls_assert ();
395 return GNUTLS_E_INVALID_REQUEST;
398 return export (resp->resp, "", data);
402 * gnutls_ocsp_req_get_version:
403 * @req: should contain a #gnutls_ocsp_req_t structure
405 * This function will return the version of the OCSP request.
406 * Typically this is always 1 indicating version 1.
408 * Returns: version of OCSP request, or a negative error code on error.
411 gnutls_ocsp_req_get_version (gnutls_ocsp_req_t req)
413 uint8_t version[8];
414 int len, ret;
416 if (req == NULL)
418 gnutls_assert ();
419 return GNUTLS_E_INVALID_REQUEST;
422 len = sizeof (version);
423 ret = asn1_read_value (req->req, "tbsRequest.version", version, &len);
424 if (ret != ASN1_SUCCESS)
426 if (ret == ASN1_ELEMENT_NOT_FOUND)
427 return 1; /* the DEFAULT version */
428 gnutls_assert ();
429 return _gnutls_asn2err (ret);
432 return (int) version[0] + 1;
436 * gnutls_ocsp_req_get_cert_id:
437 * @req: should contain a #gnutls_ocsp_req_t structure
438 * @indx: Specifies which extension OID to get. Use (0) to get the first one.
439 * @digest: output variable with #gnutls_digest_algorithm_t hash algorithm
440 * @issuer_name_hash: output buffer with hash of issuer's DN
441 * @issuer_key_hash: output buffer with hash of issuer's public key
442 * @serial_number: output buffer with serial number of certificate to check
444 * This function will return the certificate information of the
445 * @indx'ed request in the OCSP request. The information returned
446 * corresponds to the CertID structure:
448 * <informalexample><programlisting>
449 * CertID ::= SEQUENCE {
450 * hashAlgorithm AlgorithmIdentifier,
451 * issuerNameHash OCTET STRING, -- Hash of Issuer's DN
452 * issuerKeyHash OCTET STRING, -- Hash of Issuers public key
453 * serialNumber CertificateSerialNumber }
454 * </programlisting></informalexample>
456 * Each of the pointers to output variables may be NULL to indicate
457 * that the caller is not interested in that value.
459 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
460 * negative error code is returned. If you have reached the last
461 * CertID available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be
462 * returned.
465 gnutls_ocsp_req_get_cert_id (gnutls_ocsp_req_t req,
466 unsigned indx,
467 gnutls_digest_algorithm_t *digest,
468 gnutls_datum_t *issuer_name_hash,
469 gnutls_datum_t *issuer_key_hash,
470 gnutls_datum_t *serial_number)
472 gnutls_datum_t sa;
473 char name[ASN1_MAX_NAME_SIZE];
474 int ret;
476 if (req == NULL)
478 gnutls_assert ();
479 return GNUTLS_E_INVALID_REQUEST;
482 snprintf (name, sizeof (name),
483 "tbsRequest.requestList.?%u.reqCert.hashAlgorithm.algorithm",
484 indx + 1);
485 ret = _gnutls_x509_read_value (req->req, name, &sa);
486 if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
487 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
488 else if (ret < 0)
490 gnutls_assert ();
491 return ret;
494 ret = _gnutls_x509_oid_to_digest ((char*)sa.data);
495 _gnutls_free_datum (&sa);
496 if (ret < 0)
498 gnutls_assert ();
499 return ret;
502 if (digest)
503 *digest = ret;
505 if (issuer_name_hash)
507 snprintf (name, sizeof (name),
508 "tbsRequest.requestList.?%u.reqCert.issuerNameHash", indx + 1);
509 ret = _gnutls_x509_read_value (req->req, name, issuer_name_hash);
510 if (ret != GNUTLS_E_SUCCESS)
512 gnutls_assert ();
513 return ret;
517 if (issuer_key_hash)
519 snprintf (name, sizeof (name),
520 "tbsRequest.requestList.?%u.reqCert.issuerKeyHash", indx + 1);
521 ret = _gnutls_x509_read_value (req->req, name, issuer_key_hash);
522 if (ret != GNUTLS_E_SUCCESS)
524 gnutls_assert ();
525 if (issuer_name_hash)
526 gnutls_free (issuer_name_hash->data);
527 return ret;
531 if (serial_number)
533 snprintf (name, sizeof (name),
534 "tbsRequest.requestList.?%u.reqCert.serialNumber", indx + 1);
535 ret = _gnutls_x509_read_value (req->req, name, serial_number);
536 if (ret != GNUTLS_E_SUCCESS)
538 gnutls_assert ();
539 if (issuer_name_hash)
540 gnutls_free (issuer_name_hash->data);
541 if (issuer_key_hash)
542 gnutls_free (issuer_key_hash->data);
543 return ret;
547 return GNUTLS_E_SUCCESS;
551 * gnutls_ocsp_req_add_cert_id:
552 * @req: should contain a #gnutls_ocsp_req_t structure
553 * @digest: hash algorithm, a #gnutls_digest_algorithm_t value
554 * @issuer_name_hash: hash of issuer's DN
555 * @issuer_key_hash: hash of issuer's public key
556 * @serial_number: serial number of certificate to check
558 * This function will add another request to the OCSP request for a
559 * particular certificate having the issuer name hash of
560 * @issuer_name_hash and issuer key hash of @issuer_key_hash (both
561 * hashed using @digest) and serial number @serial_number.
563 * The information needed corresponds to the CertID structure:
565 * <informalexample><programlisting>
566 * CertID ::= SEQUENCE {
567 * hashAlgorithm AlgorithmIdentifier,
568 * issuerNameHash OCTET STRING, -- Hash of Issuer's DN
569 * issuerKeyHash OCTET STRING, -- Hash of Issuers public key
570 * serialNumber CertificateSerialNumber }
571 * </programlisting></informalexample>
573 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
574 * negative error code is returned.
577 gnutls_ocsp_req_add_cert_id (gnutls_ocsp_req_t req,
578 gnutls_digest_algorithm_t digest,
579 const gnutls_datum_t *issuer_name_hash,
580 const gnutls_datum_t *issuer_key_hash,
581 const gnutls_datum_t *serial_number)
583 int result;
584 const char *oid;
586 if (req == NULL || issuer_name_hash == NULL
587 || issuer_key_hash == NULL || serial_number == NULL)
589 gnutls_assert ();
590 return GNUTLS_E_INVALID_REQUEST;
593 oid = _gnutls_x509_digest_to_oid (digest);
594 if (oid == NULL)
596 gnutls_assert ();
597 return GNUTLS_E_INVALID_REQUEST;
600 result = asn1_write_value (req->req, "tbsRequest.requestList", "NEW", 1);
601 if (result != ASN1_SUCCESS)
603 gnutls_assert ();
604 return _gnutls_asn2err (result);
607 result = asn1_write_value
608 (req->req, "tbsRequest.requestList.?LAST.reqCert.hashAlgorithm.algorithm",
609 oid, 1);
610 if (result != ASN1_SUCCESS)
612 gnutls_assert ();
613 return _gnutls_asn2err (result);
616 /* XXX we don't support any algorithm with parameters */
617 result = asn1_write_value
618 (req->req, "tbsRequest.requestList.?LAST.reqCert.hashAlgorithm.parameters",
619 ASN1_NULL, ASN1_NULL_SIZE);
620 if (result != ASN1_SUCCESS)
622 gnutls_assert ();
623 return _gnutls_asn2err (result);
626 result = asn1_write_value
627 (req->req, "tbsRequest.requestList.?LAST.reqCert.issuerNameHash",
628 issuer_name_hash->data, issuer_name_hash->size);
629 if (result != ASN1_SUCCESS)
631 gnutls_assert ();
632 return _gnutls_asn2err (result);
635 result = asn1_write_value
636 (req->req, "tbsRequest.requestList.?LAST.reqCert.issuerKeyHash",
637 issuer_key_hash->data, issuer_key_hash->size);
638 if (result != ASN1_SUCCESS)
640 gnutls_assert ();
641 return _gnutls_asn2err (result);
644 result = asn1_write_value
645 (req->req, "tbsRequest.requestList.?LAST.reqCert.serialNumber",
646 serial_number->data, serial_number->size);
647 if (result != ASN1_SUCCESS)
649 gnutls_assert ();
650 return _gnutls_asn2err (result);
653 /* XXX add separate function that can add extensions too */
654 result = asn1_write_value
655 (req->req, "tbsRequest.requestList.?LAST.singleRequestExtensions",
656 NULL, 0);
657 if (result != ASN1_SUCCESS)
659 gnutls_assert ();
660 return _gnutls_asn2err (result);
663 return GNUTLS_E_SUCCESS;
667 * gnutls_ocsp_req_add_cert:
668 * @req: should contain a #gnutls_ocsp_req_t structure
669 * @digest: hash algorithm, a #gnutls_digest_algorithm_t value
670 * @issuer: issuer of @subject certificate
671 * @cert: certificate to request status for
673 * This function will add another request to the OCSP request for a
674 * particular certificate. The issuer name hash, issuer key hash, and
675 * serial number fields is populated as follows. The issuer name and
676 * the serial number is taken from @cert. The issuer key is taken
677 * from @issuer. The hashed values will be hashed using the @digest
678 * algorithm, normally %GNUTLS_DIG_SHA1.
680 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
681 * negative error code is returned.
684 gnutls_ocsp_req_add_cert (gnutls_ocsp_req_t req,
685 gnutls_digest_algorithm_t digest,
686 gnutls_x509_crt_t issuer,
687 gnutls_x509_crt_t cert)
689 int ret;
690 gnutls_datum_t sn, tmp, inh, ikh;
691 uint8_t inh_buf[MAX_HASH_SIZE];
692 uint8_t ikh_buf[MAX_HASH_SIZE];
693 size_t inhlen = MAX_HASH_SIZE;
694 size_t ikhlen = MAX_HASH_SIZE;
696 if (req == NULL || issuer == NULL || cert == NULL)
698 gnutls_assert ();
699 return GNUTLS_E_INVALID_REQUEST;
702 ret = _gnutls_x509_der_encode (cert->cert,
703 "tbsCertificate.issuer.rdnSequence",
704 &tmp, 0);
705 if (ret != GNUTLS_E_SUCCESS)
707 gnutls_assert ();
708 return ret;
711 ret = gnutls_fingerprint (digest, &tmp, inh_buf, &inhlen);
712 gnutls_free (tmp.data);
713 if (ret != GNUTLS_E_SUCCESS)
715 gnutls_assert ();
716 return ret;
718 inh.size = inhlen;
719 inh.data = inh_buf;
721 ret = _gnutls_x509_read_string
722 (issuer->cert, "tbsCertificate.subjectPublicKeyInfo.subjectPublicKey",
723 &tmp, RV_BIT_STRING);
724 if (ret != GNUTLS_E_SUCCESS)
726 gnutls_assert ();
727 return ret;
730 ret = gnutls_fingerprint (digest, &tmp, ikh_buf, &ikhlen);
731 gnutls_free (tmp.data);
732 if (ret != GNUTLS_E_SUCCESS)
734 gnutls_assert ();
735 return ret;
737 ikh.size = ikhlen;
738 ikh.data = ikh_buf;
740 ret = _gnutls_x509_read_value (cert->cert, "tbsCertificate.serialNumber",
741 &sn);
742 if (ret != GNUTLS_E_SUCCESS)
744 gnutls_assert ();
745 return ret;
748 ret = gnutls_ocsp_req_add_cert_id (req, digest, &inh, &ikh, &sn);
749 gnutls_free (sn.data);
750 if (ret != GNUTLS_E_SUCCESS)
752 gnutls_assert ();
753 return ret;
756 return GNUTLS_E_SUCCESS;
760 * gnutls_ocsp_req_get_extension:
761 * @req: should contain a #gnutls_ocsp_req_t structure
762 * @indx: Specifies which extension OID to get. Use (0) to get the first one.
763 * @oid: will hold newly allocated buffer with OID of extension, may be NULL
764 * @critical: output variable with critical flag, may be NULL.
765 * @data: will hold newly allocated buffer with extension data, may be NULL
767 * This function will return all information about the requested
768 * extension in the OCSP request. The information returned is the
769 * OID, the critical flag, and the data itself. The extension OID
770 * will be stored as a string. Any of @oid, @critical, and @data may
771 * be NULL which means that the caller is not interested in getting
772 * that information back.
774 * The caller needs to deallocate memory by calling gnutls_free() on
775 * @oid->data and @data->data.
777 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
778 * negative error code is returned. If you have reached the last
779 * extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will
780 * be returned.
783 gnutls_ocsp_req_get_extension (gnutls_ocsp_req_t req,
784 unsigned indx,
785 gnutls_datum_t *oid,
786 unsigned int *critical,
787 gnutls_datum_t *data)
789 int ret;
790 char str_critical[10];
791 char name[ASN1_MAX_NAME_SIZE];
792 int len;
794 if (!req)
796 gnutls_assert ();
797 return GNUTLS_E_INVALID_REQUEST;
800 snprintf (name, sizeof (name), "tbsRequest.requestExtensions.?%u.critical",
801 indx + 1);
802 len = sizeof (str_critical);
803 ret = asn1_read_value (req->req, name, str_critical, &len);
804 if (ret == ASN1_ELEMENT_NOT_FOUND)
805 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
806 else if (ret != ASN1_SUCCESS)
808 gnutls_assert ();
809 return _gnutls_asn2err (ret);
812 if (critical)
814 if (str_critical[0] == 'T')
815 *critical = 1;
816 else
817 *critical = 0;
820 if (oid)
822 snprintf (name, sizeof (name),
823 "tbsRequest.requestExtensions.?%u.extnID", indx + 1);
824 ret = _gnutls_x509_read_value (req->req, name, oid);
825 if (ret != GNUTLS_E_SUCCESS)
827 gnutls_assert ();
828 return ret;
832 if (data)
834 snprintf (name, sizeof (name),
835 "tbsRequest.requestExtensions.?%u.extnValue", indx + 1);
836 ret = _gnutls_x509_read_value (req->req, name, data);
837 if (ret != GNUTLS_E_SUCCESS)
839 gnutls_assert ();
840 if (oid)
841 gnutls_free (oid->data);
842 return ret;
846 return GNUTLS_E_SUCCESS;
850 * gnutls_ocsp_req_set_extension:
851 * @req: should contain a #gnutls_ocsp_req_t structure
852 * @oid: buffer with OID of extension as a string.
853 * @critical: critical flag, normally false.
854 * @data: the extension data
856 * This function will add an extension to the OCSP request. Calling
857 * this function multiple times for the same OID will overwrite values
858 * from earlier calls.
860 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
861 * negative error code is returned.
864 gnutls_ocsp_req_set_extension (gnutls_ocsp_req_t req,
865 const char *oid,
866 unsigned int critical,
867 const gnutls_datum_t *data)
869 if (req == NULL || oid == NULL || data == NULL)
871 gnutls_assert ();
872 return GNUTLS_E_INVALID_REQUEST;
875 return set_extension (req->req, "tbsRequest.requestExtensions", oid,
876 data, critical);
880 * gnutls_ocsp_req_get_nonce:
881 * @req: should contain a #gnutls_ocsp_req_t structure
882 * @critical: whether nonce extension is marked critical, or NULL
883 * @nonce: will hold newly allocated buffer with nonce data
885 * This function will return the OCSP request nonce extension data.
887 * The caller needs to deallocate memory by calling gnutls_free() on
888 * @nonce->data.
890 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
891 * negative error code is returned.
894 gnutls_ocsp_req_get_nonce (gnutls_ocsp_req_t req,
895 unsigned int *critical,
896 gnutls_datum_t *nonce)
898 int ret;
899 gnutls_datum_t tmp;
901 if (req == NULL || nonce == NULL)
903 gnutls_assert ();
904 return GNUTLS_E_INVALID_REQUEST;
907 ret = get_extension (req->req, "tbsRequest.requestExtensions",
908 GNUTLS_OCSP_NONCE, 0,
909 &tmp, critical);
910 if (ret != GNUTLS_E_SUCCESS)
912 gnutls_assert ();
913 return ret;
916 ret = _gnutls_x509_decode_string (NULL, tmp.data, (size_t) tmp.size,
917 nonce);
918 if (ret < 0)
920 gnutls_assert ();
921 gnutls_free (tmp.data);
922 return ret;
925 gnutls_free (tmp.data);
927 return GNUTLS_E_SUCCESS;
931 * gnutls_ocsp_req_set_nonce:
932 * @req: should contain a #gnutls_ocsp_req_t structure
933 * @critical: critical flag, normally false.
934 * @nonce: the nonce data
936 * This function will add an nonce extension to the OCSP request.
937 * Calling this function multiple times will overwrite values from
938 * earlier calls.
940 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
941 * negative error code is returned.
944 gnutls_ocsp_req_set_nonce (gnutls_ocsp_req_t req,
945 unsigned int critical,
946 const gnutls_datum_t *nonce)
948 int ret;
949 gnutls_datum_t dernonce;
950 unsigned char temp[SIZEOF_UNSIGNED_LONG_INT + 1];
951 int len;
953 if (req == NULL || nonce == NULL)
955 gnutls_assert ();
956 return GNUTLS_E_INVALID_REQUEST;
959 asn1_length_der (nonce->size, temp, &len);
961 dernonce.size = 1 + len + nonce->size;
962 dernonce.data = gnutls_malloc (dernonce.size);
963 if (dernonce.data == NULL)
965 gnutls_assert ();
966 return GNUTLS_E_MEMORY_ERROR;
969 dernonce.data[0] = '\x04';
970 memcpy (dernonce.data + 1, temp, len);
971 memcpy (dernonce.data + 1 + len, nonce->data, nonce->size);
973 ret = set_extension (req->req, "tbsRequest.requestExtensions",
974 GNUTLS_OCSP_NONCE, &dernonce, critical);
975 gnutls_free (dernonce.data);
976 if (ret != GNUTLS_E_SUCCESS)
978 gnutls_assert ();
979 return ret;
982 return ret;
986 * gnutls_ocsp_req_randomize_nonce:
987 * @req: should contain a #gnutls_ocsp_req_t structure
989 * This function will add or update an nonce extension to the OCSP
990 * request with a newly generated random value.
992 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
993 * negative error code is returned.
996 gnutls_ocsp_req_randomize_nonce (gnutls_ocsp_req_t req)
998 int ret;
999 uint8_t rndbuf[23];
1000 gnutls_datum_t nonce = { rndbuf, sizeof (rndbuf) };
1002 if (req == NULL)
1004 gnutls_assert ();
1005 return GNUTLS_E_INVALID_REQUEST;
1008 ret = gnutls_rnd (GNUTLS_RND_NONCE, rndbuf, sizeof (rndbuf));
1009 if (ret != GNUTLS_E_SUCCESS)
1011 gnutls_assert ();
1012 return ret;
1015 ret = gnutls_ocsp_req_set_nonce (req, 0, &nonce);
1016 if (ret != GNUTLS_E_SUCCESS)
1018 gnutls_assert ();
1019 return ret;
1022 return GNUTLS_E_SUCCESS;
1026 * gnutls_ocsp_resp_get_status:
1027 * @resp: should contain a #gnutls_ocsp_resp_t structure
1029 * This function will return the status of a OCSP response, an
1030 * #gnutls_ocsp_resp_status_t enumeration.
1032 * Returns: status of OCSP request as a #gnutls_ocsp_resp_status_t, or
1033 * a negative error code on error.
1036 gnutls_ocsp_resp_get_status (gnutls_ocsp_resp_t resp)
1038 uint8_t str[1];
1039 int len, ret;
1041 if (resp == NULL)
1043 gnutls_assert ();
1044 return GNUTLS_E_INVALID_REQUEST;
1047 len = sizeof (str);
1048 ret = asn1_read_value (resp->resp, "responseStatus", str, &len);
1049 if (ret != ASN1_SUCCESS)
1051 gnutls_assert ();
1052 return _gnutls_asn2err (ret);
1055 switch (str[0])
1057 case GNUTLS_OCSP_RESP_SUCCESSFUL:
1058 case GNUTLS_OCSP_RESP_MALFORMEDREQUEST:
1059 case GNUTLS_OCSP_RESP_INTERNALERROR:
1060 case GNUTLS_OCSP_RESP_TRYLATER:
1061 case GNUTLS_OCSP_RESP_SIGREQUIRED:
1062 case GNUTLS_OCSP_RESP_UNAUTHORIZED:
1063 break;
1064 default:
1065 return GNUTLS_E_UNEXPECTED_PACKET;
1068 return (int) str[0];
1072 * gnutls_ocsp_resp_get_response:
1073 * @resp: should contain a #gnutls_ocsp_resp_t structure
1074 * @response_type_oid: newly allocated output buffer with response type OID
1075 * @response: newly allocated output buffer with DER encoded response
1077 * This function will extract the response type OID in and the
1078 * response data from an OCSP response. Normally the
1079 * @response_type_oid is always "1.3.6.1.5.5.7.48.1.1" which means the
1080 * @response should be decoded as a Basic OCSP Response, but
1081 * technically other response types could be used.
1083 * This function is typically only useful when you want to extract the
1084 * response type OID of an response for diagnostic purposes.
1085 * Otherwise gnutls_ocsp_resp_import() will decode the basic OCSP
1086 * response part and the caller need not worry about that aspect.
1088 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1089 * negative error value.
1092 gnutls_ocsp_resp_get_response (gnutls_ocsp_resp_t resp,
1093 gnutls_datum_t *response_type_oid,
1094 gnutls_datum_t *response)
1096 int ret;
1098 if (resp == NULL)
1100 gnutls_assert ();
1101 return GNUTLS_E_INVALID_REQUEST;
1104 if (response_type_oid != NULL)
1106 ret = _gnutls_x509_read_value (resp->resp, "responseBytes.responseType",
1107 response_type_oid);
1108 if (ret < 0)
1110 gnutls_assert ();
1111 return ret;
1115 if (response != NULL)
1117 ret = _gnutls_x509_read_value (resp->resp, "responseBytes.response",
1118 response);
1119 if (ret < 0)
1121 gnutls_assert ();
1122 return ret;
1126 return GNUTLS_E_SUCCESS;
1130 * gnutls_ocsp_resp_get_version:
1131 * @resp: should contain a #gnutls_ocsp_resp_t structure
1133 * This function will return the version of the Basic OCSP Response.
1134 * Typically this is always 1 indicating version 1.
1136 * Returns: version of Basic OCSP response, or a negative error code
1137 * on error.
1140 gnutls_ocsp_resp_get_version (gnutls_ocsp_resp_t resp)
1142 uint8_t version[8];
1143 int len, ret;
1145 if (resp == NULL)
1147 gnutls_assert ();
1148 return GNUTLS_E_INVALID_REQUEST;
1151 len = sizeof (version);
1152 ret = asn1_read_value (resp->resp, "tbsResponseData.version", version, &len);
1153 if (ret != ASN1_SUCCESS)
1155 if (ret == ASN1_ELEMENT_NOT_FOUND)
1156 return 1; /* the DEFAULT version */
1157 gnutls_assert ();
1158 return _gnutls_asn2err (ret);
1161 return (int) version[0] + 1;
1165 * gnutls_ocsp_resp_get_responder:
1166 * @resp: should contain a #gnutls_ocsp_resp_t structure
1167 * @dn: newly allocated buffer with name
1169 * This function will extract the name of the Basic OCSP Response in
1170 * the provided buffer. The name will be in the form
1171 * "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output string
1172 * will be ASCII or UTF-8 encoded, depending on the certificate data.
1174 * The caller needs to deallocate memory by calling gnutls_free() on
1175 * @dn->data.
1177 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1178 * negative error code is returned.
1181 gnutls_ocsp_resp_get_responder (gnutls_ocsp_resp_t resp,
1182 gnutls_datum_t *dn)
1184 int ret;
1185 size_t l = 0;
1187 if (resp == NULL || dn == NULL)
1189 gnutls_assert ();
1190 return GNUTLS_E_INVALID_REQUEST;
1193 ret = _gnutls_x509_parse_dn
1194 (resp->basicresp, "tbsResponseData.responderID.byName",
1195 NULL, &l);
1196 if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
1198 gnutls_assert ();
1199 return ret;
1202 dn->data = gnutls_malloc (l);
1203 if (dn->data == NULL)
1205 gnutls_assert ();
1206 return GNUTLS_E_MEMORY_ERROR;
1209 ret = _gnutls_x509_parse_dn
1210 (resp->basicresp, "tbsResponseData.responderID.byName",
1211 (char*)dn->data, &l);
1212 if (ret != GNUTLS_E_SUCCESS)
1214 gnutls_assert ();
1215 return ret;
1218 dn->size = l;
1220 return GNUTLS_E_SUCCESS;
1224 * gnutls_ocsp_resp_get_produced:
1225 * @resp: should contain a #gnutls_ocsp_resp_t structure
1227 * This function will return the time when the OCSP response was
1228 * signed.
1230 * Returns: signing time, or (time_t)-1 on error.
1232 time_t
1233 gnutls_ocsp_resp_get_produced (gnutls_ocsp_resp_t resp)
1235 char ttime[MAX_TIME];
1236 int len, ret;
1237 time_t c_time;
1239 if (resp == NULL || resp->basicresp == NULL)
1241 gnutls_assert ();
1242 return (time_t) (-1);
1245 len = sizeof (ttime) - 1;
1246 ret = asn1_read_value (resp->basicresp, "tbsResponseData.producedAt",
1247 ttime, &len);
1248 if (ret != ASN1_SUCCESS)
1250 gnutls_assert ();
1251 return (time_t) (-1);
1254 c_time = _gnutls_x509_generalTime2gtime (ttime);
1256 return c_time;
1260 * gnutls_ocsp_resp_check_crt:
1261 * @resp: should contain a #gnutls_ocsp_resp_t structure
1262 * @indx: Specifies response number to get. Use (0) to get the first one.
1263 * @crt: The certificate to check
1265 * This function will check whether the OCSP response
1266 * is about the provided certificate.
1268 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1269 * negative error code is returned.
1272 gnutls_ocsp_resp_check_crt (gnutls_ocsp_resp_t resp,
1273 unsigned int indx,
1274 gnutls_x509_crt_t crt)
1276 int ret;
1277 gnutls_digest_algorithm_t digest;
1278 gnutls_datum_t rdn_hash = {NULL, 0}, rserial = {NULL, 0};
1279 gnutls_datum_t cserial = {NULL, 0};
1280 gnutls_datum_t dn = {NULL, 0};
1281 uint8_t cdn_hash[MAX_HASH_SIZE];
1282 size_t t, hash_len;
1284 ret = gnutls_ocsp_resp_get_single (resp, indx, &digest, &rdn_hash, NULL,
1285 &rserial, NULL, NULL, NULL, NULL, NULL);
1286 if (ret < 0)
1287 return gnutls_assert_val(ret);
1289 if (rserial.size == 0 || digest == GNUTLS_DIG_UNKNOWN)
1291 ret = gnutls_assert_val(GNUTLS_E_OCSP_RESPONSE_ERROR);
1292 goto cleanup;
1295 hash_len = _gnutls_hash_get_algo_len(digest);
1296 if (hash_len != rdn_hash.size)
1298 ret = gnutls_assert_val(GNUTLS_E_OCSP_RESPONSE_ERROR);
1299 goto cleanup;
1302 cserial.size = rserial.size;
1303 cserial.data = gnutls_malloc(cserial.size);
1304 if (cserial.data == NULL)
1306 ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1307 goto cleanup;
1310 t = cserial.size;
1311 ret = gnutls_x509_crt_get_serial(crt, cserial.data, &t);
1312 if (ret < 0)
1314 gnutls_assert();
1315 goto cleanup;
1318 if (rserial.size != cserial.size || memcmp(cserial.data, rserial.data, rserial.size) != 0)
1320 ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
1321 gnutls_assert();
1322 goto cleanup;
1325 ret = gnutls_x509_crt_get_raw_issuer_dn(crt, &dn);
1326 if (ret < 0)
1328 gnutls_assert();
1329 goto cleanup;
1332 ret = _gnutls_hash_fast( digest, dn.data, dn.size, cdn_hash);
1333 if (ret < 0)
1335 gnutls_assert();
1336 goto cleanup;
1339 if (memcmp(cdn_hash, rdn_hash.data, hash_len) != 0)
1341 ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
1342 gnutls_assert();
1343 goto cleanup;
1346 ret = 0;
1348 cleanup:
1349 gnutls_free(rdn_hash.data);
1350 gnutls_free(rserial.data);
1351 gnutls_free(cserial.data);
1352 gnutls_free(dn.data);
1354 return ret;
1358 * gnutls_ocsp_resp_get_single:
1359 * @resp: should contain a #gnutls_ocsp_resp_t structure
1360 * @indx: Specifies response number to get. Use (0) to get the first one.
1361 * @digest: output variable with #gnutls_digest_algorithm_t hash algorithm
1362 * @issuer_name_hash: output buffer with hash of issuer's DN
1363 * @issuer_key_hash: output buffer with hash of issuer's public key
1364 * @serial_number: output buffer with serial number of certificate to check
1365 * @cert_status: a certificate status, a #gnutls_ocsp_cert_status_t enum.
1366 * @this_update: time at which the status is known to be correct.
1367 * @next_update: when newer information will be available, or (time_t)-1 if unspecified
1368 * @revocation_time: when @cert_status is %GNUTLS_OCSP_CERT_REVOKED, holds time of revocation.
1369 * @revocation_reason: revocation reason, a #gnutls_x509_crl_reason_t enum.
1371 * This function will return the certificate information of the
1372 * @indx'ed response in the Basic OCSP Response @resp. The
1373 * information returned corresponds to the OCSP SingleResponse structure
1374 * except the final singleExtensions.
1376 * Each of the pointers to output variables may be NULL to indicate
1377 * that the caller is not interested in that value.
1379 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1380 * negative error code is returned. If you have reached the last
1381 * CertID available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be
1382 * returned.
1385 gnutls_ocsp_resp_get_single (gnutls_ocsp_resp_t resp,
1386 unsigned indx,
1387 gnutls_digest_algorithm_t *digest,
1388 gnutls_datum_t *issuer_name_hash,
1389 gnutls_datum_t *issuer_key_hash,
1390 gnutls_datum_t *serial_number,
1391 unsigned int *cert_status,
1392 time_t *this_update,
1393 time_t *next_update,
1394 time_t *revocation_time,
1395 unsigned int *revocation_reason)
1397 gnutls_datum_t sa;
1398 char name[ASN1_MAX_NAME_SIZE];
1399 int ret;
1401 snprintf (name, sizeof (name),
1402 "tbsResponseData.responses.?%u.certID.hashAlgorithm.algorithm",
1403 indx + 1);
1404 ret = _gnutls_x509_read_value (resp->basicresp, name, &sa);
1405 if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
1406 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1407 else if (ret < 0)
1409 gnutls_assert ();
1410 return ret;
1413 ret = _gnutls_x509_oid_to_digest ((char*)sa.data);
1414 _gnutls_free_datum (&sa);
1415 if (ret < 0)
1417 gnutls_assert ();
1418 return ret;
1421 if (digest)
1422 *digest = ret;
1424 if (issuer_name_hash)
1426 snprintf (name, sizeof (name),
1427 "tbsResponseData.responses.?%u.certID.issuerNameHash",
1428 indx + 1);
1429 ret = _gnutls_x509_read_value (resp->basicresp, name,
1430 issuer_name_hash);
1431 if (ret != GNUTLS_E_SUCCESS)
1433 gnutls_assert ();
1434 return ret;
1438 if (issuer_key_hash)
1440 snprintf (name, sizeof (name),
1441 "tbsResponseData.responses.?%u.certID.issuerKeyHash",
1442 indx + 1);
1443 ret = _gnutls_x509_read_value (resp->basicresp, name,
1444 issuer_key_hash);
1445 if (ret != GNUTLS_E_SUCCESS)
1447 gnutls_assert ();
1448 if (issuer_name_hash)
1449 gnutls_free (issuer_name_hash->data);
1450 return ret;
1454 if (serial_number)
1456 snprintf (name, sizeof (name),
1457 "tbsResponseData.responses.?%u.certID.serialNumber",
1458 indx + 1);
1459 ret = _gnutls_x509_read_value (resp->basicresp, name,
1460 serial_number);
1461 if (ret != GNUTLS_E_SUCCESS)
1463 gnutls_assert ();
1464 if (issuer_name_hash)
1465 gnutls_free (issuer_name_hash->data);
1466 if (issuer_key_hash)
1467 gnutls_free (issuer_key_hash->data);
1468 return ret;
1472 if (cert_status)
1474 snprintf (name, sizeof (name),
1475 "tbsResponseData.responses.?%u.certStatus",
1476 indx + 1);
1477 ret = _gnutls_x509_read_value (resp->basicresp, name, &sa);
1478 if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
1479 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1480 else if (ret < 0)
1482 gnutls_assert ();
1483 return ret;
1485 if (sa.size == 5 && memcmp (sa.data, "good", sa.size) == 0)
1486 *cert_status = GNUTLS_OCSP_CERT_GOOD;
1487 else if (sa.size == 8 && memcmp (sa.data, "revoked", sa.size) == 0)
1488 *cert_status = GNUTLS_OCSP_CERT_REVOKED;
1489 else if (sa.size == 8 && memcmp (sa.data, "unknown", sa.size) == 0)
1490 *cert_status = GNUTLS_OCSP_CERT_UNKNOWN;
1491 else
1493 gnutls_assert ();
1494 gnutls_free (sa.data);
1495 return GNUTLS_E_ASN1_DER_ERROR;
1497 gnutls_free (sa.data);
1500 if (this_update)
1502 char ttime[MAX_TIME];
1503 int len;
1505 snprintf (name, sizeof (name),
1506 "tbsResponseData.responses.?%u.thisUpdate",
1507 indx + 1);
1508 len = sizeof (ttime) - 1;
1509 ret = asn1_read_value (resp->basicresp, name, ttime, &len);
1510 if (ret != ASN1_SUCCESS)
1512 gnutls_assert ();
1513 *this_update = (time_t) (-1);
1515 else
1516 *this_update = _gnutls_x509_generalTime2gtime (ttime);
1519 if (next_update)
1521 char ttime[MAX_TIME];
1522 int len;
1524 snprintf (name, sizeof (name),
1525 "tbsResponseData.responses.?%u.nextUpdate",
1526 indx + 1);
1527 len = sizeof (ttime) - 1;
1528 ret = asn1_read_value (resp->basicresp, name, ttime, &len);
1529 if (ret != ASN1_SUCCESS)
1531 gnutls_assert ();
1532 *next_update = (time_t) (-1);
1534 else
1535 *next_update = _gnutls_x509_generalTime2gtime (ttime);
1538 if (revocation_time)
1540 char ttime[MAX_TIME];
1541 int len;
1543 snprintf (name, sizeof (name),
1544 "tbsResponseData.responses.?%u.certStatus."
1545 "revoked.revocationTime",
1546 indx + 1);
1547 len = sizeof (ttime) - 1;
1548 ret = asn1_read_value (resp->basicresp, name, ttime, &len);
1549 if (ret != ASN1_SUCCESS)
1551 gnutls_assert ();
1552 *revocation_time = (time_t) (-1);
1554 else
1555 *revocation_time = _gnutls_x509_generalTime2gtime (ttime);
1558 /* revocation_reason */
1559 if (revocation_reason)
1561 snprintf (name, sizeof (name),
1562 "tbsResponseData.responses.?%u.certStatus."
1563 "revoked.revocationReason",
1564 indx + 1);
1566 ret = _gnutls_x509_read_uint (resp->basicresp, name,
1567 revocation_reason);
1568 if (ret < 0)
1569 *revocation_reason = GNUTLS_X509_CRLREASON_UNSPECIFIED;
1572 return GNUTLS_E_SUCCESS;
1576 * gnutls_ocsp_resp_get_extension:
1577 * @resp: should contain a #gnutls_ocsp_resp_t structure
1578 * @indx: Specifies which extension OID to get. Use (0) to get the first one.
1579 * @oid: will hold newly allocated buffer with OID of extension, may be NULL
1580 * @critical: output variable with critical flag, may be NULL.
1581 * @data: will hold newly allocated buffer with extension data, may be NULL
1583 * This function will return all information about the requested
1584 * extension in the OCSP response. The information returned is the
1585 * OID, the critical flag, and the data itself. The extension OID
1586 * will be stored as a string. Any of @oid, @critical, and @data may
1587 * be NULL which means that the caller is not interested in getting
1588 * that information back.
1590 * The caller needs to deallocate memory by calling gnutls_free() on
1591 * @oid->data and @data->data.
1593 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1594 * negative error code is returned. If you have reached the last
1595 * extension available %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will
1596 * be returned.
1599 gnutls_ocsp_resp_get_extension (gnutls_ocsp_resp_t resp,
1600 unsigned indx,
1601 gnutls_datum_t *oid,
1602 unsigned int *critical,
1603 gnutls_datum_t *data)
1605 int ret;
1606 char str_critical[10];
1607 char name[ASN1_MAX_NAME_SIZE];
1608 int len;
1610 if (!resp)
1612 gnutls_assert ();
1613 return GNUTLS_E_INVALID_REQUEST;
1616 snprintf (name, sizeof (name),
1617 "tbsResponseData.responseExtensions.?%u.critical",
1618 indx + 1);
1619 len = sizeof (str_critical);
1620 ret = asn1_read_value (resp->basicresp, name, str_critical, &len);
1621 if (ret == ASN1_ELEMENT_NOT_FOUND)
1622 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
1623 else if (ret != ASN1_SUCCESS)
1625 gnutls_assert ();
1626 return _gnutls_asn2err (ret);
1629 if (critical)
1631 if (str_critical[0] == 'T')
1632 *critical = 1;
1633 else
1634 *critical = 0;
1637 if (oid)
1639 snprintf (name, sizeof (name),
1640 "tbsResponseData.responseExtensions.?%u.extnID", indx + 1);
1641 ret = _gnutls_x509_read_value (resp->basicresp, name, oid);
1642 if (ret != GNUTLS_E_SUCCESS)
1644 gnutls_assert ();
1645 return ret;
1649 if (data)
1651 snprintf (name, sizeof (name),
1652 "tbsResponseData.responseExtensions.?%u.extnValue", indx + 1);
1653 ret = _gnutls_x509_read_value (resp->basicresp, name, data);
1654 if (ret != GNUTLS_E_SUCCESS)
1656 gnutls_assert ();
1657 if (oid)
1658 gnutls_free (oid->data);
1659 return ret;
1663 return GNUTLS_E_SUCCESS;
1667 * gnutls_ocsp_resp_get_nonce:
1668 * @resp: should contain a #gnutls_ocsp_resp_t structure
1669 * @critical: whether nonce extension is marked critical
1670 * @nonce: will hold newly allocated buffer with nonce data
1672 * This function will return the Basic OCSP Response nonce extension
1673 * data.
1675 * The caller needs to deallocate memory by calling gnutls_free() on
1676 * @nonce->data.
1678 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1679 * negative error code is returned.
1682 gnutls_ocsp_resp_get_nonce (gnutls_ocsp_resp_t resp,
1683 unsigned int *critical,
1684 gnutls_datum_t *nonce)
1686 int ret;
1687 gnutls_datum_t tmp;
1689 ret = get_extension (resp->basicresp, "tbsResponseData.responseExtensions",
1690 GNUTLS_OCSP_NONCE, 0,
1691 &tmp, critical);
1692 if (ret != GNUTLS_E_SUCCESS)
1694 gnutls_assert ();
1695 return ret;
1698 ret = _gnutls_x509_decode_string (NULL, tmp.data, (size_t) tmp.size,
1699 nonce);
1700 if (ret < 0)
1702 gnutls_assert ();
1703 gnutls_free (tmp.data);
1704 return ret;
1707 gnutls_free (tmp.data);
1709 return GNUTLS_E_SUCCESS;
1713 * gnutls_ocsp_resp_get_signature_algorithm:
1714 * @resp: should contain a #gnutls_ocsp_resp_t structure
1716 * This function will return a value of the #gnutls_sign_algorithm_t
1717 * enumeration that is the signature algorithm that has been used to
1718 * sign the OCSP response.
1720 * Returns: a #gnutls_sign_algorithm_t value, or a negative error code
1721 * on error.
1724 gnutls_ocsp_resp_get_signature_algorithm (gnutls_ocsp_resp_t resp)
1726 int ret;
1727 gnutls_datum_t sa;
1729 ret = _gnutls_x509_read_value (resp->basicresp,
1730 "signatureAlgorithm.algorithm", &sa);
1731 if (ret < 0)
1733 gnutls_assert ();
1734 return ret;
1737 ret = _gnutls_x509_oid2sign_algorithm ((char*)sa.data);
1739 _gnutls_free_datum (&sa);
1741 return ret;
1745 * gnutls_ocsp_resp_get_signature:
1746 * @resp: should contain a #gnutls_ocsp_resp_t structure
1747 * @sig: newly allocated output buffer with signature data
1749 * This function will extract the signature field of a OCSP response.
1751 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1752 * negative error value.
1755 gnutls_ocsp_resp_get_signature (gnutls_ocsp_resp_t resp,
1756 gnutls_datum_t *sig)
1758 int ret;
1760 if (resp == NULL || sig == NULL)
1762 gnutls_assert ();
1763 return GNUTLS_E_INVALID_REQUEST;
1766 ret = _gnutls_x509_read_string (resp->basicresp, "signature", sig, RV_BIT_STRING);
1767 if (ret != GNUTLS_E_SUCCESS)
1769 gnutls_assert ();
1770 return ret;
1773 return GNUTLS_E_SUCCESS;
1777 * gnutls_ocsp_resp_get_certs:
1778 * @resp: should contain a #gnutls_ocsp_resp_t structure
1779 * @certs: newly allocated array with #gnutls_x509_crt_t certificates
1780 * @ncerts: output variable with number of allocated certs.
1782 * This function will extract the X.509 certificates found in the
1783 * Basic OCSP Response. The @certs output variable will hold a newly
1784 * allocated zero-terminated array with X.509 certificates.
1786 * Every certificate in the array needs to be de-allocated with
1787 * gnutls_x509_crt_deinit() and the array itself must be freed using
1788 * gnutls_free().
1790 * Both the @certs and @ncerts variables may be NULL. Then the
1791 * function will work as normal but will not return the NULL:d
1792 * information. This can be used to get the number of certificates
1793 * only, or to just get the certificate array without its size.
1795 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1796 * negative error value.
1799 gnutls_ocsp_resp_get_certs (gnutls_ocsp_resp_t resp,
1800 gnutls_x509_crt_t ** certs,
1801 size_t *ncerts)
1803 int ret;
1804 size_t ctr = 0, i;
1805 gnutls_x509_crt_t *tmpcerts = NULL, *tmpcerts2;
1806 gnutls_datum_t c = { NULL, 0 };
1808 if (resp == NULL)
1810 gnutls_assert ();
1811 return GNUTLS_E_INVALID_REQUEST;
1814 tmpcerts = gnutls_malloc (sizeof (*tmpcerts));
1815 if (tmpcerts == NULL)
1817 gnutls_assert ();
1818 return GNUTLS_E_MEMORY_ERROR;
1821 for (;;)
1823 char name[ASN1_MAX_NAME_SIZE];
1825 snprintf (name, sizeof (name), "certs.?%u", (unsigned int)(ctr + 1));
1826 ret = _gnutls_x509_der_encode (resp->basicresp, name, &c, 0);
1827 if (ret == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
1828 break;
1829 if (ret != GNUTLS_E_SUCCESS)
1831 gnutls_assert ();
1832 goto error;
1835 tmpcerts2 = gnutls_realloc (tmpcerts, (ctr + 2) * sizeof (*tmpcerts));
1836 if (tmpcerts2 == NULL)
1838 gnutls_assert ();
1839 ret = GNUTLS_E_MEMORY_ERROR;
1840 goto error;
1842 tmpcerts = tmpcerts2;
1844 ret = gnutls_x509_crt_init (&tmpcerts[ctr]);
1845 if (ret != GNUTLS_E_SUCCESS)
1847 gnutls_assert ();
1848 goto error;
1850 ctr++;
1852 ret = gnutls_x509_crt_import (tmpcerts[ctr - 1], &c,
1853 GNUTLS_X509_FMT_DER);
1854 if (ret != GNUTLS_E_SUCCESS)
1856 gnutls_assert ();
1857 goto error;
1860 gnutls_free (c.data);
1861 c.data = NULL;
1864 tmpcerts[ctr] = NULL;
1866 if (ncerts)
1867 *ncerts = ctr;
1868 if (certs)
1869 *certs = tmpcerts;
1870 else
1872 /* clean up memory */
1873 ret = GNUTLS_E_SUCCESS;
1874 goto error;
1877 return GNUTLS_E_SUCCESS;
1879 error:
1880 gnutls_free (c.data);
1881 for (i = 0; i < ctr; i++)
1882 gnutls_x509_crt_deinit (tmpcerts[i]);
1883 gnutls_free (tmpcerts);
1884 return ret;
1887 /* Search the OCSP response for a certificate matching the responderId
1888 mentioned in the OCSP response. */
1889 static gnutls_x509_crt_t
1890 find_signercert (gnutls_ocsp_resp_t resp)
1892 int rc;
1893 gnutls_x509_crt_t * certs;
1894 size_t ncerts = 0, i;
1895 gnutls_datum_t riddn;
1896 gnutls_x509_crt_t signercert = NULL;
1898 rc = gnutls_ocsp_resp_get_responder (resp, &riddn);
1899 if (rc != GNUTLS_E_SUCCESS)
1901 gnutls_assert ();
1902 return NULL;
1905 rc = gnutls_ocsp_resp_get_certs (resp, &certs, &ncerts);
1906 if (rc != GNUTLS_E_SUCCESS)
1908 gnutls_assert ();
1909 gnutls_free (riddn.data);
1910 return NULL;
1913 for (i = 0; i < ncerts; i++)
1915 char *crtdn;
1916 size_t crtdnsize = 0;
1917 int cmpok;
1919 rc = gnutls_x509_crt_get_dn (certs[i], NULL, &crtdnsize);
1920 if (rc != GNUTLS_E_SHORT_MEMORY_BUFFER)
1922 gnutls_assert ();
1923 goto quit;
1926 crtdn = gnutls_malloc (crtdnsize);
1927 if (crtdn == NULL)
1929 gnutls_assert ();
1930 goto quit;
1933 rc = gnutls_x509_crt_get_dn (certs[i], crtdn, &crtdnsize);
1934 if (rc != GNUTLS_E_SUCCESS)
1936 gnutls_assert ();
1937 gnutls_free (crtdn);
1938 goto quit;
1941 cmpok = (crtdnsize == riddn.size)
1942 && memcmp (riddn.data, crtdn, crtdnsize);
1944 gnutls_free (crtdn);
1946 if (cmpok == 0)
1948 signercert = certs[i];
1949 goto quit;
1953 gnutls_assert ();
1954 signercert = NULL;
1956 quit:
1957 gnutls_free (riddn.data);
1958 for (i = 0; i < ncerts; i++)
1959 if (certs[i] != signercert)
1960 gnutls_x509_crt_deinit (certs[i]);
1961 gnutls_free (certs);
1962 return signercert;
1965 static int
1966 _ocsp_resp_verify_direct (gnutls_ocsp_resp_t resp,
1967 gnutls_x509_crt_t signercert,
1968 unsigned int *verify,
1969 unsigned int flags)
1971 gnutls_datum_t sig = { NULL };
1972 gnutls_datum_t data = { NULL };
1973 gnutls_pubkey_t pubkey = NULL;
1974 int sigalg;
1975 int rc;
1977 if (resp == NULL || signercert == NULL)
1979 gnutls_assert ();
1980 return GNUTLS_E_INVALID_REQUEST;
1983 rc = gnutls_ocsp_resp_get_signature_algorithm (resp);
1984 if (rc < 0)
1986 gnutls_assert ();
1987 goto done;
1989 sigalg = rc;
1991 rc = export (resp->basicresp, "tbsResponseData", &data);
1992 if (rc != GNUTLS_E_SUCCESS)
1994 gnutls_assert ();
1995 goto done;
1998 rc = gnutls_pubkey_init (&pubkey);
1999 if (rc != GNUTLS_E_SUCCESS)
2001 gnutls_assert ();
2002 goto done;
2005 rc = gnutls_pubkey_import_x509 (pubkey, signercert, 0);
2006 if (rc != GNUTLS_E_SUCCESS)
2008 gnutls_assert ();
2009 goto done;
2012 rc = gnutls_ocsp_resp_get_signature (resp, &sig);
2013 if (rc != GNUTLS_E_SUCCESS)
2015 gnutls_assert ();
2016 goto done;
2019 rc = gnutls_pubkey_verify_data2 (pubkey, sigalg, 0, &data, &sig);
2020 if (rc == GNUTLS_E_PK_SIG_VERIFY_FAILED)
2022 gnutls_assert ();
2023 *verify = GNUTLS_OCSP_VERIFY_SIGNATURE_FAILURE;
2025 else if (rc < 0)
2027 gnutls_assert ();
2028 goto done;
2030 else
2031 *verify = 0;
2033 rc = GNUTLS_E_SUCCESS;
2035 done:
2036 gnutls_free (data.data);
2037 gnutls_free (sig.data);
2038 gnutls_pubkey_deinit (pubkey);
2040 return rc;
2043 static inline unsigned int vstatus_to_ocsp_status(unsigned int status)
2045 unsigned int ostatus;
2047 if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
2048 ostatus = GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM;
2049 else if (status & GNUTLS_CERT_NOT_ACTIVATED)
2050 ostatus = GNUTLS_OCSP_VERIFY_CERT_NOT_ACTIVATED;
2051 else if (status & GNUTLS_CERT_EXPIRED)
2052 ostatus = GNUTLS_OCSP_VERIFY_CERT_EXPIRED;
2053 else
2054 ostatus = GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER;
2056 return ostatus;
2059 static int check_ocsp_purpose(gnutls_x509_crt_t signercert)
2061 char oidtmp[sizeof (GNUTLS_KP_OCSP_SIGNING)];
2062 size_t oidsize;
2063 int indx, rc;
2065 for (indx = 0; ; indx++)
2067 oidsize = sizeof (oidtmp);
2068 rc = gnutls_x509_crt_get_key_purpose_oid (signercert, indx,
2069 oidtmp, &oidsize,
2070 NULL);
2071 if (rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
2073 gnutls_assert();
2074 return rc;
2076 else if (rc == GNUTLS_E_SHORT_MEMORY_BUFFER)
2078 gnutls_assert ();
2079 continue;
2081 else if (rc != GNUTLS_E_SUCCESS)
2083 return gnutls_assert_val(rc);
2086 if (memcmp (oidtmp, GNUTLS_KP_OCSP_SIGNING, oidsize) != 0)
2088 gnutls_assert ();
2089 continue;
2091 break;
2094 return 0;
2098 * gnutls_ocsp_resp_verify_direct:
2099 * @resp: should contain a #gnutls_ocsp_resp_t structure
2100 * @issuer: certificate believed to have signed the response
2101 * @verify: output variable with verification status, an #gnutls_ocsp_cert_status_t
2102 * @flags: verification flags, 0 for now.
2104 * Verify signature of the Basic OCSP Response against the public key
2105 * in the @issuer certificate.
2107 * The output @verify variable will hold verification status codes
2108 * (e.g., %GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND,
2109 * %GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM) which are only valid if the
2110 * function returned %GNUTLS_E_SUCCESS.
2112 * Note that the function returns %GNUTLS_E_SUCCESS even when
2113 * verification failed. The caller must always inspect the @verify
2114 * variable to find out the verification status.
2116 * The @flags variable should be 0 for now.
2118 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2119 * negative error value.
2122 gnutls_ocsp_resp_verify_direct (gnutls_ocsp_resp_t resp,
2123 gnutls_x509_crt_t issuer,
2124 unsigned int *verify,
2125 unsigned int flags)
2127 gnutls_x509_crt_t signercert;
2128 int rc;
2130 if (resp == NULL || issuer == NULL)
2132 gnutls_assert ();
2133 return GNUTLS_E_INVALID_REQUEST;
2136 signercert = find_signercert (resp);
2137 if (!signercert)
2139 signercert = issuer;
2141 else /* response contains a signer. Verify him */
2143 unsigned int vtmp;
2145 rc = gnutls_x509_crt_verify (signercert, &issuer, 1, 0, &vtmp);
2146 if (rc != GNUTLS_E_SUCCESS)
2148 gnutls_assert ();
2149 goto done;
2152 if (vtmp != 0)
2154 *verify = vstatus_to_ocsp_status(vtmp);
2155 gnutls_assert ();
2156 rc = GNUTLS_E_SUCCESS;
2157 goto done;
2160 rc = check_ocsp_purpose(signercert);
2161 if (rc < 0)
2163 gnutls_assert ();
2164 *verify = GNUTLS_OCSP_VERIFY_SIGNER_KEYUSAGE_ERROR;
2165 rc = GNUTLS_E_SUCCESS;
2166 goto done;
2170 rc = _ocsp_resp_verify_direct(resp, signercert, verify, flags);
2172 done:
2173 if (signercert != issuer)
2174 gnutls_x509_crt_deinit(signercert);
2176 return rc;
2180 * gnutls_ocsp_resp_verify:
2181 * @resp: should contain a #gnutls_ocsp_resp_t structure
2182 * @trustlist: trust anchors as a #gnutls_x509_trust_list_t structure
2183 * @verify: output variable with verification status, an #gnutls_ocsp_cert_status_t
2184 * @flags: verification flags, 0 for now.
2186 * Verify signature of the Basic OCSP Response against the public key
2187 * in the certificate of a trusted signer. The @trustlist should be
2188 * populated with trust anchors. The function will extract the signer
2189 * certificate from the Basic OCSP Response and will verify it against
2190 * the @trustlist. A trusted signer is a certificate that is either
2191 * in @trustlist, or it is signed directly by a certificate in
2192 * @trustlist and has the id-ad-ocspSigning Extended Key Usage bit
2193 * set.
2195 * The output @verify variable will hold verification status codes
2196 * (e.g., %GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND,
2197 * %GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM) which are only valid if the
2198 * function returned %GNUTLS_E_SUCCESS.
2200 * Note that the function returns %GNUTLS_E_SUCCESS even when
2201 * verification failed. The caller must always inspect the @verify
2202 * variable to find out the verification status.
2204 * The @flags variable should be 0 for now.
2206 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
2207 * negative error value.
2210 gnutls_ocsp_resp_verify (gnutls_ocsp_resp_t resp,
2211 gnutls_x509_trust_list_t trustlist,
2212 unsigned int *verify,
2213 unsigned int flags)
2215 gnutls_x509_crt_t signercert = NULL;
2216 int rc;
2218 /* Algorithm:
2219 1. Find signer cert.
2220 1a. Search in OCSP response Certificate field for responderID.
2221 1b. Verify that signer cert is trusted.
2222 2a. It is in trustlist?
2223 2b. It has OCSP key usage and directly signed by a CA in trustlist?
2224 3. Verify signature of Basic Response using public key from signer cert.
2227 signercert = find_signercert (resp);
2228 if (!signercert)
2230 /* XXX Search in trustlist for certificate matching
2231 responderId as well? */
2232 gnutls_assert ();
2233 *verify = GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND;
2234 rc = GNUTLS_E_SUCCESS;
2235 goto done;
2238 /* Either the signer is directly trusted (i.e., in trustlist) or it
2239 is directly signed by something in trustlist and has proper OCSP
2240 extkeyusage. */
2241 rc = _gnutls_trustlist_inlist (trustlist, signercert);
2242 if (rc < 0)
2244 gnutls_assert ();
2245 goto done;
2247 if (rc == 1)
2249 /* not in trustlist, need to verify signature and bits */
2250 gnutls_x509_crt_t issuer;
2251 unsigned vtmp;
2253 gnutls_assert ();
2255 rc = gnutls_x509_trust_list_get_issuer (trustlist, signercert,
2256 &issuer, 0);
2257 if (rc != GNUTLS_E_SUCCESS)
2259 gnutls_assert ();
2260 *verify = GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER;
2261 rc = GNUTLS_E_SUCCESS;
2262 goto done;
2265 rc = gnutls_x509_crt_verify (signercert, &issuer, 1, 0, &vtmp);
2266 if (rc != GNUTLS_E_SUCCESS)
2268 gnutls_assert ();
2269 goto done;
2272 if (vtmp != 0)
2274 *verify = vstatus_to_ocsp_status(vtmp);
2275 gnutls_assert ();
2276 rc = GNUTLS_E_SUCCESS;
2277 goto done;
2280 rc = check_ocsp_purpose(signercert);
2281 if (rc < 0)
2283 gnutls_assert ();
2284 *verify = GNUTLS_OCSP_VERIFY_SIGNER_KEYUSAGE_ERROR;
2285 rc = GNUTLS_E_SUCCESS;
2286 goto done;
2290 rc = _ocsp_resp_verify_direct (resp, signercert, verify, flags);
2292 done:
2293 gnutls_x509_crt_deinit (signercert);
2295 return rc;