⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ikev2.c

📁 IEEE 802.11a/b/g 服务器端AP
💻 C
📖 第 1 页 / 共 2 页
字号:
	return 0;}static int ikev2_process_auth_secret(struct ikev2_initiator_data *data,				     u8 method, const u8 *auth,				     size_t auth_len){	u8 auth_data[IKEV2_MAX_HASH_LEN];	const struct ikev2_prf_alg *prf;	if (method != AUTH_SHARED_KEY_MIC) {		wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication "			   "method %d", method);		return -1;	}	/* msg | Ni | prf(SK_pr,IDr') */	if (ikev2_derive_auth_data(data->proposal.prf, data->r_sign_msg,				   data->IDr, data->IDr_len, data->IDr_type,				   &data->keys, 0, data->shared_secret,				   data->shared_secret_len,				   data->i_nonce, data->i_nonce_len,				   data->key_pad, data->key_pad_len,				   auth_data) < 0) {		wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data");		return -1;	}	wpabuf_free(data->r_sign_msg);	data->r_sign_msg = NULL;	prf = ikev2_get_prf(data->proposal.prf);	if (prf == NULL)		return -1;	if (auth_len != prf->hash_len ||	    os_memcmp(auth, auth_data, auth_len) != 0) {		wpa_printf(MSG_INFO, "IKEV2: Invalid Authentication Data");		wpa_hexdump(MSG_DEBUG, "IKEV2: Received Authentication Data",			    auth, auth_len);		wpa_hexdump(MSG_DEBUG, "IKEV2: Expected Authentication Data",			    auth_data, prf->hash_len);		return -1;	}	wpa_printf(MSG_DEBUG, "IKEV2: Peer authenticated successfully "		   "using shared keys");	return 0;}static int ikev2_process_auth(struct ikev2_initiator_data *data,			      const u8 *auth, size_t auth_len){	u8 auth_method;	if (auth == NULL) {		wpa_printf(MSG_INFO, "IKEV2: No Authentication Payload");		return -1;	}	if (auth_len < 4) {		wpa_printf(MSG_INFO, "IKEV2: Too short Authentication "			   "Payload");		return -1;	}	auth_method = auth[0];	auth += 4;	auth_len -= 4;	wpa_printf(MSG_DEBUG, "IKEV2: Auth Method %d", auth_method);	wpa_hexdump(MSG_MSGDUMP, "IKEV2: Authentication Data", auth, auth_len);	switch (data->peer_auth) {	case PEER_AUTH_CERT:		return ikev2_process_auth_cert(data, auth_method, auth,					       auth_len);	case PEER_AUTH_SECRET:		return ikev2_process_auth_secret(data, auth_method, auth,						 auth_len);	}	return -1;}static int ikev2_process_sa_auth_decrypted(struct ikev2_initiator_data *data,					   u8 next_payload,					   u8 *payload, size_t payload_len){	struct ikev2_payloads pl;	wpa_printf(MSG_DEBUG, "IKEV2: Processing decrypted payloads");	if (ikev2_parse_payloads(&pl, next_payload, payload, payload +				 payload_len) < 0) {		wpa_printf(MSG_INFO, "IKEV2: Failed to parse decrypted "			   "payloads");		return -1;	}	if (ikev2_process_idr(data, pl.idr, pl.idr_len) < 0 ||	    ikev2_process_cert(data, pl.cert, pl.cert_len) < 0 ||	    ikev2_process_auth(data, pl.auth, pl.auth_len) < 0)		return -1;	return 0;}static int ikev2_process_sa_auth(struct ikev2_initiator_data *data,				 const struct ikev2_hdr *hdr,				 struct ikev2_payloads *pl){	u8 *decrypted;	size_t decrypted_len;	int ret;	decrypted = ikev2_decrypt_payload(data->proposal.encr,					  data->proposal.integ,					  &data->keys, 0, hdr, pl->encrypted,					  pl->encrypted_len, &decrypted_len);	if (decrypted == NULL)		return -1;	ret = ikev2_process_sa_auth_decrypted(data, pl->encr_next_payload,					      decrypted, decrypted_len);	os_free(decrypted);	if (ret == 0 && !data->unknown_user) {		wpa_printf(MSG_DEBUG, "IKEV2: Authentication completed");		data->state = IKEV2_DONE;	}	return ret;}static int ikev2_validate_rx_state(struct ikev2_initiator_data *data,				   u8 exchange_type, u32 message_id){	switch (data->state) {	case SA_INIT:		/* Expect to receive IKE_SA_INIT: HDR, SAr, KEr, Nr, [CERTREQ],		 * [SK{IDr}] */		if (exchange_type != IKE_SA_INIT) {			wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type "				   "%u in SA_INIT state", exchange_type);			return -1;		}		if (message_id != 0) {			wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u "				   "in SA_INIT state", message_id);			return -1;		}		break;	case SA_AUTH:		/* Expect to receive IKE_SA_AUTH:		 * HDR, SK {IDr, [CERT,] [CERTREQ,] [NFID,] AUTH}		 */		if (exchange_type != IKE_SA_AUTH) {			wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type "				   "%u in SA_AUTH state", exchange_type);			return -1;		}		if (message_id != 1) {			wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u "				   "in SA_AUTH state", message_id);			return -1;		}		break;	case CHILD_SA:		if (exchange_type != CREATE_CHILD_SA) {			wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type "				   "%u in CHILD_SA state", exchange_type);			return -1;		}		if (message_id != 2) {			wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u "				   "in CHILD_SA state", message_id);			return -1;		}		break;	case IKEV2_DONE:		return -1;	}	return 0;}int ikev2_initiator_process(struct ikev2_initiator_data *data,			    const struct wpabuf *buf){	const struct ikev2_hdr *hdr;	u32 length, message_id;	const u8 *pos, *end;	struct ikev2_payloads pl;	wpa_printf(MSG_MSGDUMP, "IKEV2: Received message (len %lu)",		   (unsigned long) wpabuf_len(buf));	if (wpabuf_len(buf) < sizeof(*hdr)) {		wpa_printf(MSG_INFO, "IKEV2: Too short frame to include HDR");		return -1;	}	hdr = (const struct ikev2_hdr *) wpabuf_head(buf);	end = wpabuf_head_u8(buf) + wpabuf_len(buf);	message_id = WPA_GET_BE32(hdr->message_id);	length = WPA_GET_BE32(hdr->length);	wpa_hexdump(MSG_DEBUG, "IKEV2:   IKE_SA Initiator's SPI",		    hdr->i_spi, IKEV2_SPI_LEN);	wpa_hexdump(MSG_DEBUG, "IKEV2:   IKE_SA Initiator's SPI",		    hdr->r_spi, IKEV2_SPI_LEN);	wpa_printf(MSG_DEBUG, "IKEV2:   Next Payload: %u  Version: 0x%x  "		   "Exchange Type: %u",		   hdr->next_payload, hdr->version, hdr->exchange_type);	wpa_printf(MSG_DEBUG, "IKEV2:   Message ID: %u  Length: %u",		   message_id, length);	if (hdr->version != IKEV2_VERSION) {		wpa_printf(MSG_INFO, "IKEV2: Unsupported HDR version 0x%x "			   "(expected 0x%x)", hdr->version, IKEV2_VERSION);		return -1;	}	if (length != wpabuf_len(buf)) {		wpa_printf(MSG_INFO, "IKEV2: Invalid length (HDR: %lu != "			   "RX: %lu)", (unsigned long) length,			   (unsigned long) wpabuf_len(buf));		return -1;	}	if (ikev2_validate_rx_state(data, hdr->exchange_type, message_id) < 0)		return -1;	if ((hdr->flags & (IKEV2_HDR_INITIATOR | IKEV2_HDR_RESPONSE)) !=	    IKEV2_HDR_RESPONSE) {		wpa_printf(MSG_INFO, "IKEV2: Unexpected Flags value 0x%x",			   hdr->flags);		return -1;	}	if (data->state != SA_INIT) {		if (os_memcmp(data->i_spi, hdr->i_spi, IKEV2_SPI_LEN) != 0) {			wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA "				   "Initiator's SPI");			return -1;		}		if (os_memcmp(data->r_spi, hdr->r_spi, IKEV2_SPI_LEN) != 0) {			wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA "				   "Responder's SPI");			return -1;		}	}	pos = (const u8 *) (hdr + 1);	if (ikev2_parse_payloads(&pl, hdr->next_payload, pos, end) < 0)		return -1;	switch (data->state) {	case SA_INIT:		if (ikev2_process_sa_init(data, hdr, &pl) < 0)			return -1;		wpabuf_free(data->r_sign_msg);		data->r_sign_msg = wpabuf_dup(buf);		break;	case SA_AUTH:		if (ikev2_process_sa_auth(data, hdr, &pl) < 0)			return -1;		break;	case CHILD_SA:	case IKEV2_DONE:		break;	}	return 0;}static void ikev2_build_hdr(struct ikev2_initiator_data *data,			    struct wpabuf *msg, u8 exchange_type,			    u8 next_payload, u32 message_id){	struct ikev2_hdr *hdr;	wpa_printf(MSG_DEBUG, "IKEV2: Adding HDR");	/* HDR - RFC 4306, Sect. 3.1 */	hdr = wpabuf_put(msg, sizeof(*hdr));	os_memcpy(hdr->i_spi, data->i_spi, IKEV2_SPI_LEN);	os_memcpy(hdr->r_spi, data->r_spi, IKEV2_SPI_LEN);	hdr->next_payload = next_payload;	hdr->version = IKEV2_VERSION;	hdr->exchange_type = exchange_type;	hdr->flags = IKEV2_HDR_INITIATOR;	WPA_PUT_BE32(hdr->message_id, message_id);}static int ikev2_build_sai(struct ikev2_initiator_data *data,			    struct wpabuf *msg, u8 next_payload){	struct ikev2_payload_hdr *phdr;	size_t plen;	struct ikev2_proposal *p;	struct ikev2_transform *t;	wpa_printf(MSG_DEBUG, "IKEV2: Adding SAi payload");	/* SAi1 - RFC 4306, Sect. 2.7 and 3.3 */	phdr = wpabuf_put(msg, sizeof(*phdr));	phdr->next_payload = next_payload;	phdr->flags = 0;	/* TODO: support for multiple proposals */	p = wpabuf_put(msg, sizeof(*p));	p->proposal_num = data->proposal.proposal_num;	p->protocol_id = IKEV2_PROTOCOL_IKE;	p->num_transforms = 4;	t = wpabuf_put(msg, sizeof(*t));	t->type = 3;	t->transform_type = IKEV2_TRANSFORM_ENCR;	WPA_PUT_BE16(t->transform_id, data->proposal.encr);	if (data->proposal.encr == ENCR_AES_CBC) {		/* Transform Attribute: Key Len = 128 bits */		wpabuf_put_be16(msg, 0x800e); /* AF=1, AttrType=14 */		wpabuf_put_be16(msg, 128); /* 128-bit key */	}	plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) t;	WPA_PUT_BE16(t->transform_length, plen);	t = wpabuf_put(msg, sizeof(*t));	t->type = 3;	WPA_PUT_BE16(t->transform_length, sizeof(*t));	t->transform_type = IKEV2_TRANSFORM_PRF;	WPA_PUT_BE16(t->transform_id, data->proposal.prf);	t = wpabuf_put(msg, sizeof(*t));	t->type = 3;	WPA_PUT_BE16(t->transform_length, sizeof(*t));	t->transform_type = IKEV2_TRANSFORM_INTEG;	WPA_PUT_BE16(t->transform_id, data->proposal.integ);	t = wpabuf_put(msg, sizeof(*t));	WPA_PUT_BE16(t->transform_length, sizeof(*t));	t->transform_type = IKEV2_TRANSFORM_DH;	WPA_PUT_BE16(t->transform_id, data->proposal.dh);	plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) p;	WPA_PUT_BE16(p->proposal_length, plen);	plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;	WPA_PUT_BE16(phdr->payload_length, plen);	return 0;}static int ikev2_build_kei(struct ikev2_initiator_data *data,			   struct wpabuf *msg, u8 next_payload){	struct ikev2_payload_hdr *phdr;	size_t plen;	struct wpabuf *pv;	wpa_printf(MSG_DEBUG, "IKEV2: Adding KEi payload");	data->dh = dh_groups_get(data->proposal.dh);	pv = dh_init(data->dh, &data->i_dh_private);	if (pv == NULL) {		wpa_printf(MSG_DEBUG, "IKEV2: Failed to initialize DH");		return -1;	}	/* KEi - RFC 4306, Sect. 3.4 */	phdr = wpabuf_put(msg, sizeof(*phdr));	phdr->next_payload = next_payload;	phdr->flags = 0;	wpabuf_put_be16(msg, data->proposal.dh); /* DH Group # */	wpabuf_put(msg, 2); /* RESERVED */	/*	 * RFC 4306, Sect. 3.4: possible zero padding for public value to	 * match the length of the prime.	 */	wpabuf_put(msg, data->dh->prime_len - wpabuf_len(pv));	wpabuf_put_buf(msg, pv);	os_free(pv);	plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;	WPA_PUT_BE16(phdr->payload_length, plen);	return 0;}static int ikev2_build_ni(struct ikev2_initiator_data *data,			  struct wpabuf *msg, u8 next_payload){	struct ikev2_payload_hdr *phdr;	size_t plen;	wpa_printf(MSG_DEBUG, "IKEV2: Adding Ni payload");	/* Ni - RFC 4306, Sect. 3.9 */	phdr = wpabuf_put(msg, sizeof(*phdr));	phdr->next_payload = next_payload;	phdr->flags = 0;	wpabuf_put_data(msg, data->i_nonce, data->i_nonce_len);	plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;	WPA_PUT_BE16(phdr->payload_length, plen);	return 0;}static int ikev2_build_idi(struct ikev2_initiator_data *data,			   struct wpabuf *msg, u8 next_payload){	struct ikev2_payload_hdr *phdr;	size_t plen;	wpa_printf(MSG_DEBUG, "IKEV2: Adding IDi payload");	if (data->IDi == NULL) {		wpa_printf(MSG_INFO, "IKEV2: No IDi available");		return -1;	}	/* IDi - RFC 4306, Sect. 3.5 */	phdr = wpabuf_put(msg, sizeof(*phdr));	phdr->next_payload = next_payload;	phdr->flags = 0;	wpabuf_put_u8(msg, ID_KEY_ID);	wpabuf_put(msg, 3); /* RESERVED */	wpabuf_put_data(msg, data->IDi, data->IDi_len);	plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;	WPA_PUT_BE16(phdr->payload_length, plen);	return 0;}static int ikev2_build_auth(struct ikev2_initiator_data *data,			    struct wpabuf *msg, u8 next_payload){	struct ikev2_payload_hdr *phdr;	size_t plen;	const struct ikev2_prf_alg *prf;	wpa_printf(MSG_DEBUG, "IKEV2: Adding AUTH payload");	prf = ikev2_get_prf(data->proposal.prf);	if (prf == NULL)		return -1;	/* Authentication - RFC 4306, Sect. 3.8 */	phdr = wpabuf_put(msg, sizeof(*phdr));	phdr->next_payload = next_payload;	phdr->flags = 0;	wpabuf_put_u8(msg, AUTH_SHARED_KEY_MIC);	wpabuf_put(msg, 3); /* RESERVED */	/* msg | Nr | prf(SK_pi,IDi') */	if (ikev2_derive_auth_data(data->proposal.prf, data->i_sign_msg,				   data->IDi, data->IDi_len, ID_KEY_ID,				   &data->keys, 1, data->shared_secret,				   data->shared_secret_len,				   data->r_nonce, data->r_nonce_len,				   data->key_pad, data->key_pad_len,				   wpabuf_put(msg, prf->hash_len)) < 0) {		wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data");		return -1;	}	wpabuf_free(data->i_sign_msg);	data->i_sign_msg = NULL;	plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;	WPA_PUT_BE16(phdr->payload_length, plen);	return 0;}static struct wpabuf * ikev2_build_sa_init(struct ikev2_initiator_data *data){	struct wpabuf *msg;	/* build IKE_SA_INIT: HDR, SAi, KEi, Ni */	if (os_get_random(data->i_spi, IKEV2_SPI_LEN))		return NULL;	wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Initiator's SPI",		    data->i_spi, IKEV2_SPI_LEN);	data->i_nonce_len = IKEV2_NONCE_MIN_LEN;	if (os_get_random(data->i_nonce, data->i_nonce_len))		return NULL;	wpa_hexdump(MSG_DEBUG, "IKEV2: Ni", data->i_nonce, data->i_nonce_len);	msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + 1000);	if (msg == NULL)		return NULL;	ikev2_build_hdr(data, msg, IKE_SA_INIT, IKEV2_PAYLOAD_SA, 0);	if (ikev2_build_sai(data, msg, IKEV2_PAYLOAD_KEY_EXCHANGE) ||	    ikev2_build_kei(data, msg, IKEV2_PAYLOAD_NONCE) ||	    ikev2_build_ni(data, msg, IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) {		wpabuf_free(msg);		return NULL;	}	ikev2_update_hdr(msg);	wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_INIT)", msg);	wpabuf_free(data->i_sign_msg);	data->i_sign_msg = wpabuf_dup(msg);	return msg;}static struct wpabuf * ikev2_build_sa_auth(struct ikev2_initiator_data *data){	struct wpabuf *msg, *plain;	const u8 *secret;	size_t secret_len;	secret = data->get_shared_secret(data->cb_ctx, data->IDr,					 data->IDr_len, &secret_len);	if (secret == NULL) {		wpa_printf(MSG_INFO, "IKEV2: Could not get shared secret - "			   "use fake value");		/* RFC 5106, Sect. 7:		 * Use a random key to fake AUTH generation in order to prevent		 * probing of user identities.		 */		data->unknown_user = 1;		os_free(data->shared_secret);		data->shared_secret = os_malloc(16);		if (data->shared_secret == NULL)			return NULL;		data->shared_secret_len = 16;		if (os_get_random(data->shared_secret, 16))			return NULL;	} else {		os_free(data->shared_secret);		data->shared_secret = os_malloc(secret_len);		if (data->shared_secret == NULL)			return NULL;		os_memcpy(data->shared_secret, secret, secret_len);		data->shared_secret_len = secret_len;	}	/* build IKE_SA_AUTH: HDR, SK {IDi, [CERT,] [CERTREQ,] AUTH} */	msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1000);	if (msg == NULL)		return NULL;	ikev2_build_hdr(data, msg, IKE_SA_AUTH, IKEV2_PAYLOAD_ENCRYPTED, 1);	plain = wpabuf_alloc(data->IDr_len + 1000);	if (plain == NULL) {		wpabuf_free(msg);		return NULL;	}	if (ikev2_build_idi(data, plain, IKEV2_PAYLOAD_AUTHENTICATION) ||	    ikev2_build_auth(data, plain, IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) ||	    ikev2_build_encrypted(data->proposal.encr, data->proposal.integ,				  &data->keys, 1, msg, plain,				  IKEV2_PAYLOAD_IDi)) {		wpabuf_free(plain);		wpabuf_free(msg);		return NULL;	}	wpabuf_free(plain);	wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_AUTH)", msg);	return msg;}struct wpabuf * ikev2_initiator_build(struct ikev2_initiator_data *data){	switch (data->state) {	case SA_INIT:		return ikev2_build_sa_init(data);	case SA_AUTH:		return ikev2_build_sa_auth(data);	case CHILD_SA:		return NULL;	case IKEV2_DONE:		return NULL;	}	return NULL;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -