summaryrefslogtreecommitdiff
path: root/lib/ui.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ui.c')
-rw-r--r--lib/ui.c914
1 files changed, 914 insertions, 0 deletions
diff --git a/lib/ui.c b/lib/ui.c
new file mode 100644
index 0000000000..7aa9f06af7
--- /dev/null
+++ b/lib/ui.c
@@ -0,0 +1,914 @@
+/*
+ * Copyright (C) 2001-2012 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/* This file contains certificate authentication functions to be exported in the
+ * API which did not fit elsewhere.
+ */
+
+#include "gnutls_int.h"
+#include <auth/srp_kx.h>
+#include <auth/anon.h>
+#include <auth/cert.h>
+#include <auth/psk.h>
+#include "errors.h"
+#include <auth.h>
+#include <state.h>
+#include <datum.h>
+#include <extras/randomart.h>
+#include <read-file.h>
+#include <algorithms.h>
+
+/**
+ * gnutls_random_art:
+ * @type: The type of the random art (for now only %GNUTLS_RANDOM_ART_OPENSSH is supported)
+ * @key_type: The type of the key (RSA, DSA etc.)
+ * @key_size: The size of the key in bits
+ * @fpr: The fingerprint of the key
+ * @fpr_size: The size of the fingerprint
+ * @art: The returned random art
+ *
+ * This function will convert a given fingerprint to an "artistic"
+ * image. The returned image is allocated using gnutls_malloc().
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
+ * an error code is returned.
+ *
+ **/
+int gnutls_random_art(gnutls_random_art_t type,
+ const char *key_type, unsigned int key_size,
+ void *fpr, size_t fpr_size, gnutls_datum_t * art)
+{
+ if (type != GNUTLS_RANDOM_ART_OPENSSH)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+ art->data =
+ (void *) _gnutls_key_fingerprint_randomart(fpr, fpr_size,
+ key_type, key_size,
+ NULL);
+ if (art->data == NULL)
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+ art->size = strlen((char *) art->data);
+
+ return 0;
+}
+
+/* ANON & DHE */
+
+#if defined(ENABLE_DHE) || defined(ENABLE_ANON)
+/**
+ * gnutls_dh_set_prime_bits:
+ * @session: is a #gnutls_session_t type.
+ * @bits: is the number of bits
+ *
+ * This function sets the number of bits, for use in a Diffie-Hellman
+ * key exchange. This is used both in DH ephemeral and DH anonymous
+ * cipher suites. This will set the minimum size of the prime that
+ * will be used for the handshake.
+ *
+ * In the client side it sets the minimum accepted number of bits. If
+ * a server sends a prime with less bits than that
+ * %GNUTLS_E_DH_PRIME_UNACCEPTABLE will be returned by the handshake.
+ *
+ * Note that this function will warn via the audit log for value that
+ * are believed to be weak.
+ *
+ * The function has no effect in server side.
+ *
+ * Note that since 3.1.7 this function is deprecated. The minimum
+ * number of bits is set by the priority string level.
+ * Also this function must be called after gnutls_priority_set_direct()
+ * or the set value may be overridden by the selected priority options.
+ *
+ *
+ **/
+void gnutls_dh_set_prime_bits(gnutls_session_t session, unsigned int bits)
+{
+ if (bits < gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_WEAK)
+ && bits != 0)
+ _gnutls_audit_log(session,
+ "Note that the security level of the Diffie-Hellman key exchange has been lowered to %u bits and this may allow decryption of the session data\n",
+ bits);
+ session->internals.priorities.dh_prime_bits = bits;
+}
+
+
+/**
+ * gnutls_dh_get_group:
+ * @session: is a gnutls session
+ * @raw_gen: will hold the generator.
+ * @raw_prime: will hold the prime.
+ *
+ * This function will return the group parameters used in the last
+ * Diffie-Hellman key exchange with the peer. These are the prime and
+ * the generator used. This function should be used for both
+ * anonymous and ephemeral Diffie-Hellman. The output parameters must
+ * be freed with gnutls_free().
+ *
+ * Note, that the prime and generator are exported as non-negative
+ * integers and may include a leading zero byte.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
+ * an error code is returned.
+ **/
+int
+gnutls_dh_get_group(gnutls_session_t session,
+ gnutls_datum_t * raw_gen, gnutls_datum_t * raw_prime)
+{
+ dh_info_st *dh;
+ int ret;
+ anon_auth_info_t anon_info;
+ cert_auth_info_t cert_info;
+ psk_auth_info_t psk_info;
+
+ switch (gnutls_auth_get_type(session)) {
+ case GNUTLS_CRD_ANON:
+ anon_info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
+ if (anon_info == NULL)
+ return GNUTLS_E_INTERNAL_ERROR;
+ dh = &anon_info->dh;
+ break;
+ case GNUTLS_CRD_PSK:
+ psk_info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
+ if (psk_info == NULL)
+ return GNUTLS_E_INTERNAL_ERROR;
+ dh = &psk_info->dh;
+ break;
+ case GNUTLS_CRD_CERTIFICATE:
+ cert_info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
+ if (cert_info == NULL)
+ return GNUTLS_E_INTERNAL_ERROR;
+ dh = &cert_info->dh;
+ break;
+ default:
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ ret = _gnutls_set_datum(raw_prime, dh->prime.data, dh->prime.size);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ ret =
+ _gnutls_set_datum(raw_gen, dh->generator.data,
+ dh->generator.size);
+ if (ret < 0) {
+ gnutls_assert();
+ _gnutls_free_datum(raw_prime);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * gnutls_dh_get_pubkey:
+ * @session: is a gnutls session
+ * @raw_key: will hold the public key.
+ *
+ * This function will return the peer's public key used in the last
+ * Diffie-Hellman key exchange. This function should be used for both
+ * anonymous and ephemeral Diffie-Hellman. The output parameters must
+ * be freed with gnutls_free().
+ *
+ * Note, that public key is exported as non-negative
+ * integer and may include a leading zero byte.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
+ * an error code is returned.
+ **/
+int
+gnutls_dh_get_pubkey(gnutls_session_t session, gnutls_datum_t * raw_key)
+{
+ dh_info_st *dh;
+ anon_auth_info_t anon_info;
+ cert_auth_info_t cert_info;
+ cert_auth_info_t psk_info;
+
+ switch (gnutls_auth_get_type(session)) {
+ case GNUTLS_CRD_ANON:
+ {
+ anon_info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
+ if (anon_info == NULL)
+ return GNUTLS_E_INTERNAL_ERROR;
+ dh = &anon_info->dh;
+ break;
+ }
+ case GNUTLS_CRD_PSK:
+ {
+ psk_info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
+ if (psk_info == NULL)
+ return GNUTLS_E_INTERNAL_ERROR;
+ dh = &psk_info->dh;
+ break;
+ }
+ case GNUTLS_CRD_CERTIFICATE:
+ {
+
+ cert_info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
+ if (cert_info == NULL)
+ return GNUTLS_E_INTERNAL_ERROR;
+ dh = &cert_info->dh;
+ break;
+ }
+ default:
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ return _gnutls_set_datum(raw_key, dh->public_key.data,
+ dh->public_key.size);
+}
+
+/**
+ * gnutls_dh_get_secret_bits:
+ * @session: is a gnutls session
+ *
+ * This function will return the bits used in the last Diffie-Hellman
+ * key exchange with the peer. Should be used for both anonymous and
+ * ephemeral Diffie-Hellman.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
+ * an error code is returned.
+ **/
+int gnutls_dh_get_secret_bits(gnutls_session_t session)
+{
+ switch (gnutls_auth_get_type(session)) {
+ case GNUTLS_CRD_ANON:
+ {
+ anon_auth_info_t info;
+
+ info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
+ if (info == NULL)
+ return GNUTLS_E_INTERNAL_ERROR;
+ return info->dh.secret_bits;
+ }
+ case GNUTLS_CRD_PSK:
+ {
+ psk_auth_info_t info;
+
+ info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
+ if (info == NULL)
+ return GNUTLS_E_INTERNAL_ERROR;
+ return info->dh.secret_bits;
+ }
+ case GNUTLS_CRD_CERTIFICATE:
+ {
+ cert_auth_info_t info;
+
+ info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
+ if (info == NULL)
+ return GNUTLS_E_INTERNAL_ERROR;
+
+ return info->dh.secret_bits;
+ }
+ default:
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+}
+
+
+static int mpi_buf2bits(gnutls_datum_t * mpi_buf)
+{
+ bigint_t mpi;
+ int rc;
+
+ rc = _gnutls_mpi_init_scan_nz(&mpi, mpi_buf->data, mpi_buf->size);
+ if (rc) {
+ gnutls_assert();
+ return rc;
+ }
+
+ rc = _gnutls_mpi_get_nbits(mpi);
+ _gnutls_mpi_release(&mpi);
+
+ return rc;
+}
+
+/**
+ * gnutls_dh_get_prime_bits:
+ * @session: is a gnutls session
+ *
+ * This function will return the bits of the prime used in the last
+ * Diffie-Hellman key exchange with the peer. Should be used for both
+ * anonymous and ephemeral Diffie-Hellman. Note that some ciphers,
+ * like RSA and DSA without DHE, do not use a Diffie-Hellman key
+ * exchange, and then this function will return 0.
+ *
+ * Returns: The Diffie-Hellman bit strength is returned, or 0 if no
+ * Diffie-Hellman key exchange was done, or a negative error code on
+ * failure.
+ **/
+int gnutls_dh_get_prime_bits(gnutls_session_t session)
+{
+ dh_info_st *dh;
+
+ switch (gnutls_auth_get_type(session)) {
+ case GNUTLS_CRD_ANON:
+ {
+ anon_auth_info_t info;
+
+ info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
+ if (info == NULL)
+ return GNUTLS_E_INTERNAL_ERROR;
+ dh = &info->dh;
+ break;
+ }
+ case GNUTLS_CRD_PSK:
+ {
+ psk_auth_info_t info;
+
+ info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
+ if (info == NULL)
+ return GNUTLS_E_INTERNAL_ERROR;
+ dh = &info->dh;
+ break;
+ }
+ case GNUTLS_CRD_CERTIFICATE:
+ {
+ cert_auth_info_t info;
+
+ info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
+ if (info == NULL)
+ return GNUTLS_E_INTERNAL_ERROR;
+
+ dh = &info->dh;
+ break;
+ }
+ default:
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ if(dh->prime.size == 0)
+ return 0;
+
+ return mpi_buf2bits(&dh->prime);
+}
+
+
+/**
+ * gnutls_dh_get_peers_public_bits:
+ * @session: is a gnutls session
+ *
+ * Get the Diffie-Hellman public key bit size. Can be used for both
+ * anonymous and ephemeral Diffie-Hellman.
+ *
+ * Returns: The public key bit size used in the last Diffie-Hellman
+ * key exchange with the peer, or a negative error code in case of error.
+ **/
+int gnutls_dh_get_peers_public_bits(gnutls_session_t session)
+{
+ dh_info_st *dh;
+
+ switch (gnutls_auth_get_type(session)) {
+ case GNUTLS_CRD_ANON:
+ {
+ anon_auth_info_t info;
+
+ info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
+ if (info == NULL)
+ return GNUTLS_E_INTERNAL_ERROR;
+
+ dh = &info->dh;
+ break;
+ }
+ case GNUTLS_CRD_PSK:
+ {
+ psk_auth_info_t info;
+
+ info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
+ if (info == NULL)
+ return GNUTLS_E_INTERNAL_ERROR;
+
+ dh = &info->dh;
+ break;
+ }
+ case GNUTLS_CRD_CERTIFICATE:
+ {
+ cert_auth_info_t info;
+
+ info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
+ if (info == NULL)
+ return GNUTLS_E_INTERNAL_ERROR;
+
+ dh = &info->dh;
+ break;
+ }
+ default:
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ return mpi_buf2bits(&dh->public_key);
+}
+
+/**
+ * gnutls_certificate_set_dh_params:
+ * @res: is a gnutls_certificate_credentials_t type
+ * @dh_params: the Diffie-Hellman parameters.
+ *
+ * This function will set the Diffie-Hellman parameters for a
+ * certificate server to use. These parameters will be used in
+ * Ephemeral Diffie-Hellman cipher suites. Note that only a pointer
+ * to the parameters are stored in the certificate handle, so you
+ * must not deallocate the parameters before the certificate is deallocated.
+ *
+ **/
+void
+gnutls_certificate_set_dh_params(gnutls_certificate_credentials_t res,
+ gnutls_dh_params_t dh_params)
+{
+ res->dh_params = dh_params;
+}
+
+#endif /* DH */
+
+/* CERTIFICATE STUFF */
+
+/**
+ * gnutls_certificate_get_ours:
+ * @session: is a gnutls session
+ *
+ * Gets the certificate as sent to the peer in the last handshake.
+ * The certificate is in raw (DER) format. No certificate
+ * list is being returned. Only the first certificate.
+ *
+ * Returns: a pointer to a #gnutls_datum_t containing our
+ * certificate, or %NULL in case of an error or if no certificate
+ * was used.
+ **/
+const gnutls_datum_t *gnutls_certificate_get_ours(gnutls_session_t session)
+{
+ gnutls_certificate_credentials_t cred;
+
+ CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, NULL);
+
+ cred = (gnutls_certificate_credentials_t)
+ _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
+ if (cred == NULL) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ if (session->internals.selected_cert_list == NULL)
+ return NULL;
+
+ return &session->internals.selected_cert_list[0].cert;
+}
+
+/**
+ * gnutls_certificate_get_peers:
+ * @session: is a gnutls session
+ * @list_size: is the length of the certificate list (may be %NULL)
+ *
+ * Get the peer's raw certificate (chain) as sent by the peer. These
+ * certificates are in raw format (DER encoded for X.509). In case of
+ * a X.509 then a certificate list may be present. The first
+ * certificate in the list is the peer's certificate, following the
+ * issuer's certificate, then the issuer's issuer etc.
+ *
+ * In case of OpenPGP keys a single key will be returned in raw
+ * format.
+ *
+ * Returns: a pointer to a #gnutls_datum_t containing the peer's
+ * certificates, or %NULL in case of an error or if no certificate
+ * was used.
+ **/
+const gnutls_datum_t *gnutls_certificate_get_peers(gnutls_session_t
+ session,
+ unsigned int *list_size)
+{
+ cert_auth_info_t info;
+
+ CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, NULL);
+
+ info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
+ if (info == NULL)
+ return NULL;
+
+ if (list_size)
+ *list_size = info->ncerts;
+ return info->raw_certificate_list;
+}
+
+#ifdef ENABLE_OPENPGP
+/**
+ * gnutls_certificate_get_peers_subkey_id:
+ * @session: is a gnutls session
+ * @id: will contain the ID
+ *
+ * Get the peer's subkey ID when OpenPGP certificates are
+ * used. The returned @id should be treated as constant.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
+ * an error code is returned.
+ *
+ * Since: 3.1.3
+ **/
+int gnutls_certificate_get_peers_subkey_id(gnutls_session_t session,
+ gnutls_datum_t * id)
+{
+ 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_INVALID_REQUEST;
+
+ id->data = info->subkey_id;
+ id->size = GNUTLS_OPENPGP_KEYID_SIZE;
+
+ return 0;
+}
+#endif
+
+/**
+ * gnutls_certificate_client_get_request_status:
+ * @session: is a gnutls session
+ *
+ * Get whether client certificate is requested or not.
+ *
+ * Returns: 0 if the peer (server) did not request client
+ * authentication or 1 otherwise.
+ **/
+int gnutls_certificate_client_get_request_status(gnutls_session_t session)
+{
+ return session->key.crt_requested;
+}
+
+/**
+ * gnutls_fingerprint:
+ * @algo: is a digest algorithm
+ * @data: is the data
+ * @result: is the place where the result will be copied (may be null).
+ * @result_size: should hold the size of the result. The actual size
+ * of the returned result will also be copied there.
+ *
+ * This function will calculate a fingerprint (actually a hash), of
+ * the given data. The result is not printable data. You should
+ * convert it to hex, or to something else printable.
+ *
+ * This is the usual way to calculate a fingerprint of an X.509 DER
+ * encoded certificate. Note however that the fingerprint of an
+ * OpenPGP certificate is not just a hash and cannot be calculated with this
+ * function.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
+ * an error code is returned.
+ **/
+int
+gnutls_fingerprint(gnutls_digest_algorithm_t algo,
+ const gnutls_datum_t * data, void *result,
+ size_t * result_size)
+{
+ int ret;
+ int hash_len = _gnutls_hash_get_algo_len(hash_to_entry(algo));
+
+ if (hash_len < 0 || (unsigned) hash_len > *result_size
+ || result == NULL) {
+ *result_size = hash_len;
+ return GNUTLS_E_SHORT_MEMORY_BUFFER;
+ }
+ *result_size = hash_len;
+
+ if (result) {
+ ret =
+ _gnutls_hash_fast(algo, data->data, data->size,
+ result);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+ }
+
+ return 0;
+}
+
+/**
+ * gnutls_certificate_set_params_function:
+ * @res: is a gnutls_certificate_credentials_t type
+ * @func: is the function to be called
+ *
+ * This function will set a callback in order for the server to get
+ * the Diffie-Hellman or RSA parameters for certificate
+ * authentication. The callback should return %GNUTLS_E_SUCCESS (0) on success.
+ **/
+void
+gnutls_certificate_set_params_function(gnutls_certificate_credentials_t
+ res, gnutls_params_function * func)
+{
+ res->params_func = func;
+}
+
+/**
+ * gnutls_certificate_set_verify_flags:
+ * @res: is a gnutls_certificate_credentials_t type
+ * @flags: are the flags
+ *
+ * This function will set the flags to be used for verification
+ * of certificates and override any defaults. The provided flags must be an OR of the
+ * #gnutls_certificate_verify_flags enumerations.
+ *
+ **/
+void
+gnutls_certificate_set_verify_flags(gnutls_certificate_credentials_t
+ res, unsigned int flags)
+{
+ res->verify_flags = flags;
+}
+
+/**
+ * gnutls_certificate_get_verify_flags:
+ * @res: is a gnutls_certificate_credentials_t type
+ *
+ * Returns the verification flags set with
+ * gnutls_certificate_set_verify_flags().
+ *
+ * Returns: The certificate verification flags used by @res.
+ *
+ * Since: 3.4.0
+ */
+unsigned int
+gnutls_certificate_get_verify_flags(gnutls_certificate_credentials_t res)
+{
+ return res->verify_flags;
+}
+
+/**
+ * gnutls_certificate_set_verify_limits:
+ * @res: is a gnutls_certificate_credentials type
+ * @max_bits: is the number of bits of an acceptable certificate (default 8200)
+ * @max_depth: is maximum depth of the verification of a certificate chain (default 5)
+ *
+ * This function will set some upper limits for the default
+ * verification function, gnutls_certificate_verify_peers2(), to avoid
+ * denial of service attacks. You can set them to zero to disable
+ * limits.
+ **/
+void
+gnutls_certificate_set_verify_limits(gnutls_certificate_credentials_t res,
+ unsigned int max_bits,
+ unsigned int max_depth)
+{
+ res->verify_depth = max_depth;
+ res->verify_bits = max_bits;
+}
+
+#ifdef ENABLE_PSK
+/**
+ * gnutls_psk_set_params_function:
+ * @res: is a gnutls_psk_server_credentials_t type
+ * @func: is the function to be called
+ *
+ * This function will set a callback in order for the server to get
+ * the Diffie-Hellman or RSA parameters for PSK authentication. The
+ * callback should return %GNUTLS_E_SUCCESS (0) on success.
+ **/
+void
+gnutls_psk_set_params_function(gnutls_psk_server_credentials_t res,
+ gnutls_params_function * func)
+{
+ res->params_func = func;
+}
+#endif
+
+#ifdef ENABLE_ANON
+/**
+ * gnutls_anon_set_params_function:
+ * @res: is a gnutls_anon_server_credentials_t type
+ * @func: is the function to be called
+ *
+ * This function will set a callback in order for the server to get
+ * the Diffie-Hellman or RSA parameters for anonymous authentication.
+ * The callback should return %GNUTLS_E_SUCCESS (0) on success.
+ **/
+void
+gnutls_anon_set_params_function(gnutls_anon_server_credentials_t res,
+ gnutls_params_function * func)
+{
+ res->params_func = func;
+}
+#endif
+
+/**
+ * gnutls_load_file:
+ * @filename: the name of the file to load
+ * @data: Where the file will be stored
+ *
+ * This function will load a file into a datum. The data are
+ * zero terminated but the terminating null is not included in length.
+ * The returned data are allocated using gnutls_malloc().
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
+ * an error code is returned.
+ *
+ * Since 3.1.0
+ **/
+int gnutls_load_file(const char *filename, gnutls_datum_t * data)
+{
+ size_t len;
+
+ data->data = (void *) read_binary_file(filename, &len);
+ if (data->data == NULL)
+ return GNUTLS_E_FILE_ERROR;
+
+ if (malloc != gnutls_malloc) {
+ void *tmp = gnutls_malloc(len);
+
+ memcpy(tmp, data->data, len);
+ free(data->data);
+ data->data = tmp;
+ }
+
+ data->size = len;
+
+ return 0;
+}
+
+#ifdef ENABLE_OCSP
+/**
+ * gnutls_ocsp_status_request_is_checked:
+ * @session: is a gnutls session
+ * @flags: should be zero or %GNUTLS_OCSP_SR_IS_AVAIL
+ *
+ * Check whether an OCSP status response was included in the handshake
+ * and whether it was checked and valid (not too old or superseded).
+ * This is a helper function when needing to decide whether to perform an
+ * OCSP validity check on the peer's certificate. Should be called after
+ * any of gnutls_certificate_verify_peers*() are called.
+ *
+ * If the flag %GNUTLS_OCSP_SR_IS_AVAIL is specified, the return
+ * value of the function indicates whether an OCSP status response have
+ * been received (even if invalid).
+ *
+ * Returns: non zero if the response was valid, or a zero if it wasn't sent,
+ * or sent and was invalid.
+ **/
+int
+gnutls_ocsp_status_request_is_checked(gnutls_session_t session,
+ unsigned int flags)
+{
+ int ret;
+ gnutls_datum_t data;
+
+ if (flags & GNUTLS_OCSP_SR_IS_AVAIL) {
+ ret = gnutls_ocsp_status_request_get(session, &data);
+ if (ret < 0)
+ return gnutls_assert_val(0);
+
+ if (data.data == NULL)
+ return gnutls_assert_val(0);
+ return 1;
+ }
+ return session->internals.ocsp_check_ok;
+}
+#endif
+
+#define DESC_SIZE 64
+
+/**
+ * gnutls_session_get_desc:
+ * @session: is a gnutls session
+ *
+ * This function returns a string describing the current session.
+ * The string is null terminated and allocated using gnutls_malloc().
+ *
+ * If initial negotiation is not complete when this function is called,
+ * %NULL will be returned.
+ *
+ * Returns: a description of the protocols and algorithms in the current session.
+ *
+ * Since: 3.1.10
+ **/
+char *gnutls_session_get_desc(gnutls_session_t session)
+{
+ gnutls_kx_algorithm_t kx;
+ const char *kx_str;
+ unsigned type;
+ char kx_name[32];
+ char proto_name[32];
+ const char *curve_name = NULL;
+ unsigned dh_bits = 0;
+ unsigned mac_id;
+ char *desc;
+
+ if (session->internals.initial_negotiation_completed == 0)
+ return NULL;
+
+ kx = session->security_parameters.kx_algorithm;
+
+ if (kx == GNUTLS_KX_ANON_ECDH || kx == GNUTLS_KX_ECDHE_PSK ||
+ kx == GNUTLS_KX_ECDHE_RSA || kx == GNUTLS_KX_ECDHE_ECDSA) {
+ curve_name =
+ gnutls_ecc_curve_get_name(gnutls_ecc_curve_get
+ (session));
+#if defined(ENABLE_DHE) || defined(ENABLE_ANON)
+ } else if (kx == GNUTLS_KX_ANON_DH || kx == GNUTLS_KX_DHE_PSK
+ || kx == GNUTLS_KX_DHE_RSA || kx == GNUTLS_KX_DHE_DSS) {
+ dh_bits = gnutls_dh_get_prime_bits(session);
+#endif
+ }
+
+ kx_str = gnutls_kx_get_name(kx);
+ if (kx_str) {
+ if (curve_name != NULL)
+ snprintf(kx_name, sizeof(kx_name), "%s-%s",
+ kx_str, curve_name);
+ else if (dh_bits != 0)
+ snprintf(kx_name, sizeof(kx_name), "%s-%u",
+ kx_str, dh_bits);
+ else
+ snprintf(kx_name, sizeof(kx_name), "%s",
+ kx_str);
+ } else {
+ strcpy(kx_name, "NULL");
+ }
+
+ type = gnutls_certificate_type_get(session);
+ if (type == GNUTLS_CRT_X509)
+ snprintf(proto_name, sizeof(proto_name), "%s",
+ gnutls_protocol_get_name(get_num_version
+ (session)));
+ else
+ snprintf(proto_name, sizeof(proto_name), "%s-%s",
+ gnutls_protocol_get_name(get_num_version
+ (session)),
+ gnutls_certificate_type_get_name(type));
+
+ gnutls_protocol_get_name(get_num_version(session)),
+ desc = gnutls_malloc(DESC_SIZE);
+ if (desc == NULL)
+ return NULL;
+
+ mac_id = gnutls_mac_get(session);
+ if (mac_id == GNUTLS_MAC_AEAD) { /* no need to print */
+ snprintf(desc, DESC_SIZE,
+ "(%s)-(%s)-(%s)",
+ proto_name,
+ kx_name,
+ gnutls_cipher_get_name(gnutls_cipher_get(session)));
+ } else {
+ snprintf(desc, DESC_SIZE,
+ "(%s)-(%s)-(%s)-(%s)",
+ proto_name,
+ kx_name,
+ gnutls_cipher_get_name(gnutls_cipher_get(session)),
+ gnutls_mac_get_name(mac_id));
+ }
+
+ return desc;
+}
+
+/**
+ * gnutls_session_set_id:
+ * @session: is a #gnutls_session_t type.
+ * @sid: the session identifier
+ *
+ * This function sets the session ID to be used in a client hello.
+ * This is a function intended for exceptional uses. Do not use this
+ * function unless you are implementing a custom protocol.
+ *
+ * To set session resumption parameters use gnutls_session_set_data() instead.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
+ * an error code is returned.
+ **/
+int
+gnutls_session_set_id(gnutls_session_t session, const gnutls_datum_t * sid)
+{
+ if (session->security_parameters.entity == GNUTLS_SERVER ||
+ sid->size > GNUTLS_MAX_SESSION_ID_SIZE)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+ memset(&session->internals.resumed_security_parameters, 0,
+ sizeof(session->internals.resumed_security_parameters));
+
+ session->internals.resumed_security_parameters.session_id_size =
+ sid->size;
+ memcpy(session->internals.resumed_security_parameters.session_id,
+ sid->data, sid->size);
+
+ return 0;
+}