|
Packit |
549fdc |
/*
|
|
Packit |
549fdc |
* Copyright (C) 2002-2016 Free Software Foundation, Inc.
|
|
Packit |
549fdc |
* Copyright (C) 2015-2017 Red Hat, Inc.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Author: Nikos Mavrogiannopoulos
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This file is part of GnuTLS.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit |
549fdc |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit |
549fdc |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit |
549fdc |
* the License, or (at your option) any later version.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This library is distributed in the hope that it will be useful, but
|
|
Packit |
549fdc |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
549fdc |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
549fdc |
* Lesser General Public License for more details.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit |
549fdc |
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* This file contains the code the Certificate Type TLS extension.
|
|
Packit |
549fdc |
* This extension is currently gnutls specific.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#include "gnutls_int.h"
|
|
Packit |
549fdc |
#include "errors.h"
|
|
Packit |
549fdc |
#include "num.h"
|
|
Packit |
549fdc |
#include <gnutls/gnutls.h>
|
|
Packit |
549fdc |
#include <ext/signature.h>
|
|
Packit |
549fdc |
#include <state.h>
|
|
Packit |
549fdc |
#include <num.h>
|
|
Packit |
549fdc |
#include <algorithms.h>
|
|
Packit |
549fdc |
#include <abstract_int.h>
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static int _gnutls_signature_algorithm_recv_params(gnutls_session_t
|
|
Packit |
549fdc |
session,
|
|
Packit |
549fdc |
const uint8_t * data,
|
|
Packit |
549fdc |
size_t data_size);
|
|
Packit |
549fdc |
static int _gnutls_signature_algorithm_send_params(gnutls_session_t
|
|
Packit |
549fdc |
session,
|
|
Packit |
549fdc |
gnutls_buffer_st *
|
|
Packit |
549fdc |
extdata);
|
|
Packit |
549fdc |
static void signature_algorithms_deinit_data(gnutls_ext_priv_data_t priv);
|
|
Packit |
549fdc |
static int signature_algorithms_pack(gnutls_ext_priv_data_t epriv,
|
|
Packit |
549fdc |
gnutls_buffer_st * ps);
|
|
Packit |
549fdc |
static int signature_algorithms_unpack(gnutls_buffer_st * ps,
|
|
Packit |
549fdc |
gnutls_ext_priv_data_t * _priv);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
const extension_entry_st ext_mod_sig = {
|
|
Packit |
549fdc |
.name = "Signature Algorithms",
|
|
Packit |
549fdc |
.type = GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
|
|
Packit |
549fdc |
.parse_type = GNUTLS_EXT_TLS,
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
.recv_func = _gnutls_signature_algorithm_recv_params,
|
|
Packit |
549fdc |
.send_func = _gnutls_signature_algorithm_send_params,
|
|
Packit |
549fdc |
.pack_func = signature_algorithms_pack,
|
|
Packit |
549fdc |
.unpack_func = signature_algorithms_unpack,
|
|
Packit |
549fdc |
.deinit_func = signature_algorithms_deinit_data,
|
|
Packit |
549fdc |
.cannot_be_overriden = 1
|
|
Packit |
549fdc |
};
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
typedef struct {
|
|
Packit |
549fdc |
/* TLS 1.2 signature algorithms */
|
|
Packit |
549fdc |
gnutls_sign_algorithm_t sign_algorithms[MAX_ALGOS];
|
|
Packit |
549fdc |
uint16_t sign_algorithms_size;
|
|
Packit |
549fdc |
} sig_ext_st;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* generates a SignatureAndHashAlgorithm structure with length as prefix
|
|
Packit |
549fdc |
* by using the setup priorities.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_sign_algorithm_write_params(gnutls_session_t session,
|
|
Packit |
549fdc |
gnutls_buffer_st * extdata)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
uint8_t *p;
|
|
Packit |
549fdc |
unsigned int len, i;
|
|
Packit |
549fdc |
const sign_algorithm_st *aid;
|
|
Packit |
549fdc |
uint8_t buffer[MAX_ALGOS*2];
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
p = buffer;
|
|
Packit |
549fdc |
len = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (i=0;i<session->internals.priorities->sigalg.size;i++) {
|
|
Packit |
549fdc |
aid = &session->internals.priorities->sigalg.entry[i]->aid;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (HAVE_UNKNOWN_SIGAID(aid))
|
|
Packit |
549fdc |
continue;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_handshake_log
|
|
Packit |
549fdc |
("EXT[%p]: sent signature algo (%d.%d) %s\n", session,
|
|
Packit |
549fdc |
(int)aid->id[0], (int)aid->id[1],
|
|
Packit |
549fdc |
session->internals.priorities->sigalg.entry[i]->name);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
len += 2;
|
|
Packit |
549fdc |
if (unlikely(len >= sizeof(buffer))) {
|
|
Packit |
549fdc |
len -= 2;
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
*p = aid->id[0];
|
|
Packit |
549fdc |
p++;
|
|
Packit |
549fdc |
*p = aid->id[1];
|
|
Packit |
549fdc |
p++;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return _gnutls_buffer_append_data_prefix(extdata, 16, buffer, len);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Parses the Signature Algorithm structure and stores data into
|
|
Packit |
549fdc |
* session->security_parameters.extensions.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_sign_algorithm_parse_data(gnutls_session_t session,
|
|
Packit |
549fdc |
const uint8_t * data, size_t data_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
unsigned int sig, i;
|
|
Packit |
549fdc |
sig_ext_st *priv;
|
|
Packit |
549fdc |
gnutls_ext_priv_data_t epriv;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (data_size == 0 || data_size % 2 != 0)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
priv = gnutls_calloc(1, sizeof(*priv));
|
|
Packit |
549fdc |
if (priv == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (i = 0; i < data_size; i += 2) {
|
|
Packit |
549fdc |
sign_algorithm_st aid;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
aid.id[0] = data[i];
|
|
Packit |
549fdc |
aid.id[1] = data[i + 1];
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
sig = _gnutls_tls_aid_to_sign(&aid);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_handshake_log
|
|
Packit |
549fdc |
("EXT[%p]: rcvd signature algo (%d.%d) %s\n", session,
|
|
Packit |
549fdc |
aid.id[0], aid.id[1],
|
|
Packit |
549fdc |
gnutls_sign_get_name(sig));
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (sig != GNUTLS_SIGN_UNKNOWN) {
|
|
Packit |
549fdc |
if (priv->sign_algorithms_size ==
|
|
Packit |
549fdc |
MAX_ALGOS)
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
priv->sign_algorithms[priv->
|
|
Packit |
549fdc |
sign_algorithms_size++] =
|
|
Packit |
549fdc |
sig;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
epriv = priv;
|
|
Packit |
549fdc |
_gnutls_ext_set_session_data(session,
|
|
Packit |
549fdc |
GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
|
|
Packit |
549fdc |
epriv);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/*
|
|
Packit |
549fdc |
* In case of a server: if a SIGNATURE_ALGORITHMS extension type is
|
|
Packit |
549fdc |
* received then it stores into the session security parameters the
|
|
Packit |
549fdc |
* new value.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* In case of a client: If a signature_algorithms have been specified
|
|
Packit |
549fdc |
* then it is an error;
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
_gnutls_signature_algorithm_recv_params(gnutls_session_t session,
|
|
Packit |
549fdc |
const uint8_t * data,
|
|
Packit |
549fdc |
size_t _data_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
ssize_t data_size = _data_size;
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (session->security_parameters.entity == GNUTLS_CLIENT) {
|
|
Packit |
549fdc |
/* nothing for now */
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
/* Although TLS 1.2 mandates that we must not accept reply
|
|
Packit |
549fdc |
* to this message, there are good reasons to just ignore it. Check
|
|
Packit |
549fdc |
* http://www.ietf.org/mail-archive/web/tls/current/msg03880.html
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
/* return GNUTLS_E_UNEXPECTED_PACKET; */
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
/* SERVER SIDE - we must check if the sent cert type is the right one
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
if (data_size >= 2) {
|
|
Packit |
549fdc |
uint16_t len;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
DECR_LEN(data_size, 2);
|
|
Packit |
549fdc |
len = _gnutls_read_uint16(data);
|
|
Packit |
549fdc |
DECR_LEN(data_size, len);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (data_size > 0)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
_gnutls_sign_algorithm_parse_data(session,
|
|
Packit |
549fdc |
data + 2,
|
|
Packit |
549fdc |
len);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* returns data_size or a negative number on failure
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
_gnutls_signature_algorithm_send_params(gnutls_session_t session,
|
|
Packit |
549fdc |
gnutls_buffer_st * extdata)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
size_t init_length = extdata->length;
|
|
Packit |
549fdc |
const version_entry_st *ver = get_version(session);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (unlikely(ver == NULL))
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* this function sends the client extension data */
|
|
Packit |
549fdc |
if (session->security_parameters.entity == GNUTLS_CLIENT
|
|
Packit |
549fdc |
&& _gnutls_version_has_selectable_sighash(ver)) {
|
|
Packit |
549fdc |
if (session->internals.priorities->sigalg.size > 0) {
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
_gnutls_sign_algorithm_write_params(session, extdata);
|
|
Packit |
549fdc |
if (ret < 0)
|
|
Packit |
549fdc |
return gnutls_assert_val(ret);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return extdata->length - init_length;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* if we are here it means we don't send the extension */
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Returns a requested by the peer signature algorithm that
|
|
Packit |
549fdc |
* matches the given certificate's public key algorithm.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* When the @client_cert flag is not set, then this function will
|
|
Packit |
549fdc |
* also check whether the signature algorithm is allowed to be
|
|
Packit |
549fdc |
* used in that session. Otherwise GNUTLS_SIGN_UNKNOWN is
|
|
Packit |
549fdc |
* returned.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
gnutls_sign_algorithm_t
|
|
Packit |
549fdc |
_gnutls_session_get_sign_algo(gnutls_session_t session,
|
|
Packit |
549fdc |
gnutls_pcert_st * cert,
|
|
Packit |
549fdc |
gnutls_privkey_t privkey,
|
|
Packit |
549fdc |
unsigned client_cert)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
unsigned i;
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
const version_entry_st *ver = get_version(session);
|
|
Packit |
549fdc |
sig_ext_st *priv;
|
|
Packit |
549fdc |
gnutls_ext_priv_data_t epriv;
|
|
Packit |
549fdc |
unsigned int cert_algo;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (unlikely(ver == NULL))
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_SIGN_UNKNOWN);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
cert_algo = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
_gnutls_ext_get_session_data(session,
|
|
Packit |
549fdc |
GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
|
|
Packit |
549fdc |
&epriv);
|
|
Packit |
549fdc |
priv = epriv;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (ret < 0 || !_gnutls_version_has_selectable_sighash(ver)) {
|
|
Packit |
549fdc |
/* none set, allow SHA-1 only */
|
|
Packit |
549fdc |
ret = gnutls_pk_to_sign(cert_algo, GNUTLS_DIG_SHA1);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (!client_cert && _gnutls_session_sign_algo_enabled(session, ret) < 0)
|
|
Packit |
549fdc |
goto fail;
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (i = 0; i < priv->sign_algorithms_size; i++) {
|
|
Packit |
549fdc |
if (_gnutls_privkey_compatible_with_sig(privkey, priv->sign_algorithms[i]) == 0)
|
|
Packit |
549fdc |
continue;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (gnutls_sign_supports_pk_algorithm(priv->sign_algorithms[i], cert_algo) != 0) {
|
|
Packit |
549fdc |
if (_gnutls_pubkey_compatible_with_sig
|
|
Packit |
549fdc |
(session, cert->pubkey, ver,
|
|
Packit |
549fdc |
priv->sign_algorithms[i]) < 0)
|
|
Packit |
549fdc |
continue;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (_gnutls_session_sign_algo_enabled
|
|
Packit |
549fdc |
(session, priv->sign_algorithms[i]) < 0)
|
|
Packit |
549fdc |
continue;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return priv->sign_algorithms[i];
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* When having a legacy client certificate which can only be signed
|
|
Packit |
549fdc |
* using algorithms we don't always enable by default (e.g., DSA-SHA1),
|
|
Packit |
549fdc |
* continue and sign with it. */
|
|
Packit |
549fdc |
if (client_cert) {
|
|
Packit |
549fdc |
_gnutls_audit_log(session, "No shared signature schemes with peer for client certificate (%s). Is the certificate a legacy one?",
|
|
Packit |
549fdc |
gnutls_pk_get_name(cert_algo));
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
fail:
|
|
Packit |
549fdc |
return GNUTLS_SIGN_UNKNOWN;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Check if the given signature algorithm is supported.
|
|
Packit |
549fdc |
* This means that it is enabled by the priority functions,
|
|
Packit |
549fdc |
* and in case of a server a matching certificate exists.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_session_sign_algo_enabled(gnutls_session_t session,
|
|
Packit |
549fdc |
gnutls_sign_algorithm_t sig)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
unsigned i;
|
|
Packit |
549fdc |
const version_entry_st *ver = get_version(session);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (unlikely(ver == NULL))
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (!_gnutls_version_has_selectable_sighash(ver)) {
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (i = 0; i < session->internals.priorities->sigalg.size;
|
|
Packit |
549fdc |
i++) {
|
|
Packit |
549fdc |
if (session->internals.priorities->sigalg.entry[i]->id ==
|
|
Packit |
549fdc |
sig) {
|
|
Packit |
549fdc |
return 0; /* ok */
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static void signature_algorithms_deinit_data(gnutls_ext_priv_data_t priv)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
gnutls_free(priv);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
signature_algorithms_pack(gnutls_ext_priv_data_t epriv,
|
|
Packit |
549fdc |
gnutls_buffer_st * ps)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
sig_ext_st *priv = epriv;
|
|
Packit |
549fdc |
int ret, i;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
BUFFER_APPEND_NUM(ps, priv->sign_algorithms_size);
|
|
Packit |
549fdc |
for (i = 0; i < priv->sign_algorithms_size; i++) {
|
|
Packit |
549fdc |
BUFFER_APPEND_NUM(ps, priv->sign_algorithms[i]);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
signature_algorithms_unpack(gnutls_buffer_st * ps,
|
|
Packit |
549fdc |
gnutls_ext_priv_data_t * _priv)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
sig_ext_st *priv;
|
|
Packit |
549fdc |
int i, ret;
|
|
Packit |
549fdc |
gnutls_ext_priv_data_t epriv;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
priv = gnutls_calloc(1, sizeof(*priv));
|
|
Packit |
549fdc |
if (priv == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
BUFFER_POP_NUM(ps, priv->sign_algorithms_size);
|
|
Packit |
549fdc |
for (i = 0; i < priv->sign_algorithms_size; i++) {
|
|
Packit |
549fdc |
BUFFER_POP_NUM(ps, priv->sign_algorithms[i]);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
epriv = priv;
|
|
Packit |
549fdc |
*_priv = epriv;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
error:
|
|
Packit |
549fdc |
gnutls_free(priv);
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_sign_algorithm_get_requested:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
* @indx: is an index of the signature algorithm to return
|
|
Packit |
549fdc |
* @algo: the returned certificate type will be stored there
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns the signature algorithm specified by index that was
|
|
Packit |
549fdc |
* requested by the peer. If the specified index has no data available
|
|
Packit |
549fdc |
* this function returns %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE. If
|
|
Packit |
549fdc |
* the negotiated TLS version does not support signature algorithms
|
|
Packit |
549fdc |
* then %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned even
|
|
Packit |
549fdc |
* for the first index. The first index is 0.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function is useful in the certificate callback functions
|
|
Packit |
549fdc |
* to assist in selecting the correct certificate.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
|
|
Packit |
549fdc |
* an error code is returned.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 2.10.0
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_sign_algorithm_get_requested(gnutls_session_t session,
|
|
Packit |
549fdc |
size_t indx,
|
|
Packit |
549fdc |
gnutls_sign_algorithm_t * algo)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
const version_entry_st *ver = get_version(session);
|
|
Packit |
549fdc |
sig_ext_st *priv;
|
|
Packit |
549fdc |
gnutls_ext_priv_data_t epriv;
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (unlikely(ver == NULL))
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
_gnutls_ext_get_session_data(session,
|
|
Packit |
549fdc |
GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS,
|
|
Packit |
549fdc |
&epriv);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
priv = epriv;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (!_gnutls_version_has_selectable_sighash(ver)
|
|
Packit |
549fdc |
|| priv->sign_algorithms_size == 0) {
|
|
Packit |
549fdc |
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (indx < priv->sign_algorithms_size) {
|
|
Packit |
549fdc |
*algo = priv->sign_algorithms[indx];
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
} else
|
|
Packit |
549fdc |
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_sign_algorithm_get:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns the signature algorithm that is (or will be) used in this
|
|
Packit |
549fdc |
* session by the server to sign data. This function should be
|
|
Packit |
549fdc |
* used only with TLS 1.2 or later.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: The sign algorithm or %GNUTLS_SIGN_UNKNOWN.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 3.1.1
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int gnutls_sign_algorithm_get(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
return session->security_parameters.server_sign_algo;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_sign_algorithm_get_client:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns the signature algorithm that is (or will be) used in this
|
|
Packit |
549fdc |
* session by the client to sign data. This function should be
|
|
Packit |
549fdc |
* used only with TLS 1.2 or later.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: The sign algorithm or %GNUTLS_SIGN_UNKNOWN.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 3.1.11
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int gnutls_sign_algorithm_get_client(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
return session->security_parameters.client_sign_algo;
|
|
Packit |
549fdc |
}
|