static struct wpabuf * ikev2_build_sa_auth(struct ikev2_responder_data *data) { struct wpabuf *msg, *plain; /* build IKE_SA_AUTH: HDR, SK {IDr, [CERT,] 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_idr(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, 0, msg, plain, IKEV2_PAYLOAD_IDr)) { wpabuf_free(plain); wpabuf_free(msg); return NULL; } wpabuf_free(plain); wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_AUTH)", msg); data->state = IKEV2_DONE; 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) { asd_printf(ASD_DEFAULT,MSG_DEBUG, "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_zalloc(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_zalloc(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; }
static struct wpabuf * ikev2_build_notify(struct ikev2_responder_data *data) { struct wpabuf *msg; msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + 1000); if (msg == NULL) return NULL; if (data->last_msg == LAST_MSG_SA_AUTH) { /* HDR, SK{N} */ struct wpabuf *plain = wpabuf_alloc(100); if (plain == NULL) { wpabuf_free(msg); return NULL; } ikev2_build_hdr(data, msg, IKE_SA_AUTH, IKEV2_PAYLOAD_ENCRYPTED, 1); if (ikev2_build_notification(data, plain, IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) || ikev2_build_encrypted(data->proposal.encr, data->proposal.integ, &data->keys, 0, msg, plain, IKEV2_PAYLOAD_NOTIFICATION)) { wpabuf_free(plain); wpabuf_free(msg); return NULL; } wpabuf_free(plain); data->state = IKEV2_FAILED; } else { /* HDR, N */ ikev2_build_hdr(data, msg, IKE_SA_INIT, IKEV2_PAYLOAD_NOTIFICATION, 0); if (ikev2_build_notification(data, msg, IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) { wpabuf_free(msg); return NULL; } data->state = SA_INIT; } ikev2_update_hdr(msg); wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (Notification)", msg); return msg; }
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_init(struct ikev2_responder_data *data) { struct wpabuf *msg; /* build IKE_SA_INIT: HDR, SAr1, KEr, Nr, [CERTREQ], [SK{IDr}] */ if (os_get_random(data->r_spi, IKEV2_SPI_LEN)) return NULL; wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Responder's SPI", data->r_spi, IKEV2_SPI_LEN); data->r_nonce_len = IKEV2_NONCE_MIN_LEN; if (random_get_bytes(data->r_nonce, data->r_nonce_len)) return NULL; #ifdef CCNS_PL /* Zeros are removed incorrectly from the beginning of the nonces in * key derivation; as a workaround, make sure Nr does not start with * zero.. */ if (data->r_nonce[0] == 0) data->r_nonce[0] = 1; #endif /* CCNS_PL */ wpa_hexdump(MSG_DEBUG, "IKEV2: Nr", data->r_nonce, data->r_nonce_len); msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1500); if (msg == NULL) return NULL; ikev2_build_hdr(data, msg, IKE_SA_INIT, IKEV2_PAYLOAD_SA, 0); if (ikev2_build_sar1(data, msg, IKEV2_PAYLOAD_KEY_EXCHANGE) || ikev2_build_ker(data, msg, IKEV2_PAYLOAD_NONCE) || ikev2_build_nr(data, msg, data->peer_auth == PEER_AUTH_SECRET ? IKEV2_PAYLOAD_ENCRYPTED : IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) { wpabuf_free(msg); return NULL; } if (ikev2_derive_keys(data)) { wpabuf_free(msg); return NULL; } if (data->peer_auth == PEER_AUTH_CERT) { /* TODO: CERTREQ with SHA-1 hashes of Subject Public Key Info * for trust agents */ } if (data->peer_auth == PEER_AUTH_SECRET) { struct wpabuf *plain = wpabuf_alloc(data->IDr_len + 1000); if (plain == NULL) { wpabuf_free(msg); return NULL; } if (ikev2_build_idr(data, plain, IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) || ikev2_build_encrypted(data->proposal.encr, data->proposal.integ, &data->keys, 0, msg, plain, IKEV2_PAYLOAD_IDr)) { wpabuf_free(plain); wpabuf_free(msg); return NULL; } wpabuf_free(plain); } ikev2_update_hdr(msg); wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_INIT)", msg); data->state = SA_AUTH; wpabuf_free(data->r_sign_msg); data->r_sign_msg = wpabuf_dup(msg); return msg; }