📄 ikev2.c
字号:
wpabuf_free(data->i_dh_public); data->i_dh_public = wpabuf_alloc(kei_len - 4); if (data->i_dh_public == NULL) return -1; wpabuf_put_data(data->i_dh_public, kei + 4, kei_len - 4); wpa_hexdump_buf(MSG_DEBUG, "IKEV2: KEi Diffie-Hellman Public Value", data->i_dh_public); return 0;}static int ikev2_process_ni(struct ikev2_responder_data *data, const u8 *ni, size_t ni_len){ if (ni == NULL) { wpa_printf(MSG_INFO, "IKEV2: Ni not received"); return -1; } if (ni_len < IKEV2_NONCE_MIN_LEN || ni_len > IKEV2_NONCE_MAX_LEN) { wpa_printf(MSG_INFO, "IKEV2: Invalid Ni length %ld", (long) ni_len); return -1; }#ifdef CCNS_PL /* Zeros are removed incorrectly from the beginning of the nonces */ while (ni_len > 1 && *ni == 0) { ni_len--; ni++; }#endif /* CCNS_PL */ data->i_nonce_len = ni_len; os_memcpy(data->i_nonce, ni, ni_len); wpa_hexdump(MSG_MSGDUMP, "IKEV2: Ni", data->i_nonce, data->i_nonce_len); return 0;}static int ikev2_process_sa_init(struct ikev2_responder_data *data, const struct ikev2_hdr *hdr, struct ikev2_payloads *pl){ if (ikev2_process_sai1(data, pl->sa, pl->sa_len) < 0 || ikev2_process_kei(data, pl->ke, pl->ke_len) < 0 || ikev2_process_ni(data, pl->nonce, pl->nonce_len) < 0) return -1; os_memcpy(data->i_spi, hdr->i_spi, IKEV2_SPI_LEN); return 0;}static int ikev2_process_idi(struct ikev2_responder_data *data, const u8 *idi, size_t idi_len){ u8 id_type; if (idi == NULL) { wpa_printf(MSG_INFO, "IKEV2: No IDi received"); return -1; } if (idi_len < 4) { wpa_printf(MSG_INFO, "IKEV2: Too short IDi payload"); return -1; } id_type = idi[0]; idi += 4; idi_len -= 4; wpa_printf(MSG_DEBUG, "IKEV2: IDi ID Type %d", id_type); wpa_hexdump_ascii(MSG_DEBUG, "IKEV2: IDi", idi, idi_len); os_free(data->IDi); data->IDi = os_malloc(idi_len); if (data->IDi == NULL) return -1; os_memcpy(data->IDi, idi, idi_len); data->IDi_len = idi_len; data->IDi_type = id_type; return 0;}static int ikev2_process_cert(struct ikev2_responder_data *data, const u8 *cert, size_t cert_len){ u8 cert_encoding; if (cert == NULL) { if (data->peer_auth == PEER_AUTH_CERT) { wpa_printf(MSG_INFO, "IKEV2: No Certificate received"); return -1; } return 0; } if (cert_len < 1) { wpa_printf(MSG_INFO, "IKEV2: No Cert Encoding field"); return -1; } cert_encoding = cert[0]; cert++; cert_len--; wpa_printf(MSG_DEBUG, "IKEV2: Cert Encoding %d", cert_encoding); wpa_hexdump(MSG_MSGDUMP, "IKEV2: Certificate Data", cert, cert_len); /* TODO: validate certificate */ return 0;}static int ikev2_process_auth_cert(struct ikev2_responder_data *data, u8 method, const u8 *auth, size_t auth_len){ if (method != AUTH_RSA_SIGN) { wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication " "method %d", method); return -1; } /* TODO: validate AUTH */ return 0;}static int ikev2_process_auth_secret(struct ikev2_responder_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 | Nr | prf(SK_pi,IDi') */ if (ikev2_derive_auth_data(data->proposal.prf, data->i_sign_msg, data->IDi, data->IDi_len, data->IDi_type, &data->keys, 1, data->shared_secret, data->shared_secret_len, data->r_nonce, data->r_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->i_sign_msg); data->i_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); data->error_type = AUTHENTICATION_FAILED; data->state = NOTIFY; return -1; } wpa_printf(MSG_DEBUG, "IKEV2: Server authenticated successfully " "using shared keys"); return 0;}static int ikev2_process_auth(struct ikev2_responder_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_responder_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_idi(data, pl.idi, pl.idi_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_responder_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, 1, 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); return ret;}static int ikev2_validate_rx_state(struct ikev2_responder_data *data, u8 exchange_type, u32 message_id){ switch (data->state) { case SA_INIT: /* Expect to receive IKE_SA_INIT: HDR, SAi1, KEi, Ni */ 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 {IDi, [CERT,] [CERTREQ,] [IDr,] * AUTH, SAi2, TSi, TSr} */ 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 NOTIFY: case IKEV2_DONE: case IKEV2_FAILED: return -1; } return 0;}int ikev2_responder_process(struct ikev2_responder_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; } data->error_type = 0; 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 Responder'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_INITIATOR) { 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; if (data->state == SA_INIT) { data->last_msg = LAST_MSG_SA_INIT; if (ikev2_process_sa_init(data, hdr, &pl) < 0) { if (data->state == NOTIFY) return 0; return -1; } wpabuf_free(data->i_sign_msg); data->i_sign_msg = wpabuf_dup(buf); } if (data->state == SA_AUTH) { data->last_msg = LAST_MSG_SA_AUTH; if (ikev2_process_sa_auth(data, hdr, &pl) < 0) { if (data->state == NOTIFY) return 0; return -1; } } return 0;}static void ikev2_build_hdr(struct ikev2_responder_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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -