summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2017-10-18 09:08:28 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2017-11-24 11:54:09 +0000
commit24b9b2f2cc871a0ee6061ca802fa885df3f78ece (patch)
treeefa32d0d0dd2381b5692d351b6682c5ec7b89ae4
parent415b7c54fafa3b32fd832018664f40c1c023449b (diff)
downloadgnutls-tmp-draft-ietf-tls-tls13-21-nmav-backports6.tar.gz
x509/cert: reorganized and split credentials and session certificate functionstmp-draft-ietf-tls-tls13-21-nmav-backports6
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
-rw-r--r--lib/Makefile.am4
-rw-r--r--lib/cert-cred-x509.c (renamed from lib/x509.c)357
-rw-r--r--lib/cert-cred.c (renamed from lib/cert.c)303
-rw-r--r--lib/cert-session.c648
4 files changed, 657 insertions, 655 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index b8bc3df4a1..daccefccbd 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -69,11 +69,11 @@ COBJECTS = range.c record.c compress.c debug.c cipher.c handshake-tls13.c \
mbuffers.c buffers.c handshake.c num.c errors.c dh.c kx.c \
priority.c hash_int.c cipher_int.c session.c db.c x509_b64.c \
hello_ext.c auth.c sslv2_compat.c datum.c session_pack.c mpi.c \
- pk.c cert.c global.c constate.c anon_cred.c pkix_asn1_tab.c gnutls_asn1_tab.c \
+ pk.c cert-cred.c global.c constate.c anon_cred.c pkix_asn1_tab.c gnutls_asn1_tab.c \
mem.c fingerprint.c tls-sig.c ecc.c alert.c privkey_raw.c atomic.h \
system/certs.c system/threads.c system/fastopen.c system/sockets.c \
system/inet_ntop.c str-iconv.c system/vasprintf.c vasprintf.h system.c \
- str.c str-unicode.c str-idna.c state.c x509.c file.c supplemental.c \
+ str.c str-unicode.c str-idna.c state.c cert-cred-x509.c file.c supplemental.c \
random.c crypto-api.c crypto-api.h privkey.c pcert.c pubkey.c locks.c dtls.c \
system_override.c crypto-backend.c verify-tofu.c pin.c tpm.c fips.c \
safe-memfuncs.c system/inet_pton.c atfork.c atfork.h randomart.c \
diff --git a/lib/x509.c b/lib/cert-cred-x509.c
index cdca9cf549..e14cdfce28 100644
--- a/lib/x509.c
+++ b/lib/cert-cred-x509.c
@@ -24,7 +24,6 @@
#include "gnutls_int.h"
#include "auth.h"
#include "errors.h"
-#include "hello_ext.h"
#include <auth/cert.h>
#include "dh.h"
#include "num.h"
@@ -40,7 +39,6 @@
#include <debug.h>
#include <x509_b64.h>
#include <x509.h>
-#include <gnutls/ocsp.h>
#include "x509/common.h"
#include "x509/x509_int.h"
#include <str_array.h>
@@ -52,8 +50,8 @@
#include <wincrypt.h>
#endif
-/*
- * some x509 certificate parsing functions.
+/* This file includes functions related to adding certificates and other
+ * related objects in a certificate credentials structure.
*/
static int
@@ -69,357 +67,6 @@ certificate_credential_append_crt_list(gnutls_certificate_credentials_t res,
return 0; \
}
-/* fifteen days */
-#define MAX_OCSP_VALIDITY_SECS (15*60*60*24)
-#ifdef ENABLE_OCSP
-/* If the certificate is revoked status will be GNUTLS_CERT_REVOKED.
- *
- * Returns:
- * Zero on success, a negative error code otherwise.
- */
-static int
-check_ocsp_response(gnutls_session_t session, gnutls_x509_crt_t cert,
- gnutls_x509_trust_list_t tl,
- unsigned verify_flags,
- gnutls_x509_crt_t *cand_issuers, unsigned cand_issuers_size,
- gnutls_datum_t * data, unsigned int *ostatus)
-{
- gnutls_ocsp_resp_t resp;
- int ret;
- unsigned int status, cert_status;
- time_t rtime, vtime, ntime, now;
- int check_failed = 0;
-
- now = gnutls_time(0);
-
- ret = gnutls_ocsp_resp_init(&resp);
- if (ret < 0)
- return gnutls_assert_val(ret);
-
- ret = gnutls_ocsp_resp_import(resp, data);
- if (ret < 0) {
- _gnutls_audit_log(session,
- "There was an error parsing the OCSP response: %s.\n",
- gnutls_strerror(ret));
- ret = gnutls_assert_val(0);
- check_failed = 1;
- *ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
- goto cleanup;
- }
-
- ret = gnutls_ocsp_resp_check_crt(resp, 0, cert);
- if (ret < 0) {
- ret = gnutls_assert_val(0);
- _gnutls_audit_log(session,
- "Got OCSP response with an unrelated certificate.\n");
- check_failed = 1;
- *ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
- goto cleanup;
- }
-
- /* Attempt to verify against our trusted list */
- ret = gnutls_ocsp_resp_verify(resp, tl, &status, verify_flags);
- if ((ret < 0 || status != 0) && cand_issuers_size > 0) {
- /* Attempt to verify against the certificate list provided by the server */
-
- ret = gnutls_ocsp_resp_verify_direct(resp, cand_issuers[0], &status, verify_flags);
- /* if verification fails attempt to find whether any of the other
- * bundled CAs is an issuer of the OCSP response */
- if ((ret < 0 || status != 0) && cand_issuers_size > 1) {
- int ret2;
- unsigned status2, i;
-
- for (i=1;i<cand_issuers_size;i++) {
- ret2 = gnutls_ocsp_resp_verify_direct(resp, cand_issuers[i], &status2, verify_flags);
- if (ret2 >= 0 && status2 == 0) {
- status = status2;
- ret = ret2;
- break;
- }
- }
- }
- }
-
- if (ret < 0) {
- ret = gnutls_assert_val(0);
- gnutls_assert();
- check_failed = 1;
- *ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
- goto cleanup;
- }
-
- /* do not consider revocation data if response was not verified */
- if (status != 0) {
- ret = gnutls_assert_val(0);
- check_failed = 1;
- *ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
- goto cleanup;
- }
-
- ret = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL, NULL,
- &cert_status, &vtime, &ntime,
- &rtime, NULL);
- if (ret < 0) {
- _gnutls_audit_log(session,
- "There was an error parsing the OCSP response: %s.\n",
- gnutls_strerror(ret));
- ret = gnutls_assert_val(0);
- check_failed = 1;
- *ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
- goto cleanup;
- }
-
- if (cert_status == GNUTLS_OCSP_CERT_REVOKED) {
- _gnutls_audit_log(session,
- "The certificate was revoked via OCSP\n");
- check_failed = 1;
- *ostatus |= GNUTLS_CERT_REVOKED;
- ret = gnutls_assert_val(0);
- goto cleanup;
- }
-
- /* Report but do not fail on the following errors. That is
- * because including the OCSP response in the handshake shouldn't
- * cause more problems that not including it.
- */
- if (ntime == -1) {
- if (now - vtime > MAX_OCSP_VALIDITY_SECS) {
- _gnutls_audit_log(session,
- "The OCSP response is old\n");
- check_failed = 1;
- *ostatus |= GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED;
- goto cleanup;
- }
- } else {
- /* there is a newer OCSP answer, don't trust this one */
- if (ntime < now) {
- _gnutls_audit_log(session,
- "There is a newer OCSP response but was not provided by the server\n");
- check_failed = 1;
- *ostatus |= GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED;
- goto cleanup;
- }
- }
-
- ret = 0;
- cleanup:
- if (check_failed == 0)
- session->internals.ocsp_check_ok = 1;
-
- gnutls_ocsp_resp_deinit(resp);
-
- return ret;
-}
-
-#endif
-
-#define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) { \
- if (peer_certificate_list[x]) \
- gnutls_x509_crt_deinit(peer_certificate_list[x]); \
- } \
- gnutls_free( peer_certificate_list)
-
-#ifdef ENABLE_OCSP
-static int
-_gnutls_ocsp_verify_mandatory_stapling(gnutls_session_t session,
- gnutls_x509_crt_t cert,
- unsigned int * ocsp_status)
-{
- gnutls_x509_tlsfeatures_t tlsfeatures;
- int i, ret;
- unsigned feature;
-
- /* RFC 7633: If cert has TLS feature GNUTLS_EXTENSION_STATUS_REQUEST, stapling is mandatory.
- *
- * At this point, we know that we did not get the certificate status.
- *
- * To proceed, first check whether we have requested the certificate status
- */
- if (!_gnutls_hello_ext_is_present(session, GNUTLS_EXTENSION_STATUS_REQUEST)) {
- return 0;
- }
-
- ret = gnutls_x509_tlsfeatures_init(&tlsfeatures);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
-
- /* We have requested the status, now check whether the certificate mandates a response */
- if (gnutls_x509_crt_get_tlsfeatures(cert, tlsfeatures, 0, NULL) == 0) {
- for (i = 0;; ++i) {
- ret = gnutls_x509_tlsfeatures_get(tlsfeatures, i, &feature);
- if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
- break;
- }
-
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
-
- if (feature == 5 /* TLS ID for status request */) {
- /* We sent a status request, the certificate mandates a reply, but we did not get any. */
- *ocsp_status |= GNUTLS_CERT_MISSING_OCSP_STATUS;
- break;
- }
- }
- }
-
- ret = 0;
- cleanup:
- gnutls_x509_tlsfeatures_deinit(tlsfeatures);
- return ret;
-}
-#endif
-
-/*-
- * _gnutls_x509_cert_verify_peers - return the peer's certificate status
- * @session: is a gnutls session
- *
- * This function will try to verify the peer's certificate and return its status (TRUSTED, REVOKED etc.).
- * The return value (status) should be one of the gnutls_certificate_status_t enumerated elements.
- * However you must also check the peer's name in order to check if the verified certificate belongs to the
- * actual peer. Returns a negative error code in case of an error, or GNUTLS_E_NO_CERTIFICATE_FOUND if no certificate was sent.
- -*/
-int
-_gnutls_x509_cert_verify_peers(gnutls_session_t session,
- gnutls_typed_vdata_st * data,
- unsigned int elements,
- unsigned int *status)
-{
- cert_auth_info_t info;
- gnutls_certificate_credentials_t cred;
- gnutls_x509_crt_t *peer_certificate_list;
- gnutls_datum_t resp;
- int peer_certificate_list_size, i, x, ret;
- gnutls_x509_crt_t *cand_issuers;
- unsigned cand_issuers_size;
- unsigned int ocsp_status = 0;
- unsigned int verify_flags;
-
- /* No OCSP check so far */
- session->internals.ocsp_check_ok = 0;
-
- CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST);
-
- info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
- if (info == NULL) {
- gnutls_assert();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- cred = (gnutls_certificate_credentials_t)
- _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
- if (cred == NULL) {
- gnutls_assert();
- return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
- }
-
- if (info->raw_certificate_list == NULL || info->ncerts == 0)
- return GNUTLS_E_NO_CERTIFICATE_FOUND;
-
- if (info->ncerts > cred->verify_depth && cred->verify_depth > 0) {
- gnutls_assert();
- return GNUTLS_E_CONSTRAINT_ERROR;
- }
-
- verify_flags =
- cred->verify_flags | session->internals.additional_verify_flags;
- /* generate a list of gnutls_certs based on the auth info
- * raw certs.
- */
- peer_certificate_list_size = info->ncerts;
- peer_certificate_list =
- gnutls_calloc(peer_certificate_list_size,
- sizeof(gnutls_x509_crt_t));
- if (peer_certificate_list == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- for (i = 0; i < peer_certificate_list_size; i++) {
- ret = gnutls_x509_crt_init(&peer_certificate_list[i]);
- if (ret < 0) {
- gnutls_assert();
- CLEAR_CERTS;
- return ret;
- }
-
- ret =
- gnutls_x509_crt_import(peer_certificate_list[i],
- &info->raw_certificate_list[i],
- GNUTLS_X509_FMT_DER);
- if (ret < 0) {
- gnutls_assert();
- CLEAR_CERTS;
- return ret;
- }
- }
-
- /* Use the OCSP extension if any */
-#ifdef ENABLE_OCSP
- if (verify_flags & GNUTLS_VERIFY_DISABLE_CRL_CHECKS)
- goto skip_ocsp;
-
- for (i=0;i<peer_certificate_list_size;i++) {
- ret = gnutls_ocsp_status_request_get2(session, i, &resp);
- if (ret < 0) {
- ret = _gnutls_ocsp_verify_mandatory_stapling(session, peer_certificate_list[i], &ocsp_status);
- if (ret < 0) {
- gnutls_assert();
- CLEAR_CERTS;
- return ret;
- }
-
- continue;
- }
-
- cand_issuers = NULL;
- cand_issuers_size = 0;
- if (peer_certificate_list_size > i+1) {
- cand_issuers = &peer_certificate_list[i+1];
- cand_issuers_size = peer_certificate_list_size-i-1;
- }
-
- ret =
- check_ocsp_response(session,
- peer_certificate_list[i],
- cred->tlist,
- verify_flags, cand_issuers,
- cand_issuers_size,
- &resp, &ocsp_status);
-
- if (ret < 0) {
- CLEAR_CERTS;
- return gnutls_assert_val(ret);
- }
- }
-#endif
-
- skip_ocsp:
- /* Verify certificate
- */
- ret =
- gnutls_x509_trust_list_verify_crt2(cred->tlist,
- peer_certificate_list,
- peer_certificate_list_size,
- data, elements,
- verify_flags, status, NULL);
-
- if (ret < 0) {
- gnutls_assert();
- CLEAR_CERTS;
- return ret;
- }
-
- CLEAR_CERTS;
-
- *status |= ocsp_status;
-
- return 0;
-}
-
static int str_array_append_idna(gnutls_str_array_t * head, const char *name, size_t size)
{
int ret;
diff --git a/lib/cert.c b/lib/cert-cred.c
index a1529bae69..6c580bdda5 100644
--- a/lib/cert.c
+++ b/lib/cert-cred.c
@@ -21,10 +21,6 @@
*
*/
-/* Some of the stuff needed for Certificate authentication is contained
- * in this file.
- */
-
#include "gnutls_int.h"
#include "errors.h"
#include <auth/cert.h>
@@ -42,6 +38,11 @@
#include "x509/x509_int.h"
#include "dh.h"
+/* This file includes mostly exported API functions related to certificate
+ * credentials structures.
+ */
+
+
/**
* gnutls_certificate_free_keys:
* @sc: is a #gnutls_certificate_credentials_t type.
@@ -239,23 +240,6 @@ gnutls_certificate_allocate_credentials(gnutls_certificate_credentials_t *
return 0;
}
-/**
- * gnutls_certificate_server_set_request:
- * @session: is a #gnutls_session_t type.
- * @req: is one of GNUTLS_CERT_REQUEST, GNUTLS_CERT_REQUIRE
- *
- * This function specifies if we (in case of a server) are going to
- * send a certificate request message to the client. If @req is
- * GNUTLS_CERT_REQUIRE then the server will return the %GNUTLS_E_NO_CERTIFICATE_FOUND
- * error if the peer does not provide a certificate. If you do not call this
- * function then the client will not be asked to send a certificate.
- **/
-void
-gnutls_certificate_server_set_request(gnutls_session_t session,
- gnutls_certificate_request_t req)
-{
- session->internals.send_cert_req = req;
-}
/**
* gnutls_certificate_set_retrieve_function:
@@ -387,283 +371,6 @@ void
cred->verify_callback = func;
}
-/*-
- * _gnutls_x509_extract_certificate_activation_time - return the peer's certificate activation time
- * @cert: should contain an X.509 DER encoded certificate
- *
- * This function will return the certificate's activation time in UNIX time
- * (ie seconds since 00:00:00 UTC January 1, 1970).
- *
- * Returns a (time_t) -1 in case of an error.
- *
- -*/
-static time_t
-_gnutls_x509_get_raw_crt_activation_time(const gnutls_datum_t * cert)
-{
- gnutls_x509_crt_t xcert;
- time_t result;
-
- result = gnutls_x509_crt_init(&xcert);
- if (result < 0)
- return (time_t) - 1;
-
- result = gnutls_x509_crt_import(xcert, cert, GNUTLS_X509_FMT_DER);
- if (result < 0) {
- gnutls_x509_crt_deinit(xcert);
- return (time_t) - 1;
- }
-
- result = gnutls_x509_crt_get_activation_time(xcert);
-
- gnutls_x509_crt_deinit(xcert);
-
- return result;
-}
-
-/*-
- * gnutls_x509_extract_certificate_expiration_time:
- * @cert: should contain an X.509 DER encoded certificate
- *
- * This function will return the certificate's expiration time in UNIX
- * time (ie seconds since 00:00:00 UTC January 1, 1970). Returns a
- *
- * (time_t) -1 in case of an error.
- *
- -*/
-static time_t
-_gnutls_x509_get_raw_crt_expiration_time(const gnutls_datum_t * cert)
-{
- gnutls_x509_crt_t xcert;
- time_t result;
-
- result = gnutls_x509_crt_init(&xcert);
- if (result < 0)
- return (time_t) - 1;
-
- result = gnutls_x509_crt_import(xcert, cert, GNUTLS_X509_FMT_DER);
- if (result < 0) {
- gnutls_x509_crt_deinit(xcert);
- return (time_t) - 1;
- }
-
- result = gnutls_x509_crt_get_expiration_time(xcert);
-
- gnutls_x509_crt_deinit(xcert);
-
- return result;
-}
-
-/**
- * gnutls_certificate_verify_peers2:
- * @session: is a gnutls session
- * @status: is the output of the verification
- *
- * This function will verify the peer's certificate and store
- * the status in the @status variable as a bitwise OR of gnutls_certificate_status_t
- * values or zero if the certificate is trusted. Note that value in @status
- * is set only when the return value of this function is success (i.e, failure
- * to trust a certificate does not imply a negative return value).
- * The default verification flags used by this function can be overridden
- * using gnutls_certificate_set_verify_flags().
- *
- * This function will take into account the OCSP Certificate Status TLS extension,
- * as well as the following X.509 certificate extensions: Name Constraints,
- * Key Usage, and Basic Constraints (pathlen).
- *
- * To avoid denial of service attacks some
- * default upper limits regarding the certificate key size and chain
- * size are set. To override them use gnutls_certificate_set_verify_limits().
- *
- * Note that you must also check the peer's name in order to check if
- * the verified certificate belongs to the actual peer, see gnutls_x509_crt_check_hostname(),
- * or use gnutls_certificate_verify_peers3().
- *
- * Returns: %GNUTLS_E_SUCCESS (0) when the validation is performed, or a negative error code otherwise.
- * A successful error code means that the @status parameter must be checked to obtain the validation status.
- **/
-int
-gnutls_certificate_verify_peers2(gnutls_session_t session,
- unsigned int *status)
-{
- return gnutls_certificate_verify_peers(session, NULL, 0, status);
-}
-
-/**
- * gnutls_certificate_verify_peers3:
- * @session: is a gnutls session
- * @hostname: is the expected name of the peer; may be %NULL
- * @status: is the output of the verification
- *
- * This function will verify the peer's certificate and store the
- * the status in the @status variable as a bitwise OR of gnutls_certificate_status_t
- * values or zero if the certificate is trusted. Note that value in @status
- * is set only when the return value of this function is success (i.e, failure
- * to trust a certificate does not imply a negative return value).
- * The default verification flags used by this function can be overridden
- * using gnutls_certificate_set_verify_flags(). See the documentation
- * of gnutls_certificate_verify_peers2() for details in the verification process.
- *
- * If the @hostname provided is non-NULL then this function will compare
- * the hostname in the certificate against it. The comparison will follow
- * the RFC6125 recommendations. If names do not match the
- * %GNUTLS_CERT_UNEXPECTED_OWNER status flag will be set.
- *
- * In order to verify the purpose of the end-certificate (by checking the extended
- * key usage), use gnutls_certificate_verify_peers().
- *
- * Returns: %GNUTLS_E_SUCCESS (0) when the validation is performed, or a negative error code otherwise.
- * A successful error code means that the @status parameter must be checked to obtain the validation status.
- *
- * Since: 3.1.4
- **/
-int
-gnutls_certificate_verify_peers3(gnutls_session_t session,
- const char *hostname,
- unsigned int *status)
-{
-gnutls_typed_vdata_st data;
-
- data.type = GNUTLS_DT_DNS_HOSTNAME;
- data.size = 0;
- data.data = (void*)hostname;
-
- return gnutls_certificate_verify_peers(session, &data, 1, status);
-}
-
-/**
- * gnutls_certificate_verify_peers:
- * @session: is a gnutls session
- * @data: an array of typed data
- * @elements: the number of data elements
- * @status: is the output of the verification
- *
- * This function will verify the peer's certificate and store the
- * the status in the @status variable as a bitwise OR of gnutls_certificate_status_t
- * values or zero if the certificate is trusted. Note that value in @status
- * is set only when the return value of this function is success (i.e, failure
- * to trust a certificate does not imply a negative return value).
- * The default verification flags used by this function can be overridden
- * using gnutls_certificate_set_verify_flags(). See the documentation
- * of gnutls_certificate_verify_peers2() for details in the verification process.
- *
- * The acceptable @data types are %GNUTLS_DT_DNS_HOSTNAME, %GNUTLS_DT_RFC822NAME and %GNUTLS_DT_KEY_PURPOSE_OID.
- * The former two accept as data a null-terminated hostname or email address, and the latter a null-terminated
- * object identifier (e.g., %GNUTLS_KP_TLS_WWW_SERVER).
- *
- * If a DNS hostname is provided then this function will compare
- * the hostname in the certificate against the given. If names do not match the
- * %GNUTLS_CERT_UNEXPECTED_OWNER status flag will be set.
- * If a key purpose OID is provided and the end-certificate contains the extended key
- * usage PKIX extension, it will be required to be have the provided key purpose
- * or be marked for any purpose, otherwise verification status will have the
- * %GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE flag set.
- *
- * Returns: %GNUTLS_E_SUCCESS (0) when the validation is performed, or a negative error code otherwise.
- * A successful error code means that the @status parameter must be checked to obtain the validation status.
- *
- * Since: 3.3.0
- **/
-int
-gnutls_certificate_verify_peers(gnutls_session_t session,
- gnutls_typed_vdata_st * data,
- unsigned int elements,
- unsigned int *status)
-{
- cert_auth_info_t info;
-
- CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST);
-
- info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
- if (info == NULL) {
- return GNUTLS_E_NO_CERTIFICATE_FOUND;
- }
-
- if (info->raw_certificate_list == NULL || info->ncerts == 0)
- return GNUTLS_E_NO_CERTIFICATE_FOUND;
-
-
- switch (gnutls_certificate_type_get(session)) {
- case GNUTLS_CRT_X509:
- return _gnutls_x509_cert_verify_peers(session, data, elements,
- status);
- default:
- return GNUTLS_E_INVALID_REQUEST;
- }
-}
-
-/**
- * gnutls_certificate_expiration_time_peers:
- * @session: is a gnutls session
- *
- * This function will return the peer's certificate expiration time.
- *
- * Returns: (time_t)-1 on error.
- *
- * Deprecated: gnutls_certificate_verify_peers2() now verifies expiration times.
- **/
-time_t gnutls_certificate_expiration_time_peers(gnutls_session_t session)
-{
- cert_auth_info_t info;
-
- CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST);
-
- info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
- if (info == NULL) {
- return (time_t) - 1;
- }
-
- if (info->raw_certificate_list == NULL || info->ncerts == 0) {
- gnutls_assert();
- return (time_t) - 1;
- }
-
- switch (gnutls_certificate_type_get(session)) {
- case GNUTLS_CRT_X509:
- return
- _gnutls_x509_get_raw_crt_expiration_time(&info->
- raw_certificate_list
- [0]);
- default:
- return (time_t) - 1;
- }
-}
-
-/**
- * gnutls_certificate_activation_time_peers:
- * @session: is a gnutls session
- *
- * This function will return the peer's certificate activation time.
- *
- * Returns: (time_t)-1 on error.
- *
- * Deprecated: gnutls_certificate_verify_peers2() now verifies activation times.
- **/
-time_t gnutls_certificate_activation_time_peers(gnutls_session_t session)
-{
- cert_auth_info_t info;
-
- CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST);
-
- info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
- if (info == NULL) {
- return (time_t) - 1;
- }
-
- if (info->raw_certificate_list == NULL || info->ncerts == 0) {
- gnutls_assert();
- return (time_t) - 1;
- }
-
- switch (gnutls_certificate_type_get(session)) {
- case GNUTLS_CRT_X509:
- return
- _gnutls_x509_get_raw_crt_activation_time(&info->
- raw_certificate_list
- [0]);
- default:
- return (time_t) - 1;
- }
-}
#define TEST_TEXT "test text"
/* returns error if the certificate has different algorithm than
diff --git a/lib/cert-session.c b/lib/cert-session.c
index 1ba55fa448..011ef1e167 100644
--- a/lib/cert-session.c
+++ b/lib/cert-session.c
@@ -35,6 +35,8 @@
#include <state.h>
#include <datum.h>
#include <algorithms.h>
+#include <gnutls/ocsp.h>
+#include "hello_ext.h"
/* CERTIFICATE STUFF */
@@ -215,3 +217,649 @@ gnutls_certificate_set_verify_limits(gnutls_certificate_credentials_t res,
res->verify_bits = max_bits;
}
+/* fifteen days */
+#define MAX_OCSP_VALIDITY_SECS (15*60*60*24)
+#ifdef ENABLE_OCSP
+/* If the certificate is revoked status will be GNUTLS_CERT_REVOKED.
+ *
+ * Returns:
+ * Zero on success, a negative error code otherwise.
+ */
+static int
+check_ocsp_response(gnutls_session_t session, gnutls_x509_crt_t cert,
+ gnutls_x509_trust_list_t tl,
+ unsigned verify_flags,
+ gnutls_x509_crt_t *cand_issuers, unsigned cand_issuers_size,
+ gnutls_datum_t * data, unsigned int *ostatus)
+{
+ gnutls_ocsp_resp_t resp;
+ int ret;
+ unsigned int status, cert_status;
+ time_t rtime, vtime, ntime, now;
+ int check_failed = 0;
+
+ now = gnutls_time(0);
+
+ ret = gnutls_ocsp_resp_init(&resp);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = gnutls_ocsp_resp_import(resp, data);
+ if (ret < 0) {
+ _gnutls_audit_log(session,
+ "There was an error parsing the OCSP response: %s.\n",
+ gnutls_strerror(ret));
+ ret = gnutls_assert_val(0);
+ check_failed = 1;
+ *ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
+ goto cleanup;
+ }
+
+ ret = gnutls_ocsp_resp_check_crt(resp, 0, cert);
+ if (ret < 0) {
+ ret = gnutls_assert_val(0);
+ _gnutls_audit_log(session,
+ "Got OCSP response with an unrelated certificate.\n");
+ check_failed = 1;
+ *ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
+ goto cleanup;
+ }
+
+ /* Attempt to verify against our trusted list */
+ ret = gnutls_ocsp_resp_verify(resp, tl, &status, verify_flags);
+ if ((ret < 0 || status != 0) && cand_issuers_size > 0) {
+ /* Attempt to verify against the certificate list provided by the server */
+
+ ret = gnutls_ocsp_resp_verify_direct(resp, cand_issuers[0], &status, verify_flags);
+ /* if verification fails attempt to find whether any of the other
+ * bundled CAs is an issuer of the OCSP response */
+ if ((ret < 0 || status != 0) && cand_issuers_size > 1) {
+ int ret2;
+ unsigned status2, i;
+
+ for (i=1;i<cand_issuers_size;i++) {
+ ret2 = gnutls_ocsp_resp_verify_direct(resp, cand_issuers[i], &status2, verify_flags);
+ if (ret2 >= 0 && status2 == 0) {
+ status = status2;
+ ret = ret2;
+ break;
+ }
+ }
+ }
+ }
+
+ if (ret < 0) {
+ ret = gnutls_assert_val(0);
+ gnutls_assert();
+ check_failed = 1;
+ *ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
+ goto cleanup;
+ }
+
+ /* do not consider revocation data if response was not verified */
+ if (status != 0) {
+ ret = gnutls_assert_val(0);
+ check_failed = 1;
+ *ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
+ goto cleanup;
+ }
+
+ ret = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL, NULL,
+ &cert_status, &vtime, &ntime,
+ &rtime, NULL);
+ if (ret < 0) {
+ _gnutls_audit_log(session,
+ "There was an error parsing the OCSP response: %s.\n",
+ gnutls_strerror(ret));
+ ret = gnutls_assert_val(0);
+ check_failed = 1;
+ *ostatus |= GNUTLS_CERT_INVALID_OCSP_STATUS;
+ goto cleanup;
+ }
+
+ if (cert_status == GNUTLS_OCSP_CERT_REVOKED) {
+ _gnutls_audit_log(session,
+ "The certificate was revoked via OCSP\n");
+ check_failed = 1;
+ *ostatus |= GNUTLS_CERT_REVOKED;
+ ret = gnutls_assert_val(0);
+ goto cleanup;
+ }
+
+ /* Report but do not fail on the following errors. That is
+ * because including the OCSP response in the handshake shouldn't
+ * cause more problems that not including it.
+ */
+ if (ntime == -1) {
+ if (now - vtime > MAX_OCSP_VALIDITY_SECS) {
+ _gnutls_audit_log(session,
+ "The OCSP response is old\n");
+ check_failed = 1;
+ *ostatus |= GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED;
+ goto cleanup;
+ }
+ } else {
+ /* there is a newer OCSP answer, don't trust this one */
+ if (ntime < now) {
+ _gnutls_audit_log(session,
+ "There is a newer OCSP response but was not provided by the server\n");
+ check_failed = 1;
+ *ostatus |= GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED;
+ goto cleanup;
+ }
+ }
+
+ ret = 0;
+ cleanup:
+ if (check_failed == 0)
+ session->internals.ocsp_check_ok = 1;
+
+ gnutls_ocsp_resp_deinit(resp);
+
+ return ret;
+}
+
+#endif
+
+#define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) { \
+ if (peer_certificate_list[x]) \
+ gnutls_x509_crt_deinit(peer_certificate_list[x]); \
+ } \
+ gnutls_free( peer_certificate_list)
+
+#ifdef ENABLE_OCSP
+static int
+_gnutls_ocsp_verify_mandatory_stapling(gnutls_session_t session,
+ gnutls_x509_crt_t cert,
+ unsigned int * ocsp_status)
+{
+ gnutls_x509_tlsfeatures_t tlsfeatures;
+ int i, ret;
+ unsigned feature;
+
+ /* RFC 7633: If cert has TLS feature GNUTLS_EXTENSION_STATUS_REQUEST, stapling is mandatory.
+ *
+ * At this point, we know that we did not get the certificate status.
+ *
+ * To proceed, first check whether we have requested the certificate status
+ */
+ if (!_gnutls_hello_ext_is_present(session, GNUTLS_EXTENSION_STATUS_REQUEST)) {
+ return 0;
+ }
+
+ ret = gnutls_x509_tlsfeatures_init(&tlsfeatures);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ /* We have requested the status, now check whether the certificate mandates a response */
+ if (gnutls_x509_crt_get_tlsfeatures(cert, tlsfeatures, 0, NULL) == 0) {
+ for (i = 0;; ++i) {
+ ret = gnutls_x509_tlsfeatures_get(tlsfeatures, i, &feature);
+ if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+ break;
+ }
+
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ if (feature == 5 /* TLS ID for status request */) {
+ /* We sent a status request, the certificate mandates a reply, but we did not get any. */
+ *ocsp_status |= GNUTLS_CERT_MISSING_OCSP_STATUS;
+ break;
+ }
+ }
+ }
+
+ ret = 0;
+ cleanup:
+ gnutls_x509_tlsfeatures_deinit(tlsfeatures);
+ return ret;
+}
+#endif
+
+/*-
+ * _gnutls_x509_cert_verify_peers - return the peer's certificate status
+ * @session: is a gnutls session
+ *
+ * This function will try to verify the peer's certificate and return its status (TRUSTED, REVOKED etc.).
+ * The return value (status) should be one of the gnutls_certificate_status_t enumerated elements.
+ * However you must also check the peer's name in order to check if the verified certificate belongs to the
+ * actual peer. Returns a negative error code in case of an error, or GNUTLS_E_NO_CERTIFICATE_FOUND if no certificate was sent.
+ -*/
+static int
+_gnutls_x509_cert_verify_peers(gnutls_session_t session,
+ gnutls_typed_vdata_st * data,
+ unsigned int elements,
+ unsigned int *status)
+{
+ cert_auth_info_t info;
+ gnutls_certificate_credentials_t cred;
+ gnutls_x509_crt_t *peer_certificate_list;
+ gnutls_datum_t resp;
+ int peer_certificate_list_size, i, x, ret;
+ gnutls_x509_crt_t *cand_issuers;
+ unsigned cand_issuers_size;
+ unsigned int ocsp_status = 0;
+ unsigned int verify_flags;
+
+ /* No OCSP check so far */
+ session->internals.ocsp_check_ok = 0;
+
+ CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST);
+
+ info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
+ if (info == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ cred = (gnutls_certificate_credentials_t)
+ _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
+ if (cred == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ if (info->raw_certificate_list == NULL || info->ncerts == 0)
+ return GNUTLS_E_NO_CERTIFICATE_FOUND;
+
+ if (info->ncerts > cred->verify_depth && cred->verify_depth > 0) {
+ gnutls_assert();
+ return GNUTLS_E_CONSTRAINT_ERROR;
+ }
+
+ verify_flags =
+ cred->verify_flags | session->internals.additional_verify_flags;
+ /* generate a list of gnutls_certs based on the auth info
+ * raw certs.
+ */
+ peer_certificate_list_size = info->ncerts;
+ peer_certificate_list =
+ gnutls_calloc(peer_certificate_list_size,
+ sizeof(gnutls_x509_crt_t));
+ if (peer_certificate_list == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ for (i = 0; i < peer_certificate_list_size; i++) {
+ ret = gnutls_x509_crt_init(&peer_certificate_list[i]);
+ if (ret < 0) {
+ gnutls_assert();
+ CLEAR_CERTS;
+ return ret;
+ }
+
+ ret =
+ gnutls_x509_crt_import(peer_certificate_list[i],
+ &info->raw_certificate_list[i],
+ GNUTLS_X509_FMT_DER);
+ if (ret < 0) {
+ gnutls_assert();
+ CLEAR_CERTS;
+ return ret;
+ }
+ }
+
+ /* Use the OCSP extension if any */
+#ifdef ENABLE_OCSP
+ if (verify_flags & GNUTLS_VERIFY_DISABLE_CRL_CHECKS)
+ goto skip_ocsp;
+
+ for (i=0;i<peer_certificate_list_size;i++) {
+ ret = gnutls_ocsp_status_request_get2(session, i, &resp);
+ if (ret < 0) {
+ ret = _gnutls_ocsp_verify_mandatory_stapling(session, peer_certificate_list[i], &ocsp_status);
+ if (ret < 0) {
+ gnutls_assert();
+ CLEAR_CERTS;
+ return ret;
+ }
+
+ continue;
+ }
+
+ cand_issuers = NULL;
+ cand_issuers_size = 0;
+ if (peer_certificate_list_size > i+1) {
+ cand_issuers = &peer_certificate_list[i+1];
+ cand_issuers_size = peer_certificate_list_size-i-1;
+ }
+
+ ret =
+ check_ocsp_response(session,
+ peer_certificate_list[i],
+ cred->tlist,
+ verify_flags, cand_issuers,
+ cand_issuers_size,
+ &resp, &ocsp_status);
+
+ if (ret < 0) {
+ CLEAR_CERTS;
+ return gnutls_assert_val(ret);
+ }
+ }
+#endif
+
+ skip_ocsp:
+ /* Verify certificate
+ */
+ ret =
+ gnutls_x509_trust_list_verify_crt2(cred->tlist,
+ peer_certificate_list,
+ peer_certificate_list_size,
+ data, elements,
+ verify_flags, status, NULL);
+
+ if (ret < 0) {
+ gnutls_assert();
+ CLEAR_CERTS;
+ return ret;
+ }
+
+ CLEAR_CERTS;
+
+ *status |= ocsp_status;
+
+ return 0;
+}
+
+/**
+ * gnutls_certificate_verify_peers2:
+ * @session: is a gnutls session
+ * @status: is the output of the verification
+ *
+ * This function will verify the peer's certificate and store
+ * the status in the @status variable as a bitwise OR of gnutls_certificate_status_t
+ * values or zero if the certificate is trusted. Note that value in @status
+ * is set only when the return value of this function is success (i.e, failure
+ * to trust a certificate does not imply a negative return value).
+ * The default verification flags used by this function can be overridden
+ * using gnutls_certificate_set_verify_flags().
+ *
+ * This function will take into account the OCSP Certificate Status TLS extension,
+ * as well as the following X.509 certificate extensions: Name Constraints,
+ * Key Usage, and Basic Constraints (pathlen).
+ *
+ * To avoid denial of service attacks some
+ * default upper limits regarding the certificate key size and chain
+ * size are set. To override them use gnutls_certificate_set_verify_limits().
+ *
+ * Note that you must also check the peer's name in order to check if
+ * the verified certificate belongs to the actual peer, see gnutls_x509_crt_check_hostname(),
+ * or use gnutls_certificate_verify_peers3().
+ *
+ * Returns: %GNUTLS_E_SUCCESS (0) when the validation is performed, or a negative error code otherwise.
+ * A successful error code means that the @status parameter must be checked to obtain the validation status.
+ **/
+int
+gnutls_certificate_verify_peers2(gnutls_session_t session,
+ unsigned int *status)
+{
+ return gnutls_certificate_verify_peers(session, NULL, 0, status);
+}
+
+/**
+ * gnutls_certificate_verify_peers3:
+ * @session: is a gnutls session
+ * @hostname: is the expected name of the peer; may be %NULL
+ * @status: is the output of the verification
+ *
+ * This function will verify the peer's certificate and store the
+ * the status in the @status variable as a bitwise OR of gnutls_certificate_status_t
+ * values or zero if the certificate is trusted. Note that value in @status
+ * is set only when the return value of this function is success (i.e, failure
+ * to trust a certificate does not imply a negative return value).
+ * The default verification flags used by this function can be overridden
+ * using gnutls_certificate_set_verify_flags(). See the documentation
+ * of gnutls_certificate_verify_peers2() for details in the verification process.
+ *
+ * If the @hostname provided is non-NULL then this function will compare
+ * the hostname in the certificate against it. The comparison will follow
+ * the RFC6125 recommendations. If names do not match the
+ * %GNUTLS_CERT_UNEXPECTED_OWNER status flag will be set.
+ *
+ * In order to verify the purpose of the end-certificate (by checking the extended
+ * key usage), use gnutls_certificate_verify_peers().
+ *
+ * Returns: %GNUTLS_E_SUCCESS (0) when the validation is performed, or a negative error code otherwise.
+ * A successful error code means that the @status parameter must be checked to obtain the validation status.
+ *
+ * Since: 3.1.4
+ **/
+int
+gnutls_certificate_verify_peers3(gnutls_session_t session,
+ const char *hostname,
+ unsigned int *status)
+{
+gnutls_typed_vdata_st data;
+
+ data.type = GNUTLS_DT_DNS_HOSTNAME;
+ data.size = 0;
+ data.data = (void*)hostname;
+
+ return gnutls_certificate_verify_peers(session, &data, 1, status);
+}
+
+/**
+ * gnutls_certificate_verify_peers:
+ * @session: is a gnutls session
+ * @data: an array of typed data
+ * @elements: the number of data elements
+ * @status: is the output of the verification
+ *
+ * This function will verify the peer's certificate and store the
+ * the status in the @status variable as a bitwise OR of gnutls_certificate_status_t
+ * values or zero if the certificate is trusted. Note that value in @status
+ * is set only when the return value of this function is success (i.e, failure
+ * to trust a certificate does not imply a negative return value).
+ * The default verification flags used by this function can be overridden
+ * using gnutls_certificate_set_verify_flags(). See the documentation
+ * of gnutls_certificate_verify_peers2() for details in the verification process.
+ *
+ * The acceptable @data types are %GNUTLS_DT_DNS_HOSTNAME, %GNUTLS_DT_RFC822NAME and %GNUTLS_DT_KEY_PURPOSE_OID.
+ * The former two accept as data a null-terminated hostname or email address, and the latter a null-terminated
+ * object identifier (e.g., %GNUTLS_KP_TLS_WWW_SERVER).
+ *
+ * If a DNS hostname is provided then this function will compare
+ * the hostname in the certificate against the given. If names do not match the
+ * %GNUTLS_CERT_UNEXPECTED_OWNER status flag will be set.
+ * If a key purpose OID is provided and the end-certificate contains the extended key
+ * usage PKIX extension, it will be required to be have the provided key purpose
+ * or be marked for any purpose, otherwise verification status will have the
+ * %GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE flag set.
+ *
+ * Returns: %GNUTLS_E_SUCCESS (0) when the validation is performed, or a negative error code otherwise.
+ * A successful error code means that the @status parameter must be checked to obtain the validation status.
+ *
+ * Since: 3.3.0
+ **/
+int
+gnutls_certificate_verify_peers(gnutls_session_t session,
+ gnutls_typed_vdata_st * data,
+ unsigned int elements,
+ unsigned int *status)
+{
+ cert_auth_info_t info;
+
+ CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST);
+
+ info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
+ if (info == NULL) {
+ return GNUTLS_E_NO_CERTIFICATE_FOUND;
+ }
+
+ if (info->raw_certificate_list == NULL || info->ncerts == 0)
+ return GNUTLS_E_NO_CERTIFICATE_FOUND;
+
+
+ switch (gnutls_certificate_type_get(session)) {
+ case GNUTLS_CRT_X509:
+ return _gnutls_x509_cert_verify_peers(session, data, elements,
+ status);
+ default:
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+}
+
+/*-
+ * gnutls_x509_extract_certificate_expiration_time:
+ * @cert: should contain an X.509 DER encoded certificate
+ *
+ * This function will return the certificate's expiration time in UNIX
+ * time (ie seconds since 00:00:00 UTC January 1, 1970). Returns a
+ *
+ * (time_t) -1 in case of an error.
+ *
+ -*/
+static time_t
+_gnutls_x509_get_raw_crt_expiration_time(const gnutls_datum_t * cert)
+{
+ gnutls_x509_crt_t xcert;
+ time_t result;
+
+ result = gnutls_x509_crt_init(&xcert);
+ if (result < 0)
+ return (time_t) - 1;
+
+ result = gnutls_x509_crt_import(xcert, cert, GNUTLS_X509_FMT_DER);
+ if (result < 0) {
+ gnutls_x509_crt_deinit(xcert);
+ return (time_t) - 1;
+ }
+
+ result = gnutls_x509_crt_get_expiration_time(xcert);
+
+ gnutls_x509_crt_deinit(xcert);
+
+ return result;
+}
+
+/**
+ * gnutls_certificate_expiration_time_peers:
+ * @session: is a gnutls session
+ *
+ * This function will return the peer's certificate expiration time.
+ *
+ * Returns: (time_t)-1 on error.
+ *
+ * Deprecated: gnutls_certificate_verify_peers2() now verifies expiration times.
+ **/
+time_t gnutls_certificate_expiration_time_peers(gnutls_session_t session)
+{
+ cert_auth_info_t info;
+
+ CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST);
+
+ info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
+ if (info == NULL) {
+ return (time_t) - 1;
+ }
+
+ if (info->raw_certificate_list == NULL || info->ncerts == 0) {
+ gnutls_assert();
+ return (time_t) - 1;
+ }
+
+ switch (gnutls_certificate_type_get(session)) {
+ case GNUTLS_CRT_X509:
+ return
+ _gnutls_x509_get_raw_crt_expiration_time(&info->
+ raw_certificate_list
+ [0]);
+ default:
+ return (time_t) - 1;
+ }
+}
+
+/*-
+ * _gnutls_x509_extract_certificate_activation_time - return the peer's certificate activation time
+ * @cert: should contain an X.509 DER encoded certificate
+ *
+ * This function will return the certificate's activation time in UNIX time
+ * (ie seconds since 00:00:00 UTC January 1, 1970).
+ *
+ * Returns a (time_t) -1 in case of an error.
+ *
+ -*/
+static time_t
+_gnutls_x509_get_raw_crt_activation_time(const gnutls_datum_t * cert)
+{
+ gnutls_x509_crt_t xcert;
+ time_t result;
+
+ result = gnutls_x509_crt_init(&xcert);
+ if (result < 0)
+ return (time_t) - 1;
+
+ result = gnutls_x509_crt_import(xcert, cert, GNUTLS_X509_FMT_DER);
+ if (result < 0) {
+ gnutls_x509_crt_deinit(xcert);
+ return (time_t) - 1;
+ }
+
+ result = gnutls_x509_crt_get_activation_time(xcert);
+
+ gnutls_x509_crt_deinit(xcert);
+
+ return result;
+}
+
+/**
+ * gnutls_certificate_activation_time_peers:
+ * @session: is a gnutls session
+ *
+ * This function will return the peer's certificate activation time.
+ *
+ * Returns: (time_t)-1 on error.
+ *
+ * Deprecated: gnutls_certificate_verify_peers2() now verifies activation times.
+ **/
+time_t gnutls_certificate_activation_time_peers(gnutls_session_t session)
+{
+ cert_auth_info_t info;
+
+ CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST);
+
+ info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
+ if (info == NULL) {
+ return (time_t) - 1;
+ }
+
+ if (info->raw_certificate_list == NULL || info->ncerts == 0) {
+ gnutls_assert();
+ return (time_t) - 1;
+ }
+
+ switch (gnutls_certificate_type_get(session)) {
+ case GNUTLS_CRT_X509:
+ return
+ _gnutls_x509_get_raw_crt_activation_time(&info->
+ raw_certificate_list
+ [0]);
+ default:
+ return (time_t) - 1;
+ }
+}
+
+/**
+ * gnutls_certificate_server_set_request:
+ * @session: is a #gnutls_session_t type.
+ * @req: is one of GNUTLS_CERT_REQUEST, GNUTLS_CERT_REQUIRE
+ *
+ * This function specifies if we (in case of a server) are going to
+ * send a certificate request message to the client. If @req is
+ * GNUTLS_CERT_REQUIRE then the server will return the %GNUTLS_E_NO_CERTIFICATE_FOUND
+ * error if the peer does not provide a certificate. If you do not call this
+ * function then the client will not be asked to send a certificate.
+ **/
+void
+gnutls_certificate_server_set_request(gnutls_session_t session,
+ gnutls_certificate_request_t req)
+{
+ session->internals.send_cert_req = req;
+}