|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* Copyright (C) 2016 - 2018 ARPA2 project
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Author: Tom Vrancken (dev@tomvrancken.nl)
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This file is part of GnuTLS.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit Service |
4684c1 |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit Service |
4684c1 |
* the License, or (at your option) any later version.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This library is distributed in the hope that it will be useful, but
|
|
Packit Service |
4684c1 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
4684c1 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
4684c1 |
* Lesser General Public License for more details.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* along with this program. If not, see <https://www.gnu.org/licenses/>
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This file is part of the server_certificate_type extension as
|
|
Packit Service |
4684c1 |
* defined in RFC7250 (https://tools.ietf.org/html/rfc7250).
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* The server_certificate_type extension in the client hello indicates
|
|
Packit Service |
4684c1 |
* the types of certificates the client is able to process when provided
|
|
Packit Service |
4684c1 |
* by the server in a subsequent certificate payload.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include <gnutls_int.h>
|
|
Packit Service |
4684c1 |
#include <gnutls/gnutls.h>
|
|
Packit Service |
4684c1 |
#include "ext/cert_types.h"
|
|
Packit Service |
4684c1 |
#include "ext/server_cert_type.h"
|
|
Packit Service |
4684c1 |
#include "hello_ext.h"
|
|
Packit Service |
4684c1 |
#include "hello_ext_lib.h"
|
|
Packit Service |
4684c1 |
#include "errors.h"
|
|
Packit Service |
4684c1 |
#include "state.h"
|
|
Packit Service |
4684c1 |
#include "datum.h"
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int _gnutls_server_cert_type_recv_params(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
const uint8_t* data,
|
|
Packit Service |
4684c1 |
size_t data_size);
|
|
Packit Service |
4684c1 |
static int _gnutls_server_cert_type_send_params(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
gnutls_buffer_st* data);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
const hello_ext_entry_st ext_mod_server_cert_type = {
|
|
Packit Service |
4684c1 |
.name = "Server Certificate Type",
|
|
Packit Service |
4684c1 |
.tls_id = 20,
|
|
Packit Service |
4684c1 |
.gid = GNUTLS_EXTENSION_SERVER_CERT_TYPE,
|
|
Packit Service |
4684c1 |
.client_parse_point = GNUTLS_EXT_TLS,
|
|
Packit Service |
4684c1 |
.server_parse_point = GNUTLS_EXT_TLS,
|
|
Packit Service |
4684c1 |
.validity = GNUTLS_EXT_FLAG_TLS |
|
|
Packit Service |
4684c1 |
GNUTLS_EXT_FLAG_DTLS |
|
|
Packit Service |
4684c1 |
GNUTLS_EXT_FLAG_CLIENT_HELLO |
|
|
Packit Service |
4684c1 |
GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO |
|
|
Packit Service |
4684c1 |
GNUTLS_EXT_FLAG_EE,
|
|
Packit Service |
4684c1 |
.recv_func = _gnutls_server_cert_type_recv_params,
|
|
Packit Service |
4684c1 |
.send_func = _gnutls_server_cert_type_send_params,
|
|
Packit Service |
4684c1 |
.pack_func = _gnutls_hello_ext_default_pack,
|
|
Packit Service |
4684c1 |
.unpack_func = _gnutls_hello_ext_default_unpack,
|
|
Packit Service |
4684c1 |
.deinit_func = _gnutls_hello_ext_default_deinit,
|
|
Packit Service |
4684c1 |
.cannot_be_overriden = 1
|
|
Packit Service |
4684c1 |
};
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int _gnutls_server_cert_type_recv_params(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
const uint8_t* data,
|
|
Packit Service |
4684c1 |
size_t data_size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
gnutls_datum_t cert_types; // Holds the received cert types
|
|
Packit Service |
4684c1 |
gnutls_datum_t sent_cert_types; // Holds the previously sent cert types
|
|
Packit Service |
4684c1 |
gnutls_certificate_type_t cert_type;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
uint8_t i, found = 0;
|
|
Packit Service |
4684c1 |
const uint8_t* pdata = data;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Only activate this extension if we have cert credentials set
|
|
Packit Service |
4684c1 |
* and alternative cert types are allowed */
|
|
Packit Service |
4684c1 |
if (!are_alternative_cert_types_allowed(session) ||
|
|
Packit Service |
4684c1 |
(_gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE) == NULL))
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!IS_SERVER(session)) { // client mode
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Compare packet length with expected packet length. For the
|
|
Packit Service |
4684c1 |
* client this is a single byte. */
|
|
Packit Service |
4684c1 |
if (data_size != 1) {
|
|
Packit Service |
4684c1 |
return
|
|
Packit Service |
4684c1 |
gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* The server picked one of the offered cert types if he supports
|
|
Packit Service |
4684c1 |
* at least one of them. If both parties play by the rules then we
|
|
Packit Service |
4684c1 |
* may only receive a cert type that we offered, i.e. one that we
|
|
Packit Service |
4684c1 |
* support. Because the world isn't as beautiful as it may seem,
|
|
Packit Service |
4684c1 |
* we're going to check it nevertheless. */
|
|
Packit Service |
4684c1 |
cert_type = IANA2cert_type(pdata[0]);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
// Check validity of cert type
|
|
Packit Service |
4684c1 |
if (cert_type == GNUTLS_CRT_UNKNOWN) {
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Get the cert types that we sent to the server (they were stored
|
|
Packit Service |
4684c1 |
* in IANA representation.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
ret = _gnutls_hello_ext_get_datum(session,
|
|
Packit Service |
4684c1 |
GNUTLS_EXTENSION_SERVER_CERT_TYPE,
|
|
Packit Service |
4684c1 |
&sent_cert_types);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
/* This should not happen and indicate a memory corruption!
|
|
Packit Service |
4684c1 |
* Assertion are always on in production code so execution
|
|
Packit Service |
4684c1 |
* will halt here. */
|
|
Packit Service |
4684c1 |
assert(false);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
// Check whether what we got back is actually offered by us
|
|
Packit Service |
4684c1 |
for (i = 0; i < sent_cert_types.size; i++) {
|
|
Packit Service |
4684c1 |
if (IANA2cert_type(sent_cert_types.data[i]) == cert_type)
|
|
Packit Service |
4684c1 |
found = 1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (found) {
|
|
Packit Service |
4684c1 |
// Everything OK, now set the server certificate type
|
|
Packit Service |
4684c1 |
_gnutls_session_server_cert_type_set(session, cert_type);
|
|
Packit Service |
4684c1 |
ret = GNUTLS_E_SUCCESS;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
// No valid cert type found
|
|
Packit Service |
4684c1 |
ret = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
} else { // server mode
|
|
Packit Service |
4684c1 |
// Compare packet length with expected packet length.
|
|
Packit Service |
4684c1 |
DECR_LEN(data_size, 1);
|
|
Packit Service |
4684c1 |
if (data[0] != data_size) {
|
|
Packit Service |
4684c1 |
return
|
|
Packit Service |
4684c1 |
gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
pdata += 1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
// Assign the contents of our data buffer to a gnutls_datum_t
|
|
Packit Service |
4684c1 |
cert_types.data = (uint8_t*)pdata; // Need casting to get rid of 'discards const qualifier' warning
|
|
Packit Service |
4684c1 |
cert_types.size = data_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
// Store the server certificate types in our session
|
|
Packit Service |
4684c1 |
_gnutls_hello_ext_set_datum(session,
|
|
Packit Service |
4684c1 |
GNUTLS_EXTENSION_SERVER_CERT_TYPE,
|
|
Packit Service |
4684c1 |
&cert_types);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* We receive a list of supported certificate types that the client
|
|
Packit Service |
4684c1 |
* is able to process when offered by the server via a subsequent
|
|
Packit Service |
4684c1 |
* Certificate message. This list is sorted by order of preference.
|
|
Packit Service |
4684c1 |
* We now check in this order of preference whether we support any
|
|
Packit Service |
4684c1 |
* of these certificate types.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
for (i = 0; i < cert_types.size; i++) {
|
|
Packit Service |
4684c1 |
// Convert to internal representation
|
|
Packit Service |
4684c1 |
cert_type = IANA2cert_type(cert_types.data[i]);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
// If we have an invalid cert id then continue to the next
|
|
Packit Service |
4684c1 |
if (cert_type == GNUTLS_CRT_UNKNOWN)
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
// Check for support of this cert type
|
|
Packit Service |
4684c1 |
if (_gnutls_session_cert_type_supported
|
|
Packit Service |
4684c1 |
(session, cert_type, true, GNUTLS_CTYPE_SERVER) == 0) {
|
|
Packit Service |
4684c1 |
found = 1;
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
// We found a matching ctype, we pick this one
|
|
Packit Service |
4684c1 |
if (found) {
|
|
Packit Service |
4684c1 |
_gnutls_session_server_cert_type_set(session, cert_type);
|
|
Packit Service |
4684c1 |
ret = GNUTLS_E_SUCCESS;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
/* If no supported certificate type can be found we terminate
|
|
Packit Service |
4684c1 |
* with a fatal alert of type "unsupported_certificate"
|
|
Packit Service |
4684c1 |
* (according to specification rfc7250).
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
ret = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int _gnutls_server_cert_type_send_params(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
gnutls_buffer_st* data)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
uint8_t cert_type; // Holds an IANA cert type ID
|
|
Packit Service |
4684c1 |
uint8_t i = 0, num_cert_types = 0;
|
|
Packit Service |
4684c1 |
priority_st* cert_priorities;
|
|
Packit Service |
4684c1 |
gnutls_datum_t tmp_cert_types; // For type conversion
|
|
Packit Service |
4684c1 |
uint8_t cert_types[GNUTLS_CRT_MAX]; // The list with supported cert types. Inv: 0 <= cert type Id < 256
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Only activate this extension if we have cert credentials set
|
|
Packit Service |
4684c1 |
* and alternative cert types are allowed */
|
|
Packit Service |
4684c1 |
if (!are_alternative_cert_types_allowed(session) ||
|
|
Packit Service |
4684c1 |
(_gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE) == NULL))
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!IS_SERVER(session)) { // Client mode
|
|
Packit Service |
4684c1 |
// For brevity
|
|
Packit Service |
4684c1 |
cert_priorities =
|
|
Packit Service |
4684c1 |
&session->internals.priorities->server_ctype;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Retrieve server certificate type priorities if any. If no
|
|
Packit Service |
4684c1 |
* priorities are set then the default server certificate type
|
|
Packit Service |
4684c1 |
* initialization values apply. This default is currently set to
|
|
Packit Service |
4684c1 |
* X.509 in which case we don't enable this extension.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
if (cert_priorities->num_priorities > 0) { // Priorities are explicitly set
|
|
Packit Service |
4684c1 |
/* If the certificate priority is explicitly set to only
|
|
Packit Service |
4684c1 |
* X.509 (default) then, according to spec we don't send
|
|
Packit Service |
4684c1 |
* this extension. We check this here to avoid further work in
|
|
Packit Service |
4684c1 |
* this routine. We also check it below after pruning supported
|
|
Packit Service |
4684c1 |
* types.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
if (cert_priorities->num_priorities == 1 &&
|
|
Packit Service |
4684c1 |
cert_priorities->priorities[0] == DEFAULT_CERT_TYPE) {
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log
|
|
Packit Service |
4684c1 |
("EXT[%p]: Server certificate type was set to default cert type (%s). "
|
|
Packit Service |
4684c1 |
"We therefore do not send this extension.\n",
|
|
Packit Service |
4684c1 |
session,
|
|
Packit Service |
4684c1 |
gnutls_certificate_type_get_name(DEFAULT_CERT_TYPE));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
// Explicitly set but default ctype, so don't send anything
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* We are only allowed to send certificate types that we support.
|
|
Packit Service |
4684c1 |
* Therefore we check this here and prune our original list.
|
|
Packit Service |
4684c1 |
* This check might seem redundant now because we don't check for
|
|
Packit Service |
4684c1 |
* credentials (they are not needed for a client) and only check the
|
|
Packit Service |
4684c1 |
* priorities over which we already iterate. In the future,
|
|
Packit Service |
4684c1 |
* additional checks might be necessary and they can be easily
|
|
Packit Service |
4684c1 |
* added in the ..type_supported() routine without modifying the
|
|
Packit Service |
4684c1 |
* structure of the code here.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
for (i = 0; i < cert_priorities->num_priorities; i++) {
|
|
Packit Service |
4684c1 |
if (_gnutls_session_cert_type_supported
|
|
Packit Service |
4684c1 |
(session, cert_priorities->priorities[i],
|
|
Packit Service |
4684c1 |
false, GNUTLS_CTYPE_SERVER) == 0) {
|
|
Packit Service |
4684c1 |
/* Check whether we are allowed to store another cert type
|
|
Packit Service |
4684c1 |
* in our buffer. In other words, prevent a possible buffer
|
|
Packit Service |
4684c1 |
* overflow. This situation can occur when a user sets
|
|
Packit Service |
4684c1 |
* duplicate cert types in the priority strings. */
|
|
Packit Service |
4684c1 |
if (num_cert_types >= GNUTLS_CRT_MAX)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
// Convert to IANA representation
|
|
Packit Service |
4684c1 |
ret = cert_type2IANA(cert_priorities->priorities[i]);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cert_type = ret; // For readability
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
// Add this cert type to our list with supported types
|
|
Packit Service |
4684c1 |
cert_types[num_cert_types] = cert_type;
|
|
Packit Service |
4684c1 |
num_cert_types++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log
|
|
Packit Service |
4684c1 |
("EXT[%p]: Server certificate type %s (%d) was queued.\n",
|
|
Packit Service |
4684c1 |
session,
|
|
Packit Service |
4684c1 |
gnutls_certificate_type_get_name(cert_priorities->priorities[i]),
|
|
Packit Service |
4684c1 |
cert_type);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Check whether there are any supported certificate types left
|
|
Packit Service |
4684c1 |
* after the previous pruning step. If not, we do not send this
|
|
Packit Service |
4684c1 |
* extension. Also, if the only supported type is the default type
|
|
Packit Service |
4684c1 |
* we do not send this extension (according to RFC7250).
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
if (num_cert_types == 0) { // For now, this should not occur since we only check priorities while pruning.
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log
|
|
Packit Service |
4684c1 |
("EXT[%p]: Server certificate types were set but none of them is supported. "
|
|
Packit Service |
4684c1 |
"We do not send this extension.\n",
|
|
Packit Service |
4684c1 |
session);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
} else if (num_cert_types == 1 &&
|
|
Packit Service |
4684c1 |
IANA2cert_type(cert_types[0]) == DEFAULT_CERT_TYPE) {
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log
|
|
Packit Service |
4684c1 |
("EXT[%p]: The only supported server certificate type is (%s) which is the default. "
|
|
Packit Service |
4684c1 |
"We therefore do not send this extension.\n",
|
|
Packit Service |
4684c1 |
session,
|
|
Packit Service |
4684c1 |
gnutls_certificate_type_get_name(DEFAULT_CERT_TYPE));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* We have data to send and store a copy internally. We convert
|
|
Packit Service |
4684c1 |
* our list with supported cert types to a datum_t in order to
|
|
Packit Service |
4684c1 |
* be able to make the ..._set_datum call.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
tmp_cert_types.data = cert_types;
|
|
Packit Service |
4684c1 |
tmp_cert_types.size = num_cert_types;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hello_ext_set_datum(session,
|
|
Packit Service |
4684c1 |
GNUTLS_EXTENSION_SERVER_CERT_TYPE,
|
|
Packit Service |
4684c1 |
&tmp_cert_types);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Serialize the certificate types into a sequence of octets
|
|
Packit Service |
4684c1 |
* uint8: length of sequence of cert types (1 octet)
|
|
Packit Service |
4684c1 |
* uint8: cert types (0 <= #octets <= 255)
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
ret = _gnutls_buffer_append_data_prefix(data, 8,
|
|
Packit Service |
4684c1 |
cert_types,
|
|
Packit Service |
4684c1 |
num_cert_types);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
// Check for errors and cleanup in case of error
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
// Number of bytes we are sending
|
|
Packit Service |
4684c1 |
return num_cert_types + 1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
} else { // Server mode
|
|
Packit Service |
4684c1 |
// Retrieve negotiated server certificate type and send it
|
|
Packit Service |
4684c1 |
ret = cert_type2IANA(get_certificate_type(
|
|
Packit Service |
4684c1 |
session, GNUTLS_CTYPE_SERVER));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cert_type = ret; // For readability
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = gnutls_buffer_append_data(data, &cert_type, 1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 1; // sent one byte
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
// In all other cases don't enable this extension
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/** Extension interface **/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* The interface is defined in state.c:
|
|
Packit Service |
4684c1 |
* Public:
|
|
Packit Service |
4684c1 |
* - gnutls_certificate_type_get2
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Private:
|
|
Packit Service |
4684c1 |
* - _gnutls_session_server_cert_type_set
|
|
Packit Service |
4684c1 |
*/
|