** gnutls-cli: --benchmark-tls was split to --benchmark-tls-kx
and --benchmark-tls-ciphers
+** libgnutls: Added support for an old version of the DTLS protocol
+used by openconnect vpn client for compatibility with Cisco's AnyConnect
+SSL VPN. It is marked as GNUTLS_DTLS0_9. Do not use it for newer protocols
+as it has issues.
+
** libgnutls: requires libnettle 2.5.
** libgnutls: Use the PKCS #1 1.5 encoding provided by nettle (2.5)
gnutls_x509_trust_list_add_trust_file: Added
gnutls_x509_trust_list_add_trust_mem: Added
gnutls_pk_to_sign: Added
+gnutls_session_set_premaster: Added
gnutls_pubkey_verify_hash: Deprecated (use gnutls_pubkey_verify_hash2)
gnutls_pubkey_verify_data: Deprecated (use gnutls_pubkey_verify_data2)
FUNCS += functions/gnutls_session_get_data
FUNCS += functions/gnutls_session_get_data2
FUNCS += functions/gnutls_session_get_random
+FUNCS += functions/gnutls_session_set_premaster
FUNCS += functions/gnutls_session_get_id
FUNCS += functions/gnutls_session_channel_binding
FUNCS += functions/gnutls_session_is_resumed
gnutls_mac_algorithm_t _gnutls_cipher_suite_get_mac_algo (const
uint8_t suite[2]);
+int
+_gnutls_cipher_suite_get_id (gnutls_kx_algorithm_t kx_algorithm,
+ gnutls_cipher_algorithm_t cipher_algorithm,
+ gnutls_mac_algorithm_t mac_algorithm, uint8_t suite[2]);
+
/* Functions for ciphers. */
int _gnutls_cipher_is_block (gnutls_cipher_algorithm_t algorithm);
int _gnutls_cipher_algo_is_aead (gnutls_cipher_algorithm_t algorithm);
return ce->name + sizeof ("GNUTLS_") - 1;
}
+/*-
+ * _gnutls_cipher_suite_get_id:
+ * @kx_algorithm: is a Key exchange algorithm
+ * @cipher_algorithm: is a cipher algorithm
+ * @mac_algorithm: is a MAC algorithm
+ * @suite: The id to be returned
+ *
+ * It fills @suite with the ID of the ciphersuite of the provided parameters.
+ *
+ * Returns: 0 on success or a negative error code otherwise.
+ -*/
+int
+_gnutls_cipher_suite_get_id (gnutls_kx_algorithm_t kx_algorithm,
+ gnutls_cipher_algorithm_t cipher_algorithm,
+ gnutls_mac_algorithm_t mac_algorithm, uint8_t suite[2])
+{
+const gnutls_cipher_suite_entry * ce;
+
+ ce = cipher_suite_get (kx_algorithm, cipher_algorithm, mac_algorithm);
+ if (ce == NULL)
+ return GNUTLS_E_INVALID_REQUEST;
+ else
+ {
+ suite[0] = ce->id[0];
+ suite[1] = ce->id[1];
+ }
+ return 0;
+}
+
/**
* gnutls_cipher_suite_info:
* @idx: index of cipher suite to get information about, starts on 0.
{"TLS1.0", GNUTLS_TLS1, 3, 1, GNUTLS_STREAM, 1},
{"TLS1.1", GNUTLS_TLS1_1, 3, 2, GNUTLS_STREAM, 1},
{"TLS1.2", GNUTLS_TLS1_2, 3, 3, GNUTLS_STREAM, 1},
+ {"DTLS0.9", GNUTLS_DTLS0_9, 1, 0, GNUTLS_DGRAM, 1}, /* Cisco AnyConnect (based on about OpenSSL 0.9.8e) */
{"DTLS1.0", GNUTLS_DTLS1_0, 254, 255, GNUTLS_DGRAM, 1}, /* 1.1 over datagram */
{0, 0, 0, 0, 0}
};
{
switch (version)
{
+ case GNUTLS_DTLS0_9:
case GNUTLS_DTLS1_0:
case GNUTLS_TLS1_1:
case GNUTLS_TLS1_0:
{
switch (version)
{
+ case GNUTLS_DTLS0_9:
case GNUTLS_DTLS1_0:
case GNUTLS_TLS1_1:
case GNUTLS_TLS1_0:
dst->timestamp = src->timestamp; \
dst->max_record_recv_size = src->max_record_recv_size; \
dst->max_record_send_size = src->max_record_send_size; \
- dst->version = src->version
+ dst->version = src->version;
static void
_gnutls_set_resumed_parameters (gnutls_session_t session)
{
int ret;
- if (recv_type == GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST ||
+ if ((gnutls_protocol_get_version (session) != GNUTLS_DTLS0_9 &&
+ recv_type == GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST) ||
recv_type == GNUTLS_HANDSHAKE_HELLO_REQUEST)
return 0;
session->internals.handshake_hash_buffer_prev_len = session->internals.handshake_hash_buffer.length;
- ret = _gnutls_buffer_append_data(&session->internals.handshake_hash_buffer,
- header, header_size);
- if (ret < 0)
- return gnutls_assert_val(ret);
-
+ if (gnutls_protocol_get_version (session) != GNUTLS_DTLS0_9)
+ {
+ ret = _gnutls_buffer_append_data(&session->internals.handshake_hash_buffer,
+ header, header_size);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+ }
if (datalen > 0)
{
ret = _gnutls_buffer_append_data(&session->internals.handshake_hash_buffer,
{
CHECK_SIZE(datalen);
+ if (gnutls_protocol_get_version (session) == GNUTLS_DTLS0_9)
+ {
+ /* Old DTLS doesn't include the header in the MAC */
+ if (datalen <= 12)
+ {
+ gnutls_assert ();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+ dataptr += 12;
+ datalen -= 12;
+ }
+
ret = _gnutls_buffer_append_data(&session->internals.handshake_hash_buffer,
dataptr, datalen);
if (ret < 0)
/* check if the credentials (username, public key etc.) are ok.
* Actually checks if they exist.
*/
- if (_gnutls_get_kx_cred
+ if (!session->internals.premaster_set &&
+ _gnutls_get_kx_cred
(session,
_gnutls_cipher_suite_get_kx_algo
(session->security_parameters.cipher_suite), &err) == NULL
*/
if (!IS_DTLS(session))
_gnutls_record_set_default_version (session, 3, 0);
+ else if (gnutls_protocol_get_version (session) == GNUTLS_DTLS0_9)
+ _gnutls_record_set_default_version (session, 1, 0);
else
_gnutls_record_set_default_version (session, 254, 255);
}
if (bufel == NULL)
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
- _mbuffer_set_uhead_size(bufel, 1);
+ if (gnutls_protocol_get_version (session) == GNUTLS_DTLS0_9)
+ _mbuffer_set_uhead_size(bufel, 3);
+ else
+ _mbuffer_set_uhead_size(bufel, 1);
_mbuffer_set_udata_size(bufel, 0);
data = _mbuffer_get_uhead_ptr (bufel);
data[0] = 1;
+ if (gnutls_protocol_get_version (session) == GNUTLS_DTLS0_9)
+ {
+ _gnutls_write_uint16 (session->internals.dtls.hsk_write_seq, &data[1]);
+ session->internals.dtls.hsk_write_seq++;
+ }
ret = _gnutls_handshake_io_cache_int (session, GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC, bufel);
if (ret < 0)
{
int ret = 0;
uint8_t ch;
-
+ unsigned int ccs_len = 1;
switch (STATE)
{
return gnutls_assert_val(ret);
}
- ret = _gnutls_recv_int (session, GNUTLS_CHANGE_CIPHER_SPEC, -1, &ch, 1, NULL);
+ if (gnutls_protocol_get_version (session) == GNUTLS_DTLS0_9)
+ ccs_len = 3;
+
+ ret = _gnutls_recv_int (session, GNUTLS_CHANGE_CIPHER_SPEC, -1, &ch, ccs_len, NULL);
if (ret <= 0)
{
ERR ("recv ChangeCipherSpec", ret);
return (ret < 0) ? ret : GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
}
+ if (gnutls_protocol_get_version (session) == GNUTLS_DTLS0_9)
+ session->internals.dtls.hsk_read_seq++;
+
/* Initialize the connection session (start encryption) - in case of server */
if (init == TRUE)
{
gnutls_assert ();
return ret;
}
-
+
case STATE31:
STATE = STATE31;
/* if it is defined but had no credentials
*/
- if (_gnutls_get_kx_cred (session, kx, NULL) == NULL)
+ if (!session->internals.premaster_set &&
+ _gnutls_get_kx_cred (session, kx, NULL) == NULL)
{
delete = 1;
}
/* DTLS session state */
dtls_st dtls;
+
+ /* if set it means that the master key was set using
+ * gnutls_session_set_master() rather than being negotiated. */
+ unsigned int premaster_set:1;
unsigned int cb_tls_unique_len;
unsigned char cb_tls_unique[MAX_VERIFY_DATA_SIZE];
#define MASTER_SECRET "master secret"
#define MASTER_SECRET_SIZE (sizeof(MASTER_SECRET)-1)
-static int generate_normal_master (gnutls_session_t session, int);
+static int generate_normal_master (gnutls_session_t session, gnutls_datum_t*, int);
int
_gnutls_generate_master (gnutls_session_t session, int keep_premaster)
{
if (session->internals.resumed == RESUME_FALSE)
- return generate_normal_master (session, keep_premaster);
+ return generate_normal_master (session, &session->key->key, keep_premaster);
+ else if (session->internals.premaster_set)
+ {
+ gnutls_datum_t premaster;
+ premaster.size = sizeof(session->internals.resumed_security_parameters.master_secret);
+ premaster.data = session->internals.resumed_security_parameters.master_secret;
+ return generate_normal_master(session, &premaster, 1);
+ }
return 0;
}
/* here we generate the TLS Master secret.
*/
-#define PREMASTER session->key->key
static int
-generate_normal_master (gnutls_session_t session, int keep_premaster)
+generate_normal_master (gnutls_session_t session, gnutls_datum_t *premaster,
+ int keep_premaster)
{
int ret = 0;
char buf[512];
- _gnutls_hard_log ("INT: PREMASTER SECRET[%d]: %s\n", PREMASTER.size,
- _gnutls_bin2hex (PREMASTER.data, PREMASTER.size, buf,
+ _gnutls_hard_log ("INT: PREMASTER SECRET[%d]: %s\n", premaster->size,
+ _gnutls_bin2hex (premaster->data, premaster->size, buf,
sizeof (buf), NULL));
_gnutls_hard_log ("INT: CLIENT RANDOM[%d]: %s\n", 32,
_gnutls_bin2hex (session->
session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);
ret =
- _gnutls_ssl3_generate_random (PREMASTER.data, PREMASTER.size,
+ _gnutls_ssl3_generate_random (premaster->data, premaster->size,
rnd, 2 * GNUTLS_RANDOM_SIZE,
GNUTLS_MASTER_SIZE,
session->
session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);
ret =
- _gnutls_PRF (session, PREMASTER.data, PREMASTER.size,
+ _gnutls_PRF (session, premaster->data, premaster->size,
MASTER_SECRET, MASTER_SECRET_SIZE,
rnd, 2 * GNUTLS_RANDOM_SIZE, GNUTLS_MASTER_SIZE,
session->security_parameters.master_secret);
}
if (!keep_premaster)
- _gnutls_free_datum (&PREMASTER);
+ _gnutls_free_datum (premaster);
if (ret < 0)
return ret;
#include <gnutls_num.h>
#include <gnutls_extensions.h>
#include <gnutls_constate.h>
+#include <algorithms.h>
static int pack_certificate_auth_info (gnutls_session_t,
gnutls_buffer_st * packed_session);
error:
return ret;
}
+
+/**
+ * gnutls_session_set_premaster:
+ * @session: is a #gnutls_session_t structure.
+ * @entity: GNUTLS_SERVER or GNUTLS_CLIENT
+ * @version: the TLS protocol version
+ * @kx: the key exchange method
+ * @cipher: the cipher
+ * @mac: the MAC algorithm
+ * @comp: the compression method
+ * @master: the master key to use
+ * @session_id: the session identifier
+ *
+ * This function sets the premaster secret in a session. This is
+ * a function intended for exceptional uses. Do not use this
+ * function unless you are implementing a legacy protocol.
+ * 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_premaster (gnutls_session_t session, unsigned int entity,
+ gnutls_protocol_t version,
+ gnutls_kx_algorithm_t kx,
+ gnutls_cipher_algorithm_t cipher,
+ gnutls_mac_algorithm_t mac,
+ gnutls_compression_method_t comp,
+ const gnutls_datum_t* master,
+ const gnutls_datum_t * session_id)
+{
+ int ret;
+
+ memset (&session->internals.resumed_security_parameters, 0,
+ sizeof (session->internals.resumed_security_parameters));
+
+ session->internals.resumed_security_parameters.entity = entity;
+ session->internals.resumed_security_parameters.kx_algorithm = kx;
+
+ ret = _gnutls_cipher_suite_get_id(kx, cipher, mac, session->internals.resumed_security_parameters.cipher_suite);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ session->internals.resumed_security_parameters.compression_method = comp;
+ session->internals.resumed_security_parameters.cert_type = GNUTLS_CRT_UNKNOWN;
+ session->internals.resumed_security_parameters.version = version;
+
+ if (master->size != GNUTLS_MASTER_SIZE)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+ memcpy(session->internals.resumed_security_parameters.master_secret, master->data, master->size);
+
+ if (session_id->size > GNUTLS_MAX_SESSION_ID)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+ session->internals.resumed_security_parameters.session_id_size = session_id->size;
+ memcpy(session->internals.resumed_security_parameters.session_id, session_id->data, session_id->size);
+
+ session->internals.resumed_security_parameters.max_record_send_size =
+ session->internals.resumed_security_parameters.max_record_recv_size = DEFAULT_MAX_RECORD_SIZE;
+
+ session->internals.resumed_security_parameters.timestamp = time(0);
+
+ session->internals.resumed_security_parameters.ecc_curve = GNUTLS_ECC_CURVE_INVALID;
+
+ session->internals.premaster_set = 1;
+
+ return 0;
+}
* @GNUTLS_TLS1_1: TLS version 1.1.
* @GNUTLS_TLS1_2: TLS version 1.2.
* @GNUTLS_DTLS1_0: DTLS version 1.0.
+ * @GNUTLS_DTLS0_9: DTLS version 0.9 (Cisco AnyConnect / OpenSSL 0.9.8e).
* @GNUTLS_VERSION_MAX: Maps to the highest supported TLS version.
* @GNUTLS_VERSION_UNKNOWN: Unknown SSL/TLS version.
*
GNUTLS_TLS1_1 = 3,
GNUTLS_TLS1_2 = 4,
GNUTLS_DTLS1_0 = 5,
- GNUTLS_VERSION_MAX = GNUTLS_DTLS1_0,
+ GNUTLS_DTLS0_9 = 6,
+ GNUTLS_VERSION_MAX = GNUTLS_DTLS0_9,
GNUTLS_VERSION_UNKNOWN = 0xff
} gnutls_protocol_t;
void gnutls_session_get_random (gnutls_session_t session, gnutls_datum_t* client,
gnutls_datum_t* server);
+ int gnutls_session_set_premaster (gnutls_session_t session, unsigned int entity,
+ gnutls_protocol_t version,
+ gnutls_kx_algorithm_t kx,
+ gnutls_cipher_algorithm_t cipher,
+ gnutls_mac_algorithm_t mac,
+ gnutls_compression_method_t comp,
+ const gnutls_datum_t* master,
+ const gnutls_datum_t * session_id);
+
/* returns the session ID */
#define GNUTLS_MAX_SESSION_ID 32
int gnutls_session_get_id (gnutls_session_t session, void *session_id,
gnutls_session_get_random;
gnutls_pubkey_verify_hash2;
gnutls_pk_to_sign;
+ gnutls_certificate_set_x509_system_trust;
} GNUTLS_2_12;
GNUTLS_3_1_0 {
global:
- gnutls_certificate_set_x509_system_trust;
gnutls_pkcs11_obj_list_import_url2;
gnutls_x509_trust_list_add_system_trust;
gnutls_x509_trust_list_add_trust_file;
gnutls_x509_trust_list_add_trust_mem;
gnutls_pkcs12_simple_parse;
+ gnutls_session_set_premaster;
} GNUTLS_3_0_0;
GNUTLS_PRIVATE {