18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IKEv2 responder (RFC 4306) for EAP-IKEV2 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2007, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/dh_groups.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ikev2.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid ikev2_responder_deinit(struct ikev2_responder_data *data) 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_free_keys(&data->keys); 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->i_dh_public); 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->r_dh_private); 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->IDi); 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->IDr); 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->shared_secret); 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->i_sign_msg); 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->r_sign_msg); 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->key_pad); 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_derive_keys(struct ikev2_responder_data *data) 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos, *pad, skeyseed[IKEV2_MAX_HASH_LEN]; 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len, pad_len; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *shared; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_integ_alg *integ; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_prf_alg *prf; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_encr_alg *encr; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr[2]; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[2]; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RFC 4306, Sect. 2.14 */ 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt integ = ikev2_get_integ(data->proposal.integ); 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prf = ikev2_get_prf(data->proposal.prf); 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encr = ikev2_get_encr(data->proposal.encr); 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (integ == NULL || prf == NULL || encr == NULL) { 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported proposal"); 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt shared = dh_derive_shared(data->i_dh_public, data->r_dh_private, 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->dh); 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (shared == NULL) 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Construct Ni | Nr | SPIi | SPIr */ 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len = data->i_nonce_len + data->r_nonce_len + 2 * IKEV2_SPI_LEN; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(buf_len); 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) { 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(shared); 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, data->i_nonce, data->i_nonce_len); 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += data->i_nonce_len; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, data->r_nonce, data->r_nonce_len); 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += data->r_nonce_len; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, data->i_spi, IKEV2_SPI_LEN); 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += IKEV2_SPI_LEN; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, data->r_spi, IKEV2_SPI_LEN); 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CCNS_PL 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if __BYTE_ORDER == __LITTLE_ENDIAN 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *tmp = pos - IKEV2_SPI_LEN; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Incorrect byte re-ordering on little endian hosts.. */ 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < IKEV2_SPI_LEN; i++) 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *tmp++ = data->i_spi[IKEV2_SPI_LEN - 1 - i]; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < IKEV2_SPI_LEN; i++) 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *tmp++ = data->r_spi[IKEV2_SPI_LEN - 1 - i]; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CCNS_PL */ 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SKEYSEED = prf(Ni | Nr, g^ir) */ 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Use zero-padding per RFC 4306, Sect. 2.14 */ 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad_len = data->dh->prime_len - wpabuf_len(shared); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CCNS_PL 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Shared secret is not zero-padded correctly */ 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad_len = 0; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CCNS_PL */ 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pad = os_zalloc(pad_len ? pad_len : 1); 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pad == NULL) { 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(shared); 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[0] = pad; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = pad_len; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr[1] = wpabuf_head(shared); 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = wpabuf_len(shared); 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_prf_hash(prf->id, buf, data->i_nonce_len + data->r_nonce_len, 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2, addr, len, skeyseed) < 0) { 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(shared); 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pad); 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pad); 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(shared); 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* DH parameters are not needed anymore, so free them */ 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->i_dh_public); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->i_dh_public = NULL; 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->r_dh_private); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->r_dh_private = NULL; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "IKEV2: SKEYSEED", 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt skeyseed, prf->hash_len); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = ikev2_derive_sk_keys(prf, integ, encr, skeyseed, buf, buf_len, 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &data->keys); 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_parse_transform(struct ikev2_proposal_data *prop, 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, const u8 *end) 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int transform_len; 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_transform *t; 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 transform_id; 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *tend; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < (int) sizeof(*t)) { 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Too short transform"); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt t = (const struct ikev2_transform *) pos; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt transform_len = WPA_GET_BE16(t->transform_length); 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (transform_len < (int) sizeof(*t) || pos + transform_len > end) { 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid transform length %d", 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt transform_len); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tend = pos + transform_len; 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt transform_id = WPA_GET_BE16(t->transform_id); 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Transform:"); 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Type: %d Transform Length: %d " 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Transform Type: %d Transform ID: %d", 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt t->type, transform_len, t->transform_type, transform_id); 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (t->type != 0 && t->type != 3) { 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Transform type"); 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (t + 1); 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos < tend) { 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "IKEV2: Transform Attributes", 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, tend - pos); 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (t->transform_type) { 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_TRANSFORM_ENCR: 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_get_encr(transform_id)) { 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (transform_id == ENCR_AES_CBC) { 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tend - pos != 4) { 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: No " 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Transform Attr for AES"); 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CCNS_PL 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (WPA_GET_BE16(pos) != 0x001d /* ?? */) { 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Not a " 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Key Size attribute for " 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AES"); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CCNS_PL */ 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (WPA_GET_BE16(pos) != 0x800e) { 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Not a " 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Key Size attribute for " 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AES"); 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CCNS_PL */ 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (WPA_GET_BE16(pos + 2) != 128) { 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: " 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Unsupported AES key size " 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d bits", 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(pos + 2)); 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prop->encr = transform_id; 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_TRANSFORM_PRF: 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_get_prf(transform_id)) 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prop->prf = transform_id; 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_TRANSFORM_INTEG: 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_get_integ(transform_id)) 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prop->integ = transform_id; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_TRANSFORM_DH: 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dh_groups_get(transform_id)) 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prop->dh = transform_id; 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return transform_len; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_parse_proposal(struct ikev2_proposal_data *prop, 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, const u8 *end) 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pend, *ppos; 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int proposal_len, i; 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_proposal *p; 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < (int) sizeof(*p)) { 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Too short proposal"); 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: AND processing if multiple proposals use the same # */ 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p = (const struct ikev2_proposal *) pos; 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt proposal_len = WPA_GET_BE16(p->proposal_length); 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (proposal_len < (int) sizeof(*p) || pos + proposal_len > end) { 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid proposal length %d", 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt proposal_len); 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: SAi1 Proposal # %d", 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p->proposal_num); 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Type: %d Proposal Length: %d " 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " Protocol ID: %d", 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p->type, proposal_len, p->protocol_id); 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: SPI Size: %d Transforms: %d", 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p->spi_size, p->num_transforms); 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p->type != 0 && p->type != 2) { 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal type"); 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p->protocol_id != IKEV2_PROTOCOL_IKE) { 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Unexpected Protocol ID " 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(only IKE allowed for EAP-IKEv2)"); 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p->proposal_num != prop->proposal_num) { 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p->proposal_num == prop->proposal_num + 1) 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prop->proposal_num = p->proposal_num; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Proposal #"); 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ppos = (const u8 *) (p + 1); 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pend = pos + proposal_len; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ppos + p->spi_size > pend) { 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Not enough room for SPI " 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "in proposal"); 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p->spi_size) { 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "IKEV2: SPI", 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ppos, p->spi_size); 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ppos += p->spi_size; 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * For initial IKE_SA negotiation, SPI Size MUST be zero; for 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * subsequent negotiations, it must be 8 for IKE. We only support 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * initial case for now. 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p->spi_size != 0) { 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected SPI Size"); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (p->num_transforms == 0) { 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: At least one transform required"); 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < (int) p->num_transforms; i++) { 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tlen = ikev2_parse_transform(prop, ppos, pend); 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlen < 0) 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ppos += tlen; 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ppos != pend) { 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected data after " 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "transforms"); 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return proposal_len; 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_process_sai1(struct ikev2_responder_data *data, 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *sai1, size_t sai1_len) 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_proposal_data prop; 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int found = 0; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Security Association Payloads: <Proposals> */ 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sai1 == NULL) { 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: SAi1 not received"); 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&prop, 0, sizeof(prop)); 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prop.proposal_num = 1; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = sai1; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = sai1 + sai1_len; 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos < end) { 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int plen; 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prop.integ = -1; 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prop.prf = -1; 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prop.encr = -1; 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prop.dh = -1; 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = ikev2_parse_proposal(&prop, pos, end); 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (plen < 0) 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!found && prop.integ != -1 && prop.prf != -1 && 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prop.encr != -1 && prop.dh != -1) { 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(&data->proposal, &prop, sizeof(prop)); 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->dh = dh_groups_get(prop.dh); 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt found = 1; 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += plen; 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos != end) { 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected data after proposals"); 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!found) { 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No acceptable proposal found"); 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Accepted proposal #%d: ENCR:%d PRF:%d " 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "INTEG:%d D-H:%d", data->proposal.proposal_num, 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->proposal.encr, data->proposal.prf, 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->proposal.integ, data->proposal.dh); 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_process_kei(struct ikev2_responder_data *data, 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *kei, size_t kei_len) 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 group; 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Key Exchange Payload: 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * DH Group # (16 bits) 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RESERVED (16 bits) 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Key Exchange Data (Diffie-Hellman public value) 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kei == NULL) { 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: KEi not received"); 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kei_len < 4 + 96) { 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Too show Key Exchange Payload"); 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group = WPA_GET_BE16(kei); 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: KEi DH Group #%u", group); 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (group != data->proposal.dh) { 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: KEi DH Group #%u does not match " 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with the selected proposal (%u)", 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt group, data->proposal.dh); 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Reject message with Notify payload of type 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * INVALID_KE_PAYLOAD (RFC 4306, Sect. 3.4) */ 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->error_type = INVALID_KE_PAYLOAD; 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = NOTIFY; 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->dh == NULL) { 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported DH group"); 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RFC 4306, Section 3.4: 4221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * The length of DH public value MUST be equal to the length of the 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * prime modulus. 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kei_len - 4 != data->dh->prime_len) { 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid DH public value length " 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%ld (expected %ld)", 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (long) (kei_len - 4), (long) data->dh->prime_len); 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->i_dh_public); 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->i_dh_public = wpabuf_alloc(kei_len - 4); 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->i_dh_public == NULL) 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(data->i_dh_public, kei + 4, kei_len - 4); 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "IKEV2: KEi Diffie-Hellman Public Value", 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->i_dh_public); 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_process_ni(struct ikev2_responder_data *data, 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ni, size_t ni_len) 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ni == NULL) { 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Ni not received"); 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ni_len < IKEV2_NONCE_MIN_LEN || ni_len > IKEV2_NONCE_MAX_LEN) { 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid Ni length %ld", 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (long) ni_len); 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CCNS_PL 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Zeros are removed incorrectly from the beginning of the nonces */ 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (ni_len > 1 && *ni == 0) { 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ni_len--; 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ni++; 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CCNS_PL */ 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->i_nonce_len = ni_len; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->i_nonce, ni, ni_len); 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "IKEV2: Ni", 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->i_nonce, data->i_nonce_len); 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_process_sa_init(struct ikev2_responder_data *data, 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_hdr *hdr, 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_payloads *pl) 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_process_sai1(data, pl->sa, pl->sa_len) < 0 || 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_process_kei(data, pl->ke, pl->ke_len) < 0 || 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_process_ni(data, pl->nonce, pl->nonce_len) < 0) 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->i_spi, hdr->i_spi, IKEV2_SPI_LEN); 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_process_idi(struct ikev2_responder_data *data, 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *idi, size_t idi_len) 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id_type; 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (idi == NULL) { 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No IDi received"); 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (idi_len < 4) { 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Too short IDi payload"); 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id_type = idi[0]; 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idi += 4; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idi_len -= 4; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: IDi ID Type %d", id_type); 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "IKEV2: IDi", idi, idi_len); 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->IDi); 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->IDi = os_malloc(idi_len); 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->IDi == NULL) 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->IDi, idi, idi_len); 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->IDi_len = idi_len; 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->IDi_type = id_type; 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_process_cert(struct ikev2_responder_data *data, 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *cert, size_t cert_len) 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 cert_encoding; 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert == NULL) { 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->peer_auth == PEER_AUTH_CERT) { 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No Certificate received"); 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert_len < 1) { 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No Cert Encoding field"); 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert_encoding = cert[0]; 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert++; 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert_len--; 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Cert Encoding %d", cert_encoding); 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "IKEV2: Certificate Data", cert, cert_len); 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: validate certificate */ 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_process_auth_cert(struct ikev2_responder_data *data, 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 method, const u8 *auth, size_t auth_len) 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (method != AUTH_RSA_SIGN) { 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication " 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "method %d", method); 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: validate AUTH */ 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_process_auth_secret(struct ikev2_responder_data *data, 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 method, const u8 *auth, 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t auth_len) 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 auth_data[IKEV2_MAX_HASH_LEN]; 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_prf_alg *prf; 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (method != AUTH_SHARED_KEY_MIC) { 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported authentication " 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "method %d", method); 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* msg | Nr | prf(SK_pi,IDi') */ 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_derive_auth_data(data->proposal.prf, data->i_sign_msg, 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->IDi, data->IDi_len, data->IDi_type, 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &data->keys, 1, data->shared_secret, 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->shared_secret_len, 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->r_nonce, data->r_nonce_len, 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_pad, data->key_pad_len, 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth_data) < 0) { 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data"); 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->i_sign_msg); 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->i_sign_msg = NULL; 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prf = ikev2_get_prf(data->proposal.prf); 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prf == NULL) 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (auth_len != prf->hash_len || 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(auth, auth_data, auth_len) != 0) { 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid Authentication Data"); 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "IKEV2: Received Authentication Data", 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth, auth_len); 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "IKEV2: Expected Authentication Data", 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth_data, prf->hash_len); 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->error_type = AUTHENTICATION_FAILED; 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = NOTIFY; 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Server authenticated successfully " 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "using shared keys"); 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_process_auth(struct ikev2_responder_data *data, 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *auth, size_t auth_len) 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 auth_method; 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (auth == NULL) { 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No Authentication Payload"); 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (auth_len < 4) { 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Too short Authentication " 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Payload"); 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth_method = auth[0]; 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth += 4; 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth_len -= 4; 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Auth Method %d", auth_method); 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "IKEV2: Authentication Data", auth, auth_len); 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->peer_auth) { 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PEER_AUTH_CERT: 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ikev2_process_auth_cert(data, auth_method, auth, 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth_len); 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PEER_AUTH_SECRET: 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ikev2_process_auth_secret(data, auth_method, auth, 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth_len); 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_process_sa_auth_decrypted(struct ikev2_responder_data *data, 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 next_payload, 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *payload, size_t payload_len) 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_payloads pl; 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Processing decrypted payloads"); 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_parse_payloads(&pl, next_payload, payload, payload + 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt payload_len) < 0) { 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Failed to parse decrypted " 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "payloads"); 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_process_idi(data, pl.idi, pl.idi_len) < 0 || 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_process_cert(data, pl.cert, pl.cert_len) < 0 || 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_process_auth(data, pl.auth, pl.auth_len) < 0) 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_process_sa_auth(struct ikev2_responder_data *data, 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_hdr *hdr, 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_payloads *pl) 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *decrypted; 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t decrypted_len; 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted = ikev2_decrypt_payload(data->proposal.encr, 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->proposal.integ, 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &data->keys, 1, hdr, pl->encrypted, 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pl->encrypted_len, &decrypted_len); 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (decrypted == NULL) 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = ikev2_process_sa_auth_decrypted(data, pl->encr_next_payload, 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt decrypted, decrypted_len); 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(decrypted); 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_validate_rx_state(struct ikev2_responder_data *data, 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 exchange_type, u32 message_id) 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SA_INIT: 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Expect to receive IKE_SA_INIT: HDR, SAi1, KEi, Ni */ 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (exchange_type != IKE_SA_INIT) { 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type " 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%u in SA_INIT state", exchange_type); 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (message_id != 0) { 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u " 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "in SA_INIT state", message_id); 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SA_AUTH: 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Expect to receive IKE_SA_AUTH: 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * HDR, SK {IDi, [CERT,] [CERTREQ,] [IDr,] 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AUTH, SAi2, TSi, TSr} 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (exchange_type != IKE_SA_AUTH) { 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type " 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%u in SA_AUTH state", exchange_type); 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (message_id != 1) { 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u " 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "in SA_AUTH state", message_id); 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHILD_SA: 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (exchange_type != CREATE_CHILD_SA) { 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Exchange Type " 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%u in CHILD_SA state", exchange_type); 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (message_id != 2) { 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Message ID %u " 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "in CHILD_SA state", message_id); 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFY: 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_DONE: 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_FAILED: 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint ikev2_responder_process(struct ikev2_responder_data *data, 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *buf) 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_hdr *hdr; 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 length, message_id; 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_payloads pl; 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_MSGDUMP, "IKEV2: Received message (len %lu)", 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(buf)); 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpabuf_len(buf) < sizeof(*hdr)) { 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Too short frame to include HDR"); 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->error_type = 0; 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (const struct ikev2_hdr *) wpabuf_head(buf); 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = wpabuf_head_u8(buf) + wpabuf_len(buf); 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt message_id = WPA_GET_BE32(hdr->message_id); 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt length = WPA_GET_BE32(hdr->length); 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Initiator's SPI", 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->i_spi, IKEV2_SPI_LEN); 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Responder's SPI", 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->r_spi, IKEV2_SPI_LEN); 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Next Payload: %u Version: 0x%x " 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Exchange Type: %u", 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->next_payload, hdr->version, hdr->exchange_type); 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Message ID: %u Length: %u", 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt message_id, length); 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr->version != IKEV2_VERSION) { 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported HDR version 0x%x " 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(expected 0x%x)", hdr->version, IKEV2_VERSION); 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (length != wpabuf_len(buf)) { 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Invalid length (HDR: %lu != " 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RX: %lu)", (unsigned long) length, 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(buf)); 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_validate_rx_state(data, hdr->exchange_type, message_id) < 0) 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((hdr->flags & (IKEV2_HDR_INITIATOR | IKEV2_HDR_RESPONSE)) != 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IKEV2_HDR_INITIATOR) { 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected Flags value 0x%x", 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->flags); 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SA_INIT) { 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(data->i_spi, hdr->i_spi, IKEV2_SPI_LEN) != 0) { 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA " 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Initiator's SPI"); 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(data->r_spi, hdr->r_spi, IKEV2_SPI_LEN) != 0) { 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unexpected IKE_SA " 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Responder's SPI"); 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (hdr + 1); 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_parse_payloads(&pl, hdr->next_payload, pos, end) < 0) 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == SA_INIT) { 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->last_msg = LAST_MSG_SA_INIT; 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_process_sa_init(data, hdr, &pl) < 0) { 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == NOTIFY) 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->i_sign_msg); 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->i_sign_msg = wpabuf_dup(buf); 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == SA_AUTH) { 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->last_msg = LAST_MSG_SA_AUTH; 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_process_sa_auth(data, hdr, &pl) < 0) { 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == NOTIFY) 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ikev2_build_hdr(struct ikev2_responder_data *data, 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg, u8 exchange_type, 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 next_payload, u32 message_id) 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_hdr *hdr; 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Adding HDR"); 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* HDR - RFC 4306, Sect. 3.1 */ 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = wpabuf_put(msg, sizeof(*hdr)); 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(hdr->i_spi, data->i_spi, IKEV2_SPI_LEN); 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(hdr->r_spi, data->r_spi, IKEV2_SPI_LEN); 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->next_payload = next_payload; 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->version = IKEV2_VERSION; 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->exchange_type = exchange_type; 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->flags = IKEV2_HDR_RESPONSE; 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE32(hdr->message_id, message_id); 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_build_sar1(struct ikev2_responder_data *data, 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg, u8 next_payload) 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_payload_hdr *phdr; 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t plen; 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_proposal *p; 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_transform *t; 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Adding SAr1 payload"); 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SAr1 - RFC 4306, Sect. 2.7 and 3.3 */ 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr = wpabuf_put(msg, sizeof(*phdr)); 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr->next_payload = next_payload; 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr->flags = 0; 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p = wpabuf_put(msg, sizeof(*p)); 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CCNS_PL 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Seems to require that the Proposal # is 1 even though RFC 4306 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Sect 3.3.1 has following requirement "When a proposal is accepted, 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * all of the proposal numbers in the SA payload MUST be the same and 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * MUST match the number on the proposal sent that was accepted.". 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p->proposal_num = 1; 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CCNS_PL */ 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p->proposal_num = data->proposal.proposal_num; 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CCNS_PL */ 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p->protocol_id = IKEV2_PROTOCOL_IKE; 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p->num_transforms = 4; 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt t = wpabuf_put(msg, sizeof(*t)); 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt t->type = 3; 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt t->transform_type = IKEV2_TRANSFORM_ENCR; 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(t->transform_id, data->proposal.encr); 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->proposal.encr == ENCR_AES_CBC) { 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Transform Attribute: Key Len = 128 bits */ 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CCNS_PL 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 0x001d); /* ?? */ 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CCNS_PL */ 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 0x800e); /* AF=1, AttrType=14 */ 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CCNS_PL */ 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, 128); /* 128-bit key */ 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) t; 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(t->transform_length, plen); 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt t = wpabuf_put(msg, sizeof(*t)); 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt t->type = 3; 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(t->transform_length, sizeof(*t)); 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt t->transform_type = IKEV2_TRANSFORM_PRF; 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(t->transform_id, data->proposal.prf); 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt t = wpabuf_put(msg, sizeof(*t)); 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt t->type = 3; 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(t->transform_length, sizeof(*t)); 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt t->transform_type = IKEV2_TRANSFORM_INTEG; 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(t->transform_id, data->proposal.integ); 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt t = wpabuf_put(msg, sizeof(*t)); 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(t->transform_length, sizeof(*t)); 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt t->transform_type = IKEV2_TRANSFORM_DH; 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(t->transform_id, data->proposal.dh); 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) p; 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(p->proposal_length, plen); 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(phdr->payload_length, plen); 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_build_ker(struct ikev2_responder_data *data, 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg, u8 next_payload) 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_payload_hdr *phdr; 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t plen; 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *pv; 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Adding KEr payload"); 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pv = dh_init(data->dh, &data->r_dh_private); 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pv == NULL) { 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Failed to initialize DH"); 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* KEr - RFC 4306, Sect. 3.4 */ 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr = wpabuf_put(msg, sizeof(*phdr)); 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr->next_payload = next_payload; 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr->flags = 0; 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, data->proposal.dh); /* DH Group # */ 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(msg, 2); /* RESERVED */ 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RFC 4306, Sect. 3.4: possible zero padding for public value to 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * match the length of the prime. 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(msg, data->dh->prime_len - wpabuf_len(pv)); 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_buf(msg, pv); 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(pv); 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(phdr->payload_length, plen); 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_build_nr(struct ikev2_responder_data *data, 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg, u8 next_payload) 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_payload_hdr *phdr; 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t plen; 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Adding Nr payload"); 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Nr - RFC 4306, Sect. 3.9 */ 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr = wpabuf_put(msg, sizeof(*phdr)); 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr->next_payload = next_payload; 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr->flags = 0; 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(msg, data->r_nonce, data->r_nonce_len); 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(phdr->payload_length, plen); 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_build_idr(struct ikev2_responder_data *data, 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg, u8 next_payload) 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_payload_hdr *phdr; 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t plen; 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Adding IDr payload"); 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->IDr == NULL) { 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No IDr available"); 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* IDr - RFC 4306, Sect. 3.5 */ 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr = wpabuf_put(msg, sizeof(*phdr)); 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr->next_payload = next_payload; 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr->flags = 0; 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, ID_KEY_ID); 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(msg, 3); /* RESERVED */ 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(msg, data->IDr, data->IDr_len); 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(phdr->payload_length, plen); 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_build_auth(struct ikev2_responder_data *data, 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg, u8 next_payload) 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_payload_hdr *phdr; 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t plen; 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ikev2_prf_alg *prf; 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Adding AUTH payload"); 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prf = ikev2_get_prf(data->proposal.prf); 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prf == NULL) 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Authentication - RFC 4306, Sect. 3.8 */ 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr = wpabuf_put(msg, sizeof(*phdr)); 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr->next_payload = next_payload; 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr->flags = 0; 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, AUTH_SHARED_KEY_MIC); 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(msg, 3); /* RESERVED */ 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* msg | Ni | prf(SK_pr,IDr') */ 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_derive_auth_data(data->proposal.prf, data->r_sign_msg, 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->IDr, data->IDr_len, ID_KEY_ID, 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &data->keys, 0, data->shared_secret, 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->shared_secret_len, 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->i_nonce, data->i_nonce_len, 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->key_pad, data->key_pad_len, 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(msg, prf->hash_len)) < 0) { 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Could not derive AUTH data"); 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->r_sign_msg); 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->r_sign_msg = NULL; 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(phdr->payload_length, plen); 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ikev2_build_notification(struct ikev2_responder_data *data, 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg, u8 next_payload) 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ikev2_payload_hdr *phdr; 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t plen; 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: Adding Notification payload"); 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->error_type == 0) { 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No Notify Message Type " 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "available"); 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Notify - RFC 4306, Sect. 3.10 */ 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr = wpabuf_put(msg, sizeof(*phdr)); 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr->next_payload = next_payload; 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phdr->flags = 0; 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CCNS_PL 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, 1); /* Protocol ID: IKE_SA notification */ 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CCNS_PL */ 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, 0); /* Protocol ID: no existing SA */ 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CCNS_PL */ 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, 0); /* SPI Size */ 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, data->error_type); 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->error_type) { 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case INVALID_KE_PAYLOAD: 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->proposal.dh == -1) { 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: No DH Group selected for " 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "INVALID_KE_PAYLOAD notifications"); 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(msg, data->proposal.dh); 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "IKEV2: INVALID_KE_PAYLOAD - request " 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "DH Group #%d", data->proposal.dh); 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case AUTHENTICATION_FAILED: 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* no associated data */ 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "IKEV2: Unsupported Notify Message Type " 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d", data->error_type); 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(phdr->payload_length, plen); 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * ikev2_build_sa_init(struct ikev2_responder_data *data) 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* build IKE_SA_INIT: HDR, SAr1, KEr, Nr, [CERTREQ], [SK{IDr}] */ 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_get_random(data->r_spi, IKEV2_SPI_LEN)) 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "IKEV2: IKE_SA Responder's SPI", 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->r_spi, IKEV2_SPI_LEN); 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->r_nonce_len = IKEV2_NONCE_MIN_LEN; 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(data->r_nonce, data->r_nonce_len)) 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CCNS_PL 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Zeros are removed incorrectly from the beginning of the nonces in 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * key derivation; as a workaround, make sure Nr does not start with 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * zero.. */ 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->r_nonce[0] == 0) 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->r_nonce[0] = 1; 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CCNS_PL */ 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "IKEV2: Nr", data->r_nonce, data->r_nonce_len); 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1500); 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_build_hdr(data, msg, IKE_SA_INIT, IKEV2_PAYLOAD_SA, 0); 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_build_sar1(data, msg, IKEV2_PAYLOAD_KEY_EXCHANGE) || 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_build_ker(data, msg, IKEV2_PAYLOAD_NONCE) || 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_build_nr(data, msg, data->peer_auth == PEER_AUTH_SECRET ? 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IKEV2_PAYLOAD_ENCRYPTED : 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) { 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_derive_keys(data)) { 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->peer_auth == PEER_AUTH_CERT) { 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: CERTREQ with SHA-1 hashes of Subject Public Key Info 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for trust agents */ 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->peer_auth == PEER_AUTH_SECRET) { 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *plain = wpabuf_alloc(data->IDr_len + 1000); 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (plain == NULL) { 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_build_idr(data, plain, 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) || 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_build_encrypted(data->proposal.encr, 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->proposal.integ, 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &data->keys, 0, msg, plain, 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IKEV2_PAYLOAD_IDr)) { 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(plain); 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(plain); 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_update_hdr(msg); 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_INIT)", msg); 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = SA_AUTH; 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->r_sign_msg); 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->r_sign_msg = wpabuf_dup(msg); 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * ikev2_build_sa_auth(struct ikev2_responder_data *data) 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg, *plain; 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* build IKE_SA_AUTH: HDR, SK {IDr, [CERT,] AUTH} */ 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + data->IDr_len + 1000); 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_build_hdr(data, msg, IKE_SA_AUTH, IKEV2_PAYLOAD_ENCRYPTED, 1); 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plain = wpabuf_alloc(data->IDr_len + 1000); 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (plain == NULL) { 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_build_idr(data, plain, IKEV2_PAYLOAD_AUTHENTICATION) || 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_build_auth(data, plain, IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) || 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_build_encrypted(data->proposal.encr, data->proposal.integ, 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &data->keys, 0, msg, plain, 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IKEV2_PAYLOAD_IDr)) { 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(plain); 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(plain); 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (SA_AUTH)", msg); 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = IKEV2_DONE; 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * ikev2_build_notify(struct ikev2_responder_data *data) 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = wpabuf_alloc(sizeof(struct ikev2_hdr) + 1000); 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->last_msg == LAST_MSG_SA_AUTH) { 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* HDR, SK{N} */ 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *plain = wpabuf_alloc(100); 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (plain == NULL) { 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_build_hdr(data, msg, IKE_SA_AUTH, 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IKEV2_PAYLOAD_ENCRYPTED, 1); 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_build_notification(data, plain, 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IKEV2_PAYLOAD_NO_NEXT_PAYLOAD) || 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_build_encrypted(data->proposal.encr, 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->proposal.integ, 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &data->keys, 0, msg, plain, 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IKEV2_PAYLOAD_NOTIFICATION)) { 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(plain); 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = IKEV2_FAILED; 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* HDR, N */ 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_build_hdr(data, msg, IKE_SA_INIT, 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IKEV2_PAYLOAD_NOTIFICATION, 0); 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ikev2_build_notification(data, msg, 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IKEV2_PAYLOAD_NO_NEXT_PAYLOAD)) { 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(msg); 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = SA_INIT; 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ikev2_update_hdr(msg); 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_buf(MSG_MSGDUMP, "IKEV2: Sending message (Notification)", 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg); 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpabuf * ikev2_responder_build(struct ikev2_responder_data *data) 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SA_INIT: 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ikev2_build_sa_init(data); 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SA_AUTH: 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ikev2_build_sa_auth(data); 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CHILD_SA: 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NOTIFY: 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ikev2_build_notify(data); 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_DONE: 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IKEV2_FAILED: 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1299