Ejemplo n.º 1
0
/* This is called when we want send our certificate
 */
int _gnutls_send_client_certificate(gnutls_session_t session, int again)
{
	gnutls_buffer_st data;
	int ret = 0;


	if (session->internals.crt_requested == 0)
		return 0;

	if (session->internals.auth_struct->
	    gnutls_generate_client_certificate == NULL)
		return 0;

	_gnutls_buffer_init(&data);

	if (again == 0) {
#ifdef ENABLE_SSL3
		if (get_num_version(session) != GNUTLS_SSL3 ||
		    session->internals.selected_cert_list_length > 0)
#endif
		{
			/* TLS 1.x or SSL 3.0 with a valid certificate 
			 */
			ret =
			    session->internals.auth_struct->
			    gnutls_generate_client_certificate(session,
							       &data);

			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}
		}
	}

#ifdef ENABLE_SSL3
	/* In the SSL 3.0 protocol we need to send a
	 * no certificate alert instead of an
	 * empty certificate.
	 */
	if (get_num_version(session) == GNUTLS_SSL3 &&
	    session->internals.selected_cert_list_length == 0) {
		ret =
		    gnutls_alert_send(session, GNUTLS_AL_WARNING,
				      GNUTLS_A_SSL3_NO_CERTIFICATE);

	} else		/* TLS 1.0 or SSL 3.0 with a valid certificate 
			 */
#endif
		ret = send_handshake(session, data.data, data.length,
				     GNUTLS_HANDSHAKE_CERTIFICATE_PKT);

      cleanup:
	_gnutls_buffer_clear(&data);
	return ret;
}
Ejemplo n.º 2
0
/* return RSA(random) using the peers public key 
 */
int
_gnutls_gen_rsa_client_kx(gnutls_session_t session,
			  gnutls_buffer_st * data)
{
	cert_auth_info_t auth = session->key.auth_info;
	gnutls_datum_t sdata;	/* data to send */
	gnutls_pk_params_st params;
	int ret;

	if (auth == NULL) {
		/* this shouldn't have happened. The proc_certificate
		 * function should have detected that.
		 */
		gnutls_assert();
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
	}

	session->key.key.size = GNUTLS_MASTER_SIZE;
	session->key.key.data = gnutls_malloc(session->key.key.size);

	if (session->key.key.data == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	ret = _gnutls_rnd(GNUTLS_RND_RANDOM, session->key.key.data,
			  session->key.key.size);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	if (session->internals.rsa_pms_version[0] == 0) {
		session->key.key.data[0] =
		    _gnutls_get_adv_version_major(session);
		session->key.key.data[1] =
		    _gnutls_get_adv_version_minor(session);
	} else {		/* use the version provided */
		session->key.key.data[0] =
		    session->internals.rsa_pms_version[0];
		session->key.key.data[1] =
		    session->internals.rsa_pms_version[1];
	}

	/* move RSA parameters to key (session).
	 */
	if ((ret = _gnutls_get_public_rsa_params(session, &params)) < 0) {
		gnutls_assert();
		return ret;
	}

	ret =
	    _gnutls_pk_encrypt(GNUTLS_PK_RSA, &sdata, &session->key.key,
			       &params);

	gnutls_pk_params_release(&params);

	if (ret < 0)
		return gnutls_assert_val(ret);


	if (get_num_version(session) == GNUTLS_SSL3) {
		/* SSL 3.0 */
		_gnutls_buffer_replace_data(data, &sdata);

		return data->length;
	} else {		/* TLS 1 */
		ret =
		    _gnutls_buffer_append_data_prefix(data, 16, sdata.data,
						      sdata.size);

		_gnutls_free_datum(&sdata);
		return ret;
	}

}
Ejemplo n.º 3
0
static int
proc_rsa_client_kx(gnutls_session_t session, uint8_t * data,
		   size_t _data_size)
{
	gnutls_datum_t plaintext;
	gnutls_datum_t ciphertext;
	int ret, dsize;
	int use_rnd_key = 0;
	ssize_t data_size = _data_size;
	gnutls_datum_t rndkey = {NULL, 0};

	if (get_num_version(session) == GNUTLS_SSL3) {
		/* SSL 3.0 
		 */
		ciphertext.data = data;
		ciphertext.size = data_size;
	} else {
		/* TLS 1.0
		 */
		DECR_LEN(data_size, 2);
		ciphertext.data = &data[2];
		dsize = _gnutls_read_uint16(data);

		if (dsize != data_size) {
			gnutls_assert();
			return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
		}
		ciphertext.size = dsize;
	}

	rndkey.size = GNUTLS_MASTER_SIZE;
	rndkey.data = gnutls_malloc(rndkey.size);
	if (rndkey.data == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	/* we do not need strong random numbers here.
	 */
	ret = _gnutls_rnd(GNUTLS_RND_NONCE, rndkey.data,
			  rndkey.size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret =
	    gnutls_privkey_decrypt_data(session->internals.selected_key, 0,
					&ciphertext, &plaintext);

	if (ret < 0 || plaintext.size != GNUTLS_MASTER_SIZE) {
		/* In case decryption fails then don't inform
		 * the peer. Just use a random key. (in order to avoid
		 * attack against pkcs-1 formating).
		 */
		_gnutls_debug_log("auth_rsa: Possible PKCS #1 format attack\n");
		use_rnd_key = 1;
	} else {
		/* If the secret was properly formatted, then
		 * check the version number.
		 */
		if (_gnutls_get_adv_version_major(session) !=
		    plaintext.data[0]
		    || (session->internals.priorities.allow_wrong_pms == 0
			&& _gnutls_get_adv_version_minor(session) !=
			plaintext.data[1])) {
			/* No error is returned here, if the version number check
			 * fails. We proceed normally.
			 * That is to defend against the attack described in the paper
			 * "Attacking RSA-based sessions in SSL/TLS" by Vlastimil Klima,
			 * Ondej Pokorny and Tomas Rosa.
			 */
			_gnutls_debug_log("auth_rsa: Possible PKCS #1 version check format attack\n");
		}
	}

	if (use_rnd_key != 0) {
		session->key.key.data = rndkey.data;
		session->key.key.size = rndkey.size;
		rndkey.data = NULL;
	} else {
		session->key.key.data = plaintext.data;
		session->key.key.size = plaintext.size;
	}

	/* This is here to avoid the version check attack
	 * discussed above.
	 */
	session->key.key.data[0] = _gnutls_get_adv_version_major(session);
	session->key.key.data[1] = _gnutls_get_adv_version_minor(session);

	ret = 0;
 cleanup:
	gnutls_free(rndkey.data);
	return ret;
}
Ejemplo n.º 4
0
/**
 * 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().
 *
 * 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;
	unsigned type;
	char kx_name[32];
	char proto_name[32];
	const char *curve_name = NULL;
	unsigned dh_bits = 0;
	unsigned mac_id;
	char *desc;

	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));
	} 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);
	}

	if (curve_name != NULL)
		snprintf(kx_name, sizeof(kx_name), "%s-%s",
			 gnutls_kx_get_name(kx), curve_name);
	else if (dh_bits != 0)
		snprintf(kx_name, sizeof(kx_name), "%s-%u",
			 gnutls_kx_get_name(kx), dh_bits);
	else
		snprintf(kx_name, sizeof(kx_name), "%s",
			 gnutls_kx_get_name(kx));

	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;
}
Ejemplo n.º 5
0
/**
 * 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));

	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;
}
Ejemplo n.º 6
0
int _gnutls_recv_client_certificate(gnutls_session_t session)
{
	gnutls_buffer_st buf;
	int ret = 0;
	int optional;

	if (session->internals.auth_struct->
	    gnutls_process_client_certificate == NULL)
		return 0;

	/* if we have not requested a certificate then just return
	 */
	if (session->internals.send_cert_req == 0) {
		return 0;
	}

	if (session->internals.send_cert_req == GNUTLS_CERT_REQUIRE)
		optional = 0;
	else
		optional = 1;

	ret =
	    _gnutls_recv_handshake(session,
				   GNUTLS_HANDSHAKE_CERTIFICATE_PKT,
				   optional, &buf);

	if (ret < 0) {
		/* Handle the case of old SSL3 clients who send
		 * a warning alert instead of an empty certificate to indicate
		 * no certificate.
		 */
#ifdef ENABLE_SSL3
		if (optional != 0 &&
		    ret == GNUTLS_E_WARNING_ALERT_RECEIVED &&
		    get_num_version(session) == GNUTLS_SSL3 &&
		    gnutls_alert_get(session) ==
		    GNUTLS_A_SSL3_NO_CERTIFICATE) {

			/* SSL3 does not send an empty certificate,
			 * but this alert. So we just ignore it.
			 */
			gnutls_assert();
			return 0;
		}
#endif

		/* certificate was required 
		 */
		if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED
		     || ret == GNUTLS_E_FATAL_ALERT_RECEIVED)
		    && optional == 0) {
			gnutls_assert();
			return GNUTLS_E_NO_CERTIFICATE_FOUND;
		}

		return ret;
	}

	if (ret == 0 && buf.length == 0 && optional != 0) {
		/* Client has not sent the certificate message.
		 * well I'm not sure we should accept this
		 * behaviour.
		 */
		gnutls_assert();
		ret = 0;
		goto cleanup;
	}
	ret =
	    session->internals.auth_struct->
	    gnutls_process_client_certificate(session, buf.data,
					      buf.length);

	if (ret < 0 && ret != GNUTLS_E_NO_CERTIFICATE_FOUND) {
		gnutls_assert();
		goto cleanup;
	}

	/* ok we should expect a certificate verify message now 
	 */
	if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND && optional != 0)
		ret = 0;
	else
		session->internals.crt_requested = 1;

      cleanup:
	_gnutls_buffer_clear(&buf);
	return ret;
}
Ejemplo n.º 7
0
/* here we generate the TLS Master secret.
 */
static int
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, sizeof(buf),
							  NULL));
	_gnutls_hard_log("INT: CLIENT RANDOM[%d]: %s\n", 32,
			 _gnutls_bin2hex(session->security_parameters.
					 client_random, 32, buf,
					 sizeof(buf), NULL));
	_gnutls_hard_log("INT: SERVER RANDOM[%d]: %s\n", 32,
			 _gnutls_bin2hex(session->security_parameters.
					 server_random, 32, buf,
					 sizeof(buf), NULL));

	if (session->security_parameters.ext_master_secret == 0) {
		uint8_t rnd[2 * GNUTLS_RANDOM_SIZE + 1];
		memcpy(rnd, session->security_parameters.client_random,
		       GNUTLS_RANDOM_SIZE);
		memcpy(&rnd[GNUTLS_RANDOM_SIZE],
		       session->security_parameters.server_random,
		       GNUTLS_RANDOM_SIZE);

#ifdef ENABLE_SSL3
		if (get_num_version(session) == GNUTLS_SSL3) {
			ret =
			    _gnutls_ssl3_generate_random(premaster->data,
							 premaster->size, rnd,
							 2 * GNUTLS_RANDOM_SIZE,
							 GNUTLS_MASTER_SIZE,
							 session->security_parameters.
							 master_secret);
		} else
#endif
			ret =
			    _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);
	} else {
		gnutls_datum_t shash = {NULL, 0};

		/* draft-ietf-tls-session-hash-02 */
		ret = _gnutls_handshake_get_session_hash(session, &shash);
		if (ret < 0)
			return gnutls_assert_val(ret);
#ifdef ENABLE_SSL3
		if (get_num_version(session) == GNUTLS_SSL3)
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
#endif

		ret =
		    _gnutls_PRF(session, premaster->data, premaster->size,
				EXT_MASTER_SECRET, EXT_MASTER_SECRET_SIZE,
				shash.data, shash.size,
				GNUTLS_MASTER_SIZE,
				session->security_parameters.
				master_secret);

		gnutls_free(shash.data);
	}

	write_nss_key_log(session, premaster);

	if (!keep_premaster)
		_gnutls_free_temp_key_datum(premaster);

	if (ret < 0)
		return ret;

	_gnutls_hard_log("INT: MASTER SECRET: %s\n",
			 _gnutls_bin2hex(session->security_parameters.
					 master_secret, GNUTLS_MASTER_SIZE,
					 buf, sizeof(buf), NULL));

	return ret;
}
Ejemplo n.º 8
0
/* This function is to be called after handshake, when master_secret,
 *  client_random and server_random have been initialized. 
 * This function creates the keys and stores them into pending session.
 * (session->cipher_specs)
 */
static int
_gnutls_set_keys(gnutls_session_t session, record_parameters_st * params,
		 int hash_size, int IV_size, int key_size)
{
	/* FIXME: This function is too long
	 */
	uint8_t rnd[2 * GNUTLS_RANDOM_SIZE];
	uint8_t rrnd[2 * GNUTLS_RANDOM_SIZE];
	int pos, ret;
	int block_size;
	char buf[65];
	/* avoid using malloc */
	uint8_t key_block[2 * MAX_HASH_SIZE + 2 * MAX_CIPHER_KEY_SIZE +
			  2 * MAX_CIPHER_BLOCK_SIZE];
	record_state_st *client_write, *server_write;

	if (session->security_parameters.entity == GNUTLS_CLIENT) {
		client_write = &params->write;
		server_write = &params->read;
	} else {
		client_write = &params->read;
		server_write = &params->write;
	}

	block_size = 2 * hash_size + 2 * key_size;
	block_size += 2 * IV_size;

	memcpy(rnd, session->security_parameters.server_random,
	       GNUTLS_RANDOM_SIZE);
	memcpy(&rnd[GNUTLS_RANDOM_SIZE],
	       session->security_parameters.client_random,
	       GNUTLS_RANDOM_SIZE);

	memcpy(rrnd, session->security_parameters.client_random,
	       GNUTLS_RANDOM_SIZE);
	memcpy(&rrnd[GNUTLS_RANDOM_SIZE],
	       session->security_parameters.server_random,
	       GNUTLS_RANDOM_SIZE);

	if (get_num_version(session) == GNUTLS_SSL3) {	/* SSL 3 */
		ret =
		    _gnutls_ssl3_generate_random
		    (session->security_parameters.master_secret,
		     GNUTLS_MASTER_SIZE, rnd, 2 * GNUTLS_RANDOM_SIZE,
		     block_size, key_block);
	} else {		/* TLS 1.0 */
		ret =
		    _gnutls_PRF(session,
				session->security_parameters.master_secret,
				GNUTLS_MASTER_SIZE, keyexp, keyexp_length,
				rnd, 2 * GNUTLS_RANDOM_SIZE, block_size,
				key_block);
	}

	if (ret < 0)
		return gnutls_assert_val(ret);

	_gnutls_hard_log("INT: KEY BLOCK[%d]: %s\n", block_size,
			 _gnutls_bin2hex(key_block, block_size, buf,
					 sizeof(buf), NULL));

	pos = 0;
	if (hash_size > 0) {

		if (_gnutls_set_datum
		    (&client_write->mac_secret, &key_block[pos],
		     hash_size) < 0)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		pos += hash_size;

		if (_gnutls_set_datum
		    (&server_write->mac_secret, &key_block[pos],
		     hash_size) < 0)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		pos += hash_size;
	}

	if (key_size > 0) {
		uint8_t *client_write_key, *server_write_key;
		int client_write_key_size, server_write_key_size;

		client_write_key = &key_block[pos];
		client_write_key_size = key_size;

		pos += key_size;

		server_write_key = &key_block[pos];
		server_write_key_size = key_size;

		pos += key_size;

		if (_gnutls_set_datum
		    (&client_write->key, client_write_key,
		     client_write_key_size) < 0)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		_gnutls_hard_log("INT: CLIENT WRITE KEY [%d]: %s\n",
				 client_write_key_size,
				 _gnutls_bin2hex(client_write_key,
						 client_write_key_size,
						 buf, sizeof(buf), NULL));

		if (_gnutls_set_datum
		    (&server_write->key, server_write_key,
		     server_write_key_size) < 0)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		_gnutls_hard_log("INT: SERVER WRITE KEY [%d]: %s\n",
				 server_write_key_size,
				 _gnutls_bin2hex(server_write_key,
						 server_write_key_size,
						 buf, sizeof(buf), NULL));

	}

	/* IV generation in export and non export ciphers.
	 */
	if (IV_size > 0) {
		if (_gnutls_set_datum
		    (&client_write->IV, &key_block[pos], IV_size) < 0)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		pos += IV_size;

		if (_gnutls_set_datum
		    (&server_write->IV, &key_block[pos], IV_size) < 0)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);


		_gnutls_hard_log("INT: CLIENT WRITE IV [%d]: %s\n",
				 client_write->IV.size,
				 _gnutls_bin2hex(client_write->IV.data,
						 client_write->IV.size,
						 buf, sizeof(buf), NULL));

		_gnutls_hard_log("INT: SERVER WRITE IV [%d]: %s\n",
				 server_write->IV.size,
				 _gnutls_bin2hex(server_write->IV.data,
						 server_write->IV.size,
						 buf, sizeof(buf), NULL));
	}

	return 0;
}