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>
29 #include <gnutls_pk.h>
31 #include "verify-high.h"
33 #include <gnutls/ocsp.h>
34 #include <auth/cert.h>
36 typedef struct gnutls_ocsp_req_int
39 } gnutls_ocsp_req_int
;
41 typedef struct gnutls_ocsp_resp_int
44 gnutls_datum_t response_type_oid
;
46 } gnutls_ocsp_resp_int
;
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.
60 gnutls_ocsp_req_init (gnutls_ocsp_req_t
* req
)
62 gnutls_ocsp_req_t tmp
= gnutls_calloc (1, sizeof (gnutls_ocsp_req_int
));
66 return GNUTLS_E_MEMORY_ERROR
;
68 ret
= asn1_create_element (_gnutls_get_pkix (), "PKIX1.OCSPRequest",
70 if (ret
!= ASN1_SUCCESS
)
74 return _gnutls_asn2err (ret
);
79 return GNUTLS_E_SUCCESS
;
83 * gnutls_ocsp_req_deinit:
84 * @req: The structure to be deinitialized
86 * This function will deinitialize a OCSP request structure.
89 gnutls_ocsp_req_deinit (gnutls_ocsp_req_t req
)
95 asn1_delete_structure (&req
->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
));
118 return GNUTLS_E_MEMORY_ERROR
;
120 ret
= asn1_create_element (_gnutls_get_pkix (),
121 "PKIX1.OCSPResponse", &tmp
->resp
);
122 if (ret
!= ASN1_SUCCESS
)
126 return _gnutls_asn2err (ret
);
129 ret
= asn1_create_element (_gnutls_get_pkix (),
130 "PKIX1.BasicOCSPResponse", &tmp
->basicresp
);
131 if (ret
!= ASN1_SUCCESS
)
134 asn1_delete_structure (&tmp
->resp
);
136 return _gnutls_asn2err (ret
);
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.
151 gnutls_ocsp_resp_deinit (gnutls_ocsp_resp_t resp
)
157 asn1_delete_structure (&resp
->resp
);
158 gnutls_free (resp
->response_type_oid
.data
);
160 asn1_delete_structure (&resp
->basicresp
);
163 resp
->response_type_oid
.data
= NULL
;
164 resp
->basicresp
= NULL
;
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
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
)
187 if (req
== NULL
|| data
== NULL
)
190 return GNUTLS_E_INVALID_REQUEST
;
195 /* Any earlier asn1_der_decoding will modify the ASN.1
196 structure, so we need to replace it with a fresh
198 asn1_delete_structure (&req
->req
);
200 ret
= asn1_create_element (_gnutls_get_pkix (),
201 "PKIX1.OCSPRequest", &req
->req
);
202 if (ret
!= ASN1_SUCCESS
)
205 return _gnutls_asn2err (ret
);
209 ret
= asn1_der_decoding (&req
->req
, data
->data
, data
->size
, NULL
);
210 if (ret
!= ASN1_SUCCESS
)
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
)
237 if (resp
== NULL
|| data
== NULL
)
240 return GNUTLS_E_INVALID_REQUEST
;
245 /* Any earlier asn1_der_decoding will modify the ASN.1
246 structure, so we need to replace it with a fresh
248 asn1_delete_structure (&resp
->resp
);
250 ret
= asn1_create_element (_gnutls_get_pkix (),
251 "PKIX1.OCSPResponse", &resp
->resp
);
252 if (ret
!= ASN1_SUCCESS
)
255 return _gnutls_asn2err (ret
);
259 ret
= asn1_der_decoding (&resp
->resp
, data
->data
, data
->size
, NULL
);
260 if (ret
!= ASN1_SUCCESS
)
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
);
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)
287 asn1_delete_structure (&resp
->basicresp
);
289 ret
= asn1_create_element (_gnutls_get_pkix (),
290 "PKIX1.BasicOCSPResponse", &resp
->basicresp
);
291 if (ret
!= ASN1_SUCCESS
)
294 return _gnutls_asn2err (ret
);
298 ret
= _gnutls_x509_read_value (resp
->resp
, "responseBytes.response",
306 ret
= asn1_der_decoding (&resp
->basicresp
, d
.data
, d
.size
, NULL
);
307 gnutls_free (d
.data
);
308 if (ret
!= ASN1_SUCCESS
)
311 return _gnutls_asn2err (ret
);
315 resp
->basicresp
= NULL
;
317 return GNUTLS_E_SUCCESS
;
321 export (ASN1_TYPE node
, const char *name
, gnutls_datum_t
* data
)
326 ret
= asn1_der_coding (node
, name
, NULL
, &len
, NULL
);
327 if (ret
!= ASN1_MEM_ERROR
)
330 return _gnutls_asn2err (ret
);
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
)
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
)
361 if (req
== NULL
|| data
== NULL
)
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
)
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
)
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 */
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
465 gnutls_ocsp_req_get_cert_id (gnutls_ocsp_req_t req
,
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
)
473 char name
[ASN1_MAX_NAME_SIZE
];
479 return GNUTLS_E_INVALID_REQUEST
;
482 snprintf (name
, sizeof (name
),
483 "tbsRequest.requestList.?%u.reqCert.hashAlgorithm.algorithm",
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
;
494 ret
= _gnutls_x509_oid_to_digest ((char*)sa
.data
);
495 _gnutls_free_datum (&sa
);
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
)
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
)
525 if (issuer_name_hash
)
526 gnutls_free (issuer_name_hash
->data
);
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
)
539 if (issuer_name_hash
)
540 gnutls_free (issuer_name_hash
->data
);
542 gnutls_free (issuer_key_hash
->data
);
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
)
586 if (req
== NULL
|| issuer_name_hash
== NULL
587 || issuer_key_hash
== NULL
|| serial_number
== NULL
)
590 return GNUTLS_E_INVALID_REQUEST
;
593 oid
= _gnutls_x509_digest_to_oid (digest
);
597 return GNUTLS_E_INVALID_REQUEST
;
600 result
= asn1_write_value (req
->req
, "tbsRequest.requestList", "NEW", 1);
601 if (result
!= ASN1_SUCCESS
)
604 return _gnutls_asn2err (result
);
607 result
= asn1_write_value
608 (req
->req
, "tbsRequest.requestList.?LAST.reqCert.hashAlgorithm.algorithm",
610 if (result
!= ASN1_SUCCESS
)
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
)
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
)
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
)
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
)
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",
657 if (result
!= ASN1_SUCCESS
)
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
)
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
)
699 return GNUTLS_E_INVALID_REQUEST
;
702 ret
= _gnutls_x509_der_encode (cert
->cert
,
703 "tbsCertificate.issuer.rdnSequence",
705 if (ret
!= GNUTLS_E_SUCCESS
)
711 ret
= gnutls_fingerprint (digest
, &tmp
, inh_buf
, &inhlen
);
712 gnutls_free (tmp
.data
);
713 if (ret
!= GNUTLS_E_SUCCESS
)
721 ret
= _gnutls_x509_read_string
722 (issuer
->cert
, "tbsCertificate.subjectPublicKeyInfo.subjectPublicKey",
723 &tmp
, RV_BIT_STRING
);
724 if (ret
!= GNUTLS_E_SUCCESS
)
730 ret
= gnutls_fingerprint (digest
, &tmp
, ikh_buf
, &ikhlen
);
731 gnutls_free (tmp
.data
);
732 if (ret
!= GNUTLS_E_SUCCESS
)
740 ret
= _gnutls_x509_read_value (cert
->cert
, "tbsCertificate.serialNumber",
742 if (ret
!= GNUTLS_E_SUCCESS
)
748 ret
= gnutls_ocsp_req_add_cert_id (req
, digest
, &inh
, &ikh
, &sn
);
749 gnutls_free (sn
.data
);
750 if (ret
!= GNUTLS_E_SUCCESS
)
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
783 gnutls_ocsp_req_get_extension (gnutls_ocsp_req_t req
,
786 unsigned int *critical
,
787 gnutls_datum_t
*data
)
790 char str_critical
[10];
791 char name
[ASN1_MAX_NAME_SIZE
];
797 return GNUTLS_E_INVALID_REQUEST
;
800 snprintf (name
, sizeof (name
), "tbsRequest.requestExtensions.?%u.critical",
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
)
809 return _gnutls_asn2err (ret
);
814 if (str_critical
[0] == 'T')
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
)
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
)
841 gnutls_free (oid
->data
);
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
,
866 unsigned int critical
,
867 const gnutls_datum_t
*data
)
869 if (req
== NULL
|| oid
== NULL
|| data
== NULL
)
872 return GNUTLS_E_INVALID_REQUEST
;
875 return set_extension (req
->req
, "tbsRequest.requestExtensions", oid
,
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
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
)
901 if (req
== NULL
|| nonce
== NULL
)
904 return GNUTLS_E_INVALID_REQUEST
;
907 ret
= get_extension (req
->req
, "tbsRequest.requestExtensions",
908 GNUTLS_OCSP_NONCE
, 0,
910 if (ret
!= GNUTLS_E_SUCCESS
)
916 ret
= _gnutls_x509_decode_string (NULL
, tmp
.data
, (size_t) tmp
.size
,
921 gnutls_free (tmp
.data
);
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
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
)
949 gnutls_datum_t dernonce
;
950 unsigned char temp
[SIZEOF_UNSIGNED_LONG_INT
+ 1];
953 if (req
== NULL
|| nonce
== NULL
)
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
)
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
)
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
)
1000 gnutls_datum_t nonce
= { rndbuf
, sizeof (rndbuf
) };
1005 return GNUTLS_E_INVALID_REQUEST
;
1008 ret
= gnutls_rnd (GNUTLS_RND_NONCE
, rndbuf
, sizeof (rndbuf
));
1009 if (ret
!= GNUTLS_E_SUCCESS
)
1015 ret
= gnutls_ocsp_req_set_nonce (req
, 0, &nonce
);
1016 if (ret
!= GNUTLS_E_SUCCESS
)
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
)
1044 return GNUTLS_E_INVALID_REQUEST
;
1048 ret
= asn1_read_value (resp
->resp
, "responseStatus", str
, &len
);
1049 if (ret
!= ASN1_SUCCESS
)
1052 return _gnutls_asn2err (ret
);
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
:
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
)
1101 return GNUTLS_E_INVALID_REQUEST
;
1104 if (response_type_oid
!= NULL
)
1106 ret
= _gnutls_x509_read_value (resp
->resp
, "responseBytes.responseType",
1115 if (response
!= NULL
)
1117 ret
= _gnutls_x509_read_value (resp
->resp
, "responseBytes.response",
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
1140 gnutls_ocsp_resp_get_version (gnutls_ocsp_resp_t resp
)
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 */
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
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
,
1187 if (resp
== NULL
|| dn
== NULL
)
1190 return GNUTLS_E_INVALID_REQUEST
;
1193 ret
= _gnutls_x509_parse_dn
1194 (resp
->basicresp
, "tbsResponseData.responderID.byName",
1196 if (ret
!= GNUTLS_E_SHORT_MEMORY_BUFFER
)
1202 dn
->data
= gnutls_malloc (l
);
1203 if (dn
->data
== NULL
)
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
)
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
1230 * Returns: signing time, or (time_t)-1 on error.
1233 gnutls_ocsp_resp_get_produced (gnutls_ocsp_resp_t resp
)
1235 char ttime
[MAX_TIME
];
1239 if (resp
== NULL
|| resp
->basicresp
== NULL
)
1242 return (time_t) (-1);
1245 len
= sizeof (ttime
) - 1;
1246 ret
= asn1_read_value (resp
->basicresp
, "tbsResponseData.producedAt",
1248 if (ret
!= ASN1_SUCCESS
)
1251 return (time_t) (-1);
1254 c_time
= _gnutls_x509_generalTime2gtime (ttime
);
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
,
1274 gnutls_x509_crt_t crt
)
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
];
1284 ret
= gnutls_ocsp_resp_get_single (resp
, indx
, &digest
, &rdn_hash
, NULL
,
1285 &rserial
, NULL
, NULL
, NULL
, NULL
, NULL
);
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
);
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
);
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
);
1311 ret
= gnutls_x509_crt_get_serial(crt
, cserial
.data
, &t
);
1318 if (rserial
.size
!= cserial
.size
|| memcmp(cserial
.data
, rserial
.data
, rserial
.size
) != 0)
1320 ret
= GNUTLS_E_OCSP_RESPONSE_ERROR
;
1325 ret
= gnutls_x509_crt_get_raw_issuer_dn(crt
, &dn
);
1332 ret
= _gnutls_hash_fast( digest
, dn
.data
, dn
.size
, cdn_hash
);
1339 if (memcmp(cdn_hash
, rdn_hash
.data
, hash_len
) != 0)
1341 ret
= GNUTLS_E_OCSP_RESPONSE_ERROR
;
1349 gnutls_free(rdn_hash
.data
);
1350 gnutls_free(rserial
.data
);
1351 gnutls_free(cserial
.data
);
1352 gnutls_free(dn
.data
);
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
1385 gnutls_ocsp_resp_get_single (gnutls_ocsp_resp_t resp
,
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
)
1398 char name
[ASN1_MAX_NAME_SIZE
];
1401 snprintf (name
, sizeof (name
),
1402 "tbsResponseData.responses.?%u.certID.hashAlgorithm.algorithm",
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
;
1413 ret
= _gnutls_x509_oid_to_digest ((char*)sa
.data
);
1414 _gnutls_free_datum (&sa
);
1424 if (issuer_name_hash
)
1426 snprintf (name
, sizeof (name
),
1427 "tbsResponseData.responses.?%u.certID.issuerNameHash",
1429 ret
= _gnutls_x509_read_value (resp
->basicresp
, name
,
1431 if (ret
!= GNUTLS_E_SUCCESS
)
1438 if (issuer_key_hash
)
1440 snprintf (name
, sizeof (name
),
1441 "tbsResponseData.responses.?%u.certID.issuerKeyHash",
1443 ret
= _gnutls_x509_read_value (resp
->basicresp
, name
,
1445 if (ret
!= GNUTLS_E_SUCCESS
)
1448 if (issuer_name_hash
)
1449 gnutls_free (issuer_name_hash
->data
);
1456 snprintf (name
, sizeof (name
),
1457 "tbsResponseData.responses.?%u.certID.serialNumber",
1459 ret
= _gnutls_x509_read_value (resp
->basicresp
, name
,
1461 if (ret
!= GNUTLS_E_SUCCESS
)
1464 if (issuer_name_hash
)
1465 gnutls_free (issuer_name_hash
->data
);
1466 if (issuer_key_hash
)
1467 gnutls_free (issuer_key_hash
->data
);
1474 snprintf (name
, sizeof (name
),
1475 "tbsResponseData.responses.?%u.certStatus",
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
;
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
;
1494 gnutls_free (sa
.data
);
1495 return GNUTLS_E_ASN1_DER_ERROR
;
1497 gnutls_free (sa
.data
);
1502 char ttime
[MAX_TIME
];
1505 snprintf (name
, sizeof (name
),
1506 "tbsResponseData.responses.?%u.thisUpdate",
1508 len
= sizeof (ttime
) - 1;
1509 ret
= asn1_read_value (resp
->basicresp
, name
, ttime
, &len
);
1510 if (ret
!= ASN1_SUCCESS
)
1513 *this_update
= (time_t) (-1);
1516 *this_update
= _gnutls_x509_generalTime2gtime (ttime
);
1521 char ttime
[MAX_TIME
];
1524 snprintf (name
, sizeof (name
),
1525 "tbsResponseData.responses.?%u.nextUpdate",
1527 len
= sizeof (ttime
) - 1;
1528 ret
= asn1_read_value (resp
->basicresp
, name
, ttime
, &len
);
1529 if (ret
!= ASN1_SUCCESS
)
1532 *next_update
= (time_t) (-1);
1535 *next_update
= _gnutls_x509_generalTime2gtime (ttime
);
1538 if (revocation_time
)
1540 char ttime
[MAX_TIME
];
1543 snprintf (name
, sizeof (name
),
1544 "tbsResponseData.responses.?%u.certStatus."
1545 "revoked.revocationTime",
1547 len
= sizeof (ttime
) - 1;
1548 ret
= asn1_read_value (resp
->basicresp
, name
, ttime
, &len
);
1549 if (ret
!= ASN1_SUCCESS
)
1552 *revocation_time
= (time_t) (-1);
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",
1566 ret
= _gnutls_x509_read_uint (resp
->basicresp
, name
,
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
1599 gnutls_ocsp_resp_get_extension (gnutls_ocsp_resp_t resp
,
1601 gnutls_datum_t
*oid
,
1602 unsigned int *critical
,
1603 gnutls_datum_t
*data
)
1606 char str_critical
[10];
1607 char name
[ASN1_MAX_NAME_SIZE
];
1613 return GNUTLS_E_INVALID_REQUEST
;
1616 snprintf (name
, sizeof (name
),
1617 "tbsResponseData.responseExtensions.?%u.critical",
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
)
1626 return _gnutls_asn2err (ret
);
1631 if (str_critical
[0] == 'T')
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
)
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
)
1658 gnutls_free (oid
->data
);
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
1675 * The caller needs to deallocate memory by calling gnutls_free() on
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
)
1689 ret
= get_extension (resp
->basicresp
, "tbsResponseData.responseExtensions",
1690 GNUTLS_OCSP_NONCE
, 0,
1692 if (ret
!= GNUTLS_E_SUCCESS
)
1698 ret
= _gnutls_x509_decode_string (NULL
, tmp
.data
, (size_t) tmp
.size
,
1703 gnutls_free (tmp
.data
);
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
1724 gnutls_ocsp_resp_get_signature_algorithm (gnutls_ocsp_resp_t resp
)
1729 ret
= _gnutls_x509_read_value (resp
->basicresp
,
1730 "signatureAlgorithm.algorithm", &sa
);
1737 ret
= _gnutls_x509_oid2sign_algorithm ((char*)sa
.data
);
1739 _gnutls_free_datum (&sa
);
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
)
1760 if (resp
== NULL
|| sig
== NULL
)
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
)
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
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
,
1805 gnutls_x509_crt_t
*tmpcerts
= NULL
, *tmpcerts2
;
1806 gnutls_datum_t c
= { NULL
, 0 };
1811 return GNUTLS_E_INVALID_REQUEST
;
1814 tmpcerts
= gnutls_malloc (sizeof (*tmpcerts
));
1815 if (tmpcerts
== NULL
)
1818 return GNUTLS_E_MEMORY_ERROR
;
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
)
1829 if (ret
!= GNUTLS_E_SUCCESS
)
1835 tmpcerts2
= gnutls_realloc (tmpcerts
, (ctr
+ 2) * sizeof (*tmpcerts
));
1836 if (tmpcerts2
== NULL
)
1839 ret
= GNUTLS_E_MEMORY_ERROR
;
1842 tmpcerts
= tmpcerts2
;
1844 ret
= gnutls_x509_crt_init (&tmpcerts
[ctr
]);
1845 if (ret
!= GNUTLS_E_SUCCESS
)
1852 ret
= gnutls_x509_crt_import (tmpcerts
[ctr
- 1], &c
,
1853 GNUTLS_X509_FMT_DER
);
1854 if (ret
!= GNUTLS_E_SUCCESS
)
1860 gnutls_free (c
.data
);
1864 tmpcerts
[ctr
] = NULL
;
1872 /* clean up memory */
1873 ret
= GNUTLS_E_SUCCESS
;
1877 return GNUTLS_E_SUCCESS
;
1880 gnutls_free (c
.data
);
1881 for (i
= 0; i
< ctr
; i
++)
1882 gnutls_x509_crt_deinit (tmpcerts
[i
]);
1883 gnutls_free (tmpcerts
);
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
)
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
)
1905 rc
= gnutls_ocsp_resp_get_certs (resp
, &certs
, &ncerts
);
1906 if (rc
!= GNUTLS_E_SUCCESS
)
1909 gnutls_free (riddn
.data
);
1913 for (i
= 0; i
< ncerts
; i
++)
1916 size_t crtdnsize
= 0;
1919 rc
= gnutls_x509_crt_get_dn (certs
[i
], NULL
, &crtdnsize
);
1920 if (rc
!= GNUTLS_E_SHORT_MEMORY_BUFFER
)
1926 crtdn
= gnutls_malloc (crtdnsize
);
1933 rc
= gnutls_x509_crt_get_dn (certs
[i
], crtdn
, &crtdnsize
);
1934 if (rc
!= GNUTLS_E_SUCCESS
)
1937 gnutls_free (crtdn
);
1941 cmpok
= (crtdnsize
== riddn
.size
)
1942 && memcmp (riddn
.data
, crtdn
, crtdnsize
);
1944 gnutls_free (crtdn
);
1948 signercert
= certs
[i
];
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
);
1966 _ocsp_resp_verify_direct (gnutls_ocsp_resp_t resp
,
1967 gnutls_x509_crt_t signercert
,
1968 unsigned int *verify
,
1971 gnutls_datum_t sig
= { NULL
};
1972 gnutls_datum_t data
= { NULL
};
1973 gnutls_pubkey_t pubkey
= NULL
;
1977 if (resp
== NULL
|| signercert
== NULL
)
1980 return GNUTLS_E_INVALID_REQUEST
;
1983 rc
= gnutls_ocsp_resp_get_signature_algorithm (resp
);
1991 rc
= export (resp
->basicresp
, "tbsResponseData", &data
);
1992 if (rc
!= GNUTLS_E_SUCCESS
)
1998 rc
= gnutls_pubkey_init (&pubkey
);
1999 if (rc
!= GNUTLS_E_SUCCESS
)
2005 rc
= gnutls_pubkey_import_x509 (pubkey
, signercert
, 0);
2006 if (rc
!= GNUTLS_E_SUCCESS
)
2012 rc
= gnutls_ocsp_resp_get_signature (resp
, &sig
);
2013 if (rc
!= GNUTLS_E_SUCCESS
)
2019 rc
= gnutls_pubkey_verify_data2 (pubkey
, sigalg
, 0, &data
, &sig
);
2020 if (rc
== GNUTLS_E_PK_SIG_VERIFY_FAILED
)
2023 *verify
= GNUTLS_OCSP_VERIFY_SIGNATURE_FAILURE
;
2033 rc
= GNUTLS_E_SUCCESS
;
2036 gnutls_free (data
.data
);
2037 gnutls_free (sig
.data
);
2038 gnutls_pubkey_deinit (pubkey
);
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
;
2054 ostatus
= GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER
;
2059 static int check_ocsp_purpose(gnutls_x509_crt_t signercert
)
2061 char oidtmp
[sizeof (GNUTLS_KP_OCSP_SIGNING
)];
2065 for (indx
= 0; ; indx
++)
2067 oidsize
= sizeof (oidtmp
);
2068 rc
= gnutls_x509_crt_get_key_purpose_oid (signercert
, indx
,
2071 if (rc
== GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
)
2076 else if (rc
== GNUTLS_E_SHORT_MEMORY_BUFFER
)
2081 else if (rc
!= GNUTLS_E_SUCCESS
)
2083 return gnutls_assert_val(rc
);
2086 if (memcmp (oidtmp
, GNUTLS_KP_OCSP_SIGNING
, oidsize
) != 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
,
2127 gnutls_x509_crt_t signercert
;
2130 if (resp
== NULL
|| issuer
== NULL
)
2133 return GNUTLS_E_INVALID_REQUEST
;
2136 signercert
= find_signercert (resp
);
2139 signercert
= issuer
;
2141 else /* response contains a signer. Verify him */
2145 rc
= gnutls_x509_crt_verify (signercert
, &issuer
, 1, 0, &vtmp
);
2146 if (rc
!= GNUTLS_E_SUCCESS
)
2154 *verify
= vstatus_to_ocsp_status(vtmp
);
2156 rc
= GNUTLS_E_SUCCESS
;
2160 rc
= check_ocsp_purpose(signercert
);
2164 *verify
= GNUTLS_OCSP_VERIFY_SIGNER_KEYUSAGE_ERROR
;
2165 rc
= GNUTLS_E_SUCCESS
;
2170 rc
= _ocsp_resp_verify_direct(resp
, signercert
, verify
, flags
);
2173 if (signercert
!= issuer
)
2174 gnutls_x509_crt_deinit(signercert
);
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
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
,
2215 gnutls_x509_crt_t signercert
= NULL
;
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
);
2230 /* XXX Search in trustlist for certificate matching
2231 responderId as well? */
2233 *verify
= GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND
;
2234 rc
= GNUTLS_E_SUCCESS
;
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
2241 rc
= _gnutls_trustlist_inlist (trustlist
, signercert
);
2249 /* not in trustlist, need to verify signature and bits */
2250 gnutls_x509_crt_t issuer
;
2255 rc
= gnutls_x509_trust_list_get_issuer (trustlist
, signercert
,
2257 if (rc
!= GNUTLS_E_SUCCESS
)
2260 *verify
= GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER
;
2261 rc
= GNUTLS_E_SUCCESS
;
2265 rc
= gnutls_x509_crt_verify (signercert
, &issuer
, 1, 0, &vtmp
);
2266 if (rc
!= GNUTLS_E_SUCCESS
)
2274 *verify
= vstatus_to_ocsp_status(vtmp
);
2276 rc
= GNUTLS_E_SUCCESS
;
2280 rc
= check_ocsp_purpose(signercert
);
2284 *verify
= GNUTLS_OCSP_VERIFY_SIGNER_KEYUSAGE_ERROR
;
2285 rc
= GNUTLS_E_SUCCESS
;
2290 rc
= _ocsp_resp_verify_direct (resp
, signercert
, verify
, flags
);
2293 gnutls_x509_crt_deinit (signercert
);