/**
 * eap_server_tls_derive_session_id - Derive a Session-Id based on TLS data
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
 * @data: Data for TLS processing
 * @eap_type: EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST)
 * @len: Pointer to length of the session ID generated
 * Returns: Pointer to allocated Session-Id on success or %NULL on failure
 *
 * This function derive the Session-Id based on the TLS session data
 * (client/server random and method type).
 *
 * The caller is responsible for freeing the returned buffer.
 */
u8 * eap_server_tls_derive_session_id(struct eap_sm *sm,
				      struct eap_ssl_data *data, u8 eap_type,
				      size_t *len)
{
	struct tls_keys keys;
	u8 *out;

	if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
		return NULL;

	if (keys.client_random == NULL || keys.server_random == NULL)
		return NULL;

	*len = 1 + keys.client_random_len + keys.server_random_len;
	out = os_malloc(*len);
	if (out == NULL)
		return NULL;

	/* Session-Id = EAP type || client.random || server.random */
	out[0] = eap_type;
	os_memcpy(out + 1, keys.client_random, keys.client_random_len);
	os_memcpy(out + 1 + keys.client_random_len, keys.server_random,
		  keys.server_random_len);

	return out;
}
示例#2
0
/**
 * eap_peer_tls_derive_session_id - Derive a Session-Id based on TLS data
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
 * @data: Data for TLS processing
 * @eap_type: EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST)
 * @len: Pointer to length of the session ID generated
 * Returns: Pointer to allocated Session-Id on success or %NULL on failure
 *
 * This function derive the Session-Id based on the TLS session data
 * (client/server random and method type).
 *
 * The caller is responsible for freeing the returned buffer.
 */
u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
				    struct eap_ssl_data *data, u8 eap_type,
				    size_t *len)
{
	struct tls_keys keys;
	u8 *out;

	/*
	 * TLS library did not support session ID generation,
	 * so get the needed TLS session parameters
	 */
	if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
		return NULL;

	if (keys.client_random == NULL || keys.server_random == NULL ||
	    keys.master_key == NULL)
		return NULL;

	*len = 1 + keys.client_random_len + keys.server_random_len;
	out = os_malloc(*len);
	if (out == NULL)
		return NULL;

	/* Session-Id = EAP type || client.random || server.random */
	out[0] = eap_type;
	os_memcpy(out + 1, keys.client_random, keys.client_random_len);
	os_memcpy(out + 1 + keys.client_random_len, keys.server_random,
	          keys.server_random_len);

	return out;
}
u8 * eap_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
			char *label, size_t len)
{
	struct tls_keys keys;
	u8 *random;
	u8 *out;

	if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
		return NULL;
	out = malloc(len);
	random = malloc(keys.client_random_len + keys.server_random_len);
	if (out == NULL || random == NULL) {
		free(out);
		free(random);
		return NULL;
	}
	memcpy(random, keys.client_random, keys.client_random_len);
	memcpy(random + keys.client_random_len, keys.server_random,
	       keys.server_random_len);

	if (tls_prf(keys.master_key, keys.master_key_len,
		    label, random, keys.client_random_len +
		    keys.server_random_len, out, len)) {
		free(random);
		free(out);
		return NULL;
	}
	free(random);
	return out;
}
static int eap_ttls_v1_derive_key(struct eap_sm *sm,
				  struct eap_ttls_data *data)
{
	struct tls_keys keys;
	u8 *rnd;

	os_free(data->key_data);
	data->key_data = NULL;

	os_memset(&keys, 0, sizeof(keys));
	if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) ||
	    keys.client_random == NULL || keys.server_random == NULL ||
	    keys.inner_secret == NULL) {
		wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, "
			   "client random, or server random to derive keying "
			   "material");
		return -1;
	}

	rnd = os_malloc(keys.client_random_len + keys.server_random_len);
	data->key_data = os_malloc(EAP_TLS_KEY_LEN);
	if (rnd == NULL || data->key_data == NULL) {
		wpa_printf(MSG_INFO, "EAP-TTLS: No memory for key derivation");
		os_free(rnd);
		os_free(data->key_data);
		data->key_data = NULL;
		return -1;
	}
	os_memcpy(rnd, keys.client_random, keys.client_random_len);
	os_memcpy(rnd + keys.client_random_len, keys.server_random,
		  keys.server_random_len);

	if (tls_prf(keys.inner_secret, keys.inner_secret_len,
		    "ttls v1 keying material", rnd, keys.client_random_len +
		    keys.server_random_len, data->key_data, EAP_TLS_KEY_LEN)) {
		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key");
		os_free(rnd);
		os_free(data->key_data);
		data->key_data = NULL;
		return -1;
	}

	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: client/server random",
		    rnd, keys.client_random_len + keys.server_random_len);
	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: TLS/IA inner secret",
			keys.inner_secret, keys.inner_secret_len);

	os_free(rnd);

	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",
			data->key_data, EAP_TLS_KEY_LEN);

	return 0;
}
static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,
					struct eap_ttls_data *data, size_t len)
{
	struct tls_keys keys;
	u8 *challenge, *rnd;

	if (data->ttls_version == 0) {
		return eap_tls_derive_key(sm, &data->ssl, "ttls challenge",
					  len);
	}

	os_memset(&keys, 0, sizeof(keys));
	if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) ||
	    keys.client_random == NULL || keys.server_random == NULL ||
	    keys.inner_secret == NULL) {
		wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, "
			   "client random, or server random to derive "
			   "implicit challenge");
		return NULL;
	}

	rnd = os_malloc(keys.client_random_len + keys.server_random_len);
	challenge = os_malloc(len);
	if (rnd == NULL || challenge == NULL) {
		wpa_printf(MSG_INFO, "EAP-TTLS: No memory for implicit "
			   "challenge derivation");
		os_free(rnd);
		os_free(challenge);
		return NULL;
	}
	os_memcpy(rnd, keys.server_random, keys.server_random_len);
	os_memcpy(rnd + keys.server_random_len, keys.client_random,
		  keys.client_random_len);

	if (tls_prf(keys.inner_secret, keys.inner_secret_len,
		    "inner application challenge", rnd,
		    keys.client_random_len + keys.server_random_len,
		    challenge, len)) {
		wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive implicit "
			   "challenge");
		os_free(rnd);
		os_free(challenge);
		return NULL;
	}

	os_free(rnd);

	wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived implicit challenge",
			challenge, len);

	return challenge;
}
示例#6
0
/**
 * eap_peer_tls_derive_key - Derive a key based on TLS session data
 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
 * @data: Data for TLS processing
 * @label: Label string for deriving the keys, e.g., "client EAP encryption"
 * @len: Length of the key material to generate (usually 64 for MSK)
 * Returns: Pointer to allocated key on success or %NULL on failure
 *
 * This function uses TLS-PRF to generate pseudo-random data based on the TLS
 * session data (client/server random and master key). Each key type may use a
 * different label to bind the key usage into the generated material.
 *
 * The caller is responsible for freeing the returned buffer.
 */
u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
			     const char *label, size_t len)
{
#ifndef CONFIG_FIPS
	struct tls_keys keys;
#endif /* CONFIG_FIPS */
	u8 *rnd = NULL, *out;

	out = os_malloc(len);
	if (out == NULL)
		return NULL;

	/* First, try to use TLS library function for PRF, if available. */
	if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, out, len)
	    == 0)
		return out;

#ifndef CONFIG_FIPS
	/*
	 * TLS library did not support key generation, so get the needed TLS
	 * session parameters and use an internal implementation of TLS PRF to
	 * derive the key.
	 */
	if (tls_connection_get_keys(data->ssl_ctx, data->conn, &keys))
		goto fail;

	if (keys.client_random == NULL || keys.server_random == NULL ||
	    keys.master_key == NULL)
		goto fail;

	rnd = os_malloc(keys.client_random_len + keys.server_random_len);
	if (rnd == NULL)
		goto fail;
	os_memcpy(rnd, keys.client_random, keys.client_random_len);
	os_memcpy(rnd + keys.client_random_len, keys.server_random,
		  keys.server_random_len);

	if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len,
			     label, rnd, keys.client_random_len +
			     keys.server_random_len, out, len))
		goto fail;

	os_free(rnd);
	return out;

fail:
#endif /* CONFIG_FIPS */
	os_free(out);
	os_free(rnd);
	return NULL;
}
示例#7
0
u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn,
			 const char *label, size_t len)
{
	struct tls_keys keys;
	u8 *rnd = NULL, *out;
	int block_size;

	block_size = tls_connection_get_keyblock_size(ssl_ctx, conn);
	if (block_size < 0)
		return NULL;

	out = os_malloc(block_size + len);
	if (out == NULL)
		return NULL;

	if (tls_connection_prf(ssl_ctx, conn, label, 1, out, block_size + len)
	    == 0) {
		os_memmove(out, out + block_size, len);
		return out;
	}

	if (tls_connection_get_keys(ssl_ctx, conn, &keys))
		goto fail;

	rnd = os_malloc(keys.client_random_len + keys.server_random_len);
	if (rnd == NULL)
		goto fail;

	os_memcpy(rnd, keys.server_random, keys.server_random_len);
	os_memcpy(rnd + keys.server_random_len, keys.client_random,
		  keys.client_random_len);

	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key "
			"expansion", keys.master_key, keys.master_key_len);
	if (tls_prf(keys.master_key, keys.master_key_len,
		    label, rnd, keys.client_random_len +
		    keys.server_random_len, out, block_size + len))
		goto fail;
	os_free(rnd);
	os_memmove(out, out + block_size, len);
	return out;

fail:
	os_free(rnd);
	os_free(out);
	return NULL;
}
u8 * eap_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
			char *label, size_t len)
{
	struct tls_keys keys;
	u8 *rnd;
	u8 *out;

	if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
		return NULL;

	if (keys.eap_tls_prf && strcmp(label, "client EAP encryption") == 0) {
		if (len > keys.eap_tls_prf_len)
			return NULL;
		out = malloc(len);
		if (out == NULL)
			return NULL;
		memcpy(out, keys.eap_tls_prf, len);
		return out;
	}

	if (keys.client_random == NULL || keys.server_random == NULL ||
	    keys.master_key == NULL)
		return NULL;

	out = malloc(len);
	rnd = malloc(keys.client_random_len + keys.server_random_len);
	if (out == NULL || rnd == NULL) {
		free(out);
		free(rnd);
		return NULL;
	}
	memcpy(rnd, keys.client_random, keys.client_random_len);
	memcpy(rnd + keys.client_random_len, keys.server_random,
	       keys.server_random_len);

	if (tls_prf(keys.master_key, keys.master_key_len,
		    label, rnd, keys.client_random_len +
		    keys.server_random_len, out, len)) {
		free(rnd);
		free(out);
		return NULL;
	}
	free(rnd);
	return out;
}
示例#9
0
u8 * eap_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
			char *label, size_t len)
{
	struct tls_keys keys;
	u8 *rnd = NULL, *out;

	out = malloc(len);
	if (out == NULL)
		return NULL;

	if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) ==
	    0)
		return out;

	if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
		goto fail;

	if (keys.client_random == NULL || keys.server_random == NULL ||
	    keys.master_key == NULL)
		goto fail;

	rnd = malloc(keys.client_random_len + keys.server_random_len);
	if (rnd == NULL)
		goto fail;
	memcpy(rnd, keys.client_random, keys.client_random_len);
	memcpy(rnd + keys.client_random_len, keys.server_random,
	       keys.server_random_len);

	if (tls_prf(keys.master_key, keys.master_key_len,
		    label, rnd, keys.client_random_len +
		    keys.server_random_len, out, len))
		goto fail;

	free(rnd);
	return out;

fail:
	free(out);
	free(rnd);
	return NULL;
}